D4225: repository: formalize interfaces for revision deltas and requests

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Thu Aug 9 23:12:16 UTC 2018


indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Now that we've sufficiently abstracted how revision deltas are
  produced in changegroup code, we can now start the process of
  formalizing that as part of the interfaces defined in the
  repository module.
  
  This commit essentially converts the revisiondelta and
  revisiondeltarequest classes into well-defined interfaces. This
  is not strictly necessary. But I want all types formalized by the
  storage interface to have interfaces. This makes it much easier
  to test for interface conformance and for implementing new
  storage backends.
  
  Because the interface is documented, comments and docstrings from
  changegroup.py have been dropped.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/changegroup.py
  mercurial/repository.py
  tests/test-check-interfaces.py

CHANGE DETAILS

diff --git a/tests/test-check-interfaces.py b/tests/test-check-interfaces.py
--- a/tests/test-check-interfaces.py
+++ b/tests/test-check-interfaces.py
@@ -21,6 +21,7 @@
     verify as ziverify,
 )
 from mercurial import (
+    changegroup,
     bundlerepo,
     filelog,
     httppeer,
@@ -196,4 +197,29 @@
     # Conforms to imanifestdict.
     checkzobject(mctx.read())
 
+    ziverify.verifyClass(repository.irevisiondelta,
+                         changegroup.revisiondelta)
+    ziverify.verifyClass(repository.irevisiondeltarequest,
+                         changegroup.revisiondeltarequest)
+
+    rd = changegroup.revisiondelta(
+        node=b'',
+        p1node=b'',
+        p2node=b'',
+        basenode=b'',
+        linknode=b'',
+        flags=b'',
+        baserevisionsize=None,
+        revision=b'',
+        delta=None)
+    checkzobject(rd)
+
+    rdr = changegroup.revisiondeltarequest(
+        node=b'',
+        linknode=b'',
+        p1node=b'',
+        p2node=b'',
+        basenode=b'')
+    checkzobject(rdr)
+
 main()
diff --git a/mercurial/repository.py b/mercurial/repository.py
--- a/mercurial/repository.py
+++ b/mercurial/repository.py
@@ -318,6 +318,87 @@
             _('cannot %s; remote repository does not support the %r '
               'capability') % (purpose, name))
 
+class irevisiondelta(interfaceutil.Interface):
+    """Represents a delta between one revision and another.
+
+    Instances convey enough information to allow a revision to be exchanged
+    with another repository.
+
+    Instances represent the fulltext revision data or a delta against
+    another revision. Therefore the ``revision`` and ``delta`` attributes
+    are mutually exclusive.
+
+    Typically used for changegroup generation.
+    """
+
+    node = interfaceutil.Attribute(
+        """20 byte node of this revision.""")
+
+    p1node = interfaceutil.Attribute(
+        """20 byte node of 1st parent of this revision.""")
+
+    p2node = interfaceutil.Attribute(
+        """20 byte node of 2nd parent of this revision.""")
+
+    linknode = interfaceutil.Attribute(
+        """20 byte node of the changelog revision this node is linked to.""")
+
+    flags = interfaceutil.Attribute(
+        """2 bytes of integer flags that apply to this revision.""")
+
+    basenode = interfaceutil.Attribute(
+        """20 byte node of the revision this data is a delta against.
+
+        ``nullid`` indicates that the revision is a full revision and not
+        a delta.
+        """)
+
+    baserevisionsize = interfaceutil.Attribute(
+        """Size of base revision this delta is against.
+
+        May be ``None`` if ``basenode`` is ``nullid``.
+        """)
+
+    revision = interfaceutil.Attribute(
+        """Raw fulltext of revision data for this node.""")
+
+    delta = interfaceutil.Attribute(
+        """Delta between ``basenode`` and ``node``.
+
+        Stored in the bdiff delta format.
+        """)
+
+class irevisiondeltarequest(interfaceutil.Interface):
+    """Represents a request to generate an ``irevisiondelta``."""
+
+    node = interfaceutil.Attribute(
+        """20 byte node of revision being requested.""")
+
+    p1node = interfaceutil.Attribute(
+        """20 byte node of 1st parent of revision.""")
+
+    p2node = interfaceutil.Attribute(
+        """20 byte node of 2nd parent of revision.""")
+
+    linknode = interfaceutil.Attribute(
+        """20 byte node to store in ``linknode`` attribute.""")
+
+    basenode = interfaceutil.Attribute(
+        """Base revision that delta should be generated against.
+
+        If ``nullid``, the derived ``irevisiondelta`` should have its
+        ``revision`` field populated and no delta should be generated.
+
+        If ``None``, the delta may be generated against any revision that
+        is an ancestor of this revision. Or a full revision may be used.
+
+        If any other value, the delta should be produced against that
+        revision.
+        """)
+
+    ellipsis = interfaceutil.Attribute(
+        """Boolean on whether the ellipsis flag should be set.""")
+
 class ifilerevisionssequence(interfaceutil.Interface):
     """Contains index data for all revisions of a file.
 
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -37,6 +37,7 @@
 )
 
 from .utils import (
+    interfaceutil,
     stringutil,
 )
 
@@ -502,58 +503,27 @@
             return d
         return readexactly(self._fh, n)
 
+ at interfaceutil.implementer(repository.irevisiondeltarequest)
 @attr.s(slots=True, frozen=True)
 class revisiondeltarequest(object):
-    """Describes a request to construct a revision delta.
-
-    Instances are converted into ``revisiondelta`` later.
-    """
-    # Revision whose delta will be generated.
     node = attr.ib()
-
-    # Linknode value.
     linknode = attr.ib()
-
-    # Parent revisions to record in ``revisiondelta`` instance.
     p1node = attr.ib()
     p2node = attr.ib()
-
-    # Base revision that delta should be generated against. If nullid,
-    # the full revision data should be populated. If None, the delta
-    # may be generated against any base revision that is an ancestor of
-    # this revision. If any other value, the delta should be produced
-    # against that revision.
     basenode = attr.ib()
-
-    # Whether this should be marked as an ellipsis revision.
     ellipsis = attr.ib(default=False)
 
+ at interfaceutil.implementer(repository.irevisiondelta)
 @attr.s(slots=True, frozen=True)
 class revisiondelta(object):
-    """Describes a delta entry in a changegroup.
-
-    Captured data is sufficient to serialize the delta into multiple
-    formats.
-
-    ``revision`` and ``delta`` are mutually exclusive.
-    """
-    # 20 byte node of this revision.
     node = attr.ib()
-    # 20 byte nodes of parent revisions.
     p1node = attr.ib()
     p2node = attr.ib()
-    # 20 byte node of node this delta is against.
     basenode = attr.ib()
-    # 20 byte node of changeset revision this delta is associated with.
     linknode = attr.ib()
-    # 2 bytes of flags to apply to revision data.
     flags = attr.ib()
-    # Size of base revision this delta is against. May be None if
-    # basenode is nullid.
     baserevisionsize = attr.ib()
-    # Raw fulltext revision data.
     revision = attr.ib()
-    # Delta between the basenode and node.
     delta = attr.ib()
 
 def _revisiondeltatochunks(delta, headerfn):



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


More information about the Mercurial-devel mailing list