51
50
from bzrlib.errors import (BzrError, BzrCheckError, DivergedBranches,
52
51
HistoryMissing, InvalidRevisionId,
53
52
InvalidRevisionNumber, LockError, NoSuchFile,
54
NoSuchRevision, NoWorkingTree, NotVersionedError,
53
NoSuchRevision, NotVersionedError,
55
54
NotBranchError, UninitializableFormat,
56
55
UnlistableStore, UnlistableBranch,
61
60
DEPRECATED_PARAMETER,
63
62
zero_eight, zero_nine, zero_sixteen,
65
from bzrlib.trace import mutter, note
65
from bzrlib.trace import mutter, mutter_callsite, note
68
68
BZR_BRANCH_FORMAT_4 = "Bazaar-NG branch, format 0.0.4\n"
118
118
master.break_lock()
121
@deprecated_method(zero_eight)
122
def open_downlevel(base):
123
"""Open a branch which may be of an old format."""
124
return Branch.open(base, _unsupported=True)
127
def open(base, _unsupported=False):
121
def open(base, _unsupported=False, possible_transports=None):
128
122
"""Open the branch rooted at base.
130
124
For instance, if the branch is at URL/.bzr/branch,
131
125
Branch.open(URL) -> a Branch instance.
133
control = bzrdir.BzrDir.open(base, _unsupported)
134
return control.open_branch(_unsupported)
137
def open_containing(url):
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):
138
139
"""Open an existing branch which contains url.
140
141
This probes for a branch at url, and searches upwards from there.
145
146
format, UnknownFormatError or UnsupportedFormatError are raised.
146
147
If there is one, it is returned, along with the unused portion of url.
148
control, relpath = bzrdir.BzrDir.open_containing(url)
149
control, relpath = bzrdir.BzrDir.open_containing(url,
149
151
return control.open_branch(), relpath
152
@deprecated_function(zero_eight)
153
def initialize(base):
154
"""Create a new working tree and branch, rooted at 'base' (url)
156
NOTE: This will soon be deprecated in favour of creation
159
return bzrdir.BzrDir.create_standalone_workingtree(base).branch
161
@deprecated_function(zero_eight)
162
def setup_caching(self, cache_root):
163
"""Subclasses that care about caching should override this, and set
164
up cached stores located under cache_root.
166
NOTE: This is unused.
170
153
def get_config(self):
171
154
return BranchConfig(self)
174
157
return self.get_config().get_nickname()
176
159
def _set_nick(self, nick):
177
self.get_config().set_user_option('nickname', nick)
160
self.get_config().set_user_option('nickname', nick, warn_masked=True)
179
162
nick = property(_get_nick, _set_nick)
339
322
return self.repository.get_commit_builder(self, parents, config,
340
323
timestamp, timezone, committer, revprops, revision_id)
342
def get_master_branch(self):
325
def get_master_branch(self, possible_transports=None):
343
326
"""Return the branch we are bound to.
345
328
:return: Either a Branch, or None
371
354
"""Print `file` to stdout."""
372
355
raise NotImplementedError(self.print_file)
374
def append_revision(self, *revision_ids):
375
raise NotImplementedError(self.append_revision)
377
357
def set_revision_history(self, rev_history):
378
358
raise NotImplementedError(self.set_revision_history)
427
407
def revision_history(self):
428
"""Return sequence of revision hashes on to this branch.
408
"""Return sequence of revision ids on this branch.
430
410
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.")
433
415
if self._revision_history_cache is not None:
434
416
history = self._revision_history_cache
519
500
def get_rev_id(self, revno, history=None):
520
501
"""Find the revision id of the specified revno."""
503
return _mod_revision.NULL_REVISION
523
504
if history is None:
524
505
history = self.revision_history()
525
506
if revno <= 0 or revno > len(history):
526
507
raise errors.NoSuchRevision(self, revno)
527
508
return history[revno - 1]
529
def pull(self, source, overwrite=False, stop_revision=None):
510
def pull(self, source, overwrite=False, stop_revision=None,
511
possible_transports=None):
530
512
"""Mirror source into this branch.
532
514
This branch is considered to be 'local', having low latency.
702
685
:param revision_id: The revision-id to truncate history at. May
703
686
be None to copy complete history.
688
if revision_id == _mod_revision.NULL_REVISION:
705
690
new_history = self.revision_history()
706
if revision_id is not None:
707
revision_id = osutils.safe_revision_id(revision_id)
691
if revision_id is not None and new_history != []:
709
693
new_history = new_history[:new_history.index(revision_id) + 1]
710
694
except ValueError:
775
759
def create_checkout(self, to_location, revision_id=None,
760
lightweight=False, accelerator_tree=None):
777
761
"""Create a checkout of a branch.
779
763
:param to_location: The url to produce the checkout at
780
764
:param revision_id: The revision to check out
781
765
:param lightweight: If True, produce a lightweight checkout, otherwise,
782
766
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.
783
771
:return: The tree of the created checkout
785
773
t = transport.get_transport(to_location)
788
776
format = self._get_checkout_format()
789
777
checkout = format.initialize_on_transport(t)
790
BranchReferenceFormat().initialize(checkout, self)
778
from_branch = BranchReferenceFormat().initialize(checkout, self)
792
780
format = self._get_checkout_format()
793
781
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
797
785
# pull up to the specified revision_id to set the initial
798
786
# branch tip correctly, and seed it with history.
799
787
checkout_branch.pull(self, stop_revision=revision_id)
800
tree = checkout.create_workingtree(revision_id)
789
tree = checkout.create_workingtree(revision_id,
790
from_branch=from_branch,
791
accelerator_tree=accelerator_tree)
801
792
basis_tree = tree.basis_tree()
802
793
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)
885
889
def get_format_string(self):
886
890
"""Return the ASCII format string that identifies this format."""
887
891
raise NotImplementedError(self.get_format_string)
1018
1022
# is read locked and the target branches write locked. The local
1019
1023
# branch is the low-latency branch.
1020
1024
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'] = []
1021
1035
# invoked after a commit operation completes.
1022
1036
# the api signature is
1023
1037
# (local, master, old_revno, old_revid, new_revno, new_revid)
1133
1147
class BzrBranchFormat6(BzrBranchFormat5):
1134
"""Branch format with last-revision
1148
"""Branch format with last-revision and tags.
1136
1150
Unlike previous formats, this has no explicit revision history. Instead,
1137
1151
this just stores the last-revision, and the left-hand history leading
1138
1152
up to there is the history.
1140
1154
This format was introduced in bzr 0.15
1155
and became the default in 0.91.
1143
1158
def get_format_string(self):
1196
1210
def get_format_description(self):
1197
1211
"""See BranchFormat.get_format_description()."""
1198
1212
return "Checkout reference format 1"
1200
1214
def get_reference(self, a_bzrdir):
1201
1215
"""See BranchFormat.get_reference()."""
1202
1216
transport = a_bzrdir.get_branch_transport(None)
1203
1217
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)
1205
1224
def initialize(self, a_bzrdir, target_branch=None):
1206
1225
"""Create a branch of this format in a_bzrdir."""
1207
1226
if target_branch is None:
1213
1232
branch_transport.put_bytes('location',
1214
1233
target_branch.bzrdir.root_transport.base)
1215
1234
branch_transport.put_bytes('format', self.get_format_string())
1216
return self.open(a_bzrdir, _found=True)
1236
a_bzrdir, _found=True,
1237
possible_transports=[target_branch.bzrdir.root_transport])
1218
1239
def __init__(self):
1219
1240
super(BranchReferenceFormat, self).__init__()
1229
1250
# emit some sort of warning/error to the caller ?!
1232
def open(self, a_bzrdir, _found=False, location=None):
1253
def open(self, a_bzrdir, _found=False, location=None,
1254
possible_transports=None):
1233
1255
"""Return the branch that the branch reference in a_bzrdir points at.
1235
1257
_found is a private parameter, do not use it. It is used to indicate
1240
1262
assert format.__class__ == self.__class__
1241
1263
if location is None:
1242
1264
location = self.get_reference(a_bzrdir)
1243
real_bzrdir = bzrdir.BzrDir.open(location)
1265
real_bzrdir = bzrdir.BzrDir.open(
1266
location, possible_transports=possible_transports)
1244
1267
result = real_bzrdir.open_branch()
1245
1268
# this changes the behaviour of result.clone to create a new reference
1246
1269
# rather than a copy of the content of the branch.
1257
1280
# formats which have no format string are not discoverable
1258
1281
# and not independently creatable, so are not registered.
1259
__default_format = BzrBranchFormat5()
1260
BranchFormat.register_format(__default_format)
1282
__format5 = BzrBranchFormat5()
1283
__format6 = BzrBranchFormat6()
1284
BranchFormat.register_format(__format5)
1261
1285
BranchFormat.register_format(BranchReferenceFormat())
1262
BranchFormat.register_format(BzrBranchFormat6())
1263
BranchFormat.set_default_format(__default_format)
1286
BranchFormat.register_format(__format6)
1287
BranchFormat.set_default_format(__format6)
1264
1288
_legacy_formats = [BzrBranchFormat4(),
1358
1382
"""See Branch.print_file."""
1359
1383
return self.repository.print_file(file, revision_id)
1362
def append_revision(self, *revision_ids):
1363
"""See Branch.append_revision."""
1364
revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
1365
for revision_id in revision_ids:
1366
_mod_revision.check_not_reserved_id(revision_id)
1367
mutter("add {%s} to revision-history" % revision_id)
1368
rev_history = self.revision_history()
1369
rev_history.extend(revision_ids)
1370
self.set_revision_history(rev_history)
1372
1385
def _write_revision_history(self, history):
1373
1386
"""Factored out of set_revision_history.
1380
1393
@needs_write_lock
1381
1394
def set_revision_history(self, rev_history):
1382
1395
"""See Branch.set_revision_history."""
1383
rev_history = [osutils.safe_revision_id(r) for r in rev_history]
1396
if 'evil' in debug.debug_flags:
1397
mutter_callsite(3, "set_revision_history scales with history.")
1384
1398
self._clear_cached_state()
1385
1399
self._write_revision_history(rev_history)
1386
1400
self._cache_revision_history(rev_history)
1390
1404
@needs_write_lock
1391
1405
def set_last_revision_info(self, revno, revision_id):
1392
revision_id = osutils.safe_revision_id(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
1416
history = self._lefthand_history(revision_id)
1394
1417
assert len(history) == revno, '%d != %d' % (len(history), revno)
1395
1418
self.set_revision_history(history)
1404
1427
def _lefthand_history(self, revision_id, last_rev=None,
1405
1428
other_branch=None):
1429
if 'evil' in debug.debug_flags:
1430
mutter_callsite(4, "_lefthand_history scales with history.")
1406
1431
# stop_revision must be a descendant of last_revision
1407
1432
stop_graph = self.repository.get_revision_graph(revision_id)
1408
if last_rev is not None and last_rev not in stop_graph:
1433
if (last_rev is not None and last_rev != _mod_revision.NULL_REVISION
1434
and last_rev not in stop_graph):
1409
1435
# our previous tip is not merged into stop_revision
1410
1436
raise errors.DivergedBranches(self, other_branch)
1411
1437
# make a new revision history from the graph
1432
1458
:param other_branch: The other branch that DivergedBranches should
1433
1459
raise with respect to.
1435
revision_id = osutils.safe_revision_id(revision_id)
1436
1461
self.set_revision_history(self._lefthand_history(revision_id,
1437
1462
last_rev, other_branch))
1439
1464
@needs_write_lock
1440
def update_revisions(self, other, stop_revision=None):
1465
def update_revisions(self, other, stop_revision=None, overwrite=False):
1441
1466
"""See Branch.update_revisions."""
1442
1467
other.lock_read()
1469
other_last_revno, other_last_revision = other.last_revision_info()
1444
1470
if stop_revision is None:
1445
stop_revision = other.last_revision()
1446
if stop_revision is None:
1471
stop_revision = other_last_revision
1472
if _mod_revision.is_null(stop_revision):
1447
1473
# if there are no commits, we're done.
1450
stop_revision = osutils.safe_revision_id(stop_revision)
1451
1475
# whats the current last revision, before we fetch [and change it
1453
last_rev = self.last_revision()
1454
# we fetch here regardless of whether we need to so that we pickup
1477
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
1482
self.fetch(other, stop_revision)
1457
my_ancestry = self.repository.get_ancestry(last_rev)
1458
if stop_revision in my_ancestry:
1459
# last_revision is a descendant of stop_revision
1461
self.generate_revision_history(stop_revision, last_rev=last_rev,
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)
1467
1510
"""See Branch.basis_tree."""
1468
1511
return self.repository.revision_tree(self.last_revision())
1470
@deprecated_method(zero_eight)
1471
def working_tree(self):
1472
"""Create a Working tree object for this branch."""
1474
from bzrlib.transport.local import LocalTransport
1475
if (self.base.find('://') != -1 or
1476
not isinstance(self._transport, LocalTransport)):
1477
raise NoWorkingTree(self.base)
1478
return self.bzrdir.open_workingtree()
1480
1513
@needs_write_lock
1481
1514
def pull(self, source, overwrite=False, stop_revision=None,
1482
_hook_master=None, run_hooks=True):
1515
_hook_master=None, run_hooks=True, possible_transports=None):
1483
1516
"""See Branch.pull.
1485
1518
:param _hook_master: Private parameter - set the branch to
1494
1527
source.lock_read()
1496
1529
result.old_revno, result.old_revid = self.last_revision_info()
1498
self.update_revisions(source, stop_revision)
1499
except DivergedBranches:
1503
if stop_revision is None:
1504
stop_revision = source.last_revision()
1505
self.generate_revision_history(stop_revision)
1506
result.tag_conflicts = source.tags.merge_to(self.tags)
1530
self.update_revisions(source, stop_revision, overwrite=overwrite)
1531
result.tag_conflicts = source.tags.merge_to(self.tags, overwrite)
1507
1532
result.new_revno, result.new_revid = self.last_revision_info()
1508
1533
if _hook_master:
1509
1534
result.master_branch = _hook_master
1664
1689
assert isinstance(url, str)
1665
1690
self.control_files.put_bytes('parent', url + '\n')
1667
@deprecated_function(zero_nine)
1668
def tree_config(self):
1669
"""DEPRECATED; call get_config instead.
1670
TreeConfig has become part of BranchConfig."""
1671
return TreeConfig(self)
1674
1693
class BzrBranch5(BzrBranch):
1675
"""A format 5 branch. This supports new features over plan branches.
1694
"""A format 5 branch. This supports new features over plain branches.
1677
1696
It has support for a master_branch which is the data for bound branches.
1690
1709
@needs_write_lock
1691
1710
def pull(self, source, overwrite=False, stop_revision=None,
1711
run_hooks=True, possible_transports=None):
1693
1712
"""Pull from source into self, updating my master if any.
1695
1714
:param run_hooks: Private parameter - if false, this branch
1779
1799
# last_rev is not in the other_last_rev history, AND
1780
1800
# other_last_rev is not in our history, and do it without pulling
1781
1801
# history around
1782
last_rev = self.last_revision()
1783
if last_rev is not None:
1786
other_last_rev = other.last_revision()
1787
if other_last_rev is not None:
1788
# neither branch is new, we have to do some work to
1789
# ascertain diversion.
1790
remote_graph = other.repository.get_revision_graph(
1792
local_graph = self.repository.get_revision_graph(last_rev)
1793
if (last_rev not in remote_graph and
1794
other_last_rev not in local_graph):
1795
raise errors.DivergedBranches(self, other)
1798
1802
self.set_bound_location(other.base)
1800
1804
@needs_write_lock
1803
1807
return self.set_bound_location(None)
1805
1809
@needs_write_lock
1810
def update(self, possible_transports=None):
1807
1811
"""Synchronise this branch with the master branch if any.
1809
1813
:return: None or the last_revision that was pivoted out during the
1812
master = self.get_master_branch()
1816
master = self.get_master_branch(possible_transports)
1813
1817
if master is not None:
1814
old_tip = self.last_revision()
1818
old_tip = _mod_revision.ensure_null(self.last_revision())
1815
1819
self.pull(master, overwrite=True)
1816
if old_tip in self.repository.get_ancestry(self.last_revision()):
1820
if self.repository.get_graph().is_ancestor(old_tip,
1821
_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)
1865
1883
def _initialize_control_files(cls, a_bzrdir, utf8_files, lock_filename,
1867
1885
branch_transport = a_bzrdir.get_branch_transport(cls)
1954
1970
@needs_write_lock
1955
1971
def set_last_revision_info(self, revno, revision_id):
1956
revision_id = osutils.safe_revision_id(revision_id)
1957
1972
if self._get_append_revisions_only():
1958
1973
self._check_history_violation(revision_id)
1959
1974
self._write_last_revision_info(revno, revision_id)
1960
1975
self._clear_cached_state()
1962
1977
def _check_history_violation(self, revision_id):
1963
last_revision = self.last_revision()
1964
if last_revision is None:
1978
last_revision = _mod_revision.ensure_null(self.last_revision())
1979
if _mod_revision.is_null(last_revision):
1966
1981
if last_revision not in self._lefthand_history(revision_id):
1967
1982
raise errors.AppendRevisionsOnlyViolation(self.base)
1991
2006
self._write_last_revision_info(len(history), last_revision)
1993
2008
@needs_write_lock
1994
def append_revision(self, *revision_ids):
1995
revision_ids = [osutils.safe_revision_id(r) for r in revision_ids]
1996
if len(revision_ids) == 0:
1998
prev_revno, prev_revision = self.last_revision_info()
1999
for revision in self.repository.get_revisions(revision_ids):
2000
if prev_revision == _mod_revision.NULL_REVISION:
2001
if revision.parent_ids != []:
2002
raise errors.NotLeftParentDescendant(self, prev_revision,
2003
revision.revision_id)
2005
if revision.parent_ids[0] != prev_revision:
2006
raise errors.NotLeftParentDescendant(self, prev_revision,
2007
revision.revision_id)
2008
prev_revision = revision.revision_id
2009
self.set_last_revision_info(prev_revno + len(revision_ids),
2013
2009
def _set_parent_location(self, url):
2014
2010
"""Set the parent branch"""
2015
2011
self._set_config_location('parent_location', url, make_relative=True)
2031
2027
if config.get_user_option('bound') != 'True':
2034
config.set_user_option('bound', 'False')
2030
config.set_user_option('bound', 'False', warn_masked=True)
2037
2033
self._set_config_location('bound_location', location,
2039
config.set_user_option('bound', 'True')
2035
config.set_user_option('bound', 'True', warn_masked=True)
2042
2038
def _get_bound_location(self, bound):
2080
2077
:param revision_id: The revision-id to truncate history at. May
2081
2078
be None to copy complete history.
2080
source_revno, source_revision_id = self.last_revision_info()
2083
2081
if revision_id is None:
2084
revno, revision_id = self.last_revision_info()
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
2086
2087
# To figure out the revno for a random revision, we need to build
2087
2088
# the revision history, and count its length.
2097
2098
return BasicTags(self)
2100
class BranchTestProviderAdapter(object):
2101
"""A tool to generate a suite testing multiple branch formats at once.
2103
This is done by copying the test once for each transport and injecting
2104
the transport_server, transport_readonly_server, and branch_format
2105
classes into each copy. Each copy is also given a new id() to make it
2109
def __init__(self, transport_server, transport_readonly_server, formats,
2110
vfs_transport_factory=None):
2111
self._transport_server = transport_server
2112
self._transport_readonly_server = transport_readonly_server
2113
self._formats = formats
2115
def adapt(self, test):
2116
result = TestSuite()
2117
for branch_format, bzrdir_format in self._formats:
2118
new_test = deepcopy(test)
2119
new_test.transport_server = self._transport_server
2120
new_test.transport_readonly_server = self._transport_readonly_server
2121
new_test.bzrdir_format = bzrdir_format
2122
new_test.branch_format = branch_format
2123
def make_new_test_id():
2124
# the format can be either a class or an instance
2125
name = getattr(branch_format, '__name__',
2126
branch_format.__class__.__name__)
2127
new_id = "%s(%s)" % (new_test.id(), name)
2128
return lambda: new_id
2129
new_test.id = make_new_test_id()
2130
result.addTest(new_test)
2134
2101
######################################################################
2135
2102
# results of operations