/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/revisionspec.py

  • Committer: Richard Wilbur
  • Date: 2016-02-04 19:07:28 UTC
  • mto: This revision was merged to the branch mainline in revision 6618.
  • Revision ID: richard.wilbur@gmail.com-20160204190728-p0zvfii6zase0fw7
Update COPYING.txt from the original http://www.gnu.org/licenses/gpl-2.0.txt  (Only differences were in whitespace.)  Thanks to Petr Stodulka for pointing out the discrepancy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
 
18
 
from .lazy_import import lazy_import
 
17
from __future__ import absolute_import
 
18
 
 
19
 
 
20
from bzrlib.lazy_import import lazy_import
19
21
lazy_import(globals(), """
20
22
import bisect
21
23
import datetime
22
24
 
23
 
from breezy import (
 
25
from bzrlib import (
24
26
    branch as _mod_branch,
25
 
    cache_utf8,
 
27
    osutils,
26
28
    revision,
 
29
    symbol_versioning,
27
30
    workingtree,
28
31
    )
29
 
from breezy.i18n import gettext
 
32
from bzrlib.i18n import gettext
30
33
""")
31
34
 
32
 
from . import (
 
35
from bzrlib import (
33
36
    errors,
34
37
    lazy_regex,
35
38
    registry,
37
40
    )
38
41
 
39
42
 
40
 
class InvalidRevisionSpec(errors.BzrError):
41
 
 
42
 
    _fmt = ("Requested revision: '%(spec)s' does not exist in branch:"
43
 
            " %(branch_url)s%(extra)s")
44
 
 
45
 
    def __init__(self, spec, branch, extra=None):
46
 
        errors.BzrError.__init__(self, branch=branch, spec=spec)
47
 
        self.branch_url = getattr(branch, 'user_url', str(branch))
48
 
        if extra:
49
 
            self.extra = '\n' + str(extra)
50
 
        else:
51
 
            self.extra = ''
52
 
 
53
 
 
54
 
class InvalidRevisionSpec(errors.BzrError):
55
 
 
56
 
    _fmt = ("Requested revision: '%(spec)s' does not exist in branch:"
57
 
            " %(branch_url)s%(extra)s")
58
 
 
59
 
    def __init__(self, spec, branch, extra=None):
60
 
        errors.BzrError.__init__(self, branch=branch, spec=spec)
61
 
        self.branch_url = getattr(branch, 'user_url', str(branch))
62
 
        if extra:
63
 
            self.extra = '\n' + str(extra)
64
 
        else:
65
 
            self.extra = ''
66
 
 
67
 
 
68
43
class RevisionInfo(object):
69
44
    """The results of applying a revision specification to a branch."""
70
45
 
96
71
        if not self._has_revno and self.rev_id is not None:
97
72
            try:
98
73
                self._revno = self.branch.revision_id_to_revno(self.rev_id)
99
 
            except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
 
74
            except errors.NoSuchRevision:
100
75
                self._revno = None
101
76
            self._has_revno = True
102
77
        return self._revno
103
78
 
104
 
    def __bool__(self):
 
79
    def __nonzero__(self):
105
80
        if self.rev_id is None:
106
81
            return False
107
82
        # TODO: otherwise, it should depend on how I was built -
109
84
        # if it's in_store(branch), do the check below
110
85
        return self.branch.repository.has_revision(self.rev_id)
111
86
 
112
 
    __nonzero__ = __bool__
113
 
 
114
87
    def __len__(self):
115
88
        return 2
116
89
 
117
90
    def __getitem__(self, index):
118
 
        if index == 0:
119
 
            return self.revno
120
 
        if index == 1:
121
 
            return self.rev_id
 
91
        if index == 0: return self.revno
 
92
        if index == 1: return self.rev_id
122
93
        raise IndexError(index)
123
94
 
124
95
    def get(self):
127
98
    def __eq__(self, other):
128
99
        if type(other) not in (tuple, list, type(self)):
129
100
            return False
130
 
        if isinstance(other, type(self)) and self.branch is not other.branch:
 
101
        if type(other) is type(self) and self.branch is not other.branch:
131
102
            return False
132
103
        return tuple(self) == tuple(other)
133
104
 
134
105
    def __repr__(self):
135
 
        return '<breezy.revisionspec.RevisionInfo object %s, %s for %r>' % (
 
106
        return '<bzrlib.revisionspec.RevisionInfo object %s, %s for %r>' % (
136
107
            self.revno, self.rev_id, self.branch)
137
108
 
138
109
    @staticmethod
139
 
    def from_revision_id(branch, revision_id):
 
110
    def from_revision_id(branch, revision_id, revs=symbol_versioning.DEPRECATED_PARAMETER):
140
111
        """Construct a RevisionInfo given just the id.
141
112
 
142
113
        Use this if you don't know or care what the revno is.
143
114
        """
 
115
        if symbol_versioning.deprecated_passed(revs):
 
116
            symbol_versioning.warn(
 
117
                'RevisionInfo.from_revision_id(revs) was deprecated in 2.5.',
 
118
                DeprecationWarning,
 
119
                stacklevel=2)
144
120
        return RevisionInfo(branch, revno=None, rev_id=revision_id)
145
121
 
146
122
 
164
140
    """
165
141
 
166
142
    prefix = None
167
 
    dwim_catchable_exceptions = (InvalidRevisionSpec,)
 
143
    # wants_revision_history has been deprecated in 2.5.
 
144
    wants_revision_history = False
 
145
    dwim_catchable_exceptions = (errors.InvalidRevisionSpec,)
168
146
    """Exceptions that RevisionSpec_dwim._match_on will catch.
169
147
 
170
148
    If the revspec is part of ``dwim_revspecs``, it may be tried with an
181
159
        :return: A RevisionSpec object that understands how to parse the
182
160
            supplied notation.
183
161
        """
 
162
        if not isinstance(spec, (type(None), basestring)):
 
163
            raise TypeError('error')
 
164
 
184
165
        if spec is None:
185
166
            return RevisionSpec(None, _internal=True)
186
 
        if not isinstance(spec, str):
187
 
            raise TypeError("revision spec needs to be text")
188
167
        match = revspec_registry.get_prefix(spec)
189
168
        if match is not None:
190
169
            spectype, specsuffix = match
204
183
            called directly. Only from RevisionSpec.from_string()
205
184
        """
206
185
        if not _internal:
207
 
            raise AssertionError(
208
 
                'Creating a RevisionSpec directly is not supported. '
209
 
                'Use RevisionSpec.from_string() instead.')
 
186
            symbol_versioning.warn('Creating a RevisionSpec directly has'
 
187
                                   ' been deprecated in version 0.11. Use'
 
188
                                   ' RevisionSpec.from_string()'
 
189
                                   ' instead.',
 
190
                                   DeprecationWarning, stacklevel=2)
210
191
        self.user_spec = spec
211
192
        if self.prefix and spec.startswith(self.prefix):
212
193
            spec = spec[len(self.prefix):]
224
205
            # special case - nothing supplied
225
206
            return info
226
207
        elif self.prefix:
227
 
            raise InvalidRevisionSpec(self.user_spec, branch)
 
208
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
228
209
        else:
229
 
            raise InvalidRevisionSpec(self.spec, branch)
 
210
            raise errors.InvalidRevisionSpec(self.spec, branch)
230
211
 
231
212
    def in_history(self, branch):
232
 
        return self._match_on_and_check(branch, revs=None)
 
213
        if branch:
 
214
            if self.wants_revision_history:
 
215
                symbol_versioning.warn(
 
216
                    "RevisionSpec.wants_revision_history was "
 
217
                    "deprecated in 2.5 (%s)." % self.__class__.__name__,
 
218
                    DeprecationWarning)
 
219
                branch.lock_read()
 
220
                try:
 
221
                    graph = branch.repository.get_graph()
 
222
                    revs = list(graph.iter_lefthand_ancestry(
 
223
                        branch.last_revision(), [revision.NULL_REVISION]))
 
224
                finally:
 
225
                    branch.unlock()
 
226
                revs.reverse()
 
227
            else:
 
228
                revs = None
 
229
        else:
 
230
            # this should never trigger.
 
231
            # TODO: make it a deprecated code path. RBC 20060928
 
232
            revs = None
 
233
        return self._match_on_and_check(branch, revs)
233
234
 
234
235
        # FIXME: in_history is somewhat broken,
235
236
        # it will return non-history revisions in many
279
280
    def __repr__(self):
280
281
        # this is mostly for helping with testing
281
282
        return '<%s %s>' % (self.__class__.__name__,
282
 
                            self.user_spec)
 
283
                              self.user_spec)
283
284
 
284
285
    def needs_branch(self):
285
286
        """Whether this revision spec needs a branch.
338
339
            except rs_class.dwim_catchable_exceptions:
339
340
                pass
340
341
 
 
342
        # Try the old (deprecated) dwim list:
 
343
        for rs_class in dwim_revspecs:
 
344
            try:
 
345
                return self._try_spectype(rs_class, branch)
 
346
            except rs_class.dwim_catchable_exceptions:
 
347
                pass
 
348
 
341
349
        # Well, I dunno what it is. Note that we don't try to keep track of the
342
350
        # first of last exception raised during the DWIM tries as none seems
343
351
        # really relevant.
344
 
        raise InvalidRevisionSpec(self.spec, branch)
 
352
        raise errors.InvalidRevisionSpec(self.spec, branch)
345
353
 
346
354
    @classmethod
347
355
    def append_possible_revspec(cls, revspec):
397
405
            branch_spec = None
398
406
        else:
399
407
            revno_spec = self.spec[:loc]
400
 
            branch_spec = self.spec[loc + 1:]
 
408
            branch_spec = self.spec[loc+1:]
401
409
 
402
410
        if revno_spec == '':
403
411
            if not branch_spec:
404
 
                raise InvalidRevisionSpec(
405
 
                    self.user_spec, branch,
406
 
                    'cannot have an empty revno and no branch')
 
412
                raise errors.InvalidRevisionSpec(self.user_spec,
 
413
                        branch, 'cannot have an empty revno and no branch')
407
414
            revno = None
408
415
        else:
409
416
            try:
414
421
                # but the from_string method is a little primitive
415
422
                # right now - RBC 20060928
416
423
                try:
417
 
                    match_revno = tuple((int(number)
418
 
                                         for number in revno_spec.split('.')))
419
 
                except ValueError as e:
420
 
                    raise InvalidRevisionSpec(self.user_spec, branch, e)
 
424
                    match_revno = tuple((int(number) for number in revno_spec.split('.')))
 
425
                except ValueError, e:
 
426
                    raise errors.InvalidRevisionSpec(self.user_spec, branch, e)
421
427
 
422
428
                dotted = True
423
429
 
428
434
        if dotted:
429
435
            try:
430
436
                revision_id = branch.dotted_revno_to_revision_id(match_revno,
431
 
                                                                 _cache_reverse=True)
432
 
            except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
433
 
                raise InvalidRevisionSpec(self.user_spec, branch)
 
437
                    _cache_reverse=True)
 
438
            except errors.NoSuchRevision:
 
439
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
434
440
            else:
435
441
                # there is no traditional 'revno' for dotted-decimal revnos.
436
442
                # so for API compatibility we return None.
446
452
                    revno = last_revno + revno + 1
447
453
            try:
448
454
                revision_id = branch.get_rev_id(revno)
449
 
            except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
450
 
                raise InvalidRevisionSpec(self.user_spec, branch)
 
455
            except errors.NoSuchRevision:
 
456
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
451
457
        return branch, revno, revision_id
452
458
 
453
459
    def _as_revision_id(self, context_branch):
462
468
        if self.spec.find(':') == -1:
463
469
            return None
464
470
        else:
465
 
            return self.spec[self.spec.find(':') + 1:]
466
 
 
 
471
            return self.spec[self.spec.find(':')+1:]
467
472
 
468
473
# Old compatibility
469
474
RevisionSpec_int = RevisionSpec_revno
495
500
        # self.spec comes straight from parsing the command line arguments,
496
501
        # so we expect it to be a Unicode string. Switch it to the internal
497
502
        # representation.
498
 
        if isinstance(self.spec, str):
499
 
            return cache_utf8.encode(self.spec)
500
 
        return self.spec
 
503
        return osutils.safe_revision_id(self.spec, warn=False)
 
504
 
501
505
 
502
506
 
503
507
class RevisionSpec_last(RevisionSpec):
529
533
 
530
534
        try:
531
535
            offset = int(self.spec)
532
 
        except ValueError as e:
533
 
            raise InvalidRevisionSpec(self.user_spec, context_branch, e)
 
536
        except ValueError, e:
 
537
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch, e)
534
538
 
535
539
        if offset <= 0:
536
 
            raise InvalidRevisionSpec(
537
 
                self.user_spec, context_branch,
538
 
                'you must supply a positive value')
 
540
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
541
                                             'you must supply a positive value')
539
542
 
540
543
        revno = last_revno - offset + 1
541
544
        try:
542
545
            revision_id = context_branch.get_rev_id(revno)
543
 
        except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
544
 
            raise InvalidRevisionSpec(self.user_spec, context_branch)
 
546
        except errors.NoSuchRevision:
 
547
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
545
548
        return revno, revision_id
546
549
 
547
550
    def _as_revision_id(self, context_branch):
551
554
        return revision_id
552
555
 
553
556
 
 
557
 
554
558
class RevisionSpec_before(RevisionSpec):
555
559
    """Selects the parent of the revision specified."""
556
560
 
578
582
    def _match_on(self, branch, revs):
579
583
        r = RevisionSpec.from_string(self.spec)._match_on(branch, revs)
580
584
        if r.revno == 0:
581
 
            raise InvalidRevisionSpec(
582
 
                self.user_spec, branch,
583
 
                'cannot go before the null: revision')
 
585
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
 
586
                                         'cannot go before the null: revision')
584
587
        if r.revno is None:
585
588
            # We need to use the repository history here
586
589
            rev = branch.repository.get_revision(r.rev_id)
593
596
            revno = r.revno - 1
594
597
            try:
595
598
                revision_id = branch.get_rev_id(revno, revs)
596
 
            except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
597
 
                raise InvalidRevisionSpec(self.user_spec, branch)
 
599
            except errors.NoSuchRevision:
 
600
                raise errors.InvalidRevisionSpec(self.user_spec,
 
601
                                                 branch)
598
602
        return RevisionInfo(branch, revno, revision_id)
599
603
 
600
604
    def _as_revision_id(self, context_branch):
601
 
        base_revision_id = RevisionSpec.from_string(
602
 
            self.spec)._as_revision_id(context_branch)
 
605
        base_revision_id = RevisionSpec.from_string(self.spec)._as_revision_id(context_branch)
603
606
        if base_revision_id == revision.NULL_REVISION:
604
 
            raise InvalidRevisionSpec(
605
 
                self.user_spec, context_branch,
606
 
                'cannot go before the null: revision')
 
607
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
608
                                         'cannot go before the null: revision')
607
609
        context_repo = context_branch.repository
608
 
        with context_repo.lock_read():
 
610
        context_repo.lock_read()
 
611
        try:
609
612
            parent_map = context_repo.get_parent_map([base_revision_id])
 
613
        finally:
 
614
            context_repo.unlock()
610
615
        if base_revision_id not in parent_map:
611
616
            # Ghost, or unknown revision id
612
 
            raise InvalidRevisionSpec(
613
 
                self.user_spec, context_branch, 'cannot find the matching revision')
 
617
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
618
                'cannot find the matching revision')
614
619
        parents = parent_map[base_revision_id]
615
620
        if len(parents) < 1:
616
 
            raise InvalidRevisionSpec(
617
 
                self.user_spec, context_branch, 'No parents for revision.')
 
621
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
622
                'No parents for revision.')
618
623
        return parents[0]
619
624
 
620
625
 
 
626
 
621
627
class RevisionSpec_tag(RevisionSpec):
622
628
    """Select a revision identified by tag name"""
623
629
 
632
638
    def _match_on(self, branch, revs):
633
639
        # Can raise tags not supported, NoSuchTag, etc
634
640
        return RevisionInfo.from_revision_id(branch,
635
 
                                             branch.tags.lookup_tag(self.spec))
 
641
            branch.tags.lookup_tag(self.spec))
636
642
 
637
643
    def _as_revision_id(self, context_branch):
638
644
        return context_branch.tags.lookup_tag(self.spec)
639
645
 
640
646
 
 
647
 
641
648
class _RevListToTimestamps(object):
642
649
    """This takes a list of revisions, and allows you to bisect by date"""
643
650
 
668
675
 
669
676
    One way to display all the changes since yesterday would be::
670
677
 
671
 
        brz log -r date:yesterday..
 
678
        bzr log -r date:yesterday..
672
679
 
673
680
    Examples::
674
681
 
678
685
    """
679
686
    prefix = 'date:'
680
687
    _date_regex = lazy_regex.lazy_compile(
681
 
        r'(?P<date>(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d))?'
682
 
        r'(,|T)?\s*'
683
 
        r'(?P<time>(?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d))?)?'
 
688
            r'(?P<date>(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d))?'
 
689
            r'(,|T)?\s*'
 
690
            r'(?P<time>(?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d))?)?'
684
691
        )
685
692
 
686
693
    def _match_on(self, branch, revs):
693
700
        #  XXX: This doesn't actually work
694
701
        #  So the proper way of saying 'give me all entries for today' is:
695
702
        #      -r date:yesterday..date:today
696
 
        today = datetime.datetime.fromordinal(
697
 
            datetime.date.today().toordinal())
 
703
        today = datetime.datetime.fromordinal(datetime.date.today().toordinal())
698
704
        if self.spec.lower() == 'yesterday':
699
705
            dt = today - datetime.timedelta(days=1)
700
706
        elif self.spec.lower() == 'today':
704
710
        else:
705
711
            m = self._date_regex.match(self.spec)
706
712
            if not m or (not m.group('date') and not m.group('time')):
707
 
                raise InvalidRevisionSpec(
708
 
                    self.user_spec, branch, 'invalid date')
 
713
                raise errors.InvalidRevisionSpec(self.user_spec,
 
714
                                                 branch, 'invalid date')
709
715
 
710
716
            try:
711
717
                if m.group('date'):
725
731
                    else:
726
732
                        second = 0
727
733
                else:
728
 
                    hour, minute, second = 0, 0, 0
 
734
                    hour, minute, second = 0,0,0
729
735
            except ValueError:
730
 
                raise InvalidRevisionSpec(
731
 
                    self.user_spec, branch, 'invalid date')
 
736
                raise errors.InvalidRevisionSpec(self.user_spec,
 
737
                                                 branch, 'invalid date')
732
738
 
733
739
            dt = datetime.datetime(year=year, month=month, day=day,
734
 
                                   hour=hour, minute=minute, second=second)
735
 
        with branch.lock_read():
 
740
                    hour=hour, minute=minute, second=second)
 
741
        branch.lock_read()
 
742
        try:
736
743
            rev = bisect.bisect(_RevListToTimestamps(branch), dt, 1)
 
744
        finally:
 
745
            branch.unlock()
737
746
        if rev == branch.revno():
738
 
            raise InvalidRevisionSpec(self.user_spec, branch)
 
747
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
739
748
        return RevisionInfo(branch, rev)
740
749
 
741
750
 
 
751
 
742
752
class RevisionSpec_ancestor(RevisionSpec):
743
753
    """Selects a common ancestor with a second branch."""
744
754
 
776
786
 
777
787
    @staticmethod
778
788
    def _find_revision_id(branch, other_location):
779
 
        from .branch import Branch
 
789
        from bzrlib.branch import Branch
780
790
 
781
 
        with branch.lock_read():
 
791
        branch.lock_read()
 
792
        try:
782
793
            revision_a = revision.ensure_null(branch.last_revision())
783
794
            if revision_a == revision.NULL_REVISION:
784
795
                raise errors.NoCommits(branch)
785
796
            if other_location == '':
786
797
                other_location = branch.get_parent()
787
798
            other_branch = Branch.open(other_location)
788
 
            with other_branch.lock_read():
 
799
            other_branch.lock_read()
 
800
            try:
789
801
                revision_b = revision.ensure_null(other_branch.last_revision())
790
802
                if revision_b == revision.NULL_REVISION:
791
803
                    raise errors.NoCommits(other_branch)
792
804
                graph = branch.repository.get_graph(other_branch.repository)
793
805
                rev_id = graph.find_unique_lca(revision_a, revision_b)
 
806
            finally:
 
807
                other_branch.unlock()
794
808
            if rev_id == revision.NULL_REVISION:
795
809
                raise errors.NoCommonAncestor(revision_a, revision_b)
796
810
            return rev_id
 
811
        finally:
 
812
            branch.unlock()
 
813
 
 
814
 
797
815
 
798
816
 
799
817
class RevisionSpec_branch(RevisionSpec):
811
829
    dwim_catchable_exceptions = (errors.NotBranchError,)
812
830
 
813
831
    def _match_on(self, branch, revs):
814
 
        from .branch import Branch
 
832
        from bzrlib.branch import Branch
815
833
        other_branch = Branch.open(self.spec)
816
834
        revision_b = other_branch.last_revision()
817
835
        if revision_b in (None, revision.NULL_REVISION):
827
845
        return RevisionInfo(branch, None, revision_b)
828
846
 
829
847
    def _as_revision_id(self, context_branch):
830
 
        from .branch import Branch
 
848
        from bzrlib.branch import Branch
831
849
        other_branch = Branch.open(self.spec)
832
850
        last_revision = other_branch.last_revision()
833
851
        last_revision = revision.ensure_null(last_revision)
837
855
        return last_revision
838
856
 
839
857
    def _as_tree(self, context_branch):
840
 
        from .branch import Branch
 
858
        from bzrlib.branch import Branch
841
859
        other_branch = Branch.open(self.spec)
842
860
        last_revision = other_branch.last_revision()
843
861
        last_revision = revision.ensure_null(last_revision)
852
870
        return self.spec
853
871
 
854
872
 
 
873
 
855
874
class RevisionSpec_submit(RevisionSpec_ancestor):
856
875
    """Selects a common ancestor with a submit branch."""
857
876
 
882
901
        if submit_location is None:
883
902
            raise errors.NoSubmitBranch(branch)
884
903
        trace.note(gettext('Using {0} {1}').format(location_type,
885
 
                                                   submit_location))
 
904
                                                        submit_location))
886
905
        return submit_location
887
906
 
888
907
    def _match_on(self, branch, revs):
889
908
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
890
909
        return self._find_revision_info(branch,
891
 
                                        self._get_submit_location(branch))
 
910
            self._get_submit_location(branch))
892
911
 
893
912
    def _as_revision_id(self, context_branch):
894
913
        return self._find_revision_id(context_branch,
895
 
                                      self._get_submit_location(context_branch))
 
914
            self._get_submit_location(context_branch))
896
915
 
897
916
 
898
917
class RevisionSpec_annotate(RevisionIDSpec):
908
927
    """
909
928
 
910
929
    def _raise_invalid(self, numstring, context_branch):
911
 
        raise InvalidRevisionSpec(
912
 
            self.user_spec, context_branch,
 
930
        raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
913
931
            'No such line: %s' % numstring)
914
932
 
915
933
    def _as_revision_id(self, context_branch):
919
937
        except ValueError:
920
938
            self._raise_invalid(numstring, context_branch)
921
939
        tree, file_path = workingtree.WorkingTree.open_containing(path)
922
 
        with tree.lock_read():
923
 
            if not tree.has_filename(file_path):
924
 
                raise InvalidRevisionSpec(
925
 
                    self.user_spec, context_branch,
926
 
                    "File '%s' is not versioned." % file_path)
927
 
            revision_ids = [r for (r, l) in tree.annotate_iter(file_path)]
 
940
        tree.lock_read()
 
941
        try:
 
942
            file_id = tree.path2id(file_path)
 
943
            if file_id is None:
 
944
                raise errors.InvalidRevisionSpec(self.user_spec,
 
945
                    context_branch, "File '%s' is not versioned." %
 
946
                    file_path)
 
947
            revision_ids = [r for (r, l) in tree.annotate_iter(file_id)]
 
948
        finally:
 
949
            tree.unlock()
928
950
        try:
929
951
            revision_id = revision_ids[index]
930
952
        except IndexError:
931
953
            self._raise_invalid(numstring, context_branch)
932
954
        if revision_id == revision.CURRENT_REVISION:
933
 
            raise InvalidRevisionSpec(
934
 
                self.user_spec, context_branch,
 
955
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
935
956
                'Line %s has not been committed.' % numstring)
936
957
        return revision_id
937
958
 
956
977
        result = graph.find_lefthand_merger(revision_id,
957
978
                                            context_branch.last_revision())
958
979
        if result is None:
959
 
            raise InvalidRevisionSpec(self.user_spec, context_branch)
 
980
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
960
981
        return result
961
982
 
962
983
 
963
984
# The order in which we want to DWIM a revision spec without any prefix.
964
985
# revno is always tried first and isn't listed here, this is used by
965
986
# RevisionSpec_dwim._match_on
 
987
dwim_revspecs = symbol_versioning.deprecated_list(
 
988
    symbol_versioning.deprecated_in((2, 4, 0)), "dwim_revspecs", [])
 
989
 
966
990
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_tag)
967
991
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_revid)
968
992
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_date)
969
993
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_branch)
970
994
 
971
995
revspec_registry = registry.Registry()
972
 
 
973
 
 
974
996
def _register_revspec(revspec):
975
997
    revspec_registry.register(revspec.prefix, revspec)
976
998
 
977
 
 
978
999
_register_revspec(RevisionSpec_revno)
979
1000
_register_revspec(RevisionSpec_revid)
980
1001
_register_revspec(RevisionSpec_last)