~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Martin Pool
  • Date: 2007-02-12 07:18:26 UTC
  • mto: (2220.2.19 tags)
  • mto: This revision was merged to the branch mainline in revision 2309.
  • Revision ID: mbp@sourcefrog.net-20070212071826-5x37ixz8r6cylk75
(broken) start moving things to branches

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
 
75
75
 
76
76
######################################################################
 
77
# tag storage
 
78
 
 
79
 
 
80
class _TagStore(object):
 
81
    def __init__(self, repository):
 
82
        self.repository = repository
 
83
 
 
84
class _DisabledTagStore(_TagStore):
 
85
    """Tag storage that refuses to store anything.
 
86
 
 
87
    This is used by older formats that can't store tags.
 
88
    """
 
89
 
 
90
    def _not_supported(self, *a, **k):
 
91
        raise errors.TagsNotSupported(self.repository)
 
92
 
 
93
    def supports_tags(self):
 
94
        return False
 
95
 
 
96
    set_tag = _not_supported
 
97
    get_tag_dict = _not_supported
 
98
    _set_tag_dict = _not_supported
 
99
    lookup_tag = _not_supported
 
100
 
 
101
 
 
102
class _BasicTagStore(_TagStore):
 
103
    """Tag storage in an unversioned repository control file.
 
104
    """
 
105
 
 
106
    def supports_tags(self):
 
107
        return True
 
108
 
 
109
    def set_tag(self, tag_name, tag_target):
 
110
        """Add a tag definition to the repository.
 
111
 
 
112
        Behaviour if the tag is already present is not defined (yet).
 
113
        """
 
114
        # all done with a write lock held, so this looks atomic
 
115
        self.repository.lock_write()
 
116
        try:
 
117
            td = self.get_tag_dict()
 
118
            td[tag_name] = tag_target
 
119
            self._set_tag_dict(td)
 
120
        finally:
 
121
            self.repository.unlock()
 
122
 
 
123
    def lookup_tag(self, tag_name):
 
124
        """Return the referent string of a tag"""
 
125
        td = self.get_tag_dict()
 
126
        try:
 
127
            return td[tag_name]
 
128
        except KeyError:
 
129
            raise errors.NoSuchTag(tag_name)
 
130
 
 
131
    def get_tag_dict(self):
 
132
        self.repository.lock_read()
 
133
        try:
 
134
            tag_content = self.repository.control_files.get_utf8('tags').read()
 
135
            return self._deserialize_tag_dict(tag_content)
 
136
        finally:
 
137
            self.repository.unlock()
 
138
 
 
139
    def _set_tag_dict(self, new_dict):
 
140
        """Replace all tag definitions
 
141
 
 
142
        :param new_dict: Dictionary from tag name to target.
 
143
        """
 
144
        self.repository.lock_read()
 
145
        try:
 
146
            self.repository.control_files.put_utf8('tags',
 
147
                self._serialize_tag_dict(new_dict))
 
148
        finally:
 
149
            self.repository.unlock()
 
150
 
 
151
    def _serialize_tag_dict(self, tag_dict):
 
152
        s = []
 
153
        for tag, target in sorted(tag_dict.items()):
 
154
            # TODO: check that tag names and targets are acceptable
 
155
            s.append(tag + '\t' + target + '\n')
 
156
        return ''.join(s)
 
157
 
 
158
    def _deserialize_tag_dict(self, tag_content):
 
159
        """Convert the tag file into a dictionary of tags"""
 
160
        d = {}
 
161
        for l in tag_content.splitlines():
 
162
            tag, target = l.split('\t', 1)
 
163
            d[tag] = target
 
164
        return d
 
165
 
 
166
 
 
167
######################################################################
77
168
# branch objects
78
169
 
79
170
class Branch(object):
86
177
    # - RBC 20060112
87
178
    base = None
88
179
 
 
180
    # override this to set the strategy for storing tags
 
181
    _tag_store_class = _DisabledTagStore
 
182
 
89
183
    def __init__(self, *ignored, **ignored_too):
90
 
        raise NotImplementedError('The Branch class is abstract')
 
184
        self._tag_store = self._tag_store_class(self)
91
185
 
92
186
    def break_lock(self):
93
187
        """Break a lock if one is present from another instance.
628
722
            checkout_branch.pull(self, stop_revision=revision_id)
629
723
        return checkout.create_workingtree(revision_id)
630
724
 
 
725
    def set_tag(self, tag_name, tag_target):
 
726
        self._tag_store.set_tag(tag_name, tag_target)
 
727
 
 
728
    def lookup_tag(self, tag_name):
 
729
        return self._tag_store.lookup_tag(tag_name)
 
730
 
 
731
    def get_tag_dict(self):
 
732
        return self._tag_store.get_tag_dict()
 
733
 
 
734
    def _set_tag_dict(self, new_dict):
 
735
        return self._tag_store._set_tag_dict(new_dict)
 
736
 
 
737
    def supports_tags(self):
 
738
        return self._tag_store.supports_tags()
 
739
 
 
740
    def copy_tags_to(self, to_repository):
 
741
        """Copy tags to another repository.
 
742
 
 
743
        Subclasses should not override this, but rather customize copying 
 
744
        through the InterRepository mechanism.
 
745
        """
 
746
        return InterRepository.get(self, to_repository).copy_tags()
 
747
 
631
748
 
632
749
class BranchFormat(object):
633
750
    """An encapsulation of the initialization and open routines for a format.
715
832
    def __str__(self):
716
833
        return self.get_format_string().rstrip()
717
834
 
 
835
    def supports_tags(self):
 
836
        """True if this format supports tags stored in the branch"""
 
837
        return False  # by default
 
838
 
 
839
    def _initialize_control_files(self, a_bzrdir, utf8_files, lock_filename,
 
840
            lock_class):
 
841
        branch_transport = a_bzrdir.get_branch_transport(self)
 
842
        control_files = lockable_files.LockableFiles(branch_transport,
 
843
            lock_filename, lock_class)
 
844
        control_files.create_lock()
 
845
        control_files.lock_write()
 
846
        try:
 
847
            for filename, content in utf8_files:
 
848
                control_files.put_utf8(filename, content)
 
849
        finally:
 
850
            control_files.unlock()
 
851
 
718
852
 
719
853
class BzrBranchFormat4(BranchFormat):
720
854
    """Bzr branch format 4.
730
864
 
731
865
    def initialize(self, a_bzrdir):
732
866
        """Create a branch of this format in a_bzrdir."""
733
 
        mutter('creating branch in %s', a_bzrdir.transport.base)
734
 
        branch_transport = a_bzrdir.get_branch_transport(self)
735
867
        utf8_files = [('revision-history', ''),
736
868
                      ('branch-name', ''),
737
869
                      ]
738
 
        control_files = lockable_files.LockableFiles(branch_transport,
739
 
                             'branch-lock', lockable_files.TransportLock)
740
 
        control_files.create_lock()
741
 
        control_files.lock_write()
742
 
        try:
743
 
            for file, content in utf8_files:
744
 
                control_files.put_utf8(file, content)
745
 
        finally:
746
 
            control_files.unlock()
 
870
        self._initialize_control_files(a_bzrdir, utf8_files,
 
871
             'branch-lock', lockable_files.TransportLock)
747
872
        return self.open(a_bzrdir, _found=True)
748
873
 
749
874
    def __init__(self):
829
954
                          a_bzrdir=a_bzrdir,
830
955
                          _repository=a_bzrdir.find_repository())
831
956
 
832
 
    def __str__(self):
833
 
        return "Bazaar-NG Metadir branch format 5"
 
957
 
 
958
class BzrBranchFormatExperimental(BranchFormat):
 
959
    """Bzr experimental branch format
 
960
 
 
961
    This format has:
 
962
     - a revision-history file.
 
963
     - a format string
 
964
     - a lock dir guarding the branch itself
 
965
     - all of this stored in a branch/ subdirectory
 
966
     - works with shared repositories.
 
967
     - a tag dictionary in the branch
 
968
 
 
969
    This format is new in bzr 0.15, but shouldn't be used for real data, 
 
970
    only for testing.
 
971
    """
 
972
 
 
973
    def get_format_string(self):
 
974
        """See BranchFormat.get_format_string()."""
 
975
        return "Bazaar-NG branch format experimental\n"
 
976
 
 
977
    def get_format_description(self):
 
978
        """See BranchFormat.get_format_description()."""
 
979
        return "Experimental branch format"
 
980
        
 
981
    def initialize(self, a_bzrdir):
 
982
        """Create a branch of this format in a_bzrdir."""
 
983
        utf8_files = [('format', self.get_format_string()),
 
984
                      ('revision-history', ''),
 
985
                      ('branch-name', ''),
 
986
                      ('tags', ''),
 
987
                      ]
 
988
        self._initialize_control_files(a_bzrdir, utf8_files,
 
989
            'lock', lockdir.LockDir)
 
990
        return self.open(a_bzrdir, _found=True)
 
991
 
 
992
    def __init__(self):
 
993
        super(BzrBranchFormatExperimental, self).__init__()
 
994
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
 
995
 
 
996
    def open(self, a_bzrdir, _found=False):
 
997
        """Return the branch object for a_bzrdir
 
998
 
 
999
        _found is a private parameter, do not use it. It is used to indicate
 
1000
               if format probing has already be done.
 
1001
        """
 
1002
        if not _found:
 
1003
            format = BranchFormat.find_format(a_bzrdir)
 
1004
            assert format.__class__ == self.__class__
 
1005
        transport = a_bzrdir.get_branch_transport(None)
 
1006
        control_files = lockable_files.LockableFiles(transport, 'lock',
 
1007
                                                     lockdir.LockDir)
 
1008
        return BzrBranchExperimental(_format=self,
 
1009
                          _control_files=control_files,
 
1010
                          a_bzrdir=a_bzrdir,
 
1011
                          _repository=a_bzrdir.find_repository())
834
1012
 
835
1013
 
836
1014
class BranchReferenceFormat(BranchFormat):
1397
1575
        return None
1398
1576
 
1399
1577
 
 
1578
class BzrBranchExperimental(BzrBranch5):
 
1579
 
 
1580
    # TODO: within a lock scope, we could keep the tags in memory...
 
1581
    
 
1582
    _tag_store_class = _BasicTagStore
 
1583
 
 
1584
 
 
1585
 
 
1586
 
1400
1587
class BranchTestProviderAdapter(object):
1401
1588
    """A tool to generate a suite testing multiple branch formats at once.
1402
1589