##// END OF EJS Templates
wireproto: fix incorrect function name in docstring...
Connor Sheehan -
r40315:4821affc default
parent child Browse files
Show More
@@ -1,1835 +1,1835 b''
1 # repository.py - Interfaces and base classes for repositories and peers.
1 # repository.py - Interfaces and base classes for repositories and peers.
2 #
2 #
3 # Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 from .i18n import _
10 from .i18n import _
11 from . import (
11 from . import (
12 error,
12 error,
13 )
13 )
14 from .utils import (
14 from .utils import (
15 interfaceutil,
15 interfaceutil,
16 )
16 )
17
17
18 # When narrowing is finalized and no longer subject to format changes,
18 # When narrowing is finalized and no longer subject to format changes,
19 # we should move this to just "narrow" or similar.
19 # we should move this to just "narrow" or similar.
20 NARROW_REQUIREMENT = 'narrowhg-experimental'
20 NARROW_REQUIREMENT = 'narrowhg-experimental'
21
21
22 # Local repository feature string.
22 # Local repository feature string.
23
23
24 # Revlogs are being used for file storage.
24 # Revlogs are being used for file storage.
25 REPO_FEATURE_REVLOG_FILE_STORAGE = b'revlogfilestorage'
25 REPO_FEATURE_REVLOG_FILE_STORAGE = b'revlogfilestorage'
26 # The storage part of the repository is shared from an external source.
26 # The storage part of the repository is shared from an external source.
27 REPO_FEATURE_SHARED_STORAGE = b'sharedstore'
27 REPO_FEATURE_SHARED_STORAGE = b'sharedstore'
28 # LFS supported for backing file storage.
28 # LFS supported for backing file storage.
29 REPO_FEATURE_LFS = b'lfs'
29 REPO_FEATURE_LFS = b'lfs'
30 # Repository supports being stream cloned.
30 # Repository supports being stream cloned.
31 REPO_FEATURE_STREAM_CLONE = b'streamclone'
31 REPO_FEATURE_STREAM_CLONE = b'streamclone'
32
32
33 REVISION_FLAG_CENSORED = 1 << 15
33 REVISION_FLAG_CENSORED = 1 << 15
34 REVISION_FLAG_ELLIPSIS = 1 << 14
34 REVISION_FLAG_ELLIPSIS = 1 << 14
35 REVISION_FLAG_EXTSTORED = 1 << 13
35 REVISION_FLAG_EXTSTORED = 1 << 13
36
36
37 REVISION_FLAGS_KNOWN = (
37 REVISION_FLAGS_KNOWN = (
38 REVISION_FLAG_CENSORED | REVISION_FLAG_ELLIPSIS | REVISION_FLAG_EXTSTORED)
38 REVISION_FLAG_CENSORED | REVISION_FLAG_ELLIPSIS | REVISION_FLAG_EXTSTORED)
39
39
40 class ipeerconnection(interfaceutil.Interface):
40 class ipeerconnection(interfaceutil.Interface):
41 """Represents a "connection" to a repository.
41 """Represents a "connection" to a repository.
42
42
43 This is the base interface for representing a connection to a repository.
43 This is the base interface for representing a connection to a repository.
44 It holds basic properties and methods applicable to all peer types.
44 It holds basic properties and methods applicable to all peer types.
45
45
46 This is not a complete interface definition and should not be used
46 This is not a complete interface definition and should not be used
47 outside of this module.
47 outside of this module.
48 """
48 """
49 ui = interfaceutil.Attribute("""ui.ui instance""")
49 ui = interfaceutil.Attribute("""ui.ui instance""")
50
50
51 def url():
51 def url():
52 """Returns a URL string representing this peer.
52 """Returns a URL string representing this peer.
53
53
54 Currently, implementations expose the raw URL used to construct the
54 Currently, implementations expose the raw URL used to construct the
55 instance. It may contain credentials as part of the URL. The
55 instance. It may contain credentials as part of the URL. The
56 expectations of the value aren't well-defined and this could lead to
56 expectations of the value aren't well-defined and this could lead to
57 data leakage.
57 data leakage.
58
58
59 TODO audit/clean consumers and more clearly define the contents of this
59 TODO audit/clean consumers and more clearly define the contents of this
60 value.
60 value.
61 """
61 """
62
62
63 def local():
63 def local():
64 """Returns a local repository instance.
64 """Returns a local repository instance.
65
65
66 If the peer represents a local repository, returns an object that
66 If the peer represents a local repository, returns an object that
67 can be used to interface with it. Otherwise returns ``None``.
67 can be used to interface with it. Otherwise returns ``None``.
68 """
68 """
69
69
70 def peer():
70 def peer():
71 """Returns an object conforming to this interface.
71 """Returns an object conforming to this interface.
72
72
73 Most implementations will ``return self``.
73 Most implementations will ``return self``.
74 """
74 """
75
75
76 def canpush():
76 def canpush():
77 """Returns a boolean indicating if this peer can be pushed to."""
77 """Returns a boolean indicating if this peer can be pushed to."""
78
78
79 def close():
79 def close():
80 """Close the connection to this peer.
80 """Close the connection to this peer.
81
81
82 This is called when the peer will no longer be used. Resources
82 This is called when the peer will no longer be used. Resources
83 associated with the peer should be cleaned up.
83 associated with the peer should be cleaned up.
84 """
84 """
85
85
86 class ipeercapabilities(interfaceutil.Interface):
86 class ipeercapabilities(interfaceutil.Interface):
87 """Peer sub-interface related to capabilities."""
87 """Peer sub-interface related to capabilities."""
88
88
89 def capable(name):
89 def capable(name):
90 """Determine support for a named capability.
90 """Determine support for a named capability.
91
91
92 Returns ``False`` if capability not supported.
92 Returns ``False`` if capability not supported.
93
93
94 Returns ``True`` if boolean capability is supported. Returns a string
94 Returns ``True`` if boolean capability is supported. Returns a string
95 if capability support is non-boolean.
95 if capability support is non-boolean.
96
96
97 Capability strings may or may not map to wire protocol capabilities.
97 Capability strings may or may not map to wire protocol capabilities.
98 """
98 """
99
99
100 def requirecap(name, purpose):
100 def requirecap(name, purpose):
101 """Require a capability to be present.
101 """Require a capability to be present.
102
102
103 Raises a ``CapabilityError`` if the capability isn't present.
103 Raises a ``CapabilityError`` if the capability isn't present.
104 """
104 """
105
105
106 class ipeercommands(interfaceutil.Interface):
106 class ipeercommands(interfaceutil.Interface):
107 """Client-side interface for communicating over the wire protocol.
107 """Client-side interface for communicating over the wire protocol.
108
108
109 This interface is used as a gateway to the Mercurial wire protocol.
109 This interface is used as a gateway to the Mercurial wire protocol.
110 methods commonly call wire protocol commands of the same name.
110 methods commonly call wire protocol commands of the same name.
111 """
111 """
112
112
113 def branchmap():
113 def branchmap():
114 """Obtain heads in named branches.
114 """Obtain heads in named branches.
115
115
116 Returns a dict mapping branch name to an iterable of nodes that are
116 Returns a dict mapping branch name to an iterable of nodes that are
117 heads on that branch.
117 heads on that branch.
118 """
118 """
119
119
120 def capabilities():
120 def capabilities():
121 """Obtain capabilities of the peer.
121 """Obtain capabilities of the peer.
122
122
123 Returns a set of string capabilities.
123 Returns a set of string capabilities.
124 """
124 """
125
125
126 def clonebundles():
126 def clonebundles():
127 """Obtains the clone bundles manifest for the repo.
127 """Obtains the clone bundles manifest for the repo.
128
128
129 Returns the manifest as unparsed bytes.
129 Returns the manifest as unparsed bytes.
130 """
130 """
131
131
132 def debugwireargs(one, two, three=None, four=None, five=None):
132 def debugwireargs(one, two, three=None, four=None, five=None):
133 """Used to facilitate debugging of arguments passed over the wire."""
133 """Used to facilitate debugging of arguments passed over the wire."""
134
134
135 def getbundle(source, **kwargs):
135 def getbundle(source, **kwargs):
136 """Obtain remote repository data as a bundle.
136 """Obtain remote repository data as a bundle.
137
137
138 This command is how the bulk of repository data is transferred from
138 This command is how the bulk of repository data is transferred from
139 the peer to the local repository
139 the peer to the local repository
140
140
141 Returns a generator of bundle data.
141 Returns a generator of bundle data.
142 """
142 """
143
143
144 def heads():
144 def heads():
145 """Determine all known head revisions in the peer.
145 """Determine all known head revisions in the peer.
146
146
147 Returns an iterable of binary nodes.
147 Returns an iterable of binary nodes.
148 """
148 """
149
149
150 def known(nodes):
150 def known(nodes):
151 """Determine whether multiple nodes are known.
151 """Determine whether multiple nodes are known.
152
152
153 Accepts an iterable of nodes whose presence to check for.
153 Accepts an iterable of nodes whose presence to check for.
154
154
155 Returns an iterable of booleans indicating of the corresponding node
155 Returns an iterable of booleans indicating of the corresponding node
156 at that index is known to the peer.
156 at that index is known to the peer.
157 """
157 """
158
158
159 def listkeys(namespace):
159 def listkeys(namespace):
160 """Obtain all keys in a pushkey namespace.
160 """Obtain all keys in a pushkey namespace.
161
161
162 Returns an iterable of key names.
162 Returns an iterable of key names.
163 """
163 """
164
164
165 def lookup(key):
165 def lookup(key):
166 """Resolve a value to a known revision.
166 """Resolve a value to a known revision.
167
167
168 Returns a binary node of the resolved revision on success.
168 Returns a binary node of the resolved revision on success.
169 """
169 """
170
170
171 def pushkey(namespace, key, old, new):
171 def pushkey(namespace, key, old, new):
172 """Set a value using the ``pushkey`` protocol.
172 """Set a value using the ``pushkey`` protocol.
173
173
174 Arguments correspond to the pushkey namespace and key to operate on and
174 Arguments correspond to the pushkey namespace and key to operate on and
175 the old and new values for that key.
175 the old and new values for that key.
176
176
177 Returns a string with the peer result. The value inside varies by the
177 Returns a string with the peer result. The value inside varies by the
178 namespace.
178 namespace.
179 """
179 """
180
180
181 def stream_out():
181 def stream_out():
182 """Obtain streaming clone data.
182 """Obtain streaming clone data.
183
183
184 Successful result should be a generator of data chunks.
184 Successful result should be a generator of data chunks.
185 """
185 """
186
186
187 def unbundle(bundle, heads, url):
187 def unbundle(bundle, heads, url):
188 """Transfer repository data to the peer.
188 """Transfer repository data to the peer.
189
189
190 This is how the bulk of data during a push is transferred.
190 This is how the bulk of data during a push is transferred.
191
191
192 Returns the integer number of heads added to the peer.
192 Returns the integer number of heads added to the peer.
193 """
193 """
194
194
195 class ipeerlegacycommands(interfaceutil.Interface):
195 class ipeerlegacycommands(interfaceutil.Interface):
196 """Interface for implementing support for legacy wire protocol commands.
196 """Interface for implementing support for legacy wire protocol commands.
197
197
198 Wire protocol commands transition to legacy status when they are no longer
198 Wire protocol commands transition to legacy status when they are no longer
199 used by modern clients. To facilitate identifying which commands are
199 used by modern clients. To facilitate identifying which commands are
200 legacy, the interfaces are split.
200 legacy, the interfaces are split.
201 """
201 """
202
202
203 def between(pairs):
203 def between(pairs):
204 """Obtain nodes between pairs of nodes.
204 """Obtain nodes between pairs of nodes.
205
205
206 ``pairs`` is an iterable of node pairs.
206 ``pairs`` is an iterable of node pairs.
207
207
208 Returns an iterable of iterables of nodes corresponding to each
208 Returns an iterable of iterables of nodes corresponding to each
209 requested pair.
209 requested pair.
210 """
210 """
211
211
212 def branches(nodes):
212 def branches(nodes):
213 """Obtain ancestor changesets of specific nodes back to a branch point.
213 """Obtain ancestor changesets of specific nodes back to a branch point.
214
214
215 For each requested node, the peer finds the first ancestor node that is
215 For each requested node, the peer finds the first ancestor node that is
216 a DAG root or is a merge.
216 a DAG root or is a merge.
217
217
218 Returns an iterable of iterables with the resolved values for each node.
218 Returns an iterable of iterables with the resolved values for each node.
219 """
219 """
220
220
221 def changegroup(nodes, source):
221 def changegroup(nodes, source):
222 """Obtain a changegroup with data for descendants of specified nodes."""
222 """Obtain a changegroup with data for descendants of specified nodes."""
223
223
224 def changegroupsubset(bases, heads, source):
224 def changegroupsubset(bases, heads, source):
225 pass
225 pass
226
226
227 class ipeercommandexecutor(interfaceutil.Interface):
227 class ipeercommandexecutor(interfaceutil.Interface):
228 """Represents a mechanism to execute remote commands.
228 """Represents a mechanism to execute remote commands.
229
229
230 This is the primary interface for requesting that wire protocol commands
230 This is the primary interface for requesting that wire protocol commands
231 be executed. Instances of this interface are active in a context manager
231 be executed. Instances of this interface are active in a context manager
232 and have a well-defined lifetime. When the context manager exits, all
232 and have a well-defined lifetime. When the context manager exits, all
233 outstanding requests are waited on.
233 outstanding requests are waited on.
234 """
234 """
235
235
236 def callcommand(name, args):
236 def callcommand(name, args):
237 """Request that a named command be executed.
237 """Request that a named command be executed.
238
238
239 Receives the command name and a dictionary of command arguments.
239 Receives the command name and a dictionary of command arguments.
240
240
241 Returns a ``concurrent.futures.Future`` that will resolve to the
241 Returns a ``concurrent.futures.Future`` that will resolve to the
242 result of that command request. That exact value is left up to
242 result of that command request. That exact value is left up to
243 the implementation and possibly varies by command.
243 the implementation and possibly varies by command.
244
244
245 Not all commands can coexist with other commands in an executor
245 Not all commands can coexist with other commands in an executor
246 instance: it depends on the underlying wire protocol transport being
246 instance: it depends on the underlying wire protocol transport being
247 used and the command itself.
247 used and the command itself.
248
248
249 Implementations MAY call ``sendcommands()`` automatically if the
249 Implementations MAY call ``sendcommands()`` automatically if the
250 requested command can not coexist with other commands in this executor.
250 requested command can not coexist with other commands in this executor.
251
251
252 Implementations MAY call ``sendcommands()`` automatically when the
252 Implementations MAY call ``sendcommands()`` automatically when the
253 future's ``result()`` is called. So, consumers using multiple
253 future's ``result()`` is called. So, consumers using multiple
254 commands with an executor MUST ensure that ``result()`` is not called
254 commands with an executor MUST ensure that ``result()`` is not called
255 until all command requests have been issued.
255 until all command requests have been issued.
256 """
256 """
257
257
258 def sendcommands():
258 def sendcommands():
259 """Trigger submission of queued command requests.
259 """Trigger submission of queued command requests.
260
260
261 Not all transports submit commands as soon as they are requested to
261 Not all transports submit commands as soon as they are requested to
262 run. When called, this method forces queued command requests to be
262 run. When called, this method forces queued command requests to be
263 issued. It will no-op if all commands have already been sent.
263 issued. It will no-op if all commands have already been sent.
264
264
265 When called, no more new commands may be issued with this executor.
265 When called, no more new commands may be issued with this executor.
266 """
266 """
267
267
268 def close():
268 def close():
269 """Signal that this command request is finished.
269 """Signal that this command request is finished.
270
270
271 When called, no more new commands may be issued. All outstanding
271 When called, no more new commands may be issued. All outstanding
272 commands that have previously been issued are waited on before
272 commands that have previously been issued are waited on before
273 returning. This not only includes waiting for the futures to resolve,
273 returning. This not only includes waiting for the futures to resolve,
274 but also waiting for all response data to arrive. In other words,
274 but also waiting for all response data to arrive. In other words,
275 calling this waits for all on-wire state for issued command requests
275 calling this waits for all on-wire state for issued command requests
276 to finish.
276 to finish.
277
277
278 When used as a context manager, this method is called when exiting the
278 When used as a context manager, this method is called when exiting the
279 context manager.
279 context manager.
280
280
281 This method may call ``sendcommands()`` if there are buffered commands.
281 This method may call ``sendcommands()`` if there are buffered commands.
282 """
282 """
283
283
284 class ipeerrequests(interfaceutil.Interface):
284 class ipeerrequests(interfaceutil.Interface):
285 """Interface for executing commands on a peer."""
285 """Interface for executing commands on a peer."""
286
286
287 def commandexecutor():
287 def commandexecutor():
288 """A context manager that resolves to an ipeercommandexecutor.
288 """A context manager that resolves to an ipeercommandexecutor.
289
289
290 The object this resolves to can be used to issue command requests
290 The object this resolves to can be used to issue command requests
291 to the peer.
291 to the peer.
292
292
293 Callers should call its ``callcommand`` method to issue command
293 Callers should call its ``callcommand`` method to issue command
294 requests.
294 requests.
295
295
296 A new executor should be obtained for each distinct set of commands
296 A new executor should be obtained for each distinct set of commands
297 (possibly just a single command) that the consumer wants to execute
297 (possibly just a single command) that the consumer wants to execute
298 as part of a single operation or round trip. This is because some
298 as part of a single operation or round trip. This is because some
299 peers are half-duplex and/or don't support persistent connections.
299 peers are half-duplex and/or don't support persistent connections.
300 e.g. in the case of HTTP peers, commands sent to an executor represent
300 e.g. in the case of HTTP peers, commands sent to an executor represent
301 a single HTTP request. While some peers may support multiple command
301 a single HTTP request. While some peers may support multiple command
302 sends over the wire per executor, consumers need to code to the least
302 sends over the wire per executor, consumers need to code to the least
303 capable peer. So it should be assumed that command executors buffer
303 capable peer. So it should be assumed that command executors buffer
304 called commands until they are told to send them and that each
304 called commands until they are told to send them and that each
305 command executor could result in a new connection or wire-level request
305 command executor could result in a new connection or wire-level request
306 being issued.
306 being issued.
307 """
307 """
308
308
309 class ipeerbase(ipeerconnection, ipeercapabilities, ipeerrequests):
309 class ipeerbase(ipeerconnection, ipeercapabilities, ipeerrequests):
310 """Unified interface for peer repositories.
310 """Unified interface for peer repositories.
311
311
312 All peer instances must conform to this interface.
312 All peer instances must conform to this interface.
313 """
313 """
314
314
315 class ipeerv2(ipeerconnection, ipeercapabilities, ipeerrequests):
315 class ipeerv2(ipeerconnection, ipeercapabilities, ipeerrequests):
316 """Unified peer interface for wire protocol version 2 peers."""
316 """Unified peer interface for wire protocol version 2 peers."""
317
317
318 apidescriptor = interfaceutil.Attribute(
318 apidescriptor = interfaceutil.Attribute(
319 """Data structure holding description of server API.""")
319 """Data structure holding description of server API.""")
320
320
321 @interfaceutil.implementer(ipeerbase)
321 @interfaceutil.implementer(ipeerbase)
322 class peer(object):
322 class peer(object):
323 """Base class for peer repositories."""
323 """Base class for peer repositories."""
324
324
325 def capable(self, name):
325 def capable(self, name):
326 caps = self.capabilities()
326 caps = self.capabilities()
327 if name in caps:
327 if name in caps:
328 return True
328 return True
329
329
330 name = '%s=' % name
330 name = '%s=' % name
331 for cap in caps:
331 for cap in caps:
332 if cap.startswith(name):
332 if cap.startswith(name):
333 return cap[len(name):]
333 return cap[len(name):]
334
334
335 return False
335 return False
336
336
337 def requirecap(self, name, purpose):
337 def requirecap(self, name, purpose):
338 if self.capable(name):
338 if self.capable(name):
339 return
339 return
340
340
341 raise error.CapabilityError(
341 raise error.CapabilityError(
342 _('cannot %s; remote repository does not support the %r '
342 _('cannot %s; remote repository does not support the %r '
343 'capability') % (purpose, name))
343 'capability') % (purpose, name))
344
344
345 class iverifyproblem(interfaceutil.Interface):
345 class iverifyproblem(interfaceutil.Interface):
346 """Represents a problem with the integrity of the repository.
346 """Represents a problem with the integrity of the repository.
347
347
348 Instances of this interface are emitted to describe an integrity issue
348 Instances of this interface are emitted to describe an integrity issue
349 with a repository (e.g. corrupt storage, missing data, etc).
349 with a repository (e.g. corrupt storage, missing data, etc).
350
350
351 Instances are essentially messages associated with severity.
351 Instances are essentially messages associated with severity.
352 """
352 """
353 warning = interfaceutil.Attribute(
353 warning = interfaceutil.Attribute(
354 """Message indicating a non-fatal problem.""")
354 """Message indicating a non-fatal problem.""")
355
355
356 error = interfaceutil.Attribute(
356 error = interfaceutil.Attribute(
357 """Message indicating a fatal problem.""")
357 """Message indicating a fatal problem.""")
358
358
359 node = interfaceutil.Attribute(
359 node = interfaceutil.Attribute(
360 """Revision encountering the problem.
360 """Revision encountering the problem.
361
361
362 ``None`` means the problem doesn't apply to a single revision.
362 ``None`` means the problem doesn't apply to a single revision.
363 """)
363 """)
364
364
365 class irevisiondelta(interfaceutil.Interface):
365 class irevisiondelta(interfaceutil.Interface):
366 """Represents a delta between one revision and another.
366 """Represents a delta between one revision and another.
367
367
368 Instances convey enough information to allow a revision to be exchanged
368 Instances convey enough information to allow a revision to be exchanged
369 with another repository.
369 with another repository.
370
370
371 Instances represent the fulltext revision data or a delta against
371 Instances represent the fulltext revision data or a delta against
372 another revision. Therefore the ``revision`` and ``delta`` attributes
372 another revision. Therefore the ``revision`` and ``delta`` attributes
373 are mutually exclusive.
373 are mutually exclusive.
374
374
375 Typically used for changegroup generation.
375 Typically used for changegroup generation.
376 """
376 """
377
377
378 node = interfaceutil.Attribute(
378 node = interfaceutil.Attribute(
379 """20 byte node of this revision.""")
379 """20 byte node of this revision.""")
380
380
381 p1node = interfaceutil.Attribute(
381 p1node = interfaceutil.Attribute(
382 """20 byte node of 1st parent of this revision.""")
382 """20 byte node of 1st parent of this revision.""")
383
383
384 p2node = interfaceutil.Attribute(
384 p2node = interfaceutil.Attribute(
385 """20 byte node of 2nd parent of this revision.""")
385 """20 byte node of 2nd parent of this revision.""")
386
386
387 linknode = interfaceutil.Attribute(
387 linknode = interfaceutil.Attribute(
388 """20 byte node of the changelog revision this node is linked to.""")
388 """20 byte node of the changelog revision this node is linked to.""")
389
389
390 flags = interfaceutil.Attribute(
390 flags = interfaceutil.Attribute(
391 """2 bytes of integer flags that apply to this revision.
391 """2 bytes of integer flags that apply to this revision.
392
392
393 This is a bitwise composition of the ``REVISION_FLAG_*`` constants.
393 This is a bitwise composition of the ``REVISION_FLAG_*`` constants.
394 """)
394 """)
395
395
396 basenode = interfaceutil.Attribute(
396 basenode = interfaceutil.Attribute(
397 """20 byte node of the revision this data is a delta against.
397 """20 byte node of the revision this data is a delta against.
398
398
399 ``nullid`` indicates that the revision is a full revision and not
399 ``nullid`` indicates that the revision is a full revision and not
400 a delta.
400 a delta.
401 """)
401 """)
402
402
403 baserevisionsize = interfaceutil.Attribute(
403 baserevisionsize = interfaceutil.Attribute(
404 """Size of base revision this delta is against.
404 """Size of base revision this delta is against.
405
405
406 May be ``None`` if ``basenode`` is ``nullid``.
406 May be ``None`` if ``basenode`` is ``nullid``.
407 """)
407 """)
408
408
409 revision = interfaceutil.Attribute(
409 revision = interfaceutil.Attribute(
410 """Raw fulltext of revision data for this node.""")
410 """Raw fulltext of revision data for this node.""")
411
411
412 delta = interfaceutil.Attribute(
412 delta = interfaceutil.Attribute(
413 """Delta between ``basenode`` and ``node``.
413 """Delta between ``basenode`` and ``node``.
414
414
415 Stored in the bdiff delta format.
415 Stored in the bdiff delta format.
416 """)
416 """)
417
417
418 class ifilerevisionssequence(interfaceutil.Interface):
418 class ifilerevisionssequence(interfaceutil.Interface):
419 """Contains index data for all revisions of a file.
419 """Contains index data for all revisions of a file.
420
420
421 Types implementing this behave like lists of tuples. The index
421 Types implementing this behave like lists of tuples. The index
422 in the list corresponds to the revision number. The values contain
422 in the list corresponds to the revision number. The values contain
423 index metadata.
423 index metadata.
424
424
425 The *null* revision (revision number -1) is always the last item
425 The *null* revision (revision number -1) is always the last item
426 in the index.
426 in the index.
427 """
427 """
428
428
429 def __len__():
429 def __len__():
430 """The total number of revisions."""
430 """The total number of revisions."""
431
431
432 def __getitem__(rev):
432 def __getitem__(rev):
433 """Returns the object having a specific revision number.
433 """Returns the object having a specific revision number.
434
434
435 Returns an 8-tuple with the following fields:
435 Returns an 8-tuple with the following fields:
436
436
437 offset+flags
437 offset+flags
438 Contains the offset and flags for the revision. 64-bit unsigned
438 Contains the offset and flags for the revision. 64-bit unsigned
439 integer where first 6 bytes are the offset and the next 2 bytes
439 integer where first 6 bytes are the offset and the next 2 bytes
440 are flags. The offset can be 0 if it is not used by the store.
440 are flags. The offset can be 0 if it is not used by the store.
441 compressed size
441 compressed size
442 Size of the revision data in the store. It can be 0 if it isn't
442 Size of the revision data in the store. It can be 0 if it isn't
443 needed by the store.
443 needed by the store.
444 uncompressed size
444 uncompressed size
445 Fulltext size. It can be 0 if it isn't needed by the store.
445 Fulltext size. It can be 0 if it isn't needed by the store.
446 base revision
446 base revision
447 Revision number of revision the delta for storage is encoded
447 Revision number of revision the delta for storage is encoded
448 against. -1 indicates not encoded against a base revision.
448 against. -1 indicates not encoded against a base revision.
449 link revision
449 link revision
450 Revision number of changelog revision this entry is related to.
450 Revision number of changelog revision this entry is related to.
451 p1 revision
451 p1 revision
452 Revision number of 1st parent. -1 if no 1st parent.
452 Revision number of 1st parent. -1 if no 1st parent.
453 p2 revision
453 p2 revision
454 Revision number of 2nd parent. -1 if no 1st parent.
454 Revision number of 2nd parent. -1 if no 1st parent.
455 node
455 node
456 Binary node value for this revision number.
456 Binary node value for this revision number.
457
457
458 Negative values should index off the end of the sequence. ``-1``
458 Negative values should index off the end of the sequence. ``-1``
459 should return the null revision. ``-2`` should return the most
459 should return the null revision. ``-2`` should return the most
460 recent revision.
460 recent revision.
461 """
461 """
462
462
463 def __contains__(rev):
463 def __contains__(rev):
464 """Whether a revision number exists."""
464 """Whether a revision number exists."""
465
465
466 def insert(self, i, entry):
466 def insert(self, i, entry):
467 """Add an item to the index at specific revision."""
467 """Add an item to the index at specific revision."""
468
468
469 class ifileindex(interfaceutil.Interface):
469 class ifileindex(interfaceutil.Interface):
470 """Storage interface for index data of a single file.
470 """Storage interface for index data of a single file.
471
471
472 File storage data is divided into index metadata and data storage.
472 File storage data is divided into index metadata and data storage.
473 This interface defines the index portion of the interface.
473 This interface defines the index portion of the interface.
474
474
475 The index logically consists of:
475 The index logically consists of:
476
476
477 * A mapping between revision numbers and nodes.
477 * A mapping between revision numbers and nodes.
478 * DAG data (storing and querying the relationship between nodes).
478 * DAG data (storing and querying the relationship between nodes).
479 * Metadata to facilitate storage.
479 * Metadata to facilitate storage.
480 """
480 """
481 def __len__():
481 def __len__():
482 """Obtain the number of revisions stored for this file."""
482 """Obtain the number of revisions stored for this file."""
483
483
484 def __iter__():
484 def __iter__():
485 """Iterate over revision numbers for this file."""
485 """Iterate over revision numbers for this file."""
486
486
487 def revs(start=0, stop=None):
487 def revs(start=0, stop=None):
488 """Iterate over revision numbers for this file, with control."""
488 """Iterate over revision numbers for this file, with control."""
489
489
490 def parents(node):
490 def parents(node):
491 """Returns a 2-tuple of parent nodes for a revision.
491 """Returns a 2-tuple of parent nodes for a revision.
492
492
493 Values will be ``nullid`` if the parent is empty.
493 Values will be ``nullid`` if the parent is empty.
494 """
494 """
495
495
496 def parentrevs(rev):
496 def parentrevs(rev):
497 """Like parents() but operates on revision numbers."""
497 """Like parents() but operates on revision numbers."""
498
498
499 def rev(node):
499 def rev(node):
500 """Obtain the revision number given a node.
500 """Obtain the revision number given a node.
501
501
502 Raises ``error.LookupError`` if the node is not known.
502 Raises ``error.LookupError`` if the node is not known.
503 """
503 """
504
504
505 def node(rev):
505 def node(rev):
506 """Obtain the node value given a revision number.
506 """Obtain the node value given a revision number.
507
507
508 Raises ``IndexError`` if the node is not known.
508 Raises ``IndexError`` if the node is not known.
509 """
509 """
510
510
511 def lookup(node):
511 def lookup(node):
512 """Attempt to resolve a value to a node.
512 """Attempt to resolve a value to a node.
513
513
514 Value can be a binary node, hex node, revision number, or a string
514 Value can be a binary node, hex node, revision number, or a string
515 that can be converted to an integer.
515 that can be converted to an integer.
516
516
517 Raises ``error.LookupError`` if a node could not be resolved.
517 Raises ``error.LookupError`` if a node could not be resolved.
518 """
518 """
519
519
520 def linkrev(rev):
520 def linkrev(rev):
521 """Obtain the changeset revision number a revision is linked to."""
521 """Obtain the changeset revision number a revision is linked to."""
522
522
523 def iscensored(rev):
523 def iscensored(rev):
524 """Return whether a revision's content has been censored."""
524 """Return whether a revision's content has been censored."""
525
525
526 def commonancestorsheads(node1, node2):
526 def commonancestorsheads(node1, node2):
527 """Obtain an iterable of nodes containing heads of common ancestors.
527 """Obtain an iterable of nodes containing heads of common ancestors.
528
528
529 See ``ancestor.commonancestorsheads()``.
529 See ``ancestor.commonancestorsheads()``.
530 """
530 """
531
531
532 def descendants(revs):
532 def descendants(revs):
533 """Obtain descendant revision numbers for a set of revision numbers.
533 """Obtain descendant revision numbers for a set of revision numbers.
534
534
535 If ``nullrev`` is in the set, this is equivalent to ``revs()``.
535 If ``nullrev`` is in the set, this is equivalent to ``revs()``.
536 """
536 """
537
537
538 def heads(start=None, stop=None):
538 def heads(start=None, stop=None):
539 """Obtain a list of nodes that are DAG heads, with control.
539 """Obtain a list of nodes that are DAG heads, with control.
540
540
541 The set of revisions examined can be limited by specifying
541 The set of revisions examined can be limited by specifying
542 ``start`` and ``stop``. ``start`` is a node. ``stop`` is an
542 ``start`` and ``stop``. ``start`` is a node. ``stop`` is an
543 iterable of nodes. DAG traversal starts at earlier revision
543 iterable of nodes. DAG traversal starts at earlier revision
544 ``start`` and iterates forward until any node in ``stop`` is
544 ``start`` and iterates forward until any node in ``stop`` is
545 encountered.
545 encountered.
546 """
546 """
547
547
548 def children(node):
548 def children(node):
549 """Obtain nodes that are children of a node.
549 """Obtain nodes that are children of a node.
550
550
551 Returns a list of nodes.
551 Returns a list of nodes.
552 """
552 """
553
553
554 class ifiledata(interfaceutil.Interface):
554 class ifiledata(interfaceutil.Interface):
555 """Storage interface for data storage of a specific file.
555 """Storage interface for data storage of a specific file.
556
556
557 This complements ``ifileindex`` and provides an interface for accessing
557 This complements ``ifileindex`` and provides an interface for accessing
558 data for a tracked file.
558 data for a tracked file.
559 """
559 """
560 def size(rev):
560 def size(rev):
561 """Obtain the fulltext size of file data.
561 """Obtain the fulltext size of file data.
562
562
563 Any metadata is excluded from size measurements.
563 Any metadata is excluded from size measurements.
564 """
564 """
565
565
566 def revision(node, raw=False):
566 def revision(node, raw=False):
567 """"Obtain fulltext data for a node.
567 """"Obtain fulltext data for a node.
568
568
569 By default, any storage transformations are applied before the data
569 By default, any storage transformations are applied before the data
570 is returned. If ``raw`` is True, non-raw storage transformations
570 is returned. If ``raw`` is True, non-raw storage transformations
571 are not applied.
571 are not applied.
572
572
573 The fulltext data may contain a header containing metadata. Most
573 The fulltext data may contain a header containing metadata. Most
574 consumers should use ``read()`` to obtain the actual file data.
574 consumers should use ``read()`` to obtain the actual file data.
575 """
575 """
576
576
577 def read(node):
577 def read(node):
578 """Resolve file fulltext data.
578 """Resolve file fulltext data.
579
579
580 This is similar to ``revision()`` except any metadata in the data
580 This is similar to ``revision()`` except any metadata in the data
581 headers is stripped.
581 headers is stripped.
582 """
582 """
583
583
584 def renamed(node):
584 def renamed(node):
585 """Obtain copy metadata for a node.
585 """Obtain copy metadata for a node.
586
586
587 Returns ``False`` if no copy metadata is stored or a 2-tuple of
587 Returns ``False`` if no copy metadata is stored or a 2-tuple of
588 (path, node) from which this revision was copied.
588 (path, node) from which this revision was copied.
589 """
589 """
590
590
591 def cmp(node, fulltext):
591 def cmp(node, fulltext):
592 """Compare fulltext to another revision.
592 """Compare fulltext to another revision.
593
593
594 Returns True if the fulltext is different from what is stored.
594 Returns True if the fulltext is different from what is stored.
595
595
596 This takes copy metadata into account.
596 This takes copy metadata into account.
597
597
598 TODO better document the copy metadata and censoring logic.
598 TODO better document the copy metadata and censoring logic.
599 """
599 """
600
600
601 def emitrevisions(nodes,
601 def emitrevisions(nodes,
602 nodesorder=None,
602 nodesorder=None,
603 revisiondata=False,
603 revisiondata=False,
604 assumehaveparentrevisions=False,
604 assumehaveparentrevisions=False,
605 deltaprevious=False):
605 deltaprevious=False):
606 """Produce ``irevisiondelta`` for revisions.
606 """Produce ``irevisiondelta`` for revisions.
607
607
608 Given an iterable of nodes, emits objects conforming to the
608 Given an iterable of nodes, emits objects conforming to the
609 ``irevisiondelta`` interface that describe revisions in storage.
609 ``irevisiondelta`` interface that describe revisions in storage.
610
610
611 This method is a generator.
611 This method is a generator.
612
612
613 The input nodes may be unordered. Implementations must ensure that a
613 The input nodes may be unordered. Implementations must ensure that a
614 node's parents are emitted before the node itself. Transitively, this
614 node's parents are emitted before the node itself. Transitively, this
615 means that a node may only be emitted once all its ancestors in
615 means that a node may only be emitted once all its ancestors in
616 ``nodes`` have also been emitted.
616 ``nodes`` have also been emitted.
617
617
618 By default, emits "index" data (the ``node``, ``p1node``, and
618 By default, emits "index" data (the ``node``, ``p1node``, and
619 ``p2node`` attributes). If ``revisiondata`` is set, revision data
619 ``p2node`` attributes). If ``revisiondata`` is set, revision data
620 will also be present on the emitted objects.
620 will also be present on the emitted objects.
621
621
622 With default argument values, implementations can choose to emit
622 With default argument values, implementations can choose to emit
623 either fulltext revision data or a delta. When emitting deltas,
623 either fulltext revision data or a delta. When emitting deltas,
624 implementations must consider whether the delta's base revision
624 implementations must consider whether the delta's base revision
625 fulltext is available to the receiver.
625 fulltext is available to the receiver.
626
626
627 The base revision fulltext is guaranteed to be available if any of
627 The base revision fulltext is guaranteed to be available if any of
628 the following are met:
628 the following are met:
629
629
630 * Its fulltext revision was emitted by this method call.
630 * Its fulltext revision was emitted by this method call.
631 * A delta for that revision was emitted by this method call.
631 * A delta for that revision was emitted by this method call.
632 * ``assumehaveparentrevisions`` is True and the base revision is a
632 * ``assumehaveparentrevisions`` is True and the base revision is a
633 parent of the node.
633 parent of the node.
634
634
635 ``nodesorder`` can be used to control the order that revisions are
635 ``nodesorder`` can be used to control the order that revisions are
636 emitted. By default, revisions can be reordered as long as they are
636 emitted. By default, revisions can be reordered as long as they are
637 in DAG topological order (see above). If the value is ``nodes``,
637 in DAG topological order (see above). If the value is ``nodes``,
638 the iteration order from ``nodes`` should be used. If the value is
638 the iteration order from ``nodes`` should be used. If the value is
639 ``storage``, then the native order from the backing storage layer
639 ``storage``, then the native order from the backing storage layer
640 is used. (Not all storage layers will have strong ordering and behavior
640 is used. (Not all storage layers will have strong ordering and behavior
641 of this mode is storage-dependent.) ``nodes`` ordering can force
641 of this mode is storage-dependent.) ``nodes`` ordering can force
642 revisions to be emitted before their ancestors, so consumers should
642 revisions to be emitted before their ancestors, so consumers should
643 use it with care.
643 use it with care.
644
644
645 The ``linknode`` attribute on the returned ``irevisiondelta`` may not
645 The ``linknode`` attribute on the returned ``irevisiondelta`` may not
646 be set and it is the caller's responsibility to resolve it, if needed.
646 be set and it is the caller's responsibility to resolve it, if needed.
647
647
648 If ``deltaprevious`` is True and revision data is requested, all
648 If ``deltaprevious`` is True and revision data is requested, all
649 revision data should be emitted as deltas against the revision
649 revision data should be emitted as deltas against the revision
650 emitted just prior. The initial revision should be a delta against
650 emitted just prior. The initial revision should be a delta against
651 its 1st parent.
651 its 1st parent.
652 """
652 """
653
653
654 class ifilemutation(interfaceutil.Interface):
654 class ifilemutation(interfaceutil.Interface):
655 """Storage interface for mutation events of a tracked file."""
655 """Storage interface for mutation events of a tracked file."""
656
656
657 def add(filedata, meta, transaction, linkrev, p1, p2):
657 def add(filedata, meta, transaction, linkrev, p1, p2):
658 """Add a new revision to the store.
658 """Add a new revision to the store.
659
659
660 Takes file data, dictionary of metadata, a transaction, linkrev,
660 Takes file data, dictionary of metadata, a transaction, linkrev,
661 and parent nodes.
661 and parent nodes.
662
662
663 Returns the node that was added.
663 Returns the node that was added.
664
664
665 May no-op if a revision matching the supplied data is already stored.
665 May no-op if a revision matching the supplied data is already stored.
666 """
666 """
667
667
668 def addrevision(revisiondata, transaction, linkrev, p1, p2, node=None,
668 def addrevision(revisiondata, transaction, linkrev, p1, p2, node=None,
669 flags=0, cachedelta=None):
669 flags=0, cachedelta=None):
670 """Add a new revision to the store.
670 """Add a new revision to the store.
671
671
672 This is similar to ``add()`` except it operates at a lower level.
672 This is similar to ``add()`` except it operates at a lower level.
673
673
674 The data passed in already contains a metadata header, if any.
674 The data passed in already contains a metadata header, if any.
675
675
676 ``node`` and ``flags`` can be used to define the expected node and
676 ``node`` and ``flags`` can be used to define the expected node and
677 the flags to use with storage. ``flags`` is a bitwise value composed
677 the flags to use with storage. ``flags`` is a bitwise value composed
678 of the various ``REVISION_FLAG_*`` constants.
678 of the various ``REVISION_FLAG_*`` constants.
679
679
680 ``add()`` is usually called when adding files from e.g. the working
680 ``add()`` is usually called when adding files from e.g. the working
681 directory. ``addrevision()`` is often called by ``add()`` and for
681 directory. ``addrevision()`` is often called by ``add()`` and for
682 scenarios where revision data has already been computed, such as when
682 scenarios where revision data has already been computed, such as when
683 applying raw data from a peer repo.
683 applying raw data from a peer repo.
684 """
684 """
685
685
686 def addgroup(deltas, linkmapper, transaction, addrevisioncb=None):
686 def addgroup(deltas, linkmapper, transaction, addrevisioncb=None):
687 """Process a series of deltas for storage.
687 """Process a series of deltas for storage.
688
688
689 ``deltas`` is an iterable of 7-tuples of
689 ``deltas`` is an iterable of 7-tuples of
690 (node, p1, p2, linknode, deltabase, delta, flags) defining revisions
690 (node, p1, p2, linknode, deltabase, delta, flags) defining revisions
691 to add.
691 to add.
692
692
693 The ``delta`` field contains ``mpatch`` data to apply to a base
693 The ``delta`` field contains ``mpatch`` data to apply to a base
694 revision, identified by ``deltabase``. The base node can be
694 revision, identified by ``deltabase``. The base node can be
695 ``nullid``, in which case the header from the delta can be ignored
695 ``nullid``, in which case the header from the delta can be ignored
696 and the delta used as the fulltext.
696 and the delta used as the fulltext.
697
697
698 ``addrevisioncb`` should be called for each node as it is committed.
698 ``addrevisioncb`` should be called for each node as it is committed.
699
699
700 Returns a list of nodes that were processed. A node will be in the list
700 Returns a list of nodes that were processed. A node will be in the list
701 even if it existed in the store previously.
701 even if it existed in the store previously.
702 """
702 """
703
703
704 def censorrevision(tr, node, tombstone=b''):
704 def censorrevision(tr, node, tombstone=b''):
705 """Remove the content of a single revision.
705 """Remove the content of a single revision.
706
706
707 The specified ``node`` will have its content purged from storage.
707 The specified ``node`` will have its content purged from storage.
708 Future attempts to access the revision data for this node will
708 Future attempts to access the revision data for this node will
709 result in failure.
709 result in failure.
710
710
711 A ``tombstone`` message can optionally be stored. This message may be
711 A ``tombstone`` message can optionally be stored. This message may be
712 displayed to users when they attempt to access the missing revision
712 displayed to users when they attempt to access the missing revision
713 data.
713 data.
714
714
715 Storage backends may have stored deltas against the previous content
715 Storage backends may have stored deltas against the previous content
716 in this revision. As part of censoring a revision, these storage
716 in this revision. As part of censoring a revision, these storage
717 backends are expected to rewrite any internally stored deltas such
717 backends are expected to rewrite any internally stored deltas such
718 that they no longer reference the deleted content.
718 that they no longer reference the deleted content.
719 """
719 """
720
720
721 def getstrippoint(minlink):
721 def getstrippoint(minlink):
722 """Find the minimum revision that must be stripped to strip a linkrev.
722 """Find the minimum revision that must be stripped to strip a linkrev.
723
723
724 Returns a 2-tuple containing the minimum revision number and a set
724 Returns a 2-tuple containing the minimum revision number and a set
725 of all revisions numbers that would be broken by this strip.
725 of all revisions numbers that would be broken by this strip.
726
726
727 TODO this is highly revlog centric and should be abstracted into
727 TODO this is highly revlog centric and should be abstracted into
728 a higher-level deletion API. ``repair.strip()`` relies on this.
728 a higher-level deletion API. ``repair.strip()`` relies on this.
729 """
729 """
730
730
731 def strip(minlink, transaction):
731 def strip(minlink, transaction):
732 """Remove storage of items starting at a linkrev.
732 """Remove storage of items starting at a linkrev.
733
733
734 This uses ``getstrippoint()`` to determine the first node to remove.
734 This uses ``getstrippoint()`` to determine the first node to remove.
735 Then it effectively truncates storage for all revisions after that.
735 Then it effectively truncates storage for all revisions after that.
736
736
737 TODO this is highly revlog centric and should be abstracted into a
737 TODO this is highly revlog centric and should be abstracted into a
738 higher-level deletion API.
738 higher-level deletion API.
739 """
739 """
740
740
741 class ifilestorage(ifileindex, ifiledata, ifilemutation):
741 class ifilestorage(ifileindex, ifiledata, ifilemutation):
742 """Complete storage interface for a single tracked file."""
742 """Complete storage interface for a single tracked file."""
743
743
744 def files():
744 def files():
745 """Obtain paths that are backing storage for this file.
745 """Obtain paths that are backing storage for this file.
746
746
747 TODO this is used heavily by verify code and there should probably
747 TODO this is used heavily by verify code and there should probably
748 be a better API for that.
748 be a better API for that.
749 """
749 """
750
750
751 def storageinfo(exclusivefiles=False, sharedfiles=False,
751 def storageinfo(exclusivefiles=False, sharedfiles=False,
752 revisionscount=False, trackedsize=False,
752 revisionscount=False, trackedsize=False,
753 storedsize=False):
753 storedsize=False):
754 """Obtain information about storage for this file's data.
754 """Obtain information about storage for this file's data.
755
755
756 Returns a dict describing storage for this tracked path. The keys
756 Returns a dict describing storage for this tracked path. The keys
757 in the dict map to arguments of the same. The arguments are bools
757 in the dict map to arguments of the same. The arguments are bools
758 indicating whether to calculate and obtain that data.
758 indicating whether to calculate and obtain that data.
759
759
760 exclusivefiles
760 exclusivefiles
761 Iterable of (vfs, path) describing files that are exclusively
761 Iterable of (vfs, path) describing files that are exclusively
762 used to back storage for this tracked path.
762 used to back storage for this tracked path.
763
763
764 sharedfiles
764 sharedfiles
765 Iterable of (vfs, path) describing files that are used to back
765 Iterable of (vfs, path) describing files that are used to back
766 storage for this tracked path. Those files may also provide storage
766 storage for this tracked path. Those files may also provide storage
767 for other stored entities.
767 for other stored entities.
768
768
769 revisionscount
769 revisionscount
770 Number of revisions available for retrieval.
770 Number of revisions available for retrieval.
771
771
772 trackedsize
772 trackedsize
773 Total size in bytes of all tracked revisions. This is a sum of the
773 Total size in bytes of all tracked revisions. This is a sum of the
774 length of the fulltext of all revisions.
774 length of the fulltext of all revisions.
775
775
776 storedsize
776 storedsize
777 Total size in bytes used to store data for all tracked revisions.
777 Total size in bytes used to store data for all tracked revisions.
778 This is commonly less than ``trackedsize`` due to internal usage
778 This is commonly less than ``trackedsize`` due to internal usage
779 of deltas rather than fulltext revisions.
779 of deltas rather than fulltext revisions.
780
780
781 Not all storage backends may support all queries are have a reasonable
781 Not all storage backends may support all queries are have a reasonable
782 value to use. In that case, the value should be set to ``None`` and
782 value to use. In that case, the value should be set to ``None`` and
783 callers are expected to handle this special value.
783 callers are expected to handle this special value.
784 """
784 """
785
785
786 def verifyintegrity(state):
786 def verifyintegrity(state):
787 """Verifies the integrity of file storage.
787 """Verifies the integrity of file storage.
788
788
789 ``state`` is a dict holding state of the verifier process. It can be
789 ``state`` is a dict holding state of the verifier process. It can be
790 used to communicate data between invocations of multiple storage
790 used to communicate data between invocations of multiple storage
791 primitives.
791 primitives.
792
792
793 If individual revisions cannot have their revision content resolved,
793 If individual revisions cannot have their revision content resolved,
794 the method is expected to set the ``skipread`` key to a set of nodes
794 the method is expected to set the ``skipread`` key to a set of nodes
795 that encountered problems.
795 that encountered problems.
796
796
797 The method yields objects conforming to the ``iverifyproblem``
797 The method yields objects conforming to the ``iverifyproblem``
798 interface.
798 interface.
799 """
799 """
800
800
801 class idirs(interfaceutil.Interface):
801 class idirs(interfaceutil.Interface):
802 """Interface representing a collection of directories from paths.
802 """Interface representing a collection of directories from paths.
803
803
804 This interface is essentially a derived data structure representing
804 This interface is essentially a derived data structure representing
805 directories from a collection of paths.
805 directories from a collection of paths.
806 """
806 """
807
807
808 def addpath(path):
808 def addpath(path):
809 """Add a path to the collection.
809 """Add a path to the collection.
810
810
811 All directories in the path will be added to the collection.
811 All directories in the path will be added to the collection.
812 """
812 """
813
813
814 def delpath(path):
814 def delpath(path):
815 """Remove a path from the collection.
815 """Remove a path from the collection.
816
816
817 If the removal was the last path in a particular directory, the
817 If the removal was the last path in a particular directory, the
818 directory is removed from the collection.
818 directory is removed from the collection.
819 """
819 """
820
820
821 def __iter__():
821 def __iter__():
822 """Iterate over the directories in this collection of paths."""
822 """Iterate over the directories in this collection of paths."""
823
823
824 def __contains__(path):
824 def __contains__(path):
825 """Whether a specific directory is in this collection."""
825 """Whether a specific directory is in this collection."""
826
826
827 class imanifestdict(interfaceutil.Interface):
827 class imanifestdict(interfaceutil.Interface):
828 """Interface representing a manifest data structure.
828 """Interface representing a manifest data structure.
829
829
830 A manifest is effectively a dict mapping paths to entries. Each entry
830 A manifest is effectively a dict mapping paths to entries. Each entry
831 consists of a binary node and extra flags affecting that entry.
831 consists of a binary node and extra flags affecting that entry.
832 """
832 """
833
833
834 def __getitem__(path):
834 def __getitem__(path):
835 """Returns the binary node value for a path in the manifest.
835 """Returns the binary node value for a path in the manifest.
836
836
837 Raises ``KeyError`` if the path does not exist in the manifest.
837 Raises ``KeyError`` if the path does not exist in the manifest.
838
838
839 Equivalent to ``self.find(path)[0]``.
839 Equivalent to ``self.find(path)[0]``.
840 """
840 """
841
841
842 def find(path):
842 def find(path):
843 """Returns the entry for a path in the manifest.
843 """Returns the entry for a path in the manifest.
844
844
845 Returns a 2-tuple of (node, flags).
845 Returns a 2-tuple of (node, flags).
846
846
847 Raises ``KeyError`` if the path does not exist in the manifest.
847 Raises ``KeyError`` if the path does not exist in the manifest.
848 """
848 """
849
849
850 def __len__():
850 def __len__():
851 """Return the number of entries in the manifest."""
851 """Return the number of entries in the manifest."""
852
852
853 def __nonzero__():
853 def __nonzero__():
854 """Returns True if the manifest has entries, False otherwise."""
854 """Returns True if the manifest has entries, False otherwise."""
855
855
856 __bool__ = __nonzero__
856 __bool__ = __nonzero__
857
857
858 def __setitem__(path, node):
858 def __setitem__(path, node):
859 """Define the node value for a path in the manifest.
859 """Define the node value for a path in the manifest.
860
860
861 If the path is already in the manifest, its flags will be copied to
861 If the path is already in the manifest, its flags will be copied to
862 the new entry.
862 the new entry.
863 """
863 """
864
864
865 def __contains__(path):
865 def __contains__(path):
866 """Whether a path exists in the manifest."""
866 """Whether a path exists in the manifest."""
867
867
868 def __delitem__(path):
868 def __delitem__(path):
869 """Remove a path from the manifest.
869 """Remove a path from the manifest.
870
870
871 Raises ``KeyError`` if the path is not in the manifest.
871 Raises ``KeyError`` if the path is not in the manifest.
872 """
872 """
873
873
874 def __iter__():
874 def __iter__():
875 """Iterate over paths in the manifest."""
875 """Iterate over paths in the manifest."""
876
876
877 def iterkeys():
877 def iterkeys():
878 """Iterate over paths in the manifest."""
878 """Iterate over paths in the manifest."""
879
879
880 def keys():
880 def keys():
881 """Obtain a list of paths in the manifest."""
881 """Obtain a list of paths in the manifest."""
882
882
883 def filesnotin(other, match=None):
883 def filesnotin(other, match=None):
884 """Obtain the set of paths in this manifest but not in another.
884 """Obtain the set of paths in this manifest but not in another.
885
885
886 ``match`` is an optional matcher function to be applied to both
886 ``match`` is an optional matcher function to be applied to both
887 manifests.
887 manifests.
888
888
889 Returns a set of paths.
889 Returns a set of paths.
890 """
890 """
891
891
892 def dirs():
892 def dirs():
893 """Returns an object implementing the ``idirs`` interface."""
893 """Returns an object implementing the ``idirs`` interface."""
894
894
895 def hasdir(dir):
895 def hasdir(dir):
896 """Returns a bool indicating if a directory is in this manifest."""
896 """Returns a bool indicating if a directory is in this manifest."""
897
897
898 def matches(match):
898 def matches(match):
899 """Generate a new manifest filtered through a matcher.
899 """Generate a new manifest filtered through a matcher.
900
900
901 Returns an object conforming to the ``imanifestdict`` interface.
901 Returns an object conforming to the ``imanifestdict`` interface.
902 """
902 """
903
903
904 def walk(match):
904 def walk(match):
905 """Generator of paths in manifest satisfying a matcher.
905 """Generator of paths in manifest satisfying a matcher.
906
906
907 This is equivalent to ``self.matches(match).iterkeys()`` except a new
907 This is equivalent to ``self.matches(match).iterkeys()`` except a new
908 manifest object is not created.
908 manifest object is not created.
909
909
910 If the matcher has explicit files listed and they don't exist in
910 If the matcher has explicit files listed and they don't exist in
911 the manifest, ``match.bad()`` is called for each missing file.
911 the manifest, ``match.bad()`` is called for each missing file.
912 """
912 """
913
913
914 def diff(other, match=None, clean=False):
914 def diff(other, match=None, clean=False):
915 """Find differences between this manifest and another.
915 """Find differences between this manifest and another.
916
916
917 This manifest is compared to ``other``.
917 This manifest is compared to ``other``.
918
918
919 If ``match`` is provided, the two manifests are filtered against this
919 If ``match`` is provided, the two manifests are filtered against this
920 matcher and only entries satisfying the matcher are compared.
920 matcher and only entries satisfying the matcher are compared.
921
921
922 If ``clean`` is True, unchanged files are included in the returned
922 If ``clean`` is True, unchanged files are included in the returned
923 object.
923 object.
924
924
925 Returns a dict with paths as keys and values of 2-tuples of 2-tuples of
925 Returns a dict with paths as keys and values of 2-tuples of 2-tuples of
926 the form ``((node1, flag1), (node2, flag2))`` where ``(node1, flag1)``
926 the form ``((node1, flag1), (node2, flag2))`` where ``(node1, flag1)``
927 represents the node and flags for this manifest and ``(node2, flag2)``
927 represents the node and flags for this manifest and ``(node2, flag2)``
928 are the same for the other manifest.
928 are the same for the other manifest.
929 """
929 """
930
930
931 def setflag(path, flag):
931 def setflag(path, flag):
932 """Set the flag value for a given path.
932 """Set the flag value for a given path.
933
933
934 Raises ``KeyError`` if the path is not already in the manifest.
934 Raises ``KeyError`` if the path is not already in the manifest.
935 """
935 """
936
936
937 def get(path, default=None):
937 def get(path, default=None):
938 """Obtain the node value for a path or a default value if missing."""
938 """Obtain the node value for a path or a default value if missing."""
939
939
940 def flags(path, default=''):
940 def flags(path, default=''):
941 """Return the flags value for a path or a default value if missing."""
941 """Return the flags value for a path or a default value if missing."""
942
942
943 def copy():
943 def copy():
944 """Return a copy of this manifest."""
944 """Return a copy of this manifest."""
945
945
946 def items():
946 def items():
947 """Returns an iterable of (path, node) for items in this manifest."""
947 """Returns an iterable of (path, node) for items in this manifest."""
948
948
949 def iteritems():
949 def iteritems():
950 """Identical to items()."""
950 """Identical to items()."""
951
951
952 def iterentries():
952 def iterentries():
953 """Returns an iterable of (path, node, flags) for this manifest.
953 """Returns an iterable of (path, node, flags) for this manifest.
954
954
955 Similar to ``iteritems()`` except items are a 3-tuple and include
955 Similar to ``iteritems()`` except items are a 3-tuple and include
956 flags.
956 flags.
957 """
957 """
958
958
959 def text():
959 def text():
960 """Obtain the raw data representation for this manifest.
960 """Obtain the raw data representation for this manifest.
961
961
962 Result is used to create a manifest revision.
962 Result is used to create a manifest revision.
963 """
963 """
964
964
965 def fastdelta(base, changes):
965 def fastdelta(base, changes):
966 """Obtain a delta between this manifest and another given changes.
966 """Obtain a delta between this manifest and another given changes.
967
967
968 ``base`` in the raw data representation for another manifest.
968 ``base`` in the raw data representation for another manifest.
969
969
970 ``changes`` is an iterable of ``(path, to_delete)``.
970 ``changes`` is an iterable of ``(path, to_delete)``.
971
971
972 Returns a 2-tuple containing ``bytearray(self.text())`` and the
972 Returns a 2-tuple containing ``bytearray(self.text())`` and the
973 delta between ``base`` and this manifest.
973 delta between ``base`` and this manifest.
974 """
974 """
975
975
976 class imanifestrevisionbase(interfaceutil.Interface):
976 class imanifestrevisionbase(interfaceutil.Interface):
977 """Base interface representing a single revision of a manifest.
977 """Base interface representing a single revision of a manifest.
978
978
979 Should not be used as a primary interface: should always be inherited
979 Should not be used as a primary interface: should always be inherited
980 as part of a larger interface.
980 as part of a larger interface.
981 """
981 """
982
982
983 def new():
983 def new():
984 """Obtain a new manifest instance.
984 """Obtain a new manifest instance.
985
985
986 Returns an object conforming to the ``imanifestrevisionwritable``
986 Returns an object conforming to the ``imanifestrevisionwritable``
987 interface. The instance will be associated with the same
987 interface. The instance will be associated with the same
988 ``imanifestlog`` collection as this instance.
988 ``imanifestlog`` collection as this instance.
989 """
989 """
990
990
991 def copy():
991 def copy():
992 """Obtain a copy of this manifest instance.
992 """Obtain a copy of this manifest instance.
993
993
994 Returns an object conforming to the ``imanifestrevisionwritable``
994 Returns an object conforming to the ``imanifestrevisionwritable``
995 interface. The instance will be associated with the same
995 interface. The instance will be associated with the same
996 ``imanifestlog`` collection as this instance.
996 ``imanifestlog`` collection as this instance.
997 """
997 """
998
998
999 def read():
999 def read():
1000 """Obtain the parsed manifest data structure.
1000 """Obtain the parsed manifest data structure.
1001
1001
1002 The returned object conforms to the ``imanifestdict`` interface.
1002 The returned object conforms to the ``imanifestdict`` interface.
1003 """
1003 """
1004
1004
1005 class imanifestrevisionstored(imanifestrevisionbase):
1005 class imanifestrevisionstored(imanifestrevisionbase):
1006 """Interface representing a manifest revision committed to storage."""
1006 """Interface representing a manifest revision committed to storage."""
1007
1007
1008 def node():
1008 def node():
1009 """The binary node for this manifest."""
1009 """The binary node for this manifest."""
1010
1010
1011 parents = interfaceutil.Attribute(
1011 parents = interfaceutil.Attribute(
1012 """List of binary nodes that are parents for this manifest revision."""
1012 """List of binary nodes that are parents for this manifest revision."""
1013 )
1013 )
1014
1014
1015 def readdelta(shallow=False):
1015 def readdelta(shallow=False):
1016 """Obtain the manifest data structure representing changes from parent.
1016 """Obtain the manifest data structure representing changes from parent.
1017
1017
1018 This manifest is compared to its 1st parent. A new manifest representing
1018 This manifest is compared to its 1st parent. A new manifest representing
1019 those differences is constructed.
1019 those differences is constructed.
1020
1020
1021 The returned object conforms to the ``imanifestdict`` interface.
1021 The returned object conforms to the ``imanifestdict`` interface.
1022 """
1022 """
1023
1023
1024 def readfast(shallow=False):
1024 def readfast(shallow=False):
1025 """Calls either ``read()`` or ``readdelta()``.
1025 """Calls either ``read()`` or ``readdelta()``.
1026
1026
1027 The faster of the two options is called.
1027 The faster of the two options is called.
1028 """
1028 """
1029
1029
1030 def find(key):
1030 def find(key):
1031 """Calls self.read().find(key)``.
1031 """Calls self.read().find(key)``.
1032
1032
1033 Returns a 2-tuple of ``(node, flags)`` or raises ``KeyError``.
1033 Returns a 2-tuple of ``(node, flags)`` or raises ``KeyError``.
1034 """
1034 """
1035
1035
1036 class imanifestrevisionwritable(imanifestrevisionbase):
1036 class imanifestrevisionwritable(imanifestrevisionbase):
1037 """Interface representing a manifest revision that can be committed."""
1037 """Interface representing a manifest revision that can be committed."""
1038
1038
1039 def write(transaction, linkrev, p1node, p2node, added, removed, match=None):
1039 def write(transaction, linkrev, p1node, p2node, added, removed, match=None):
1040 """Add this revision to storage.
1040 """Add this revision to storage.
1041
1041
1042 Takes a transaction object, the changeset revision number it will
1042 Takes a transaction object, the changeset revision number it will
1043 be associated with, its parent nodes, and lists of added and
1043 be associated with, its parent nodes, and lists of added and
1044 removed paths.
1044 removed paths.
1045
1045
1046 If match is provided, storage can choose not to inspect or write out
1046 If match is provided, storage can choose not to inspect or write out
1047 items that do not match. Storage is still required to be able to provide
1047 items that do not match. Storage is still required to be able to provide
1048 the full manifest in the future for any directories written (these
1048 the full manifest in the future for any directories written (these
1049 manifests should not be "narrowed on disk").
1049 manifests should not be "narrowed on disk").
1050
1050
1051 Returns the binary node of the created revision.
1051 Returns the binary node of the created revision.
1052 """
1052 """
1053
1053
1054 class imanifeststorage(interfaceutil.Interface):
1054 class imanifeststorage(interfaceutil.Interface):
1055 """Storage interface for manifest data."""
1055 """Storage interface for manifest data."""
1056
1056
1057 tree = interfaceutil.Attribute(
1057 tree = interfaceutil.Attribute(
1058 """The path to the directory this manifest tracks.
1058 """The path to the directory this manifest tracks.
1059
1059
1060 The empty bytestring represents the root manifest.
1060 The empty bytestring represents the root manifest.
1061 """)
1061 """)
1062
1062
1063 index = interfaceutil.Attribute(
1063 index = interfaceutil.Attribute(
1064 """An ``ifilerevisionssequence`` instance.""")
1064 """An ``ifilerevisionssequence`` instance.""")
1065
1065
1066 indexfile = interfaceutil.Attribute(
1066 indexfile = interfaceutil.Attribute(
1067 """Path of revlog index file.
1067 """Path of revlog index file.
1068
1068
1069 TODO this is revlog specific and should not be exposed.
1069 TODO this is revlog specific and should not be exposed.
1070 """)
1070 """)
1071
1071
1072 opener = interfaceutil.Attribute(
1072 opener = interfaceutil.Attribute(
1073 """VFS opener to use to access underlying files used for storage.
1073 """VFS opener to use to access underlying files used for storage.
1074
1074
1075 TODO this is revlog specific and should not be exposed.
1075 TODO this is revlog specific and should not be exposed.
1076 """)
1076 """)
1077
1077
1078 version = interfaceutil.Attribute(
1078 version = interfaceutil.Attribute(
1079 """Revlog version number.
1079 """Revlog version number.
1080
1080
1081 TODO this is revlog specific and should not be exposed.
1081 TODO this is revlog specific and should not be exposed.
1082 """)
1082 """)
1083
1083
1084 _generaldelta = interfaceutil.Attribute(
1084 _generaldelta = interfaceutil.Attribute(
1085 """Whether generaldelta storage is being used.
1085 """Whether generaldelta storage is being used.
1086
1086
1087 TODO this is revlog specific and should not be exposed.
1087 TODO this is revlog specific and should not be exposed.
1088 """)
1088 """)
1089
1089
1090 fulltextcache = interfaceutil.Attribute(
1090 fulltextcache = interfaceutil.Attribute(
1091 """Dict with cache of fulltexts.
1091 """Dict with cache of fulltexts.
1092
1092
1093 TODO this doesn't feel appropriate for the storage interface.
1093 TODO this doesn't feel appropriate for the storage interface.
1094 """)
1094 """)
1095
1095
1096 def __len__():
1096 def __len__():
1097 """Obtain the number of revisions stored for this manifest."""
1097 """Obtain the number of revisions stored for this manifest."""
1098
1098
1099 def __iter__():
1099 def __iter__():
1100 """Iterate over revision numbers for this manifest."""
1100 """Iterate over revision numbers for this manifest."""
1101
1101
1102 def rev(node):
1102 def rev(node):
1103 """Obtain the revision number given a binary node.
1103 """Obtain the revision number given a binary node.
1104
1104
1105 Raises ``error.LookupError`` if the node is not known.
1105 Raises ``error.LookupError`` if the node is not known.
1106 """
1106 """
1107
1107
1108 def node(rev):
1108 def node(rev):
1109 """Obtain the node value given a revision number.
1109 """Obtain the node value given a revision number.
1110
1110
1111 Raises ``error.LookupError`` if the revision is not known.
1111 Raises ``error.LookupError`` if the revision is not known.
1112 """
1112 """
1113
1113
1114 def lookup(value):
1114 def lookup(value):
1115 """Attempt to resolve a value to a node.
1115 """Attempt to resolve a value to a node.
1116
1116
1117 Value can be a binary node, hex node, revision number, or a bytes
1117 Value can be a binary node, hex node, revision number, or a bytes
1118 that can be converted to an integer.
1118 that can be converted to an integer.
1119
1119
1120 Raises ``error.LookupError`` if a ndoe could not be resolved.
1120 Raises ``error.LookupError`` if a ndoe could not be resolved.
1121 """
1121 """
1122
1122
1123 def parents(node):
1123 def parents(node):
1124 """Returns a 2-tuple of parent nodes for a node.
1124 """Returns a 2-tuple of parent nodes for a node.
1125
1125
1126 Values will be ``nullid`` if the parent is empty.
1126 Values will be ``nullid`` if the parent is empty.
1127 """
1127 """
1128
1128
1129 def parentrevs(rev):
1129 def parentrevs(rev):
1130 """Like parents() but operates on revision numbers."""
1130 """Like parents() but operates on revision numbers."""
1131
1131
1132 def linkrev(rev):
1132 def linkrev(rev):
1133 """Obtain the changeset revision number a revision is linked to."""
1133 """Obtain the changeset revision number a revision is linked to."""
1134
1134
1135 def revision(node, _df=None, raw=False):
1135 def revision(node, _df=None, raw=False):
1136 """Obtain fulltext data for a node."""
1136 """Obtain fulltext data for a node."""
1137
1137
1138 def revdiff(rev1, rev2):
1138 def revdiff(rev1, rev2):
1139 """Obtain a delta between two revision numbers.
1139 """Obtain a delta between two revision numbers.
1140
1140
1141 The returned data is the result of ``bdiff.bdiff()`` on the raw
1141 The returned data is the result of ``bdiff.bdiff()`` on the raw
1142 revision data.
1142 revision data.
1143 """
1143 """
1144
1144
1145 def cmp(node, fulltext):
1145 def cmp(node, fulltext):
1146 """Compare fulltext to another revision.
1146 """Compare fulltext to another revision.
1147
1147
1148 Returns True if the fulltext is different from what is stored.
1148 Returns True if the fulltext is different from what is stored.
1149 """
1149 """
1150
1150
1151 def emitrevisions(nodes,
1151 def emitrevisions(nodes,
1152 nodesorder=None,
1152 nodesorder=None,
1153 revisiondata=False,
1153 revisiondata=False,
1154 assumehaveparentrevisions=False):
1154 assumehaveparentrevisions=False):
1155 """Produce ``irevisiondelta`` describing revisions.
1155 """Produce ``irevisiondelta`` describing revisions.
1156
1156
1157 See the documentation for ``ifiledata`` for more.
1157 See the documentation for ``ifiledata`` for more.
1158 """
1158 """
1159
1159
1160 def addgroup(deltas, linkmapper, transaction, addrevisioncb=None):
1160 def addgroup(deltas, linkmapper, transaction, addrevisioncb=None):
1161 """Process a series of deltas for storage.
1161 """Process a series of deltas for storage.
1162
1162
1163 See the documentation in ``ifilemutation`` for more.
1163 See the documentation in ``ifilemutation`` for more.
1164 """
1164 """
1165
1165
1166 def rawsize(rev):
1166 def rawsize(rev):
1167 """Obtain the size of tracked data.
1167 """Obtain the size of tracked data.
1168
1168
1169 Is equivalent to ``len(m.revision(node, raw=True))``.
1169 Is equivalent to ``len(m.revision(node, raw=True))``.
1170
1170
1171 TODO this method is only used by upgrade code and may be removed.
1171 TODO this method is only used by upgrade code and may be removed.
1172 """
1172 """
1173
1173
1174 def getstrippoint(minlink):
1174 def getstrippoint(minlink):
1175 """Find minimum revision that must be stripped to strip a linkrev.
1175 """Find minimum revision that must be stripped to strip a linkrev.
1176
1176
1177 See the documentation in ``ifilemutation`` for more.
1177 See the documentation in ``ifilemutation`` for more.
1178 """
1178 """
1179
1179
1180 def strip(minlink, transaction):
1180 def strip(minlink, transaction):
1181 """Remove storage of items starting at a linkrev.
1181 """Remove storage of items starting at a linkrev.
1182
1182
1183 See the documentation in ``ifilemutation`` for more.
1183 See the documentation in ``ifilemutation`` for more.
1184 """
1184 """
1185
1185
1186 def checksize():
1186 def checksize():
1187 """Obtain the expected sizes of backing files.
1187 """Obtain the expected sizes of backing files.
1188
1188
1189 TODO this is used by verify and it should not be part of the interface.
1189 TODO this is used by verify and it should not be part of the interface.
1190 """
1190 """
1191
1191
1192 def files():
1192 def files():
1193 """Obtain paths that are backing storage for this manifest.
1193 """Obtain paths that are backing storage for this manifest.
1194
1194
1195 TODO this is used by verify and there should probably be a better API
1195 TODO this is used by verify and there should probably be a better API
1196 for this functionality.
1196 for this functionality.
1197 """
1197 """
1198
1198
1199 def deltaparent(rev):
1199 def deltaparent(rev):
1200 """Obtain the revision that a revision is delta'd against.
1200 """Obtain the revision that a revision is delta'd against.
1201
1201
1202 TODO delta encoding is an implementation detail of storage and should
1202 TODO delta encoding is an implementation detail of storage and should
1203 not be exposed to the storage interface.
1203 not be exposed to the storage interface.
1204 """
1204 """
1205
1205
1206 def clone(tr, dest, **kwargs):
1206 def clone(tr, dest, **kwargs):
1207 """Clone this instance to another."""
1207 """Clone this instance to another."""
1208
1208
1209 def clearcaches(clear_persisted_data=False):
1209 def clearcaches(clear_persisted_data=False):
1210 """Clear any caches associated with this instance."""
1210 """Clear any caches associated with this instance."""
1211
1211
1212 def dirlog(d):
1212 def dirlog(d):
1213 """Obtain a manifest storage instance for a tree."""
1213 """Obtain a manifest storage instance for a tree."""
1214
1214
1215 def add(m, transaction, link, p1, p2, added, removed, readtree=None,
1215 def add(m, transaction, link, p1, p2, added, removed, readtree=None,
1216 match=None):
1216 match=None):
1217 """Add a revision to storage.
1217 """Add a revision to storage.
1218
1218
1219 ``m`` is an object conforming to ``imanifestdict``.
1219 ``m`` is an object conforming to ``imanifestdict``.
1220
1220
1221 ``link`` is the linkrev revision number.
1221 ``link`` is the linkrev revision number.
1222
1222
1223 ``p1`` and ``p2`` are the parent revision numbers.
1223 ``p1`` and ``p2`` are the parent revision numbers.
1224
1224
1225 ``added`` and ``removed`` are iterables of added and removed paths,
1225 ``added`` and ``removed`` are iterables of added and removed paths,
1226 respectively.
1226 respectively.
1227
1227
1228 ``readtree`` is a function that can be used to read the child tree(s)
1228 ``readtree`` is a function that can be used to read the child tree(s)
1229 when recursively writing the full tree structure when using
1229 when recursively writing the full tree structure when using
1230 treemanifets.
1230 treemanifets.
1231
1231
1232 ``match`` is a matcher that can be used to hint to storage that not all
1232 ``match`` is a matcher that can be used to hint to storage that not all
1233 paths must be inspected; this is an optimization and can be safely
1233 paths must be inspected; this is an optimization and can be safely
1234 ignored. Note that the storage must still be able to reproduce a full
1234 ignored. Note that the storage must still be able to reproduce a full
1235 manifest including files that did not match.
1235 manifest including files that did not match.
1236 """
1236 """
1237
1237
1238 def storageinfo(exclusivefiles=False, sharedfiles=False,
1238 def storageinfo(exclusivefiles=False, sharedfiles=False,
1239 revisionscount=False, trackedsize=False,
1239 revisionscount=False, trackedsize=False,
1240 storedsize=False):
1240 storedsize=False):
1241 """Obtain information about storage for this manifest's data.
1241 """Obtain information about storage for this manifest's data.
1242
1242
1243 See ``ifilestorage.storageinfo()`` for a description of this method.
1243 See ``ifilestorage.storageinfo()`` for a description of this method.
1244 This one behaves the same way, except for manifest data.
1244 This one behaves the same way, except for manifest data.
1245 """
1245 """
1246
1246
1247 class imanifestlog(interfaceutil.Interface):
1247 class imanifestlog(interfaceutil.Interface):
1248 """Interface representing a collection of manifest snapshots.
1248 """Interface representing a collection of manifest snapshots.
1249
1249
1250 Represents the root manifest in a repository.
1250 Represents the root manifest in a repository.
1251
1251
1252 Also serves as a means to access nested tree manifests and to cache
1252 Also serves as a means to access nested tree manifests and to cache
1253 tree manifests.
1253 tree manifests.
1254 """
1254 """
1255
1255
1256 def __getitem__(node):
1256 def __getitem__(node):
1257 """Obtain a manifest instance for a given binary node.
1257 """Obtain a manifest instance for a given binary node.
1258
1258
1259 Equivalent to calling ``self.get('', node)``.
1259 Equivalent to calling ``self.get('', node)``.
1260
1260
1261 The returned object conforms to the ``imanifestrevisionstored``
1261 The returned object conforms to the ``imanifestrevisionstored``
1262 interface.
1262 interface.
1263 """
1263 """
1264
1264
1265 def get(tree, node, verify=True):
1265 def get(tree, node, verify=True):
1266 """Retrieve the manifest instance for a given directory and binary node.
1266 """Retrieve the manifest instance for a given directory and binary node.
1267
1267
1268 ``node`` always refers to the node of the root manifest (which will be
1268 ``node`` always refers to the node of the root manifest (which will be
1269 the only manifest if flat manifests are being used).
1269 the only manifest if flat manifests are being used).
1270
1270
1271 If ``tree`` is the empty string, the root manifest is returned.
1271 If ``tree`` is the empty string, the root manifest is returned.
1272 Otherwise the manifest for the specified directory will be returned
1272 Otherwise the manifest for the specified directory will be returned
1273 (requires tree manifests).
1273 (requires tree manifests).
1274
1274
1275 If ``verify`` is True, ``LookupError`` is raised if the node is not
1275 If ``verify`` is True, ``LookupError`` is raised if the node is not
1276 known.
1276 known.
1277
1277
1278 The returned object conforms to the ``imanifestrevisionstored``
1278 The returned object conforms to the ``imanifestrevisionstored``
1279 interface.
1279 interface.
1280 """
1280 """
1281
1281
1282 def getstorage(tree):
1282 def getstorage(tree):
1283 """Retrieve an interface to storage for a particular tree.
1283 """Retrieve an interface to storage for a particular tree.
1284
1284
1285 If ``tree`` is the empty bytestring, storage for the root manifest will
1285 If ``tree`` is the empty bytestring, storage for the root manifest will
1286 be returned. Otherwise storage for a tree manifest is returned.
1286 be returned. Otherwise storage for a tree manifest is returned.
1287
1287
1288 TODO formalize interface for returned object.
1288 TODO formalize interface for returned object.
1289 """
1289 """
1290
1290
1291 def clearcaches():
1291 def clearcaches():
1292 """Clear caches associated with this collection."""
1292 """Clear caches associated with this collection."""
1293
1293
1294 def rev(node):
1294 def rev(node):
1295 """Obtain the revision number for a binary node.
1295 """Obtain the revision number for a binary node.
1296
1296
1297 Raises ``error.LookupError`` if the node is not known.
1297 Raises ``error.LookupError`` if the node is not known.
1298 """
1298 """
1299
1299
1300 class ilocalrepositoryfilestorage(interfaceutil.Interface):
1300 class ilocalrepositoryfilestorage(interfaceutil.Interface):
1301 """Local repository sub-interface providing access to tracked file storage.
1301 """Local repository sub-interface providing access to tracked file storage.
1302
1302
1303 This interface defines how a repository accesses storage for a single
1303 This interface defines how a repository accesses storage for a single
1304 tracked file path.
1304 tracked file path.
1305 """
1305 """
1306
1306
1307 def file(f):
1307 def file(f):
1308 """Obtain a filelog for a tracked path.
1308 """Obtain a filelog for a tracked path.
1309
1309
1310 The returned type conforms to the ``ifilestorage`` interface.
1310 The returned type conforms to the ``ifilestorage`` interface.
1311 """
1311 """
1312
1312
1313 class ilocalrepositorymain(interfaceutil.Interface):
1313 class ilocalrepositorymain(interfaceutil.Interface):
1314 """Main interface for local repositories.
1314 """Main interface for local repositories.
1315
1315
1316 This currently captures the reality of things - not how things should be.
1316 This currently captures the reality of things - not how things should be.
1317 """
1317 """
1318
1318
1319 supportedformats = interfaceutil.Attribute(
1319 supportedformats = interfaceutil.Attribute(
1320 """Set of requirements that apply to stream clone.
1320 """Set of requirements that apply to stream clone.
1321
1321
1322 This is actually a class attribute and is shared among all instances.
1322 This is actually a class attribute and is shared among all instances.
1323 """)
1323 """)
1324
1324
1325 supported = interfaceutil.Attribute(
1325 supported = interfaceutil.Attribute(
1326 """Set of requirements that this repo is capable of opening.""")
1326 """Set of requirements that this repo is capable of opening.""")
1327
1327
1328 requirements = interfaceutil.Attribute(
1328 requirements = interfaceutil.Attribute(
1329 """Set of requirements this repo uses.""")
1329 """Set of requirements this repo uses.""")
1330
1330
1331 features = interfaceutil.Attribute(
1331 features = interfaceutil.Attribute(
1332 """Set of "features" this repository supports.
1332 """Set of "features" this repository supports.
1333
1333
1334 A "feature" is a loosely-defined term. It can refer to a feature
1334 A "feature" is a loosely-defined term. It can refer to a feature
1335 in the classical sense or can describe an implementation detail
1335 in the classical sense or can describe an implementation detail
1336 of the repository. For example, a ``readonly`` feature may denote
1336 of the repository. For example, a ``readonly`` feature may denote
1337 the repository as read-only. Or a ``revlogfilestore`` feature may
1337 the repository as read-only. Or a ``revlogfilestore`` feature may
1338 denote that the repository is using revlogs for file storage.
1338 denote that the repository is using revlogs for file storage.
1339
1339
1340 The intent of features is to provide a machine-queryable mechanism
1340 The intent of features is to provide a machine-queryable mechanism
1341 for repo consumers to test for various repository characteristics.
1341 for repo consumers to test for various repository characteristics.
1342
1342
1343 Features are similar to ``requirements``. The main difference is that
1343 Features are similar to ``requirements``. The main difference is that
1344 requirements are stored on-disk and represent requirements to open the
1344 requirements are stored on-disk and represent requirements to open the
1345 repository. Features are more run-time capabilities of the repository
1345 repository. Features are more run-time capabilities of the repository
1346 and more granular capabilities (which may be derived from requirements).
1346 and more granular capabilities (which may be derived from requirements).
1347 """)
1347 """)
1348
1348
1349 filtername = interfaceutil.Attribute(
1349 filtername = interfaceutil.Attribute(
1350 """Name of the repoview that is active on this repo.""")
1350 """Name of the repoview that is active on this repo.""")
1351
1351
1352 wvfs = interfaceutil.Attribute(
1352 wvfs = interfaceutil.Attribute(
1353 """VFS used to access the working directory.""")
1353 """VFS used to access the working directory.""")
1354
1354
1355 vfs = interfaceutil.Attribute(
1355 vfs = interfaceutil.Attribute(
1356 """VFS rooted at the .hg directory.
1356 """VFS rooted at the .hg directory.
1357
1357
1358 Used to access repository data not in the store.
1358 Used to access repository data not in the store.
1359 """)
1359 """)
1360
1360
1361 svfs = interfaceutil.Attribute(
1361 svfs = interfaceutil.Attribute(
1362 """VFS rooted at the store.
1362 """VFS rooted at the store.
1363
1363
1364 Used to access repository data in the store. Typically .hg/store.
1364 Used to access repository data in the store. Typically .hg/store.
1365 But can point elsewhere if the store is shared.
1365 But can point elsewhere if the store is shared.
1366 """)
1366 """)
1367
1367
1368 root = interfaceutil.Attribute(
1368 root = interfaceutil.Attribute(
1369 """Path to the root of the working directory.""")
1369 """Path to the root of the working directory.""")
1370
1370
1371 path = interfaceutil.Attribute(
1371 path = interfaceutil.Attribute(
1372 """Path to the .hg directory.""")
1372 """Path to the .hg directory.""")
1373
1373
1374 origroot = interfaceutil.Attribute(
1374 origroot = interfaceutil.Attribute(
1375 """The filesystem path that was used to construct the repo.""")
1375 """The filesystem path that was used to construct the repo.""")
1376
1376
1377 auditor = interfaceutil.Attribute(
1377 auditor = interfaceutil.Attribute(
1378 """A pathauditor for the working directory.
1378 """A pathauditor for the working directory.
1379
1379
1380 This checks if a path refers to a nested repository.
1380 This checks if a path refers to a nested repository.
1381
1381
1382 Operates on the filesystem.
1382 Operates on the filesystem.
1383 """)
1383 """)
1384
1384
1385 nofsauditor = interfaceutil.Attribute(
1385 nofsauditor = interfaceutil.Attribute(
1386 """A pathauditor for the working directory.
1386 """A pathauditor for the working directory.
1387
1387
1388 This is like ``auditor`` except it doesn't do filesystem checks.
1388 This is like ``auditor`` except it doesn't do filesystem checks.
1389 """)
1389 """)
1390
1390
1391 baseui = interfaceutil.Attribute(
1391 baseui = interfaceutil.Attribute(
1392 """Original ui instance passed into constructor.""")
1392 """Original ui instance passed into constructor.""")
1393
1393
1394 ui = interfaceutil.Attribute(
1394 ui = interfaceutil.Attribute(
1395 """Main ui instance for this instance.""")
1395 """Main ui instance for this instance.""")
1396
1396
1397 sharedpath = interfaceutil.Attribute(
1397 sharedpath = interfaceutil.Attribute(
1398 """Path to the .hg directory of the repo this repo was shared from.""")
1398 """Path to the .hg directory of the repo this repo was shared from.""")
1399
1399
1400 store = interfaceutil.Attribute(
1400 store = interfaceutil.Attribute(
1401 """A store instance.""")
1401 """A store instance.""")
1402
1402
1403 spath = interfaceutil.Attribute(
1403 spath = interfaceutil.Attribute(
1404 """Path to the store.""")
1404 """Path to the store.""")
1405
1405
1406 sjoin = interfaceutil.Attribute(
1406 sjoin = interfaceutil.Attribute(
1407 """Alias to self.store.join.""")
1407 """Alias to self.store.join.""")
1408
1408
1409 cachevfs = interfaceutil.Attribute(
1409 cachevfs = interfaceutil.Attribute(
1410 """A VFS used to access the cache directory.
1410 """A VFS used to access the cache directory.
1411
1411
1412 Typically .hg/cache.
1412 Typically .hg/cache.
1413 """)
1413 """)
1414
1414
1415 filteredrevcache = interfaceutil.Attribute(
1415 filteredrevcache = interfaceutil.Attribute(
1416 """Holds sets of revisions to be filtered.""")
1416 """Holds sets of revisions to be filtered.""")
1417
1417
1418 names = interfaceutil.Attribute(
1418 names = interfaceutil.Attribute(
1419 """A ``namespaces`` instance.""")
1419 """A ``namespaces`` instance.""")
1420
1420
1421 def close():
1421 def close():
1422 """Close the handle on this repository."""
1422 """Close the handle on this repository."""
1423
1423
1424 def peer():
1424 def peer():
1425 """Obtain an object conforming to the ``peer`` interface."""
1425 """Obtain an object conforming to the ``peer`` interface."""
1426
1426
1427 def unfiltered():
1427 def unfiltered():
1428 """Obtain an unfiltered/raw view of this repo."""
1428 """Obtain an unfiltered/raw view of this repo."""
1429
1429
1430 def filtered(name, visibilityexceptions=None):
1430 def filtered(name, visibilityexceptions=None):
1431 """Obtain a named view of this repository."""
1431 """Obtain a named view of this repository."""
1432
1432
1433 obsstore = interfaceutil.Attribute(
1433 obsstore = interfaceutil.Attribute(
1434 """A store of obsolescence data.""")
1434 """A store of obsolescence data.""")
1435
1435
1436 changelog = interfaceutil.Attribute(
1436 changelog = interfaceutil.Attribute(
1437 """A handle on the changelog revlog.""")
1437 """A handle on the changelog revlog.""")
1438
1438
1439 manifestlog = interfaceutil.Attribute(
1439 manifestlog = interfaceutil.Attribute(
1440 """An instance conforming to the ``imanifestlog`` interface.
1440 """An instance conforming to the ``imanifestlog`` interface.
1441
1441
1442 Provides access to manifests for the repository.
1442 Provides access to manifests for the repository.
1443 """)
1443 """)
1444
1444
1445 dirstate = interfaceutil.Attribute(
1445 dirstate = interfaceutil.Attribute(
1446 """Working directory state.""")
1446 """Working directory state.""")
1447
1447
1448 narrowpats = interfaceutil.Attribute(
1448 narrowpats = interfaceutil.Attribute(
1449 """Matcher patterns for this repository's narrowspec.""")
1449 """Matcher patterns for this repository's narrowspec.""")
1450
1450
1451 def narrowmatch():
1451 def narrowmatch():
1452 """Obtain a matcher for the narrowspec."""
1452 """Obtain a matcher for the narrowspec."""
1453
1453
1454 def setnarrowpats(newincludes, newexcludes):
1454 def setnarrowpats(newincludes, newexcludes):
1455 """Define the narrowspec for this repository."""
1455 """Define the narrowspec for this repository."""
1456
1456
1457 def __getitem__(changeid):
1457 def __getitem__(changeid):
1458 """Try to resolve a changectx."""
1458 """Try to resolve a changectx."""
1459
1459
1460 def __contains__(changeid):
1460 def __contains__(changeid):
1461 """Whether a changeset exists."""
1461 """Whether a changeset exists."""
1462
1462
1463 def __nonzero__():
1463 def __nonzero__():
1464 """Always returns True."""
1464 """Always returns True."""
1465 return True
1465 return True
1466
1466
1467 __bool__ = __nonzero__
1467 __bool__ = __nonzero__
1468
1468
1469 def __len__():
1469 def __len__():
1470 """Returns the number of changesets in the repo."""
1470 """Returns the number of changesets in the repo."""
1471
1471
1472 def __iter__():
1472 def __iter__():
1473 """Iterate over revisions in the changelog."""
1473 """Iterate over revisions in the changelog."""
1474
1474
1475 def revs(expr, *args):
1475 def revs(expr, *args):
1476 """Evaluate a revset.
1476 """Evaluate a revset.
1477
1477
1478 Emits revisions.
1478 Emits revisions.
1479 """
1479 """
1480
1480
1481 def set(expr, *args):
1481 def set(expr, *args):
1482 """Evaluate a revset.
1482 """Evaluate a revset.
1483
1483
1484 Emits changectx instances.
1484 Emits changectx instances.
1485 """
1485 """
1486
1486
1487 def anyrevs(specs, user=False, localalias=None):
1487 def anyrevs(specs, user=False, localalias=None):
1488 """Find revisions matching one of the given revsets."""
1488 """Find revisions matching one of the given revsets."""
1489
1489
1490 def url():
1490 def url():
1491 """Returns a string representing the location of this repo."""
1491 """Returns a string representing the location of this repo."""
1492
1492
1493 def hook(name, throw=False, **args):
1493 def hook(name, throw=False, **args):
1494 """Call a hook."""
1494 """Call a hook."""
1495
1495
1496 def tags():
1496 def tags():
1497 """Return a mapping of tag to node."""
1497 """Return a mapping of tag to node."""
1498
1498
1499 def tagtype(tagname):
1499 def tagtype(tagname):
1500 """Return the type of a given tag."""
1500 """Return the type of a given tag."""
1501
1501
1502 def tagslist():
1502 def tagslist():
1503 """Return a list of tags ordered by revision."""
1503 """Return a list of tags ordered by revision."""
1504
1504
1505 def nodetags(node):
1505 def nodetags(node):
1506 """Return the tags associated with a node."""
1506 """Return the tags associated with a node."""
1507
1507
1508 def nodebookmarks(node):
1508 def nodebookmarks(node):
1509 """Return the list of bookmarks pointing to the specified node."""
1509 """Return the list of bookmarks pointing to the specified node."""
1510
1510
1511 def branchmap():
1511 def branchmap():
1512 """Return a mapping of branch to heads in that branch."""
1512 """Return a mapping of branch to heads in that branch."""
1513
1513
1514 def revbranchcache():
1514 def revbranchcache():
1515 pass
1515 pass
1516
1516
1517 def branchtip(branchtip, ignoremissing=False):
1517 def branchtip(branchtip, ignoremissing=False):
1518 """Return the tip node for a given branch."""
1518 """Return the tip node for a given branch."""
1519
1519
1520 def lookup(key):
1520 def lookup(key):
1521 """Resolve the node for a revision."""
1521 """Resolve the node for a revision."""
1522
1522
1523 def lookupbranch(key):
1523 def lookupbranch(key):
1524 """Look up the branch name of the given revision or branch name."""
1524 """Look up the branch name of the given revision or branch name."""
1525
1525
1526 def known(nodes):
1526 def known(nodes):
1527 """Determine whether a series of nodes is known.
1527 """Determine whether a series of nodes is known.
1528
1528
1529 Returns a list of bools.
1529 Returns a list of bools.
1530 """
1530 """
1531
1531
1532 def local():
1532 def local():
1533 """Whether the repository is local."""
1533 """Whether the repository is local."""
1534 return True
1534 return True
1535
1535
1536 def publishing():
1536 def publishing():
1537 """Whether the repository is a publishing repository."""
1537 """Whether the repository is a publishing repository."""
1538
1538
1539 def cancopy():
1539 def cancopy():
1540 pass
1540 pass
1541
1541
1542 def shared():
1542 def shared():
1543 """The type of shared repository or None."""
1543 """The type of shared repository or None."""
1544
1544
1545 def wjoin(f, *insidef):
1545 def wjoin(f, *insidef):
1546 """Calls self.vfs.reljoin(self.root, f, *insidef)"""
1546 """Calls self.vfs.reljoin(self.root, f, *insidef)"""
1547
1547
1548 def setparents(p1, p2):
1548 def setparents(p1, p2):
1549 """Set the parent nodes of the working directory."""
1549 """Set the parent nodes of the working directory."""
1550
1550
1551 def filectx(path, changeid=None, fileid=None):
1551 def filectx(path, changeid=None, fileid=None):
1552 """Obtain a filectx for the given file revision."""
1552 """Obtain a filectx for the given file revision."""
1553
1553
1554 def getcwd():
1554 def getcwd():
1555 """Obtain the current working directory from the dirstate."""
1555 """Obtain the current working directory from the dirstate."""
1556
1556
1557 def pathto(f, cwd=None):
1557 def pathto(f, cwd=None):
1558 """Obtain the relative path to a file."""
1558 """Obtain the relative path to a file."""
1559
1559
1560 def adddatafilter(name, fltr):
1560 def adddatafilter(name, fltr):
1561 pass
1561 pass
1562
1562
1563 def wread(filename):
1563 def wread(filename):
1564 """Read a file from wvfs, using data filters."""
1564 """Read a file from wvfs, using data filters."""
1565
1565
1566 def wwrite(filename, data, flags, backgroundclose=False, **kwargs):
1566 def wwrite(filename, data, flags, backgroundclose=False, **kwargs):
1567 """Write data to a file in the wvfs, using data filters."""
1567 """Write data to a file in the wvfs, using data filters."""
1568
1568
1569 def wwritedata(filename, data):
1569 def wwritedata(filename, data):
1570 """Resolve data for writing to the wvfs, using data filters."""
1570 """Resolve data for writing to the wvfs, using data filters."""
1571
1571
1572 def currenttransaction():
1572 def currenttransaction():
1573 """Obtain the current transaction instance or None."""
1573 """Obtain the current transaction instance or None."""
1574
1574
1575 def transaction(desc, report=None):
1575 def transaction(desc, report=None):
1576 """Open a new transaction to write to the repository."""
1576 """Open a new transaction to write to the repository."""
1577
1577
1578 def undofiles():
1578 def undofiles():
1579 """Returns a list of (vfs, path) for files to undo transactions."""
1579 """Returns a list of (vfs, path) for files to undo transactions."""
1580
1580
1581 def recover():
1581 def recover():
1582 """Roll back an interrupted transaction."""
1582 """Roll back an interrupted transaction."""
1583
1583
1584 def rollback(dryrun=False, force=False):
1584 def rollback(dryrun=False, force=False):
1585 """Undo the last transaction.
1585 """Undo the last transaction.
1586
1586
1587 DANGEROUS.
1587 DANGEROUS.
1588 """
1588 """
1589
1589
1590 def updatecaches(tr=None, full=False):
1590 def updatecaches(tr=None, full=False):
1591 """Warm repo caches."""
1591 """Warm repo caches."""
1592
1592
1593 def invalidatecaches():
1593 def invalidatecaches():
1594 """Invalidate cached data due to the repository mutating."""
1594 """Invalidate cached data due to the repository mutating."""
1595
1595
1596 def invalidatevolatilesets():
1596 def invalidatevolatilesets():
1597 pass
1597 pass
1598
1598
1599 def invalidatedirstate():
1599 def invalidatedirstate():
1600 """Invalidate the dirstate."""
1600 """Invalidate the dirstate."""
1601
1601
1602 def invalidate(clearfilecache=False):
1602 def invalidate(clearfilecache=False):
1603 pass
1603 pass
1604
1604
1605 def invalidateall():
1605 def invalidateall():
1606 pass
1606 pass
1607
1607
1608 def lock(wait=True):
1608 def lock(wait=True):
1609 """Lock the repository store and return a lock instance."""
1609 """Lock the repository store and return a lock instance."""
1610
1610
1611 def wlock(wait=True):
1611 def wlock(wait=True):
1612 """Lock the non-store parts of the repository."""
1612 """Lock the non-store parts of the repository."""
1613
1613
1614 def currentwlock():
1614 def currentwlock():
1615 """Return the wlock if it's held or None."""
1615 """Return the wlock if it's held or None."""
1616
1616
1617 def checkcommitpatterns(wctx, vdirs, match, status, fail):
1617 def checkcommitpatterns(wctx, vdirs, match, status, fail):
1618 pass
1618 pass
1619
1619
1620 def commit(text='', user=None, date=None, match=None, force=False,
1620 def commit(text='', user=None, date=None, match=None, force=False,
1621 editor=False, extra=None):
1621 editor=False, extra=None):
1622 """Add a new revision to the repository."""
1622 """Add a new revision to the repository."""
1623
1623
1624 def commitctx(ctx, error=False):
1624 def commitctx(ctx, error=False):
1625 """Commit a commitctx instance to the repository."""
1625 """Commit a commitctx instance to the repository."""
1626
1626
1627 def destroying():
1627 def destroying():
1628 """Inform the repository that nodes are about to be destroyed."""
1628 """Inform the repository that nodes are about to be destroyed."""
1629
1629
1630 def destroyed():
1630 def destroyed():
1631 """Inform the repository that nodes have been destroyed."""
1631 """Inform the repository that nodes have been destroyed."""
1632
1632
1633 def status(node1='.', node2=None, match=None, ignored=False,
1633 def status(node1='.', node2=None, match=None, ignored=False,
1634 clean=False, unknown=False, listsubrepos=False):
1634 clean=False, unknown=False, listsubrepos=False):
1635 """Convenience method to call repo[x].status()."""
1635 """Convenience method to call repo[x].status()."""
1636
1636
1637 def addpostdsstatus(ps):
1637 def addpostdsstatus(ps):
1638 pass
1638 pass
1639
1639
1640 def postdsstatus():
1640 def postdsstatus():
1641 pass
1641 pass
1642
1642
1643 def clearpostdsstatus():
1643 def clearpostdsstatus():
1644 pass
1644 pass
1645
1645
1646 def heads(start=None):
1646 def heads(start=None):
1647 """Obtain list of nodes that are DAG heads."""
1647 """Obtain list of nodes that are DAG heads."""
1648
1648
1649 def branchheads(branch=None, start=None, closed=False):
1649 def branchheads(branch=None, start=None, closed=False):
1650 pass
1650 pass
1651
1651
1652 def branches(nodes):
1652 def branches(nodes):
1653 pass
1653 pass
1654
1654
1655 def between(pairs):
1655 def between(pairs):
1656 pass
1656 pass
1657
1657
1658 def checkpush(pushop):
1658 def checkpush(pushop):
1659 pass
1659 pass
1660
1660
1661 prepushoutgoinghooks = interfaceutil.Attribute(
1661 prepushoutgoinghooks = interfaceutil.Attribute(
1662 """util.hooks instance.""")
1662 """util.hooks instance.""")
1663
1663
1664 def pushkey(namespace, key, old, new):
1664 def pushkey(namespace, key, old, new):
1665 pass
1665 pass
1666
1666
1667 def listkeys(namespace):
1667 def listkeys(namespace):
1668 pass
1668 pass
1669
1669
1670 def debugwireargs(one, two, three=None, four=None, five=None):
1670 def debugwireargs(one, two, three=None, four=None, five=None):
1671 pass
1671 pass
1672
1672
1673 def savecommitmessage(text):
1673 def savecommitmessage(text):
1674 pass
1674 pass
1675
1675
1676 class completelocalrepository(ilocalrepositorymain,
1676 class completelocalrepository(ilocalrepositorymain,
1677 ilocalrepositoryfilestorage):
1677 ilocalrepositoryfilestorage):
1678 """Complete interface for a local repository."""
1678 """Complete interface for a local repository."""
1679
1679
1680 class iwireprotocolcommandcacher(interfaceutil.Interface):
1680 class iwireprotocolcommandcacher(interfaceutil.Interface):
1681 """Represents a caching backend for wire protocol commands.
1681 """Represents a caching backend for wire protocol commands.
1682
1682
1683 Wire protocol version 2 supports transparent caching of many commands.
1683 Wire protocol version 2 supports transparent caching of many commands.
1684 To leverage this caching, servers can activate objects that cache
1684 To leverage this caching, servers can activate objects that cache
1685 command responses. Objects handle both cache writing and reading.
1685 command responses. Objects handle both cache writing and reading.
1686 This interface defines how that response caching mechanism works.
1686 This interface defines how that response caching mechanism works.
1687
1687
1688 Wire protocol version 2 commands emit a series of objects that are
1688 Wire protocol version 2 commands emit a series of objects that are
1689 serialized and sent to the client. The caching layer exists between
1689 serialized and sent to the client. The caching layer exists between
1690 the invocation of the command function and the sending of its output
1690 the invocation of the command function and the sending of its output
1691 objects to an output layer.
1691 objects to an output layer.
1692
1692
1693 Instances of this interface represent a binding to a cache that
1693 Instances of this interface represent a binding to a cache that
1694 can serve a response (in place of calling a command function) and/or
1694 can serve a response (in place of calling a command function) and/or
1695 write responses to a cache for subsequent use.
1695 write responses to a cache for subsequent use.
1696
1696
1697 When a command request arrives, the following happens with regards
1697 When a command request arrives, the following happens with regards
1698 to this interface:
1698 to this interface:
1699
1699
1700 1. The server determines whether the command request is cacheable.
1700 1. The server determines whether the command request is cacheable.
1701 2. If it is, an instance of this interface is spawned.
1701 2. If it is, an instance of this interface is spawned.
1702 3. The cacher is activated in a context manager (``__enter__`` is called).
1702 3. The cacher is activated in a context manager (``__enter__`` is called).
1703 4. A cache *key* for that request is derived. This will call the
1703 4. A cache *key* for that request is derived. This will call the
1704 instance's ``adjustcachekeystate()`` method so the derivation
1704 instance's ``adjustcachekeystate()`` method so the derivation
1705 can be influenced.
1705 can be influenced.
1706 5. The cacher is informed of the derived cache key via a call to
1706 5. The cacher is informed of the derived cache key via a call to
1707 ``setcachekey()``.
1707 ``setcachekey()``.
1708 6. The cacher's ``lookup()`` method is called to test for presence of
1708 6. The cacher's ``lookup()`` method is called to test for presence of
1709 the derived key in the cache.
1709 the derived key in the cache.
1710 7. If ``lookup()`` returns a hit, that cached result is used in place
1710 7. If ``lookup()`` returns a hit, that cached result is used in place
1711 of invoking the command function. ``__exit__`` is called and the instance
1711 of invoking the command function. ``__exit__`` is called and the instance
1712 is discarded.
1712 is discarded.
1713 8. The command function is invoked.
1713 8. The command function is invoked.
1714 9. ``onobject()`` is called for each object emitted by the command
1714 9. ``onobject()`` is called for each object emitted by the command
1715 function.
1715 function.
1716 10. After the final object is seen, ``onoutputfinished()`` is called.
1716 10. After the final object is seen, ``onfinished()`` is called.
1717 11. ``__exit__`` is called to signal the end of use of the instance.
1717 11. ``__exit__`` is called to signal the end of use of the instance.
1718
1718
1719 Cache *key* derivation can be influenced by the instance.
1719 Cache *key* derivation can be influenced by the instance.
1720
1720
1721 Cache keys are initially derived by a deterministic representation of
1721 Cache keys are initially derived by a deterministic representation of
1722 the command request. This includes the command name, arguments, protocol
1722 the command request. This includes the command name, arguments, protocol
1723 version, etc. This initial key derivation is performed by CBOR-encoding a
1723 version, etc. This initial key derivation is performed by CBOR-encoding a
1724 data structure and feeding that output into a hasher.
1724 data structure and feeding that output into a hasher.
1725
1725
1726 Instances of this interface can influence this initial key derivation
1726 Instances of this interface can influence this initial key derivation
1727 via ``adjustcachekeystate()``.
1727 via ``adjustcachekeystate()``.
1728
1728
1729 The instance is informed of the derived cache key via a call to
1729 The instance is informed of the derived cache key via a call to
1730 ``setcachekey()``. The instance must store the key locally so it can
1730 ``setcachekey()``. The instance must store the key locally so it can
1731 be consulted on subsequent operations that may require it.
1731 be consulted on subsequent operations that may require it.
1732
1732
1733 When constructed, the instance has access to a callable that can be used
1733 When constructed, the instance has access to a callable that can be used
1734 for encoding response objects. This callable receives as its single
1734 for encoding response objects. This callable receives as its single
1735 argument an object emitted by a command function. It returns an iterable
1735 argument an object emitted by a command function. It returns an iterable
1736 of bytes chunks representing the encoded object. Unless the cacher is
1736 of bytes chunks representing the encoded object. Unless the cacher is
1737 caching native Python objects in memory or has a way of reconstructing
1737 caching native Python objects in memory or has a way of reconstructing
1738 the original Python objects, implementations typically call this function
1738 the original Python objects, implementations typically call this function
1739 to produce bytes from the output objects and then store those bytes in
1739 to produce bytes from the output objects and then store those bytes in
1740 the cache. When it comes time to re-emit those bytes, they are wrapped
1740 the cache. When it comes time to re-emit those bytes, they are wrapped
1741 in a ``wireprototypes.encodedresponse`` instance to tell the output
1741 in a ``wireprototypes.encodedresponse`` instance to tell the output
1742 layer that they are pre-encoded.
1742 layer that they are pre-encoded.
1743
1743
1744 When receiving the objects emitted by the command function, instances
1744 When receiving the objects emitted by the command function, instances
1745 can choose what to do with those objects. The simplest thing to do is
1745 can choose what to do with those objects. The simplest thing to do is
1746 re-emit the original objects. They will be forwarded to the output
1746 re-emit the original objects. They will be forwarded to the output
1747 layer and will be processed as if the cacher did not exist.
1747 layer and will be processed as if the cacher did not exist.
1748
1748
1749 Implementations could also choose to not emit objects - instead locally
1749 Implementations could also choose to not emit objects - instead locally
1750 buffering objects or their encoded representation. They could then emit
1750 buffering objects or their encoded representation. They could then emit
1751 a single "coalesced" object when ``onoutputfinished()`` is called. In
1751 a single "coalesced" object when ``onfinished()`` is called. In
1752 this way, the implementation would function as a filtering layer of
1752 this way, the implementation would function as a filtering layer of
1753 sorts.
1753 sorts.
1754
1754
1755 When caching objects, typically the encoded form of the object will
1755 When caching objects, typically the encoded form of the object will
1756 be stored. Keep in mind that if the original object is forwarded to
1756 be stored. Keep in mind that if the original object is forwarded to
1757 the output layer, it will need to be encoded there as well. For large
1757 the output layer, it will need to be encoded there as well. For large
1758 output, this redundant encoding could add overhead. Implementations
1758 output, this redundant encoding could add overhead. Implementations
1759 could wrap the encoded object data in ``wireprototypes.encodedresponse``
1759 could wrap the encoded object data in ``wireprototypes.encodedresponse``
1760 instances to avoid this overhead.
1760 instances to avoid this overhead.
1761 """
1761 """
1762 def __enter__():
1762 def __enter__():
1763 """Marks the instance as active.
1763 """Marks the instance as active.
1764
1764
1765 Should return self.
1765 Should return self.
1766 """
1766 """
1767
1767
1768 def __exit__(exctype, excvalue, exctb):
1768 def __exit__(exctype, excvalue, exctb):
1769 """Called when cacher is no longer used.
1769 """Called when cacher is no longer used.
1770
1770
1771 This can be used by implementations to perform cleanup actions (e.g.
1771 This can be used by implementations to perform cleanup actions (e.g.
1772 disconnecting network sockets, aborting a partially cached response.
1772 disconnecting network sockets, aborting a partially cached response.
1773 """
1773 """
1774
1774
1775 def adjustcachekeystate(state):
1775 def adjustcachekeystate(state):
1776 """Influences cache key derivation by adjusting state to derive key.
1776 """Influences cache key derivation by adjusting state to derive key.
1777
1777
1778 A dict defining the state used to derive the cache key is passed.
1778 A dict defining the state used to derive the cache key is passed.
1779
1779
1780 Implementations can modify this dict to record additional state that
1780 Implementations can modify this dict to record additional state that
1781 is wanted to influence key derivation.
1781 is wanted to influence key derivation.
1782
1782
1783 Implementations are *highly* encouraged to not modify or delete
1783 Implementations are *highly* encouraged to not modify or delete
1784 existing keys.
1784 existing keys.
1785 """
1785 """
1786
1786
1787 def setcachekey(key):
1787 def setcachekey(key):
1788 """Record the derived cache key for this request.
1788 """Record the derived cache key for this request.
1789
1789
1790 Instances may mutate the key for internal usage, as desired. e.g.
1790 Instances may mutate the key for internal usage, as desired. e.g.
1791 instances may wish to prepend the repo name, introduce path
1791 instances may wish to prepend the repo name, introduce path
1792 components for filesystem or URL addressing, etc. Behavior is up to
1792 components for filesystem or URL addressing, etc. Behavior is up to
1793 the cache.
1793 the cache.
1794
1794
1795 Returns a bool indicating if the request is cacheable by this
1795 Returns a bool indicating if the request is cacheable by this
1796 instance.
1796 instance.
1797 """
1797 """
1798
1798
1799 def lookup():
1799 def lookup():
1800 """Attempt to resolve an entry in the cache.
1800 """Attempt to resolve an entry in the cache.
1801
1801
1802 The instance is instructed to look for the cache key that it was
1802 The instance is instructed to look for the cache key that it was
1803 informed about via the call to ``setcachekey()``.
1803 informed about via the call to ``setcachekey()``.
1804
1804
1805 If there's no cache hit or the cacher doesn't wish to use the cached
1805 If there's no cache hit or the cacher doesn't wish to use the cached
1806 entry, ``None`` should be returned.
1806 entry, ``None`` should be returned.
1807
1807
1808 Else, a dict defining the cached result should be returned. The
1808 Else, a dict defining the cached result should be returned. The
1809 dict may have the following keys:
1809 dict may have the following keys:
1810
1810
1811 objs
1811 objs
1812 An iterable of objects that should be sent to the client. That
1812 An iterable of objects that should be sent to the client. That
1813 iterable of objects is expected to be what the command function
1813 iterable of objects is expected to be what the command function
1814 would return if invoked or an equivalent representation thereof.
1814 would return if invoked or an equivalent representation thereof.
1815 """
1815 """
1816
1816
1817 def onobject(obj):
1817 def onobject(obj):
1818 """Called when a new object is emitted from the command function.
1818 """Called when a new object is emitted from the command function.
1819
1819
1820 Receives as its argument the object that was emitted from the
1820 Receives as its argument the object that was emitted from the
1821 command function.
1821 command function.
1822
1822
1823 This method returns an iterator of objects to forward to the output
1823 This method returns an iterator of objects to forward to the output
1824 layer. The easiest implementation is a generator that just
1824 layer. The easiest implementation is a generator that just
1825 ``yield obj``.
1825 ``yield obj``.
1826 """
1826 """
1827
1827
1828 def onfinished():
1828 def onfinished():
1829 """Called after all objects have been emitted from the command function.
1829 """Called after all objects have been emitted from the command function.
1830
1830
1831 Implementations should return an iterator of objects to forward to
1831 Implementations should return an iterator of objects to forward to
1832 the output layer.
1832 the output layer.
1833
1833
1834 This method can be a generator.
1834 This method can be a generator.
1835 """
1835 """
General Comments 0
You need to be logged in to leave comments. Login now