Show More
@@ -1,71 +1,232 b'' | |||
|
1 | 1 | # repository.py - Interfaces and base classes for repositories and peers. |
|
2 | 2 | # |
|
3 | 3 | # Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com> |
|
4 | 4 | # |
|
5 | 5 | # This software may be used and distributed according to the terms of the |
|
6 | 6 | # GNU General Public License version 2 or any later version. |
|
7 | 7 | |
|
8 | 8 | from __future__ import absolute_import |
|
9 | 9 | |
|
10 | 10 | import abc |
|
11 | 11 | |
|
12 | 12 | class _basepeer(object): |
|
13 | 13 | """Represents a "connection" to a repository. |
|
14 | 14 | |
|
15 | 15 | This is the base interface for representing a connection to a repository. |
|
16 | 16 | It holds basic properties and methods applicable to all peer types. |
|
17 | 17 | |
|
18 | 18 | This is not a complete interface definition and should not be used |
|
19 | 19 | outside of this module. |
|
20 | 20 | """ |
|
21 | 21 | __metaclass__ = abc.ABCMeta |
|
22 | 22 | |
|
23 | 23 | @abc.abstractproperty |
|
24 | 24 | def ui(self): |
|
25 | 25 | """ui.ui instance.""" |
|
26 | 26 | |
|
27 | 27 | @abc.abstractmethod |
|
28 | 28 | def url(self): |
|
29 | 29 | """Returns a URL string representing this peer. |
|
30 | 30 | |
|
31 | 31 | Currently, implementations expose the raw URL used to construct the |
|
32 | 32 | instance. It may contain credentials as part of the URL. The |
|
33 | 33 | expectations of the value aren't well-defined and this could lead to |
|
34 | 34 | data leakage. |
|
35 | 35 | |
|
36 | 36 | TODO audit/clean consumers and more clearly define the contents of this |
|
37 | 37 | value. |
|
38 | 38 | """ |
|
39 | 39 | |
|
40 | 40 | @abc.abstractmethod |
|
41 | 41 | def local(self): |
|
42 | 42 | """Returns a local repository instance. |
|
43 | 43 | |
|
44 | 44 | If the peer represents a local repository, returns an object that |
|
45 | 45 | can be used to interface with it. Otherwise returns ``None``. |
|
46 | 46 | """ |
|
47 | 47 | |
|
48 | 48 | @abc.abstractmethod |
|
49 | 49 | def peer(self): |
|
50 | 50 | """Returns an object conforming to this interface. |
|
51 | 51 | |
|
52 | 52 | Most implementations will ``return self``. |
|
53 | 53 | """ |
|
54 | 54 | |
|
55 | 55 | @abc.abstractmethod |
|
56 | 56 | def canpush(self): |
|
57 | 57 | """Returns a boolean indicating if this peer can be pushed to.""" |
|
58 | 58 | |
|
59 | 59 | @abc.abstractmethod |
|
60 | 60 | def close(self): |
|
61 | 61 | """Close the connection to this peer. |
|
62 | 62 | |
|
63 | 63 | This is called when the peer will no longer be used. Resources |
|
64 | 64 | associated with the peer should be cleaned up. |
|
65 | 65 | """ |
|
66 | 66 | |
|
67 | class peer(_basepeer): | |
|
67 | class _basewirecommands(object): | |
|
68 | """Client-side interface for communicating over the wire protocol. | |
|
69 | ||
|
70 | This interface is used as a gateway to the Mercurial wire protocol. | |
|
71 | methods commonly call wire protocol commands of the same name. | |
|
72 | """ | |
|
73 | __metaclass__ = abc.ABCMeta | |
|
74 | ||
|
75 | @abc.abstractmethod | |
|
76 | def branchmap(self): | |
|
77 | """Obtain heads in named branches. | |
|
78 | ||
|
79 | Returns a dict mapping branch name to an iterable of nodes that are | |
|
80 | heads on that branch. | |
|
81 | """ | |
|
82 | ||
|
83 | @abc.abstractmethod | |
|
84 | def capabilities(self): | |
|
85 | """Obtain capabilities of the peer. | |
|
86 | ||
|
87 | Returns a set of string capabilities. | |
|
88 | """ | |
|
89 | ||
|
90 | @abc.abstractmethod | |
|
91 | def debugwireargs(self, one, two, three=None, four=None, five=None): | |
|
92 | """Used to facilitate debugging of arguments passed over the wire.""" | |
|
93 | ||
|
94 | @abc.abstractmethod | |
|
95 | def getbundle(self, source, **kwargs): | |
|
96 | """Obtain remote repository data as a bundle. | |
|
97 | ||
|
98 | This command is how the bulk of repository data is transferred from | |
|
99 | the peer to the local repository | |
|
100 | ||
|
101 | Returns a generator of bundle data. | |
|
102 | """ | |
|
103 | ||
|
104 | @abc.abstractmethod | |
|
105 | def heads(self): | |
|
106 | """Determine all known head revisions in the peer. | |
|
107 | ||
|
108 | Returns an iterable of binary nodes. | |
|
109 | """ | |
|
110 | ||
|
111 | @abc.abstractmethod | |
|
112 | def known(self, nodes): | |
|
113 | """Determine whether multiple nodes are known. | |
|
114 | ||
|
115 | Accepts an iterable of nodes whose presence to check for. | |
|
116 | ||
|
117 | Returns an iterable of booleans indicating of the corresponding node | |
|
118 | at that index is known to the peer. | |
|
119 | """ | |
|
120 | ||
|
121 | @abc.abstractmethod | |
|
122 | def listkeys(self, namespace): | |
|
123 | """Obtain all keys in a pushkey namespace. | |
|
124 | ||
|
125 | Returns an iterable of key names. | |
|
126 | """ | |
|
127 | ||
|
128 | @abc.abstractmethod | |
|
129 | def lookup(self, key): | |
|
130 | """Resolve a value to a known revision. | |
|
131 | ||
|
132 | Returns a binary node of the resolved revision on success. | |
|
133 | """ | |
|
134 | ||
|
135 | @abc.abstractmethod | |
|
136 | def pushkey(self, namespace, key, old, new): | |
|
137 | """Set a value using the ``pushkey`` protocol. | |
|
138 | ||
|
139 | Arguments correspond to the pushkey namespace and key to operate on and | |
|
140 | the old and new values for that key. | |
|
141 | ||
|
142 | Returns a string with the peer result. The value inside varies by the | |
|
143 | namespace. | |
|
144 | """ | |
|
145 | ||
|
146 | @abc.abstractmethod | |
|
147 | def stream_out(self): | |
|
148 | """Obtain streaming clone data. | |
|
149 | ||
|
150 | Successful result should be a generator of data chunks. | |
|
151 | """ | |
|
152 | ||
|
153 | @abc.abstractmethod | |
|
154 | def unbundle(self, bundle, heads, url): | |
|
155 | """Transfer repository data to the peer. | |
|
156 | ||
|
157 | This is how the bulk of data during a push is transferred. | |
|
158 | ||
|
159 | Returns the integer number of heads added to the peer. | |
|
160 | """ | |
|
161 | ||
|
162 | class _baselegacywirecommands(object): | |
|
163 | """Interface for implementing support for legacy wire protocol commands. | |
|
164 | ||
|
165 | Wire protocol commands transition to legacy status when they are no longer | |
|
166 | used by modern clients. To facilitate identifying which commands are | |
|
167 | legacy, the interfaces are split. | |
|
168 | """ | |
|
169 | __metaclass__ = abc.ABCMeta | |
|
170 | ||
|
171 | @abc.abstractmethod | |
|
172 | def between(self, pairs): | |
|
173 | """Obtain nodes between pairs of nodes. | |
|
174 | ||
|
175 | ``pairs`` is an iterable of node pairs. | |
|
176 | ||
|
177 | Returns an iterable of iterables of nodes corresponding to each | |
|
178 | requested pair. | |
|
179 | """ | |
|
180 | ||
|
181 | @abc.abstractmethod | |
|
182 | def branches(self, nodes): | |
|
183 | """Obtain ancestor changesets of specific nodes back to a branch point. | |
|
184 | ||
|
185 | For each requested node, the peer finds the first ancestor node that is | |
|
186 | a DAG root or is a merge. | |
|
187 | ||
|
188 | Returns an iterable of iterables with the resolved values for each node. | |
|
189 | """ | |
|
190 | ||
|
191 | @abc.abstractmethod | |
|
192 | def changegroup(self, nodes, kind): | |
|
193 | """Obtain a changegroup with data for descendants of specified nodes.""" | |
|
194 | ||
|
195 | @abc.abstractmethod | |
|
196 | def changegroupsubset(self, bases, heads, kind): | |
|
197 | pass | |
|
198 | ||
|
199 | class peer(_basepeer, _basewirecommands): | |
|
68 | 200 | """Unified interface and base class for peer repositories. |
|
69 | 201 | |
|
70 |
All peer instances must inherit from this class |
|
|
202 | All peer instances must inherit from this class and conform to its | |
|
203 | interface. | |
|
71 | 204 | """ |
|
205 | ||
|
206 | @abc.abstractmethod | |
|
207 | def iterbatch(self): | |
|
208 | """Obtain an object to be used for multiple method calls. | |
|
209 | ||
|
210 | Various operations call several methods on peer instances. If each | |
|
211 | method call were performed immediately and serially, this would | |
|
212 | require round trips to remote peers and/or would slow down execution. | |
|
213 | ||
|
214 | Some peers have the ability to "batch" method calls to avoid costly | |
|
215 | round trips or to facilitate concurrent execution. | |
|
216 | ||
|
217 | This method returns an object that can be used to indicate intent to | |
|
218 | perform batched method calls. | |
|
219 | ||
|
220 | The returned object is a proxy of this peer. It intercepts calls to | |
|
221 | batchable methods and queues them instead of performing them | |
|
222 | immediately. This proxy object has a ``submit`` method that will | |
|
223 | perform all queued batchable method calls. A ``results()`` method | |
|
224 | exposes the results of queued/batched method calls. It is a generator | |
|
225 | of results in the order they were called. | |
|
226 | ||
|
227 | Not all peers or wire protocol implementations may actually batch method | |
|
228 | calls. However, they must all support this API. | |
|
229 | """ | |
|
230 | ||
|
231 | class legacypeer(peer, _baselegacywirecommands): | |
|
232 | """peer but with support for legacy wire protocol commands.""" |
General Comments 0
You need to be logged in to leave comments.
Login now