comparison mercurial/revlog.py @ 47012:d55b71393907

node: replace nullid and friends with nodeconstants class The introduction of 256bit hashes require changes to nullid and other constant magic values. Start pushing them down from repository and revlog where sensible. Differential Revision: https://phab.mercurial-scm.org/D9465
author Joerg Sonnenberger <joerg@bec.de>
date Mon, 29 Mar 2021 01:52:06 +0200
parents 3c9208702db3
children 0d8ff1f4ab0c
comparison
equal deleted inserted replaced
46992:5fa019ceb499 47012:d55b71393907
24 24
25 # import stuff from node for others to import from revlog 25 # import stuff from node for others to import from revlog
26 from .node import ( 26 from .node import (
27 bin, 27 bin,
28 hex, 28 hex,
29 nullhex,
30 nullid,
31 nullrev, 29 nullrev,
32 sha1nodeconstants, 30 sha1nodeconstants,
33 short, 31 short,
34 wdirfilenodeids,
35 wdirhex,
36 wdirid,
37 wdirrev, 32 wdirrev,
38 ) 33 )
39 from .i18n import _ 34 from .i18n import _
40 from .pycompat import getattr 35 from .pycompat import getattr
41 from .revlogutils.constants import ( 36 from .revlogutils.constants import (
230 util.nouideprecwarn(msg, b'5.3', stacklevel=2) 225 util.nouideprecwarn(msg, b'5.3', stacklevel=2)
231 return self._nodemap 226 return self._nodemap
232 227
233 @util.propertycache 228 @util.propertycache
234 def _nodemap(self): 229 def _nodemap(self):
235 nodemap = nodemaputil.NodeMap({nullid: nullrev}) 230 nodemap = nodemaputil.NodeMap({sha1nodeconstants.nullid: nullrev})
236 for r in range(0, len(self)): 231 for r in range(0, len(self)):
237 n = self[r][7] 232 n = self[r][7]
238 nodemap[n] = r 233 nodemap[n] = r
239 return nodemap 234 return nodemap
240 235
268 def clearcaches(self): 263 def clearcaches(self):
269 self.__dict__.pop('_nodemap', None) 264 self.__dict__.pop('_nodemap', None)
270 265
271 def __getitem__(self, i): 266 def __getitem__(self, i):
272 if i == -1: 267 if i == -1:
273 return (0, 0, 0, -1, -1, -1, -1, nullid) 268 return (0, 0, 0, -1, -1, -1, -1, sha1nodeconstants.nullid)
274 return list.__getitem__(self, i) 269 return list.__getitem__(self, i)
275 270
276 271
277 class revlogoldio(object): 272 class revlogoldio(object):
278 def parseindex(self, data, inline): 273 def parseindex(self, data, inline):
279 s = INDEX_ENTRY_V0.size 274 s = INDEX_ENTRY_V0.size
280 index = [] 275 index = []
281 nodemap = nodemaputil.NodeMap({nullid: nullrev}) 276 nodemap = nodemaputil.NodeMap({sha1nodeconstants.nullid: nullrev})
282 n = off = 0 277 n = off = 0
283 l = len(data) 278 l = len(data)
284 while off + s <= l: 279 while off + s <= l:
285 cur = data[off : off + s] 280 cur = data[off : off + s]
286 off += s 281 off += s
816 return self.index.rev(node) 811 return self.index.rev(node)
817 except TypeError: 812 except TypeError:
818 raise 813 raise
819 except error.RevlogError: 814 except error.RevlogError:
820 # parsers.c radix tree lookup failed 815 # parsers.c radix tree lookup failed
821 if node == wdirid or node in wdirfilenodeids: 816 if (
817 node == self.nodeconstants.wdirid
818 or node in self.nodeconstants.wdirfilenodeids
819 ):
822 raise error.WdirUnsupported 820 raise error.WdirUnsupported
823 raise error.LookupError(node, self.indexfile, _(b'no node')) 821 raise error.LookupError(node, self.indexfile, _(b'no node'))
824 822
825 # Accessors for index entries. 823 # Accessors for index entries.
826 824
907 905
908 def parents(self, node): 906 def parents(self, node):
909 i = self.index 907 i = self.index
910 d = i[self.rev(node)] 908 d = i[self.rev(node)]
911 # inline node() to avoid function call overhead 909 # inline node() to avoid function call overhead
912 if d[5] == nullid: 910 if d[5] == self.nullid:
913 return i[d[6]][7], i[d[5]][7] 911 return i[d[6]][7], i[d[5]][7]
914 else: 912 else:
915 return i[d[5]][7], i[d[6]][7] 913 return i[d[5]][7], i[d[6]][7]
916 914
917 def chainlen(self, rev): 915 def chainlen(self, rev):
1025 1023
1026 'heads' and 'common' are both lists of node IDs. If heads is 1024 'heads' and 'common' are both lists of node IDs. If heads is
1027 not supplied, uses all of the revlog's heads. If common is not 1025 not supplied, uses all of the revlog's heads. If common is not
1028 supplied, uses nullid.""" 1026 supplied, uses nullid."""
1029 if common is None: 1027 if common is None:
1030 common = [nullid] 1028 common = [self.nullid]
1031 if heads is None: 1029 if heads is None:
1032 heads = self.heads() 1030 heads = self.heads()
1033 1031
1034 common = [self.rev(n) for n in common] 1032 common = [self.rev(n) for n in common]
1035 heads = [self.rev(n) for n in heads] 1033 heads = [self.rev(n) for n in heads]
1131 1129
1132 'heads' and 'common' are both lists of node IDs. If heads is 1130 'heads' and 'common' are both lists of node IDs. If heads is
1133 not supplied, uses all of the revlog's heads. If common is not 1131 not supplied, uses all of the revlog's heads. If common is not
1134 supplied, uses nullid.""" 1132 supplied, uses nullid."""
1135 if common is None: 1133 if common is None:
1136 common = [nullid] 1134 common = [self.nullid]
1137 if heads is None: 1135 if heads is None:
1138 heads = self.heads() 1136 heads = self.heads()
1139 1137
1140 common = [self.rev(n) for n in common] 1138 common = [self.rev(n) for n in common]
1141 heads = [self.rev(n) for n in heads] 1139 heads = [self.rev(n) for n in heads]
1169 roots = list(roots) 1167 roots = list(roots)
1170 if not roots: 1168 if not roots:
1171 return nonodes 1169 return nonodes
1172 lowestrev = min([self.rev(n) for n in roots]) 1170 lowestrev = min([self.rev(n) for n in roots])
1173 else: 1171 else:
1174 roots = [nullid] # Everybody's a descendant of nullid 1172 roots = [self.nullid] # Everybody's a descendant of nullid
1175 lowestrev = nullrev 1173 lowestrev = nullrev
1176 if (lowestrev == nullrev) and (heads is None): 1174 if (lowestrev == nullrev) and (heads is None):
1177 # We want _all_ the nodes! 1175 # We want _all_ the nodes!
1178 return ([self.node(r) for r in self], [nullid], list(self.heads())) 1176 return (
1177 [self.node(r) for r in self],
1178 [self.nullid],
1179 list(self.heads()),
1180 )
1179 if heads is None: 1181 if heads is None:
1180 # All nodes are ancestors, so the latest ancestor is the last 1182 # All nodes are ancestors, so the latest ancestor is the last
1181 # node. 1183 # node.
1182 highestrev = len(self) - 1 1184 highestrev = len(self) - 1
1183 # Set ancestors to None to signal that every node is an ancestor. 1185 # Set ancestors to None to signal that every node is an ancestor.
1199 highestrev = max([self.rev(n) for n in nodestotag]) 1201 highestrev = max([self.rev(n) for n in nodestotag])
1200 while nodestotag: 1202 while nodestotag:
1201 # grab a node to tag 1203 # grab a node to tag
1202 n = nodestotag.pop() 1204 n = nodestotag.pop()
1203 # Never tag nullid 1205 # Never tag nullid
1204 if n == nullid: 1206 if n == self.nullid:
1205 continue 1207 continue
1206 # A node's revision number represents its place in a 1208 # A node's revision number represents its place in a
1207 # topologically sorted list of nodes. 1209 # topologically sorted list of nodes.
1208 r = self.rev(n) 1210 r = self.rev(n)
1209 if r >= lowestrev: 1211 if r >= lowestrev:
1211 # If we are possibly a descendant of one of the roots 1213 # If we are possibly a descendant of one of the roots
1212 # and we haven't already been marked as an ancestor 1214 # and we haven't already been marked as an ancestor
1213 ancestors.add(n) # Mark as ancestor 1215 ancestors.add(n) # Mark as ancestor
1214 # Add non-nullid parents to list of nodes to tag. 1216 # Add non-nullid parents to list of nodes to tag.
1215 nodestotag.update( 1217 nodestotag.update(
1216 [p for p in self.parents(n) if p != nullid] 1218 [p for p in self.parents(n) if p != self.nullid]
1217 ) 1219 )
1218 elif n in heads: # We've seen it before, is it a fake head? 1220 elif n in heads: # We've seen it before, is it a fake head?
1219 # So it is, real heads should not be the ancestors of 1221 # So it is, real heads should not be the ancestors of
1220 # any other heads. 1222 # any other heads.
1221 heads.pop(n) 1223 heads.pop(n)
1239 return nonodes 1241 return nonodes
1240 else: 1242 else:
1241 # We are descending from nullid, and don't need to care about 1243 # We are descending from nullid, and don't need to care about
1242 # any other roots. 1244 # any other roots.
1243 lowestrev = nullrev 1245 lowestrev = nullrev
1244 roots = [nullid] 1246 roots = [self.nullid]
1245 # Transform our roots list into a set. 1247 # Transform our roots list into a set.
1246 descendants = set(roots) 1248 descendants = set(roots)
1247 # Also, keep the original roots so we can filter out roots that aren't 1249 # Also, keep the original roots so we can filter out roots that aren't
1248 # 'real' roots (i.e. are descended from other roots). 1250 # 'real' roots (i.e. are descended from other roots).
1249 roots = descendants.copy() 1251 roots = descendants.copy()
1333 if stop is specified, it will consider all the revs from stop 1335 if stop is specified, it will consider all the revs from stop
1334 as if they had no children 1336 as if they had no children
1335 """ 1337 """
1336 if start is None and stop is None: 1338 if start is None and stop is None:
1337 if not len(self): 1339 if not len(self):
1338 return [nullid] 1340 return [self.nullid]
1339 return [self.node(r) for r in self.headrevs()] 1341 return [self.node(r) for r in self.headrevs()]
1340 1342
1341 if start is None: 1343 if start is None:
1342 start = nullrev 1344 start = nullrev
1343 else: 1345 else:
1423 except (AttributeError, OverflowError): 1425 except (AttributeError, OverflowError):
1424 ancs = ancestor.ancestors(self.parentrevs, a, b) 1426 ancs = ancestor.ancestors(self.parentrevs, a, b)
1425 if ancs: 1427 if ancs:
1426 # choose a consistent winner when there's a tie 1428 # choose a consistent winner when there's a tie
1427 return min(map(self.node, ancs)) 1429 return min(map(self.node, ancs))
1428 return nullid 1430 return self.nullid
1429 1431
1430 def _match(self, id): 1432 def _match(self, id):
1431 if isinstance(id, int): 1433 if isinstance(id, int):
1432 # rev 1434 # rev
1433 return self.node(id) 1435 return self.node(id)
1461 except (TypeError, error.LookupError): 1463 except (TypeError, error.LookupError):
1462 pass 1464 pass
1463 1465
1464 def _partialmatch(self, id): 1466 def _partialmatch(self, id):
1465 # we don't care wdirfilenodeids as they should be always full hash 1467 # we don't care wdirfilenodeids as they should be always full hash
1466 maybewdir = wdirhex.startswith(id) 1468 maybewdir = self.nodeconstants.wdirhex.startswith(id)
1467 try: 1469 try:
1468 partial = self.index.partialmatch(id) 1470 partial = self.index.partialmatch(id)
1469 if partial and self.hasnode(partial): 1471 if partial and self.hasnode(partial):
1470 if maybewdir: 1472 if maybewdir:
1471 # single 'ff...' match in radix tree, ambiguous with wdir 1473 # single 'ff...' match in radix tree, ambiguous with wdir
1497 prefix = bin(id[: l * 2]) 1499 prefix = bin(id[: l * 2])
1498 nl = [e[7] for e in self.index if e[7].startswith(prefix)] 1500 nl = [e[7] for e in self.index if e[7].startswith(prefix)]
1499 nl = [ 1501 nl = [
1500 n for n in nl if hex(n).startswith(id) and self.hasnode(n) 1502 n for n in nl if hex(n).startswith(id) and self.hasnode(n)
1501 ] 1503 ]
1502 if nullhex.startswith(id): 1504 if self.nodeconstants.nullhex.startswith(id):
1503 nl.append(nullid) 1505 nl.append(self.nullid)
1504 if len(nl) > 0: 1506 if len(nl) > 0:
1505 if len(nl) == 1 and not maybewdir: 1507 if len(nl) == 1 and not maybewdir:
1506 self._pcache[id] = nl[0] 1508 self._pcache[id] = nl[0]
1507 return nl[0] 1509 return nl[0]
1508 raise error.AmbiguousPrefixLookupError( 1510 raise error.AmbiguousPrefixLookupError(
1558 if not getattr(self, 'filteredrevs', None): 1560 if not getattr(self, 'filteredrevs', None):
1559 try: 1561 try:
1560 length = max(self.index.shortest(node), minlength) 1562 length = max(self.index.shortest(node), minlength)
1561 return disambiguate(hexnode, length) 1563 return disambiguate(hexnode, length)
1562 except error.RevlogError: 1564 except error.RevlogError:
1563 if node != wdirid: 1565 if node != self.nodeconstants.wdirid:
1564 raise error.LookupError(node, self.indexfile, _(b'no node')) 1566 raise error.LookupError(node, self.indexfile, _(b'no node'))
1565 except AttributeError: 1567 except AttributeError:
1566 # Fall through to pure code 1568 # Fall through to pure code
1567 pass 1569 pass
1568 1570
1569 if node == wdirid: 1571 if node == self.nodeconstants.wdirid:
1570 for length in range(minlength, len(hexnode) + 1): 1572 for length in range(minlength, len(hexnode) + 1):
1571 prefix = hexnode[:length] 1573 prefix = hexnode[:length]
1572 if isvalid(prefix): 1574 if isvalid(prefix):
1573 return prefix 1575 return prefix
1574 1576
1879 else: 1881 else:
1880 node = nodeorrev 1882 node = nodeorrev
1881 rev = None 1883 rev = None
1882 1884
1883 # fast path the special `nullid` rev 1885 # fast path the special `nullid` rev
1884 if node == nullid: 1886 if node == self.nullid:
1885 return b"", {} 1887 return b"", {}
1886 1888
1887 # ``rawtext`` is the text as stored inside the revlog. Might be the 1889 # ``rawtext`` is the text as stored inside the revlog. Might be the
1888 # revision or might need to be processed to retrieve the revision. 1890 # revision or might need to be processed to retrieve the revision.
1889 rev, rawtext, validated = self._rawtext(node, rev, _df=_df) 1891 rev, rawtext, validated = self._rawtext(node, rev, _df=_df)
2300 2302
2301 invariants: 2303 invariants:
2302 - rawtext is optional (can be None); if not set, cachedelta must be set. 2304 - rawtext is optional (can be None); if not set, cachedelta must be set.
2303 if both are set, they must correspond to each other. 2305 if both are set, they must correspond to each other.
2304 """ 2306 """
2305 if node == nullid: 2307 if node == self.nullid:
2306 raise error.RevlogError( 2308 raise error.RevlogError(
2307 _(b"%s: attempt to add null revision") % self.indexfile 2309 _(b"%s: attempt to add null revision") % self.indexfile
2308 ) 2310 )
2309 if node == wdirid or node in wdirfilenodeids: 2311 if (
2312 node == self.nodeconstants.wdirid
2313 or node in self.nodeconstants.wdirfilenodeids
2314 ):
2310 raise error.RevlogError( 2315 raise error.RevlogError(
2311 _(b"%s: attempt to add wdir revision") % self.indexfile 2316 _(b"%s: attempt to add wdir revision") % self.indexfile
2312 ) 2317 )
2313 2318
2314 if self._inline: 2319 if self._inline: