Mercurial > hg
changeset 51781:a891347058e7
manifest: introduce a `read_delta_parents` method
This new method have a clearer semantic and can be used by code that need this
semantic. This should avoid bugs, allow for more targeted optimisation, and
provide a clearer API. Users will be updated in subsequent changesets.
This is also part of the wider effort to clarify and fix this API. one more
method coming.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 01 Aug 2024 13:10:09 +0200 |
parents | 852bd109dd55 |
children | 4704c4c79f21 |
files | mercurial/interfaces/repository.py mercurial/manifest.py |
diffstat | 2 files changed, 104 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/interfaces/repository.py Thu Aug 01 12:14:40 2024 +0200 +++ b/mercurial/interfaces/repository.py Thu Aug 01 13:10:09 2024 +0200 @@ -1210,6 +1210,20 @@ The returned object conforms to the ``imanifestdict`` interface. """ + def read_delta_parents(*, shallow=False, exact=True): + """return a diff from this revision against both parents. + + If `exact` is False, this might return a superset of the diff, containing + files that are actually present as is in one of the parents. + + If `shallow` is True, this will read the delta for this directory, + without recursively reading subdirectory manifests. Instead, any + subdirectory entry will be reported as it appears in the manifest, i.e. + the subdirectory will be reported among files and distinguished only by + its 't' flag. This only apply if the underlying manifest support it. + + The returned object conforms to the ``imanifestdict`` interface.""" + def readfast(shallow=False): """Calls either ``read()`` or ``readdelta()``.
--- a/mercurial/manifest.py Thu Aug 01 12:14:40 2024 +0200 +++ b/mercurial/manifest.py Thu Aug 01 13:10:09 2024 +0200 @@ -2283,6 +2283,40 @@ ) return (None, self.read()) + def read_delta_parents( + self, + *, + shallow: bool = False, + exact: bool = True, + ) -> ManifestDict: + """see `interface.imanifestrevisionbase` documentations""" + store = self._storage() + r = store.rev(self._node) + deltaparent = store.deltaparent(r) + parents = [p for p in store.parentrevs(r) if p is not nullrev] + if not exact and deltaparent in parents: + d = mdiff.patchtext(store.revdiff(store.deltaparent(r), r)) + return manifestdict(store.nodeconstants.nodelen, d) + elif not exact or len(parents) == 0: + return self.read() + elif len(parents) == 1: + p = parents[0] + d = mdiff.patchtext(store.revdiff(p, r)) + return manifestdict(store.nodeconstants.nodelen, d) + else: + p1, p2 = parents + d1 = mdiff.patchtext(store.revdiff(p1, r)) + d2 = mdiff.patchtext(store.revdiff(p2, r)) + d1 = manifestdict(store.nodeconstants.nodelen, d1) + d2 = manifestdict(store.nodeconstants.nodelen, d2) + md = manifestdict(store.nodeconstants.nodelen) + for f, new_node, new_flag in d1.iterentries(): + if f not in d2: + continue + if new_node is not None: + md.set(f, new_node, new_flag) + return md + def find(self, key: bytes) -> Tuple[bytes, bytes]: return self.read().find(key) @@ -2486,6 +2520,62 @@ md.setflag(f, fl1) return md + def read_delta_parents( + self, + *, + shallow: bool = False, + exact: bool = True, + ) -> AnyManifestDict: + """see `interface.imanifestrevisionbase` documentations""" + store = self._storage() + r = store.rev(self._node) + parents = [p for p in store.parentrevs(r) if p is not nullrev] + if not exact: + return self.read_any_fast_delta(parents, shallow=shallow)[1] + elif len(parents) == 0: + if shallow: + d = store.revision(self._node) + return manifestdict(store.nodeconstants.nodelen, d) + else: + return self.read() + elif len(parents) == 1: + p = parents[0] + if shallow: + d = mdiff.patchtext(store.revdiff(p, r)) + return manifestdict(store.nodeconstants.nodelen, d) + else: + return self._read_storage_slow_delta(base=p) + else: + p1, p2 = parents + if shallow: + d1 = mdiff.patchtext(store.revdiff(p1, r)) + d2 = mdiff.patchtext(store.revdiff(p2, r)) + d1 = manifestdict(store.nodeconstants.nodelen, d1) + d2 = manifestdict(store.nodeconstants.nodelen, d2) + md = manifestdict(store.nodeconstants.nodelen) + for f, new_node, new_flag in d1.iterentries(): + if f not in d2: + continue + if new_node is not None: + md.set(f, new_node, new_flag) + return md + else: + m1 = self._manifestlog.get(self._dir, store.node(p1)).read() + m2 = self._manifestlog.get(self._dir, store.node(p2)).read() + mc = self.read() + d1 = m1.diff(mc) + d2 = m2.diff(mc) + md = treemanifest( + self._manifestlog.nodeconstants, + dir=self._dir, + ) + for f, new_node, new_flag in d1.iterentries(): + if f not in d2: + continue + if new_node is not None: + md.set(f, new_node, new_flag) + return md + def readfast(self, shallow=False) -> AnyManifestDict: """Calls either readdelta or read, based on which would be less work. readdelta is called if the delta is against the p1, and therefore can be