changeset 30231:741e5d7f282d stable

templater: do not use index.partialmatch() directly to calculate shortest() cl.index.partialmatch() isn't a drop-in replacement for cl._partialmatch(). It has no knowledge about hidden revisions, and it raises ValueError if a node shorter than 4 chars is given. Instead, use index.partialmatch() through cl._partialmatch(), which has no such problems and gives the identical result with/without --pure. The test output was sampled with --pure without this patch, which shows the most correct result. However, we'll need to switch to using an unfiltered changelog because _partialmatch() of a filtered changelog can be an order of magnitude slower. (with hidden revisions) % hg log -R hg-committed -r0:20000 -T '{node|shortest}\n' --time > /dev/null (.^) time: real 1.530 secs (user 1.480+0.000 sys 0.040+0.000) (.) time: real 43.080 secs (user 43.060+0.000 sys 0.030+0.000)
author Yuya Nishihara <yuya@tcha.org>
date Sun, 23 Oct 2016 14:05:23 +0900
parents 46a0203dfb89
children 362740e05460
files mercurial/templater.py tests/test-command-template.t
diffstat 2 files changed, 70 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/templater.py	Wed Oct 26 22:50:06 2016 +0900
+++ b/mercurial/templater.py	Sun Oct 23 14:05:23 2016 +0900
@@ -840,13 +840,8 @@
     cl = mapping['ctx']._repo.changelog
     def isvalid(test):
         try:
-            try:
-                cl.index.partialmatch(test)
-            except AttributeError:
-                # Pure mercurial doesn't support partialmatch on the index.
-                # Fallback to the slow way.
-                if cl._partialmatch(test) is None:
-                    return False
+            if cl._partialmatch(test) is None:
+                return False
 
             try:
                 i = int(test)
--- a/tests/test-command-template.t	Wed Oct 26 22:50:06 2016 +0900
+++ b/tests/test-command-template.t	Sun Oct 23 14:05:23 2016 +0900
@@ -3413,8 +3413,76 @@
   hg: parse error: shortest() expects an integer minlength
   [255]
 
+  $ cd ..
+
+Test shortest(node) with the repo having short hash collision:
+
+  $ hg init hashcollision
+  $ cd hashcollision
+  $ cat <<EOF >> .hg/hgrc
+  > [experimental]
+  > evolution = createmarkers
+  > EOF
+  $ echo 0 > a
+  $ hg ci -qAm 0
+  $ for i in 17 129 248 242 480 580 617 1057 2857 4025; do
+  >   hg up -q 0
+  >   echo $i > a
+  >   hg ci -qm $i
+  > done
+  $ hg up -q null
+  $ hg log -r0: -T '{rev}:{node}\n'
+  0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
+  1:11424df6dc1dd4ea255eae2b58eaca7831973bbc
+  2:11407b3f1b9c3e76a79c1ec5373924df096f0499
+  3:11dd92fe0f39dfdaacdaa5f3997edc533875cfc4
+  4:10776689e627b465361ad5c296a20a487e153ca4
+  5:a00be79088084cb3aff086ab799f8790e01a976b
+  6:a0b0acd79b4498d0052993d35a6a748dd51d13e6
+  7:a0457b3450b8e1b778f1163b31a435802987fe5d
+  8:c56256a09cd28e5764f32e8e2810d0f01e2e357a
+  9:c5623987d205cd6d9d8389bfc40fff9dbb670b48
+  10:c562ddd9c94164376c20b86b0b4991636a3bf84f
+  $ hg debugobsolete a00be79088084cb3aff086ab799f8790e01a976b
+  $ hg debugobsolete c5623987d205cd6d9d8389bfc40fff9dbb670b48
+  $ hg debugobsolete c562ddd9c94164376c20b86b0b4991636a3bf84f
+
+ nodes starting with '11' (we don't have the revision number '11' though)
+
+  $ hg log -r 1:3 -T '{rev}:{shortest(node, 0)}\n'
+  1:1142
+  2:1140
+  3:11d
+
+ '5:a00' is hidden, but still we have two nodes starting with 'a0'
+
+  $ hg log -r 6:7 -T '{rev}:{shortest(node, 0)}\n'
+  6:a0b
+  7:a04
+
+ node '10' conflicts with the revision number '10' even if it is hidden
+ (we could exclude hidden revision numbers, but currently we don't)
+
+  $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n'
+  4:107
+  $ hg log -r 4 -T '{rev}:{shortest(node, 0)}\n' --hidden
+  4:107
+
+ node 'c562' should be unique if the other 'c562' nodes are hidden
+
+  $ hg log -r 8 -T '{rev}:{node|shortest}\n'
+  8:c562
+  $ hg log -r 8:10 -T '{rev}:{node|shortest}\n' --hidden
+  8:c5625
+  9:c5623
+  10:c562d
+
+  $ cd ..
+
 Test pad function
 
+  $ cd r
+
   $ hg log --template '{pad(rev, 20)} {author|user}\n'
   2                    test
   1                    {node|short}