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;
}