/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 breezy/revisionspec.py

  • Committer: Jelmer Vernooij
  • Date: 2020-03-22 01:35:14 UTC
  • mfrom: (7490.7.6 work)
  • mto: This revision was merged to the branch mainline in revision 7499.
  • Revision ID: jelmer@jelmer.uk-20200322013514-7vw1ntwho04rcuj3
merge lp:brz/3.1.

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
 
from __future__ import absolute_import
18
 
 
19
17
 
20
18
from .lazy_import import lazy_import
21
19
lazy_import(globals(), """
25
23
from breezy import (
26
24
    branch as _mod_branch,
27
25
    cache_utf8,
28
 
    osutils,
29
26
    revision,
30
27
    workingtree,
31
28
    )
38
35
    registry,
39
36
    trace,
40
37
    )
41
 
from .sixish import (
42
 
    text_type,
43
 
    )
44
38
 
45
39
 
46
40
class RevisionInfo(object):
74
68
        if not self._has_revno and self.rev_id is not None:
75
69
            try:
76
70
                self._revno = self.branch.revision_id_to_revno(self.rev_id)
77
 
            except errors.NoSuchRevision:
 
71
            except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
78
72
                self._revno = None
79
73
            self._has_revno = True
80
74
        return self._revno
93
87
        return 2
94
88
 
95
89
    def __getitem__(self, index):
96
 
        if index == 0: return self.revno
97
 
        if index == 1: return self.rev_id
 
90
        if index == 0:
 
91
            return self.revno
 
92
        if index == 1:
 
93
            return self.rev_id
98
94
        raise IndexError(index)
99
95
 
100
96
    def get(self):
159
155
        """
160
156
        if spec is None:
161
157
            return RevisionSpec(None, _internal=True)
162
 
        if not isinstance(spec, (str, text_type)):
 
158
        if not isinstance(spec, str):
163
159
            raise TypeError("revision spec needs to be text")
164
160
        match = revspec_registry.get_prefix(spec)
165
161
        if match is not None:
255
251
    def __repr__(self):
256
252
        # this is mostly for helping with testing
257
253
        return '<%s %s>' % (self.__class__.__name__,
258
 
                              self.user_spec)
 
254
                            self.user_spec)
259
255
 
260
256
    def needs_branch(self):
261
257
        """Whether this revision spec needs a branch.
373
369
            branch_spec = None
374
370
        else:
375
371
            revno_spec = self.spec[:loc]
376
 
            branch_spec = self.spec[loc+1:]
 
372
            branch_spec = self.spec[loc + 1:]
377
373
 
378
374
        if revno_spec == '':
379
375
            if not branch_spec:
380
376
                raise errors.InvalidRevisionSpec(self.user_spec,
381
 
                        branch, 'cannot have an empty revno and no branch')
 
377
                                                 branch, 'cannot have an empty revno and no branch')
382
378
            revno = None
383
379
        else:
384
380
            try:
389
385
                # but the from_string method is a little primitive
390
386
                # right now - RBC 20060928
391
387
                try:
392
 
                    match_revno = tuple((int(number) for number in revno_spec.split('.')))
 
388
                    match_revno = tuple((int(number)
 
389
                                         for number in revno_spec.split('.')))
393
390
                except ValueError as e:
394
391
                    raise errors.InvalidRevisionSpec(self.user_spec, branch, e)
395
392
 
402
399
        if dotted:
403
400
            try:
404
401
                revision_id = branch.dotted_revno_to_revision_id(match_revno,
405
 
                    _cache_reverse=True)
406
 
            except errors.NoSuchRevision:
 
402
                                                                 _cache_reverse=True)
 
403
            except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
407
404
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
408
405
            else:
409
406
                # there is no traditional 'revno' for dotted-decimal revnos.
420
417
                    revno = last_revno + revno + 1
421
418
            try:
422
419
                revision_id = branch.get_rev_id(revno)
423
 
            except errors.NoSuchRevision:
 
420
            except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
424
421
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
425
422
        return branch, revno, revision_id
426
423
 
436
433
        if self.spec.find(':') == -1:
437
434
            return None
438
435
        else:
439
 
            return self.spec[self.spec.find(':')+1:]
 
436
            return self.spec[self.spec.find(':') + 1:]
 
437
 
440
438
 
441
439
# Old compatibility
442
440
RevisionSpec_int = RevisionSpec_revno
468
466
        # self.spec comes straight from parsing the command line arguments,
469
467
        # so we expect it to be a Unicode string. Switch it to the internal
470
468
        # representation.
471
 
        if isinstance(self.spec, unicode):
 
469
        if isinstance(self.spec, str):
472
470
            return cache_utf8.encode(self.spec)
473
471
        return self.spec
474
472
 
475
473
 
476
 
 
477
474
class RevisionSpec_last(RevisionSpec):
478
475
    """Selects the nth revision from the end."""
479
476
 
513
510
        revno = last_revno - offset + 1
514
511
        try:
515
512
            revision_id = context_branch.get_rev_id(revno)
516
 
        except errors.NoSuchRevision:
 
513
        except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
517
514
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
518
515
        return revno, revision_id
519
516
 
524
521
        return revision_id
525
522
 
526
523
 
527
 
 
528
524
class RevisionSpec_before(RevisionSpec):
529
525
    """Selects the parent of the revision specified."""
530
526
 
553
549
        r = RevisionSpec.from_string(self.spec)._match_on(branch, revs)
554
550
        if r.revno == 0:
555
551
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
556
 
                                         'cannot go before the null: revision')
 
552
                                             'cannot go before the null: revision')
557
553
        if r.revno is None:
558
554
            # We need to use the repository history here
559
555
            rev = branch.repository.get_revision(r.rev_id)
566
562
            revno = r.revno - 1
567
563
            try:
568
564
                revision_id = branch.get_rev_id(revno, revs)
569
 
            except errors.NoSuchRevision:
 
565
            except (errors.NoSuchRevision, errors.RevnoOutOfBounds):
570
566
                raise errors.InvalidRevisionSpec(self.user_spec,
571
567
                                                 branch)
572
568
        return RevisionInfo(branch, revno, revision_id)
573
569
 
574
570
    def _as_revision_id(self, context_branch):
575
 
        base_revision_id = RevisionSpec.from_string(self.spec)._as_revision_id(context_branch)
 
571
        base_revision_id = RevisionSpec.from_string(
 
572
            self.spec)._as_revision_id(context_branch)
576
573
        if base_revision_id == revision.NULL_REVISION:
577
574
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
578
 
                                         'cannot go before the null: revision')
 
575
                                             'cannot go before the null: revision')
579
576
        context_repo = context_branch.repository
580
 
        context_repo.lock_read()
581
 
        try:
 
577
        with context_repo.lock_read():
582
578
            parent_map = context_repo.get_parent_map([base_revision_id])
583
 
        finally:
584
 
            context_repo.unlock()
585
579
        if base_revision_id not in parent_map:
586
580
            # Ghost, or unknown revision id
587
581
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
588
 
                'cannot find the matching revision')
 
582
                                             'cannot find the matching revision')
589
583
        parents = parent_map[base_revision_id]
590
584
        if len(parents) < 1:
591
585
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
592
 
                'No parents for revision.')
 
586
                                             'No parents for revision.')
593
587
        return parents[0]
594
588
 
595
589
 
596
 
 
597
590
class RevisionSpec_tag(RevisionSpec):
598
591
    """Select a revision identified by tag name"""
599
592
 
608
601
    def _match_on(self, branch, revs):
609
602
        # Can raise tags not supported, NoSuchTag, etc
610
603
        return RevisionInfo.from_revision_id(branch,
611
 
            branch.tags.lookup_tag(self.spec))
 
604
                                             branch.tags.lookup_tag(self.spec))
612
605
 
613
606
    def _as_revision_id(self, context_branch):
614
607
        return context_branch.tags.lookup_tag(self.spec)
615
608
 
616
609
 
617
 
 
618
610
class _RevListToTimestamps(object):
619
611
    """This takes a list of revisions, and allows you to bisect by date"""
620
612
 
655
647
    """
656
648
    prefix = 'date:'
657
649
    _date_regex = lazy_regex.lazy_compile(
658
 
            r'(?P<date>(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d))?'
659
 
            r'(,|T)?\s*'
660
 
            r'(?P<time>(?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d))?)?'
 
650
        r'(?P<date>(?P<year>\d\d\d\d)-(?P<month>\d\d)-(?P<day>\d\d))?'
 
651
        r'(,|T)?\s*'
 
652
        r'(?P<time>(?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d))?)?'
661
653
        )
662
654
 
663
655
    def _match_on(self, branch, revs):
670
662
        #  XXX: This doesn't actually work
671
663
        #  So the proper way of saying 'give me all entries for today' is:
672
664
        #      -r date:yesterday..date:today
673
 
        today = datetime.datetime.fromordinal(datetime.date.today().toordinal())
 
665
        today = datetime.datetime.fromordinal(
 
666
            datetime.date.today().toordinal())
674
667
        if self.spec.lower() == 'yesterday':
675
668
            dt = today - datetime.timedelta(days=1)
676
669
        elif self.spec.lower() == 'today':
707
700
                                                 branch, 'invalid date')
708
701
 
709
702
            dt = datetime.datetime(year=year, month=month, day=day,
710
 
                    hour=hour, minute=minute, second=second)
 
703
                                   hour=hour, minute=minute, second=second)
711
704
        with branch.lock_read():
712
705
            rev = bisect.bisect(_RevListToTimestamps(branch), dt, 1)
713
706
        if rev == branch.revno():
715
708
        return RevisionInfo(branch, rev)
716
709
 
717
710
 
718
 
 
719
711
class RevisionSpec_ancestor(RevisionSpec):
720
712
    """Selects a common ancestor with a second branch."""
721
713
 
829
821
        return self.spec
830
822
 
831
823
 
832
 
 
833
824
class RevisionSpec_submit(RevisionSpec_ancestor):
834
825
    """Selects a common ancestor with a submit branch."""
835
826
 
860
851
        if submit_location is None:
861
852
            raise errors.NoSubmitBranch(branch)
862
853
        trace.note(gettext('Using {0} {1}').format(location_type,
863
 
                                                        submit_location))
 
854
                                                   submit_location))
864
855
        return submit_location
865
856
 
866
857
    def _match_on(self, branch, revs):
867
858
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
868
859
        return self._find_revision_info(branch,
869
 
            self._get_submit_location(branch))
 
860
                                        self._get_submit_location(branch))
870
861
 
871
862
    def _as_revision_id(self, context_branch):
872
863
        return self._find_revision_id(context_branch,
873
 
            self._get_submit_location(context_branch))
 
864
                                      self._get_submit_location(context_branch))
874
865
 
875
866
 
876
867
class RevisionSpec_annotate(RevisionIDSpec):
887
878
 
888
879
    def _raise_invalid(self, numstring, context_branch):
889
880
        raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
890
 
            'No such line: %s' % numstring)
 
881
                                         'No such line: %s' % numstring)
891
882
 
892
883
    def _as_revision_id(self, context_branch):
893
884
        path, numstring = self.spec.rsplit(':', 1)
899
890
        with tree.lock_read():
900
891
            if not tree.has_filename(file_path):
901
892
                raise errors.InvalidRevisionSpec(self.user_spec,
902
 
                    context_branch, "File '%s' is not versioned." %
903
 
                    file_path)
 
893
                                                 context_branch, "File '%s' is not versioned." %
 
894
                                                 file_path)
904
895
            revision_ids = [r for (r, l) in tree.annotate_iter(file_path)]
905
896
        try:
906
897
            revision_id = revision_ids[index]
908
899
            self._raise_invalid(numstring, context_branch)
909
900
        if revision_id == revision.CURRENT_REVISION:
910
901
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
911
 
                'Line %s has not been committed.' % numstring)
 
902
                                             'Line %s has not been committed.' % numstring)
912
903
        return revision_id
913
904
 
914
905
 
945
936
RevisionSpec_dwim.append_possible_revspec(RevisionSpec_branch)
946
937
 
947
938
revspec_registry = registry.Registry()
 
939
 
 
940
 
948
941
def _register_revspec(revspec):
949
942
    revspec_registry.register(revspec.prefix, revspec)
950
943
 
 
944
 
951
945
_register_revspec(RevisionSpec_revno)
952
946
_register_revspec(RevisionSpec_revid)
953
947
_register_revspec(RevisionSpec_last)