/** * Test FilesystemHelper::symlinkDir(). */ public function testSymlinkDir() { $testTarget = $this->tempDir(); $testLink = $this->tempDir() . '/link'; $this->filesystemHelper->symlink($testTarget, $testLink); $this->assertTrue(is_link($testLink)); touch($testTarget . '/test-file'); $this->assertFileExists($testLink . '/test-file'); }
/** * Process the defined special destinations. */ protected function symLinkSpecialDestinations() { foreach ($this->specialDestinations as $sourcePattern => $relDestination) { $matched = glob($this->appRoot . '/' . $sourcePattern, GLOB_NOSORT); if (!$matched) { continue; } // On Platform these replacements would be a bit different. $absDestination = str_replace(array('{webroot}', '{approot}'), $this->buildDir, $relDestination); foreach ($matched as $source) { // Ignore the source if it's in ignoredFiles. $relSource = str_replace($this->appRoot . '/', '', $source); if (in_array($relSource, $this->ignoredFiles)) { continue; } $this->output->writeln("Symlinking {$relSource} to {$relDestination}"); $destination = $absDestination; // Do not overwrite directories with files. if (!is_dir($source) && is_dir($destination)) { $destination = $destination . '/' . basename($source); } // Delete existing files, emitting a warning. if (file_exists($destination)) { $this->output->writeln(sprintf("Overriding existing path '%s' in destination", str_replace($this->buildDir . '/', '', $destination))); $this->fsHelper->remove($destination); } $this->fsHelper->symlink($source, $destination); } } }
/** * Create a settings.local.php for a Drupal site. * * This helps with database setup, etc. */ protected function installDrupalSettingsLocal() { $sitesDefault = $this->getWebRoot() . '/sites/default'; $shared = $this->getSharedDir(); $settingsLocal = $sitesDefault . '/settings.local.php'; if ($shared !== false && is_dir($sitesDefault) && !file_exists($settingsLocal)) { $sharedSettingsLocal = $shared . '/settings.local.php'; $relative = $this->config->get('local.shared_dir') . '/settings.local.php'; if (!file_exists($sharedSettingsLocal)) { $this->output->writeln("Creating file: <info>{$relative}</info>"); $this->fsHelper->copy(CLI_ROOT . '/resources/drupal/settings.local.php.dist', $sharedSettingsLocal); $this->output->writeln('Edit this file to add your database credentials and other Drupal configuration.'); } else { $this->output->writeln("Symlinking <info>{$relative}</info> into sites/default"); } $this->fsHelper->symlink($sharedSettingsLocal, $settingsLocal); } }
/** * @param LocalApplication $app * @param string $sourceDir * @param string $destination * * @return bool */ 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; }