comparison mercurial/utils/storageutil.py @ 40003:0e8836be9541

storageutil: implement file identifier resolution method (BC) revlog.lookup() has a number of advanced features, including partial node matching. These advanced features aren't needed for file id lookup because file identifiers are almost always from internal sources. (An exception to this is hgweb, which appears to have some code paths that attempt to resolve a user-supplied string to a node.) This commit implements a new function for resolving file identifiers to nodes. It behaves like revlog.lookup() but without the advanced features. Tests reveal behavior changes: * Partial hex nodes are no longer resolved to nodes. * "-1" now returns nullid instead of raising LookupError. * "0" on an empty store now raises LookupError instead of returning nullid. I'm not sure why "-1" wasn't recognized before. But it seems reasonable to accept it as a value since integer -1 resolves to nullid. These changes all seem reasonable to me. And with the exception of partial hex node matching, we may want to consider changing revlog.lookup() as well. Differential Revision: https://phab.mercurial-scm.org/D4797
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 28 Sep 2018 11:03:17 -0700
parents d63153611ed5
children ad8389ecd3f5
comparison
equal deleted inserted replaced
40002:215fd73cfe52 40003:0e8836be9541
8 from __future__ import absolute_import 8 from __future__ import absolute_import
9 9
10 import hashlib 10 import hashlib
11 import re 11 import re
12 12
13 from ..i18n import _
13 from ..node import ( 14 from ..node import (
15 bin,
14 nullid, 16 nullid,
15 ) 17 )
16 from .. import ( 18 from .. import (
19 error,
17 pycompat, 20 pycompat,
18 ) 21 )
19 22
20 _nullhash = hashlib.sha1(nullid) 23 _nullhash = hashlib.sha1(nullid)
21 24
97 stop = storelen 100 stop = storelen
98 else: 101 else:
99 stop = storelen 102 stop = storelen
100 103
101 return pycompat.xrange(start, stop, step) 104 return pycompat.xrange(start, stop, step)
105
106 def fileidlookup(store, fileid, identifier):
107 """Resolve the file node for a value.
108
109 ``store`` is an object implementing the ``ifileindex`` interface.
110
111 ``fileid`` can be:
112
113 * A 20 byte binary node.
114 * An integer revision number
115 * A 40 byte hex node.
116 * A bytes that can be parsed as an integer representing a revision number.
117
118 ``identifier`` is used to populate ``error.LookupError`` with an identifier
119 for the store.
120
121 Raises ``error.LookupError`` on failure.
122 """
123 if isinstance(fileid, int):
124 return store.node(fileid)
125
126 if len(fileid) == 20:
127 try:
128 store.rev(fileid)
129 return fileid
130 except error.LookupError:
131 pass
132
133 if len(fileid) == 40:
134 try:
135 rawnode = bin(fileid)
136 store.rev(rawnode)
137 return rawnode
138 except TypeError:
139 pass
140
141 try:
142 rev = int(fileid)
143
144 if b'%d' % rev != fileid:
145 raise ValueError
146
147 try:
148 return store.node(rev)
149 except (IndexError, TypeError):
150 pass
151 except (ValueError, OverflowError):
152 pass
153
154 raise error.LookupError(fileid, identifier, _('no match found'))