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
24
27
from bzrlib import (
30
config as _mod_config,
35
revision as _mod_revision,
36
from bzrlib.config import TreeConfig
41
from bzrlib.config import BranchConfig, TreeConfig
42
from bzrlib.lockable_files import LockableFiles, TransportLock
37
45
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,
46
from bzrlib.errors import (BzrError, BzrCheckError, DivergedBranches,
47
HistoryMissing, InvalidRevisionId,
48
InvalidRevisionNumber, LockError, NoSuchFile,
42
49
NoSuchRevision, NoWorkingTree, NotVersionedError,
43
NotBranchError, UninitializableFormat,
44
UnlistableStore, UnlistableBranch,
50
NotBranchError, UninitializableFormat,
51
UnlistableStore, UnlistableBranch,
46
from bzrlib.lockable_files import LockableFiles, TransportLock
47
53
from bzrlib.symbol_versioning import (deprecated_function,
49
55
DEPRECATED_PARAMETER,
222
230
last_revision = from_history[-1]
224
232
# no history in the source branch
225
last_revision = revision.NULL_REVISION
233
last_revision = _mod_revision.NULL_REVISION
226
234
return self.repository.fetch(from_branch.repository,
227
235
revision_id=last_revision,
369
377
return history[revno - 1]
371
379
def pull(self, source, overwrite=False, stop_revision=None):
380
"""Mirror source into this branch.
382
This branch is considered to be 'local', having low latency.
372
384
raise NotImplementedError(self.pull)
386
def push(self, target, overwrite=False, stop_revision=None):
387
"""Mirror this branch into target.
389
This branch is considered to be 'local', having low latency.
391
raise NotImplementedError(self.push)
374
393
def basis_tree(self):
375
394
"""Return `Tree` object for last revision."""
376
395
return self.repository.revision_tree(self.last_revision())
593
612
format = self.repository.bzrdir.cloning_metadir()
596
def create_checkout(self, to_location, revision_id=None,
615
def create_checkout(self, to_location, revision_id=None,
597
616
lightweight=False):
598
617
"""Create a checkout of a branch.
710
729
return self.get_format_string().rstrip()
732
class BranchHooks(dict):
733
"""A dictionary mapping hook name to a list of callables for branch hooks.
735
e.g. ['set_rh'] Is the list of items to be called when the
736
set_revision_history function is invoked.
740
"""Create the default hooks.
742
These are all empty initially, because by default nothing should get
746
# invoked whenever the revision history has been set
747
# with set_revision_history. The api signature is
748
# (branch, revision_history), and the branch will
749
# be write-locked. Introduced in 0.15.
752
def install_hook(self, hook_name, a_callable):
753
"""Install a_callable in to the hook hook_name.
755
:param hook_name: A hook name. See the __init__ method of BranchHooks
756
for the complete list of hooks.
757
:param a_callable: The callable to be invoked when the hook triggers.
758
The exact signature will depend on the hook - see the __init__
759
method of BranchHooks for details on each hook.
762
self[hook_name].append(a_callable)
764
raise errors.UnknownHook('branch', hook_name)
767
# install the default hooks into the Branch class.
768
Branch.hooks = BranchHooks()
713
771
class BzrBranchFormat4(BranchFormat):
714
772
"""Bzr branch format 4.
729
787
utf8_files = [('revision-history', ''),
730
788
('branch-name', ''),
732
control_files = LockableFiles(branch_transport, 'branch-lock',
790
control_files = lockable_files.LockableFiles(branch_transport,
791
'branch-lock', lockable_files.TransportLock)
734
792
control_files.create_lock()
735
793
control_files.lock_write()
790
848
utf8_files = [('revision-history', ''),
791
849
('branch-name', ''),
793
control_files = LockableFiles(branch_transport, 'lock', lockdir.LockDir)
851
control_files = lockable_files.LockableFiles(branch_transport, 'lock',
794
853
control_files.create_lock()
795
854
control_files.lock_write()
796
855
control_files.put_utf8('format', self.get_format_string())
815
874
format = BranchFormat.find_format(a_bzrdir)
816
875
assert format.__class__ == self.__class__
817
876
transport = a_bzrdir.get_branch_transport(None)
818
control_files = LockableFiles(transport, 'lock', lockdir.LockDir)
877
control_files = lockable_files.LockableFiles(transport, 'lock',
819
879
return BzrBranch5(_format=self,
820
880
_control_files=control_files,
821
881
a_bzrdir=a_bzrdir,
1069
1129
def append_revision(self, *revision_ids):
1070
1130
"""See Branch.append_revision."""
1071
1131
for revision_id in revision_ids:
1132
_mod_revision.check_not_reserved_id(revision_id)
1072
1133
mutter("add {%s} to revision-history" % revision_id)
1073
1134
rev_history = self.revision_history()
1074
1135
rev_history.extend(revision_ids)
1092
1153
# this call is disabled because revision_history is
1093
1154
# not really an object yet, and the transaction is for objects.
1094
1155
# transaction.register_clean(history)
1156
for hook in Branch.hooks['set_rh']:
1157
hook(self, rev_history)
1096
1159
@needs_read_lock
1097
1160
def revision_history(self):
1129
1192
# make a new revision history from the graph
1130
1193
current_rev_id = revision_id
1131
1194
new_history = []
1132
while current_rev_id not in (None, revision.NULL_REVISION):
1195
while current_rev_id not in (None, _mod_revision.NULL_REVISION):
1133
1196
new_history.append(current_rev_id)
1134
1197
current_rev_id_parents = stop_graph[current_rev_id]
1197
1260
source.unlock()
1263
def push(self, target, overwrite=False, stop_revision=None):
1264
"""See Branch.push."""
1267
old_count = len(target.revision_history())
1269
target.update_revisions(self, stop_revision)
1270
except DivergedBranches:
1274
target.set_revision_history(self.revision_history())
1275
new_count = len(target.revision_history())
1276
return new_count - old_count
1199
1280
def get_parent(self):
1200
1281
"""See Branch.get_parent."""
1224
1305
def set_push_location(self, location):
1225
1306
"""See Branch.set_push_location."""
1226
self.get_config().set_user_option('push_location', location,
1307
self.get_config().set_user_option(
1308
'push_location', location,
1309
store=_mod_config.STORE_LOCATION_NORECURSE)
1229
1311
@needs_write_lock
1230
1312
def set_parent(self, url):
1274
1356
@needs_write_lock
1275
1357
def pull(self, source, overwrite=False, stop_revision=None):
1276
"""Updates branch.pull to be bound branch aware."""
1358
"""Extends branch.pull to be bound branch aware."""
1277
1359
bound_location = self.get_bound_location()
1278
1360
if source.base != bound_location:
1279
1361
# not pulling from master, so we need to update master.
1283
1365
source = master_branch
1284
1366
return super(BzrBranch5, self).pull(source, overwrite, stop_revision)
1369
def push(self, target, overwrite=False, stop_revision=None):
1370
"""Updates branch.push to be bound branch aware."""
1371
bound_location = target.get_bound_location()
1372
if target.base != bound_location:
1373
# not pushing to master, so we need to update master.
1374
master_branch = target.get_master_branch()
1376
# push into the master from this branch.
1377
super(BzrBranch5, self).push(master_branch, overwrite,
1379
# and push into the target branch from this. Note that we push from
1380
# this branch again, because its considered the highest bandwidth
1382
return super(BzrBranch5, self).push(target, overwrite, stop_revision)
1286
1384
def get_bound_location(self):
1288
1386
return self.control_files.get_utf8('bound').read()[:-1]
1445
1543
@deprecated_function(zero_eight)
1446
1544
def is_control_file(*args, **kwargs):
1447
1545
"""See bzrlib.workingtree.is_control_file."""
1448
return bzrlib.workingtree.is_control_file(*args, **kwargs)
1546
from bzrlib import workingtree
1547
return workingtree.is_control_file(*args, **kwargs)