Get a list of applications in a directory.
public static getApplications ( string $directory, |
||
$directory | string | The absolute path to a directory. |
$config | CLI configuration. | |
return |
/** * Build a project from any source directory, targeting any destination. * * @param string $sourceDir The absolute path to the source directory. * @param string $destination Where the web root(s) will be linked (absolute * path). * @param array $apps An array of application names to build. * * @throws \Exception on failure * * @return bool */ public function build($sourceDir, $destination, array $apps = []) { $success = true; $ids = []; foreach (LocalApplication::getApplications($sourceDir) as $app) { $id = $app->getId(); $ids[] = $id; if ($apps && !in_array($id, $apps)) { continue; } $success = $this->buildApp($app, $sourceDir, $destination) && $success; } $notFounds = array_diff($apps, $ids); if ($notFounds) { foreach ($notFounds as $notFound) { $this->output->writeln("Application not found: <comment>{$notFound}</comment>"); } } if (empty($this->settings['noClean'])) { if (!empty($this->settings['projectRoot'])) { $this->output->writeln("Cleaning up..."); $this->cleanBuilds($this->settings['projectRoot']); $this->cleanArchives($this->settings['projectRoot']); } else { $buildsDir = $sourceDir . '/' . LocalProject::BUILD_DIR; if (is_dir($buildsDir)) { $this->output->writeln("Cleaning up..."); $this->cleanDirectory($buildsDir); } } } return $success; }
/** * Build a project from any source directory, targeting any destination. * * @param string $sourceDir The absolute path to the source directory. * @param string $destination Where the web root(s) will be linked (absolute * path). * @param array $apps An array of application names to build. * * @throws \Exception on failure * * @return bool */ public function build($sourceDir, $destination = null, array $apps = []) { $success = true; if (file_exists($sourceDir . '/.git')) { (new LocalProject())->writeGitExclude($sourceDir); } $ids = []; foreach (LocalApplication::getApplications($sourceDir, $this->config) as $app) { $id = $app->getId(); $ids[] = $id; if ($apps && !in_array($id, $apps)) { continue; } $success = $this->buildApp($app, $sourceDir, $destination) && $success; } $notFounds = array_diff($apps, $ids); if ($notFounds) { foreach ($notFounds as $notFound) { $this->output->writeln("Application not found: <comment>{$notFound}</comment>"); } } if (empty($this->settings['no-clean'])) { $this->output->writeln("Cleaning up..."); $this->cleanBuilds($sourceDir); $this->cleanArchives($sourceDir); } return $success; }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { if (!($projectRoot = $this->getProjectRoot())) { throw new RootNotFoundException(); } $repository = $projectRoot . '/' . LocalProject::REPOSITORY_DIR; $apps = LocalApplication::getApplications($repository); $rows = []; foreach ($apps as $app) { $rows[] = [$app->getName(), $app->getRoot()]; } $table = new Table($input, $output); $table->render($rows, ['Name', 'Path']); }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { if (!($projectRoot = $this->getProjectRoot())) { throw new RootNotFoundException(); } $apps = LocalApplication::getApplications($projectRoot, self::$config); $rows = []; foreach ($apps as $app) { $config = $app->getConfig(); $type = isset($config['type']) ? $config['type'] : null; $rows[] = [$app->getName(), $type, $app->getRoot()]; } $table = new Table($input, $output); $table->render($rows, ['Name', 'Type', 'Path']); }
public function testToolstackDetectionMultiple() { $fakeRepositoryRoot = 'tests/data/repositories/multiple'; $applications = LocalApplication::getApplications($fakeRepositoryRoot); $this->assertCount(6, $applications, 'Detect multiple apps'); }
/** * Find the name of the app the user wants to use for an SSH command. * * @param InputInterface $input * The user input object. * @param callable|null $filter * A filter callback that takes one argument: a LocalApplication object. * * @return string|null * The application name, or null if it could not be found. */ protected function selectApp(InputInterface $input, callable $filter = null) { $appName = $input->getOption('app'); if ($appName) { return $appName; } $projectRoot = $this->getProjectRoot(); if (!$projectRoot || !$this->selectedProjectIsCurrent() || !is_dir($projectRoot . '/' . LocalProject::REPOSITORY_DIR)) { return null; } $this->debug('Searching for applications in local repository'); /** @var LocalApplication[] $apps */ $apps = LocalApplication::getApplications($projectRoot . '/' . LocalProject::REPOSITORY_DIR); if ($filter) { $apps = array_filter($apps, $filter); } if (count($apps) > 1 && $input->isInteractive()) { /** @var \Platformsh\Cli\Helper\PlatformQuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); $choices = []; foreach ($apps as $app) { $choices[$app->getName()] = $app->getName(); } $appName = $questionHelper->choose($choices, 'Enter a number to choose an app:', $input, $this->stdErr); } $input->setOption('app', $appName); return $appName; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); if ($input instanceof ArgvInput) { $helper = new ArgvHelper(); $drushCommand = $helper->getPassedCommand($this, $input); } if (empty($drushCommand)) { $drushCommand = $input->getArgument('cmd'); } $sshOptions = ''; // Pass through options that the CLI shares with Drush and SSH. foreach (['yes', 'no', 'quiet'] as $option) { if ($input->getOption($option)) { $drushCommand .= " --{$option}"; } } if ($output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) { $drushCommand .= " --debug"; $sshOptions .= ' -vv'; } elseif ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) { $drushCommand .= " --verbose"; $sshOptions .= ' -v'; } elseif ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { $drushCommand .= " --verbose"; } elseif ($output->getVerbosity() == OutputInterface::VERBOSITY_QUIET) { $drushCommand .= " --quiet"; $sshOptions .= ' -q'; } $appName = $this->selectApp($input, function (LocalApplication $app) { return Drupal::isDrupal($app->getRoot()); }); $selectedEnvironment = $this->getSelectedEnvironment(); $sshUrl = $selectedEnvironment->getSshUrl($appName); // Get the LocalApplication object for the specified application, if // available. $projectRoot = $this->getProjectRoot(); if ($projectRoot && $this->selectedProjectIsCurrent() && is_dir($projectRoot . '/' . LocalProject::REPOSITORY_DIR)) { $apps = LocalApplication::getApplications($projectRoot . '/' . LocalProject::REPOSITORY_DIR); if (count($apps) === 1 && $appName === null) { $app = reset($apps); } else { foreach ($apps as $possibleApp) { if ($possibleApp->getName() === $appName) { $app = $possibleApp; break; } } } } // Use the local application configuration (if available) to determine // the correct Drupal root. if (isset($app) && isset($app->getConfig()['web']['document_root'])) { $documentRoot = trim($app->getConfig()['web']['document_root'], '/') ?: 'public'; $drupalRoot = '/app/' . $documentRoot; } else { // Fall back to the PLATFORM_DOCUMENT_ROOT environment variable, // which is usually correct, except where the document_root was // specified as '/'. $drupalRoot = '${PLATFORM_DOCUMENT_ROOT:-/app/public}'; $this->debug('<comment>Warning:</comment> using $PLATFORM_DOCUMENT_ROOT for the Drupal root. This fails in cases where the document_root is /.'); } $dimensions = $this->getApplication()->getTerminalDimensions(); $columns = $dimensions[0] ?: 80; $sshDrushCommand = "COLUMNS={$columns} drush --root=\"{$drupalRoot}\""; if ($environmentUrl = $selectedEnvironment->getLink('public-url')) { $sshDrushCommand .= " --uri=" . escapeshellarg($environmentUrl); } $sshDrushCommand .= ' ' . $drushCommand . ' 2>&1'; $command = 'ssh' . $sshOptions . ' ' . escapeshellarg($sshUrl) . ' ' . escapeshellarg($sshDrushCommand); if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) { $this->stdErr->writeln("Running command: <info>{$command}</info>"); } passthru($command, $return_var); return $return_var; }
/** * Create Drush aliases for the provided project and environments. * * @param Project $project The project * @param string $projectRoot The project root * @param Environment[] $environments The environments * @param string $original The original group name * @param bool $merge Whether to merge existing alias settings * * @throws \Exception * * @return bool Whether any aliases have been created. */ public function createAliases(Project $project, $projectRoot, $environments, $original = null, $merge = true) { $config = LocalProject::getProjectConfig($projectRoot); $group = !empty($config['alias-group']) ? $config['alias-group'] : $project['id']; // Ensure the existence of the .drush directory. $drushDir = $this->homeDir . '/.drush'; if (!is_dir($drushDir)) { mkdir($drushDir); } $filename = $drushDir . '/' . $group . '.aliases.drushrc.php'; if (!is_writable($drushDir) || file_exists($filename) && !is_writable($filename)) { throw new \Exception("Drush alias file not writable: {$filename}"); } // Include the previous alias file(s) so that the user's own // modifications can be merged. This may create a PHP parse error for // invalid syntax, but in that case the user could not run Drush anyway. $aliases = []; $originalFiles = [$filename]; if ($original) { array_unshift($originalFiles, $drushDir . '/' . $original . '.aliases.drushrc.php'); } if ($merge) { foreach ($originalFiles as $originalFile) { if (file_exists($originalFile)) { include $originalFile; } } } // Gather applications. $apps = LocalApplication::getApplications($projectRoot . '/' . LocalProject::REPOSITORY_DIR); $drupalApps = $apps; $multiApp = false; if (count($apps) > 1) { $multiApp = true; // Remove non-Drupal applications. foreach ($drupalApps as $key => $app) { if (!Drupal::isDrupal($app->getRoot())) { unset($drupalApps[$key]); } } } // Generate aliases for the remote environments and applications. $autoGenerated = ''; foreach ($environments as $environment) { foreach ($drupalApps as $app) { $newAlias = $this->generateRemoteAlias($environment, $app, $multiApp); if (!$newAlias) { continue; } $aliasName = $environment->id; if (count($drupalApps) > 1) { $aliasName .= '--' . $app->getId(); } // If the alias already exists, recursively replace existing // settings with new ones. if (isset($aliases[$aliasName])) { $newAlias = array_replace_recursive($aliases[$aliasName], $newAlias); unset($aliases[$aliasName]); } $autoGenerated .= sprintf("\n// Automatically generated alias for the environment \"%s\", application \"%s\".\n", $environment->title, $app->getId()); $autoGenerated .= $this->exportAlias($aliasName, $newAlias); } } // Generate an alias for the local environment, for each app. $localAlias = ''; foreach ($drupalApps as $app) { $appId = $app->getId(); $localAliasName = '_local'; $webRoot = $projectRoot . '/' . LocalProject::WEB_ROOT; if (count($drupalApps) > 1) { $localAliasName .= '--' . $appId; } if ($multiApp) { $webRoot .= '/' . $appId; } $local = ['root' => $webRoot, self::AUTO_REMOVE_KEY => true]; if (isset($aliases[$localAliasName])) { $local = array_replace_recursive($aliases[$localAliasName], $local); unset($aliases[$localAliasName]); } $localAlias .= sprintf("\n// Automatically generated alias for the local environment, application \"%s\".\n", $appId) . $this->exportAlias($localAliasName, $local); } // Add any user-defined (pre-existing) aliases. $userDefined = ''; foreach ($aliases as $name => $alias) { if (!empty($alias[self::AUTO_REMOVE_KEY])) { // This is probably for a deleted Platform.sh environment. continue; } $userDefined .= $this->exportAlias($name, $alias) . "\n"; } if ($userDefined) { $userDefined = "\n// User-defined aliases.\n" . $userDefined; } $header = "<?php\n" . "/**\n * @file" . "\n * Drush aliases for the Platform.sh project \"{$project->title}\"." . "\n *" . "\n * This file is auto-generated by the Platform.sh CLI." . "\n *" . "\n * WARNING" . "\n * This file may be regenerated at any time." . "\n * - User-defined aliases will be preserved." . "\n * - Aliases for active environments (including any custom additions) will be preserved." . "\n * - Aliases for deleted or inactive environments will be deleted." . "\n * - All other information will be deleted." . "\n */\n\n"; $export = $header . $userDefined . $localAlias . $autoGenerated; $this->writeAliasFile($filename, $export); return true; }
/** * Get a list of application names in the local project. * * @return string[] */ public function getAppNames() { $apps = []; if ($projectRoot = $this->welcomeCommand->getProjectRoot()) { foreach (LocalApplication::getApplications($projectRoot) as $app) { $name = $app->getName(); if ($name !== null) { $apps[] = $name; } } } return $apps; }