D4803: storageutil: extract most of emitrevisions() to standalone function

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Wed Oct 3 11:05:56 EDT 2018


This revision was automatically updated to reflect the committed changes.
Closed by commit rHG842ffcf1d42f: storageutil: extract most of emitrevisions() to standalone function (authored by indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4803?vs=11486&id=11617

REVISION DETAIL
  https://phab.mercurial-scm.org/D4803

AFFECTED FILES
  mercurial/revlog.py
  mercurial/utils/storageutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/storageutil.py b/mercurial/utils/storageutil.py
--- a/mercurial/utils/storageutil.py
+++ b/mercurial/utils/storageutil.py
@@ -262,3 +262,149 @@
                     futurelargelinkrevs.add(plinkrev)
 
     return strippoint, brokenrevs
+
+def emitrevisions(store, revs, resultcls, deltaparentfn, candeltafn,
+                  rawsizefn, revdifffn, flagsfn, sendfulltext=False,
+                  revisiondata=False, assumehaveparentrevisions=False,
+                  deltaprevious=False):
+    """Generic implementation of ifiledata.emitrevisions().
+
+    Emitting revision data is subtly complex. This function attempts to
+    encapsulate all the logic for doing so in a backend-agnostic way.
+
+    ``store``
+       Object conforming to ``ifilestorage`` interface.
+
+    ``revs``
+       List of integer revision numbers whose data to emit.
+
+    ``resultcls``
+       A type implementing the ``irevisiondelta`` interface that will be
+       constructed and returned.
+
+    ``deltaparentfn``
+       Callable receiving a revision number and returning the revision number
+       of a revision that the internal delta is stored against. This delta
+       will be preferred over computing a new arbitrary delta.
+
+    ``candeltafn``
+       Callable receiving a pair of revision numbers that returns a bool
+       indicating whether a delta between them can be produced.
+
+    ``rawsizefn``
+       Callable receiving a revision number and returning the length of the
+       ``store.revision(rev, raw=True)``.
+
+    ``revdifffn``
+       Callable receiving a pair of revision numbers that returns a delta
+       between them.
+
+    ``flagsfn``
+       Callable receiving a revision number and returns the integer flags
+       value for it.
+
+    ``sendfulltext``
+       Whether to send fulltext revisions instead of deltas, if allowed.
+
+    ``revisiondata``
+    ``assumehaveparentrevisions``
+    ``deltaprevious``
+       See ``ifiledata.emitrevisions()`` interface documentation.
+    """
+
+    fnode = store.node
+
+    prevrev = None
+
+    if deltaprevious or assumehaveparentrevisions:
+        prevrev = store.parentrevs(revs[0])[0]
+
+    # Set of revs available to delta against.
+    available = set()
+
+    for rev in revs:
+        if rev == nullrev:
+            continue
+
+        node = fnode(rev)
+        deltaparentrev = deltaparentfn(rev)
+        p1rev, p2rev = store.parentrevs(rev)
+
+        # Forced delta against previous mode.
+        if deltaprevious:
+            baserev = prevrev
+
+        # We're instructed to send fulltext. Honor that.
+        elif sendfulltext:
+            baserev = nullrev
+
+        # There is a delta in storage. We try to use that because it
+        # amounts to effectively copying data from storage and is
+        # therefore the fastest.
+        elif deltaparentrev != nullrev:
+            # Base revision was already emitted in this group. We can
+            # always safely use the delta.
+            if deltaparentrev in available:
+                baserev = deltaparentrev
+
+            # Base revision is a parent that hasn't been emitted already.
+            # Use it if we can assume the receiver has the parent revision.
+            elif (assumehaveparentrevisions
+                  and deltaparentrev in (p1rev, p2rev)):
+                baserev = deltaparentrev
+
+            # No guarantee the receiver has the delta parent. Send delta
+            # against last revision (if possible), which in the common case
+            # should be similar enough to this revision that the delta is
+            # reasonable.
+            elif prevrev is not None:
+                baserev = prevrev
+            else:
+                baserev = nullrev
+
+        # Storage has a fulltext revision.
+
+        # Let's use the previous revision, which is as good a guess as any.
+        # There is definitely room to improve this logic.
+        elif prevrev is not None:
+            baserev = prevrev
+        else:
+            baserev = nullrev
+
+        # But we can't actually use our chosen delta base for whatever
+        # reason. Reset to fulltext.
+        if baserev != nullrev and not candeltafn(baserev, rev):
+            baserev = nullrev
+
+        revision = None
+        delta = None
+        baserevisionsize = None
+
+        if revisiondata:
+            if store.iscensored(baserev) or store.iscensored(rev):
+                try:
+                    revision = store.revision(node, raw=True)
+                except error.CensoredNodeError as e:
+                    revision = e.tombstone
+
+                if baserev != nullrev:
+                    baserevisionsize = rawsizefn(baserev)
+
+            elif baserev == nullrev and not deltaprevious:
+                revision = store.revision(node, raw=True)
+                available.add(rev)
+            else:
+                delta = revdifffn(baserev, rev)
+                available.add(rev)
+
+        yield resultcls(
+            node=node,
+            p1node=fnode(p1rev),
+            p2node=fnode(p2rev),
+            basenode=fnode(baserev),
+            flags=flagsfn(rev),
+            baserevisionsize=baserevisionsize,
+            revision=revision,
+            delta=delta)
+
+        prevrev = rev
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -2193,7 +2193,6 @@
             nodesorder = 'storage'
 
         frev = self.rev
-        fnode = self.node
 
         if nodesorder == 'nodes':
             revs = [frev(n) for n in nodes]
@@ -2204,100 +2203,17 @@
             revs = set(frev(n) for n in nodes)
             revs = dagop.linearize(revs, self.parentrevs)
 
-        prevrev = None
-
-        if deltaprevious or assumehaveparentrevisions:
-            prevrev = self.parentrevs(revs[0])[0]
-
-        # Set of revs available to delta against.
-        available = set()
-
-        for rev in revs:
-            if rev == nullrev:
-                continue
-
-            node = fnode(rev)
-            deltaparentrev = self.deltaparent(rev)
-            p1rev, p2rev = self.parentrevs(rev)
-
-            # Forced delta against previous mode.
-            if deltaprevious:
-                baserev = prevrev
-
-            # Revlog is configured to use full snapshots. Stick to that.
-            elif not self._storedeltachains:
-                baserev = nullrev
-
-            # There is a delta in storage. We try to use that because it
-            # amounts to effectively copying data from storage and is
-            # therefore the fastest.
-            elif deltaparentrev != nullrev:
-                # Base revision was already emitted in this group. We can
-                # always safely use the delta.
-                if deltaparentrev in available:
-                    baserev = deltaparentrev
-
-                # Base revision is a parent that hasn't been emitted already.
-                # Use it if we can assume the receiver has the parent revision.
-                elif (assumehaveparentrevisions
-                      and deltaparentrev in (p1rev, p2rev)):
-                    baserev = deltaparentrev
-
-                # No guarantee the receiver has the delta parent. Send delta
-                # against last revision (if possible), which in the common case
-                # should be similar enough to this revision that the delta is
-                # reasonable.
-                elif prevrev is not None:
-                    baserev = prevrev
-                else:
-                    baserev = nullrev
-
-            # Storage has a fulltext revision.
-
-            # Let's use the previous revision, which is as good a guess as any.
-            # There is definitely room to improve this logic.
-            elif prevrev is not None:
-                baserev = prevrev
-            else:
-                baserev = nullrev
-
-            # But we can't actually use our chosen delta base for whatever
-            # reason. Reset to fulltext.
-            if baserev != nullrev and not self.candelta(baserev, rev):
-                baserev = nullrev
-
-            revision = None
-            delta = None
-            baserevisionsize = None
-
-            if revisiondata:
-                if self.iscensored(baserev) or self.iscensored(rev):
-                    try:
-                        revision = self.revision(node, raw=True)
-                    except error.CensoredNodeError as e:
-                        revision = e.tombstone
-
-                    if baserev != nullrev:
-                        baserevisionsize = self.rawsize(baserev)
-
-                elif baserev == nullrev and not deltaprevious:
-                    revision = self.revision(node, raw=True)
-                    available.add(rev)
-                else:
-                    delta = self.revdiff(baserev, rev)
-                    available.add(rev)
-
-            yield revlogrevisiondelta(
-                node=node,
-                p1node=fnode(p1rev),
-                p2node=fnode(p2rev),
-                basenode=fnode(baserev),
-                flags=self.flags(rev),
-                baserevisionsize=baserevisionsize,
-                revision=revision,
-                delta=delta)
-
-            prevrev = rev
+        return storageutil.emitrevisions(
+            self, revs, revlogrevisiondelta,
+            deltaparentfn=self.deltaparent,
+            candeltafn=self.candelta,
+            rawsizefn=self.rawsize,
+            revdifffn=self.revdiff,
+            flagsfn=self.flags,
+            sendfulltext=not self._storedeltachains,
+            revisiondata=revisiondata,
+            assumehaveparentrevisions=assumehaveparentrevisions,
+            deltaprevious=deltaprevious)
 
     DELTAREUSEALWAYS = 'always'
     DELTAREUSESAMEREVS = 'samerevs'



To: indygreg, #hg-reviewers, durin42
Cc: durin42, mercurial-devel


More information about the Mercurial-devel mailing list