371
369
if revno < 1 or revno > self.revno():
372
370
raise InvalidRevisionNumber(revno)
374
def clone(self, to_location, revision=None, basis_branch=None, to_branch_format=None):
375
"""Copy this branch into the existing directory to_location.
377
Returns the newly created branch object.
380
If not None, only revisions up to this point will be copied.
381
The head of the new branch will be that revision. Must be a
384
to_location -- The destination directory; must either exist and be
385
empty, or not exist, in which case it is created.
388
A local branch to copy revisions from, related to this branch.
389
This is used when branching from a remote (slow) branch, and we have
390
a local branch that might contain some relevant revisions.
393
Branch type of destination branch
395
from bzrlib.workingtree import WorkingTree
396
assert isinstance(to_location, basestring)
397
segments = to_location.split('/')
398
if segments and segments[-1] not in ('', '.'):
399
parent = '/'.join(segments[:-1])
400
t = get_transport(parent)
373
def clone(self, *args, **kwargs):
374
"""Clone this branch into to_bzrdir preserving all semantic values.
376
revision_id: if not None, the revision history in the new branch will
377
be truncated to end with revision_id.
379
# for API compatability, until 0.8 releases we provide the old api:
380
# def clone(self, to_location, revision=None, basis_branch=None, to_branch_format=None):
381
# after 0.8 releases, the *args and **kwargs should be changed:
382
# def clone(self, to_bzrdir, revision_id=None):
383
if (kwargs.get('to_location', None) or
384
kwargs.get('revision', None) or
385
kwargs.get('basis_branch', None) or
386
(len(args) and isinstance(args[0], basestring))):
387
# backwards compatability api:
388
warn("Branch.clone() has been deprecated for BzrDir.clone() from"
389
" bzrlib 0.8.", DeprecationWarning, stacklevel=3)
392
basis_branch = args[2]
394
basis_branch = kwargs.get('basis_branch', None)
396
basis = basis_branch.bzrdir
401
revision_id = args[1]
403
revision_id = kwargs.get('revision', None)
408
# no default to raise if not provided.
409
url = kwargs.get('to_location')
410
return self.bzrdir.clone(url,
411
revision_id=revision_id,
412
basis=basis).open_branch()
414
# generate args by hand
416
revision_id = args[1]
418
revision_id = kwargs.get('revision_id', None)
422
# no default to raise if not provided.
423
to_bzrdir = kwargs.get('to_bzrdir')
424
result = self._format.initialize(to_bzrdir)
425
self.copy_content_into(result, revision_id=revision_id)
429
def sprout(self, to_bzrdir, revision_id=None):
430
"""Create a new line of development from the branch, into to_bzrdir.
432
revision_id: if not None, the revision history in the new branch will
433
be truncated to end with revision_id.
435
result = self._format.initialize(to_bzrdir)
436
self.copy_content_into(result, revision_id=revision_id)
437
result.set_parent(self.bzrdir.root_transport.base)
441
def copy_content_into(self, destination, revision_id=None):
442
"""Copy the content of self into destination.
444
revision_id: if not None, the revision history in the new branch will
445
be truncated to end with revision_id.
447
new_history = self.revision_history()
448
if revision_id is not None:
402
t.mkdir(segments[-1])
403
except errors.FileExists:
405
if to_branch_format is None:
407
br_to = bzrdir.BzrDir.create_branch_and_repo(to_location)
409
br_to = to_branch_format.initialize(to_location)
410
mutter("copy branch from %s to %s", self, br_to)
412
revision = self.last_revision()
413
if basis_branch is not None:
414
basis_branch.repository.push_stores(br_to.repository,
416
br_to.update_revisions(self, stop_revision=revision)
417
br_to.set_parent(self.base)
450
new_history = new_history[:new_history.index(revision_id) + 1]
452
rev = self.repository.get_revision(revision_id)
453
new_history = rev.get_history(self.repository)[1:]
454
destination.set_revision_history(new_history)
455
parent = self.get_parent()
457
destination.set_parent(parent)
422
460
class BranchFormat(object):
619
657
a_bzrdir=a_bzrdir)
660
class BranchReferenceFormat(BranchFormat):
661
"""Bzr branch reference format.
663
Branch references are used in implementing checkouts, they
664
act as an alias to the real branch which is at some other url.
671
def get_format_string(self):
672
"""See BranchFormat.get_format_string()."""
673
return "Bazaar-NG Branch Reference Format 1\n"
675
def initialize(self, a_bzrdir, target_branch=None):
676
"""Create a branch of this format in a_bzrdir."""
677
if target_branch is None:
678
# this format does not implement branch itself, thus the implicit
679
# creation contract must see it as uninitializable
680
raise errors.UninitializableFormat(self)
681
mutter('creating branch reference in %s', a_bzrdir.transport.base)
682
branch_transport = a_bzrdir.get_branch_transport(self)
683
# FIXME rbc 20060209 one j-a-ms encoding branch lands this str() cast is not needed.
684
branch_transport.put('location', StringIO(str(target_branch.bzrdir.root_transport.base)))
685
branch_transport.put('format', StringIO(self.get_format_string()))
686
return self.open(a_bzrdir, _found=True)
689
super(BranchReferenceFormat, self).__init__()
690
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
692
def _make_reference_clone_function(format, a_branch):
693
"""Create a clone() routine for a branch dynamically."""
694
def clone(to_bzrdir, revision_id=None):
695
"""See Branch.clone()."""
696
return format.initialize(to_bzrdir, a_branch)
697
# cannot obey revision_id limits when cloning a reference ...
698
# FIXME RBC 20060210 either nuke revision_id for clone, or
699
# emit some sort of warning/error to the caller ?!
702
def open(self, a_bzrdir, _found=False):
703
"""Return the branch that the branch reference in a_bzrdir points at.
705
_found is a private parameter, do not use it. It is used to indicate
706
if format probing has already be done.
709
format = BranchFormat.find_format(a_bzrdir)
710
assert format.__class__ == self.__class__
711
transport = a_bzrdir.get_branch_transport(None)
712
real_bzrdir = bzrdir.BzrDir.open(transport.get('location').read())
713
result = real_bzrdir.open_branch()
714
# this changes the behaviour of result.clone to create a new reference
715
# rather than a copy of the content of the branch.
716
# I did not use a proxy object because that needs much more extensive
717
# testing, and we are only changing one behaviour at the moment.
718
# If we decide to alter more behaviours - i.e. the implicit nickname
719
# then this should be refactored to introduce a tested proxy branch
720
# and a subclass of that for use in overriding clone() and ....
722
result.clone = self._make_reference_clone_function(result)
622
726
# formats which have no format string are not discoverable
623
727
# and not independently creatable, so are not registered.
624
728
__default_format = BzrBranchFormat5()
625
729
BranchFormat.register_format(__default_format)
730
BranchFormat.register_format(BranchReferenceFormat())
626
731
BranchFormat.set_default_format(__default_format)
627
732
_legacy_formats = [BzrBranchFormat4(),