scmutil: make shortesthexnodeidprefix() take a full binary nodeid
authorMartin von Zweigbergk <martinvonz@google.com>
Sat, 14 Apr 2018 00:13:08 -0700
changeset 37709 7b2955624777
parent 37708 8e8541610d85
child 37710 0a5fe2a08e82
scmutil: make shortesthexnodeidprefix() take a full binary nodeid The shortest() template function depended on the behavior of revlog._partialmatch() for these types of inputs: * non-hex strings * ambiguous strings * too long strings revlog._partialmatch() seems to return the input unchanged in these cases, but we shouldn't depend on such a low-level function to match the behavior we want in the user-facing template function. Instead, let's handle these cases in the template function and always pass a binary nodeid to _partialmatch(). Differential Revision: https://phab.mercurial-scm.org/D3371
hgext/show.py
mercurial/scmutil.py
mercurial/templatefuncs.py
tests/test-command-template.t
--- a/hgext/show.py	Fri Apr 13 10:36:03 2018 -0700
+++ b/hgext/show.py	Sat Apr 14 00:13:08 2018 -0700
@@ -29,7 +29,6 @@
 
 from mercurial.i18n import _
 from mercurial.node import (
-    hex,
     nullrev,
 )
 from mercurial import (
@@ -448,8 +447,8 @@
     if not revs:
         return minlen
     cl = repo.changelog
-    return max(len(scmutil.shortesthexnodeidprefix(repo, hex(cl.node(r)),
-                                                   minlen)) for r in revs)
+    return max(len(scmutil.shortesthexnodeidprefix(repo, cl.node(r), minlen))
+               for r in revs)
 
 # Adjust the docstring of the show command so it shows all registered views.
 # This is a bit hacky because it runs at the end of module load. When moved
--- a/mercurial/scmutil.py	Fri Apr 13 10:36:03 2018 -0700
+++ b/mercurial/scmutil.py	Sat Apr 14 00:13:08 2018 -0700
@@ -443,12 +443,12 @@
     repo.changelog.rev(node)  # make sure node isn't filtered
     return node
 
-def shortesthexnodeidprefix(repo, hexnode, minlength=1):
+def shortesthexnodeidprefix(repo, node, minlength=1):
     """Find the shortest unambiguous prefix that matches hexnode."""
     # _partialmatch() of filtered changelog could take O(len(repo)) time,
     # which would be unacceptably slow. so we look for hash collision in
     # unfiltered space, which means some hashes may be slightly longer.
-    return repo.unfiltered().changelog.shortest(hexnode, minlength)
+    return repo.unfiltered().changelog.shortest(hex(node), minlength)
 
 def isrevsymbol(repo, symbol):
     """Checks if a symbol exists in the repo.
--- a/mercurial/templatefuncs.py	Fri Apr 13 10:36:03 2018 -0700
+++ b/mercurial/templatefuncs.py	Sat Apr 14 00:13:08 2018 -0700
@@ -10,6 +10,9 @@
 import re
 
 from .i18n import _
+from .node import (
+    bin,
+)
 from . import (
     color,
     encoding,
@@ -579,7 +582,7 @@
         # i18n: "shortest" is a keyword
         raise error.ParseError(_("shortest() expects one or two arguments"))
 
-    node = evalstring(context, mapping, args[0])
+    hexnode = evalstring(context, mapping, args[0])
 
     minlength = 4
     if len(args) > 1:
@@ -588,6 +591,20 @@
                                 _("shortest() expects an integer minlength"))
 
     repo = context.resource(mapping, 'ctx')._repo
+    if len(hexnode) > 40:
+        return hexnode
+    elif len(hexnode) == 40:
+        try:
+            node = bin(hexnode)
+        except TypeError:
+            return hexnode
+    else:
+        try:
+            node = scmutil.resolvehexnodeidprefix(repo, hexnode)
+        except (error.LookupError, error.WdirUnsupported):
+            return hexnode
+        if not node:
+            return hexnode
     return scmutil.shortesthexnodeidprefix(repo, node, minlength)
 
 @templatefunc('strip(text[, chars])')
--- a/tests/test-command-template.t	Fri Apr 13 10:36:03 2018 -0700
+++ b/tests/test-command-template.t	Sat Apr 14 00:13:08 2018 -0700
@@ -3900,6 +3900,21 @@
   $ hg log -r 'wdir()' -T '{node|shortest}\n'
   ffff
 
+  $ hg log --template '{shortest("f")}\n' -l1
+  f
+
+  $ hg log --template '{shortest("0123456789012345678901234567890123456789")}\n' -l1
+  0123456789012345678901234567890123456789
+
+  $ hg log --template '{shortest("01234567890123456789012345678901234567890123456789")}\n' -l1
+  01234567890123456789012345678901234567890123456789
+
+  $ hg log --template '{shortest("not a hex string")}\n' -l1
+  not a hex string
+
+  $ hg log --template '{shortest("not a hex string, but it'\''s 40 bytes long")}\n' -l1
+  not a hex string, but it's 40 bytes long
+
   $ cd ..
 
 Test shortest(node) with the repo having short hash collision: