~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revisionspec.py

  • Committer: Martin Packman
  • Date: 2012-01-05 10:37:58 UTC
  • mto: This revision was merged to the branch mainline in revision 6427.
  • Revision ID: martin.packman@canonical.com-20120105103758-wzftnmsip5iv9n2g
Revert addition of get_message_encoding function

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
    symbol_versioning,
28
28
    workingtree,
29
29
    )
 
30
from bzrlib.i18n import gettext
30
31
""")
31
32
 
32
33
from bzrlib import (
37
38
    )
38
39
 
39
40
 
40
 
_marker = []
41
 
 
42
 
 
43
41
class RevisionInfo(object):
44
42
    """The results of applying a revision specification to a branch."""
45
43
 
57
55
    or treat the result as a tuple.
58
56
    """
59
57
 
60
 
    def __init__(self, branch, revno, rev_id=_marker):
 
58
    def __init__(self, branch, revno=None, rev_id=None):
61
59
        self.branch = branch
62
 
        self.revno = revno
63
 
        if rev_id is _marker:
 
60
        self._has_revno = (revno is not None)
 
61
        self._revno = revno
 
62
        self.rev_id = rev_id
 
63
        if self.rev_id is None and self._revno is not None:
64
64
            # allow caller to be lazy
65
 
            if self.revno is None:
66
 
                self.rev_id = None
67
 
            else:
68
 
                self.rev_id = branch.get_rev_id(self.revno)
69
 
        else:
70
 
            self.rev_id = rev_id
 
65
            self.rev_id = branch.get_rev_id(self._revno)
 
66
 
 
67
    @property
 
68
    def revno(self):
 
69
        if not self._has_revno and self.rev_id is not None:
 
70
            try:
 
71
                self._revno = self.branch.revision_id_to_revno(self.rev_id)
 
72
            except errors.NoSuchRevision:
 
73
                self._revno = None
 
74
            self._has_revno = True
 
75
        return self._revno
71
76
 
72
77
    def __nonzero__(self):
73
78
        # first the easy ones...
74
79
        if self.rev_id is None:
75
80
            return False
76
 
        if self.revno is not None:
77
 
            return True
78
81
        # TODO: otherwise, it should depend on how I was built -
79
82
        # if it's in_history(branch), then check revision_history(),
80
83
        # if it's in_store(branch), do the check below
103
106
            self.revno, self.rev_id, self.branch)
104
107
 
105
108
    @staticmethod
106
 
    def from_revision_id(branch, revision_id, revs):
 
109
    def from_revision_id(branch, revision_id, revs=symbol_versioning.DEPRECATED_PARAMETER):
107
110
        """Construct a RevisionInfo given just the id.
108
111
 
109
112
        Use this if you don't know or care what the revno is.
110
113
        """
111
 
        if revision_id == revision.NULL_REVISION:
112
 
            return RevisionInfo(branch, 0, revision_id)
113
 
        try:
114
 
            revno = revs.index(revision_id) + 1
115
 
        except ValueError:
116
 
            revno = None
117
 
        return RevisionInfo(branch, revno, revision_id)
 
114
        if symbol_versioning.deprecated_passed(revs):
 
115
            symbol_versioning.warn(
 
116
                'RevisionInfo.from_revision_id(revs) was deprecated in 2.5.',
 
117
                DeprecationWarning,
 
118
                stacklevel=2)
 
119
        return RevisionInfo(branch, revno=None, rev_id=revision_id)
118
120
 
119
121
 
120
122
class RevisionSpec(object):
137
139
    """
138
140
 
139
141
    prefix = None
140
 
    wants_revision_history = True
 
142
    # wants_revision_history has been deprecated in 2.5.
 
143
    wants_revision_history = False
141
144
    dwim_catchable_exceptions = (errors.InvalidRevisionSpec,)
142
145
    """Exceptions that RevisionSpec_dwim._match_on will catch.
143
146
 
208
211
    def in_history(self, branch):
209
212
        if branch:
210
213
            if self.wants_revision_history:
211
 
                revs = branch.revision_history()
 
214
                symbol_versioning.warn(
 
215
                    "RevisionSpec.wants_revision_history was "
 
216
                    "deprecated in 2.5 (%s)." % self.__class__.__name__,
 
217
                    DeprecationWarning)
 
218
                branch.lock_read()
 
219
                try:
 
220
                    graph = branch.repository.get_graph()
 
221
                    revs = list(graph.iter_lefthand_ancestry(
 
222
                        branch.last_revision(), [revision.NULL_REVISION]))
 
223
                finally:
 
224
                    branch.unlock()
 
225
                revs.reverse()
212
226
            else:
213
227
                revs = None
214
228
        else:
294
308
    """
295
309
 
296
310
    help_txt = None
297
 
    # We don't need to build the revision history ourself, that's delegated to
298
 
    # each revspec we try.
299
 
    wants_revision_history = False
300
311
 
301
312
    _revno_regex = lazy_regex.lazy_compile(r'^(?:(\d+(\.\d+)*)|-\d+)(:.*)?$')
302
313
 
380
391
                                   your history is very long.
381
392
    """
382
393
    prefix = 'revno:'
383
 
    wants_revision_history = False
384
394
 
385
395
    def _match_on(self, branch, revs):
386
396
        """Lookup a revision by revision number"""
387
 
        branch, revno, revision_id = self._lookup(branch, revs)
 
397
        branch, revno, revision_id = self._lookup(branch)
388
398
        return RevisionInfo(branch, revno, revision_id)
389
399
 
390
 
    def _lookup(self, branch, revs_or_none):
 
400
    def _lookup(self, branch):
391
401
        loc = self.spec.find(':')
392
402
        if loc == -1:
393
403
            revno_spec = self.spec
417
427
                dotted = True
418
428
 
419
429
        if branch_spec:
420
 
            # the user has override the branch to look in.
421
 
            # we need to refresh the revision_history map and
422
 
            # the branch object.
423
 
            from bzrlib.branch import Branch
424
 
            branch = Branch.open(branch_spec)
425
 
            revs_or_none = None
 
430
            # the user has overriden the branch to look in.
 
431
            branch = _mod_branch.Branch.open(branch_spec)
426
432
 
427
433
        if dotted:
428
434
            try:
432
438
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
433
439
            else:
434
440
                # there is no traditional 'revno' for dotted-decimal revnos.
435
 
                # so for  API compatability we return None.
 
441
                # so for API compatibility we return None.
436
442
                return branch, None, revision_id
437
443
        else:
438
444
            last_revno, last_revision_id = branch.last_revision_info()
444
450
                else:
445
451
                    revno = last_revno + revno + 1
446
452
            try:
447
 
                revision_id = branch.get_rev_id(revno, revs_or_none)
 
453
                revision_id = branch.get_rev_id(revno)
448
454
            except errors.NoSuchRevision:
449
455
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
450
456
        return branch, revno, revision_id
451
457
 
452
458
    def _as_revision_id(self, context_branch):
453
459
        # We would have the revno here, but we don't really care
454
 
        branch, revno, revision_id = self._lookup(context_branch, None)
 
460
        branch, revno, revision_id = self._lookup(context_branch)
455
461
        return revision_id
456
462
 
457
463
    def needs_branch(self):
467
473
RevisionSpec_int = RevisionSpec_revno
468
474
 
469
475
 
470
 
 
471
476
class RevisionIDSpec(RevisionSpec):
472
477
 
473
478
    def _match_on(self, branch, revs):
474
479
        revision_id = self.as_revision_id(branch)
475
 
        return RevisionInfo.from_revision_id(branch, revision_id, revs)
 
480
        return RevisionInfo.from_revision_id(branch, revision_id)
476
481
 
477
482
 
478
483
class RevisionSpec_revid(RevisionIDSpec):
514
519
    prefix = 'last:'
515
520
 
516
521
    def _match_on(self, branch, revs):
517
 
        revno, revision_id = self._revno_and_revision_id(branch, revs)
 
522
        revno, revision_id = self._revno_and_revision_id(branch)
518
523
        return RevisionInfo(branch, revno, revision_id)
519
524
 
520
 
    def _revno_and_revision_id(self, context_branch, revs_or_none):
 
525
    def _revno_and_revision_id(self, context_branch):
521
526
        last_revno, last_revision_id = context_branch.last_revision_info()
522
527
 
523
528
        if self.spec == '':
536
541
 
537
542
        revno = last_revno - offset + 1
538
543
        try:
539
 
            revision_id = context_branch.get_rev_id(revno, revs_or_none)
 
544
            revision_id = context_branch.get_rev_id(revno)
540
545
        except errors.NoSuchRevision:
541
546
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
542
547
        return revno, revision_id
544
549
    def _as_revision_id(self, context_branch):
545
550
        # We compute the revno as part of the process, but we don't really care
546
551
        # about it.
547
 
        revno, revision_id = self._revno_and_revision_id(context_branch, None)
 
552
        revno, revision_id = self._revno_and_revision_id(context_branch)
548
553
        return revision_id
549
554
 
550
555
 
582
587
            # We need to use the repository history here
583
588
            rev = branch.repository.get_revision(r.rev_id)
584
589
            if not rev.parent_ids:
585
 
                revno = 0
586
590
                revision_id = revision.NULL_REVISION
587
591
            else:
588
592
                revision_id = rev.parent_ids[0]
589
 
                try:
590
 
                    revno = revs.index(revision_id) + 1
591
 
                except ValueError:
592
 
                    revno = None
 
593
            revno = None
593
594
        else:
594
595
            revno = r.revno - 1
595
596
            try:
600
601
        return RevisionInfo(branch, revno, revision_id)
601
602
 
602
603
    def _as_revision_id(self, context_branch):
603
 
        base_revspec = RevisionSpec.from_string(self.spec)
604
 
        base_revision_id = base_revspec.as_revision_id(context_branch)
 
604
        base_revision_id = RevisionSpec.from_string(self.spec)._as_revision_id(context_branch)
605
605
        if base_revision_id == revision.NULL_REVISION:
606
606
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
607
607
                                         'cannot go before the null: revision')
637
637
    def _match_on(self, branch, revs):
638
638
        # Can raise tags not supported, NoSuchTag, etc
639
639
        return RevisionInfo.from_revision_id(branch,
640
 
            branch.tags.lookup_tag(self.spec),
641
 
            revs)
 
640
            branch.tags.lookup_tag(self.spec))
642
641
 
643
642
    def _as_revision_id(self, context_branch):
644
643
        return context_branch.tags.lookup_tag(self.spec)
648
647
class _RevListToTimestamps(object):
649
648
    """This takes a list of revisions, and allows you to bisect by date"""
650
649
 
651
 
    __slots__ = ['revs', 'branch']
 
650
    __slots__ = ['branch']
652
651
 
653
 
    def __init__(self, revs, branch):
654
 
        self.revs = revs
 
652
    def __init__(self, branch):
655
653
        self.branch = branch
656
654
 
657
655
    def __getitem__(self, index):
658
656
        """Get the date of the index'd item"""
659
 
        r = self.branch.repository.get_revision(self.revs[index])
 
657
        r = self.branch.repository.get_revision(self.branch.get_rev_id(index))
660
658
        # TODO: Handle timezone.
661
659
        return datetime.datetime.fromtimestamp(r.timestamp)
662
660
 
663
661
    def __len__(self):
664
 
        return len(self.revs)
 
662
        return self.branch.revno()
665
663
 
666
664
 
667
665
class RevisionSpec_date(RevisionSpec):
741
739
                    hour=hour, minute=minute, second=second)
742
740
        branch.lock_read()
743
741
        try:
744
 
            rev = bisect.bisect(_RevListToTimestamps(revs, branch), dt)
 
742
            rev = bisect.bisect(_RevListToTimestamps(branch), dt, 1)
745
743
        finally:
746
744
            branch.unlock()
747
 
        if rev == len(revs):
 
745
        if rev == branch.revno():
748
746
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
749
 
        else:
750
 
            return RevisionInfo(branch, rev + 1)
 
747
        return RevisionInfo(branch, rev)
751
748
 
752
749
 
753
750
 
784
781
    def _find_revision_info(branch, other_location):
785
782
        revision_id = RevisionSpec_ancestor._find_revision_id(branch,
786
783
                                                              other_location)
787
 
        try:
788
 
            revno = branch.revision_id_to_revno(revision_id)
789
 
        except errors.NoSuchRevision:
790
 
            revno = None
791
 
        return RevisionInfo(branch, revno, revision_id)
 
784
        return RevisionInfo(branch, None, revision_id)
792
785
 
793
786
    @staticmethod
794
787
    def _find_revision_id(branch, other_location):
848
841
                branch.fetch(other_branch, revision_b)
849
842
            except errors.ReadOnlyError:
850
843
                branch = other_branch
851
 
        try:
852
 
            revno = branch.revision_id_to_revno(revision_b)
853
 
        except errors.NoSuchRevision:
854
 
            revno = None
855
 
        return RevisionInfo(branch, revno, revision_b)
 
844
        return RevisionInfo(branch, None, revision_b)
856
845
 
857
846
    def _as_revision_id(self, context_branch):
858
847
        from bzrlib.branch import Branch
910
899
            location_type = 'parent branch'
911
900
        if submit_location is None:
912
901
            raise errors.NoSubmitBranch(branch)
913
 
        trace.note('Using %s %s', location_type, submit_location)
 
902
        trace.note(gettext('Using {0} {1}').format(location_type,
 
903
                                                        submit_location))
914
904
        return submit_location
915
905
 
916
906
    def _match_on(self, branch, revs):