Ejemplo n.º 1
0
 public function createExampleRepo($dir)
 {
     $this->createExampleFile("{$dir}/example.txt");
     ProcessUtil::runOk($this->command($dir, "git init"));
     ProcessUtil::runOk($this->command($dir, "git add example.txt"));
     ProcessUtil::runOk($this->command($dir, "git commit -m Import example.txt"));
 }
Ejemplo n.º 2
0
 public function testRunOk_fail()
 {
     try {
         ProcessUtil::runOk(new \Symfony\Component\Process\Process("echo tragedy befell the software > /dev/stderr; exit 1"));
         $this->fail("Failed to generate expected exception");
     } catch (\GitScan\Exception\ProcessErrorException $e) {
         $this->assertEquals("tragedy befell the software", trim($e->getProcess()->getErrorOutput()));
     }
 }
Ejemplo n.º 3
0
 /**
  * @param string $checkout the treeish to checkout
  * @return GitRepo the upstream repo has:
  *  - a master branch
  *  - a new (unmerged) feature branch (1.x-master)
  *  - a tag of after the merge of 1.x-master-1 (0.2)
  */
 protected function createUpstreamRepo($checkout = 'master')
 {
     $gitRepo = new GitRepo($this->fixturePath . '/upstream');
     if (!$gitRepo->init()) {
         throw new \RuntimeException("Error: Repo already exists!");
     }
     $gitRepo->commitFile("example.txt", "example text");
     ProcessUtil::runOk($gitRepo->command("git tag 0.1"));
     $gitRepo->commitFile("changelog.txt", "new in v0.2: don't know yet!");
     ProcessUtil::runOk($gitRepo->command("git checkout -b 1.x-master"));
     $gitRepo->commitFile("example.txt", "example text plus my feature");
     // Validate
     ProcessUtil::runOk($gitRepo->command("git checkout master"));
     $this->assertEquals("example text", $gitRepo->readFile("example.txt"));
     ProcessUtil::runOk($gitRepo->command("git checkout 1.x-master"));
     $this->assertEquals("example text plus my feature", $gitRepo->readFile("example.txt"));
     // Wrap up
     ProcessUtil::runOk($gitRepo->command("git checkout {$checkout}"));
     return $gitRepo;
 }
Ejemplo n.º 4
0
 public function testDiff_multiCase_json()
 {
     $this->createExampleRepo($this->fixturePath . '/orig/foo/repo-change-me');
     $this->createExampleRepo($this->fixturePath . '/orig/bar/repo-keep-me');
     $this->createExampleRepo($this->fixturePath . '/orig/whiz/repo-delete-me');
     ProcessUtil::runOk($this->command($this->fixturePath, "cp -r orig changed"));
     ProcessUtil::runOk($this->command($this->fixturePath, "rm -rf changed/whiz/repo-delete-me"));
     $this->createExampleRepo($this->fixturePath . '/changed/bang/repo-add-me');
     $changeMe = new GitRepo($this->fixturePath . '/changed/foo/repo-change-me');
     ProcessUtil::runOk($changeMe->command("git checkout -b feature-branch"));
     $changeMe->commitFile("new-stuff.txt", "This is a change to the repo!");
     $commandTester = $this->createCommandTester(array('command' => 'diff', 'from' => "{$this->fixturePath}/orig", 'to' => "{$this->fixturePath}/changed", '--format' => 'json'));
     $json = $commandTester->getDisplay(FALSE);
     $actualDoc = json_decode($json, TRUE);
     $expectRegexp = array(array('path' => ':^bang/repo-add-me$:', 'status' => '/^\\+$/', 'from' => '/^$/', 'to' => '/^master \\([0-9a-f]+\\)$/', 'changes' => '/^\\(Added repository\\)$/'), array('path' => ':^bar/repo-keep-me$:', 'status' => '/^ $/', 'from' => '/^master \\([0-9a-f]+\\)$/', 'to' => '/^master \\([0-9a-f]+\\)$/', 'changes' => '/^$/'), array('path' => ':^foo/repo-change-me$:', 'status' => '/^M$/', 'from' => '/^master \\([0-9a-f]+\\)$/', 'to' => '/^feature-branch \\([0-9a-f]+\\)$/', 'changes' => '/^1 \\[.*\\]$/'), array('path' => ':^whiz/repo-delete-me$:', 'status' => '/^-$/', 'from' => '/^master \\([0-9a-f]+\\)$/', 'to' => '/^$/', 'changes' => '/^\\(Removed repository\\)$/'));
     $this->assertEquals(count($actualDoc), count($expectRegexp), "Unexpected number of rows: " . print_r($actualDoc, TRUE));
     foreach ($expectRegexp as $offset => $expectRow) {
         foreach ($expectRow as $key => $pattern) {
             $this->assertRegExp($pattern, $actualDoc[$offset][$key]);
         }
     }
 }
Ejemplo n.º 5
0
 public function testTag_delete()
 {
     Process::runOk($this->repo1b->command("git branch -m master 1.x-master"));
     Process::runOk($this->repo1b->command("git tag 1.x-1.0 1.x-master"));
     $commandTester = $this->createCommandTester(array('command' => 'tag', '--path' => $this->fixturePath, '--delete' => 1, '--prefix' => 1, '--dry-run' => 1, 'tagName' => '1.0'));
     $output = $commandTester->getDisplay(FALSE);
     $this->assertEquals(0, $commandTester->getStatusCode());
     $this->assertContains('In "example-1/repo-1/repo-1b/", delete tag "1.x-1.0"', $output);
     $this->assertContains("repo-1b'\n\$ git tag -d '1.x-1.0'", $output);
 }
Ejemplo n.º 6
0
 public function testBranch_forceDelete()
 {
     Process::runOk($this->repo1b->command("git branch -m master 1.x-master"));
     $commandTester = $this->createCommandTester(array('command' => 'branch', '--path' => $this->fixturePath, '--force-delete' => 1, '--prefix' => 1, '--dry-run' => 1, 'branchName' => 'master'));
     $output = $commandTester->getDisplay(FALSE);
     $this->assertEquals(0, $commandTester->getStatusCode());
     $this->assertContains('In "example-1/repo-1/repo-1b/", delete branch "1.x-master"', $output);
     $this->assertContains("repo-1b'\n\$ git branch -D '1.x-master'", $output);
 }
Ejemplo n.º 7
0
 /**
  * Ensure that we've checked out a branch where we can do merges.
  *
  * @param \GitScan\GitRepo $gitRepo
  */
 protected function checkoutAutomergeBranch(InputInterface $input, OutputInterface $output, GitRepo $gitRepo, $repoName)
 {
     if ($gitRepo->hasUncommittedChanges(TRUE)) {
         throw new \RuntimeException("Cannot apply patch");
     }
     $localBranch = $gitRepo->getLocalBranch();
     $upstreamBranch = $gitRepo->getUpstreamBranch();
     $newLocalBranch = "merge-{$localBranch}-" . date('YmdHis');
     $mode = $this->getAutomergeMode($input, $output, $repoName, $localBranch, $upstreamBranch, $newLocalBranch);
     switch ($mode) {
         case 'keep':
             $output->writeln("In \"<info>{$repoName}</info>\", keep the current branch \"<info>{$localBranch}</info>\".");
             return;
         case 'rebuild':
             $backupBranch = 'backup-' . $localBranch . '-' . date('YmdHis') . '-' . rand(0, 100);
             $output->writeln("In \"<info>{$repoName}</info>\", rename \"<info>{$localBranch}</info>\" to \"<info>{$backupBranch}</info>\".");
             Process::runOk($gitRepo->command("git branch -m {$localBranch} {$backupBranch}"));
             $output->writeln("In \"<info>{$repoName}</info>\", create \"<info>{$localBranch}</info>\" using \"<info>{$upstreamBranch}</info>\".");
             Process::runOk($gitRepo->command("git checkout {$upstreamBranch} -b {$localBranch}"));
             return;
         case 'new':
             $output->writeln("In \"<info>{$repoName}</info>\", create \"<info>{$newLocalBranch}</info>\" using \"<info>{$upstreamBranch}</info>\".");
             Process::runOk($gitRepo->command("git checkout {$upstreamBranch} -b {$newLocalBranch}"));
             return;
         case 'abort':
             // Pass through...
         // Pass through...
         default:
             throw new \RuntimeException("Could not decide how to base local branch.");
     }
 }
Ejemplo n.º 8
0
 /**
  * @param \GitScan\GitRepo $gitRepo
  * @param $name
  * @return string
  *   Path to the patch file.
  */
 protected function createPatchFile(GitRepo $gitRepo, $name)
 {
     $file = $this->fixturePath . '/' . $name . '.patch';
     ProcessUtil::runOk($gitRepo->command("git checkout master -b tmp"));
     $gitRepo->commitFile("changelog.txt", "new in v0.3: the future has been patched!");
     ProcessUtil::runOk($gitRepo->command("git format-patch --stdout HEAD~1 > {$file}"));
     ProcessUtil::runOk($gitRepo->command("git checkout master"));
     return $file;
 }
Ejemplo n.º 9
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.");
         }
     }
 }
Ejemplo n.º 10
0
 /**
  * @param string $relPath
  * @param string $content
  * @param string|null $commitMessage
  */
 public function commitFile($relPath, $content, $commitMessage = NULL)
 {
     if ($commitMessage === NULL) {
         $commitMessage = "Update {$relPath}";
     }
     $this->writeFile($relPath, $content);
     ProcessUtil::runOk($this->command("git add " . escapeshellarg($relPath)));
     ProcessUtil::runOk($this->command("git commit " . escapeshellarg($relPath) . ' -m ' . escapeshellarg($commitMessage)));
 }