/** * @return string|false */ public function getProjectRoot() { if (!isset(self::$projectRoot)) { $this->debug('Finding the project root based on the CWD'); self::$projectRoot = $this->localProject->getProjectRoot(); $this->debug(self::$projectRoot ? 'Project root found: ' . self::$projectRoot : 'Project root not found'); } return self::$projectRoot; }
/** * Builds Docker Compose YML file. * * @param $name */ function __construct($name) { $this->path = LocalProject::getProjectRoot(); $this->name = $name; // Add required containers. $this->addPhpFpm(); $this->addDatabase(); $this->addWebserver(); }
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; }
/** * @param string $sourceDir * * @return string */ protected function createDummyProject($sourceDir) { if (!is_dir($sourceDir)) { throw new \InvalidArgumentException("Not a directory: {$sourceDir}"); } $tempDir = self::$root->getName(); $projectRoot = tempnam($tempDir, ''); unlink($projectRoot); mkdir($projectRoot); // Set up the project files. $local = new LocalProject(); $local->createProjectFiles($projectRoot, 'testProjectId'); // Make a dummy repository. $repositoryDir = $projectRoot . '/' . LocalProject::REPOSITORY_DIR; mkdir($repositoryDir); $fsHelper = new FilesystemHelper(); $fsHelper->copyAll($sourceDir, $repositoryDir); return $projectRoot; }
/** * @param string $sourceDir * * @return string */ protected function createDummyProject($sourceDir) { if (!is_dir($sourceDir)) { throw new \InvalidArgumentException("Not a directory: {$sourceDir}"); } $projectRoot = $this->createTempSubDir('project'); // Set up the project. $fsHelper = new FilesystemHelper(); $fsHelper->copyAll($sourceDir, $projectRoot); // @todo perhaps make some of these steps unnecessary $local = new LocalProject(); $cwd = getcwd(); chdir($projectRoot); exec('git init'); chdir($cwd); $local->ensureGitRemote($projectRoot, 'testProjectId'); $local->writeCurrentProjectConfig(['id' => 'testProjectId'], $projectRoot); return $projectRoot; }
protected function execute(InputInterface $input, OutputInterface $output) { $directory = $input->getArgument('directory') ?: getcwd(); $realPath = realpath($directory); if (!$realPath) { $this->stdErr->writeln("<error>Directory not found: {$directory}</error>"); return 1; } if (!is_dir($realPath . '/.git')) { /** @var \Platformsh\Cli\Helper\PlatformQuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); $question = "The directory is not a Git repository: <comment>{$realPath}</comment>\nInitialize a Git repository?"; if ($questionHelper->confirm($question, $input, $this->stdErr)) { /** @var \Platformsh\Cli\Helper\GitHelper $gitHelper */ $gitHelper = $this->getHelper('git'); $gitHelper->ensureInstalled(); $gitHelper->init($realPath, true); } } $gitUrl = null; $projectId = $input->getOption('project') ?: null; if ($projectId !== null) { $project = $this->getProject($projectId, $input->getOption('host')); if (!$project) { $this->stdErr->writeln("Project not found: <error>{$projectId}</error>"); return 1; } $gitUrl = $project->getGitUrl(); $projectId = $project->id; } $inside = strpos(getcwd(), $realPath) === 0; $local = new LocalProject(); $projectRoot = $local->initialize($realPath, $projectId, $gitUrl); // Fetch environments to start caching, and to create Drush aliases, // etc. $this->setProjectRoot($projectRoot); $this->getEnvironments($this->getCurrentProject(), true); $this->stdErr->writeln("Project initialized in directory: <info>{$projectRoot}</info>"); if ($inside) { $this->stdErr->writeln("<comment>Type 'cd .' to refresh your shell</comment>"); } return 0; }
/** * {@inheritdoc} * * @see PlatformCommand::getCurrentEnvironment() */ protected function execute(InputInterface $input, OutputInterface $output) { $xhpfg = LocalProject::getProjectRoot() . '/docker/xhpfg/xhprof-sample-to-flamegraph-stacks'; $fg = LocalProject::getProjectRoot() . '/docker/fg/flamegraph.pl'; $xhprof = LocalProject::getProjectRoot() . '/xhprof'; $graphName = $input->getArgument('filename'); $graphDestination = LocalProject::getProjectRoot() . '/' . $graphName . '.svg'; exec("{$xhpfg} {$xhprof} | {$fg} > {$graphDestination}"); $url = 'file://' . $graphDestination; $this->openUrl($url); }
protected function execute(InputInterface $input, OutputInterface $output) { $directory = $input->getArgument('directory') ?: getcwd(); $realPath = realpath($directory); if (!$realPath) { $output->writeln("<error>Directory not found: {$directory}</error>"); return 1; } $inside = strpos(getcwd(), $realPath) === 0; $local = new LocalProject(); $projectRoot = $local->initialize($directory); // Fetch environments to start caching, and to create Drush aliases, // etc. $this->setProjectRoot($projectRoot); $this->getEnvironments($this->getCurrentProject(), true); $output->writeln("Project initialized in directory: <info>{$projectRoot}</info>"); if ($inside) { $output->writeln("<comment>Type 'cd .' to refresh your shell</comment>"); } return 0; }
public function testGetProjectRoot() { $tempDir = $this->root->getName(); $testDir = tempnam($tempDir, ''); unlink($testDir); mkdir("{$testDir}/1/2/3/4/5", 0755, true); $expectedRoot = "{$testDir}/1"; touch("{$expectedRoot}/.platform-project"); chdir($testDir); $this->assertFalse(LocalProject::getProjectRoot()); chdir($expectedRoot); $this->assertEquals($expectedRoot, LocalProject::getProjectRoot()); chdir("{$testDir}/1/2/3/4/5"); $this->assertEquals($expectedRoot, LocalProject::getProjectRoot()); }
/** * {@inheritdoc} * * @see PlatformCommand::getCurrentEnvironment() */ protected function execute(InputInterface $input, OutputInterface $output) { /** @var ShellHelper $shell */ $shell = $this->getHelper('shell'); $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); $shell->setOutput($output); if (!is_dir(LocalProject::getProjectRoot() . '/docker/fg')) { $shell->execute(['git', 'clone', 'https://github.com/brendangregg/FlameGraph.git', LocalProject::getProjectRoot() . '/docker/fg']); } if (!is_dir(LocalProject::getProjectRoot() . '/docker/xhpfg')) { $shell->execute(['git', 'clone', 'https://github.com/msonnabaum/xhprof-flamegraphs.git', LocalProject::getProjectRoot() . '/docker/xhpfg']); } $this->stdOut->writeln("<comment>Patching Drupal for xhprof</comment>"); $process = new Process('patch -p1 < ' . CLI_ROOT . '/resources/drupal-enable-profiling.patch', Platform::webDir()); $process->mustRun(null); }
/** * */ public function __construct() { $this->resourcesDir = CLI_ROOT . '/resources'; $this->projectPath = LocalProject::getProjectRoot(); $this->fs = new Filesystem(); }
protected function execute(InputInterface $input, OutputInterface $output) { $projectId = $input->getArgument('id'); $environmentOption = $input->getOption('environment'); $hostOption = $input->getOption('host'); if (empty($projectId)) { if ($input->isInteractive() && ($projects = $this->getProjects(true))) { $projectId = $this->offerProjectChoice($projects, $input); } else { $this->stdErr->writeln("<error>You must specify a project.</error>"); return 1; } } else { $result = $this->parseProjectId($projectId); $projectId = $result['projectId']; $hostOption = $hostOption ?: $result['host']; $environmentOption = $environmentOption ?: $result['environmentId']; } $project = $this->getProject($projectId, $hostOption, true); if (!$project) { $this->stdErr->writeln("<error>Project not found: {$projectId}</error>"); return 1; } $environments = $this->getEnvironments($project); if ($environmentOption) { if (!isset($environments[$environmentOption])) { // Reload the environments list. $environments = $this->getEnvironments($project, true); if (!isset($environments[$environmentOption])) { $this->stdErr->writeln("Environment not found: <error>{$environmentOption}</error>"); } return 1; } $environment = $environmentOption; } elseif (count($environments) === 1) { $environment = key($environments); } else { $environment = 'master'; } /** @var \Platformsh\Cli\Helper\PlatformQuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); $directory = $input->getArgument('directory'); if (empty($directory)) { $slugify = new Slugify(); $directory = $project->title ? $slugify->slugify($project->title) : $project->id; $directory = $questionHelper->askInput('Directory', $input, $this->stdErr, $directory); } if ($projectRoot = $this->getProjectRoot()) { if (strpos(realpath(dirname($directory)), $projectRoot) === 0) { $this->stdErr->writeln("<error>A project cannot be cloned inside another project.</error>"); return 1; } } /** @var \Platformsh\Cli\Helper\FilesystemHelper $fsHelper */ $fsHelper = $this->getHelper('fs'); // Create the directory structure. $existed = false; if (file_exists($directory)) { $existed = true; $this->stdErr->writeln("The directory <error>{$directory}</error> already exists"); if (file_exists($directory . '/' . LocalProject::PROJECT_CONFIG) && $questionHelper->confirm("Overwrite?", $input, $this->stdErr, false)) { $fsHelper->remove($directory); } else { return 1; } } mkdir($directory); $projectRoot = realpath($directory); if (!$projectRoot) { throw new \Exception("Failed to create project directory: {$directory}"); } if ($existed) { $this->stdErr->writeln("Re-created project directory: {$directory}"); } else { $this->stdErr->writeln("Created new project directory: {$directory}"); } $cleanUp = function () use($projectRoot, $fsHelper) { $fsHelper->remove($projectRoot); }; $local = new LocalProject(); $hostname = parse_url($project->getUri(), PHP_URL_HOST) ?: null; $local->createProjectFiles($projectRoot, $project->id, $hostname); // Prepare to talk to the Platform.sh repository. $gitUrl = $project->getGitUrl(); $repositoryDir = $projectRoot . '/' . LocalProject::REPOSITORY_DIR; $gitHelper = new GitHelper(new ShellHelper($this->stdErr)); $gitHelper->ensureInstalled(); // First check if the repo actually exists. $repoHead = $gitHelper->execute(['ls-remote', $gitUrl, 'HEAD'], false); if ($repoHead === false) { // The ls-remote command failed. $cleanUp(); $this->stdErr->writeln('<error>Failed to connect to the Platform.sh Git server</error>'); // Suggest SSH key commands. $sshKeys = []; try { $sshKeys = $this->getClient(false)->getSshKeys(); } catch (\Exception $e) { // Ignore exceptions. } if (!empty($sshKeys)) { $this->stdErr->writeln(''); $this->stdErr->writeln('Please check your SSH credentials'); $this->stdErr->writeln('You can list your keys with: <comment>platform ssh-keys</comment>'); } else { $this->stdErr->writeln('You probably need to add an SSH key, with: <comment>platform ssh-key:add</comment>'); } return 1; } elseif (is_bool($repoHead)) { // The repository doesn't have a HEAD, which means it is empty. // We need to create the folder, run git init, and attach the remote. mkdir($repositoryDir); // Initialize the repo and attach our remotes. $this->stdErr->writeln("Initializing empty project repository"); $gitHelper->execute(['init'], $repositoryDir, true); $this->stdErr->writeln("Adding Platform.sh Git remote"); $local->ensureGitRemote($repositoryDir, $gitUrl); $this->stdErr->writeln("Your repository has been initialized and connected to <info>Platform.sh</info>!"); $this->stdErr->writeln("Commit and push to the <info>{$environment}</info> branch and Platform.sh will build your project automatically"); return 0; } // We have a repo! Yay. Clone it. $cloneArgs = ['--branch', $environment, '--origin', 'platform']; $cloned = $gitHelper->cloneRepo($gitUrl, $repositoryDir, $cloneArgs); if (!$cloned) { // The clone wasn't successful. Clean up the folders we created // and then bow out with a message. $cleanUp(); $this->stdErr->writeln('<error>Failed to clone Git repository</error>'); $this->stdErr->writeln('Please check your SSH credentials or contact Platform.sh support'); return 1; } $gitHelper->updateSubmodules(true, $repositoryDir); $local->ensureGitRemote($repositoryDir, $gitUrl); $this->setProjectRoot($projectRoot); $this->stdErr->writeln("\nThe project <info>{$project->title}</info> was successfully downloaded to: <info>{$directory}</info>"); // Return early if there is no code in the repository. if (!glob($repositoryDir . '/*')) { return 0; } // Ensure that Drush aliases are created. if (Drupal::isDrupal($projectRoot . '/' . LocalProject::REPOSITORY_DIR)) { $this->stdErr->writeln(''); $this->runOtherCommand('local:drush-aliases', ['--group' => basename($directory)]); } // Launch the first build. $success = true; if ($input->getOption('build')) { // Launch the first build. $this->stdErr->writeln(''); $this->stdErr->writeln('Building the project locally for the first time. Run <info>platform build</info> to repeat this.'); $options = ['environmentId' => $environment, 'noClean' => true]; $builder = new LocalBuild($options, $output); $success = $builder->buildProject($projectRoot); } else { $this->stdErr->writeln("\nYou can build the project with: " . "\n cd {$directory}" . "\n platform build"); } return $success ? 0 : 1; }
/** * @return string|false */ public function getProjectRoot() { if (empty(self::$projectRoot)) { self::$projectRoot = LocalProject::getProjectRoot(); } return self::$projectRoot; }
protected function execute(InputInterface $input, OutputInterface $output) { $project = $this->getCurrentProject(); if (!$project) { throw new RootNotFoundException(); } $specifiedBranch = $input->getArgument('id'); if (empty($specifiedBranch) && $input->isInteractive()) { $environments = $this->getEnvironments($project); $currentEnvironment = $this->getCurrentEnvironment($project); if ($currentEnvironment) { $this->stdErr->writeln("The current environment is <info>{$currentEnvironment['title']}</info>."); } $environmentList = array(); foreach ($environments as $id => $environment) { if ($currentEnvironment && $id == $currentEnvironment['id']) { continue; } $environmentList[$id] = $environment['title']; } $config = $this->getProjectConfig($this->getProjectRoot()); if (!empty($config['mapping'])) { foreach ($config['mapping'] as $branch => $id) { unset($environmentList[$id]); if ($currentEnvironment && $id == $currentEnvironment['id']) { continue; } if (!isset($environments[$id])) { continue; } $environmentList[$branch] = sprintf('%s (%s)', $environments[$id]->title, $branch); } } if (!count($environmentList)) { $this->stdErr->writeln("Use <info>platform branch</info> to create an environment."); return 1; } $chooseEnvironmentText = "Enter a number to check out another environment:"; $helper = $this->getHelper('question'); $specifiedBranch = $helper->choose($environmentList, $chooseEnvironmentText, $input, $output); } elseif (empty($specifiedBranch)) { $this->stdErr->writeln("<error>No branch specified.</error>"); return 1; } $projectRoot = $this->getProjectRoot(); $repositoryDir = $projectRoot . '/' . LocalProject::REPOSITORY_DIR; $gitHelper = new GitHelper(new ShellHelper($this->stdErr)); $gitHelper->setDefaultRepositoryDir($repositoryDir); $branch = $this->branchExists($specifiedBranch, $project, $gitHelper); if (!$branch) { $this->stdErr->writeln("<error>Branch not found: {$specifiedBranch}</error>"); return 1; } // If the branch exists locally, check it out directly. if ($gitHelper->branchExists($branch)) { $this->stdErr->writeln("Checking out <info>{$branch}</info>"); return $gitHelper->checkOut($branch) ? 0 : 1; } // Make sure that remotes are set up correctly. $localProject = new LocalProject(); $localProject->ensureGitRemote($repositoryDir, $project->getGitUrl()); // Determine the correct upstream for the new branch. If there is an // 'origin' remote, then it has priority. $upstreamRemote = 'platform'; if ($gitHelper->getConfig('remote.origin.url') && $gitHelper->remoteBranchExists('origin', $branch)) { $upstreamRemote = 'origin'; } $this->stdErr->writeln("Creating branch {$branch} based on upstream {$upstreamRemote}/{$branch}"); // Fetch the branch from the upstream remote. $gitHelper->execute(array('fetch', $upstreamRemote, $branch)); // Create the new branch, and set the correct upstream. $success = $gitHelper->checkoutNew($branch, $upstreamRemote . '/' . $branch); return $success ? 0 : 1; }
public static function webDir() { return LocalProject::getProjectRoot() . '/' . LocalProject::WEB_ROOT; }
/** * 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; }
/** * @return string|false */ protected function getProjectRoot() { return $this->projectRoot ?: LocalProject::getProjectRoot(); }
/** * 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; }
/** * Returns current project's Platform.sh config. * * @throws \Exception */ protected function getProjectConfig() { $this->platformConfig = LocalProject::getProjectConfig(); }
protected function execute(InputInterface $input, OutputInterface $output) { $projectId = $input->getArgument('id'); if (empty($projectId)) { if ($input->isInteractive() && ($projects = $this->getProjects(true))) { $projectId = $this->offerProjectChoice($projects, $input); } else { $this->stdErr->writeln("<error>You must specify a project.</error>"); return 1; } } $project = $this->getProject($projectId, $input->getOption('host')); if (!$project) { $this->stdErr->writeln("<error>Project not found: {$projectId}</error>"); return 1; } /** @var \Platformsh\Cli\Helper\PlatformQuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); $directoryName = $input->getArgument('directory-name'); if (empty($directoryName)) { $slugify = new Slugify(); $directoryName = $project->title ? $slugify->slugify($project->title) : $project->id; $directoryName = $questionHelper->askInput('Directory name', $input, $this->stdErr, $directoryName); } if ($projectRoot = $this->getProjectRoot()) { if (strpos(realpath(dirname($directoryName)), $projectRoot) === 0) { $this->stdErr->writeln("<error>A project cannot be cloned inside another project.</error>"); return 1; } } /** @var \Platformsh\Cli\Helper\FilesystemHelper $fsHelper */ $fsHelper = $this->getHelper('fs'); // Create the directory structure. $existed = false; if (file_exists($directoryName)) { $existed = true; $this->stdErr->writeln("The directory <error>{$directoryName}</error> already exists"); if ($questionHelper->confirm("Overwrite?", $input, $this->stdErr, false)) { $fsHelper->remove($directoryName); } else { return 1; } } mkdir($directoryName); $projectRoot = realpath($directoryName); if (!$projectRoot) { throw new \Exception("Failed to create project directory: {$directoryName}"); } if ($existed) { $this->stdErr->writeln("Re-created project directory: <info>{$directoryName}</info>"); } else { $this->stdErr->writeln("Created new project directory: <info>{$directoryName}</info>"); } $local = new LocalProject(); $hostname = parse_url($project->getUri(), PHP_URL_HOST) ?: null; $local->createProjectFiles($projectRoot, $project->id, $hostname); $environments = $this->getEnvironments($project, true); $environmentOption = $input->getOption('environment'); if ($environmentOption) { if (!isset($environments[$environmentOption])) { $this->stdErr->writeln("Environment not found: <error>{$environmentOption}</error>"); return 1; } $environment = $environmentOption; } elseif (count($environments) === 1) { $environment = key($environments); } elseif ($environments && $input->isInteractive()) { $environment = $this->offerEnvironmentChoice($environments, $input); } else { $environment = 'master'; } // Prepare to talk to the Platform.sh repository. $gitUrl = $project->getGitUrl(); $repositoryDir = $directoryName . '/' . LocalProject::REPOSITORY_DIR; $gitHelper = new GitHelper(new ShellHelper($this->stdErr)); $gitHelper->ensureInstalled(); // First check if the repo actually exists. $repoHead = $gitHelper->execute(array('ls-remote', $gitUrl, 'HEAD'), false); if ($repoHead === false) { // The ls-remote command failed. $fsHelper->rmdir($projectRoot); $this->stdErr->writeln('<error>Failed to connect to the Platform.sh Git server</error>'); $this->stdErr->writeln('Please check your SSH credentials or contact Platform.sh support'); return 1; } elseif (is_bool($repoHead)) { // The repository doesn't have a HEAD, which means it is empty. // We need to create the folder, run git init, and attach the remote. mkdir($repositoryDir); // Initialize the repo and attach our remotes. $this->stdErr->writeln("Initializing empty project repository"); $gitHelper->execute(array('init'), $repositoryDir, true); $this->stdErr->writeln("Adding Platform.sh Git remote"); $local->ensureGitRemote($repositoryDir, $gitUrl); $this->stdErr->writeln("Your repository has been initialized and connected to <info>Platform.sh</info>!"); $this->stdErr->writeln("Commit and push to the <info>{$environment}</info> branch and Platform.sh will build your project automatically"); return 0; } // We have a repo! Yay. Clone it. $cloneArgs = array('--branch', $environment, '--origin', 'platform'); $cloned = $gitHelper->cloneRepo($gitUrl, $repositoryDir, $cloneArgs); if (!$cloned) { // The clone wasn't successful. Clean up the folders we created // and then bow out with a message. $fsHelper->rmdir($projectRoot); $this->stdErr->writeln('<error>Failed to clone Git repository</error>'); $this->stdErr->writeln('Please check your SSH credentials or contact Platform.sh support'); return 1; } $local->ensureGitRemote($repositoryDir, $gitUrl); $this->setProjectRoot($projectRoot); $this->stdErr->writeln(''); $this->stdErr->writeln("The project <info>{$project->title}</info> was successfully downloaded to: <info>{$directoryName}</info>"); // Ensure that Drush aliases are created. if (Drupal::isDrupal($projectRoot . '/' . LocalProject::REPOSITORY_DIR)) { $this->stdErr->writeln(''); $this->runOtherCommand('local:drush-aliases', array('--group' => $directoryName), $input); } // Allow the build to be skipped. if ($input->getOption('no-build')) { return 0; } // Always skip the build if the cloned repository is empty ('.', '..', // '.git' being the only found items) if (count(scandir($repositoryDir)) <= 3) { return 0; } // Launch the first build. $this->stdErr->writeln(''); $this->stdErr->writeln('Building the project locally for the first time. Run <info>platform build</info> to repeat this.'); $builder = new LocalBuild(array('environmentId' => $environment), $output); $success = $builder->buildProject($projectRoot); return $success ? 0 : 1; }
protected function execute(InputInterface $input, OutputInterface $output) { $projectId = $input->getArgument('id'); if (empty($projectId)) { if ($input->isInteractive() && ($projects = $this->getProjects(true))) { $projectId = $this->offerProjectChoice($projects, $input, $output); } else { $output->writeln("<error>You must specify a project.</error>"); return 1; } } $project = $this->getProject($projectId); if (!$project) { $output->writeln("<error>Project not found: {$projectId}</error>"); return 1; } $directoryName = $input->getArgument('directory-name'); if (empty($directoryName)) { $directoryName = $projectId; } if (file_exists($directoryName)) { $output->writeln("<error>The project directory '{$directoryName}' already exists.</error>"); return 1; } if ($projectRoot = $this->getProjectRoot()) { if (strpos(realpath(dirname($directoryName)), $projectRoot) === 0) { $output->writeln("<error>A project cannot be cloned inside another project.</error>"); return 1; } } // Create the directory structure. mkdir($directoryName); $projectRoot = realpath($directoryName); if (!$projectRoot) { throw new \Exception("Failed to create project directory: {$directoryName}"); } $output->writeln("Created project directory: {$directoryName}"); $local = new LocalProject(); $local->createProjectFiles($projectRoot, $projectId); $environments = $this->getEnvironments($project, true); $environmentOption = $input->getOption('environment'); if ($environmentOption) { if (!isset($environments[$environmentOption])) { $output->writeln("<error>Environment not found: {$environmentOption}</error>"); return 1; } $environment = $environmentOption; } elseif (count($environments) === 1) { $environment = key($environments); } elseif ($environments && $input->isInteractive()) { $environment = $this->offerEnvironmentChoice($environments, $input, $output); } else { $environment = 'master'; } /** @var \Platformsh\Cli\Helper\FilesystemHelper $fsHelper */ $fsHelper = $this->getHelper('fs'); // Prepare to talk to the Platform.sh repository. if (isset($project['repository'])) { $gitUrl = $project['repository']['url']; } else { $projectUriParts = explode('/', str_replace(array('http://', 'https://'), '', $project['uri'])); $cluster = $projectUriParts[0]; $gitUrl = "{$projectId}@git.{$cluster}:{$projectId}.git"; } $repositoryDir = $directoryName . '/' . LocalProject::REPOSITORY_DIR; $gitHelper = new GitHelper(new ShellHelper($output)); // First check if the repo actually exists. $repoHead = $gitHelper->execute(array('ls-remote', $gitUrl, 'HEAD'), false); if ($repoHead === false) { // The ls-remote command failed. $fsHelper->rmdir($projectRoot); $output->writeln('<error>Failed to connect to the Platform.sh Git server</error>'); $output->writeln('Please check your SSH credentials or contact Platform.sh support'); return 1; } elseif (is_bool($repoHead)) { // The repository doesn't have a HEAD, which means it is empty. // We need to create the folder, run git init, and attach the remote. mkdir($repositoryDir); // Initialize the repo and attach our remotes. $output->writeln("<info>Initializing empty project repository...</info>"); $gitHelper->execute(array('init'), $repositoryDir, true); $output->writeln("<info>Adding Platform.sh remote endpoint to Git...</info>"); $gitHelper->execute(array('remote', 'add', '-m', 'master', 'origin', $gitUrl), $repositoryDir, true); $output->writeln("<info>Your repository has been initialized and connected to Platform.sh!</info>"); $output->writeln("<info>Commit and push to the {$environment} branch and Platform.sh will build your project automatically.</info>"); return 0; } // We have a repo! Yay. Clone it. if (!$gitHelper->cloneRepo($gitUrl, $repositoryDir, $environment)) { // The clone wasn't successful. Clean up the folders we created // and then bow out with a message. $fsHelper->rmdir($projectRoot); $output->writeln('<error>Failed to clone Git repository</error>'); $output->writeln('Please check your SSH credentials or contact Platform.sh support'); return 1; } $output->writeln("The project <info>{$project['name']}</info> was successfully downloaded to: <info>{$directoryName}</info>"); // Ensure that Drush aliases are created. $this->setProjectRoot($projectRoot); $this->updateDrushAliases($project, $environments); // Allow the build to be skipped. if ($input->getOption('no-build')) { return 0; } // Always skip the build if the cloned repository is empty ('.', '..', // '.git' being the only found items) if (count(scandir($repositoryDir)) <= 3) { return 0; } // Launch the first build. try { $builder = new LocalBuild(array('environmentId' => $environment), $output); $builder->buildProject($projectRoot); } catch (\Exception $e) { $output->writeln("<comment>The build failed with an error</comment>"); $formattedMessage = $this->getHelper('formatter')->formatBlock($e->getMessage(), 'comment'); $output->writeln($formattedMessage); } return 0; }
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; }