protected function execute(InputInterface $input, OutputInterface $output) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ $config = $configHelper->getConfiguration(); $config = $config->getConfigOption(Util::createPropertyPath($input->getArgument('parameter'))); foreach ($input->getOption('filter') as $fn) { try { if (!is_callable($fn)) { throw new \InvalidArgumentException(sprintf('"%s" is not callable', $fn)); } if (!function_exists($fn)) { throw new \InvalidArgumentException(sprintf('"%s" does not exist', $fn)); } $prevError = error_get_last(); $config = @$fn($config); $currError = error_get_last(); if ($prevError !== $currError) { throw new \InvalidArgumentException(sprintf('"%s" failed: %s', $fn, error_get_last()['message'])); } } catch (\Exception $ex) { throw new \InvalidArgumentException(sprintf('Filtering with function "%s" did not work', $fn), 0, $ex); } } if (is_null($config)) { // noop } elseif (is_scalar($config)) { $output->writeln($config); } else { foreach (self::flatten($config) as $parameter => $value) { $output->writeln(sprintf('%s: %s', $parameter, $value)); } } }
protected function execute(InputInterface $input, OutputInterface $output) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ $configHelper->getConfiguration()->removeConfigOption(Util::createPropertyPath($input->getArgument('parameter'))); $configHelper->getConfiguration()->write(); }
protected function execute(InputInterface $input, OutputInterface $output) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ $questionHelper = $this->getHelper('question'); /* @var $questionHelper QuestionHelper */ $sshConfig = new \SplFileInfo($configHelper->getConfiguration()->getSshDirectory() . '/config'); if (!$sshConfig->isFile()) { throw new NotAFileException($sshConfig); } if (!$sshConfig->isReadable()) { throw new UnreadableFileException($sshConfig); } if (!$sshConfig->isWritable()) { throw new UnwritableFileException($sshConfig); } $sshConfigLines = file($sshConfig->getPathname()); $repoName = $input->getArgument('repository'); $repositoryConfig = $configHelper->getConfiguration()->getRepositoryConfiguration($repoName); if (!$questionHelper->ask($input, $output, new ConfirmationQuestion(sprintf('Are you sure you want to remove the ssh key for "%s"? This action is irreversible.', $repoName)))) { return 1; } $sshKeyFile = $repositoryConfig->getIdentityFile(); $this->unlinkFile($output, $sshKeyFile); $this->unlinkFile($output, $sshKeyFile . '.pub'); if (Util::removeSshAliasLines($sshConfigLines, $repositoryConfig)) { $output->writeln(sprintf('Removed section <info>Host %s</info> from <info>%s</info>', $repositoryConfig->getSshAlias(), $sshConfig->getPathname()), OutputInterface::VERBOSITY_VERBOSE); } $output->writeln(sprintf('Removed repository <info>%s</info>', $repoName)); $configHelper->getConfiguration()->removeRepositoryConfiguration($repoName); FsUtil::file_put_contents($sshConfig->getPathname(), implode('', $sshConfigLines)); $configHelper->getConfiguration()->write(); return 0; }
/** * @param string $archiveFile * @param string $targetDir * @param OutputInterface $output */ public function extractArchive($archiveFile, $targetDir, OutputInterface $output) { if ($output->getVerbosity() < OutputInterface::VERBOSITY_VERY_VERBOSE) { $output->write(sprintf('Extracting <comment>%s</comment> to <comment>%s</comment>...', $archiveFile, $targetDir)); } $processHelper = $this->getHelperSet()->get('process'); /* @var $processHelper ProcessHelper */ $tempDir = $this->getTempDir($archiveFile); $extractProcess = Util::getExtractProcess($archiveFile); if (!$extractProcess) { throw new \RuntimeException(sprintf('Archive type of %s cannot be handled', $archiveFile)); } $extractProcess->setWorkingDirectory($tempDir); $processHelper->mustRun($output, $extractProcess); $commonPrefix = PathUtil::commonPrefix(Finder::create()->ignoreDotFiles(false)->ignoreVCS(false)->directories()->in($tempDir)); FsUtil::rename($commonPrefix, $targetDir); foreach (Finder::create()->ignoreDotFiles(false)->ignoreVCS(false)->directories()->in($tempDir) as $files) { FsUtil::rmdir($files); } if ($output->getVerbosity() < OutputInterface::VERBOSITY_VERY_VERBOSE) { $output->writeln('<info>OK</info>'); } }
public static function addSshAliasLines(array &$sshConfigLines, $repository, RepositoryConfiguration $repositoryConfig) { $repoParts = Util::parseRepositoryUrl($repository); $newConfigLines = ['Host ' . $repositoryConfig->getSshAlias(), 'HostName ' . $repoParts['host'], 'User ' . $repoParts['user'], 'IdentityFile ' . $repositoryConfig->getIdentityFile()]; $foundAliasLines = self::findSshAliasLines($sshConfigLines, $repositoryConfig->getSshAlias()); if (!$foundAliasLines) { $sshConfigLines = array_merge($sshConfigLines, $newConfigLines); return true; } else { $presentAliasLines = array_map(function ($i) use($sshConfigLines) { return $sshConfigLines[$i]; }, $foundAliasLines); foreach ($newConfigLines as $newConfigLine) { if (!in_array($newConfigLine, $presentAliasLines)) { throw new SshAliasExistsException($repositoryConfig->getSshAlias(), $foundAliasLines[0]); } } return false; } }
private function getRepositoryName(ApplicationConfiguration $applicationConfig) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ $repoName = $applicationConfig->getRepository(); if (!$repoName) { return '<comment>None</comment>'; } if (!Util::isSshRepositoryUrl($repoName)) { return $repoName; } try { $repoConfig = $configHelper->getConfiguration()->getRepositoryConfiguration($repoName); if (is_file($repoConfig->getIdentityFile())) { return $repoName; } } catch (NoSuchRepositoryException $ex) { // no op } return sprintf('<error>%s</error>', $repoName); }
protected function execute(InputInterface $input, OutputInterface $output) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ $processHelper = $this->getHelper('process'); /* @var $processHelper ProcessHelper */ if ($input->getOption('remote') && $input->getOption('archive-url')) { throw new \InvalidArgumentException('The --remote and --archive-url options are mutually exclusive.'); } try { $configHelper->getConfiguration()->getApplication($input->getArgument('application')); throw new ApplicationExistsException($input->getArgument('application')); } catch (NoSuchApplicationException $ex) { // no op } $application = Application::create($configHelper->getConfiguration(), $input->getArgument('application')); if (!$input->getOption('remote') && !$input->getOption('archive-url')) { try { $process = $application->getProcessBuilder(['bash', '-c', 'git remote show origin -n | awk \'/Fetch URL:/{print $3}\''])->getProcess(); $processHelper->mustRun($output, $process); $input->setOption('remote', trim($process->getOutput())); } catch (ProcessFailedException $ex) { $output->writeln(sprintf('<comment>Could not determine repository remote: %s</comment>', $ex->getMessage())); } } if ($input->getOption('remote')) { $repoParts = Util::parseRepositoryUrl($input->getOption('remote')); if (Util::isSshRepositoryUrl($repoParts)) { // If the remote is already mangled to contain an unique ssh alias, put it back in canonical form foreach ($configHelper->getConfiguration()->getRepositoryConfigurations() as $repoName => $repoConf) { /* @var $repoConf RepositoryConfiguration */ if ($repoConf->getSshAlias() === $repoParts['host']) { $repoConfParts = Util::parseRepositoryUrl($repoName); if ($repoConfParts['repository'] === $repoParts['repository']) { $input->setOption('remote', $repoName); } } } } $application->setRepository($input->getOption('remote')); } if ($input->getOption('archive-url')) { $application->setArchiveUrl($input->getOption('archive-url')); } $configHelper->getConfiguration()->write(); if ($application->getArchiveUrl()) { $output->writeln(sprintf('Registered application <info>%s</info> (downloaded from <info>%s</info>)', $input->getArgument('application'), $application->getArchiveUrl())); } elseif (!$application->getRepository()) { $output->writeln(sprintf('Registered application <info>%s</info> (<comment>without repository</comment>)', $input->getArgument('application'))); } else { $output->writeln(sprintf('Registered application <info>%s</info> with repository <info>%s</info>', $input->getArgument('application'), $application->getRepository())); } }
protected function execute(InputInterface $input, OutputInterface $output) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ try { $configHelper->getConfiguration()->getRepositoryConfiguration($input->getArgument('repository')); throw new RepositoryExistsException($input->getArgument('repository')); } catch (NoSuchRepositoryException $ex) { // no op } if (!Util::isSshRepositoryUrl($input->getArgument('repository'))) { throw new NoSshRepositoryException($input->getArgument('repository')); } $repositoryConfig = new RepositoryConfiguration(); $repositoryConfig->setSshAlias($input->getOption('alias') ?: sha1($input->getArgument('repository') . time())); $sshKeyFile = new \SplFileInfo($input->getArgument('key')); if (!$sshKeyFile->isFile()) { throw new NotAFileException($sshKeyFile); } $repositoryConfig->setIdentityFile($sshKeyFile->getRealPath()); $sshConfigFile = new \SplFileInfo($configHelper->getConfiguration()->getSshDirectory() . '/config'); if (!file_exists($sshConfigFile->getPathname())) { FsUtil::touch($sshConfigFile->getPathname()); } if (!$sshConfigFile->isFile()) { throw new NotAFileException($sshConfigFile); } if (!$sshConfigFile->isReadable()) { throw new UnreadableFileException($sshConfigFile); } if (!$sshConfigFile->isWritable()) { throw new UnwritableFileException($sshConfigFile); } $sshConfigLines = file($sshConfigFile); try { if (Util::addSshAliasLines($sshConfigLines, $input->getArgument('repository'), $repositoryConfig)) { FsUtil::file_put_contents($sshConfigFile, implode(PHP_EOL, $sshConfigLines)); $output->writeln(sprintf('Added section <info>%s</info> to <info>%s</info>', 'Host ' . $repositoryConfig->getSshAlias(), $sshConfigFile->getPathname()), OutputInterface::VERBOSITY_VERBOSE); } else { $output->writeln(sprintf('Added section <info>%s</info> already exists in <info>%s</info>', 'Host ' . $repositoryConfig->getSshAlias(), $sshConfigFile->getPathname()), OutputInterface::VERBOSITY_VERBOSE); } } catch (SshAliasExistsException $ex) { throw new SshAliasExistsException($ex->getAliasName(), $ex->getLineNumber(), $sshConfigFile); } $configHelper->getConfiguration()->setRepositoryConfiguration($input->getArgument('repository'), $repositoryConfig); $configHelper->getConfiguration()->write(); $output->writeln(sprintf('Registered private key <info>%s</info> for repository <info>%s</info>', $repositoryConfig->getIdentityFile(), $input->getArgument('repository'))); return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ $processHelper = $this->getHelper('process'); /* @var $processHelper ProcessHelper */ $questionHelper = $this->getHelper('question'); /* @var $questionHelper QuestionHelper */ if (!$input->getArgument('application')) { $input->setArgument('application', basename($input->getArgument('repository'), '.git')); } try { $repositoryConfiguration = $configHelper->getConfiguration()->getRepositoryConfiguration($input->getArgument('repository')); } catch (NoSuchRepositoryException $ex) { $repositoryConfiguration = null; } $repositoryParts = Util::parseRepositoryUrl($input->getArgument('repository')); if (!Util::isSshRepositoryUrl($repositoryParts)) { $input->setOption('no-deploy-key', true); } $application = Application::create($configHelper->getConfiguration(), $input->getArgument('application')); if (!is_dir($application->getPath())) { FsUtil::mkdir($application->getPath(), true); $output->writeln(sprintf('Created directory <info>%s</info>', $application->getPath()), OutputInterface::VERBOSITY_VERY_VERBOSE); } NotEmptyException::assert($application->getPath()); if (!$repositoryConfiguration && !$input->getOption('no-deploy-key')) { $output->writeln('You do not have a deploy key configured for this repository.', OutputInterface::VERBOSITY_VERBOSE); $repositoryConfiguration = new RepositoryConfiguration(); $repositoryConfiguration->setSshAlias(sha1($input->getArgument('repository')) . '-' . basename($input->getArgument('application'))); /* * Generate a new deploy key, link it to the repository and print it. */ $keyFile = $configHelper->getConfiguration()->getSshDirectory() . '/id_rsa-' . $repositoryConfiguration->getSshAlias(); try { $this->getApplication()->find('repository:generate-key')->run(new ArrayInput(['key' => $keyFile, '--comment' => 'clic-deploy-key-' . $repositoryConfiguration->getSshAlias() . '@' . gethostname(), '--target-repository' => $input->getArgument('repository'), '--print-public-key' => true]), $output); $repositoryConfiguration = $configHelper->getConfiguration()->getRepositoryConfiguration($input->getArgument('repository')); } catch (FileExistsException $ex) { $repositoryConfiguration->setIdentityFile($ex->getFilename()); $output->writeln(sprintf('Key <info>%s</info> already exists. Not generating a new one.', $ex->getFilename())); } /* * Ask to add it as a deploy key to the repo */ $output->writeln('<comment>Please set the public key printed above as a deploy key for the repository</comment>'); while (!$questionHelper->ask($input, $output, new ConfirmationQuestion('Is the deploy key uploaded?'))) { } } if ($repositoryConfiguration && !$input->getOption('no-deploy-key')) { /* * If there is a configuration now, save it */ $configHelper->getConfiguration()->setRepositoryConfiguration($input->getArgument('repository'), $repositoryConfiguration); $configHelper->getConfiguration()->write(); } else { $repositoryConfiguration = null; } /* * Run a git clone for the application */ $gitClone = ProcessBuilder::create(['git', 'clone', Util::replaceRepositoryUrl($repositoryParts, $repositoryConfiguration), $application->getPath()])->setTimeout(null)->getProcess(); $processHelper->mustRun($output, $gitClone, null, null, OutputInterface::VERBOSITY_NORMAL, OutputInterface::VERBOSITY_NORMAL); $configHelper->getConfiguration()->removeApplication($application->getName()); // Clean up application again, so application:add further down does not complain. $this->getApplication()->find('application:add')->run(new ArrayInput(['application' => $input->getArgument('application'), '--remote' => $input->getArgument('repository')]), $output); if ($input->getOption('override')) { $input1 = new ArrayInput(['application' => $input->getArgument('application'), 'config-file' => $input->getOption('override')]); if ($input->getOption('override-type')) { $input1->setOption('type', $input->getOption('override-type')); } $this->getApplication()->find('application:override')->run($input1, $output); } if (!$input->getOption('no-scripts')) { /* * Run post-clone script */ return $this->getApplication()->find('application:execute')->run(new ArrayInput(['script' => 'post-clone', 'application' => $input->getArgument('application')]), $output); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ $extractHelper = $this->getHelper('extract'); /* @var $extractHelper ExtractHelper */ $globalConfiguration = $configHelper->getConfiguration(); $application = $globalConfiguration->getApplication($input->getArgument('application')); $configFile = $input->getArgument('config-file'); if ($configFile) { if (!$input->getOption('type')) { // Attempt to detect the type of config-file if none is given if (is_file($input->getArgument('config-file'))) { $input->setOption('type', 'file'); } else { try { $repoParts = Util::parseRepositoryUrl($input->getArgument('config-file')); if (in_array($repoParts['protocol'], ['git', 'ssh', 'rsync'])) { $input->setOption('type', 'git'); } } catch (\InvalidArgumentException $ex) { $input->setOption('type', 'http'); } } } switch ($input->getOption('type') ?: 'git') { case 'git': try { $configFile = $this->downloadGit($output, $configFile); } catch (ProcessFailedException $ex) { if ($input->getOption('type')) { throw $ex; } $errorOutput = $ex->getProcess()->getErrorOutput(); if (preg_match('/fatal: repository .*not found/i', $errorOutput)) { // "No such repository" when trying to clone a normal http url. Try downloading the file $configFile = $extractHelper->downloadFile($configFile, $output); } else { throw $ex; } } break; case 'http': $configFile = $extractHelper->downloadFile($configFile, $output); break; case 'file': break; default: throw new \InvalidArgumentException('--type must be one of git, http, file'); } $configFile = $this->extractFile($output, $configFile); $configFile = new \SplFileInfo($configFile); if (!$configFile->isFile()) { throw new NotAFileException($configFile); } if (!$configFile->isReadable()) { throw new UnreadableFileException($configFile); } $configFile = $configFile->getRealPath(); } $application->setConfigurationFileOverride($configFile); $globalConfiguration->write(); $output->writeln(sprintf('Registered <comment>%s</comment> as override file for <info>%s</info>', $configFile, $application->getName())); }
protected function initialize(InputInterface $input, OutputInterface $output) { if ($input->getOption('target-repository')) { $configHelper = $this->getHelper('configuration'); /* @var $configHelper GlobalConfigurationHelper */ try { $configHelper->getConfiguration()->getRepositoryConfiguration($input->getOption('target-repository')); throw new RepositoryExistsException($input->getOption('target-repository')); } catch (NoSuchRepositoryException $ex) { // no op } if (!Util::isSshRepositoryUrl($input->getOption('target-repository'))) { throw new NoSshRepositoryException($input->getOption('target-repository')); } } }