Browse files

Change hg arc diff to detect up to the nearest parent with a diff

Changes arc diff to choose the base commit as the first ancestor
that has a diff.  So if your tree looks like master->A->B->C->D, if you
have a diff on B (which will include A), when you run arc diff on D it will
only include C and D.

This makes the scenario for stacked diffs nicer.  A user can commit A, commit B,
arc diff, commit C, commit D, arc diff, arc land B, arc land D.

Test Plan:
Commit A on top of master
Commit B on top of A
arc diff
Commit C on top of B
Commit D on top of C
arc diff

Verify the second diff contains the changes in C and D, but not A and B.

hg up B
arc land --preview
Verify that arc land shows A and B

hg up D
arc land --preview
Verify that arc land shows A, B, C, and D
(arc land should be unaffected by this change.
It always tries to land the entire branch)

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin

Differential Revision:
  • Loading branch information...
1 parent b1fe436 commit f5c843018899d58d45ddd5225711a495916153b5 @DurhamG DurhamG committed Apr 12, 2013
Showing with 31 additions and 1 deletion.
  1. +2 −0 src/parser/ArcanistBaseCommitParser.php
  2. +29 −1 src/repository/api/ArcanistMercurialAPI.php
@@ -165,6 +165,8 @@ private function resolveArcRule($rule, $name, $source) {
} else {
return null;
+ } else if (preg_match('/^nodiff\((.*)\)$/', $name, $matches)) {
+ return $this->api->resolveBaseCommitRule($rule, $source);
throw new ArcanistUsageException(
@@ -832,7 +832,35 @@ public function resolveBaseCommitRule($rule, $source) {
"you specified '{$rule}' in your {$source} 'base' ".
return $this->getCanonicalRevisionName('.^');
- }
+ default:
+ if (preg_match('/^nodiff\((.+)\)$/', $name, $matches)) {
+ list($results) = $this->execxLocal(
+ 'log --template %s --rev %s',
+ '{node}\1{desc}\2',
+ sprintf('ancestor(.,%s)::.^', $matches[1]));
+ $results = array_reverse(explode("\2", trim($results)));
+ foreach ($results as $result) {
+ if (empty($result)) {
+ continue;
+ }
+ list($node, $desc) = explode("\1", $result, 2);
+ $message = ArcanistDifferentialCommitMessage::newFromRawCorpus(
+ $desc);
+ if ($message->getRevisionID()) {
+ $this->setBaseCommitExplanation(
+ "it is the first ancestor of . that has a diff ".
+ "and is the gca or a descendant of the gca with ".
+ "'{$matches[1]}', specified by '{$rule}' in your ".
+ "{$source} 'base' configuration.");
+ return $node;
+ }
+ }
+ }
+ break;
+ }
return null;

0 comments on commit f5c8430

Please sign in to comment.