##// END OF EJS Templates
repository: clarify role of imanifestlog...
Gregory Szorc -
r39276:2af6b2d8 default
parent child Browse files
Show More
@@ -1,1400 +1,1406
1 1 # repository.py - Interfaces and base classes for repositories and peers.
2 2 #
3 3 # Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 from .i18n import _
11 11 from . import (
12 12 error,
13 13 )
14 14 from .utils import (
15 15 interfaceutil,
16 16 )
17 17
18 18 # When narrowing is finalized and no longer subject to format changes,
19 19 # we should move this to just "narrow" or similar.
20 20 NARROW_REQUIREMENT = 'narrowhg-experimental'
21 21
22 22 class ipeerconnection(interfaceutil.Interface):
23 23 """Represents a "connection" to a repository.
24 24
25 25 This is the base interface for representing a connection to a repository.
26 26 It holds basic properties and methods applicable to all peer types.
27 27
28 28 This is not a complete interface definition and should not be used
29 29 outside of this module.
30 30 """
31 31 ui = interfaceutil.Attribute("""ui.ui instance""")
32 32
33 33 def url():
34 34 """Returns a URL string representing this peer.
35 35
36 36 Currently, implementations expose the raw URL used to construct the
37 37 instance. It may contain credentials as part of the URL. The
38 38 expectations of the value aren't well-defined and this could lead to
39 39 data leakage.
40 40
41 41 TODO audit/clean consumers and more clearly define the contents of this
42 42 value.
43 43 """
44 44
45 45 def local():
46 46 """Returns a local repository instance.
47 47
48 48 If the peer represents a local repository, returns an object that
49 49 can be used to interface with it. Otherwise returns ``None``.
50 50 """
51 51
52 52 def peer():
53 53 """Returns an object conforming to this interface.
54 54
55 55 Most implementations will ``return self``.
56 56 """
57 57
58 58 def canpush():
59 59 """Returns a boolean indicating if this peer can be pushed to."""
60 60
61 61 def close():
62 62 """Close the connection to this peer.
63 63
64 64 This is called when the peer will no longer be used. Resources
65 65 associated with the peer should be cleaned up.
66 66 """
67 67
68 68 class ipeercapabilities(interfaceutil.Interface):
69 69 """Peer sub-interface related to capabilities."""
70 70
71 71 def capable(name):
72 72 """Determine support for a named capability.
73 73
74 74 Returns ``False`` if capability not supported.
75 75
76 76 Returns ``True`` if boolean capability is supported. Returns a string
77 77 if capability support is non-boolean.
78 78
79 79 Capability strings may or may not map to wire protocol capabilities.
80 80 """
81 81
82 82 def requirecap(name, purpose):
83 83 """Require a capability to be present.
84 84
85 85 Raises a ``CapabilityError`` if the capability isn't present.
86 86 """
87 87
88 88 class ipeercommands(interfaceutil.Interface):
89 89 """Client-side interface for communicating over the wire protocol.
90 90
91 91 This interface is used as a gateway to the Mercurial wire protocol.
92 92 methods commonly call wire protocol commands of the same name.
93 93 """
94 94
95 95 def branchmap():
96 96 """Obtain heads in named branches.
97 97
98 98 Returns a dict mapping branch name to an iterable of nodes that are
99 99 heads on that branch.
100 100 """
101 101
102 102 def capabilities():
103 103 """Obtain capabilities of the peer.
104 104
105 105 Returns a set of string capabilities.
106 106 """
107 107
108 108 def clonebundles():
109 109 """Obtains the clone bundles manifest for the repo.
110 110
111 111 Returns the manifest as unparsed bytes.
112 112 """
113 113
114 114 def debugwireargs(one, two, three=None, four=None, five=None):
115 115 """Used to facilitate debugging of arguments passed over the wire."""
116 116
117 117 def getbundle(source, **kwargs):
118 118 """Obtain remote repository data as a bundle.
119 119
120 120 This command is how the bulk of repository data is transferred from
121 121 the peer to the local repository
122 122
123 123 Returns a generator of bundle data.
124 124 """
125 125
126 126 def heads():
127 127 """Determine all known head revisions in the peer.
128 128
129 129 Returns an iterable of binary nodes.
130 130 """
131 131
132 132 def known(nodes):
133 133 """Determine whether multiple nodes are known.
134 134
135 135 Accepts an iterable of nodes whose presence to check for.
136 136
137 137 Returns an iterable of booleans indicating of the corresponding node
138 138 at that index is known to the peer.
139 139 """
140 140
141 141 def listkeys(namespace):
142 142 """Obtain all keys in a pushkey namespace.
143 143
144 144 Returns an iterable of key names.
145 145 """
146 146
147 147 def lookup(key):
148 148 """Resolve a value to a known revision.
149 149
150 150 Returns a binary node of the resolved revision on success.
151 151 """
152 152
153 153 def pushkey(namespace, key, old, new):
154 154 """Set a value using the ``pushkey`` protocol.
155 155
156 156 Arguments correspond to the pushkey namespace and key to operate on and
157 157 the old and new values for that key.
158 158
159 159 Returns a string with the peer result. The value inside varies by the
160 160 namespace.
161 161 """
162 162
163 163 def stream_out():
164 164 """Obtain streaming clone data.
165 165
166 166 Successful result should be a generator of data chunks.
167 167 """
168 168
169 169 def unbundle(bundle, heads, url):
170 170 """Transfer repository data to the peer.
171 171
172 172 This is how the bulk of data during a push is transferred.
173 173
174 174 Returns the integer number of heads added to the peer.
175 175 """
176 176
177 177 class ipeerlegacycommands(interfaceutil.Interface):
178 178 """Interface for implementing support for legacy wire protocol commands.
179 179
180 180 Wire protocol commands transition to legacy status when they are no longer
181 181 used by modern clients. To facilitate identifying which commands are
182 182 legacy, the interfaces are split.
183 183 """
184 184
185 185 def between(pairs):
186 186 """Obtain nodes between pairs of nodes.
187 187
188 188 ``pairs`` is an iterable of node pairs.
189 189
190 190 Returns an iterable of iterables of nodes corresponding to each
191 191 requested pair.
192 192 """
193 193
194 194 def branches(nodes):
195 195 """Obtain ancestor changesets of specific nodes back to a branch point.
196 196
197 197 For each requested node, the peer finds the first ancestor node that is
198 198 a DAG root or is a merge.
199 199
200 200 Returns an iterable of iterables with the resolved values for each node.
201 201 """
202 202
203 203 def changegroup(nodes, source):
204 204 """Obtain a changegroup with data for descendants of specified nodes."""
205 205
206 206 def changegroupsubset(bases, heads, source):
207 207 pass
208 208
209 209 class ipeercommandexecutor(interfaceutil.Interface):
210 210 """Represents a mechanism to execute remote commands.
211 211
212 212 This is the primary interface for requesting that wire protocol commands
213 213 be executed. Instances of this interface are active in a context manager
214 214 and have a well-defined lifetime. When the context manager exits, all
215 215 outstanding requests are waited on.
216 216 """
217 217
218 218 def callcommand(name, args):
219 219 """Request that a named command be executed.
220 220
221 221 Receives the command name and a dictionary of command arguments.
222 222
223 223 Returns a ``concurrent.futures.Future`` that will resolve to the
224 224 result of that command request. That exact value is left up to
225 225 the implementation and possibly varies by command.
226 226
227 227 Not all commands can coexist with other commands in an executor
228 228 instance: it depends on the underlying wire protocol transport being
229 229 used and the command itself.
230 230
231 231 Implementations MAY call ``sendcommands()`` automatically if the
232 232 requested command can not coexist with other commands in this executor.
233 233
234 234 Implementations MAY call ``sendcommands()`` automatically when the
235 235 future's ``result()`` is called. So, consumers using multiple
236 236 commands with an executor MUST ensure that ``result()`` is not called
237 237 until all command requests have been issued.
238 238 """
239 239
240 240 def sendcommands():
241 241 """Trigger submission of queued command requests.
242 242
243 243 Not all transports submit commands as soon as they are requested to
244 244 run. When called, this method forces queued command requests to be
245 245 issued. It will no-op if all commands have already been sent.
246 246
247 247 When called, no more new commands may be issued with this executor.
248 248 """
249 249
250 250 def close():
251 251 """Signal that this command request is finished.
252 252
253 253 When called, no more new commands may be issued. All outstanding
254 254 commands that have previously been issued are waited on before
255 255 returning. This not only includes waiting for the futures to resolve,
256 256 but also waiting for all response data to arrive. In other words,
257 257 calling this waits for all on-wire state for issued command requests
258 258 to finish.
259 259
260 260 When used as a context manager, this method is called when exiting the
261 261 context manager.
262 262
263 263 This method may call ``sendcommands()`` if there are buffered commands.
264 264 """
265 265
266 266 class ipeerrequests(interfaceutil.Interface):
267 267 """Interface for executing commands on a peer."""
268 268
269 269 def commandexecutor():
270 270 """A context manager that resolves to an ipeercommandexecutor.
271 271
272 272 The object this resolves to can be used to issue command requests
273 273 to the peer.
274 274
275 275 Callers should call its ``callcommand`` method to issue command
276 276 requests.
277 277
278 278 A new executor should be obtained for each distinct set of commands
279 279 (possibly just a single command) that the consumer wants to execute
280 280 as part of a single operation or round trip. This is because some
281 281 peers are half-duplex and/or don't support persistent connections.
282 282 e.g. in the case of HTTP peers, commands sent to an executor represent
283 283 a single HTTP request. While some peers may support multiple command
284 284 sends over the wire per executor, consumers need to code to the least
285 285 capable peer. So it should be assumed that command executors buffer
286 286 called commands until they are told to send them and that each
287 287 command executor could result in a new connection or wire-level request
288 288 being issued.
289 289 """
290 290
291 291 class ipeerbase(ipeerconnection, ipeercapabilities, ipeerrequests):
292 292 """Unified interface for peer repositories.
293 293
294 294 All peer instances must conform to this interface.
295 295 """
296 296
297 297 @interfaceutil.implementer(ipeerbase)
298 298 class peer(object):
299 299 """Base class for peer repositories."""
300 300
301 301 def capable(self, name):
302 302 caps = self.capabilities()
303 303 if name in caps:
304 304 return True
305 305
306 306 name = '%s=' % name
307 307 for cap in caps:
308 308 if cap.startswith(name):
309 309 return cap[len(name):]
310 310
311 311 return False
312 312
313 313 def requirecap(self, name, purpose):
314 314 if self.capable(name):
315 315 return
316 316
317 317 raise error.CapabilityError(
318 318 _('cannot %s; remote repository does not support the %r '
319 319 'capability') % (purpose, name))
320 320
321 321 class irevisiondelta(interfaceutil.Interface):
322 322 """Represents a delta between one revision and another.
323 323
324 324 Instances convey enough information to allow a revision to be exchanged
325 325 with another repository.
326 326
327 327 Instances represent the fulltext revision data or a delta against
328 328 another revision. Therefore the ``revision`` and ``delta`` attributes
329 329 are mutually exclusive.
330 330
331 331 Typically used for changegroup generation.
332 332 """
333 333
334 334 node = interfaceutil.Attribute(
335 335 """20 byte node of this revision.""")
336 336
337 337 p1node = interfaceutil.Attribute(
338 338 """20 byte node of 1st parent of this revision.""")
339 339
340 340 p2node = interfaceutil.Attribute(
341 341 """20 byte node of 2nd parent of this revision.""")
342 342
343 343 linknode = interfaceutil.Attribute(
344 344 """20 byte node of the changelog revision this node is linked to.""")
345 345
346 346 flags = interfaceutil.Attribute(
347 347 """2 bytes of integer flags that apply to this revision.""")
348 348
349 349 basenode = interfaceutil.Attribute(
350 350 """20 byte node of the revision this data is a delta against.
351 351
352 352 ``nullid`` indicates that the revision is a full revision and not
353 353 a delta.
354 354 """)
355 355
356 356 baserevisionsize = interfaceutil.Attribute(
357 357 """Size of base revision this delta is against.
358 358
359 359 May be ``None`` if ``basenode`` is ``nullid``.
360 360 """)
361 361
362 362 revision = interfaceutil.Attribute(
363 363 """Raw fulltext of revision data for this node.""")
364 364
365 365 delta = interfaceutil.Attribute(
366 366 """Delta between ``basenode`` and ``node``.
367 367
368 368 Stored in the bdiff delta format.
369 369 """)
370 370
371 371 class irevisiondeltarequest(interfaceutil.Interface):
372 372 """Represents a request to generate an ``irevisiondelta``."""
373 373
374 374 node = interfaceutil.Attribute(
375 375 """20 byte node of revision being requested.""")
376 376
377 377 p1node = interfaceutil.Attribute(
378 378 """20 byte node of 1st parent of revision.""")
379 379
380 380 p2node = interfaceutil.Attribute(
381 381 """20 byte node of 2nd parent of revision.""")
382 382
383 383 linknode = interfaceutil.Attribute(
384 384 """20 byte node to store in ``linknode`` attribute.""")
385 385
386 386 basenode = interfaceutil.Attribute(
387 387 """Base revision that delta should be generated against.
388 388
389 389 If ``nullid``, the derived ``irevisiondelta`` should have its
390 390 ``revision`` field populated and no delta should be generated.
391 391
392 392 If ``None``, the delta may be generated against any revision that
393 393 is an ancestor of this revision. Or a full revision may be used.
394 394
395 395 If any other value, the delta should be produced against that
396 396 revision.
397 397 """)
398 398
399 399 ellipsis = interfaceutil.Attribute(
400 400 """Boolean on whether the ellipsis flag should be set.""")
401 401
402 402 class ifilerevisionssequence(interfaceutil.Interface):
403 403 """Contains index data for all revisions of a file.
404 404
405 405 Types implementing this behave like lists of tuples. The index
406 406 in the list corresponds to the revision number. The values contain
407 407 index metadata.
408 408
409 409 The *null* revision (revision number -1) is always the last item
410 410 in the index.
411 411 """
412 412
413 413 def __len__():
414 414 """The total number of revisions."""
415 415
416 416 def __getitem__(rev):
417 417 """Returns the object having a specific revision number.
418 418
419 419 Returns an 8-tuple with the following fields:
420 420
421 421 offset+flags
422 422 Contains the offset and flags for the revision. 64-bit unsigned
423 423 integer where first 6 bytes are the offset and the next 2 bytes
424 424 are flags. The offset can be 0 if it is not used by the store.
425 425 compressed size
426 426 Size of the revision data in the store. It can be 0 if it isn't
427 427 needed by the store.
428 428 uncompressed size
429 429 Fulltext size. It can be 0 if it isn't needed by the store.
430 430 base revision
431 431 Revision number of revision the delta for storage is encoded
432 432 against. -1 indicates not encoded against a base revision.
433 433 link revision
434 434 Revision number of changelog revision this entry is related to.
435 435 p1 revision
436 436 Revision number of 1st parent. -1 if no 1st parent.
437 437 p2 revision
438 438 Revision number of 2nd parent. -1 if no 1st parent.
439 439 node
440 440 Binary node value for this revision number.
441 441
442 442 Negative values should index off the end of the sequence. ``-1``
443 443 should return the null revision. ``-2`` should return the most
444 444 recent revision.
445 445 """
446 446
447 447 def __contains__(rev):
448 448 """Whether a revision number exists."""
449 449
450 450 def insert(self, i, entry):
451 451 """Add an item to the index at specific revision."""
452 452
453 453 class ifileindex(interfaceutil.Interface):
454 454 """Storage interface for index data of a single file.
455 455
456 456 File storage data is divided into index metadata and data storage.
457 457 This interface defines the index portion of the interface.
458 458
459 459 The index logically consists of:
460 460
461 461 * A mapping between revision numbers and nodes.
462 462 * DAG data (storing and querying the relationship between nodes).
463 463 * Metadata to facilitate storage.
464 464 """
465 465 index = interfaceutil.Attribute(
466 466 """An ``ifilerevisionssequence`` instance.""")
467 467
468 468 def __len__():
469 469 """Obtain the number of revisions stored for this file."""
470 470
471 471 def __iter__():
472 472 """Iterate over revision numbers for this file."""
473 473
474 474 def revs(start=0, stop=None):
475 475 """Iterate over revision numbers for this file, with control."""
476 476
477 477 def parents(node):
478 478 """Returns a 2-tuple of parent nodes for a revision.
479 479
480 480 Values will be ``nullid`` if the parent is empty.
481 481 """
482 482
483 483 def parentrevs(rev):
484 484 """Like parents() but operates on revision numbers."""
485 485
486 486 def rev(node):
487 487 """Obtain the revision number given a node.
488 488
489 489 Raises ``error.LookupError`` if the node is not known.
490 490 """
491 491
492 492 def node(rev):
493 493 """Obtain the node value given a revision number.
494 494
495 495 Raises ``IndexError`` if the node is not known.
496 496 """
497 497
498 498 def lookup(node):
499 499 """Attempt to resolve a value to a node.
500 500
501 501 Value can be a binary node, hex node, revision number, or a string
502 502 that can be converted to an integer.
503 503
504 504 Raises ``error.LookupError`` if a node could not be resolved.
505 505 """
506 506
507 507 def linkrev(rev):
508 508 """Obtain the changeset revision number a revision is linked to."""
509 509
510 510 def flags(rev):
511 511 """Obtain flags used to affect storage of a revision."""
512 512
513 513 def iscensored(rev):
514 514 """Return whether a revision's content has been censored."""
515 515
516 516 def commonancestorsheads(node1, node2):
517 517 """Obtain an iterable of nodes containing heads of common ancestors.
518 518
519 519 See ``ancestor.commonancestorsheads()``.
520 520 """
521 521
522 522 def descendants(revs):
523 523 """Obtain descendant revision numbers for a set of revision numbers.
524 524
525 525 If ``nullrev`` is in the set, this is equivalent to ``revs()``.
526 526 """
527 527
528 528 def headrevs():
529 529 """Obtain a list of revision numbers that are DAG heads.
530 530
531 531 The list is sorted oldest to newest.
532 532
533 533 TODO determine if sorting is required.
534 534 """
535 535
536 536 def heads(start=None, stop=None):
537 537 """Obtain a list of nodes that are DAG heads, with control.
538 538
539 539 The set of revisions examined can be limited by specifying
540 540 ``start`` and ``stop``. ``start`` is a node. ``stop`` is an
541 541 iterable of nodes. DAG traversal starts at earlier revision
542 542 ``start`` and iterates forward until any node in ``stop`` is
543 543 encountered.
544 544 """
545 545
546 546 def children(node):
547 547 """Obtain nodes that are children of a node.
548 548
549 549 Returns a list of nodes.
550 550 """
551 551
552 552 def deltaparent(rev):
553 553 """"Return the revision that is a suitable parent to delta against."""
554 554
555 555 class ifiledata(interfaceutil.Interface):
556 556 """Storage interface for data storage of a specific file.
557 557
558 558 This complements ``ifileindex`` and provides an interface for accessing
559 559 data for a tracked file.
560 560 """
561 561 def rawsize(rev):
562 562 """The size of the fulltext data for a revision as stored."""
563 563
564 564 def size(rev):
565 565 """Obtain the fulltext size of file data.
566 566
567 567 Any metadata is excluded from size measurements. Use ``rawsize()`` if
568 568 metadata size is important.
569 569 """
570 570
571 571 def checkhash(fulltext, node, p1=None, p2=None, rev=None):
572 572 """Validate the stored hash of a given fulltext and node.
573 573
574 574 Raises ``error.RevlogError`` is hash validation fails.
575 575 """
576 576
577 577 def revision(node, raw=False):
578 578 """"Obtain fulltext data for a node.
579 579
580 580 By default, any storage transformations are applied before the data
581 581 is returned. If ``raw`` is True, non-raw storage transformations
582 582 are not applied.
583 583
584 584 The fulltext data may contain a header containing metadata. Most
585 585 consumers should use ``read()`` to obtain the actual file data.
586 586 """
587 587
588 588 def read(node):
589 589 """Resolve file fulltext data.
590 590
591 591 This is similar to ``revision()`` except any metadata in the data
592 592 headers is stripped.
593 593 """
594 594
595 595 def renamed(node):
596 596 """Obtain copy metadata for a node.
597 597
598 598 Returns ``False`` if no copy metadata is stored or a 2-tuple of
599 599 (path, node) from which this revision was copied.
600 600 """
601 601
602 602 def cmp(node, fulltext):
603 603 """Compare fulltext to another revision.
604 604
605 605 Returns True if the fulltext is different from what is stored.
606 606
607 607 This takes copy metadata into account.
608 608
609 609 TODO better document the copy metadata and censoring logic.
610 610 """
611 611
612 612 def revdiff(rev1, rev2):
613 613 """Obtain a delta between two revision numbers.
614 614
615 615 Operates on raw data in the store (``revision(node, raw=True)``).
616 616
617 617 The returned data is the result of ``bdiff.bdiff`` on the raw
618 618 revision data.
619 619 """
620 620
621 621 def emitrevisiondeltas(requests):
622 622 """Produce ``irevisiondelta`` from ``irevisiondeltarequest``s.
623 623
624 624 Given an iterable of objects conforming to the ``irevisiondeltarequest``
625 625 interface, emits objects conforming to the ``irevisiondelta``
626 626 interface.
627 627
628 628 This method is a generator.
629 629
630 630 ``irevisiondelta`` should be emitted in the same order of
631 631 ``irevisiondeltarequest`` that was passed in.
632 632
633 633 The emitted objects MUST conform by the results of
634 634 ``irevisiondeltarequest``. Namely, they must respect any requests
635 635 for building a delta from a specific ``basenode`` if defined.
636 636
637 637 When sending deltas, implementations must take into account whether
638 638 the client has the base delta before encoding a delta against that
639 639 revision. A revision encountered previously in ``requests`` is
640 640 always a suitable base revision. An example of a bad delta is a delta
641 641 against a non-ancestor revision. Another example of a bad delta is a
642 642 delta against a censored revision.
643 643 """
644 644
645 645 class ifilemutation(interfaceutil.Interface):
646 646 """Storage interface for mutation events of a tracked file."""
647 647
648 648 def add(filedata, meta, transaction, linkrev, p1, p2):
649 649 """Add a new revision to the store.
650 650
651 651 Takes file data, dictionary of metadata, a transaction, linkrev,
652 652 and parent nodes.
653 653
654 654 Returns the node that was added.
655 655
656 656 May no-op if a revision matching the supplied data is already stored.
657 657 """
658 658
659 659 def addrevision(revisiondata, transaction, linkrev, p1, p2, node=None,
660 660 flags=0, cachedelta=None):
661 661 """Add a new revision to the store.
662 662
663 663 This is similar to ``add()`` except it operates at a lower level.
664 664
665 665 The data passed in already contains a metadata header, if any.
666 666
667 667 ``node`` and ``flags`` can be used to define the expected node and
668 668 the flags to use with storage.
669 669
670 670 ``add()`` is usually called when adding files from e.g. the working
671 671 directory. ``addrevision()`` is often called by ``add()`` and for
672 672 scenarios where revision data has already been computed, such as when
673 673 applying raw data from a peer repo.
674 674 """
675 675
676 676 def addgroup(deltas, linkmapper, transaction, addrevisioncb=None):
677 677 """Process a series of deltas for storage.
678 678
679 679 ``deltas`` is an iterable of 7-tuples of
680 680 (node, p1, p2, linknode, deltabase, delta, flags) defining revisions
681 681 to add.
682 682
683 683 The ``delta`` field contains ``mpatch`` data to apply to a base
684 684 revision, identified by ``deltabase``. The base node can be
685 685 ``nullid``, in which case the header from the delta can be ignored
686 686 and the delta used as the fulltext.
687 687
688 688 ``addrevisioncb`` should be called for each node as it is committed.
689 689
690 690 Returns a list of nodes that were processed. A node will be in the list
691 691 even if it existed in the store previously.
692 692 """
693 693
694 694 def getstrippoint(minlink):
695 695 """Find the minimum revision that must be stripped to strip a linkrev.
696 696
697 697 Returns a 2-tuple containing the minimum revision number and a set
698 698 of all revisions numbers that would be broken by this strip.
699 699
700 700 TODO this is highly revlog centric and should be abstracted into
701 701 a higher-level deletion API. ``repair.strip()`` relies on this.
702 702 """
703 703
704 704 def strip(minlink, transaction):
705 705 """Remove storage of items starting at a linkrev.
706 706
707 707 This uses ``getstrippoint()`` to determine the first node to remove.
708 708 Then it effectively truncates storage for all revisions after that.
709 709
710 710 TODO this is highly revlog centric and should be abstracted into a
711 711 higher-level deletion API.
712 712 """
713 713
714 714 class ifilestorage(ifileindex, ifiledata, ifilemutation):
715 715 """Complete storage interface for a single tracked file."""
716 716
717 717 version = interfaceutil.Attribute(
718 718 """Version number of storage.
719 719
720 720 TODO this feels revlog centric and could likely be removed.
721 721 """)
722 722
723 723 _generaldelta = interfaceutil.Attribute(
724 724 """Whether deltas can be against any parent revision.
725 725
726 726 TODO this is used by changegroup code and it could probably be
727 727 folded into another API.
728 728 """)
729 729
730 730 def files():
731 731 """Obtain paths that are backing storage for this file.
732 732
733 733 TODO this is used heavily by verify code and there should probably
734 734 be a better API for that.
735 735 """
736 736
737 737 def checksize():
738 738 """Obtain the expected sizes of backing files.
739 739
740 740 TODO this is used by verify and it should not be part of the interface.
741 741 """
742 742
743 743 class idirs(interfaceutil.Interface):
744 744 """Interface representing a collection of directories from paths.
745 745
746 746 This interface is essentially a derived data structure representing
747 747 directories from a collection of paths.
748 748 """
749 749
750 750 def addpath(path):
751 751 """Add a path to the collection.
752 752
753 753 All directories in the path will be added to the collection.
754 754 """
755 755
756 756 def delpath(path):
757 757 """Remove a path from the collection.
758 758
759 759 If the removal was the last path in a particular directory, the
760 760 directory is removed from the collection.
761 761 """
762 762
763 763 def __iter__():
764 764 """Iterate over the directories in this collection of paths."""
765 765
766 766 def __contains__(path):
767 767 """Whether a specific directory is in this collection."""
768 768
769 769 class imanifestdict(interfaceutil.Interface):
770 770 """Interface representing a manifest data structure.
771 771
772 772 A manifest is effectively a dict mapping paths to entries. Each entry
773 773 consists of a binary node and extra flags affecting that entry.
774 774 """
775 775
776 776 def __getitem__(path):
777 777 """Returns the binary node value for a path in the manifest.
778 778
779 779 Raises ``KeyError`` if the path does not exist in the manifest.
780 780
781 781 Equivalent to ``self.find(path)[0]``.
782 782 """
783 783
784 784 def find(path):
785 785 """Returns the entry for a path in the manifest.
786 786
787 787 Returns a 2-tuple of (node, flags).
788 788
789 789 Raises ``KeyError`` if the path does not exist in the manifest.
790 790 """
791 791
792 792 def __len__():
793 793 """Return the number of entries in the manifest."""
794 794
795 795 def __nonzero__():
796 796 """Returns True if the manifest has entries, False otherwise."""
797 797
798 798 __bool__ = __nonzero__
799 799
800 800 def __setitem__(path, node):
801 801 """Define the node value for a path in the manifest.
802 802
803 803 If the path is already in the manifest, its flags will be copied to
804 804 the new entry.
805 805 """
806 806
807 807 def __contains__(path):
808 808 """Whether a path exists in the manifest."""
809 809
810 810 def __delitem__(path):
811 811 """Remove a path from the manifest.
812 812
813 813 Raises ``KeyError`` if the path is not in the manifest.
814 814 """
815 815
816 816 def __iter__():
817 817 """Iterate over paths in the manifest."""
818 818
819 819 def iterkeys():
820 820 """Iterate over paths in the manifest."""
821 821
822 822 def keys():
823 823 """Obtain a list of paths in the manifest."""
824 824
825 825 def filesnotin(other, match=None):
826 826 """Obtain the set of paths in this manifest but not in another.
827 827
828 828 ``match`` is an optional matcher function to be applied to both
829 829 manifests.
830 830
831 831 Returns a set of paths.
832 832 """
833 833
834 834 def dirs():
835 835 """Returns an object implementing the ``idirs`` interface."""
836 836
837 837 def hasdir(dir):
838 838 """Returns a bool indicating if a directory is in this manifest."""
839 839
840 840 def matches(match):
841 841 """Generate a new manifest filtered through a matcher.
842 842
843 843 Returns an object conforming to the ``imanifestdict`` interface.
844 844 """
845 845
846 846 def walk(match):
847 847 """Generator of paths in manifest satisfying a matcher.
848 848
849 849 This is equivalent to ``self.matches(match).iterkeys()`` except a new
850 850 manifest object is not created.
851 851
852 852 If the matcher has explicit files listed and they don't exist in
853 853 the manifest, ``match.bad()`` is called for each missing file.
854 854 """
855 855
856 856 def diff(other, match=None, clean=False):
857 857 """Find differences between this manifest and another.
858 858
859 859 This manifest is compared to ``other``.
860 860
861 861 If ``match`` is provided, the two manifests are filtered against this
862 862 matcher and only entries satisfying the matcher are compared.
863 863
864 864 If ``clean`` is True, unchanged files are included in the returned
865 865 object.
866 866
867 867 Returns a dict with paths as keys and values of 2-tuples of 2-tuples of
868 868 the form ``((node1, flag1), (node2, flag2))`` where ``(node1, flag1)``
869 869 represents the node and flags for this manifest and ``(node2, flag2)``
870 870 are the same for the other manifest.
871 871 """
872 872
873 873 def setflag(path, flag):
874 874 """Set the flag value for a given path.
875 875
876 876 Raises ``KeyError`` if the path is not already in the manifest.
877 877 """
878 878
879 879 def get(path, default=None):
880 880 """Obtain the node value for a path or a default value if missing."""
881 881
882 882 def flags(path, default=''):
883 883 """Return the flags value for a path or a default value if missing."""
884 884
885 885 def copy():
886 886 """Return a copy of this manifest."""
887 887
888 888 def items():
889 889 """Returns an iterable of (path, node) for items in this manifest."""
890 890
891 891 def iteritems():
892 892 """Identical to items()."""
893 893
894 894 def iterentries():
895 895 """Returns an iterable of (path, node, flags) for this manifest.
896 896
897 897 Similar to ``iteritems()`` except items are a 3-tuple and include
898 898 flags.
899 899 """
900 900
901 901 def text():
902 902 """Obtain the raw data representation for this manifest.
903 903
904 904 Result is used to create a manifest revision.
905 905 """
906 906
907 907 def fastdelta(base, changes):
908 908 """Obtain a delta between this manifest and another given changes.
909 909
910 910 ``base`` in the raw data representation for another manifest.
911 911
912 912 ``changes`` is an iterable of ``(path, to_delete)``.
913 913
914 914 Returns a 2-tuple containing ``bytearray(self.text())`` and the
915 915 delta between ``base`` and this manifest.
916 916 """
917 917
918 918 class imanifestrevisionbase(interfaceutil.Interface):
919 919 """Base interface representing a single revision of a manifest.
920 920
921 921 Should not be used as a primary interface: should always be inherited
922 922 as part of a larger interface.
923 923 """
924 924
925 925 def new():
926 926 """Obtain a new manifest instance.
927 927
928 928 Returns an object conforming to the ``imanifestrevisionwritable``
929 929 interface. The instance will be associated with the same
930 930 ``imanifestlog`` collection as this instance.
931 931 """
932 932
933 933 def copy():
934 934 """Obtain a copy of this manifest instance.
935 935
936 936 Returns an object conforming to the ``imanifestrevisionwritable``
937 937 interface. The instance will be associated with the same
938 938 ``imanifestlog`` collection as this instance.
939 939 """
940 940
941 941 def read():
942 942 """Obtain the parsed manifest data structure.
943 943
944 944 The returned object conforms to the ``imanifestdict`` interface.
945 945 """
946 946
947 947 class imanifestrevisionstored(imanifestrevisionbase):
948 948 """Interface representing a manifest revision committed to storage."""
949 949
950 950 def node():
951 951 """The binary node for this manifest."""
952 952
953 953 parents = interfaceutil.Attribute(
954 954 """List of binary nodes that are parents for this manifest revision."""
955 955 )
956 956
957 957 def readdelta(shallow=False):
958 958 """Obtain the manifest data structure representing changes from parent.
959 959
960 960 This manifest is compared to its 1st parent. A new manifest representing
961 961 those differences is constructed.
962 962
963 963 The returned object conforms to the ``imanifestdict`` interface.
964 964 """
965 965
966 966 def readfast(shallow=False):
967 967 """Calls either ``read()`` or ``readdelta()``.
968 968
969 969 The faster of the two options is called.
970 970 """
971 971
972 972 def find(key):
973 973 """Calls self.read().find(key)``.
974 974
975 975 Returns a 2-tuple of ``(node, flags)`` or raises ``KeyError``.
976 976 """
977 977
978 978 class imanifestrevisionwritable(imanifestrevisionbase):
979 979 """Interface representing a manifest revision that can be committed."""
980 980
981 981 def write(transaction, linkrev, p1node, p2node, added, removed):
982 982 """Add this revision to storage.
983 983
984 984 Takes a transaction object, the changeset revision number it will
985 985 be associated with, its parent nodes, and lists of added and
986 986 removed paths.
987 987
988 988 Returns the binary node of the created revision.
989 989 """
990 990
991 991 class imanifestlog(interfaceutil.Interface):
992 """Interface representing a collection of manifest snapshots."""
992 """Interface representing a collection of manifest snapshots.
993
994 Represents the root manifest in a repository.
995
996 Also serves as a means to access nested tree manifests and to cache
997 tree manifests.
998 """
993 999
994 1000 def __getitem__(node):
995 1001 """Obtain a manifest instance for a given binary node.
996 1002
997 1003 Equivalent to calling ``self.get('', node)``.
998 1004
999 1005 The returned object conforms to the ``imanifestrevisionstored``
1000 1006 interface.
1001 1007 """
1002 1008
1003 1009 def get(tree, node, verify=True):
1004 1010 """Retrieve the manifest instance for a given directory and binary node.
1005 1011
1006 1012 ``node`` always refers to the node of the root manifest (which will be
1007 1013 the only manifest if flat manifests are being used).
1008 1014
1009 1015 If ``tree`` is the empty string, the root manifest is returned.
1010 1016 Otherwise the manifest for the specified directory will be returned
1011 1017 (requires tree manifests).
1012 1018
1013 1019 If ``verify`` is True, ``LookupError`` is raised if the node is not
1014 1020 known.
1015 1021
1016 1022 The returned object conforms to the ``imanifestrevisionstored``
1017 1023 interface.
1018 1024 """
1019 1025
1020 1026 def clearcaches():
1021 1027 """Clear caches associated with this collection."""
1022 1028
1023 1029 def rev(node):
1024 1030 """Obtain the revision number for a binary node.
1025 1031
1026 1032 Raises ``error.LookupError`` if the node is not known.
1027 1033 """
1028 1034
1029 1035 def addgroup(deltas, linkmapper, transaction):
1030 1036 """Process a series of deltas for storage.
1031 1037
1032 1038 ``deltas`` is an iterable of 7-tuples of
1033 1039 (node, p1, p2, linknode, deltabase, delta, flags) defining revisions
1034 1040 to add.
1035 1041
1036 1042 The ``delta`` field contains ``mpatch`` data to apply to a base
1037 1043 revision, identified by ``deltabase``. The base node can be
1038 1044 ``nullid``, in which case the header from the delta can be ignored
1039 1045 and the delta used as the fulltext.
1040 1046
1041 1047 Returns a list of nodes that were processed. A node will be in the list
1042 1048 even if it existed in the store previously.
1043 1049 """
1044 1050
1045 1051 class completelocalrepository(interfaceutil.Interface):
1046 1052 """Monolithic interface for local repositories.
1047 1053
1048 1054 This currently captures the reality of things - not how things should be.
1049 1055 """
1050 1056
1051 1057 supportedformats = interfaceutil.Attribute(
1052 1058 """Set of requirements that apply to stream clone.
1053 1059
1054 1060 This is actually a class attribute and is shared among all instances.
1055 1061 """)
1056 1062
1057 1063 openerreqs = interfaceutil.Attribute(
1058 1064 """Set of requirements that are passed to the opener.
1059 1065
1060 1066 This is actually a class attribute and is shared among all instances.
1061 1067 """)
1062 1068
1063 1069 supported = interfaceutil.Attribute(
1064 1070 """Set of requirements that this repo is capable of opening.""")
1065 1071
1066 1072 requirements = interfaceutil.Attribute(
1067 1073 """Set of requirements this repo uses.""")
1068 1074
1069 1075 filtername = interfaceutil.Attribute(
1070 1076 """Name of the repoview that is active on this repo.""")
1071 1077
1072 1078 wvfs = interfaceutil.Attribute(
1073 1079 """VFS used to access the working directory.""")
1074 1080
1075 1081 vfs = interfaceutil.Attribute(
1076 1082 """VFS rooted at the .hg directory.
1077 1083
1078 1084 Used to access repository data not in the store.
1079 1085 """)
1080 1086
1081 1087 svfs = interfaceutil.Attribute(
1082 1088 """VFS rooted at the store.
1083 1089
1084 1090 Used to access repository data in the store. Typically .hg/store.
1085 1091 But can point elsewhere if the store is shared.
1086 1092 """)
1087 1093
1088 1094 root = interfaceutil.Attribute(
1089 1095 """Path to the root of the working directory.""")
1090 1096
1091 1097 path = interfaceutil.Attribute(
1092 1098 """Path to the .hg directory.""")
1093 1099
1094 1100 origroot = interfaceutil.Attribute(
1095 1101 """The filesystem path that was used to construct the repo.""")
1096 1102
1097 1103 auditor = interfaceutil.Attribute(
1098 1104 """A pathauditor for the working directory.
1099 1105
1100 1106 This checks if a path refers to a nested repository.
1101 1107
1102 1108 Operates on the filesystem.
1103 1109 """)
1104 1110
1105 1111 nofsauditor = interfaceutil.Attribute(
1106 1112 """A pathauditor for the working directory.
1107 1113
1108 1114 This is like ``auditor`` except it doesn't do filesystem checks.
1109 1115 """)
1110 1116
1111 1117 baseui = interfaceutil.Attribute(
1112 1118 """Original ui instance passed into constructor.""")
1113 1119
1114 1120 ui = interfaceutil.Attribute(
1115 1121 """Main ui instance for this instance.""")
1116 1122
1117 1123 sharedpath = interfaceutil.Attribute(
1118 1124 """Path to the .hg directory of the repo this repo was shared from.""")
1119 1125
1120 1126 store = interfaceutil.Attribute(
1121 1127 """A store instance.""")
1122 1128
1123 1129 spath = interfaceutil.Attribute(
1124 1130 """Path to the store.""")
1125 1131
1126 1132 sjoin = interfaceutil.Attribute(
1127 1133 """Alias to self.store.join.""")
1128 1134
1129 1135 cachevfs = interfaceutil.Attribute(
1130 1136 """A VFS used to access the cache directory.
1131 1137
1132 1138 Typically .hg/cache.
1133 1139 """)
1134 1140
1135 1141 filteredrevcache = interfaceutil.Attribute(
1136 1142 """Holds sets of revisions to be filtered.""")
1137 1143
1138 1144 names = interfaceutil.Attribute(
1139 1145 """A ``namespaces`` instance.""")
1140 1146
1141 1147 def close():
1142 1148 """Close the handle on this repository."""
1143 1149
1144 1150 def peer():
1145 1151 """Obtain an object conforming to the ``peer`` interface."""
1146 1152
1147 1153 def unfiltered():
1148 1154 """Obtain an unfiltered/raw view of this repo."""
1149 1155
1150 1156 def filtered(name, visibilityexceptions=None):
1151 1157 """Obtain a named view of this repository."""
1152 1158
1153 1159 obsstore = interfaceutil.Attribute(
1154 1160 """A store of obsolescence data.""")
1155 1161
1156 1162 changelog = interfaceutil.Attribute(
1157 1163 """A handle on the changelog revlog.""")
1158 1164
1159 1165 manifestlog = interfaceutil.Attribute(
1160 1166 """An instance conforming to the ``imanifestlog`` interface.
1161 1167
1162 1168 Provides access to manifests for the repository.
1163 1169 """)
1164 1170
1165 1171 dirstate = interfaceutil.Attribute(
1166 1172 """Working directory state.""")
1167 1173
1168 1174 narrowpats = interfaceutil.Attribute(
1169 1175 """Matcher patterns for this repository's narrowspec.""")
1170 1176
1171 1177 def narrowmatch():
1172 1178 """Obtain a matcher for the narrowspec."""
1173 1179
1174 1180 def setnarrowpats(newincludes, newexcludes):
1175 1181 """Define the narrowspec for this repository."""
1176 1182
1177 1183 def __getitem__(changeid):
1178 1184 """Try to resolve a changectx."""
1179 1185
1180 1186 def __contains__(changeid):
1181 1187 """Whether a changeset exists."""
1182 1188
1183 1189 def __nonzero__():
1184 1190 """Always returns True."""
1185 1191 return True
1186 1192
1187 1193 __bool__ = __nonzero__
1188 1194
1189 1195 def __len__():
1190 1196 """Returns the number of changesets in the repo."""
1191 1197
1192 1198 def __iter__():
1193 1199 """Iterate over revisions in the changelog."""
1194 1200
1195 1201 def revs(expr, *args):
1196 1202 """Evaluate a revset.
1197 1203
1198 1204 Emits revisions.
1199 1205 """
1200 1206
1201 1207 def set(expr, *args):
1202 1208 """Evaluate a revset.
1203 1209
1204 1210 Emits changectx instances.
1205 1211 """
1206 1212
1207 1213 def anyrevs(specs, user=False, localalias=None):
1208 1214 """Find revisions matching one of the given revsets."""
1209 1215
1210 1216 def url():
1211 1217 """Returns a string representing the location of this repo."""
1212 1218
1213 1219 def hook(name, throw=False, **args):
1214 1220 """Call a hook."""
1215 1221
1216 1222 def tags():
1217 1223 """Return a mapping of tag to node."""
1218 1224
1219 1225 def tagtype(tagname):
1220 1226 """Return the type of a given tag."""
1221 1227
1222 1228 def tagslist():
1223 1229 """Return a list of tags ordered by revision."""
1224 1230
1225 1231 def nodetags(node):
1226 1232 """Return the tags associated with a node."""
1227 1233
1228 1234 def nodebookmarks(node):
1229 1235 """Return the list of bookmarks pointing to the specified node."""
1230 1236
1231 1237 def branchmap():
1232 1238 """Return a mapping of branch to heads in that branch."""
1233 1239
1234 1240 def revbranchcache():
1235 1241 pass
1236 1242
1237 1243 def branchtip(branchtip, ignoremissing=False):
1238 1244 """Return the tip node for a given branch."""
1239 1245
1240 1246 def lookup(key):
1241 1247 """Resolve the node for a revision."""
1242 1248
1243 1249 def lookupbranch(key):
1244 1250 """Look up the branch name of the given revision or branch name."""
1245 1251
1246 1252 def known(nodes):
1247 1253 """Determine whether a series of nodes is known.
1248 1254
1249 1255 Returns a list of bools.
1250 1256 """
1251 1257
1252 1258 def local():
1253 1259 """Whether the repository is local."""
1254 1260 return True
1255 1261
1256 1262 def publishing():
1257 1263 """Whether the repository is a publishing repository."""
1258 1264
1259 1265 def cancopy():
1260 1266 pass
1261 1267
1262 1268 def shared():
1263 1269 """The type of shared repository or None."""
1264 1270
1265 1271 def wjoin(f, *insidef):
1266 1272 """Calls self.vfs.reljoin(self.root, f, *insidef)"""
1267 1273
1268 1274 def file(f):
1269 1275 """Obtain a filelog for a tracked path.
1270 1276
1271 1277 The returned type conforms to the ``ifilestorage`` interface.
1272 1278 """
1273 1279
1274 1280 def setparents(p1, p2):
1275 1281 """Set the parent nodes of the working directory."""
1276 1282
1277 1283 def filectx(path, changeid=None, fileid=None):
1278 1284 """Obtain a filectx for the given file revision."""
1279 1285
1280 1286 def getcwd():
1281 1287 """Obtain the current working directory from the dirstate."""
1282 1288
1283 1289 def pathto(f, cwd=None):
1284 1290 """Obtain the relative path to a file."""
1285 1291
1286 1292 def adddatafilter(name, fltr):
1287 1293 pass
1288 1294
1289 1295 def wread(filename):
1290 1296 """Read a file from wvfs, using data filters."""
1291 1297
1292 1298 def wwrite(filename, data, flags, backgroundclose=False, **kwargs):
1293 1299 """Write data to a file in the wvfs, using data filters."""
1294 1300
1295 1301 def wwritedata(filename, data):
1296 1302 """Resolve data for writing to the wvfs, using data filters."""
1297 1303
1298 1304 def currenttransaction():
1299 1305 """Obtain the current transaction instance or None."""
1300 1306
1301 1307 def transaction(desc, report=None):
1302 1308 """Open a new transaction to write to the repository."""
1303 1309
1304 1310 def undofiles():
1305 1311 """Returns a list of (vfs, path) for files to undo transactions."""
1306 1312
1307 1313 def recover():
1308 1314 """Roll back an interrupted transaction."""
1309 1315
1310 1316 def rollback(dryrun=False, force=False):
1311 1317 """Undo the last transaction.
1312 1318
1313 1319 DANGEROUS.
1314 1320 """
1315 1321
1316 1322 def updatecaches(tr=None, full=False):
1317 1323 """Warm repo caches."""
1318 1324
1319 1325 def invalidatecaches():
1320 1326 """Invalidate cached data due to the repository mutating."""
1321 1327
1322 1328 def invalidatevolatilesets():
1323 1329 pass
1324 1330
1325 1331 def invalidatedirstate():
1326 1332 """Invalidate the dirstate."""
1327 1333
1328 1334 def invalidate(clearfilecache=False):
1329 1335 pass
1330 1336
1331 1337 def invalidateall():
1332 1338 pass
1333 1339
1334 1340 def lock(wait=True):
1335 1341 """Lock the repository store and return a lock instance."""
1336 1342
1337 1343 def wlock(wait=True):
1338 1344 """Lock the non-store parts of the repository."""
1339 1345
1340 1346 def currentwlock():
1341 1347 """Return the wlock if it's held or None."""
1342 1348
1343 1349 def checkcommitpatterns(wctx, vdirs, match, status, fail):
1344 1350 pass
1345 1351
1346 1352 def commit(text='', user=None, date=None, match=None, force=False,
1347 1353 editor=False, extra=None):
1348 1354 """Add a new revision to the repository."""
1349 1355
1350 1356 def commitctx(ctx, error=False):
1351 1357 """Commit a commitctx instance to the repository."""
1352 1358
1353 1359 def destroying():
1354 1360 """Inform the repository that nodes are about to be destroyed."""
1355 1361
1356 1362 def destroyed():
1357 1363 """Inform the repository that nodes have been destroyed."""
1358 1364
1359 1365 def status(node1='.', node2=None, match=None, ignored=False,
1360 1366 clean=False, unknown=False, listsubrepos=False):
1361 1367 """Convenience method to call repo[x].status()."""
1362 1368
1363 1369 def addpostdsstatus(ps):
1364 1370 pass
1365 1371
1366 1372 def postdsstatus():
1367 1373 pass
1368 1374
1369 1375 def clearpostdsstatus():
1370 1376 pass
1371 1377
1372 1378 def heads(start=None):
1373 1379 """Obtain list of nodes that are DAG heads."""
1374 1380
1375 1381 def branchheads(branch=None, start=None, closed=False):
1376 1382 pass
1377 1383
1378 1384 def branches(nodes):
1379 1385 pass
1380 1386
1381 1387 def between(pairs):
1382 1388 pass
1383 1389
1384 1390 def checkpush(pushop):
1385 1391 pass
1386 1392
1387 1393 prepushoutgoinghooks = interfaceutil.Attribute(
1388 1394 """util.hooks instance.""")
1389 1395
1390 1396 def pushkey(namespace, key, old, new):
1391 1397 pass
1392 1398
1393 1399 def listkeys(namespace):
1394 1400 pass
1395 1401
1396 1402 def debugwireargs(one, two, three=None, four=None, five=None):
1397 1403 pass
1398 1404
1399 1405 def savecommitmessage(text):
1400 1406 pass
General Comments 0
You need to be logged in to leave comments. Login now