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. |
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 |
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): |
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. |
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) |