506
506
writer = rio.RioWriter(s)
507
for key, (tree_path, branch_location) in viewitems(info_dict):
508
stanza = rio.Stanza(file_id=key, tree_path=tree_path,
507
for tree_path, ( branch_location, file_id) in viewitems(info_dict):
508
stanza = rio.Stanza(tree_path=tree_path,
509
509
branch_location=branch_location)
510
if file_id is not None:
511
stanza.add('file_id', file_id)
510
512
writer.write_stanza(stanza)
511
513
with self.lock_write():
512
514
self._transport.put_bytes('references', s.getvalue())
515
517
def _get_all_reference_info(self):
516
518
"""Return all the reference info stored in a branch.
518
:return: A dict of {file_id: (tree_path, branch_location)}
520
:return: A dict of {tree_path: (branch_location, file_id)}
520
522
with self.lock_read():
521
523
if self._reference_info is not None:
522
524
return self._reference_info
523
525
with self._transport.get('references') as rio_file:
524
526
stanzas = rio.read_stanzas(rio_file)
525
info_dict = dict((s['file_id'], (s['tree_path'],
526
s['branch_location'])) for s in stanzas)
529
s['branch_location'],
530
s['file_id'].encode('ascii') if 'file_id' in s else None)
527
532
self._reference_info = info_dict
530
def set_reference_info(self, file_id, tree_path, branch_location):
535
def set_reference_info(self, tree_path, branch_location, file_id=None):
531
536
"""Set the branch location to use for a tree reference.
533
:param file_id: The file-id of the tree reference.
534
538
:param tree_path: The path of the tree reference in the tree.
535
539
:param branch_location: The location of the branch to retrieve tree
541
:param file_id: The file-id of the tree reference.
538
543
info_dict = self._get_all_reference_info()
539
info_dict[file_id] = (tree_path, branch_location)
540
if None in (tree_path, branch_location):
541
if tree_path is not None:
542
raise ValueError('tree_path must be None when branch_location'
544
if branch_location is not None:
545
raise ValueError('branch_location must be None when tree_path'
547
del info_dict[file_id]
544
info_dict[tree_path] = (branch_location, file_id)
545
if branch_location is None:
546
del info_dict[tree_path]
548
547
self._set_all_reference_info(info_dict)
550
def get_reference_info(self, file_id):
549
def get_reference_info(self, path):
551
550
"""Get the tree_path and branch_location for a tree reference.
553
:return: a tuple of (tree_path, branch_location)
552
:return: a tuple of (branch_location, file_id)
555
return self._get_all_reference_info().get(file_id, (None, None))
554
return self._get_all_reference_info().get(path, (None, None))
557
def reference_parent(self, file_id, path, possible_transports=None):
556
def reference_parent(self, path, file_id=None, possible_transports=None):
558
557
"""Return the parent branch for a tree-reference file_id.
560
559
:param file_id: The file_id of the tree reference
561
560
:param path: The path of the file_id in the tree
562
561
:return: A branch associated with the file_id
564
branch_location = self.get_reference_info(file_id)[1]
563
branch_location = self.get_reference_info(path)[0]
565
564
if branch_location is None:
566
return Branch.reference_parent(self, file_id, path,
565
return Branch.reference_parent(self, path, file_id,
567
566
possible_transports)
568
567
branch_location = urlutils.join(self.user_url, branch_location)
569
568
return Branch.open(branch_location,
665
664
class BzrBranch7(BzrBranch8):
666
665
"""A branch with support for a fallback repository."""
668
def set_reference_info(self, file_id, tree_path, branch_location):
667
def set_reference_info(self, tree_path, branch_location, file_id=None):
669
668
Branch.set_reference_info(self, file_id, tree_path, branch_location)
671
def get_reference_info(self, file_id):
672
Branch.get_reference_info(self, file_id)
670
def get_reference_info(self, path):
671
Branch.get_reference_info(self, path)
674
def reference_parent(self, file_id, path, possible_transports=None):
675
return Branch.reference_parent(self, file_id, path,
673
def reference_parent(self, path, file_id=None, possible_transports=None):
674
return Branch.reference_parent(self, path, file_id, possible_transports)
679
677
class BzrBranch6(BzrBranch7):
946
944
def get_reference(self, a_controldir, name=None):
947
945
"""See BranchFormat.get_reference()."""
948
946
transport = a_controldir.get_branch_transport(None, name=name)
949
return transport.get_bytes('location')
947
url = urlutils.split_segment_parameters(a_controldir.user_url)[0]
948
return urlutils.join(url, transport.get_bytes('location'))
950
def _write_reference(self, a_controldir, transport, to_branch):
951
to_url = to_branch.user_url
952
if a_controldir.control_url == to_branch.controldir.control_url:
953
# Write relative paths for colocated branches, but absolute
954
# paths for everything else. This is for the benefit
955
# of older bzr versions that don't support relative paths.
956
to_url = urlutils.relative_url(a_controldir.user_url, to_branch.user_url)
957
transport.put_bytes('location', to_url)
951
959
def set_reference(self, a_controldir, name, to_branch):
952
960
"""See BranchFormat.set_reference()."""
953
961
transport = a_controldir.get_branch_transport(None, name=name)
954
location = transport.put_bytes('location', to_branch.base)
962
self._write_reference(a_controldir, transport, to_branch)
956
964
def initialize(self, a_controldir, name=None, target_branch=None,
957
965
repository=None, append_revisions_only=None):
967
975
name = a_controldir._get_selected_branch()
968
976
branch_transport = a_controldir.get_branch_transport(self, name=name)
969
branch_transport.put_bytes('location', target_branch.user_url)
977
self._write_reference(a_controldir, branch_transport, target_branch)
970
978
branch_transport.put_bytes('format', self.as_string())
971
979
branch = self.open(a_controldir, name, _found=True,
972
980
possible_transports=[target_branch.controldir.root_transport])