protected function buildApp($app, $sourceDir, $destination = null)
{
$verbose = $this->output->isVerbose();
$destination = $destination ?: $sourceDir . '/' . $this->config->get('local.web_root');
$appRoot = $app->getRoot();
$appConfig = $app->getConfig();
$multiApp = $appRoot != $sourceDir;
$appId = $app->getId();
$toolstack = $app->getToolstack();
if (!$toolstack) {
$this->output->writeln("Toolstack not found for application <error>{$appId}</error>");
return false;
}
// Find the right build directory.
$buildName = $multiApp ? str_replace('/', '-', $appId) : 'default';
$tmpBuildDir = $sourceDir . '/' . $this->config->get('local.build_dir') . '/' . $buildName . '-tmp';
if (file_exists($tmpBuildDir)) {
if (!$this->fsHelper->remove($tmpBuildDir)) {
$this->output->writeln(sprintf('Failed to remove directory <error>%s</error>', $tmpBuildDir));
return false;
}
}
// If the destination is inside the source directory, ensure it isn't
// copied or symlinked into the build.
if (strpos($destination, $sourceDir) === 0) {
$toolstack->addIgnoredFiles([ltrim(substr($destination, strlen($sourceDir)), '/')]);
}
// Warn about a mismatched PHP version.
if (isset($appConfig['type']) && strpos($appConfig['type'], ':')) {
list($stack, $version) = explode(':', $appConfig['type'], 2);
if ($stack === 'php' && version_compare($version, PHP_VERSION, '>')) {
$this->output->writeln(sprintf('<comment>Warning:</comment> the application <comment>%s</comment> expects PHP %s, but the system version is %s.', $appId, $version, PHP_VERSION));
}
}
$toolstack->setOutput($this->output);
$buildSettings = $this->settings + ['multiApp' => $multiApp, 'sourceDir' => $sourceDir];
$toolstack->prepare($tmpBuildDir, $app, $this->config, $buildSettings);
$archive = false;
if (empty($this->settings['no-archive']) && empty($this->settings['no-cache'])) {
$treeId = $this->getTreeId($appRoot);
if ($treeId) {
if ($verbose) {
$this->output->writeln("Tree ID: {$treeId}");
}
$archive = $sourceDir . '/' . $this->config->get('local.archive_dir') . '/' . $treeId . '.tar.gz';
}
}
if ($archive && file_exists($archive)) {
$message = "Extracting archive for application <info>{$appId}</info>";
$this->output->writeln($message);
$this->fsHelper->extractArchive($archive, $tmpBuildDir);
} else {
$message = "Building application <info>{$appId}</info>";
if (isset($appConfig['type'])) {
$message .= ' (runtime type: ' . $appConfig['type'] . ')';
}
$this->output->writeln($message);
$toolstack->build();
if ($this->runPostBuildHooks($appConfig, $toolstack->getAppDir()) === false) {
// The user may not care if build hooks fail, but we should
// not archive the result.
$archive = false;
}
if ($archive && $toolstack->canArchive()) {
$this->output->writeln("Saving build archive");
if (!is_dir(dirname($archive))) {
mkdir(dirname($archive));
}
$this->fsHelper->archiveDir($tmpBuildDir, $archive);
}
}
// The build is complete. Move the directory.
$buildDir = substr($tmpBuildDir, 0, strlen($tmpBuildDir) - 4);
if (file_exists($buildDir)) {
if (empty($this->settings['no-backup']) && is_dir($buildDir) && !is_link($buildDir)) {
$previousBuildArchive = dirname($buildDir) . '/' . basename($buildDir) . '-old.tar.gz';
$this->output->writeln("Backing up previous build to: " . $previousBuildArchive);
$this->fsHelper->archiveDir($buildDir, $previousBuildArchive);
}
if (!$this->fsHelper->remove($buildDir, true)) {
$this->output->writeln(sprintf('Failed to remove directory <error>%s</error>', $buildDir));
return false;
}
}
if (!rename($tmpBuildDir, $buildDir)) {
$this->output->writeln(sprintf('Failed to move temporary build directory into <error>%s</error>', $buildDir));
return false;
}
$toolstack->setBuildDir($buildDir);
$toolstack->install();
$this->runPostDeployHooks($appConfig, $buildDir);
$webRoot = $toolstack->getWebRoot();
// Symlink the built web root ($webRoot) into www or www/appId.
if (!is_dir($webRoot)) {
$this->output->writeln("\nWeb root not found: <error>{$webRoot}</error>\n");
return false;
}
if ($multiApp) {
$appDir = str_replace('/', '-', $appId);
if (is_link($destination)) {
$this->fsHelper->remove($destination);
}
$destination .= "/{$appDir}";
}
$this->fsHelper->symlink($webRoot, $destination);
$message = "\nBuild complete for application <info>{$appId}</info>";
$this->output->writeln($message);
$this->output->writeln("Web root: <info>{$destination}</info>\n");
return true;
}