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.
1218
1246
reconciler.reconcile()
1219
1247
return reconciler
1221
def reference_parent(self, file_id, path):
1249
def reference_parent(self, file_id, path, possible_transports=None):
1222
1250
"""Return the parent branch for a tree-reference file_id
1223
1251
:param file_id: The file_id of the tree reference
1224
1252
:param path: The path of the file_id in the tree
1225
1253
:return: A branch associated with the file_id
1227
1255
# FIXME should provide multiple branches, based on config
1228
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)
1230
1259
def supports_tags(self):
1231
1260
return self._format.supports_tags()
1732
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):
1733
1800
"""Branch format with last-revision, tags, and a stacked location pointer.
1735
1802
The stacked location pointer is passed down to the repository and requires
1749
1824
"""See BranchFormat.get_format_description()."""
1750
1825
return "Branch format 7"
1752
def initialize(self, a_bzrdir):
1753
"""Create a branch of this format in a_bzrdir."""
1754
utf8_files = [('last-revision', '0 null:\n'),
1755
('branch.conf', ''),
1758
return self._initialize_helper(a_bzrdir, utf8_files)
1761
super(BzrBranchFormat7, self).__init__()
1762
self._matchingbzrdir.repository_format = \
1763
RepositoryFormatKnitPack5RichRoot()
1765
def make_tags(self, branch):
1766
"""See bzrlib.branch.BranchFormat.make_tags()."""
1767
return BasicTags(branch)
1769
def supports_stacking(self):
1827
supports_reference_locations = False
1773
1830
class BranchReferenceFormat(BranchFormat):
1880
1937
__format5 = BzrBranchFormat5()
1881
1938
__format6 = BzrBranchFormat6()
1882
1939
__format7 = BzrBranchFormat7()
1940
__format8 = BzrBranchFormat8()
1883
1941
BranchFormat.register_format(__format5)
1884
1942
BranchFormat.register_format(BranchReferenceFormat())
1885
1943
BranchFormat.register_format(__format6)
1886
1944
BranchFormat.register_format(__format7)
1945
BranchFormat.register_format(__format8)
1887
1946
BranchFormat.set_default_format(__format6)
1888
1947
_legacy_formats = [BzrBranchFormat4(),
2413
2474
def __init__(self, *args, **kwargs):
2414
2475
self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
2415
super(BzrBranch7, self).__init__(*args, **kwargs)
2476
super(BzrBranch8, self).__init__(*args, **kwargs)
2416
2477
self._last_revision_info_cache = None
2417
2478
self._partial_revision_history_cache = []
2479
self._reference_info = None
2419
2481
def _clear_cached_state(self):
2420
super(BzrBranch7, self)._clear_cached_state()
2482
super(BzrBranch8, self)._clear_cached_state()
2421
2483
self._last_revision_info_cache = None
2422
2484
self._partial_revision_history_cache = []
2485
self._reference_info = None
2424
2487
def _last_revision_info(self):
2425
2488
revision_string = self._transport.get_bytes('last-revision')
2535
2598
"""Set the parent branch"""
2536
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)
2538
2676
def set_push_location(self, location):
2539
2677
"""See Branch.set_push_location."""
2540
2678
self._set_config_location('push_location', location)
2638
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)
2641
2793
class BzrBranch6(BzrBranch7):
2642
2794
"""See BzrBranchFormat6 for the capabilities of this branch.
2784
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())
2788
2949
def _run_with_write_locked_target(target, callable, *args, **kwargs):
2789
2950
"""Run ``callable(*args, **kwargs)``, write-locking target for the