~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/revisionspec.py

  • Committer: Jelmer Vernooij
  • Date: 2011-02-20 00:53:24 UTC
  • mto: This revision was merged to the branch mainline in revision 5673.
  • Revision ID: jelmer@samba.org-20110220005324-xnb1ifis5bfkrl51
Lazy load gzip (we don't use it when doing 2a), remove some unused imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
lazy_import(globals(), """
22
22
import bisect
23
23
import datetime
 
24
 
 
25
from bzrlib import (
 
26
    workingtree,
 
27
    )
24
28
""")
25
29
 
26
30
from bzrlib import (
 
31
    branch as _mod_branch,
27
32
    errors,
28
33
    osutils,
29
34
    registry,
30
35
    revision,
31
36
    symbol_versioning,
32
37
    trace,
 
38
    workingtree,
33
39
    )
34
40
 
35
41
 
444
450
 
445
451
 
446
452
 
447
 
class RevisionSpec_revid(RevisionSpec):
 
453
class RevisionIDSpec(RevisionSpec):
 
454
 
 
455
    def _match_on(self, branch, revs):
 
456
        revision_id = self.as_revision_id(branch)
 
457
        return RevisionInfo.from_revision_id(branch, revision_id, revs)
 
458
 
 
459
 
 
460
class RevisionSpec_revid(RevisionIDSpec):
448
461
    """Selects a revision using the revision id."""
449
462
 
450
463
    help_txt = """Selects a revision using the revision id.
459
472
 
460
473
    prefix = 'revid:'
461
474
 
462
 
    def _match_on(self, branch, revs):
 
475
    def _as_revision_id(self, context_branch):
463
476
        # self.spec comes straight from parsing the command line arguments,
464
477
        # so we expect it to be a Unicode string. Switch it to the internal
465
478
        # representation.
466
 
        revision_id = osutils.safe_revision_id(self.spec, warn=False)
467
 
        return RevisionInfo.from_revision_id(branch, revision_id, revs)
468
 
 
469
 
    def _as_revision_id(self, context_branch):
470
479
        return osutils.safe_revision_id(self.spec, warn=False)
471
480
 
472
481
 
813
822
        revision_b = other_branch.last_revision()
814
823
        if revision_b in (None, revision.NULL_REVISION):
815
824
            raise errors.NoCommits(other_branch)
816
 
        # pull in the remote revisions so we can diff
817
 
        branch.fetch(other_branch, revision_b)
 
825
        if branch is None:
 
826
            branch = other_branch
 
827
        else:
 
828
            try:
 
829
                # pull in the remote revisions so we can diff
 
830
                branch.fetch(other_branch, revision_b)
 
831
            except errors.ReadOnlyError:
 
832
                branch = other_branch
818
833
        try:
819
834
            revno = branch.revision_id_to_revno(revision_b)
820
835
        except errors.NoSuchRevision:
840
855
            raise errors.NoCommits(other_branch)
841
856
        return other_branch.repository.revision_tree(last_revision)
842
857
 
 
858
    def needs_branch(self):
 
859
        return False
 
860
 
 
861
    def get_branch(self):
 
862
        return self.spec
 
863
 
843
864
 
844
865
 
845
866
class RevisionSpec_submit(RevisionSpec_ancestor):
884
905
            self._get_submit_location(context_branch))
885
906
 
886
907
 
 
908
class RevisionSpec_annotate(RevisionIDSpec):
 
909
 
 
910
    prefix = 'annotate:'
 
911
 
 
912
    help_txt = """Select the revision that last modified the specified line.
 
913
 
 
914
    Select the revision that last modified the specified line.  Line is
 
915
    specified as path:number.  Path is a relative path to the file.  Numbers
 
916
    start at 1, and are relative to the current version, not the last-
 
917
    committed version of the file.
 
918
    """
 
919
 
 
920
    def _raise_invalid(self, numstring, context_branch):
 
921
        raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
922
            'No such line: %s' % numstring)
 
923
 
 
924
    def _as_revision_id(self, context_branch):
 
925
        path, numstring = self.spec.rsplit(':', 1)
 
926
        try:
 
927
            index = int(numstring) - 1
 
928
        except ValueError:
 
929
            self._raise_invalid(numstring, context_branch)
 
930
        tree, file_path = workingtree.WorkingTree.open_containing(path)
 
931
        tree.lock_read()
 
932
        try:
 
933
            file_id = tree.path2id(file_path)
 
934
            if file_id is None:
 
935
                raise errors.InvalidRevisionSpec(self.user_spec,
 
936
                    context_branch, "File '%s' is not versioned." %
 
937
                    file_path)
 
938
            revision_ids = [r for (r, l) in tree.annotate_iter(file_id)]
 
939
        finally:
 
940
            tree.unlock()
 
941
        try:
 
942
            revision_id = revision_ids[index]
 
943
        except IndexError:
 
944
            self._raise_invalid(numstring, context_branch)
 
945
        if revision_id == revision.CURRENT_REVISION:
 
946
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
947
                'Line %s has not been committed.' % numstring)
 
948
        return revision_id
 
949
 
 
950
 
 
951
class RevisionSpec_mainline(RevisionIDSpec):
 
952
 
 
953
    help_txt = """Select mainline revision that merged the specified revision.
 
954
 
 
955
    Select the revision that merged the specified revision into mainline.
 
956
    """
 
957
 
 
958
    prefix = 'mainline:'
 
959
 
 
960
    def _as_revision_id(self, context_branch):
 
961
        revspec = RevisionSpec.from_string(self.spec)
 
962
        if revspec.get_branch() is None:
 
963
            spec_branch = context_branch
 
964
        else:
 
965
            spec_branch = _mod_branch.Branch.open(revspec.get_branch())
 
966
        revision_id = revspec.as_revision_id(spec_branch)
 
967
        graph = context_branch.repository.get_graph()
 
968
        result = graph.find_lefthand_merger(revision_id,
 
969
                                            context_branch.last_revision())
 
970
        if result is None:
 
971
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
 
972
        return result
 
973
 
 
974
 
887
975
# The order in which we want to DWIM a revision spec without any prefix.
888
976
# revno is always tried first and isn't listed here, this is used by
889
977
# RevisionSpec_dwim._match_on
908
996
_register_revspec(RevisionSpec_ancestor)
909
997
_register_revspec(RevisionSpec_branch)
910
998
_register_revspec(RevisionSpec_submit)
 
999
_register_revspec(RevisionSpec_annotate)
 
1000
_register_revspec(RevisionSpec_mainline)
911
1001
 
912
1002
# classes in this list should have a "prefix" attribute, against which
913
1003
# string specs are matched