15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
from cStringIO import StringIO
20
from bzrlib.lazy_import import lazy_import
21
lazy_import(globals(), """
18
22
from copy import deepcopy
19
from cStringIO import StringIO
20
23
from unittest import TestSuite
21
24
from warnings import warn
34
revision as _mod_revision,
36
from bzrlib.config import TreeConfig
40
from bzrlib.config import BranchConfig, TreeConfig
41
from bzrlib.lockable_files import LockableFiles, TransportLock
37
44
from bzrlib.decorators import needs_read_lock, needs_write_lock
38
import bzrlib.errors as errors
39
from bzrlib.errors import (BzrError, BzrCheckError, DivergedBranches,
40
HistoryMissing, InvalidRevisionId,
41
InvalidRevisionNumber, LockError, NoSuchFile,
45
from bzrlib.errors import (BzrError, BzrCheckError, DivergedBranches,
46
HistoryMissing, InvalidRevisionId,
47
InvalidRevisionNumber, LockError, NoSuchFile,
42
48
NoSuchRevision, NoWorkingTree, NotVersionedError,
43
NotBranchError, UninitializableFormat,
44
UnlistableStore, UnlistableBranch,
49
NotBranchError, UninitializableFormat,
50
UnlistableStore, UnlistableBranch,
46
from bzrlib.lockable_files import LockableFiles, TransportLock
47
52
from bzrlib.symbol_versioning import (deprecated_function,
49
54
DEPRECATED_PARAMETER,
139
144
return bzrdir.BzrDir.create_standalone_workingtree(base).branch
146
@deprecated_function(zero_eight)
141
147
def setup_caching(self, cache_root):
142
148
"""Subclasses that care about caching should override this, and set
143
149
up cached stores located under cache_root.
151
NOTE: This is unused.
145
# seems to be unused, 2006-01-13 mbp
146
warn('%s is deprecated' % self.setup_caching)
147
self.cache_root = cache_root
149
155
def get_config(self):
150
return bzrlib.config.BranchConfig(self)
156
return BranchConfig(self)
152
158
def _get_nick(self):
153
159
return self.get_config().get_nickname()
221
227
last_revision = from_history[-1]
223
229
# no history in the source branch
224
last_revision = revision.NULL_REVISION
230
last_revision = _mod_revision.NULL_REVISION
225
231
return self.repository.fetch(from_branch.repository,
226
232
revision_id=last_revision,
294
300
def revision_history(self):
295
301
"""Return sequence of revision hashes on to this branch."""
296
raise NotImplementedError('revision_history is abstract')
302
raise NotImplementedError(self.revision_history)
299
305
"""Return current revision number for this branch.
580
586
mainline_parent_id = revision_id
581
587
return BranchCheckResult(self)
589
def _get_checkout_format(self):
590
"""Return the most suitable metadir for a checkout of this branch.
591
Weaves are used if this branch's repostory uses weaves.
593
if isinstance(self.bzrdir, bzrdir.BzrDirPreSplitOut):
594
from bzrlib import repository
595
format = bzrdir.BzrDirMetaFormat1()
596
format.repository_format = repository.RepositoryFormat7()
598
format = self.repository.bzrdir.cloning_metadir()
583
601
def create_checkout(self, to_location, revision_id=None,
584
602
lightweight=False):
585
603
"""Create a checkout of a branch.
590
608
produce a bound branch (heavyweight checkout)
591
609
:return: The tree of the created checkout
611
t = transport.get_transport(to_location)
614
except errors.FileExists:
594
t = transport.get_transport(to_location)
597
except errors.FileExists:
599
617
checkout = bzrdir.BzrDirMetaFormat1().initialize_on_transport(t)
600
618
BranchReferenceFormat().initialize(checkout, self)
620
format = self._get_checkout_format()
602
621
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
603
to_location, force_new_tree=False)
622
to_location, force_new_tree=False, format=format)
604
623
checkout = checkout_branch.bzrdir
605
624
checkout_branch.bind(self)
606
if revision_id is not None:
607
rh = checkout_branch.revision_history()
608
new_rh = rh[:rh.index(revision_id) + 1]
609
checkout_branch.set_revision_history(new_rh)
625
# pull up to the specified revision_id to set the initial
626
# branch tip correctly, and seed it with history.
627
checkout_branch.pull(self, stop_revision=revision_id)
610
628
return checkout.create_workingtree(revision_id)
716
734
utf8_files = [('revision-history', ''),
717
735
('branch-name', ''),
719
control_files = LockableFiles(branch_transport, 'branch-lock',
737
control_files = lockable_files.LockableFiles(branch_transport,
738
'branch-lock', lockable_files.TransportLock)
721
739
control_files.create_lock()
722
740
control_files.lock_write()
777
795
utf8_files = [('revision-history', ''),
778
796
('branch-name', ''),
780
control_files = LockableFiles(branch_transport, 'lock', lockdir.LockDir)
798
control_files = lockable_files.LockableFiles(branch_transport, 'lock',
781
800
control_files.create_lock()
782
801
control_files.lock_write()
783
802
control_files.put_utf8('format', self.get_format_string())
802
821
format = BranchFormat.find_format(a_bzrdir)
803
822
assert format.__class__ == self.__class__
804
823
transport = a_bzrdir.get_branch_transport(None)
805
control_files = LockableFiles(transport, 'lock', lockdir.LockDir)
824
control_files = lockable_files.LockableFiles(transport, 'lock',
806
826
return BzrBranch5(_format=self,
807
827
_control_files=control_files,
808
828
a_bzrdir=a_bzrdir,
959
979
__repr__ = __str__
962
# TODO: It might be best to do this somewhere else,
963
# but it is nice for a Branch object to automatically
964
# cache it's information.
965
# Alternatively, we could have the Transport objects cache requests
966
# See the earlier discussion about how major objects (like Branch)
967
# should never expect their __del__ function to run.
968
# XXX: cache_root seems to be unused, 2006-01-13 mbp
969
if hasattr(self, 'cache_root') and self.cache_root is not None:
971
osutils.rmtree(self.cache_root)
974
self.cache_root = None
976
981
def _get_base(self):
977
982
return self._base
1131
1136
# make a new revision history from the graph
1132
1137
current_rev_id = revision_id
1133
1138
new_history = []
1134
while current_rev_id not in (None, revision.NULL_REVISION):
1139
while current_rev_id not in (None, _mod_revision.NULL_REVISION):
1135
1140
new_history.append(current_rev_id)
1136
1141
current_rev_id_parents = stop_graph[current_rev_id]
1329
1334
@needs_write_lock
1330
1335
def bind(self, other):
1331
"""Bind the local branch the other branch.
1336
"""Bind this branch to the branch other.
1338
This does not push or pull data between the branches, though it does
1339
check for divergence to raise an error when the branches are not
1340
either the same, or one a prefix of the other. That behaviour may not
1341
be useful, so that check may be removed in future.
1333
1343
:param other: The branch to bind to
1334
1344
:type other: Branch
1340
1350
# but binding itself may not be.
1341
1351
# Since we *have* to check at commit time, we don't
1342
1352
# *need* to check here
1345
# we are now equal to or a suffix of other.
1347
# Since we have 'pulled' from the remote location,
1348
# now we should try to pull in the opposite direction
1349
# in case the local tree has more revisions than the
1351
# There may be a different check you could do here
1352
# rather than actually trying to install revisions remotely.
1353
# TODO: capture an exception which indicates the remote branch
1355
# If it is up-to-date, this probably should not be a failure
1357
# lock other for write so the revision-history syncing cannot race
1361
# if this does not error, other now has the same last rev we do
1362
# it can only error if the pull from other was concurrent with
1363
# a commit to other from someone else.
1365
# until we ditch revision-history, we need to sync them up:
1366
self.set_revision_history(other.revision_history())
1367
# now other and self are up to date with each other and have the
1368
# same revision-history.
1354
# we want to raise diverged if:
1355
# last_rev is not in the other_last_rev history, AND
1356
# other_last_rev is not in our history, and do it without pulling
1358
last_rev = self.last_revision()
1359
if last_rev is not None:
1362
other_last_rev = other.last_revision()
1363
if other_last_rev is not None:
1364
# neither branch is new, we have to do some work to
1365
# ascertain diversion.
1366
remote_graph = other.repository.get_revision_graph(
1368
local_graph = self.repository.get_revision_graph(last_rev)
1369
if (last_rev not in remote_graph and
1370
other_last_rev not in local_graph):
1371
raise errors.DivergedBranches(self, other)
1372
1374
self.set_bound_location(other.base)
1374
1376
@needs_write_lock