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')); }
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')); }
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])); }
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()); }
/** * @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); } }
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; }
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); } }
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; } }
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; }
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."); } } }