##// END OF EJS Templates
manifest: introduce a `read_any_fast_delta` method...
marmoute -
r52668:ca420871 default
parent child Browse files
Show More
@@ -1175,8 +1175,37 b' class imanifestrevisionstored(imanifestr'
1175 def readdelta(shallow=False):
1175 def readdelta(shallow=False):
1176 """Obtain the manifest data structure representing changes from parent.
1176 """Obtain the manifest data structure representing changes from parent.
1177
1177
1178 This manifest is compared to its 1st parent. A new manifest representing
1178 This manifest is compared to its 1st parent. A new manifest
1179 those differences is constructed.
1179 representing those differences is constructed.
1180
1181 If `shallow` is True, this will read the delta for this directory,
1182 without recursively reading subdirectory manifests. Instead, any
1183 subdirectory entry will be reported as it appears in the manifest, i.e.
1184 the subdirectory will be reported among files and distinguished only by
1185 its 't' flag. This only apply if the underlying manifest support it.
1186
1187 The returned object conforms to the ``imanifestdict`` interface.
1188 """
1189
1190 def read_any_fast_delta(valid_bases, *, shallow=False):
1191 """read some manifest information as fast if possible
1192
1193 This might return a "delta", a manifest object containing only file
1194 changed compared to another revisions. The `valid_bases` argument
1195 control the set of revision that might be used as a base.
1196
1197 If no delta can be retrieved quickly, a full read of the manifest will
1198 be performed instead.
1199
1200 The function return a tuple with two elements. The first one is the
1201 delta base used (or None if we did a full read), the second one is the
1202 manifest information.
1203
1204 If `shallow` is True, this will read the delta for this directory,
1205 without recursively reading subdirectory manifests. Instead, any
1206 subdirectory entry will be reported as it appears in the manifest, i.e.
1207 the subdirectory will be reported among files and distinguished only by
1208 its 't' flag. This only apply if the underlying manifest support it.
1180
1209
1181 The returned object conforms to the ``imanifestdict`` interface.
1210 The returned object conforms to the ``imanifestdict`` interface.
1182 """
1211 """
@@ -14,6 +14,7 b' import weakref'
14 from typing import (
14 from typing import (
15 ByteString,
15 ByteString,
16 Callable,
16 Callable,
17 Collection,
17 Dict,
18 Dict,
18 Iterable,
19 Iterable,
19 Iterator,
20 Iterator,
@@ -2261,6 +2262,24 b' class ManifestCtx:'
2261 d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
2262 d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
2262 return manifestdict(store.nodeconstants.nodelen, d)
2263 return manifestdict(store.nodeconstants.nodelen, d)
2263
2264
2265 def read_any_fast_delta(
2266 self,
2267 valid_bases: Collection[int],
2268 *,
2269 shallow: bool = False,
2270 ) -> Tuple[Optional[int], ManifestDict]:
2271 """see `imanifestrevisionstored` documentation"""
2272 store = self._storage()
2273 r = store.rev(self._node)
2274 deltaparent = store.deltaparent(r)
2275 if deltaparent != nullrev and deltaparent in valid_bases:
2276 d = mdiff.patchtext(store.revdiff(deltaparent, r))
2277 return (
2278 deltaparent,
2279 manifestdict(store.nodeconstants.nodelen, d),
2280 )
2281 return (None, self.read())
2282
2264 def find(self, key: bytes) -> Tuple[bytes, bytes]:
2283 def find(self, key: bytes) -> Tuple[bytes, bytes]:
2265 return self.read().find(key)
2284 return self.read().find(key)
2266
2285
@@ -2379,16 +2398,7 b' class TreeManifestCtx:'
2379 return self._storage().parents(self._node)
2398 return self._storage().parents(self._node)
2380
2399
2381 def readdelta(self, shallow: bool = False) -> AnyManifestDict:
2400 def readdelta(self, shallow: bool = False) -> AnyManifestDict:
2382 """Returns a manifest containing just the entries that are present
2401 """see `imanifestrevisionstored` documentation"""
2383 in this manifest, but not in its p1 manifest. This is efficient to read
2384 if the revlog delta is already p1.
2385
2386 If `shallow` is True, this will read the delta for this directory,
2387 without recursively reading subdirectory manifests. Instead, any
2388 subdirectory entry will be reported as it appears in the manifest, i.e.
2389 the subdirectory will be reported among files and distinguished only by
2390 its 't' flag.
2391 """
2392 store = self._storage()
2402 store = self._storage()
2393 if shallow:
2403 if shallow:
2394 r = store.rev(self._node)
2404 r = store.rev(self._node)
@@ -2407,6 +2417,69 b' class TreeManifestCtx:'
2407 md.setflag(f, fl1)
2417 md.setflag(f, fl1)
2408 return md
2418 return md
2409
2419
2420 def read_any_fast_delta(
2421 self,
2422 valid_bases: Collection[int],
2423 *,
2424 shallow: bool = False,
2425 ) -> Tuple[Optional[int], AnyManifestDict]:
2426 """see `imanifestrevisionstored` documentation"""
2427 store = self._storage()
2428 r = store.rev(self._node)
2429 deltaparent = store.deltaparent(r)
2430
2431 can_use_delta = deltaparent != nullrev and deltaparent in valid_bases
2432
2433 if shallow:
2434 if can_use_delta:
2435 return (deltaparent, self._read_storage_delta_shallow())
2436 else:
2437 d = store.revision(self._node)
2438 return (None, manifestdict(store.nodeconstants.nodelen, d))
2439 else:
2440 # note: This use "slow_delta" here is cargo culted from the previous
2441 # implementation. I am not sure it make sense since the goal here is to
2442 # be fast, so why are we computing a delta? On the other hand, tree
2443 # manifest delta as fairly "cheap" and allow for skipping whole part of
2444 # the tree that a full read would access. So it might be a good idea.
2445 #
2446 # If we realize we don't need delta here, we should simply use:
2447 #
2448 # return (None, self.read())
2449 if can_use_delta:
2450 return (None, self._read_storage_slow_delta(base=deltaparent))
2451 else:
2452 parents = [
2453 p
2454 for p in store.parentrevs(r)
2455 if p is not nullrev and p in valid_bases
2456 ]
2457 if parents:
2458 best_base = max(parents)
2459 else:
2460 best_base = max(valid_bases)
2461 return (None, self._read_storage_slow_delta(base=best_base))
2462
2463 def _read_storage_delta_shallow(self) -> ManifestDict:
2464 store = self._storage()
2465 r = store.rev(self._node)
2466 d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r))
2467 return manifestdict(store.nodeconstants.nodelen, d)
2468
2469 def _read_storage_slow_delta(self, base) -> 'TreeManifest':
2470 store = self._storage()
2471 if base is None:
2472 base = store.deltaparent(store.rev(self._node))
2473 m0 = self._manifestlog.get(self._dir, store.node(base)).read()
2474 m1 = self.read()
2475 md = treemanifest(self._manifestlog.nodeconstants, dir=self._dir)
2476 for f, ((n0, fl0), (n1, fl1)) in m0.diff(m1).items():
2477 if n1:
2478 md[f] = n1
2479 if fl1:
2480 md.setflag(f, fl1)
2481 return md
2482
2410 def readfast(self, shallow=False) -> AnyManifestDict:
2483 def readfast(self, shallow=False) -> AnyManifestDict:
2411 """Calls either readdelta or read, based on which would be less work.
2484 """Calls either readdelta or read, based on which would be less work.
2412 readdelta is called if the delta is against the p1, and therefore can be
2485 readdelta is called if the delta is against the p1, and therefore can be
General Comments 0
You need to be logged in to leave comments. Login now