From f5c843018899d58d45ddd5225711a495916153b5 Mon Sep 17 00:00:00 2001 From: durham Date: Fri, 12 Apr 2013 14:11:51 -0700 Subject: [PATCH] Change hg arc diff to detect up to the nearest parent with a diff Summary: 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: https://secure.phabricator.com/D5639 --- src/parser/ArcanistBaseCommitParser.php | 2 ++ src/repository/api/ArcanistMercurialAPI.php | 30 ++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/parser/ArcanistBaseCommitParser.php b/src/parser/ArcanistBaseCommitParser.php index 24cf6c73..3081e7ed 100644 --- a/src/parser/ArcanistBaseCommitParser.php +++ b/src/parser/ArcanistBaseCommitParser.php @@ -165,6 +165,8 @@ final class ArcanistBaseCommitParser { } else { return null; } + } else if (preg_match('/^nodiff\((.*)\)$/', $name, $matches)) { + return $this->api->resolveBaseCommitRule($rule, $source); } throw new ArcanistUsageException( diff --git a/src/repository/api/ArcanistMercurialAPI.php b/src/repository/api/ArcanistMercurialAPI.php index 001eeeba..7b9d78ab 100644 --- a/src/repository/api/ArcanistMercurialAPI.php +++ b/src/repository/api/ArcanistMercurialAPI.php @@ -832,7 +832,35 @@ final class ArcanistMercurialAPI extends ArcanistRepositoryAPI { "you specified '{$rule}' in your {$source} 'base' ". "configuration."); 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; + } break; default: return null;