protected function execute(InputInterface $input, OutputInterface $output) { $projectRoot = $this->getProjectRoot(); if (!$projectRoot) { throw new RootNotFoundException(); } $projectConfig = LocalProject::getProjectConfig($projectRoot); $current_group = isset($projectConfig['alias-group']) ? $projectConfig['alias-group'] : $projectConfig['id']; if ($input->getOption('pipe')) { $output->writeln($current_group); return 0; } $project = $this->getCurrentProject(); $new_group = ltrim($input->getOption('group'), '@'); $homeDir = $this->getHomeDir(); $drushHelper = new DrushHelper($output); $drushHelper->ensureInstalled(); $drushHelper->setHomeDir($homeDir); $aliases = $drushHelper->getAliases($current_group); if ($new_group && $new_group != $current_group || !$aliases || $input->getOption('recreate')) { $new_group = $new_group ?: $current_group; $this->stdErr->writeln("Creating Drush aliases in the group <info>@{$new_group}</info>"); $questionHelper = $this->getHelper('question'); if ($new_group != $current_group) { $existing = $drushHelper->getAliases($new_group); if ($existing && $new_group != $current_group) { $question = "The Drush alias group <info>@{$new_group}</info> already exists. Overwrite?"; if (!$questionHelper->confirm($question, $input, $output, false)) { return 1; } } LocalProject::writeCurrentProjectConfig('alias-group', $new_group, $projectRoot); } $environments = $this->getEnvironments($project, true, false); $drushHelper->createAliases($project, $projectRoot, $environments, $current_group); if ($new_group != $current_group) { $drushDir = $homeDir . '/.drush'; $oldFile = $drushDir . '/' . $current_group . '.aliases.drushrc.php'; if (file_exists($oldFile)) { if ($questionHelper->confirm("Delete old Drush alias group <info>@{$current_group}</info>?", $input, $this->stdErr)) { unlink($oldFile); } } } // Clear the Drush cache now that the aliases have been updated. $drushHelper->clearCache(); // Read the new aliases. $aliases = $drushHelper->getAliases($new_group); } if ($aliases) { $this->stdErr->writeln("Drush aliases for <info>{$project->title}</info> ({$project->id}):"); foreach (explode("\n", $aliases) as $alias) { $output->writeln(' @' . $alias); } } return 0; }
/** * @return mixed */ public static function projectName() { $platformConfig = LocalProject::getProjectConfig(); if (isset($platformConfig['alias-group'])) { return $platformConfig['alias-group']; } else { return $platformConfig['id']; } }
/** * Get the current environment if the user is in a project directory. * * @param Project $expectedProject The expected project. * @param bool|null $refresh Whether to refresh the environments or projects * cache. * * @return Environment|false The current environment. */ public function getCurrentEnvironment(Project $expectedProject = null, $refresh = null) { if (!($projectRoot = $this->getProjectRoot()) || !($project = $this->getCurrentProject()) || $expectedProject !== null && $expectedProject->id !== $project->id) { return false; } $gitHelper = $this->getHelper('git'); $gitHelper->setDefaultRepositoryDir($this->getProjectRoot()); $config = $this->localProject->getProjectConfig($projectRoot); // Check if there is a manual mapping set for the current branch. if (!empty($config['mapping']) && ($currentBranch = $gitHelper->getCurrentBranch()) && !empty($config['mapping'][$currentBranch])) { $environment = $this->api()->getEnvironment($config['mapping'][$currentBranch], $project, $refresh); if ($environment) { $this->debug('Found mapped environment for branch ' . $currentBranch . ': ' . $environment->id); return $environment; } else { unset($config['mapping'][$currentBranch]); $this->localProject->writeCurrentProjectConfig($config, $projectRoot); } } // Check whether the user has a Git upstream set to a remote environment // ID. $upstream = $gitHelper->getUpstream(); if ($upstream && strpos($upstream, '/') !== false) { list(, $potentialEnvironment) = explode('/', $upstream, 2); $environment = $this->api()->getEnvironment($potentialEnvironment, $project, $refresh); if ($environment) { $this->debug('Selected environment ' . $potentialEnvironment . ', based on Git upstream: ' . $upstream); return $environment; } } // There is no Git remote set. Fall back to trying the current branch // name. if (!empty($currentBranch) || ($currentBranch = $gitHelper->getCurrentBranch())) { $environment = $this->api()->getEnvironment($currentBranch, $project, $refresh); if (!$environment) { // Try a sanitized version of the branch name too. $currentBranchSanitized = Environment::sanitizeId($currentBranch); $environment = $this->api()->getEnvironment($currentBranchSanitized, $project, $refresh); } if ($environment) { $this->debug('Selected environment ' . $environment->id . ' based on branch name: ' . $currentBranch); return $environment; } } return false; }
/** * Get the project configuration. * * @param string $projectRoot * * @return array */ protected function getProjectConfig($projectRoot) { if (!isset(self::$projectConfig[$projectRoot])) { $this->debug('Loading project config for ' . $projectRoot); self::$projectConfig[$projectRoot] = LocalProject::getProjectConfig($projectRoot) ?: []; } return self::$projectConfig[$projectRoot]; }
/** * Get the current project if the user is in a project directory. * * @throws \RuntimeException * * @return Project|false The current project */ public function getCurrentProject() { if (!$this->getProjectRoot()) { return false; } $project = false; $config = LocalProject::getProjectConfig($this->getProjectRoot()); if ($config) { $project = $this->getProject($config['id']); // There is a chance that the project isn't available. if (!$project) { $filename = LocalProject::getProjectRoot() . '/' . LocalProject::PROJECT_CONFIG; throw new \RuntimeException("Project ID not found: " . $config['id'] . "\nEither you do not have access to the project on Platform.sh, or it no longer exists." . "\nThe project ID was determined from the file: " . $filename); } } return $project; }
protected function execute(InputInterface $input, OutputInterface $output) { $project = $this->getCurrentProject(); if (!$project) { throw new \Exception('This can only be run from inside a project directory'); } $projectRoot = $this->getProjectRoot(); $projectConfig = LocalProject::getProjectConfig($projectRoot); $current_group = isset($projectConfig['alias-group']) ? $projectConfig['alias-group'] : $project['id']; if ($input->getOption('pipe') || !$this->isTerminal($output)) { $output->writeln($current_group); return 0; } $new_group = ltrim($input->getOption('group'), '@'); $homeDir = $this->getHelper('fs')->getHomeDirectory(); $drushHelper = new DrushHelper($output); $drushHelper->ensureInstalled(); $drushHelper->setHomeDir($homeDir); if ($new_group && $new_group != $current_group) { $questionHelper = $this->getHelper('question'); $existing = $drushHelper->getAliases($new_group); if ($existing) { if (!$questionHelper->confirm("The alias group <info>@{$new_group}</info> already exists. Overwrite?", $input, $output, false)) { return 1; } } $project['alias-group'] = $new_group; LocalProject::writeCurrentProjectConfig('alias-group', $new_group, $projectRoot); $output->write("Creating Drush aliases in the group <info>@{$new_group}</info>..."); $environments = $this->getEnvironments($project, true, false); $drushHelper->createAliases($project, $projectRoot, $environments); $output->writeln(" done"); $drushDir = $homeDir . '/.drush'; $oldFile = $drushDir . '/' . $current_group . '.aliases.drushrc.php'; if (file_exists($oldFile)) { if ($questionHelper->confirm("Delete old alias group <info>@{$current_group}</info>?", $input, $output)) { unlink($oldFile); } } // Clear the Drush cache now that the aliases have been updated. $drushHelper->clearCache(); $current_group = $new_group; } elseif ($input->getOption('recreate')) { $output->write("Recreating Drush aliases..."); $environments = $this->getEnvironments($project, true, false); $drushHelper->createAliases($project, $projectRoot, $environments); $drushHelper->clearCache(); $output->writeln(' done'); } // Don't run expensive drush calls if they are not needed. if ($input->getOption('quiet')) { return 0; } $aliases = $drushHelper->getAliases($current_group); if ($aliases) { $output->writeln("Aliases for <info>{$project['name']}</info> ({$project['id']}):"); foreach (explode("\n", $aliases) as $alias) { $output->writeln(' @' . $alias); } } return 0; }
/** * Get the project configuration. * * @param string $projectRoot * * @return array */ protected function getProjectConfig($projectRoot) { if (!isset($this->projectConfig[$projectRoot])) { $this->projectConfig[$projectRoot] = LocalProject::getProjectConfig($projectRoot) ?: []; } return $this->projectConfig[$projectRoot]; }
/** * Returns current project's Platform.sh config. * * @throws \Exception */ protected function getProjectConfig() { $this->platformConfig = LocalProject::getProjectConfig(); }
/** * 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; }
/** * 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 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, $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 alias file so that the user's own modifications can be // merged. $aliases = array(); if (file_exists($filename) && $merge) { // This may create a PHP parse error for invalid syntax, but in // that case the user could not run Drush anyway. include $filename; } // Generate aliases for the remote environments. $numValidEnvironments = 0; $autoGenerated = ''; foreach ($environments as $environment) { $newAlias = $this->generateRemoteAlias($environment); if (!$newAlias) { continue; } // If the alias already exists, recursively replace existing // settings with new ones. if (isset($aliases[$environment['id']])) { $newAlias = array_replace_recursive($aliases[$environment['id']], $newAlias); unset($aliases[$environment['id']]); } $autoGenerated .= "\n// Automatically generated alias for the environment \"" . $environment['title'] . "\".\n"; $autoGenerated .= $this->exportAlias($environment['id'], $newAlias); $numValidEnvironments++; } // Generate an alias for the local environment. $localAliasName = '_local'; $local = array('root' => $projectRoot . '/' . LocalProject::WEB_ROOT, self::AUTO_REMOVE_KEY => true); if (isset($aliases[$localAliasName])) { $local = array_replace_recursive($aliases[$localAliasName], $local); unset($aliases[$localAliasName]); } $localAlias = "\n// Automatically generated alias for the local environment.\n" . $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; }