/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: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
""")
25
25
 
26
26
from bzrlib import (
27
 
    branch as _mod_branch,
28
27
    errors,
29
28
    osutils,
30
29
    registry,
31
30
    revision,
32
31
    symbol_versioning,
33
32
    trace,
34
 
    workingtree,
35
33
    )
36
34
 
37
35
 
168
166
                         spectype.__name__, spec)
169
167
            return spectype(spec, _internal=True)
170
168
        else:
 
169
            for spectype in SPEC_TYPES:
 
170
                if spec.startswith(spectype.prefix):
 
171
                    trace.mutter('Returning RevisionSpec %s for %s',
 
172
                                 spectype.__name__, spec)
 
173
                    return spectype(spec, _internal=True)
171
174
            # Otherwise treat it as a DWIM, build the RevisionSpec object and
172
175
            # wait for _match_on to be called.
173
176
            return RevisionSpec_dwim(spec, _internal=True)
441
444
 
442
445
 
443
446
 
444
 
class RevisionIDSpec(RevisionSpec):
445
 
 
446
 
    def _match_on(self, branch, revs):
447
 
        revision_id = self.as_revision_id(branch)
448
 
        return RevisionInfo.from_revision_id(branch, revision_id, revs)
449
 
 
450
 
 
451
 
class RevisionSpec_revid(RevisionIDSpec):
 
447
class RevisionSpec_revid(RevisionSpec):
452
448
    """Selects a revision using the revision id."""
453
449
 
454
450
    help_txt = """Selects a revision using the revision id.
463
459
 
464
460
    prefix = 'revid:'
465
461
 
466
 
    def _as_revision_id(self, context_branch):
 
462
    def _match_on(self, branch, revs):
467
463
        # self.spec comes straight from parsing the command line arguments,
468
464
        # so we expect it to be a Unicode string. Switch it to the internal
469
465
        # 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
470
        return osutils.safe_revision_id(self.spec, warn=False)
471
471
 
472
472
 
813
813
        revision_b = other_branch.last_revision()
814
814
        if revision_b in (None, revision.NULL_REVISION):
815
815
            raise errors.NoCommits(other_branch)
816
 
        if branch is None:
817
 
            branch = other_branch
818
 
        else:
819
 
            try:
820
 
                # pull in the remote revisions so we can diff
821
 
                branch.fetch(other_branch, revision_b)
822
 
            except errors.ReadOnlyError:
823
 
                branch = other_branch
 
816
        # pull in the remote revisions so we can diff
 
817
        branch.fetch(other_branch, revision_b)
824
818
        try:
825
819
            revno = branch.revision_id_to_revno(revision_b)
826
820
        except errors.NoSuchRevision:
846
840
            raise errors.NoCommits(other_branch)
847
841
        return other_branch.repository.revision_tree(last_revision)
848
842
 
849
 
    def needs_branch(self):
850
 
        return False
851
 
 
852
 
    def get_branch(self):
853
 
        return self.spec
854
 
 
855
843
 
856
844
 
857
845
class RevisionSpec_submit(RevisionSpec_ancestor):
896
884
            self._get_submit_location(context_branch))
897
885
 
898
886
 
899
 
class RevisionSpec_annotate(RevisionIDSpec):
900
 
 
901
 
    prefix = 'annotate:'
902
 
 
903
 
    help_txt = """Select the revision that last modified the specified line.
904
 
 
905
 
    Select the revision that last modified the specified line.  Line is
906
 
    specified as path:number.  Path is a relative path to the file.  Numbers
907
 
    start at 1, and are relative to the current version, not the last-
908
 
    committed version of the file.
909
 
    """
910
 
 
911
 
    def _raise_invalid(self, numstring, context_branch):
912
 
        raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
913
 
            'No such line: %s' % numstring)
914
 
 
915
 
    def _as_revision_id(self, context_branch):
916
 
        path, numstring = self.spec.rsplit(':', 1)
917
 
        try:
918
 
            index = int(numstring) - 1
919
 
        except ValueError:
920
 
            self._raise_invalid(numstring, context_branch)
921
 
        tree, file_path = workingtree.WorkingTree.open_containing(path)
922
 
        tree.lock_read()
923
 
        try:
924
 
            file_id = tree.path2id(file_path)
925
 
            if file_id is None:
926
 
                raise errors.InvalidRevisionSpec(self.user_spec,
927
 
                    context_branch, "File '%s' is not versioned." %
928
 
                    file_path)
929
 
            revision_ids = [r for (r, l) in tree.annotate_iter(file_id)]
930
 
        finally:
931
 
            tree.unlock()
932
 
        try:
933
 
            revision_id = revision_ids[index]
934
 
        except IndexError:
935
 
            self._raise_invalid(numstring, context_branch)
936
 
        if revision_id == revision.CURRENT_REVISION:
937
 
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
938
 
                'Line %s has not been committed.' % numstring)
939
 
        return revision_id
940
 
 
941
 
 
942
 
class RevisionSpec_mainline(RevisionIDSpec):
943
 
 
944
 
    help_txt = """Select mainline revision that merged the specified revision.
945
 
 
946
 
    Select the revision that merged the specified revision into mainline.
947
 
    """
948
 
 
949
 
    prefix = 'mainline:'
950
 
 
951
 
    def _as_revision_id(self, context_branch):
952
 
        revspec = RevisionSpec.from_string(self.spec)
953
 
        if revspec.get_branch() is None:
954
 
            spec_branch = context_branch
955
 
        else:
956
 
            spec_branch = _mod_branch.Branch.open(revspec.get_branch())
957
 
        revision_id = revspec.as_revision_id(spec_branch)
958
 
        graph = context_branch.repository.get_graph()
959
 
        result = graph.find_lefthand_merger(revision_id,
960
 
                                            context_branch.last_revision())
961
 
        if result is None:
962
 
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
963
 
        return result
964
 
 
965
 
 
966
887
# The order in which we want to DWIM a revision spec without any prefix.
967
888
# revno is always tried first and isn't listed here, this is used by
968
889
# RevisionSpec_dwim._match_on
987
908
_register_revspec(RevisionSpec_ancestor)
988
909
_register_revspec(RevisionSpec_branch)
989
910
_register_revspec(RevisionSpec_submit)
990
 
_register_revspec(RevisionSpec_annotate)
991
 
_register_revspec(RevisionSpec_mainline)
 
911
 
 
912
# classes in this list should have a "prefix" attribute, against which
 
913
# string specs are matched
 
914
SPEC_TYPES = symbol_versioning.deprecated_list(
 
915
    symbol_versioning.deprecated_in((1, 12, 0)), "SPEC_TYPES", [])