annotate mercurial/repository.py @ 33800:f257943e47ab

repository: formalize peer interface with abstract base class 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. Differential Revision: https://phab.mercurial-scm.org/D332
author Gregory Szorc <gregory.szorc@gmail.com>
date Sun, 13 Aug 2017 10:58:48 -0700
parents
children 558f5b2ee10e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
33800
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 # repository.py - Interfaces and base classes for repositories and peers.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2 #
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 # Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4 #
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8 from __future__ import absolute_import
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
9
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
10 import abc
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
11
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
12 class _basepeer(object):
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
13 """Represents a "connection" to a repository.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
14
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
15 This is the base interface for representing a connection to a repository.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
16 It holds basic properties and methods applicable to all peer types.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
17
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
18 This is not a complete interface definition and should not be used
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
19 outside of this module.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
20 """
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
21 __metaclass__ = abc.ABCMeta
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
22
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
23 @abc.abstractproperty
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
24 def ui(self):
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
25 """ui.ui instance."""
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
26
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
27 @abc.abstractmethod
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
28 def url(self):
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
29 """Returns a URL string representing this peer.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
30
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
31 Currently, implementations expose the raw URL used to construct the
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
32 instance. It may contain credentials as part of the URL. The
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
33 expectations of the value aren't well-defined and this could lead to
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
34 data leakage.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
35
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
36 TODO audit/clean consumers and more clearly define the contents of this
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
37 value.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
38 """
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
39
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
40 @abc.abstractmethod
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
41 def local(self):
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
42 """Returns a local repository instance.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
43
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
44 If the peer represents a local repository, returns an object that
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
45 can be used to interface with it. Otherwise returns ``None``.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
46 """
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
47
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
48 @abc.abstractmethod
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
49 def peer(self):
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
50 """Returns an object conforming to this interface.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
51
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
52 Most implementations will ``return self``.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
53 """
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
54
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
55 @abc.abstractmethod
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
56 def canpush(self):
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
57 """Returns a boolean indicating if this peer can be pushed to."""
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
58
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
59 @abc.abstractmethod
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
60 def close(self):
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
61 """Close the connection to this peer.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
62
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
63 This is called when the peer will no longer be used. Resources
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
64 associated with the peer should be cleaned up.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
65 """
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
66
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
67 class peer(_basepeer):
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
68 """Unified interface and base class for peer repositories.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
69
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
70 All peer instances must inherit from this class.
f257943e47ab repository: formalize peer interface with abstract base class
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
71 """