mercurial/manifest.py
changeset 47043 12450fbea288
parent 47012 d55b71393907
child 47072 4c041c71ec01
equal deleted inserted replaced
47042:c5e1cc0b4c77 47043:12450fbea288
    40 
    40 
    41 # Allow tests to more easily test the alternate path in manifestdict.fastdelta()
    41 # Allow tests to more easily test the alternate path in manifestdict.fastdelta()
    42 FASTDELTA_TEXTDIFF_THRESHOLD = 1000
    42 FASTDELTA_TEXTDIFF_THRESHOLD = 1000
    43 
    43 
    44 
    44 
    45 def _parse(data):
    45 def _parse(nodelen, data):
    46     # This method does a little bit of excessive-looking
    46     # This method does a little bit of excessive-looking
    47     # precondition checking. This is so that the behavior of this
    47     # precondition checking. This is so that the behavior of this
    48     # class exactly matches its C counterpart to try and help
    48     # class exactly matches its C counterpart to try and help
    49     # prevent surprise breakage for anyone that develops against
    49     # prevent surprise breakage for anyone that develops against
    50     # the pure version.
    50     # the pure version.
    61         if flags in _manifestflags:
    61         if flags in _manifestflags:
    62             n = n[:-1]
    62             n = n[:-1]
    63             nl -= 1
    63             nl -= 1
    64         else:
    64         else:
    65             flags = b''
    65             flags = b''
    66         if nl not in (40, 64):
    66         if nl != 2 * nodelen:
    67             raise ValueError(b'Invalid manifest line')
    67             raise ValueError(b'Invalid manifest line')
    68 
    68 
    69         yield f, bin(n), flags
    69         yield f, bin(n), flags
    70 
    70 
    71 
    71 
   129         if flags in _manifestflags:
   129         if flags in _manifestflags:
   130             hlen = nlpos - zeropos - 2
   130             hlen = nlpos - zeropos - 2
   131         else:
   131         else:
   132             hlen = nlpos - zeropos - 1
   132             hlen = nlpos - zeropos - 1
   133             flags = b''
   133             flags = b''
   134         if hlen not in (40, 64):
   134         if hlen != 2 * self.lm._nodelen:
   135             raise error.StorageError(b'Invalid manifest line')
   135             raise error.StorageError(b'Invalid manifest line')
   136         hashval = unhexlify(
   136         hashval = unhexlify(
   137             data, self.lm.extrainfo[self.pos], zeropos + 1, hlen
   137             data, self.lm.extrainfo[self.pos], zeropos + 1, hlen
   138         )
   138         )
   139         self.pos += 1
   139         self.pos += 1
   174     modified since the manifest was created or compacted.
   174     modified since the manifest was created or compacted.
   175     """
   175     """
   176 
   176 
   177     def __init__(
   177     def __init__(
   178         self,
   178         self,
       
   179         nodelen,
   179         data,
   180         data,
   180         positions=None,
   181         positions=None,
   181         extrainfo=None,
   182         extrainfo=None,
   182         extradata=None,
   183         extradata=None,
   183         hasremovals=False,
   184         hasremovals=False,
   184     ):
   185     ):
       
   186         self._nodelen = nodelen
   185         if positions is None:
   187         if positions is None:
   186             self.positions = self.findlines(data)
   188             self.positions = self.findlines(data)
   187             self.extrainfo = [0] * len(self.positions)
   189             self.extrainfo = [0] * len(self.positions)
   188             self.data = data
   190             self.data = data
   189             self.extradata = []
   191             self.extradata = []
   286         flags = data[nlpos - 1 : nlpos]
   288         flags = data[nlpos - 1 : nlpos]
   287         if flags in _manifestflags:
   289         if flags in _manifestflags:
   288             hlen -= 1
   290             hlen -= 1
   289         else:
   291         else:
   290             flags = b''
   292             flags = b''
   291         if hlen not in (40, 64):
   293         if hlen != 2 * self._nodelen:
   292             raise error.StorageError(b'Invalid manifest line')
   294             raise error.StorageError(b'Invalid manifest line')
   293         hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, hlen)
   295         hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, hlen)
   294         return (hashval, flags)
   296         return (hashval, flags)
   295 
   297 
   296     def __delitem__(self, key):
   298     def __delitem__(self, key):
   342             )
   344             )
   343 
   345 
   344     def copy(self):
   346     def copy(self):
   345         # XXX call _compact like in C?
   347         # XXX call _compact like in C?
   346         return _lazymanifest(
   348         return _lazymanifest(
       
   349             self._nodelen,
   347             self.data,
   350             self.data,
   348             self.positions,
   351             self.positions,
   349             self.extrainfo,
   352             self.extrainfo,
   350             self.extradata,
   353             self.extradata,
   351             self.hasremovals,
   354             self.hasremovals,
   452     def __len__(self):
   455     def __len__(self):
   453         return len(self.positions)
   456         return len(self.positions)
   454 
   457 
   455     def filtercopy(self, filterfn):
   458     def filtercopy(self, filterfn):
   456         # XXX should be optimized
   459         # XXX should be optimized
   457         c = _lazymanifest(b'')
   460         c = _lazymanifest(self._nodelen, b'')
   458         for f, n, fl in self.iterentries():
   461         for f, n, fl in self.iterentries():
   459             if filterfn(f):
   462             if filterfn(f):
   460                 c[f] = n, fl
   463                 c[f] = n, fl
   461         return c
   464         return c
   462 
   465 
   467     pass
   470     pass
   468 
   471 
   469 
   472 
   470 @interfaceutil.implementer(repository.imanifestdict)
   473 @interfaceutil.implementer(repository.imanifestdict)
   471 class manifestdict(object):
   474 class manifestdict(object):
   472     def __init__(self, data=b''):
   475     def __init__(self, nodelen, data=b''):
   473         self._lm = _lazymanifest(data)
   476         self._nodelen = nodelen
       
   477         self._lm = _lazymanifest(nodelen, data)
   474 
   478 
   475     def __getitem__(self, key):
   479     def __getitem__(self, key):
   476         return self._lm[key][0]
   480         return self._lm[key][0]
   477 
   481 
   478     def find(self, key):
   482     def find(self, key):
   576         '''generate a new manifest filtered by the match argument'''
   580         '''generate a new manifest filtered by the match argument'''
   577         if match.always():
   581         if match.always():
   578             return self.copy()
   582             return self.copy()
   579 
   583 
   580         if self._filesfastpath(match):
   584         if self._filesfastpath(match):
   581             m = manifestdict()
   585             m = manifestdict(self._nodelen)
   582             lm = self._lm
   586             lm = self._lm
   583             for fn in match.files():
   587             for fn in match.files():
   584                 if fn in lm:
   588                 if fn in lm:
   585                     m._lm[fn] = lm[fn]
   589                     m._lm[fn] = lm[fn]
   586             return m
   590             return m
   587 
   591 
   588         m = manifestdict()
   592         m = manifestdict(self._nodelen)
   589         m._lm = self._lm.filtercopy(match)
   593         m._lm = self._lm.filtercopy(match)
   590         return m
   594         return m
   591 
   595 
   592     def diff(self, m2, match=None, clean=False):
   596     def diff(self, m2, match=None, clean=False):
   593         """Finds changes between the current manifest and m2.
   597         """Finds changes between the current manifest and m2.
   626             return self._lm[key][1]
   630             return self._lm[key][1]
   627         except KeyError:
   631         except KeyError:
   628             return b''
   632             return b''
   629 
   633 
   630     def copy(self):
   634     def copy(self):
   631         c = manifestdict()
   635         c = manifestdict(self._nodelen)
   632         c._lm = self._lm.copy()
   636         c._lm = self._lm.copy()
   633         return c
   637         return c
   634 
   638 
   635     def items(self):
   639     def items(self):
   636         return (x[:2] for x in self._lm.iterentries())
   640         return (x[:2] for x in self._lm.iterentries())
   793 class treemanifest(object):
   797 class treemanifest(object):
   794     def __init__(self, nodeconstants, dir=b'', text=b''):
   798     def __init__(self, nodeconstants, dir=b'', text=b''):
   795         self._dir = dir
   799         self._dir = dir
   796         self.nodeconstants = nodeconstants
   800         self.nodeconstants = nodeconstants
   797         self._node = self.nodeconstants.nullid
   801         self._node = self.nodeconstants.nullid
       
   802         self._nodelen = self.nodeconstants.nodelen
   798         self._loadfunc = _noop
   803         self._loadfunc = _noop
   799         self._copyfunc = _noop
   804         self._copyfunc = _noop
   800         self._dirty = False
   805         self._dirty = False
   801         self._dirs = {}
   806         self._dirs = {}
   802         self._lazydirs = {}
   807         self._lazydirs = {}
  1320     def unmodifiedsince(self, m2):
  1325     def unmodifiedsince(self, m2):
  1321         return not self._dirty and not m2._dirty and self._node == m2._node
  1326         return not self._dirty and not m2._dirty and self._node == m2._node
  1322 
  1327 
  1323     def parse(self, text, readsubtree):
  1328     def parse(self, text, readsubtree):
  1324         selflazy = self._lazydirs
  1329         selflazy = self._lazydirs
  1325         for f, n, fl in _parse(text):
  1330         for f, n, fl in _parse(self._nodelen, text):
  1326             if fl == b't':
  1331             if fl == b't':
  1327                 f = f + b'/'
  1332                 f = f + b'/'
  1328                 # False below means "doesn't need to be copied" and can use the
  1333                 # False below means "doesn't need to be copied" and can use the
  1329                 # cached value from readsubtree directly.
  1334                 # cached value from readsubtree directly.
  1330                 selflazy[f] = (n, readsubtree, False)
  1335                 selflazy[f] = (n, readsubtree, False)
  2017 
  2022 
  2018 @interfaceutil.implementer(repository.imanifestrevisionwritable)
  2023 @interfaceutil.implementer(repository.imanifestrevisionwritable)
  2019 class memmanifestctx(object):
  2024 class memmanifestctx(object):
  2020     def __init__(self, manifestlog):
  2025     def __init__(self, manifestlog):
  2021         self._manifestlog = manifestlog
  2026         self._manifestlog = manifestlog
  2022         self._manifestdict = manifestdict()
  2027         self._manifestdict = manifestdict(manifestlog.nodeconstants.nodelen)
  2023 
  2028 
  2024     def _storage(self):
  2029     def _storage(self):
  2025         return self._manifestlog.getstorage(b'')
  2030         return self._manifestlog.getstorage(b'')
  2026 
  2031 
  2027     def copy(self):
  2032     def copy(self):
  2079     def parents(self):
  2084     def parents(self):
  2080         return self._storage().parents(self._node)
  2085         return self._storage().parents(self._node)
  2081 
  2086 
  2082     def read(self):
  2087     def read(self):
  2083         if self._data is None:
  2088         if self._data is None:
  2084             if self._node == self._manifestlog.nodeconstants.nullid:
  2089             nc = self._manifestlog.nodeconstants
  2085                 self._data = manifestdict()
  2090             if self._node == nc.nullid:
       
  2091                 self._data = manifestdict(nc.nodelen)
  2086             else:
  2092             else:
  2087                 store = self._storage()
  2093                 store = self._storage()
  2088                 if self._node in store.fulltextcache:
  2094                 if self._node in store.fulltextcache:
  2089                     text = pycompat.bytestr(store.fulltextcache[self._node])
  2095                     text = pycompat.bytestr(store.fulltextcache[self._node])
  2090                 else:
  2096                 else:
  2091                     text = store.revision(self._node)
  2097                     text = store.revision(self._node)
  2092                     arraytext = bytearray(text)
  2098                     arraytext = bytearray(text)
  2093                     store.fulltextcache[self._node] = arraytext
  2099                     store.fulltextcache[self._node] = arraytext
  2094                 self._data = manifestdict(text)
  2100                 self._data = manifestdict(nc.nodelen, text)
  2095         return self._data
  2101         return self._data
  2096 
  2102 
  2097     def readfast(self, shallow=False):
  2103     def readfast(self, shallow=False):
  2098         """Calls either readdelta or read, based on which would be less work.
  2104         """Calls either readdelta or read, based on which would be less work.
  2099         readdelta is called if the delta is against the p1, and therefore can be
  2105         readdelta is called if the delta is against the p1, and therefore can be
  2116         Changing the value of `shallow` has no effect on flat manifests.
  2122         Changing the value of `shallow` has no effect on flat manifests.
  2117         """
  2123         """
  2118         store = self._storage()
  2124         store = self._storage()
  2119         r = store.rev(self._node)
  2125         r = store.rev(self._node)
  2120         d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
  2126         d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
  2121         return manifestdict(d)
  2127         return manifestdict(store.nodeconstants.nodelen, d)
  2122 
  2128 
  2123     def find(self, key):
  2129     def find(self, key):
  2124         return self.read().find(key)
  2130         return self.read().find(key)
  2125 
  2131 
  2126 
  2132 
  2242         """
  2248         """
  2243         store = self._storage()
  2249         store = self._storage()
  2244         if shallow:
  2250         if shallow:
  2245             r = store.rev(self._node)
  2251             r = store.rev(self._node)
  2246             d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
  2252             d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
  2247             return manifestdict(d)
  2253             return manifestdict(store.nodeconstants.nodelen, d)
  2248         else:
  2254         else:
  2249             # Need to perform a slow delta
  2255             # Need to perform a slow delta
  2250             r0 = store.deltaparent(store.rev(self._node))
  2256             r0 = store.deltaparent(store.rev(self._node))
  2251             m0 = self._manifestlog.get(self._dir, store.node(r0)).read()
  2257             m0 = self._manifestlog.get(self._dir, store.node(r0)).read()
  2252             m1 = self.read()
  2258             m1 = self.read()
  2271         deltaparent = store.deltaparent(r)
  2277         deltaparent = store.deltaparent(r)
  2272         if deltaparent != nullrev and deltaparent in store.parentrevs(r):
  2278         if deltaparent != nullrev and deltaparent in store.parentrevs(r):
  2273             return self.readdelta(shallow=shallow)
  2279             return self.readdelta(shallow=shallow)
  2274 
  2280 
  2275         if shallow:
  2281         if shallow:
  2276             return manifestdict(store.revision(self._node))
  2282             return manifestdict(
       
  2283                 store.nodeconstants.nodelen, store.revision(self._node)
       
  2284             )
  2277         else:
  2285         else:
  2278             return self.read()
  2286             return self.read()
  2279 
  2287 
  2280     def find(self, key):
  2288     def find(self, key):
  2281         return self.read().find(key)
  2289         return self.read().find(key)