Skip to content

Commit

Permalink
Add new options to pull-request:merge command
Browse files Browse the repository at this point in the history
  • Loading branch information
phansys committed Aug 29, 2016
1 parent f7054ea commit 01e29b1
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 9 deletions.
14 changes: 14 additions & 0 deletions src/Command/PullRequest/PullRequestMergeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ protected function configure()
->addOption('fast-forward', null, InputOption::VALUE_NONE, 'Merge pull-request using fast forward (no merge commit will be created)')
->addOption('squash', null, InputOption::VALUE_NONE, 'Squash the PR before merging')
->addOption('force-squash', null, InputOption::VALUE_NONE, 'Force squashing the PR, even if there are multiple authors (this will implicitly use --squash)')
->addOption('rebase', null, InputOption::VALUE_NONE, 'Rebase the PR before merging')
->addOption('ensure-sync', null, InputOption::VALUE_NONE, 'Ensure that the pull request history is up to date before merging')
->addOption('switch', null, InputOption::VALUE_REQUIRED, 'Switch the base of the pull request before merging')
->addOption('pat', null, InputOption::VALUE_REQUIRED, 'Give the PR\'s author a pat on the back after the merge')
->setHelp(
Expand Down Expand Up @@ -79,6 +81,16 @@ protected function configure()
<info>$ gush %command.name% --fast-forward 12</info>
If you want to perform an automatic rebase against the base branch before merging, the <comment>--rebase</comment> option can be used
in order to try that operation:
<info>$ gush %command.name% --rebase 12</info>
A synchronization check against the base branch can be done before the merge, passing the <comment>--ensure-sync</comment> option; so
if this check fails, the operation will be aborted:
<info>$ gush %command.name% --ensure-sync 12</info>
After the pull request is merged, you can give a pat on the back to its author using the <comment>--pat</comment>.
This option accepts the name of any configured pat's name:
Expand Down Expand Up @@ -173,6 +185,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
$mergeOperation->setTarget($targetRemote, $targetBranch);
$mergeOperation->setSource($sourceRemote, $sourceBranch);
$mergeOperation->squashCommits($squash, $input->getOption('force-squash'));
$mergeOperation->guardSync($input->getOption('ensure-sync'));
$mergeOperation->rebase($input->getOption('rebase'));
$mergeOperation->switchBase($input->getOption('switch'));
$mergeOperation->setMergeMessage($messageCallback);
$mergeOperation->useFastForward($input->getOption('fast-forward'));
Expand Down
7 changes: 0 additions & 7 deletions src/Helper/GitHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -615,13 +615,6 @@ public function squashCommits($base, $branchName, $ignoreMultipleAuthors = false
$base.'..'.$branchName,
]))[0];

$currentBaseHeadCommit = $this->processHelper->runCommand(['git', 'rev-parse', $base]);
$lastKnownCommonCommit = $this->processHelper->runCommand(['git', 'merge-base', '--fork-point', $base, $branchName]);

if ($currentBaseHeadCommit !== $lastKnownCommonCommit) {
throw new MergeWorkflowException(sprintf('Failed while trying to perform merge against "%s", history is out of sync.', $base));
}

// 0=author anything higher then 0 is the full body
$commitData = StringUtil::splitLines(
$this->processHelper->runCommand(
Expand Down
45 changes: 44 additions & 1 deletion src/Operation/RemoteMergeOperation.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class RemoteMergeOperation
private $performed = false;
private $fastForward = false;
private $withLog = false;
private $rebase = false;
private $guardSync = false;

public function __construct(GitHelper $gitHelper, FilesystemHelper $filesystemHelper)
{
Expand Down Expand Up @@ -80,6 +82,8 @@ public function setMergeMessage($message, $withLog = false)
public function useFastForward($fastForward = true)
{
$this->fastForward = (bool) $fastForward;

return $this;
}

public function performMerge()
Expand Down Expand Up @@ -143,6 +147,21 @@ public function pushToRemote()
$this->gitHelper->pushToRemote($this->targetRemote, $target);
}

public function rebase(bool $rebase = false)
{
$this->rebase = $rebase;
$this->guardSync = !$rebase;

return $this;
}

public function guardSync(bool $guardSync = false)
{
$this->guardSync = $guardSync;

return $this;
}

private function createBaseBranch()
{
$targetBranch = null !== $this->switchBase ? $this->switchBase : $this->targetBranch;
Expand Down Expand Up @@ -171,7 +190,31 @@ private function createSourceBranch()
}

if ($this->squash) {
$this->gitHelper->squashCommits($this->targetBase, $sourceBranch, $this->forceSquash);
$this->gitHelper->squashCommits($this->targetBase, $sourceBranch, $this->forceSquash, $this->guardSync);
}

$currentBaseHeadCommit = $this->processHelper->runCommand(['git', 'rev-parse', $this->targetBase]);
$lastKnownCommonCommit = $this->processHelper->runCommand(['git', 'merge-base', '--fork-point', $this->targetBase, $sourceBranch]);

if ($currentBaseHeadCommit !== $lastKnownCommonCommit) {
if ($this->rebase) {
try {
$this->processHelper->runCommand(['git', 'pull', '--rebase', $this->targetBase]);
} catch (\Exception $e) {
// Error, abort the rebase operation
$this->processHelper->runCommand(['git', 'rebase', '--abort'], true);

throw new MergeWorkflowException(sprintf('Git rebase failed while trying to synchronize history against "%s".', $this->targetBase), 0, $e);
}

// Retrieve the commits again
$currentBaseHeadCommit = $this->processHelper->runCommand(['git', 'rev-parse', $this->targetBase]);
$lastKnownCommonCommit = $this->processHelper->runCommand(['git', 'merge-base', '--fork-point', $this->targetBase, $sourceBranch]);
}

if ($this->guardSync && $currentBaseHeadCommit !== $lastKnownCommonCommit) {
throw new MergeWorkflowException(sprintf('Failed while trying to perform merge against "%s", history is out of sync.', $this->targetBase));
}
}

// Allow a callback to allow late commits list composition
Expand Down
4 changes: 3 additions & 1 deletion tests/Command/PullRequest/PullRequestMergeCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ protected function getGitConfigHelper($notes = true)
return $helper;
}

private function getLocalGitHelper($message = null, $squash = false, $forceSquash = false, $switch = null, $withComments = true, $fastForward = false)
private function getLocalGitHelper($message = null, $squash = false, $forceSquash = false, $switch = null, $withComments = true, $fastForward = false, $guardSync = false, $rebase = false)
{
$helper = parent::getGitHelper();

Expand All @@ -470,6 +470,8 @@ private function getLocalGitHelper($message = null, $squash = false, $forceSquas
$mergeOperation->setTarget('gushphp', 'base_ref')->shouldBeCalled();
$mergeOperation->setSource('cordoval', 'head_ref')->shouldBeCalled();
$mergeOperation->squashCommits($squash, $forceSquash)->shouldBeCalled();
$mergeOperation->guardSync($guardSync)->shouldBeCalled();
$mergeOperation->rebase($rebase)->shouldBeCalled();
$mergeOperation->switchBase($switch)->shouldBeCalled();
$mergeOperation->useFastForward($fastForward)->shouldBeCalled();
$mergeOperation->setMergeMessage(
Expand Down

0 comments on commit 01e29b1

Please sign in to comment.