50
49
from bzrlib.errors import (BzrError, BzrCheckError, DivergedBranches,
51
50
HistoryMissing, InvalidRevisionId,
52
51
InvalidRevisionNumber, LockError, NoSuchFile,
53
NoSuchRevision, NotVersionedError,
52
NoSuchRevision, NoWorkingTree, NotVersionedError,
54
53
NotBranchError, UninitializableFormat,
55
54
UnlistableStore, UnlistableBranch,
60
59
DEPRECATED_PARAMETER,
62
61
zero_eight, zero_nine, zero_sixteen,
65
from bzrlib.trace import mutter, mutter_callsite, note
63
from bzrlib.trace import mutter, note
68
66
BZR_BRANCH_FORMAT_4 = "Bazaar-NG branch, format 0.0.4\n"
118
116
master.break_lock()
121
def open(base, _unsupported=False, possible_transports=None):
119
@deprecated_method(zero_eight)
120
def open_downlevel(base):
121
"""Open a branch which may be of an old format."""
122
return Branch.open(base, _unsupported=True)
125
def open(base, _unsupported=False):
122
126
"""Open the branch rooted at base.
124
128
For instance, if the branch is at URL/.bzr/branch,
125
129
Branch.open(URL) -> a Branch instance.
127
control = bzrdir.BzrDir.open(base, _unsupported,
128
possible_transports=possible_transports)
129
return control.open_branch(_unsupported)
132
def open_from_transport(transport, _unsupported=False):
133
"""Open the branch rooted at transport"""
134
control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
135
return control.open_branch(_unsupported)
138
def open_containing(url, possible_transports=None):
131
control = bzrdir.BzrDir.open(base, _unsupported)
132
return control.open_branch(_unsupported)
135
def open_containing(url):
139
136
"""Open an existing branch which contains url.
141
138
This probes for a branch at url, and searches upwards from there.
146
143
format, UnknownFormatError or UnsupportedFormatError are raised.
147
144
If there is one, it is returned, along with the unused portion of url.
149
control, relpath = bzrdir.BzrDir.open_containing(url,
146
control, relpath = bzrdir.BzrDir.open_containing(url)
151
147
return control.open_branch(), relpath
150
@deprecated_function(zero_eight)
151
def initialize(base):
152
"""Create a new working tree and branch, rooted at 'base' (url)
154
NOTE: This will soon be deprecated in favour of creation
157
return bzrdir.BzrDir.create_standalone_workingtree(base).branch
159
@deprecated_function(zero_eight)
160
def setup_caching(self, cache_root):
161
"""Subclasses that care about caching should override this, and set
162
up cached stores located under cache_root.
164
NOTE: This is unused.
153
168
def get_config(self):
154
169
return BranchConfig(self)
322
337
return self.repository.get_commit_builder(self, parents, config,
323
338
timestamp, timezone, committer, revprops, revision_id)
325
def get_master_branch(self, possible_transports=None):
340
def get_master_branch(self):
326
341
"""Return the branch we are bound to.
328
343
:return: Either a Branch, or None
354
369
"""Print `file` to stdout."""
355
370
raise NotImplementedError(self.print_file)
372
def append_revision(self, *revision_ids):
373
raise NotImplementedError(self.append_revision)
357
375
def set_revision_history(self, rev_history):
358
376
raise NotImplementedError(self.set_revision_history)
407
425
def revision_history(self):
408
"""Return sequence of revision ids on this branch.
426
"""Return sequence of revision hashes on to this branch.
410
428
This method will cache the revision history for as long as it is safe to
413
if 'evil' in debug.debug_flags:
414
mutter_callsite(3, "revision_history scales with history.")
415
431
if self._revision_history_cache is not None:
416
432
history = self._revision_history_cache
500
517
def get_rev_id(self, revno, history=None):
501
518
"""Find the revision id of the specified revno."""
503
return _mod_revision.NULL_REVISION
504
521
if history is None:
505
522
history = self.revision_history()
506
523
if revno <= 0 or revno > len(history):
507
524
raise errors.NoSuchRevision(self, revno)
508
525
return history[revno - 1]
510
def pull(self, source, overwrite=False, stop_revision=None,
511
possible_transports=None):
527
def pull(self, source, overwrite=False, stop_revision=None):
512
528
"""Mirror source into this branch.
514
530
This branch is considered to be 'local', having low latency.
759
776
def create_checkout(self, to_location, revision_id=None,
760
lightweight=False, accelerator_tree=None):
761
778
"""Create a checkout of a branch.
763
780
:param to_location: The url to produce the checkout at
764
781
:param revision_id: The revision to check out
765
782
:param lightweight: If True, produce a lightweight checkout, otherwise,
766
783
produce a bound branch (heavyweight checkout)
767
:param accelerator_tree: A tree which can be used for retrieving file
768
contents more quickly than the revision tree, i.e. a workingtree.
769
The revision tree will be used for cases where accelerator_tree's
770
content is different.
771
784
:return: The tree of the created checkout
773
786
t = transport.get_transport(to_location)
776
789
format = self._get_checkout_format()
777
790
checkout = format.initialize_on_transport(t)
778
from_branch = BranchReferenceFormat().initialize(checkout, self)
791
BranchReferenceFormat().initialize(checkout, self)
780
793
format = self._get_checkout_format()
781
794
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
785
798
# pull up to the specified revision_id to set the initial
786
799
# branch tip correctly, and seed it with history.
787
800
checkout_branch.pull(self, stop_revision=revision_id)
789
tree = checkout.create_workingtree(revision_id,
790
from_branch=from_branch,
791
accelerator_tree=accelerator_tree)
801
tree = checkout.create_workingtree(revision_id)
792
802
basis_tree = tree.basis_tree()
793
803
basis_tree.lock_read()
877
def set_reference(self, a_bzrdir, to_branch):
878
"""Set the target reference of the branch in a_bzrdir.
880
format probing must have been completed before calling
881
this method - it is assumed that the format of the branch
882
in a_bzrdir is correct.
884
:param a_bzrdir: The bzrdir to set the branch reference for.
885
:param to_branch: branch that the checkout is to reference
887
raise NotImplementedError(self.set_reference)
889
886
def get_format_string(self):
890
887
"""Return the ASCII format string that identifies this format."""
891
888
raise NotImplementedError(self.get_format_string)
1022
1019
# is read locked and the target branches write locked. The local
1023
1020
# branch is the low-latency branch.
1024
1021
self['post_pull'] = []
1025
# invoked before a commit operation takes place.
1026
# the api signature is
1027
# (local, master, old_revno, old_revid, future_revno, future_revid,
1028
# tree_delta, future_tree).
1029
# old_revid is NULL_REVISION for the first commit to a branch
1030
# tree_delta is a TreeDelta object describing changes from the basis
1031
# revision, hooks MUST NOT modify this delta
1032
# future_tree is an in-memory tree obtained from
1033
# CommitBuilder.revision_tree() and hooks MUST NOT modify this tree
1034
self['pre_commit'] = []
1035
1022
# invoked after a commit operation completes.
1036
1023
# the api signature is
1037
1024
# (local, master, old_revno, old_revid, new_revno, new_revid)
1147
1134
class BzrBranchFormat6(BzrBranchFormat5):
1148
"""Branch format with last-revision and tags.
1135
"""Branch format with last-revision
1150
1137
Unlike previous formats, this has no explicit revision history. Instead,
1151
1138
this just stores the last-revision, and the left-hand history leading
1152
1139
up to there is the history.
1154
1141
This format was introduced in bzr 0.15
1155
and became the default in 0.91.
1158
1144
def get_format_string(self):
1210
1197
def get_format_description(self):
1211
1198
"""See BranchFormat.get_format_description()."""
1212
1199
return "Checkout reference format 1"
1214
1201
def get_reference(self, a_bzrdir):
1215
1202
"""See BranchFormat.get_reference()."""
1216
1203
transport = a_bzrdir.get_branch_transport(None)
1217
1204
return transport.get('location').read()
1219
def set_reference(self, a_bzrdir, to_branch):
1220
"""See BranchFormat.set_reference()."""
1221
transport = a_bzrdir.get_branch_transport(None)
1222
location = transport.put_bytes('location', to_branch.base)
1224
1206
def initialize(self, a_bzrdir, target_branch=None):
1225
1207
"""Create a branch of this format in a_bzrdir."""
1226
1208
if target_branch is None:
1232
1214
branch_transport.put_bytes('location',
1233
1215
target_branch.bzrdir.root_transport.base)
1234
1216
branch_transport.put_bytes('format', self.get_format_string())
1236
a_bzrdir, _found=True,
1237
possible_transports=[target_branch.bzrdir.root_transport])
1217
return self.open(a_bzrdir, _found=True)
1239
1219
def __init__(self):
1240
1220
super(BranchReferenceFormat, self).__init__()
1250
1230
# emit some sort of warning/error to the caller ?!
1253
def open(self, a_bzrdir, _found=False, location=None,
1254
possible_transports=None):
1233
def open(self, a_bzrdir, _found=False, location=None):
1255
1234
"""Return the branch that the branch reference in a_bzrdir points at.
1257
1236
_found is a private parameter, do not use it. It is used to indicate
1262
1241
assert format.__class__ == self.__class__
1263
1242
if location is None:
1264
1243
location = self.get_reference(a_bzrdir)
1265
real_bzrdir = bzrdir.BzrDir.open(
1266
location, possible_transports=possible_transports)
1244
real_bzrdir = bzrdir.BzrDir.open(location)
1267
1245
result = real_bzrdir.open_branch()
1268
1246
# this changes the behaviour of result.clone to create a new reference
1269
1247
# rather than a copy of the content of the branch.
1280
1258
# formats which have no format string are not discoverable
1281
1259
# and not independently creatable, so are not registered.
1282
__format5 = BzrBranchFormat5()
1283
__format6 = BzrBranchFormat6()
1284
BranchFormat.register_format(__format5)
1260
__default_format = BzrBranchFormat5()
1261
BranchFormat.register_format(__default_format)
1285
1262
BranchFormat.register_format(BranchReferenceFormat())
1286
BranchFormat.register_format(__format6)
1287
BranchFormat.set_default_format(__format6)
1263
BranchFormat.register_format(BzrBranchFormat6())
1264
BranchFormat.set_default_format(__default_format)
1288
1265
_legacy_formats = [BzrBranchFormat4(),
1382
1359
"""See Branch.print_file."""
1383
1360
return self.repository.print_file(file, revision_id)
1363
def append_revision(self, *revision_ids):
1364
"""See Branch.append_revision."""
1365
revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
1366
for revision_id in revision_ids:
1367
_mod_revision.check_not_reserved_id(revision_id)
1368
mutter("add {%s} to revision-history" % revision_id)
1369
rev_history = self.revision_history()
1370
rev_history.extend(revision_ids)
1371
self.set_revision_history(rev_history)
1385
1373
def _write_revision_history(self, history):
1386
1374
"""Factored out of set_revision_history.
1393
1381
@needs_write_lock
1394
1382
def set_revision_history(self, rev_history):
1395
1383
"""See Branch.set_revision_history."""
1396
if 'evil' in debug.debug_flags:
1397
mutter_callsite(3, "set_revision_history scales with history.")
1384
rev_history = [osutils.safe_revision_id(r) for r in rev_history]
1398
1385
self._clear_cached_state()
1399
1386
self._write_revision_history(rev_history)
1400
1387
self._cache_revision_history(rev_history)
1404
1391
@needs_write_lock
1405
1392
def set_last_revision_info(self, revno, revision_id):
1406
"""Set the last revision of this branch.
1408
The caller is responsible for checking that the revno is correct
1409
for this revision id.
1411
It may be possible to set the branch last revision to an id not
1412
present in the repository. However, branches can also be
1413
configured to check constraints on history, in which case this may not
1393
revision_id = osutils.safe_revision_id(revision_id)
1416
1394
history = self._lefthand_history(revision_id)
1417
1395
assert len(history) == revno, '%d != %d' % (len(history), revno)
1418
1396
self.set_revision_history(history)
1427
1405
def _lefthand_history(self, revision_id, last_rev=None,
1428
1406
other_branch=None):
1429
if 'evil' in debug.debug_flags:
1430
mutter_callsite(4, "_lefthand_history scales with history.")
1431
1407
# stop_revision must be a descendant of last_revision
1432
1408
stop_graph = self.repository.get_revision_graph(revision_id)
1433
1409
if (last_rev is not None and last_rev != _mod_revision.NULL_REVISION
1458
1434
:param other_branch: The other branch that DivergedBranches should
1459
1435
raise with respect to.
1437
revision_id = osutils.safe_revision_id(revision_id)
1461
1438
self.set_revision_history(self._lefthand_history(revision_id,
1462
1439
last_rev, other_branch))
1464
1441
@needs_write_lock
1465
def update_revisions(self, other, stop_revision=None, overwrite=False):
1442
def update_revisions(self, other, stop_revision=None):
1466
1443
"""See Branch.update_revisions."""
1467
1444
other.lock_read()
1469
other_last_revno, other_last_revision = other.last_revision_info()
1470
1446
if stop_revision is None:
1471
stop_revision = other_last_revision
1472
if _mod_revision.is_null(stop_revision):
1447
stop_revision = other.last_revision()
1448
if stop_revision is None:
1473
1449
# if there are no commits, we're done.
1452
stop_revision = osutils.safe_revision_id(stop_revision)
1475
1453
# whats the current last revision, before we fetch [and change it
1477
1455
last_rev = _mod_revision.ensure_null(self.last_revision())
1478
# we fetch here so that we don't process data twice in the common
1479
# case of having something to pull, and so that the check for
1480
# already merged can operate on the just fetched graph, which will
1481
# be cached in memory.
1456
# we fetch here regardless of whether we need to so that we pickup
1482
1458
self.fetch(other, stop_revision)
1483
# Check to see if one is an ancestor of the other
1485
heads = self.repository.get_graph().heads([stop_revision,
1487
if heads == set([last_rev]):
1488
# The current revision is a decendent of the target,
1491
elif heads == set([stop_revision, last_rev]):
1492
# These branches have diverged
1493
raise errors.DivergedBranches(self, other)
1494
assert heads == set([stop_revision])
1495
if other_last_revision == stop_revision:
1496
self.set_last_revision_info(other_last_revno,
1497
other_last_revision)
1499
# TODO: jam 2007-11-29 Is there a way to determine the
1500
# revno without searching all of history??
1502
self.generate_revision_history(stop_revision)
1504
self.generate_revision_history(stop_revision,
1505
last_rev=last_rev, other_branch=other)
1459
my_ancestry = self.repository.get_ancestry(last_rev,
1461
if stop_revision in my_ancestry:
1462
# last_revision is a descendant of stop_revision
1464
self.generate_revision_history(stop_revision, last_rev=last_rev,
1510
1470
"""See Branch.basis_tree."""
1511
1471
return self.repository.revision_tree(self.last_revision())
1473
@deprecated_method(zero_eight)
1474
def working_tree(self):
1475
"""Create a Working tree object for this branch."""
1477
from bzrlib.transport.local import LocalTransport
1478
if (self.base.find('://') != -1 or
1479
not isinstance(self._transport, LocalTransport)):
1480
raise NoWorkingTree(self.base)
1481
return self.bzrdir.open_workingtree()
1513
1483
@needs_write_lock
1514
1484
def pull(self, source, overwrite=False, stop_revision=None,
1515
_hook_master=None, run_hooks=True, possible_transports=None):
1485
_hook_master=None, run_hooks=True):
1516
1486
"""See Branch.pull.
1518
1488
:param _hook_master: Private parameter - set the branch to
1527
1497
source.lock_read()
1529
1499
result.old_revno, result.old_revid = self.last_revision_info()
1530
self.update_revisions(source, stop_revision, overwrite=overwrite)
1531
result.tag_conflicts = source.tags.merge_to(self.tags, overwrite)
1501
self.update_revisions(source, stop_revision)
1502
except DivergedBranches:
1506
if stop_revision is None:
1507
stop_revision = source.last_revision()
1508
self.generate_revision_history(stop_revision)
1509
result.tag_conflicts = source.tags.merge_to(self.tags)
1532
1510
result.new_revno, result.new_revid = self.last_revision_info()
1533
1511
if _hook_master:
1534
1512
result.master_branch = _hook_master
1689
1667
assert isinstance(url, str)
1690
1668
self.control_files.put_bytes('parent', url + '\n')
1670
@deprecated_function(zero_nine)
1671
def tree_config(self):
1672
"""DEPRECATED; call get_config instead.
1673
TreeConfig has become part of BranchConfig."""
1674
return TreeConfig(self)
1693
1677
class BzrBranch5(BzrBranch):
1694
"""A format 5 branch. This supports new features over plain branches.
1678
"""A format 5 branch. This supports new features over plan branches.
1696
1680
It has support for a master_branch which is the data for bound branches.
1709
1693
@needs_write_lock
1710
1694
def pull(self, source, overwrite=False, stop_revision=None,
1711
run_hooks=True, possible_transports=None):
1712
1696
"""Pull from source into self, updating my master if any.
1714
1698
:param run_hooks: Private parameter - if false, this branch
1799
1782
# last_rev is not in the other_last_rev history, AND
1800
1783
# other_last_rev is not in our history, and do it without pulling
1801
1784
# history around
1785
last_rev = _mod_revision.ensure_null(self.last_revision())
1786
if not _mod_revision.is_null(last_rev):
1789
other_last_rev = other.last_revision()
1790
if not _mod_revision.is_null(other_last_rev):
1791
# neither branch is new, we have to do some work to
1792
# ascertain diversion.
1793
remote_graph = other.repository.get_revision_graph(
1795
local_graph = self.repository.get_revision_graph(last_rev)
1796
if (last_rev not in remote_graph and
1797
other_last_rev not in local_graph):
1798
raise errors.DivergedBranches(self, other)
1802
1801
self.set_bound_location(other.base)
1804
1803
@needs_write_lock
1807
1806
return self.set_bound_location(None)
1809
1808
@needs_write_lock
1810
def update(self, possible_transports=None):
1811
1810
"""Synchronise this branch with the master branch if any.
1813
1812
:return: None or the last_revision that was pivoted out during the
1816
master = self.get_master_branch(possible_transports)
1815
master = self.get_master_branch()
1817
1816
if master is not None:
1818
old_tip = _mod_revision.ensure_null(self.last_revision())
1817
old_tip = self.last_revision()
1819
1818
self.pull(master, overwrite=True)
1820
if self.repository.get_graph().is_ancestor(old_tip,
1821
_mod_revision.ensure_null(self.last_revision())):
1819
if old_tip in self.repository.get_ancestry(
1820
_mod_revision.ensure_null(self.last_revision()),
1870
def set_reference(self, a_bzrdir, to_branch):
1871
"""Set the target reference of the branch in a_bzrdir.
1873
format probing must have been completed before calling
1874
this method - it is assumed that the format of the branch
1875
in a_bzrdir is correct.
1877
:param a_bzrdir: The bzrdir to set the branch reference for.
1878
:param to_branch: branch that the checkout is to reference
1880
raise NotImplementedError(self.set_reference)
1883
1870
def _initialize_control_files(cls, a_bzrdir, utf8_files, lock_filename,
1885
1872
branch_transport = a_bzrdir.get_branch_transport(cls)
2006
1996
self._write_last_revision_info(len(history), last_revision)
2008
1998
@needs_write_lock
1999
def append_revision(self, *revision_ids):
2000
revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
2001
if len(revision_ids) == 0:
2003
prev_revno, prev_revision = self.last_revision_info()
2004
for revision in self.repository.get_revisions(revision_ids):
2005
if prev_revision == _mod_revision.NULL_REVISION:
2006
if revision.parent_ids != []:
2007
raise errors.NotLeftParentDescendant(self, prev_revision,
2008
revision.revision_id)
2010
if revision.parent_ids[0] != prev_revision:
2011
raise errors.NotLeftParentDescendant(self, prev_revision,
2012
revision.revision_id)
2013
prev_revision = revision.revision_id
2014
self.set_last_revision_info(prev_revno + len(revision_ids),
2009
2018
def _set_parent_location(self, url):
2010
2019
"""Set the parent branch"""
2011
2020
self._set_config_location('parent_location', url, make_relative=True)
2077
2086
:param revision_id: The revision-id to truncate history at. May
2078
2087
be None to copy complete history.
2080
source_revno, source_revision_id = self.last_revision_info()
2081
2089
if revision_id is None:
2082
revno, revision_id = source_revno, source_revision_id
2083
elif source_revision_id == revision_id:
2084
# we know the revno without needing to walk all of history
2085
revno = source_revno
2090
revno, revision_id = self.last_revision_info()
2087
2092
# To figure out the revno for a random revision, we need to build
2088
2093
# the revision history, and count its length.