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