execute() public method

Execute a Git command.
public execute ( array $args, string | false $dir = null, boolean $mustRun = false, boolean $quiet = true ) : string | boolean
$args array Command arguments (everything after 'git').
$dir string | false The path to a Git repository. Set to false if the command should not run inside a repository.
$mustRun boolean Enable exceptions if the Git command fails.
$quiet boolean Suppress command output.
return string | boolean The command output, true if there is no output, or false if the command fails.
Esempio n. 1
0
 /**
  * Get a hash of the application files.
  *
  * This should change if any of the application files or build settings
  * change.
  *
  * @param string $appRoot
  *
  * @return string|false
  */
 public function getTreeId($appRoot)
 {
     $hashes = [];
     // Get a hash representing all the files in the application, excluding
     // the project config folder (CLI_PROJECT_CONFIG_DIR).
     $tree = $this->gitHelper->execute(['ls-files', '-s'], $appRoot);
     if ($tree === false) {
         return false;
     }
     $tree = preg_replace('#^|\\n[^\\n]+?' . preg_quote($this->config->get('service.project_config_dir')) . '\\n|$#', "\n", $tree);
     $hashes[] = sha1($tree);
     // Include the hashes of untracked and modified files.
     $others = $this->gitHelper->execute(['ls-files', '--modified', '--others', '--exclude-standard', '-x ' . $this->config->get('service.project_config_dir'), '.'], $appRoot);
     if ($others === false) {
         return false;
     }
     $count = 0;
     foreach (explode("\n", $others) as $filename) {
         if ($count > 5000) {
             return false;
         }
         $filename = "{$appRoot}/{$filename}";
         if (is_file($filename)) {
             $hashes[] = sha1_file($filename);
             $count++;
         }
     }
     // Include relevant build settings.
     $relevant = ['abslinks', 'copy', 'clone', 'no-cache', 'working-copy', 'lock'];
     $settings = array_intersect_key($this->settings, array_flip($relevant));
     $hashes[] = serialize($settings);
     $hashes[] = self::BUILD_VERSION;
     // Combine them all.
     return sha1(implode(' ', $hashes));
 }
Esempio n. 2
0
 /**
  * Ensure there are appropriate Git remotes in the repository.
  *
  * @param string $dir
  * @param string $url
  */
 public function ensureGitRemote($dir, $url)
 {
     if (!file_exists($dir . '/.git')) {
         throw new \InvalidArgumentException('The directory is not a Git repository');
     }
     $gitHelper = new GitHelper();
     $gitHelper->ensureInstalled();
     $gitHelper->setDefaultRepositoryDir($dir);
     $currentUrl = $gitHelper->getConfig("remote." . $this->config->get('detection.git_remote_name') . ".url", $dir);
     if (!$currentUrl) {
         $gitHelper->execute(['remote', 'add', $this->config->get('detection.git_remote_name'), $url], $dir, true);
     } elseif ($currentUrl != $url) {
         $gitHelper->execute(['remote', 'set-url', $this->config->get('detection.git_remote_name'), $url], $dir, true);
     }
     // Add an origin remote too.
     if ($this->config->get('detection.git_remote_name') !== 'origin' && !$gitHelper->getConfig("remote.origin.url", $dir)) {
         $gitHelper->execute(['remote', 'add', 'origin', $url]);
     }
 }
 /**
  * Clone the app to the build directory via Git.
  *
  * @param string $buildDir
  */
 private function cloneToBuildDir($buildDir)
 {
     $gitRoot = $this->gitHelper->getRoot($this->appRoot, true);
     $ref = $this->gitHelper->execute(['rev-parse', 'HEAD'], $gitRoot, true);
     $cloneArgs = ['--recursive', '--shared'];
     $tmpRepo = $buildDir . '-repo';
     if (file_exists($tmpRepo)) {
         $this->fsHelper->remove($tmpRepo, true);
     }
     $this->gitHelper->cloneRepo($gitRoot, $tmpRepo, $cloneArgs, true);
     $this->gitHelper->checkOut($ref, $tmpRepo, true, true);
     $this->fsHelper->remove($tmpRepo . '/.git');
     $appDir = $tmpRepo . '/' . substr($this->appRoot, strlen($gitRoot));
     if (!rename($appDir, $buildDir)) {
         throw new \RuntimeException(sprintf('Failed to move app from %s to %s', $appDir, $buildDir));
     }
     $this->fsHelper->remove($tmpRepo);
 }
 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)
 {
     $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;
 }
Esempio n. 6
0
 /**
  * Ensure there are appropriate Git remotes in the repository.
  *
  * @param string $dir
  * @param string $url
  */
 public function ensureGitRemote($dir, $url)
 {
     if (!file_exists("{$dir}/.git")) {
         throw new \InvalidArgumentException('The directory is not a Git repository');
     }
     $gitHelper = new GitHelper();
     $gitHelper->ensureInstalled();
     $gitHelper->setDefaultRepositoryDir($dir);
     $platformUrl = $gitHelper->getConfig("remote.platform.url", $dir);
     if (!$platformUrl) {
         $gitHelper->execute(array('remote', 'add', 'platform', $url), $dir, true);
     } elseif ($platformUrl != $url) {
         $gitHelper->execute(array('remote', 'set-url', 'platform', $url), $dir, true);
     }
     // Add an origin remote too.
     if (!$gitHelper->getConfig("remote.origin.url", $dir)) {
         $gitHelper->execute(array('remote', 'add', 'origin', $url));
     }
 }
 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;
 }