Page MenuHomePhabricator

D21716.id51764.diff
No OneTemporary

D21716.id51764.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -346,6 +346,7 @@
'ArcanistMercurialAPI' => 'repository/api/ArcanistMercurialAPI.php',
'ArcanistMercurialCommitGraphQuery' => 'repository/graph/query/ArcanistMercurialCommitGraphQuery.php',
'ArcanistMercurialCommitMessageHardpointQuery' => 'query/ArcanistMercurialCommitMessageHardpointQuery.php',
+ 'ArcanistMercurialCommitSymbolCommitHardpointQuery' => 'ref/commit/ArcanistMercurialCommitSymbolCommitHardpointQuery.php',
'ArcanistMercurialLandEngine' => 'land/engine/ArcanistMercurialLandEngine.php',
'ArcanistMercurialLocalState' => 'repository/state/ArcanistMercurialLocalState.php',
'ArcanistMercurialParser' => 'repository/parser/ArcanistMercurialParser.php',
@@ -1404,6 +1405,7 @@
'ArcanistMercurialAPI' => 'ArcanistRepositoryAPI',
'ArcanistMercurialCommitGraphQuery' => 'ArcanistCommitGraphQuery',
'ArcanistMercurialCommitMessageHardpointQuery' => 'ArcanistWorkflowMercurialHardpointQuery',
+ 'ArcanistMercurialCommitSymbolCommitHardpointQuery' => 'ArcanistWorkflowMercurialHardpointQuery',
'ArcanistMercurialLandEngine' => 'ArcanistLandEngine',
'ArcanistMercurialLocalState' => 'ArcanistRepositoryLocalState',
'ArcanistMercurialParser' => 'Phobject',
diff --git a/src/ref/commit/ArcanistMercurialCommitSymbolCommitHardpointQuery.php b/src/ref/commit/ArcanistMercurialCommitSymbolCommitHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/ref/commit/ArcanistMercurialCommitSymbolCommitHardpointQuery.php
@@ -0,0 +1,159 @@
+<?php
+
+final class ArcanistMercurialCommitSymbolCommitHardpointQuery
+ extends ArcanistWorkflowMercurialHardpointQuery {
+
+ public function getHardpoints() {
+ return array(
+ ArcanistCommitSymbolRef::HARDPOINT_OBJECT,
+ );
+ }
+
+ protected function canLoadRef(ArcanistRef $ref) {
+ return ($ref instanceof ArcanistCommitSymbolRef);
+ }
+
+ public function loadHardpoint(array $refs, $hardpoint) {
+ $symbol_map = array();
+ foreach ($refs as $key => $ref) {
+ $symbol_map[$key] = $ref->getSymbol();
+ }
+
+ $symbol_set = array_fuse($symbol_map);
+ foreach ($symbol_set as $symbol) {
+ $this->validateSymbol($symbol);
+ }
+
+ $api = $this->getRepositoryAPI();
+
+ // Using "hg log" with repeated "--rev arguments will have the following
+ // behaviors which need accounted for:
+ // 1. If any one revision is invalid then the entire command will fail. To
+ // work around this the revset uses a trick where specifying a pattern
+ // for the bookmark() or tag() predicates instead of a literal won't
+ // result in failure if the pattern isn't found.
+ // 2. Multiple markers that resolve to the same node will only be included
+ // once in the output. Because of this the order of output can't be
+ // relied upon to match up with the requested symbol. To work around
+ // this, the template used will also include tags and bookmarks as the
+ // possible symbols being checked then build a map of used symbols to be
+ // the lookup for the ones requested. Here we lump both tags and
+ // bookmarks together as it's not important to distinguish between them.
+ // However Mercurial does permit bookmarks and tags to share the same
+ // name~.
+ // 3. The working directory can't be identified directly, instead a special
+ // template conditional is used to include 'CWD' as the second item in
+ // the output if the node is also the working directory, or 'NOTCWD'
+ // otherwise. This needs included before the tags/bookmarks in order to
+ // distinguish it from some repository using that same name for a tag or
+ // bookmark.
+
+ $pattern = array();
+ $arguments = array();
+
+ $pattern[] = 'log';
+
+ $pattern[] = '--template %s';
+ $arguments[] = "{node}\1".
+ "{ifcontains(rev, revset('parents()'), 'CWD', 'NOTCWD')}\1".
+ "{tags % '{tag}\2'}{bookmarks % '{bookmark}\2'}\3";
+
+ foreach ($symbol_set as $symbol) {
+ // This is the one symbol that wouldn't be a bookmark or tag
+ if ($symbol === '.') {
+ $pattern[] = '--rev .';
+ continue;
+ }
+ $pattern[] = '--rev %s';
+ $symbol = preg_quote($symbol);
+ $arguments[] = hgsprintf('bookmark("re:^%s$") or tag("re:^%s$")',
+ $symbol,
+ $symbol);
+ }
+
+ $pattern = implode(' ', $pattern);
+ array_unshift($arguments, $pattern);
+
+ $future = call_user_func_array(
+ array($api, 'newFuture'),
+ $arguments);
+
+ list($stdout) = (yield $this->yieldFuture($future));
+
+ $lines = explode("\3", $stdout);
+
+ $hash_map = array();
+ $symmap = array();
+
+ foreach ($lines as $line) {
+ $parts = array_filter(explode("\1", $line, 4));
+
+ if (empty($parts)) {
+ continue;
+ } else if (count($parts) === 2) {
+ list($node, $cwd) = $parts;
+ $markers = array();
+ } else if (count($parts) === 3) {
+ list($node, $cwd, $markers) = $parts;
+ $markers = array_filter(explode("\2", $markers));
+ } else {
+ throw new Exception(
+ pht('Execution of "hg log" emitted an unexpected line ("%s").',
+ $line));
+ }
+
+ foreach ($markers as $marker) {
+ if (!isset($hash_map[$marker])) {
+ $hash_map[$marker] = $node;
+ } else if ($hash_map[$marker] !== $node) {
+ $hash_map[$marker] = '';
+ }
+ }
+
+ // The log template will mark the working directory node with 'CWD' which
+ // we insert for the special marker '.' for the working directory, used
+ // by ArcanistMercurialAPI::newCurrentCommitSymbol().
+ if ($cwd === 'CWD') {
+ if (!isset($hash_map['.'])) {
+ $hash_map['.'] = $node;
+ } else if ($hash_map['.'] !== $node) {
+ $hash_map['.'] = '';
+ }
+ }
+ }
+
+ // Remove entries resulting in collisions, which set empty string values
+ $hash_map = array_filter($hash_map);
+
+ $results = array();
+ foreach ($symbol_map as $key => $symbol) {
+ if (isset($hash_map[$symbol])) {
+ $results[$key] = $hash_map[$symbol];
+ }
+ }
+
+ foreach ($results as $key => $result) {
+ if ($result === null) {
+ continue;
+ }
+
+ $ref = id(new ArcanistCommitRef())
+ ->setCommitHash($result);
+
+ $results[$key] = $ref;
+ }
+
+ yield $this->yieldMap($results);
+ }
+
+ private function validateSymbol($symbol) {
+ if (strpos($symbol, "\n") !== false) {
+ throw new Exception(
+ pht(
+ 'Commit symbol "%s" contains a newline. This is not a valid '.
+ 'character in a Mercurial commit symbol.',
+ addcslashes($symbol, "\\\n")));
+ }
+ }
+
+}
diff --git a/src/repository/api/ArcanistMercurialAPI.php b/src/repository/api/ArcanistMercurialAPI.php
--- a/src/repository/api/ArcanistMercurialAPI.php
+++ b/src/repository/api/ArcanistMercurialAPI.php
@@ -454,6 +454,10 @@
}
}
+ protected function newCurrentCommitSymbol() {
+ return $this->getWorkingCopyRevision();
+ }
+
public function getWorkingCopyRevision() {
return '.';
}
diff --git a/src/workflow/ArcanistAmendWorkflow.php b/src/workflow/ArcanistAmendWorkflow.php
--- a/src/workflow/ArcanistAmendWorkflow.php
+++ b/src/workflow/ArcanistAmendWorkflow.php
@@ -164,8 +164,6 @@
->execute();
}
- return;
-
if ($api->getUncommittedChanges()) {
// TODO: Make this class of error show the uncommitted changes.

File Metadata

Mime Type
text/plain
Expires
Wed, May 8, 11:40 PM (4 w, 12 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6273534
Default Alt Text
D21716.id51764.diff (7 KB)

Event Timeline