D332: repository: formalize peer interface with abstract base class

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Fri Aug 11 04:20:36 UTC 2017


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

REVISION SUMMARY
  There are various interfaces for interacting with repositories
  and peers. They form a contract for how one should interact with
  a repo or peer object.
  
  The contracts today aren't very well-defined or enforced. There
  have been several bugs over the years where peers or repo types
  have forgotten to implement certain methods. In addition, the
  inheritance of some classes is wonky. For example, localrepository
  doesn't inherit from an interface and the god-object nature of
  that class means the repository interface isn't well-defined. Other
  repository types inherit from localrepository then stub out
  methods that don't make sense (e.g. statichttprepository
  re-defining locking methods to fail fast).
  
  Not having well-defined interfaces makes implementing alternate
  storage backends, wire protocol transports, and repository types
  difficult because it isn't clear what exactly needs to be
  implemented.
  
  This patch starts the process of attempting to establish more
  order to the type system around repositories and peers.
  
  Our first patch starts with a problem space that already has a
  partial solution: peers. The peer.peerrepository class already
  somewhat defines a peer interface. But it is missing a few things
  and the total interface isn't well-defined because it is combined
  with wireproto.wirepeer.
  
  Our newly-established basepeer class uses the abc module to
  declare an abstract base class with the properties and methods that
  a generic peer must implement.
  
  We create a new class that inherits from it. This class will hold
  our other future abstract base classes / interfaces so we can expose
  a unified base class/interface.
  
  We don't yet use the new interface because subsequent additions
  will break existing code without some refactoring first.
  
  A new module (repository.py) was created to hold the interfaces.
  I could have put things in peer.py. However, I have plans to
  eventually add interfaces to define repository and storage types.
  These almost certainly require a new module. And I figured having
  all the interfaces live in one module makes sense. So I created
  repository.py to be that future home.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/repository.py

CHANGE DETAILS

diff --git a/mercurial/repository.py b/mercurial/repository.py
new file mode 100644
--- /dev/null
+++ b/mercurial/repository.py
@@ -0,0 +1,62 @@
+# repository.py - Interfaces and base classes for repositories and peers.
+#
+# Copyright 2017 Gregory Szorc <gregory.szorc at gmail.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+import abc
+
+class _basepeer(object):
+    """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.
+    """
+    __metaclass__ = abc.ABCMeta
+
+    @abc.abstractproperty
+    def ui(self):
+        """ui.ui instance."""
+
+    @abc.abstractmethod
+    def url(self):
+        """Returns a string representing this peer."""
+
+    @abc.abstractmethod
+    def local(self):
+        """Returns a local repository instance.
+
+        If the peer represents a local repository, returns an object that
+        can be used to interface with it. Otherwise returns ``None``.
+        """
+
+    @abc.abstractmethod
+    def peer(self):
+        """Returns an object conforming to this interface.
+
+        Most implementations will ``return self``.
+        """
+
+    @abc.abstractmethod
+    def canpush(self):
+        """Returns a boolean indicating if this peer can be pushed to."""
+
+    @abc.abstractmethod
+    def close(self):
+        """Close the connection to this peer.
+
+        This is called when the peer will no longer be used. Resources
+        associated with the peer should be cleaned up.
+        """
+
+class peer(_basepeer):
+    """Unified interface and base class for peer repositories.
+
+    All peer instances must inherit from this class.
+    """



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


More information about the Mercurial-devel mailing list