public function deploy(DNEnvironment $environment, $sha, DeploynautLogFile $log, DNProject $project, $leaveMaintenancePage = false) {
		$name = $environment->getFullName();
		$repository = $project->LocalCVSPath;

		$args = array(
			'branch' => $sha,
			'repository' => $repository,
		);

		$this->extend('deployStart', $environment, $sha, $log, $project);

		$log->write(sprintf('Deploying "%s" to "%s"', $sha, $name));

		$this->enableMaintenance($environment, $log, $project);

		// Use a package generator if specified, otherwise run a direct deploy, which is the default behaviour
		// if build_filename isn't specified
		if($this->packageGenerator) {
			$args['build_filename'] = $this->packageGenerator->getPackageFilename($project->Name, $sha, $repository, $log);
			if(empty($args['build_filename'])) {
				throw new RuntimeException('Failed to generate package.');
			}
		}

		$command = $this->getCommand('deploy', 'web', $environment, $args, $log);
		$command->run(function($type, $buffer) use($log) {
			$log->write($buffer);
		});

		// Deployment cleanup. We assume it is always safe to run this at the end, regardless of the outcome.
		$self = $this;
		$cleanupFn = function() use($self, $environment, $args, $log, $sha, $project) {
			$command = $self->getCommand('deploy:cleanup', 'web', $environment, $args, $log);
			$command->run(function($type, $buffer) use($log) {
				$log->write($buffer);
			});

			if(!$command->isSuccessful()) {
				$self->extend('cleanupFailure', $environment, $sha, $log, $project);
				$log->write('Warning: Cleanup failed, but fine to continue. Needs manual cleanup sometime.');
			}
		};

		// Once the deployment has run it's necessary to update the maintenance page status
		if($leaveMaintenancePage) {
			$this->enableMaintenance($environment, $log, $project);
		}

		if(!$command->isSuccessful()) {
			$cleanupFn();
			$this->extend('deployFailure', $environment, $sha, $log, $project);
			throw new RuntimeException($command->getErrorOutput());
		}

		// Check if maintenance page should be removed
		if(!$leaveMaintenancePage) {
			$this->disableMaintenance($environment, $log, $project);
		}

		$cleanupFn();

		$log->write(sprintf('Deploy of "%s" to "%s" finished', $sha, $name));

		$this->extend('deployEnd', $environment, $sha, $log, $project);
	}