Example #1
0
 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));
         }
     }
 }
Example #2
0
 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();
 }
Example #3
0
 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;
 }
Example #4
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>');
     }
 }
Example #5
0
 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;
     }
 }
Example #6
0
 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);
 }
Example #7
0
 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()));
     }
 }
Example #8
0
 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;
 }
Example #9
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;
 }
Example #10
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()));
 }
Example #11
0
 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'));
         }
     }
 }