~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revisionspec.py

  • Committer: Martin Pool
  • Date: 2007-04-04 06:17:31 UTC
  • mto: This revision was merged to the branch mainline in revision 2397.
  • Revision ID: mbp@sourcefrog.net-20070404061731-tt2xrzllqhbodn83
Contents of TODO file moved into bug tracker

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)
162
 
        else:
163
 
            for spectype in SPEC_TYPES:
 
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):
164
167
                trace.mutter('Returning RevisionSpec %s for %s',
165
168
                             spectype.__name__, spec)
166
 
                if spec.startswith(spectype.prefix):
167
 
                    return spectype(spec, _internal=True)
 
169
                return spectype(spec, _internal=True)
 
170
        else:
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
198
201
 
199
202
    def _match_on(self, branch, revs):
200
203
        trace.mutter('Returning RevisionSpec._match_on: None')
201
 
        return RevisionInfo(branch, None, None)
 
204
        return RevisionInfo(branch, 0, None)
202
205
 
203
206
    def _match_on_and_check(self, branch, revs):
204
207
        info = self._match_on(branch, revs)
205
208
        if info:
206
209
            return info
207
 
        elif info == (None, None):
208
 
            # special case - nothing supplied
 
210
        elif info == (0, None):
 
211
            # special case - the empty tree
209
212
            return info
210
213
        elif self.prefix:
211
214
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
214
217
 
215
218
    def in_history(self, branch):
216
219
        if branch:
217
 
            if self.wants_revision_history:
218
 
                revs = branch.revision_history()
219
 
            else:
220
 
                revs = None
 
220
            revs = branch.revision_history()
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
 
 
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
 
 
 
236
        
272
237
    def __repr__(self):
273
238
        # this is mostly for helping with testing
274
239
        return '<%s %s>' % (self.__class__.__name__,
275
240
                              self.user_spec)
276
 
 
 
241
    
277
242
    def needs_branch(self):
278
243
        """Whether this revision spec needs a branch.
279
244
 
283
248
 
284
249
    def get_branch(self):
285
250
        """When the revision specifier contains a branch location, return it.
286
 
 
 
251
        
287
252
        Otherwise, return None.
288
253
        """
289
254
        return None
301
266
    A negative number will count from the end of the branch (-1 is the
302
267
    last revision, -2 the previous one). If the negative number is larger
303
268
    than the branch's history, the first revision is returned.
304
 
    Examples::
305
 
 
306
 
      revno:1                   -> return the first revision of this branch
 
269
    examples:
 
270
      revno:1                   -> return the first revision
307
271
      revno:3:/path/to/branch   -> return the 3rd revision of
308
272
                                   the branch '/path/to/branch'
309
273
      revno:-1                  -> The last revision in a branch.
313
277
                                   your history is very long.
314
278
    """
315
279
    prefix = 'revno:'
316
 
    wants_revision_history = False
317
280
 
318
281
    def _match_on(self, branch, revs):
319
282
        """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):
324
283
        loc = self.spec.find(':')
325
284
        if loc == -1:
326
285
            revno_spec = self.spec
340
299
                dotted = False
341
300
            except ValueError:
342
301
                # dotted decimal. This arguably should not be here
343
 
                # but the from_string method is a little primitive
 
302
                # but the from_string method is a little primitive 
344
303
                # right now - RBC 20060928
345
304
                try:
346
305
                    match_revno = tuple((int(number) for number in revno_spec.split('.')))
355
314
            # the branch object.
356
315
            from bzrlib.branch import Branch
357
316
            branch = Branch.open(branch_spec)
358
 
            revs_or_none = None
 
317
            # Need to use a new revision history
 
318
            # because we are using a specific branch
 
319
            revs = branch.revision_history()
359
320
 
360
321
        if dotted:
 
322
            branch.lock_read()
361
323
            try:
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)
 
324
                last_rev = branch.last_revision()
 
325
                merge_sorted_revisions = tsort.merge_sort(
 
326
                    branch.repository.get_revision_graph(last_rev),
 
327
                    last_rev,
 
328
                    generate_revno=True)
 
329
                def match(item):
 
330
                    return item[3] == match_revno
 
331
                revisions = filter(match, merge_sorted_revisions)
 
332
            finally:
 
333
                branch.unlock()
 
334
            if len(revisions) != 1:
 
335
                return RevisionInfo(branch, None, None)
366
336
            else:
367
337
                # there is no traditional 'revno' for dotted-decimal revnos.
368
338
                # so for  API compatability we return None.
369
 
                return branch, None, revision_id
 
339
                return RevisionInfo(branch, None, revisions[0][1])
370
340
        else:
371
 
            last_revno, last_revision_id = branch.last_revision_info()
372
341
            if revno < 0:
373
342
                # if get_rev_id supported negative revnos, there would not be a
374
343
                # need for this special case.
375
 
                if (-revno) >= last_revno:
 
344
                if (-revno) >= len(revs):
376
345
                    revno = 1
377
346
                else:
378
 
                    revno = last_revno + revno + 1
 
347
                    revno = len(revs) + revno + 1
379
348
            try:
380
 
                revision_id = branch.get_rev_id(revno, revs_or_none)
 
349
                revision_id = branch.get_rev_id(revno, revs)
381
350
            except errors.NoSuchRevision:
382
351
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
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
 
 
 
352
        return RevisionInfo(branch, revno, revision_id)
 
353
        
390
354
    def needs_branch(self):
391
355
        return self.spec.find(':') == -1
392
356
 
396
360
        else:
397
361
            return self.spec[self.spec.find(':')+1:]
398
362
 
399
 
# Old compatibility
 
363
# Old compatibility 
400
364
RevisionSpec_int = RevisionSpec_revno
401
365
 
 
366
SPEC_TYPES.append(RevisionSpec_revno)
402
367
 
403
368
 
404
369
class RevisionSpec_revid(RevisionSpec):
407
372
    help_txt = """Selects a revision using the revision id.
408
373
 
409
374
    Supply a specific revision id, that can be used to specify any
410
 
    revision id in the ancestry of the branch.
 
375
    revision id in the ancestry of the branch. 
411
376
    Including merges, and pending merges.
412
 
    Examples::
413
 
 
 
377
    examples:
414
378
      revid:aaaa@bbbb-123456789 -> Select revision 'aaaa@bbbb-123456789'
415
 
    """
416
 
 
 
379
    """    
417
380
    prefix = 'revid:'
418
381
 
419
382
    def _match_on(self, branch, revs):
423
386
        revision_id = osutils.safe_revision_id(self.spec, warn=False)
424
387
        return RevisionInfo.from_revision_id(branch, revision_id, revs)
425
388
 
426
 
    def _as_revision_id(self, context_branch):
427
 
        return osutils.safe_revision_id(self.spec, warn=False)
428
 
 
 
389
SPEC_TYPES.append(RevisionSpec_revid)
429
390
 
430
391
 
431
392
class RevisionSpec_last(RevisionSpec):
435
396
 
436
397
    Supply a positive number to get the nth revision from the end.
437
398
    This is the same as supplying negative numbers to the 'revno:' spec.
438
 
    Examples::
439
 
 
 
399
    examples:
440
400
      last:1        -> return the last revision
441
401
      last:3        -> return the revision 2 before the end.
442
 
    """
 
402
    """    
443
403
 
444
404
    prefix = 'last:'
445
405
 
446
406
    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
 
 
453
407
        if self.spec == '':
454
 
            if not last_revno:
455
 
                raise errors.NoCommits(context_branch)
456
 
            return last_revno, last_revision_id
 
408
            if not revs:
 
409
                raise errors.NoCommits(branch)
 
410
            return RevisionInfo(branch, len(revs), revs[-1])
457
411
 
458
412
        try:
459
413
            offset = int(self.spec)
460
414
        except ValueError, e:
461
 
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch, e)
 
415
            raise errors.InvalidRevisionSpec(self.user_spec, branch, e)
462
416
 
463
417
        if offset <= 0:
464
 
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
418
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
465
419
                                             'you must supply a positive value')
466
 
 
467
 
        revno = last_revno - offset + 1
 
420
        revno = len(revs) - offset + 1
468
421
        try:
469
 
            revision_id = context_branch.get_rev_id(revno, revs_or_none)
 
422
            revision_id = branch.get_rev_id(revno, revs)
470
423
        except errors.NoSuchRevision:
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
 
 
 
424
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
 
425
        return RevisionInfo(branch, revno, revision_id)
 
426
 
 
427
SPEC_TYPES.append(RevisionSpec_last)
480
428
 
481
429
 
482
430
class RevisionSpec_before(RevisionSpec):
484
432
 
485
433
    help_txt = """Selects the parent of the revision specified.
486
434
 
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
    Supply any revision spec to return the parent of that revision.
491
436
    It is an error to request the parent of the null revision (before:0).
492
 
 
493
 
    Examples::
494
 
 
 
437
    This is mostly useful when inspecting revisions that are not in the
 
438
    revision history of a branch.
 
439
 
 
440
    examples:
495
441
      before:1913    -> Return the parent of revno 1913 (revno 1912)
496
442
      before:revid:aaaa@bbbb-1234567890  -> return the parent of revision
497
443
                                            aaaa@bbbb-1234567890
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
 
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)
502
447
    """
503
448
 
504
449
    prefix = 'before:'
505
 
 
 
450
    
506
451
    def _match_on(self, branch, revs):
507
452
        r = RevisionSpec.from_string(self.spec)._match_on(branch, revs)
508
453
        if r.revno == 0:
513
458
            rev = branch.repository.get_revision(r.rev_id)
514
459
            if not rev.parent_ids:
515
460
                revno = 0
516
 
                revision_id = revision.NULL_REVISION
 
461
                revision_id = None
517
462
            else:
518
463
                revision_id = rev.parent_ids[0]
519
464
                try:
529
474
                                                 branch)
530
475
        return RevisionInfo(branch, revno, revision_id)
531
476
 
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
 
 
 
477
SPEC_TYPES.append(RevisionSpec_before)
554
478
 
555
479
 
556
480
class RevisionSpec_tag(RevisionSpec):
569
493
            branch.tags.lookup_tag(self.spec),
570
494
            revs)
571
495
 
572
 
    def _as_revision_id(self, context_branch):
573
 
        return context_branch.tags.lookup_tag(self.spec)
574
 
 
 
496
SPEC_TYPES.append(RevisionSpec_tag)
575
497
 
576
498
 
577
499
class _RevListToTimestamps(object):
603
525
    Matches the first entry after a given date (either at midnight or
604
526
    at a specified time).
605
527
 
606
 
    One way to display all the changes since yesterday would be::
607
 
 
608
 
        bzr log -r date:yesterday..
609
 
 
610
 
    Examples::
611
 
 
 
528
    One way to display all the changes since yesterday would be:
 
529
        bzr log -r date:yesterday..-1
 
530
 
 
531
    examples:
612
532
      date:yesterday            -> select the first revision since yesterday
613
533
      date:2006-08-14,17:10:14  -> select the first revision after
614
534
                                   August 14th, 2006 at 5:10pm.
615
 
    """
 
535
    """    
616
536
    prefix = 'date:'
617
537
    _date_re = re.compile(
618
538
            r'(?P<date>(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d))?'
674
594
        finally:
675
595
            branch.unlock()
676
596
        if rev == len(revs):
677
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
 
597
            return RevisionInfo(branch, None)
678
598
        else:
679
599
            return RevisionInfo(branch, rev + 1)
680
600
 
 
601
SPEC_TYPES.append(RevisionSpec_date)
681
602
 
682
603
 
683
604
class RevisionSpec_ancestor(RevisionSpec):
695
616
    that your branch introduces, while excluding the changes that you
696
617
    have not merged from the remote branch.
697
618
 
698
 
    Examples::
699
 
 
 
619
    examples:
700
620
      ancestor:/path/to/branch
701
621
      $ bzr diff -r ancestor:../../mainline/branch
702
622
    """
706
626
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
707
627
        return self._find_revision_info(branch, self.spec)
708
628
 
709
 
    def _as_revision_id(self, context_branch):
710
 
        return self._find_revision_id(context_branch, self.spec)
711
 
 
712
629
    @staticmethod
713
630
    def _find_revision_info(branch, other_location):
714
 
        revision_id = RevisionSpec_ancestor._find_revision_id(branch,
715
 
                                                              other_location)
 
631
        from bzrlib.branch import Branch
 
632
 
 
633
        other_branch = Branch.open(other_location)
 
634
        revision_a = branch.last_revision()
 
635
        revision_b = other_branch.last_revision()
 
636
        for r, b in ((revision_a, branch), (revision_b, other_branch)):
 
637
            if r in (None, revision.NULL_REVISION):
 
638
                raise errors.NoCommits(b)
 
639
        revision_source = revision.MultipleRevisionSources(
 
640
                branch.repository, other_branch.repository)
 
641
        rev_id = revision.common_ancestor(revision_a, revision_b,
 
642
                                          revision_source)
716
643
        try:
717
 
            revno = branch.revision_id_to_revno(revision_id)
 
644
            revno = branch.revision_id_to_revno(rev_id)
718
645
        except errors.NoSuchRevision:
719
646
            revno = None
720
 
        return RevisionInfo(branch, revno, revision_id)
721
 
 
722
 
    @staticmethod
723
 
    def _find_revision_id(branch, other_location):
724
 
        from bzrlib.branch import Branch
725
 
 
726
 
        branch.lock_read()
727
 
        try:
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)
740
 
                rev_id = graph.find_unique_lca(revision_a, revision_b)
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
746
 
        finally:
747
 
            branch.unlock()
748
 
 
749
 
 
 
647
        return RevisionInfo(branch, revno, rev_id)
 
648
 
 
649
 
 
650
SPEC_TYPES.append(RevisionSpec_ancestor)
750
651
 
751
652
 
752
653
class RevisionSpec_branch(RevisionSpec):
756
657
 
757
658
    Supply the path to a branch to select its last revision.
758
659
 
759
 
    Examples::
760
 
 
 
660
    examples:
761
661
      branch:/path/to/branch
762
662
    """
763
663
    prefix = 'branch:'
775
675
        except errors.NoSuchRevision:
776
676
            revno = None
777
677
        return RevisionInfo(branch, revno, revision_b)
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
 
 
 
678
        
 
679
SPEC_TYPES.append(RevisionSpec_branch)
798
680
 
799
681
 
800
682
class RevisionSpec_submit(RevisionSpec_ancestor):
804
686
 
805
687
    Diffing against this shows all the changes that were made in this branch,
806
688
    and is a good predictor of what merge will do.  The submit branch is
807
 
    used by the bundle and merge directive commands.  If no submit branch
 
689
    used by the bundle and merge directive comands.  If no submit branch
808
690
    is specified, the parent branch is used instead.
809
691
 
810
692
    The common ancestor is the last revision that existed in both
811
693
    branches. Usually this is the branch point, but it could also be
812
694
    a revision that was merged.
813
695
 
814
 
    Examples::
815
 
 
 
696
    examples:
816
697
      $ bzr diff -r submit:
817
698
    """
818
699
 
819
700
    prefix = 'submit:'
820
701
 
821
 
    def _get_submit_location(self, branch):
 
702
    def _match_on(self, branch, revs):
 
703
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
822
704
        submit_location = branch.get_submit_branch()
823
705
        location_type = 'submit branch'
824
706
        if submit_location is None:
827
709
        if submit_location is None:
828
710
            raise errors.NoSubmitBranch(branch)
829
711
        trace.note('Using %s %s', location_type, submit_location)
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", [])
 
712
        return self._find_revision_info(branch, submit_location)
 
713
 
 
714
 
 
715
SPEC_TYPES.append(RevisionSpec_submit)