Mercurial > hg-stable
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')) |