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.
1205
1233
reconciler.reconcile()
1206
1234
return reconciler
1208
def reference_parent(self, file_id, path):
1236
def reference_parent(self, file_id, path, possible_transports=None):
1209
1237
"""Return the parent branch for a tree-reference file_id
1210
1238
:param file_id: The file_id of the tree reference
1211
1239
:param path: The path of the file_id in the tree
1212
1240
:return: A branch associated with the file_id
1214
1242
# FIXME should provide multiple branches, based on config
1215
return Branch.open(self.bzrdir.root_transport.clone(path).base)
1243
return Branch.open(self.bzrdir.root_transport.clone(path).base,
1244
possible_transports=possible_transports)
1217
1246
def supports_tags(self):
1218
1247
return self._format.supports_tags()
1719
class BzrBranchFormat7(BranchFormatMetadir):
1748
class BzrBranchFormat8(BranchFormatMetadir):
1749
"""Metadir format supporting storing locations of subtree branches."""
1751
def _branch_class(self):
1754
def get_format_string(self):
1755
"""See BranchFormat.get_format_string()."""
1756
return "Bazaar Branch Format 8 (needs bzr 1.15)\n"
1758
def get_format_description(self):
1759
"""See BranchFormat.get_format_description()."""
1760
return "Branch format 8"
1762
def initialize(self, a_bzrdir):
1763
"""Create a branch of this format in a_bzrdir."""
1764
utf8_files = [('last-revision', '0 null:\n'),
1765
('branch.conf', ''),
1769
return self._initialize_helper(a_bzrdir, utf8_files)
1772
super(BzrBranchFormat8, self).__init__()
1773
self._matchingbzrdir.repository_format = \
1774
RepositoryFormatKnitPack5RichRoot()
1776
def make_tags(self, branch):
1777
"""See bzrlib.branch.BranchFormat.make_tags()."""
1778
return BasicTags(branch)
1780
def supports_stacking(self):
1783
supports_reference_locations = True
1786
class BzrBranchFormat7(BzrBranchFormat8):
1720
1787
"""Branch format with last-revision, tags, and a stacked location pointer.
1722
1789
The stacked location pointer is passed down to the repository and requires
1736
1811
"""See BranchFormat.get_format_description()."""
1737
1812
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):
1814
supports_reference_locations = False
1760
1817
class BranchReferenceFormat(BranchFormat):
1867
1924
__format5 = BzrBranchFormat5()
1868
1925
__format6 = BzrBranchFormat6()
1869
1926
__format7 = BzrBranchFormat7()
1927
__format8 = BzrBranchFormat8()
1870
1928
BranchFormat.register_format(__format5)
1871
1929
BranchFormat.register_format(BranchReferenceFormat())
1872
1930
BranchFormat.register_format(__format6)
1873
1931
BranchFormat.register_format(__format7)
1932
BranchFormat.register_format(__format8)
1874
1933
BranchFormat.set_default_format(__format6)
1875
1934
_legacy_formats = [BzrBranchFormat4(),
2400
2461
def __init__(self, *args, **kwargs):
2401
2462
self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
2402
super(BzrBranch7, self).__init__(*args, **kwargs)
2463
super(BzrBranch8, self).__init__(*args, **kwargs)
2403
2464
self._last_revision_info_cache = None
2404
2465
self._partial_revision_history_cache = []
2466
self._reference_info = None
2406
2468
def _clear_cached_state(self):
2407
super(BzrBranch7, self)._clear_cached_state()
2469
super(BzrBranch8, self)._clear_cached_state()
2408
2470
self._last_revision_info_cache = None
2409
2471
self._partial_revision_history_cache = []
2472
self._reference_info = None
2411
2474
def _last_revision_info(self):
2412
2475
revision_string = self._transport.get_bytes('last-revision')
2522
2585
"""Set the parent branch"""
2523
2586
return self._get_config_location('parent_location')
2589
def _set_all_reference_info(self, info_dict):
2590
"""Replace all reference info stored in a branch.
2592
:param info_dict: A dict of {file_id: (tree_path, branch_location)}
2595
writer = rio.RioWriter(s)
2596
for key, (tree_path, branch_location) in info_dict.iteritems():
2597
stanza = rio.Stanza(file_id=key, tree_path=tree_path,
2598
branch_location=branch_location)
2599
writer.write_stanza(stanza)
2600
self._transport.put_bytes('references', s.getvalue())
2601
self._reference_info = info_dict
2604
def _get_all_reference_info(self):
2605
"""Return all the reference info stored in a branch.
2607
:return: A dict of {file_id: (tree_path, branch_location)}
2609
if self._reference_info is not None:
2610
return self._reference_info
2611
rio_file = self._transport.get('references')
2613
stanzas = rio.read_stanzas(rio_file)
2614
info_dict = dict((s['file_id'], (s['tree_path'],
2615
s['branch_location'])) for s in stanzas)
2618
self._reference_info = info_dict
2621
def set_reference_info(self, file_id, tree_path, branch_location):
2622
"""Set the branch location to use for a tree reference.
2624
:param file_id: The file-id of the tree reference.
2625
:param tree_path: The path of the tree reference in the tree.
2626
:param branch_location: The location of the branch to retrieve tree
2629
info_dict = self._get_all_reference_info()
2630
info_dict[file_id] = (tree_path, branch_location)
2631
if None in (tree_path, branch_location):
2632
if tree_path is not None:
2633
raise ValueError('tree_path must be None when branch_location'
2635
if branch_location is not None:
2636
raise ValueError('branch_location must be None when tree_path'
2638
del info_dict[file_id]
2639
self._set_all_reference_info(info_dict)
2641
def get_reference_info(self, file_id):
2642
"""Get the tree_path and branch_location for a tree reference.
2644
:return: a tuple of (tree_path, branch_location)
2646
return self._get_all_reference_info().get(file_id, (None, None))
2648
def reference_parent(self, file_id, path, possible_transports=None):
2649
"""Return the parent branch for a tree-reference file_id.
2651
:param file_id: The file_id of the tree reference
2652
:param path: The path of the file_id in the tree
2653
:return: A branch associated with the file_id
2655
branch_location = self.get_reference_info(file_id)[1]
2656
if branch_location is None:
2657
return Branch.reference_parent(self, file_id, path,
2658
possible_transports)
2659
branch_location = urlutils.join(self.base, branch_location)
2660
return Branch.open(branch_location,
2661
possible_transports=possible_transports)
2525
2663
def set_push_location(self, location):
2526
2664
"""See Branch.set_push_location."""
2527
2665
self._set_config_location('push_location', location)
2625
2763
return self.revno() - index
2766
class BzrBranch7(BzrBranch8):
2767
"""A branch with support for a fallback repository."""
2769
def set_reference_info(self, file_id, tree_path, branch_location):
2770
Branch.set_reference_info(self, file_id, tree_path, branch_location)
2772
def get_reference_info(self, file_id):
2773
Branch.get_reference_info(self, file_id)
2775
def reference_parent(self, file_id, path, possible_transports=None):
2776
return Branch.reference_parent(self, file_id, path,
2777
possible_transports)
2628
2780
class BzrBranch6(BzrBranch7):
2629
2781
"""See BzrBranchFormat6 for the capabilities of this branch.
2771
2923
branch._transport.put_bytes('format', format.get_format_string())
2926
class Converter7to8(object):
2927
"""Perform an in-place upgrade of format 6 to format 7"""
2929
def convert(self, branch):
2930
format = BzrBranchFormat8()
2931
branch._transport.put_bytes('references', '')
2932
# update target format
2933
branch._transport.put_bytes('format', format.get_format_string())
2775
2936
def _run_with_write_locked_target(target, callable, *args, **kwargs):
2776
2937
"""Run ``callable(*args, **kwargs)``, write-locking target for the