changegroup: refactor emitrevision to use a `deltamode` argument
authorBoris Feld <boris.feld@octobus.net>
Tue, 09 Oct 2018 22:02:01 +0200
changeset 53154 59a870a4ad6ee47266990f97bc57a4b8a28b42ae
parent 53153 5e5c8f2a1eb5f050a7d13b6f1b6a21fbc2fd1b65
child 53155 6a917075535aa9648a8aecb951d08e51c9159b4b
push id1065
push usergszorc@mozilla.com
push dateWed, 31 Oct 2018 02:06:22 +0000
changegroup: refactor emitrevision to use a `deltamode` argument This new argument gathers the semantic of `sendfulltext` and `deltaprevious` in a single value. We are about to introduce a new type of constraints. Avoiding yet another argument sounds like a plus.
mercurial/repository.py
mercurial/revlog.py
mercurial/utils/storageutil.py
--- a/mercurial/repository.py
+++ b/mercurial/repository.py
@@ -34,16 +34,20 @@ REPO_FEATURE_SHALLOW_FILE_STORAGE = b'sh
 
 REVISION_FLAG_CENSORED = 1 << 15
 REVISION_FLAG_ELLIPSIS = 1 << 14
 REVISION_FLAG_EXTSTORED = 1 << 13
 
 REVISION_FLAGS_KNOWN = (
     REVISION_FLAG_CENSORED | REVISION_FLAG_ELLIPSIS | REVISION_FLAG_EXTSTORED)
 
+CG_DELTAMODE_STD = b'default'
+CG_DELTAMODE_PREV = b'previous'
+CG_DELTAMODE_FULL = b'fulltext'
+
 class ipeerconnection(interfaceutil.Interface):
     """Represents a "connection" to a repository.
 
     This is the base interface for representing a connection to a repository.
     It holds basic properties and methods applicable to all peer types.
 
     This is not a complete interface definition and should not be used
     outside of this module.
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -2208,27 +2208,32 @@ class revlog(object):
                       assumehaveparentrevisions=False, deltaprevious=False):
         if nodesorder not in ('nodes', 'storage', None):
             raise error.ProgrammingError('unhandled value for nodesorder: %s' %
                                          nodesorder)
 
         if nodesorder is None and not self._generaldelta:
             nodesorder = 'storage'
 
+        deltamode = repository.CG_DELTAMODE_STD
+        if deltaprevious:
+            deltamode = repository.CG_DELTAMODE_PREV
+        elif not self._storedeltachains:
+            deltamode = repository.CG_DELTAMODE_FULL
+
         return storageutil.emitrevisions(
             self, nodes, nodesorder, revlogrevisiondelta,
             deltaparentfn=self.deltaparent,
             candeltafn=self.candelta,
             rawsizefn=self.rawsize,
             revdifffn=self.revdiff,
             flagsfn=self.flags,
-            sendfulltext=not self._storedeltachains,
+            deltamode=deltamode,
             revisiondata=revisiondata,
-            assumehaveparentrevisions=assumehaveparentrevisions,
-            deltaprevious=deltaprevious)
+            assumehaveparentrevisions=assumehaveparentrevisions)
 
     DELTAREUSEALWAYS = 'always'
     DELTAREUSESAMEREVS = 'samerevs'
     DELTAREUSENEVER = 'never'
 
     DELTAREUSEFULLADD = 'fulladd'
 
     DELTAREUSEALL = {'always', 'samerevs', 'never', 'fulladd'}
--- a/mercurial/utils/storageutil.py
+++ b/mercurial/utils/storageutil.py
@@ -17,16 +17,17 @@ from ..node import (
     nullid,
     nullrev,
 )
 from .. import (
     dagop,
     error,
     mdiff,
     pycompat,
+    repository,
 )
 
 _nullhash = hashlib.sha1(nullid)
 
 def hashrevisionsha1(text, p1, p2):
     """Compute the SHA-1 for revision data and its parents.
 
     This hash combines both the current file contents and its history
@@ -264,19 +265,18 @@ def resolvestripinfo(minlinkrev, tiprev,
                 heads[p] = plinkrev
                 if plinkrev >= minlinkrev:
                     futurelargelinkrevs.add(plinkrev)
 
     return strippoint, brokenrevs
 
 def emitrevisions(store, nodes, nodesorder, resultcls, deltaparentfn=None,
                   candeltafn=None, rawsizefn=None, revdifffn=None, flagsfn=None,
-                  sendfulltext=False,
-                  revisiondata=False, assumehaveparentrevisions=False,
-                  deltaprevious=False):
+                  deltamode=repository.CG_DELTAMODE_STD,
+                  revisiondata=False, assumehaveparentrevisions=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.
 
@@ -317,40 +317,43 @@ def emitrevisions(store, nodes, nodesord
 
        Defining this function allows a precomputed or stored delta to be
        used without having to compute on.
 
     ``flagsfn`` (optional)
        Callable receiving a revision number and returns the integer flags
        value for it. If not defined, flags value will be 0.
 
-    ``sendfulltext``
+    ``deltamode``
+       constaint on delta to be sent:
+       * CG_DELTAMODE_STD  - normal mode, try to reuse storage deltas,
+       * CG_DELTAMODE_PREV - only delta against "prev",
+       * CG_DELTAMODE_FULL - only issue full snapshot.
+
        Whether to send fulltext revisions instead of deltas, if allowed.
 
     ``nodesorder``
     ``revisiondata``
     ``assumehaveparentrevisions``
-    ``deltaprevious``
-       See ``ifiledata.emitrevisions()`` interface documentation.
     """
 
     fnode = store.node
     frev = store.rev
 
     if nodesorder == 'nodes':
         revs = [frev(n) for n in nodes]
     elif nodesorder == 'storage':
         revs = sorted(frev(n) for n in nodes)
     else:
         revs = set(frev(n) for n in nodes)
         revs = dagop.linearize(revs, store.parentrevs)
 
     prevrev = None
 
-    if deltaprevious or assumehaveparentrevisions:
+    if deltamode == repository.CG_DELTAMODE_PREV 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
@@ -359,21 +362,21 @@ def emitrevisions(store, nodes, nodesord
         p1rev, p2rev = store.parentrevs(rev)
 
         if deltaparentfn:
             deltaparentrev = deltaparentfn(rev)
         else:
             deltaparentrev = nullrev
 
         # Forced delta against previous mode.
-        if deltaprevious:
+        if deltamode == repository.CG_DELTAMODE_PREV:
             baserev = prevrev
 
         # We're instructed to send fulltext. Honor that.
-        elif sendfulltext:
+        elif deltamode == repository.CG_DELTAMODE_FULL:
             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.
@@ -422,17 +425,18 @@ def emitrevisions(store, nodes, nodesord
 
                 if baserev != nullrev:
                     if rawsizefn:
                         baserevisionsize = rawsizefn(baserev)
                     else:
                         baserevisionsize = len(store.revision(baserev,
                                                               raw=True))
 
-            elif baserev == nullrev and not deltaprevious:
+            elif (baserev == nullrev
+                    and deltamode != repository.CG_DELTAMODE_PREV):
                 revision = store.revision(node, raw=True)
                 available.add(rev)
             else:
                 if revdifffn:
                     delta = revdifffn(baserev, rev)
                 else:
                     delta = mdiff.textdiff(store.revision(baserev, raw=True),
                                            store.revision(rev, raw=True))