mercurial/revlog.py
changeset 47012 d55b71393907
parent 46974 3c9208702db3
child 47034 0d8ff1f4ab0c
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: