~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revisionspec.py

  • Committer: Ian Clatworthy
  • Date: 2007-08-13 14:33:10 UTC
  • mto: (2733.1.1 ianc-integration)
  • mto: This revision was merged to the branch mainline in revision 2734.
  • Revision ID: ian.clatworthy@internode.on.net-20070813143310-twhj4la0qnupvze8
Added Quick Start Summary

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