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