Exemple #1
0
 protected function executeDelete(InputInterface $input, OutputInterface $output)
 {
     $scanner = new \GitScan\GitRepoScanner();
     $gitRepos = $scanner->scan($input->getOption('path'));
     $batch = new ProcessBatch('Deleting branch(es)...');
     $tagName = $input->getArgument('tagName');
     $tagQuoted = preg_quote($tagName, '/');
     foreach ($gitRepos as $gitRepo) {
         /** @var \GitScan\GitRepo $gitRepo */
         $relPath = $this->fs->makePathRelative($gitRepo->getPath(), $input->getOption('path'));
         $tags = $gitRepo->getTags();
         $matches = array();
         if ($input->getOption('prefix')) {
             $matches = preg_grep("/[-_]{$tagQuoted}\$/", $tags);
         }
         if (in_array($tagName, $tags)) {
             $matches[] = $tagName;
         }
         // TODO: Verify that user wants to delete these.
         foreach ($matches as $match) {
             $label = "In \"<info>{$relPath}</info>\", delete tag \"<info>{$match}</info>\" .";
             $batch->add($label, $gitRepo->command("git tag -d " . escapeshellarg($match)));
         }
     }
     $batch->runAllOk($output, $input->getOption('dry-run'));
 }
Exemple #2
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $scanner = new \GitScan\GitRepoScanner();
     $gitRepos = $scanner->scan($input->getOption('path'));
     $remote = $input->getArgument('remote');
     $batch = new ProcessBatch('Pushing...');
     $branchQuoted = preg_quote($input->getArgument('refspec'), '/');
     $branchRegex = $input->getOption('prefix') ? "/^((.+[-_])|){$branchQuoted}\$/" : "/^{$branchQuoted}\$/";
     foreach ($gitRepos as $gitRepo) {
         /** @var \GitScan\GitRepo $gitRepo */
         $relPath = $this->fs->makePathRelative($gitRepo->getPath(), $input->getOption('path'));
         $remotes = $gitRepo->getRemotes();
         if (!in_array($remote, $remotes)) {
             $output->writeln("<error>Repo \"<info>{$relPath}</info>\" does not have remote \"<info>{$remote}</info>\"</error>");
             return 1;
         }
         $names = array_merge($gitRepo->getBranches(), $gitRepo->getTags());
         $matchedNames = preg_grep($branchRegex, $names);
         // TODO: Interactively confirm/filter.
         foreach ($matchedNames as $name) {
             $batch->add("In \"<info>{$relPath}</info>\", push \"<info>{$name}</info>\" to \"<info>{$remote}</info>\"", $gitRepo->command(sprintf("git push %s %s", escapeshellarg($remote), escapeshellarg($name))));
         }
     }
     $batch->runAllOk($output, $input->getOption('dry-run'));
 }
Exemple #3
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $scanner = new \GitScan\GitRepoScanner();
     $paths = $input->getArgument('path');
     if (count($paths) != 1) {
         $output->writeln('<error>Expected only one root path</error>');
         return;
     }
     $output->writeln($scanner->hash($paths[0]));
 }
Exemple #4
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $scanner = new \GitScan\GitRepoScanner();
     $paths = $input->getArgument('path');
     if (count($paths) != 1) {
         $output->writeln('<error>Expected only one root path</error>');
         return;
     }
     $gitRepos = $scanner->scan($paths);
     $output->writeln(\GitScan\CheckoutDocument::create($paths[0])->importRepos($gitRepos)->toJson());
 }
Exemple #5
0
 /**
  * @param string $path path to a directory or JSON file
  * @return CheckoutDocument
  */
 protected function getCheckoutDocument($path)
 {
     if (is_dir($path)) {
         $scanner = new \GitScan\GitRepoScanner();
         $gitRepos = $scanner->scan($path);
         return CheckoutDocument::create($path)->importRepos($gitRepos);
     } else {
         $json = file_get_contents($path);
         return CheckoutDocument::create(NULL)->importJson($json);
     }
 }
Exemple #6
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     if (!$input->getOption('command')) {
         $output->writeln("<error>Missing required option: --command</error>");
         return 1;
     }
     $statusCode = 0;
     if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
         $output->writeln("<info>[[ Finding repositories ]]</info>");
     }
     $scanner = new \GitScan\GitRepoScanner();
     $gitRepos = $scanner->scan($input->getArgument('path'));
     foreach ($gitRepos as $gitRepo) {
         /** @var \GitScan\GitRepo $gitRepo */
         if (!$gitRepo->matchesStatus($input->getOption('status'))) {
             continue;
         }
         $topLevel = $this->fs->findFirstParent($gitRepo->getPath(), $input->getArgument('path'));
         if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
             $output->writeln("<info>[[ {$gitRepo->getPath()} ]]</info>");
         }
         $process = new \Symfony\Component\Process\Process($input->getOption('command'));
         $process->setWorkingDirectory($gitRepo->getPath());
         // $process->setEnv(...); sucks in Debian/Ubuntu
         putenv("path=" . $this->fs->makePathRelative($gitRepo->getPath(), $topLevel));
         putenv("toplevel=" . $topLevel);
         $errorOutput = $output;
         if (is_callable($output, 'getErrorOutput') && $output->getErrorOutput()) {
             $errorOutput = $output->getErrorOutput();
         }
         $process->run(function ($type, $buffer) use($output, $errorOutput) {
             if (\Symfony\Component\Process\Process::ERR === $type) {
                 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                     $errorOutput->write("<error>STDERR</error> ");
                 }
                 $errorOutput->write($buffer, FALSE, OutputInterface::OUTPUT_RAW);
             } else {
                 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                     $output->write("<comment>STDOUT</comment> ");
                 }
                 $output->write($buffer, FALSE, OutputInterface::OUTPUT_RAW);
             }
         });
         if (!$process->isSuccessful()) {
             $errorOutput->writeln("<error>[[ {$gitRepo->getPath()}: exit code = {$process->getExitCode()} ]]</error>");
             $statusCode = 2;
         }
     }
     putenv("path");
     putenv("toplevel");
     return $statusCode;
 }
Exemple #7
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $scanner = new \GitScan\GitRepoScanner();
     $paths = $input->getArgument('path');
     if (count($paths) != 1) {
         $output->writeln('<error>Expected only one root path</error>');
         return;
     }
     $gitRepos = $scanner->scan($paths);
     foreach ($gitRepos as $gitRepo) {
         /** @var GitRepo $gitRepo */
         $path = $input->getOption('absolute') ? $gitRepo->getPath() : $this->fs->makePathRelative($gitRepo->getPath(), $paths[0]);
         $path = rtrim($path, '/');
         $output->writeln($path);
     }
 }
Exemple #8
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $rules = array();
     foreach ($this->getPatchExprs($input, $output) as $expr) {
         $rule = new AutoMergeRule($expr);
         $rules[] = $rule;
     }
     $scanner = new \GitScan\GitRepoScanner();
     $gitRepos = $scanner->scan($input->getOption('path'));
     $checkouts = array();
     // array(string $absDir => TRUE)
     foreach ($gitRepos as $gitRepo) {
         /** @var GitRepo $gitRepo */
         $relPath = $this->fs->makePathRelative($gitRepo->getPath(), $input->getOption('path'));
         $hasPatch = 0;
         foreach (array_keys($rules) as $ruleId) {
             /** @var AutoMergeRule $rule */
             $rule = $rules[$ruleId];
             $rule->fetch();
             if ($rule->isMatch($gitRepo)) {
                 unset($rules[$ruleId]);
                 $hasPatch = 1;
                 if (!isset($checkouts[$gitRepo->getPath()])) {
                     $this->checkoutAutomergeBranch($input, $output, $gitRepo, $relPath);
                     $checkouts[$gitRepo->getPath()] = 1;
                 }
                 $output->writeln("In \"<info>{$relPath}</info>\", apply \"<info>{$rule->getExpr()}</info>\" on top of \"<info>{$gitRepo->getCommit()}</info>\".");
                 $process = $gitRepo->applyPatch($rule->getPatch(), $input->getOption('passthru'));
                 $output->writeln($process->getOutput());
             }
         }
         if ($hasPatch) {
             $output->writeln("In \"<info>{$relPath}</info>\", final commit is \"<info>{$gitRepo->getCommit()}</info>\".");
         }
     }
     foreach ($rules as $ruleId => $rule) {
         $output->writeln("<error>Failed to match {$rule->getExpr()} to a local repo. Ensure that one of the repos has the proper remote URL.</error>");
     }
     if (!empty($rules)) {
         return 1;
     }
 }
Exemple #9
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $statusCode = 0;
     $output->writeln("<info>[[ Finding repositories ]]</info>");
     $scanner = new \GitScan\GitRepoScanner();
     $gitRepos = $scanner->scan($input->getArgument('path'));
     $output->writeln("<info>[[ Fast-forwarding ]]</info>");
     foreach ($gitRepos as $gitRepo) {
         /** @var \GitScan\GitRepo $gitRepo */
         $path = $this->fs->formatPrettyPath($gitRepo->getPath(), $input->getArgument('path'));
         if ($gitRepo->getUpstreamBranch() === NULL) {
             $output->writeln("<comment>Skip {$path}: No upstream tracking branch</comment>");
         } elseif (!$gitRepo->isLocalFastForwardable()) {
             $output->writeln("<comment>Skip {$path}: Cannot be fast-forwarded</comment>");
         } else {
             $output->writeln("<comment>Fast-forward {$path} ({$gitRepo->getLocalBranch()} <= {$gitRepo->getUpstreamBranch()})...</comment>");
             $process = $gitRepo->command('git pull --ff-only');
             $process->run();
             if (!$process->isSuccessful()) {
                 $output->writeln("<error>Failed to update {$gitRepo->getPath()}/<error>");
                 if ($process->getOutput()) {
                     $output->writeln("//---------- BEGIN STDOUT ----------\\\\");
                     $output->writeln($process->getOutput(), OutputInterface::OUTPUT_RAW);
                     $output->writeln("\\\\----------- END STDOUT -----------//");
                 }
                 if ($process->getErrorOutput()) {
                     $output->writeln("//---------- BEGIN STDERR ----------\\\\");
                     $output->writeln($process->getErrorOutput(), OutputInterface::OUTPUT_RAW);
                     $output->writeln("\\\\----------- END STDERR -----------//");
                 }
                 $statusCode = 1;
             }
         }
     }
     return $statusCode;
 }
Exemple #10
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $output->writeln("<info>[[ Finding repositories ]]</info>");
     $scanner = new \GitScan\GitRepoScanner();
     $gitRepos = $scanner->scan($input->getArgument('path'));
     if ($input->getOption('status') == 'auto') {
         $input->setOption('status', count($gitRepos) > self::DISPLAY_ALL_THRESHOLD ? 'novel' : 'all');
     }
     $output->writeln($input->getOption('fetch') ? "<info>[[ Fetching statuses ]]</info>" : "<info>[[ Checking statuses ]]</info>");
     /** @var \Symfony\Component\Console\Helper\ProgressHelper $progress */
     $progress = $this->getApplication()->getHelperSet()->get('progress');
     $progress->start($output, 1 + count($gitRepos));
     $progress->advance();
     $rows = array();
     $hiddenCount = 0;
     foreach ($gitRepos as $gitRepo) {
         /** @var \GitScan\GitRepo $gitRepo */
         if ($input->getOption('fetch') && $gitRepo->getUpstreamBranch() !== NULL) {
             ProcessUtil::runOk($gitRepo->command('git fetch'));
         }
         if ($gitRepo->matchesStatus($input->getOption('status'))) {
             $rows[] = array($gitRepo->getStatusCode(), $this->fs->formatPrettyPath($gitRepo->getPath(), $input->getArgument('path')), $gitRepo->getLocalBranch(), $gitRepo->getUpstreamBranch());
         } else {
             $hiddenCount++;
         }
         $progress->advance();
     }
     $progress->finish();
     $output->writeln("<info>[[ Results ]]</info>\n");
     if (!empty($rows)) {
         $table = $this->getApplication()->getHelperSet()->get('table');
         $table->setHeaders(array('Status', 'Path', 'Local Branch', 'Remote Branch'))->setRows($rows);
         $table->render($output);
         $chars = $this->getUniqueChars(ArrayUtil::collect($rows, 0));
         foreach ($chars as $char) {
             switch ($char) {
                 case ' ':
                     break;
                 case 'M':
                     $output->writeln("[M] Modifications have not been committed");
                     break;
                 case 'N':
                     $output->writeln("[N] New files have not been committed");
                     break;
                 case 'F':
                     $output->writeln("[F] Fast-forwards are not possible");
                     break;
                 case 'B':
                     $output->writeln("[B] Branch names are suspiciously different");
                     break;
                 case 'S':
                     $output->writeln("[S] Stash contains data");
                     break;
                 default:
                     throw new \RuntimeException("Unrecognized status code [{$char}]");
             }
         }
     } else {
         $output->writeln("No repositories to display.");
     }
     if ($hiddenCount > 0) {
         switch ($input->getOption('status')) {
             case 'novel':
                 $output->writeln("NOTE: Omitted information about {$hiddenCount} boring repo(s). To display all, use --status=all.");
                 break;
             case 'boring':
                 $output->writeln("NOTE: Omitted information about {$hiddenCount} novel repo(s). To display all, use --status=all.");
                 break;
             default:
                 $output->writeln("NOTE: Omitted information about {$hiddenCount} repo(s). To display all, use --status=all.");
         }
     }
 }