76
76
######################################################################
80
class _TagStore(object):
81
def __init__(self, repository):
82
self.repository = repository
84
class _DisabledTagStore(_TagStore):
85
"""Tag storage that refuses to store anything.
87
This is used by older formats that can't store tags.
90
def _not_supported(self, *a, **k):
91
raise errors.TagsNotSupported(self.repository)
93
def supports_tags(self):
96
set_tag = _not_supported
97
get_tag_dict = _not_supported
98
_set_tag_dict = _not_supported
99
lookup_tag = _not_supported
102
class _BasicTagStore(_TagStore):
103
"""Tag storage in an unversioned repository control file.
106
def supports_tags(self):
109
def set_tag(self, tag_name, tag_target):
110
"""Add a tag definition to the repository.
112
Behaviour if the tag is already present is not defined (yet).
114
# all done with a write lock held, so this looks atomic
115
self.repository.lock_write()
117
td = self.get_tag_dict()
118
td[tag_name] = tag_target
119
self._set_tag_dict(td)
121
self.repository.unlock()
123
def lookup_tag(self, tag_name):
124
"""Return the referent string of a tag"""
125
td = self.get_tag_dict()
129
raise errors.NoSuchTag(tag_name)
131
def get_tag_dict(self):
132
self.repository.lock_read()
134
tag_content = self.repository.control_files.get_utf8('tags').read()
135
return self._deserialize_tag_dict(tag_content)
137
self.repository.unlock()
139
def _set_tag_dict(self, new_dict):
140
"""Replace all tag definitions
142
:param new_dict: Dictionary from tag name to target.
144
self.repository.lock_read()
146
self.repository.control_files.put_utf8('tags',
147
self._serialize_tag_dict(new_dict))
149
self.repository.unlock()
151
def _serialize_tag_dict(self, tag_dict):
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')
158
def _deserialize_tag_dict(self, tag_content):
159
"""Convert the tag file into a dictionary of tags"""
161
for l in tag_content.splitlines():
162
tag, target = l.split('\t', 1)
167
######################################################################
79
170
class Branch(object):
180
# override this to set the strategy for storing tags
181
_tag_store_class = _DisabledTagStore
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)
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)
725
def set_tag(self, tag_name, tag_target):
726
self._tag_store.set_tag(tag_name, tag_target)
728
def lookup_tag(self, tag_name):
729
return self._tag_store.lookup_tag(tag_name)
731
def get_tag_dict(self):
732
return self._tag_store.get_tag_dict()
734
def _set_tag_dict(self, new_dict):
735
return self._tag_store._set_tag_dict(new_dict)
737
def supports_tags(self):
738
return self._tag_store.supports_tags()
740
def copy_tags_to(self, to_repository):
741
"""Copy tags to another repository.
743
Subclasses should not override this, but rather customize copying
744
through the InterRepository mechanism.
746
return InterRepository.get(self, to_repository).copy_tags()
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()
835
def supports_tags(self):
836
"""True if this format supports tags stored in the branch"""
837
return False # by default
839
def _initialize_control_files(self, a_bzrdir, utf8_files, lock_filename,
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()
847
for filename, content in utf8_files:
848
control_files.put_utf8(filename, content)
850
control_files.unlock()
719
853
class BzrBranchFormat4(BranchFormat):
720
854
"""Bzr branch format 4.
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', ''),
738
control_files = lockable_files.LockableFiles(branch_transport,
739
'branch-lock', lockable_files.TransportLock)
740
control_files.create_lock()
741
control_files.lock_write()
743
for file, content in utf8_files:
744
control_files.put_utf8(file, content)
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)
749
874
def __init__(self):
829
954
a_bzrdir=a_bzrdir,
830
955
_repository=a_bzrdir.find_repository())
833
return "Bazaar-NG Metadir branch format 5"
958
class BzrBranchFormatExperimental(BranchFormat):
959
"""Bzr experimental branch format
962
- a revision-history file.
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
969
This format is new in bzr 0.15, but shouldn't be used for real data,
973
def get_format_string(self):
974
"""See BranchFormat.get_format_string()."""
975
return "Bazaar-NG branch format experimental\n"
977
def get_format_description(self):
978
"""See BranchFormat.get_format_description()."""
979
return "Experimental branch format"
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', ''),
988
self._initialize_control_files(a_bzrdir, utf8_files,
989
'lock', lockdir.LockDir)
990
return self.open(a_bzrdir, _found=True)
993
super(BzrBranchFormatExperimental, self).__init__()
994
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
996
def open(self, a_bzrdir, _found=False):
997
"""Return the branch object for a_bzrdir
999
_found is a private parameter, do not use it. It is used to indicate
1000
if format probing has already be done.
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',
1008
return BzrBranchExperimental(_format=self,
1009
_control_files=control_files,
1011
_repository=a_bzrdir.find_repository())
836
1014
class BranchReferenceFormat(BranchFormat):