revlog: add support for partial matching of wdir node id
The idea is simple. If the given node id prefix is 'ff...f', add +1 to the
number of matches (e.g. ambiguous if partial + maybewdir > 1).
This patch also fixes id() revset and shortest() template since _partialmatch()
can raise WdirUnsupported exception.
--- a/mercurial/node.py Sat Aug 20 18:15:19 2016 +0900
+++ b/mercurial/node.py Fri Aug 19 18:26:04 2016 +0900
@@ -29,6 +29,7 @@
# (they are experimental, so don't add too many dependencies on them)
wdirrev = 0x7fffffff
wdirid = b"\xff" * 20
+wdirhex = hex(wdirid)
def short(node):
return hex(node[:6])
--- a/mercurial/revlog.py Sat Aug 20 18:15:19 2016 +0900
+++ b/mercurial/revlog.py Fri Aug 19 18:26:04 2016 +0900
@@ -26,6 +26,7 @@
hex,
nullid,
nullrev,
+ wdirhex,
wdirid,
wdirrev,
)
@@ -1038,10 +1039,17 @@
pass
def _partialmatch(self, id):
+ maybewdir = wdirhex.startswith(id)
try:
partial = self.index.partialmatch(id)
if partial and self.hasnode(partial):
+ if maybewdir:
+ # single 'ff...' match in radix tree, ambiguous with wdir
+ raise RevlogError
return partial
+ if maybewdir:
+ # no 'ff...' match in radix tree, wdir identified
+ raise error.WdirUnsupported
return None
except RevlogError:
# parsers.c radix tree lookup gave multiple matches
@@ -1066,11 +1074,13 @@
nl = [n for n in nl if hex(n).startswith(id) and
self.hasnode(n)]
if len(nl) > 0:
- if len(nl) == 1:
+ if len(nl) == 1 and not maybewdir:
self._pcache[id] = nl[0]
return nl[0]
raise LookupError(id, self.indexfile,
_('ambiguous identifier'))
+ if maybewdir:
+ raise error.WdirUnsupported
return None
except TypeError:
pass
--- a/mercurial/revset.py Sat Aug 20 18:15:19 2016 +0900
+++ b/mercurial/revset.py Fri Aug 19 18:26:04 2016 +0900
@@ -1309,12 +1309,12 @@
rn = None
else:
rn = None
- pm = repo.changelog._partialmatch(n)
- if pm is not None:
- try:
+ try:
+ pm = repo.changelog._partialmatch(n)
+ if pm is not None:
rn = repo.changelog.rev(pm)
- except error.WdirUnsupported:
- rn = node.wdirrev
+ except error.WdirUnsupported:
+ rn = node.wdirrev
if rn is None:
return baseset()
--- a/mercurial/templater.py Sat Aug 20 18:15:19 2016 +0900
+++ b/mercurial/templater.py Fri Aug 19 18:26:04 2016 +0900
@@ -960,6 +960,9 @@
return True
except error.RevlogError:
return False
+ except error.WdirUnsupported:
+ # single 'ff...' match
+ return True
shortest = node
startlength = max(6, minlength)
--- a/tests/test-command-template.t Sat Aug 20 18:15:19 2016 +0900
+++ b/tests/test-command-template.t Fri Aug 19 18:26:04 2016 +0900
@@ -3503,6 +3503,9 @@
hg: parse error: shortest() expects an integer minlength
[255]
+ $ hg log -r 'wdir()' -T '{node|shortest}\n'
+ ffff
+
$ cd ..
Test shortest(node) with the repo having short hash collision:
--- a/tests/test-revset.t Sat Aug 20 18:15:19 2016 +0900
+++ b/tests/test-revset.t Fri Aug 19 18:26:04 2016 +0900
@@ -1289,13 +1289,64 @@
2147483647
$ hg debugrevspec '0:wdir() & ffffffffffffffffffffffffffffffffffffffff'
2147483647
+ $ hg debugrevspec '0:wdir() & ffffffffffff'
+ 2147483647
$ hg debugrevspec '0:wdir() & id(ffffffffffffffffffffffffffffffffffffffff)'
2147483647
$ hg debugrevspec '0:wdir() & id(ffffffffffff)'
-BROKEN: should be '2147483647'
+ 2147483647
+
+ $ cd ..
+
+Test short 'ff...' hash collision
+(BUG: '0:wdir()' is still needed to populate wdir revision)
+
+ $ hg init wdir-hashcollision
+ $ cd wdir-hashcollision
+ $ cat <<EOF >> .hg/hgrc
+ > [experimental]
+ > evolution = createmarkers
+ > EOF
+ $ echo 0 > a
+ $ hg ci -qAm 0
+ $ for i in 2463 2961 6726 78127; do
+ > hg up -q 0
+ > echo $i > a
+ > hg ci -qm $i
+ > done
+ $ hg up -q null
+ $ hg log -r '0:wdir()' -T '{rev}:{node} {shortest(node, 3)}\n'
+ 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a b4e
+ 1:fffbae3886c8fbb2114296380d276fd37715d571 fffba
+ 2:fffb6093b00943f91034b9bdad069402c834e572 fffb6
+ 3:fff48a9b9de34a4d64120c29548214c67980ade3 fff4
+ 4:ffff85cff0ff78504fcdc3c0bc10de0c65379249 ffff8
+ 2147483647:ffffffffffffffffffffffffffffffffffffffff fffff
+ $ hg debugobsolete fffbae3886c8fbb2114296380d276fd37715d571
+
+ $ hg debugrevspec '0:wdir() & fff'
+ abort: 00changelog.i@fff: ambiguous identifier!
+ [255]
+ $ hg debugrevspec '0:wdir() & ffff'
+ abort: 00changelog.i@ffff: ambiguous identifier!
+ [255]
+ $ hg debugrevspec '0:wdir() & fffb'
+ abort: 00changelog.i@fffb: ambiguous identifier!
+ [255]
+BROKEN should be '2' (node lookup uses unfiltered repo since dc25ed84bee8)
+ $ hg debugrevspec '0:wdir() & id(fffb)'
+ 2
+ $ hg debugrevspec '0:wdir() & ffff8'
+ 4
+ $ hg debugrevspec '0:wdir() & fffff'
+ 2147483647
+
+ $ cd ..
Test branch() with wdir()
+ $ cd repo
+
$ log '0:wdir() & branch("literal:é")'
8
9