Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15505022
D9369.id22423.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
D9369.id22423.diff
View Options
diff --git a/src/repository/api/ArcanistGitAPI.php b/src/repository/api/ArcanistGitAPI.php
--- a/src/repository/api/ArcanistGitAPI.php
+++ b/src/repository/api/ArcanistGitAPI.php
@@ -16,6 +16,9 @@
*/
const GIT_MAGIC_ROOT_COMMIT = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
+ private $symbolicHeadCommit = 'HEAD';
+ private $resolvedHeadCommit;
+
public static function newHookAPI($root) {
return new ArcanistGitAPI($root);
}
@@ -75,6 +78,20 @@
return !$this->repositoryHasNoCommits;
}
+ /**
+ * Tests if a child commit is descendant of a parent commit.
+ * @param child commit SHA.
+ * @param parent commit SHA.
+ * @return bool
+ */
+ public function isDescendant($child, $parent) {
+ list($common_ancestor) =
+ $this->execxLocal('merge-base %s %s', $child, $parent);
+ $common_ancestor = trim($common_ancestor, " \n\2");
+
+ return $common_ancestor == $parent && $common_ancestor != $child;
+ }
+
public function getLocalCommitInformation() {
if ($this->repositoryHasNoCommits) {
// Zero commits.
@@ -106,7 +123,16 @@
// this as being the commits X and Y. If we log "B..Y", we only show
// Y. With "Y --not B", we show X and Y.
- $against = csprintf('%s --not %s', 'HEAD', $this->getBaseCommit());
+ $base_commit = $this->getBaseCommit();
+ $head_commit = $this->getHeadCommit();
+ if ($this->isDescendant($head_commit, $base_commit) === false) {
+ throw new Exception(
+ "base commit ${head_commit} is not a child of head commit ".
+ "${base_commit}");
+ }
+
+ $against = csprintf('%s --not %s',
+ $this->getHeadCommit(), $this->getBaseCommit());
}
// NOTE: Windows escaping of "%" symbols apparently is inherently broken;
@@ -161,8 +187,9 @@
}
list($err, $merge_base) = $this->execManualLocal(
- 'merge-base %s HEAD',
- $symbolic_commit);
+ 'merge-base %s %s',
+ $symbolic_commit,
+ $this->getHeadCommit());
if ($err) {
throw new ArcanistUsageException(
"Unable to find any git commit named '{$symbolic_commit}' in ".
@@ -170,8 +197,8 @@
}
$this->setBaseCommitExplanation(
- "it is the merge-base of '{$symbolic_commit}' and HEAD, as you ".
- "explicitly specified.");
+ "it is the merge-base of '{$symbolic_commit}' and ".
+ "{$this->symbolicHeadCommit}, as you explicitly specified.");
return trim($merge_base);
}
@@ -301,6 +328,44 @@
return trim($merge_base);
}
+ public function getHeadCommit() {
+ if (!$this->supportsCommitRanges()) {
+ throw new ArcanistCapabilityNotSupportedException($this);
+ }
+
+ if ($this->resolvedHeadCommit === null) {
+ $this->resolvedHeadCommit =
+ $this->resolveCommit($this->symbolicHeadCommit);
+ }
+
+ return $this->resolvedHeadCommit;
+ }
+
+ final public function setHeadCommit($symbolic_commit) {
+ $this->symbolicHeadCommit = $symbolic_commit;
+ $this->reloadCommitRange();
+ return $this;
+ }
+
+ /**
+ * Translates a symbolic commit (like "HEAD^") to a commit identifier.
+ * @param string_symbol commit.
+ * @return string the commit SHA.
+ */
+ private function resolveCommit($symbolic_commit) {
+ list($err, $commit_hash) = $this->execManualLocal(
+ 'rev-parse %s',
+ $symbolic_commit);
+
+ if ($err) {
+ throw new ArcanistUsageException(
+ "Unable to find any git commit named '{$symbolic_commit}' in ".
+ "this repository.");
+ }
+
+ return trim($commit_hash);
+ }
+
private function getDiffFullOptions($detect_moves_and_renames = true) {
$options = array(
self::getDiffBaseOptions(),
@@ -335,8 +400,9 @@
public function getFullGitDiff() {
$options = $this->getDiffFullOptions();
list($stdout) = $this->execxLocal(
- "diff {$options} %s --",
- $this->getBaseCommit());
+ "diff {$options} %s..%s --",
+ $this->getBaseCommit(),
+ $this->getHeadCommit());
return $stdout;
}
@@ -401,8 +467,9 @@
} else {
// 2..N commits.
list($stdout) = $this->execxLocal(
- 'log --first-parent --format=medium %s..HEAD',
- $this->getBaseCommit());
+ 'log --first-parent --format=medium %s..%s',
+ $this->getBaseCommit(),
+ $this->getHeadCommit());
}
return $stdout;
}
diff --git a/src/repository/api/ArcanistRepositoryAPI.php b/src/repository/api/ArcanistRepositoryAPI.php
--- a/src/repository/api/ArcanistRepositoryAPI.php
+++ b/src/repository/api/ArcanistRepositoryAPI.php
@@ -575,6 +575,10 @@
return $this;
}
+ public function setHeadCommit($symbolic_commit) {
+ throw new ArcanistCapabilityNotSupportedException($this);
+ }
+
final public function getBaseCommit() {
if (!$this->supportsCommitRanges()) {
throw new ArcanistCapabilityNotSupportedException($this);
@@ -588,6 +592,10 @@
return $this->resolvedBaseCommit;
}
+ public function getHeadCommit() {
+ throw new ArcanistCapabilityNotSupportedException($this);
+ }
+
final public function reloadCommitRange() {
$this->resolvedBaseCommit = null;
$this->baseCommitExplanation = null;
diff --git a/src/workflow/ArcanistDiffWorkflow.php b/src/workflow/ArcanistDiffWorkflow.php
--- a/src/workflow/ArcanistDiffWorkflow.php
+++ b/src/workflow/ArcanistDiffWorkflow.php
@@ -395,6 +395,18 @@
),
),
'*' => 'paths',
+ 'head' => array(
+ 'param' => 'commit',
+ 'help' => "specify the head commit.\n".
+ "This disables many Arcanist/Phabricator features which depend on ".
+ "having access to the working copy.",
+ 'supports' => array('git'),
+ 'conflicts' => array(
+ 'lintall' => '--head suppresses lint.',
+ 'advice' => '--head suppresses lint.',
+ ),
+
+ )
);
if (phutil_is_windows()) {
@@ -433,8 +445,19 @@
array_unshift($argv, '--ansi');
}
- if ($this->getRepositoryAPI()->supportsCommitRanges()) {
- $this->getRepositoryAPI()->getBaseCommit();
+ $repo = $this->getRepositoryAPI();
+ $head_commit = $this->getArgument('head', null);
+ $range_supported = $repo->supportsCommitRanges();
+ if ($head_commit) {
+ if (!$range_supported) {
+ throw new Exception('ranged are not supported');
+ }
+
+ $repo->setHeadCommit($head_commit);
+ }
+
+ if ($range_supported) {
+ $repo->getBaseCommit();
}
$script = phutil_get_library_root('arcanist').'/../scripts/arcanist.php';
@@ -661,7 +684,9 @@
if ($repository_api instanceof ArcanistSubversionAPI) {
$repository_api->limitStatusToPaths($this->getArgument('paths'));
}
- $this->requireCleanWorkingCopy();
+ if (!$this->getArgument('range')) {
+ $this->requireCleanWorkingCopy();
+ }
} catch (ArcanistUncommittedChangesException $ex) {
if ($repository_api instanceof ArcanistMercurialAPI) {
$use_dirty_changes = false;
@@ -1216,7 +1241,8 @@
private function runLint() {
if ($this->getArgument('nolint') ||
$this->getArgument('only') ||
- $this->isRawDiffSource()) {
+ $this->isRawDiffSource() ||
+ $this->getArgument('range')) {
return ArcanistLintWorkflow::RESULT_SKIP;
}
@@ -1297,7 +1323,8 @@
private function runUnit() {
if ($this->getArgument('nounit') ||
$this->getArgument('only') ||
- $this->isRawDiffSource()) {
+ $this->isRawDiffSource() ||
+ $this->getArgument('range')) {
return ArcanistUnitWorkflow::RESULT_SKIP;
}
diff --git a/src/workflow/ArcanistWhichWorkflow.php b/src/workflow/ArcanistWhichWorkflow.php
--- a/src/workflow/ArcanistWhichWorkflow.php
+++ b/src/workflow/ArcanistWhichWorkflow.php
@@ -61,6 +61,10 @@
),
'supports' => array('git', 'hg'),
),
+ 'head' => array(
+ 'param' => 'commit',
+ 'help' => 'specify the head commit.'
+ ),
'*' => 'commit',
);
}
@@ -83,7 +87,19 @@
$repository_api->setBaseCommitArgumentRules(
$this->getArgument('base', ''));
- if ($repository_api->supportsCommitRanges()) {
+ $supports_ranges = $repository_api->supportsCommitRanges();
+
+ if ($this->getArgument('head')) {
+ if ($supports_ranges === false) {
+ throw new Exception('--head is not supported in this VCS');
+ }
+
+ $head_commit = $this->getArgument('head');
+ $arg .= " --head ${head_commit}";
+ $repository_api->setHeadCommit($head_commit);
+ }
+
+ if ($supports_ranges) {
$relative = $repository_api->getBaseCommit();
if ($this->getArgument('show-base')) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 15, 11:22 PM (1 w, 17 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7619601
Default Alt Text
D9369.id22423.diff (8 KB)
Attached To
Mode
D9369: --range support for git
Attached
Detach File
Event Timeline
Log In to Comment