501
503
raise errors.UpgradeRequired(self.base)
505
def set_reference_info(self, file_id, tree_path, branch_location):
506
"""Set the branch location to use for a tree reference."""
507
raise errors.UnsupportedOperation(self.set_reference_info, self)
509
def get_reference_info(self, file_id):
510
"""Get the tree_path and branch_location for a tree reference."""
511
raise errors.UnsupportedOperation(self.get_reference_info, self)
503
513
@needs_write_lock
504
514
def fetch(self, from_branch, last_revision=None, pb=None):
505
515
"""Copy revisions from from_branch into this branch.
1081
1092
if self._push_should_merge_tags():
1082
1093
self.tags.merge_to(destination.tags)
1095
def update_references(self, target):
1096
if not getattr(self._format, 'supports_reference_locations', False):
1098
reference_dict = self._get_all_reference_info()
1099
if len(reference_dict) == 0:
1101
old_base = self.base
1102
new_base = target.base
1103
target_reference_dict = target._get_all_reference_info()
1104
for file_id, (tree_path, branch_location) in (
1105
reference_dict.items()):
1106
branch_location = urlutils.rebase_url(branch_location,
1108
target_reference_dict.setdefault(
1109
file_id, (tree_path, branch_location))
1110
target._set_all_reference_info(target_reference_dict)
1084
1112
@needs_read_lock
1085
1113
def check(self):
1086
1114
"""Check consistency of the branch.
1136
1164
def create_clone_on_transport(self, to_transport, revision_id=None,
1165
stacked_on=None, create_prefix=False, use_existing_dir=False):
1138
1166
"""Create a clone of this branch and its bzrdir.
1140
1168
:param to_transport: The transport to clone onto.
1141
1169
:param revision_id: The revision id to use as tip in the new branch.
1142
1170
If None the tip is obtained from this branch.
1143
1171
:param stacked_on: An optional URL to stack the clone on.
1172
:param create_prefix: Create any missing directories leading up to
1174
:param use_existing_dir: Use an existing directory if one exists.
1145
1176
# XXX: Fix the bzrdir API to allow getting the branch back from the
1146
1177
# clone call. Or something. 20090224 RBC/spiv.
1147
dir_to = self.bzrdir.clone_on_transport(to_transport,
1148
revision_id=revision_id, stacked_on=stacked_on)
1178
if revision_id is None:
1179
revision_id = self.last_revision()
1181
dir_to = self.bzrdir.clone_on_transport(to_transport,
1182
revision_id=revision_id, stacked_on=stacked_on,
1183
create_prefix=create_prefix, use_existing_dir=use_existing_dir)
1184
except errors.FileExists:
1185
if not use_existing_dir:
1187
except errors.NoSuchFile:
1188
if not create_prefix:
1149
1190
return dir_to.open_branch()
1151
1192
def create_checkout(self, to_location, revision_id=None,
1205
1246
reconciler.reconcile()
1206
1247
return reconciler
1208
def reference_parent(self, file_id, path):
1249
def reference_parent(self, file_id, path, possible_transports=None):
1209
1250
"""Return the parent branch for a tree-reference file_id
1210
1251
:param file_id: The file_id of the tree reference
1211
1252
:param path: The path of the file_id in the tree
1212
1253
:return: A branch associated with the file_id
1214
1255
# FIXME should provide multiple branches, based on config
1215
return Branch.open(self.bzrdir.root_transport.clone(path).base)
1256
return Branch.open(self.bzrdir.root_transport.clone(path).base,
1257
possible_transports=possible_transports)
1217
1259
def supports_tags(self):
1218
1260
return self._format.supports_tags()
1719
class BzrBranchFormat7(BranchFormatMetadir):
1761
class BzrBranchFormat8(BranchFormatMetadir):
1762
"""Metadir format supporting storing locations of subtree branches."""
1764
def _branch_class(self):
1767
def get_format_string(self):
1768
"""See BranchFormat.get_format_string()."""
1769
return "Bazaar Branch Format 8 (needs bzr 1.15)\n"
1771
def get_format_description(self):
1772
"""See BranchFormat.get_format_description()."""
1773
return "Branch format 8"
1775
def initialize(self, a_bzrdir):
1776
"""Create a branch of this format in a_bzrdir."""
1777
utf8_files = [('last-revision', '0 null:\n'),
1778
('branch.conf', ''),
1782
return self._initialize_helper(a_bzrdir, utf8_files)
1785
super(BzrBranchFormat8, self).__init__()
1786
self._matchingbzrdir.repository_format = \
1787
RepositoryFormatKnitPack5RichRoot()
1789
def make_tags(self, branch):
1790
"""See bzrlib.branch.BranchFormat.make_tags()."""
1791
return BasicTags(branch)
1793
def supports_stacking(self):
1796
supports_reference_locations = True
1799
class BzrBranchFormat7(BzrBranchFormat8):
1720
1800
"""Branch format with last-revision, tags, and a stacked location pointer.
1722
1802
The stacked location pointer is passed down to the repository and requires
1736
1824
"""See BranchFormat.get_format_description()."""
1737
1825
return "Branch format 7"
1739
def initialize(self, a_bzrdir):
1740
"""Create a branch of this format in a_bzrdir."""
1741
utf8_files = [('last-revision', '0 null:\n'),
1742
('branch.conf', ''),
1745
return self._initialize_helper(a_bzrdir, utf8_files)
1748
super(BzrBranchFormat7, self).__init__()
1749
self._matchingbzrdir.repository_format = \
1750
RepositoryFormatKnitPack5RichRoot()
1752
def make_tags(self, branch):
1753
"""See bzrlib.branch.BranchFormat.make_tags()."""
1754
return BasicTags(branch)
1756
def supports_stacking(self):
1827
supports_reference_locations = False
1760
1830
class BranchReferenceFormat(BranchFormat):
1867
1937
__format5 = BzrBranchFormat5()
1868
1938
__format6 = BzrBranchFormat6()
1869
1939
__format7 = BzrBranchFormat7()
1940
__format8 = BzrBranchFormat8()
1870
1941
BranchFormat.register_format(__format5)
1871
1942
BranchFormat.register_format(BranchReferenceFormat())
1872
1943
BranchFormat.register_format(__format6)
1873
1944
BranchFormat.register_format(__format7)
1945
BranchFormat.register_format(__format8)
1874
1946
BranchFormat.set_default_format(__format6)
1875
1947
_legacy_formats = [BzrBranchFormat4(),
2400
2474
def __init__(self, *args, **kwargs):
2401
2475
self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
2402
super(BzrBranch7, self).__init__(*args, **kwargs)
2476
super(BzrBranch8, self).__init__(*args, **kwargs)
2403
2477
self._last_revision_info_cache = None
2404
2478
self._partial_revision_history_cache = []
2479
self._reference_info = None
2406
2481
def _clear_cached_state(self):
2407
super(BzrBranch7, self)._clear_cached_state()
2482
super(BzrBranch8, self)._clear_cached_state()
2408
2483
self._last_revision_info_cache = None
2409
2484
self._partial_revision_history_cache = []
2485
self._reference_info = None
2411
2487
def _last_revision_info(self):
2412
2488
revision_string = self._transport.get_bytes('last-revision')
2522
2598
"""Set the parent branch"""
2523
2599
return self._get_config_location('parent_location')
2602
def _set_all_reference_info(self, info_dict):
2603
"""Replace all reference info stored in a branch.
2605
:param info_dict: A dict of {file_id: (tree_path, branch_location)}
2608
writer = rio.RioWriter(s)
2609
for key, (tree_path, branch_location) in info_dict.iteritems():
2610
stanza = rio.Stanza(file_id=key, tree_path=tree_path,
2611
branch_location=branch_location)
2612
writer.write_stanza(stanza)
2613
self._transport.put_bytes('references', s.getvalue())
2614
self._reference_info = info_dict
2617
def _get_all_reference_info(self):
2618
"""Return all the reference info stored in a branch.
2620
:return: A dict of {file_id: (tree_path, branch_location)}
2622
if self._reference_info is not None:
2623
return self._reference_info
2624
rio_file = self._transport.get('references')
2626
stanzas = rio.read_stanzas(rio_file)
2627
info_dict = dict((s['file_id'], (s['tree_path'],
2628
s['branch_location'])) for s in stanzas)
2631
self._reference_info = info_dict
2634
def set_reference_info(self, file_id, tree_path, branch_location):
2635
"""Set the branch location to use for a tree reference.
2637
:param file_id: The file-id of the tree reference.
2638
:param tree_path: The path of the tree reference in the tree.
2639
:param branch_location: The location of the branch to retrieve tree
2642
info_dict = self._get_all_reference_info()
2643
info_dict[file_id] = (tree_path, branch_location)
2644
if None in (tree_path, branch_location):
2645
if tree_path is not None:
2646
raise ValueError('tree_path must be None when branch_location'
2648
if branch_location is not None:
2649
raise ValueError('branch_location must be None when tree_path'
2651
del info_dict[file_id]
2652
self._set_all_reference_info(info_dict)
2654
def get_reference_info(self, file_id):
2655
"""Get the tree_path and branch_location for a tree reference.
2657
:return: a tuple of (tree_path, branch_location)
2659
return self._get_all_reference_info().get(file_id, (None, None))
2661
def reference_parent(self, file_id, path, possible_transports=None):
2662
"""Return the parent branch for a tree-reference file_id.
2664
:param file_id: The file_id of the tree reference
2665
:param path: The path of the file_id in the tree
2666
:return: A branch associated with the file_id
2668
branch_location = self.get_reference_info(file_id)[1]
2669
if branch_location is None:
2670
return Branch.reference_parent(self, file_id, path,
2671
possible_transports)
2672
branch_location = urlutils.join(self.base, branch_location)
2673
return Branch.open(branch_location,
2674
possible_transports=possible_transports)
2525
2676
def set_push_location(self, location):
2526
2677
"""See Branch.set_push_location."""
2527
2678
self._set_config_location('push_location', location)
2625
2776
return self.revno() - index
2779
class BzrBranch7(BzrBranch8):
2780
"""A branch with support for a fallback repository."""
2782
def set_reference_info(self, file_id, tree_path, branch_location):
2783
Branch.set_reference_info(self, file_id, tree_path, branch_location)
2785
def get_reference_info(self, file_id):
2786
Branch.get_reference_info(self, file_id)
2788
def reference_parent(self, file_id, path, possible_transports=None):
2789
return Branch.reference_parent(self, file_id, path,
2790
possible_transports)
2628
2793
class BzrBranch6(BzrBranch7):
2629
2794
"""See BzrBranchFormat6 for the capabilities of this branch.
2771
2936
branch._transport.put_bytes('format', format.get_format_string())
2939
class Converter7to8(object):
2940
"""Perform an in-place upgrade of format 6 to format 7"""
2942
def convert(self, branch):
2943
format = BzrBranchFormat8()
2944
branch._transport.put_bytes('references', '')
2945
# update target format
2946
branch._transport.put_bytes('format', format.get_format_string())
2775
2949
def _run_with_write_locked_target(target, callable, *args, **kwargs):
2776
2950
"""Run ``callable(*args, **kwargs)``, write-locking target for the