changeset 1000:a128b9a53b5a

revset_gitnode: allow abbreviated hashes The previous implementation only allowed passing 40-hexdigit hashes or 12-hexdigit abbreviations to `gitnode(hash)`. Shorter or longer hashes were accepted, but failed silently. With this fix, any unambiguous abbreviation is accepted. `gitnode(a5b)` selects the revision whose Git hash starts with `a5b`, if there is one, and aborts if there are several.
author Sietse Brouwer <sbbrouwer@gmail.com>
date Thu, 06 Oct 2016 10:11:14 +0200
parents ff663d2214db
children d0ce6eaebe7b
files hggit/__init__.py tests/test-keywords.t
diffstat 2 files changed, 24 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/hggit/__init__.py
+++ b/hggit/__init__.py
@@ -30,6 +30,7 @@
 from bisect import insort
 from git_handler import GitHandler
 from mercurial.node import hex
+from mercurial.error import LookupError
 from mercurial.i18n import _
 from mercurial import (
     bundlerepo,
@@ -382,7 +383,9 @@
 
 def revset_gitnode(repo, subset, x):
     '''``gitnode(hash)``
-    Select changesets that originate in the given Git revision.
+    Select the changeset that originates in the given Git revision. The hash
+    may be abbreviated: `gitnode(a5b)` selects the revision whose Git hash
+    starts with `a5b`. Aborts if multiple changesets match the abbreviation.
     '''
     args = revset.getargs(x, 1, 1, "gitnode takes one argument")
     rev = revset.getstring(args[0],
@@ -394,8 +397,11 @@
         gitnode = git.map_git_get(hex(node(r)))
         if gitnode is None:
             return False
-        return rev in [gitnode, gitnode[:12]]
-    return baseset(r for r in subset if matches(r))
+        return gitnode.startswith(rev)
+    result = baseset(r for r in subset if matches(r))
+    if 0 <= len(result) < 2:
+        return result
+    raise LookupError(rev, git.map_file, _('ambiguous identifier'))
 
 def gitnodekw(**args):
     """:gitnode: String.  The Git changeset identification hash, as a 40 hexadecimal digit string."""
--- a/tests/test-keywords.t
+++ b/tests/test-keywords.t
@@ -11,25 +11,37 @@
   $ git add beta
   $ fn_git_commit -m 'add beta'
 
+This commit is called gamma10 so that its hash will have the same initial digit
+as commit alpha. This lets us test ambiguous abbreviated identifiers.
+
+  $ echo gamma10 > gamma10
+  $ git add gamma10
+  $ fn_git_commit -m 'add gamma10'
+
   $ cd ..
 
   $ hg clone gitrepo hgrepo | grep -v '^updating'
   importing git objects into hg
-  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd hgrepo
   $ echo gamma > gamma
   $ hg add gamma
   $ hg commit -m 'add gamma'
 
   $ hg log --template "{rev} {node} {node|short} {gitnode} {gitnode|short}\n"
-  2 168eb1ee8b3c04e6723c9330327b0eec1e36577f 168eb1ee8b3c  
+  3 965bf7d08d3ac847dd8eb9e72ee0bf547d1a65d9 965bf7d08d3a  
+  2 8e3f0ecc9aefd4ea2fdf8e2d5299cac548762a1c 8e3f0ecc9aef 7e2a5465ff4e3b992c429bb87a392620a0ac97b7 7e2a5465ff4e
   1 7fe02317c63d9ee324d4b5df7c9296085162da1b 7fe02317c63d 9497a4ee62e16ee641860d7677cdb2589ea15554 9497a4ee62e1
   0 ff7a2f2d8d7099694ae1e8b03838d40575bebb63 ff7a2f2d8d70 7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 7eeab2ea75ec
   $ hg log --template "fromgit {rev}\n" --rev "fromgit()"
   fromgit 0
   fromgit 1
+  fromgit 2
   $ hg log --template "gitnode_existsA {rev}\n" --rev "gitnode(9497a4ee62e16ee641860d7677cdb2589ea15554)"
   gitnode_existsA 1
-  $ hg log --template "gitnode_existsB {rev}\n" --rev "gitnode(7eeab2ea75ec)"
+  $ hg log --template "gitnode_existsB {rev}\n" --rev "gitnode(7eeab)"
   gitnode_existsB 0
+  $ hg log --rev "gitnode(7e)"
+  abort: git-mapfile@7e: ambiguous identifier!
+  [255]
   $ hg log --template "gitnode_notexists {rev}\n" --rev "gitnode(1234567890ab)"