~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revisionspec.py

  • Committer: Sabin Iacob
  • Date: 2009-03-23 14:59:43 UTC
  • mto: (4189.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4193.
  • Revision ID: iacobs@m0n5t3r.info-20090323145943-3s3p1px5q1rkh2e5
update FSF mailing address

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
 
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
 
 
18
import re
 
19
 
 
20
from bzrlib.lazy_import import lazy_import
 
21
lazy_import(globals(), """
18
22
import bisect
19
23
import datetime
20
 
import re
 
24
""")
21
25
 
22
26
from bzrlib import (
23
27
    errors,
24
28
    osutils,
 
29
    registry,
25
30
    revision,
26
31
    symbol_versioning,
27
32
    trace,
28
 
    tsort,
29
33
    )
30
34
 
31
35
 
100
104
 
101
105
        Use this if you don't know or care what the revno is.
102
106
        """
 
107
        if revision_id == revision.NULL_REVISION:
 
108
            return RevisionInfo(branch, 0, revision_id)
103
109
        try:
104
110
            revno = revs.index(revision_id) + 1
105
111
        except ValueError:
109
115
 
110
116
# classes in this list should have a "prefix" attribute, against which
111
117
# string specs are matched
112
 
SPEC_TYPES = []
113
118
_revno_regex = None
114
119
 
115
120
 
133
138
    """
134
139
 
135
140
    prefix = None
136
 
 
137
 
    def __new__(cls, spec, _internal=False):
138
 
        if _internal:
139
 
            return object.__new__(cls, spec, _internal=_internal)
140
 
 
141
 
        symbol_versioning.warn('Creating a RevisionSpec directly has'
142
 
                               ' been deprecated in version 0.11. Use'
143
 
                               ' RevisionSpec.from_string()'
144
 
                               ' instead.',
145
 
                               DeprecationWarning, stacklevel=2)
146
 
        return RevisionSpec.from_string(spec)
 
141
    wants_revision_history = True
147
142
 
148
143
    @staticmethod
149
144
    def from_string(spec):
158
153
 
159
154
        if spec is None:
160
155
            return RevisionSpec(None, _internal=True)
161
 
 
162
 
        assert isinstance(spec, basestring), \
163
 
            "You should only supply strings not %s" % (type(spec),)
164
 
 
165
 
        for spectype in SPEC_TYPES:
166
 
            if spec.startswith(spectype.prefix):
 
156
        match = revspec_registry.get_prefix(spec)
 
157
        if match is not None:
 
158
            spectype, specsuffix = match
 
159
            trace.mutter('Returning RevisionSpec %s for %s',
 
160
                         spectype.__name__, spec)
 
161
            return spectype(spec, _internal=True)
 
162
        else:
 
163
            for spectype in SPEC_TYPES:
167
164
                trace.mutter('Returning RevisionSpec %s for %s',
168
165
                             spectype.__name__, spec)
169
 
                return spectype(spec, _internal=True)
170
 
        else:
 
166
                if spec.startswith(spectype.prefix):
 
167
                    return spectype(spec, _internal=True)
171
168
            # RevisionSpec_revno is special cased, because it is the only
172
169
            # one that directly handles plain integers
173
170
            # TODO: This should not be special cased rather it should be
201
198
 
202
199
    def _match_on(self, branch, revs):
203
200
        trace.mutter('Returning RevisionSpec._match_on: None')
204
 
        return RevisionInfo(branch, 0, None)
 
201
        return RevisionInfo(branch, None, None)
205
202
 
206
203
    def _match_on_and_check(self, branch, revs):
207
204
        info = self._match_on(branch, revs)
208
205
        if info:
209
206
            return info
210
 
        elif info == (0, None):
211
 
            # special case - the empty tree
 
207
        elif info == (None, None):
 
208
            # special case - nothing supplied
212
209
            return info
213
210
        elif self.prefix:
214
211
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
217
214
 
218
215
    def in_history(self, branch):
219
216
        if branch:
220
 
            revs = branch.revision_history()
 
217
            if self.wants_revision_history:
 
218
                revs = branch.revision_history()
 
219
            else:
 
220
                revs = None
221
221
        else:
222
222
            # this should never trigger.
223
223
            # TODO: make it a deprecated code path. RBC 20060928
233
233
    # will do what you expect.
234
234
    in_store = in_history
235
235
    in_branch = in_store
236
 
        
 
236
 
 
237
    def as_revision_id(self, context_branch):
 
238
        """Return just the revision_id for this revisions spec.
 
239
 
 
240
        Some revision specs require a context_branch to be able to determine
 
241
        their value. Not all specs will make use of it.
 
242
        """
 
243
        return self._as_revision_id(context_branch)
 
244
 
 
245
    def _as_revision_id(self, context_branch):
 
246
        """Implementation of as_revision_id()
 
247
 
 
248
        Classes should override this function to provide appropriate
 
249
        functionality. The default is to just call '.in_history().rev_id'
 
250
        """
 
251
        return self.in_history(context_branch).rev_id
 
252
 
 
253
    def as_tree(self, context_branch):
 
254
        """Return the tree object for this revisions spec.
 
255
 
 
256
        Some revision specs require a context_branch to be able to determine
 
257
        the revision id and access the repository. Not all specs will make
 
258
        use of it.
 
259
        """
 
260
        return self._as_tree(context_branch)
 
261
 
 
262
    def _as_tree(self, context_branch):
 
263
        """Implementation of as_tree().
 
264
 
 
265
        Classes should override this function to provide appropriate
 
266
        functionality. The default is to just call '.as_revision_id()'
 
267
        and get the revision tree from context_branch's repository.
 
268
        """
 
269
        revision_id = self.as_revision_id(context_branch)
 
270
        return context_branch.repository.revision_tree(revision_id)
 
271
 
237
272
    def __repr__(self):
238
273
        # this is mostly for helping with testing
239
274
        return '<%s %s>' % (self.__class__.__name__,
240
275
                              self.user_spec)
241
 
    
 
276
 
242
277
    def needs_branch(self):
243
278
        """Whether this revision spec needs a branch.
244
279
 
248
283
 
249
284
    def get_branch(self):
250
285
        """When the revision specifier contains a branch location, return it.
251
 
        
 
286
 
252
287
        Otherwise, return None.
253
288
        """
254
289
        return None
268
303
    than the branch's history, the first revision is returned.
269
304
    Examples::
270
305
 
271
 
      revno:1                   -> return the first revision
 
306
      revno:1                   -> return the first revision of this branch
272
307
      revno:3:/path/to/branch   -> return the 3rd revision of
273
308
                                   the branch '/path/to/branch'
274
309
      revno:-1                  -> The last revision in a branch.
278
313
                                   your history is very long.
279
314
    """
280
315
    prefix = 'revno:'
 
316
    wants_revision_history = False
281
317
 
282
318
    def _match_on(self, branch, revs):
283
319
        """Lookup a revision by revision number"""
 
320
        branch, revno, revision_id = self._lookup(branch, revs)
 
321
        return RevisionInfo(branch, revno, revision_id)
 
322
 
 
323
    def _lookup(self, branch, revs_or_none):
284
324
        loc = self.spec.find(':')
285
325
        if loc == -1:
286
326
            revno_spec = self.spec
300
340
                dotted = False
301
341
            except ValueError:
302
342
                # dotted decimal. This arguably should not be here
303
 
                # but the from_string method is a little primitive 
 
343
                # but the from_string method is a little primitive
304
344
                # right now - RBC 20060928
305
345
                try:
306
346
                    match_revno = tuple((int(number) for number in revno_spec.split('.')))
315
355
            # the branch object.
316
356
            from bzrlib.branch import Branch
317
357
            branch = Branch.open(branch_spec)
318
 
            # Need to use a new revision history
319
 
            # because we are using a specific branch
320
 
            revs = branch.revision_history()
 
358
            revs_or_none = None
321
359
 
322
360
        if dotted:
323
 
            branch.lock_read()
324
361
            try:
325
 
                revision_id_to_revno = branch.get_revision_id_to_revno_map()
326
 
                revisions = [revision_id for revision_id, revno
327
 
                             in revision_id_to_revno.iteritems()
328
 
                             if revno == match_revno]
329
 
            finally:
330
 
                branch.unlock()
331
 
            if len(revisions) != 1:
332
 
                return RevisionInfo(branch, None, None)
 
362
                revision_id = branch.dotted_revno_to_revision_id(match_revno,
 
363
                    _cache_reverse=True)
 
364
            except errors.NoSuchRevision:
 
365
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
333
366
            else:
334
367
                # there is no traditional 'revno' for dotted-decimal revnos.
335
368
                # so for  API compatability we return None.
336
 
                return RevisionInfo(branch, None, revisions[0])
 
369
                return branch, None, revision_id
337
370
        else:
 
371
            last_revno, last_revision_id = branch.last_revision_info()
338
372
            if revno < 0:
339
373
                # if get_rev_id supported negative revnos, there would not be a
340
374
                # need for this special case.
341
 
                if (-revno) >= len(revs):
 
375
                if (-revno) >= last_revno:
342
376
                    revno = 1
343
377
                else:
344
 
                    revno = len(revs) + revno + 1
 
378
                    revno = last_revno + revno + 1
345
379
            try:
346
 
                revision_id = branch.get_rev_id(revno, revs)
 
380
                revision_id = branch.get_rev_id(revno, revs_or_none)
347
381
            except errors.NoSuchRevision:
348
382
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
349
 
        return RevisionInfo(branch, revno, revision_id)
350
 
        
 
383
        return branch, revno, revision_id
 
384
 
 
385
    def _as_revision_id(self, context_branch):
 
386
        # We would have the revno here, but we don't really care
 
387
        branch, revno, revision_id = self._lookup(context_branch, None)
 
388
        return revision_id
 
389
 
351
390
    def needs_branch(self):
352
391
        return self.spec.find(':') == -1
353
392
 
357
396
        else:
358
397
            return self.spec[self.spec.find(':')+1:]
359
398
 
360
 
# Old compatibility 
 
399
# Old compatibility
361
400
RevisionSpec_int = RevisionSpec_revno
362
401
 
363
 
SPEC_TYPES.append(RevisionSpec_revno)
364
402
 
365
403
 
366
404
class RevisionSpec_revid(RevisionSpec):
369
407
    help_txt = """Selects a revision using the revision id.
370
408
 
371
409
    Supply a specific revision id, that can be used to specify any
372
 
    revision id in the ancestry of the branch. 
 
410
    revision id in the ancestry of the branch.
373
411
    Including merges, and pending merges.
374
412
    Examples::
375
413
 
376
414
      revid:aaaa@bbbb-123456789 -> Select revision 'aaaa@bbbb-123456789'
377
 
    """    
 
415
    """
 
416
 
378
417
    prefix = 'revid:'
379
418
 
380
419
    def _match_on(self, branch, revs):
384
423
        revision_id = osutils.safe_revision_id(self.spec, warn=False)
385
424
        return RevisionInfo.from_revision_id(branch, revision_id, revs)
386
425
 
387
 
SPEC_TYPES.append(RevisionSpec_revid)
 
426
    def _as_revision_id(self, context_branch):
 
427
        return osutils.safe_revision_id(self.spec, warn=False)
 
428
 
388
429
 
389
430
 
390
431
class RevisionSpec_last(RevisionSpec):
398
439
 
399
440
      last:1        -> return the last revision
400
441
      last:3        -> return the revision 2 before the end.
401
 
    """    
 
442
    """
402
443
 
403
444
    prefix = 'last:'
404
445
 
405
446
    def _match_on(self, branch, revs):
 
447
        revno, revision_id = self._revno_and_revision_id(branch, revs)
 
448
        return RevisionInfo(branch, revno, revision_id)
 
449
 
 
450
    def _revno_and_revision_id(self, context_branch, revs_or_none):
 
451
        last_revno, last_revision_id = context_branch.last_revision_info()
 
452
 
406
453
        if self.spec == '':
407
 
            if not revs:
408
 
                raise errors.NoCommits(branch)
409
 
            return RevisionInfo(branch, len(revs), revs[-1])
 
454
            if not last_revno:
 
455
                raise errors.NoCommits(context_branch)
 
456
            return last_revno, last_revision_id
410
457
 
411
458
        try:
412
459
            offset = int(self.spec)
413
460
        except ValueError, e:
414
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch, e)
 
461
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch, e)
415
462
 
416
463
        if offset <= 0:
417
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
 
464
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
418
465
                                             'you must supply a positive value')
419
 
        revno = len(revs) - offset + 1
 
466
 
 
467
        revno = last_revno - offset + 1
420
468
        try:
421
 
            revision_id = branch.get_rev_id(revno, revs)
 
469
            revision_id = context_branch.get_rev_id(revno, revs_or_none)
422
470
        except errors.NoSuchRevision:
423
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
424
 
        return RevisionInfo(branch, revno, revision_id)
425
 
 
426
 
SPEC_TYPES.append(RevisionSpec_last)
 
471
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
 
472
        return revno, revision_id
 
473
 
 
474
    def _as_revision_id(self, context_branch):
 
475
        # We compute the revno as part of the process, but we don't really care
 
476
        # about it.
 
477
        revno, revision_id = self._revno_and_revision_id(context_branch, None)
 
478
        return revision_id
 
479
 
427
480
 
428
481
 
429
482
class RevisionSpec_before(RevisionSpec):
431
484
 
432
485
    help_txt = """Selects the parent of the revision specified.
433
486
 
434
 
    Supply any revision spec to return the parent of that revision.
 
487
    Supply any revision spec to return the parent of that revision.  This is
 
488
    mostly useful when inspecting revisions that are not in the revision history
 
489
    of a branch.
 
490
 
435
491
    It is an error to request the parent of the null revision (before:0).
436
 
    This is mostly useful when inspecting revisions that are not in the
437
 
    revision history of a branch.
438
492
 
439
493
    Examples::
440
494
 
441
495
      before:1913    -> Return the parent of revno 1913 (revno 1912)
442
496
      before:revid:aaaa@bbbb-1234567890  -> return the parent of revision
443
497
                                            aaaa@bbbb-1234567890
444
 
      bzr diff -r before:revid:aaaa..revid:aaaa
445
 
            -> Find the changes between revision 'aaaa' and its parent.
446
 
               (what changes did 'aaaa' introduce)
 
498
      bzr diff -r before:1913..1913
 
499
            -> Find the changes between revision 1913 and its parent (1912).
 
500
               (What changes did revision 1913 introduce).
 
501
               This is equivalent to:  bzr diff -c 1913
447
502
    """
448
503
 
449
504
    prefix = 'before:'
450
 
    
 
505
 
451
506
    def _match_on(self, branch, revs):
452
507
        r = RevisionSpec.from_string(self.spec)._match_on(branch, revs)
453
508
        if r.revno == 0:
474
529
                                                 branch)
475
530
        return RevisionInfo(branch, revno, revision_id)
476
531
 
477
 
SPEC_TYPES.append(RevisionSpec_before)
 
532
    def _as_revision_id(self, context_branch):
 
533
        base_revspec = RevisionSpec.from_string(self.spec)
 
534
        base_revision_id = base_revspec.as_revision_id(context_branch)
 
535
        if base_revision_id == revision.NULL_REVISION:
 
536
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
537
                                         'cannot go before the null: revision')
 
538
        context_repo = context_branch.repository
 
539
        context_repo.lock_read()
 
540
        try:
 
541
            parent_map = context_repo.get_parent_map([base_revision_id])
 
542
        finally:
 
543
            context_repo.unlock()
 
544
        if base_revision_id not in parent_map:
 
545
            # Ghost, or unknown revision id
 
546
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
547
                'cannot find the matching revision')
 
548
        parents = parent_map[base_revision_id]
 
549
        if len(parents) < 1:
 
550
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
551
                'No parents for revision.')
 
552
        return parents[0]
 
553
 
478
554
 
479
555
 
480
556
class RevisionSpec_tag(RevisionSpec):
493
569
            branch.tags.lookup_tag(self.spec),
494
570
            revs)
495
571
 
496
 
SPEC_TYPES.append(RevisionSpec_tag)
 
572
    def _as_revision_id(self, context_branch):
 
573
        return context_branch.tags.lookup_tag(self.spec)
 
574
 
497
575
 
498
576
 
499
577
class _RevListToTimestamps(object):
527
605
 
528
606
    One way to display all the changes since yesterday would be::
529
607
 
530
 
        bzr log -r date:yesterday..-1
 
608
        bzr log -r date:yesterday..
531
609
 
532
610
    Examples::
533
611
 
534
612
      date:yesterday            -> select the first revision since yesterday
535
613
      date:2006-08-14,17:10:14  -> select the first revision after
536
614
                                   August 14th, 2006 at 5:10pm.
537
 
    """    
 
615
    """
538
616
    prefix = 'date:'
539
617
    _date_re = re.compile(
540
618
            r'(?P<date>(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d))?'
596
674
        finally:
597
675
            branch.unlock()
598
676
        if rev == len(revs):
599
 
            return RevisionInfo(branch, None)
 
677
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
600
678
        else:
601
679
            return RevisionInfo(branch, rev + 1)
602
680
 
603
 
SPEC_TYPES.append(RevisionSpec_date)
604
681
 
605
682
 
606
683
class RevisionSpec_ancestor(RevisionSpec):
629
706
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
630
707
        return self._find_revision_info(branch, self.spec)
631
708
 
 
709
    def _as_revision_id(self, context_branch):
 
710
        return self._find_revision_id(context_branch, self.spec)
 
711
 
632
712
    @staticmethod
633
713
    def _find_revision_info(branch, other_location):
 
714
        revision_id = RevisionSpec_ancestor._find_revision_id(branch,
 
715
                                                              other_location)
 
716
        try:
 
717
            revno = branch.revision_id_to_revno(revision_id)
 
718
        except errors.NoSuchRevision:
 
719
            revno = None
 
720
        return RevisionInfo(branch, revno, revision_id)
 
721
 
 
722
    @staticmethod
 
723
    def _find_revision_id(branch, other_location):
634
724
        from bzrlib.branch import Branch
635
725
 
636
 
        other_branch = Branch.open(other_location)
637
 
        revision_a = branch.last_revision()
638
 
        revision_b = other_branch.last_revision()
639
 
        for r, b in ((revision_a, branch), (revision_b, other_branch)):
640
 
            if r in (None, revision.NULL_REVISION):
641
 
                raise errors.NoCommits(b)
642
726
        branch.lock_read()
643
 
        other_branch.lock_read()
644
727
        try:
645
 
            revision_source = revision.MultipleRevisionSources(
646
 
                    branch.repository, other_branch.repository)
647
 
            graph = branch.repository.get_graph(other_branch.repository)
648
 
            revision_a = revision.ensure_null(revision_a)
649
 
            revision_b = revision.ensure_null(revision_b)
650
 
            if revision.NULL_REVISION in (revision_a, revision_b):
651
 
                rev_id = revision.NULL_REVISION
652
 
            else:
 
728
            revision_a = revision.ensure_null(branch.last_revision())
 
729
            if revision_a == revision.NULL_REVISION:
 
730
                raise errors.NoCommits(branch)
 
731
            if other_location == '':
 
732
                other_location = branch.get_parent()
 
733
            other_branch = Branch.open(other_location)
 
734
            other_branch.lock_read()
 
735
            try:
 
736
                revision_b = revision.ensure_null(other_branch.last_revision())
 
737
                if revision_b == revision.NULL_REVISION:
 
738
                    raise errors.NoCommits(other_branch)
 
739
                graph = branch.repository.get_graph(other_branch.repository)
653
740
                rev_id = graph.find_unique_lca(revision_a, revision_b)
654
 
                if rev_id == revision.NULL_REVISION:
655
 
                    raise errors.NoCommonAncestor(revision_a, revision_b)
656
 
            try:
657
 
                revno = branch.revision_id_to_revno(rev_id)
658
 
            except errors.NoSuchRevision:
659
 
                revno = None
660
 
            return RevisionInfo(branch, revno, rev_id)
 
741
            finally:
 
742
                other_branch.unlock()
 
743
            if rev_id == revision.NULL_REVISION:
 
744
                raise errors.NoCommonAncestor(revision_a, revision_b)
 
745
            return rev_id
661
746
        finally:
662
747
            branch.unlock()
663
 
            other_branch.unlock()
664
 
 
665
 
 
666
 
SPEC_TYPES.append(RevisionSpec_ancestor)
 
748
 
 
749
 
667
750
 
668
751
 
669
752
class RevisionSpec_branch(RevisionSpec):
692
775
        except errors.NoSuchRevision:
693
776
            revno = None
694
777
        return RevisionInfo(branch, revno, revision_b)
695
 
        
696
 
SPEC_TYPES.append(RevisionSpec_branch)
 
778
 
 
779
    def _as_revision_id(self, context_branch):
 
780
        from bzrlib.branch import Branch
 
781
        other_branch = Branch.open(self.spec)
 
782
        last_revision = other_branch.last_revision()
 
783
        last_revision = revision.ensure_null(last_revision)
 
784
        context_branch.fetch(other_branch, last_revision)
 
785
        if last_revision == revision.NULL_REVISION:
 
786
            raise errors.NoCommits(other_branch)
 
787
        return last_revision
 
788
 
 
789
    def _as_tree(self, context_branch):
 
790
        from bzrlib.branch import Branch
 
791
        other_branch = Branch.open(self.spec)
 
792
        last_revision = other_branch.last_revision()
 
793
        last_revision = revision.ensure_null(last_revision)
 
794
        if last_revision == revision.NULL_REVISION:
 
795
            raise errors.NoCommits(other_branch)
 
796
        return other_branch.repository.revision_tree(last_revision)
 
797
 
697
798
 
698
799
 
699
800
class RevisionSpec_submit(RevisionSpec_ancestor):
703
804
 
704
805
    Diffing against this shows all the changes that were made in this branch,
705
806
    and is a good predictor of what merge will do.  The submit branch is
706
 
    used by the bundle and merge directive comands.  If no submit branch
 
807
    used by the bundle and merge directive commands.  If no submit branch
707
808
    is specified, the parent branch is used instead.
708
809
 
709
810
    The common ancestor is the last revision that existed in both
717
818
 
718
819
    prefix = 'submit:'
719
820
 
720
 
    def _match_on(self, branch, revs):
721
 
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
 
821
    def _get_submit_location(self, branch):
722
822
        submit_location = branch.get_submit_branch()
723
823
        location_type = 'submit branch'
724
824
        if submit_location is None:
727
827
        if submit_location is None:
728
828
            raise errors.NoSubmitBranch(branch)
729
829
        trace.note('Using %s %s', location_type, submit_location)
730
 
        return self._find_revision_info(branch, submit_location)
731
 
 
732
 
 
733
 
SPEC_TYPES.append(RevisionSpec_submit)
 
830
        return submit_location
 
831
 
 
832
    def _match_on(self, branch, revs):
 
833
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
 
834
        return self._find_revision_info(branch,
 
835
            self._get_submit_location(branch))
 
836
 
 
837
    def _as_revision_id(self, context_branch):
 
838
        return self._find_revision_id(context_branch,
 
839
            self._get_submit_location(context_branch))
 
840
 
 
841
 
 
842
revspec_registry = registry.Registry()
 
843
def _register_revspec(revspec):
 
844
    revspec_registry.register(revspec.prefix, revspec)
 
845
 
 
846
_register_revspec(RevisionSpec_revno)
 
847
_register_revspec(RevisionSpec_revid)
 
848
_register_revspec(RevisionSpec_last)
 
849
_register_revspec(RevisionSpec_before)
 
850
_register_revspec(RevisionSpec_tag)
 
851
_register_revspec(RevisionSpec_date)
 
852
_register_revspec(RevisionSpec_ancestor)
 
853
_register_revspec(RevisionSpec_branch)
 
854
_register_revspec(RevisionSpec_submit)
 
855
 
 
856
SPEC_TYPES = symbol_versioning.deprecated_list(
 
857
    symbol_versioning.deprecated_in((1, 12, 0)), "SPEC_TYPES", [])