46
46
from bzrlib.decorators import needs_read_lock, needs_write_lock
47
47
from bzrlib.hooks import Hooks
48
from bzrlib import registry
48
49
from bzrlib.symbol_versioning import (
135
136
def open_containing(url, possible_transports=None):
136
137
"""Open an existing branch which contains url.
138
139
This probes for a branch at url, and searches upwards from there.
140
141
Basically we keep looking up until we find the control directory or
141
142
run into the root. If there isn't one, raises NotBranchError.
142
If there is one and it is either an unrecognised format or an unsupported
143
If there is one and it is either an unrecognised format or an unsupported
143
144
format, UnknownFormatError or UnsupportedFormatError are raised.
144
145
If there is one, it is returned, along with the unused portion of url.
147
148
possible_transports)
148
149
return control.open_branch(), relpath
151
def _push_should_merge_tags(self):
152
"""Should _basic_push merge this branch's tags into the target?
154
The default implementation returns False if this branch has no tags,
155
and True the rest of the time. Subclasses may override this.
157
return self.tags.supports_tags() and self.tags.get_tag_dict()
150
159
def get_config(self):
151
160
return BranchConfig(self)
174
183
def is_locked(self):
175
184
raise NotImplementedError(self.is_locked)
186
def _lefthand_history(self, revision_id, last_rev=None,
188
if 'evil' in debug.debug_flags:
189
mutter_callsite(4, "_lefthand_history scales with history.")
190
# stop_revision must be a descendant of last_revision
191
graph = self.repository.get_graph()
192
if last_rev is not None:
193
if not graph.is_ancestor(last_rev, revision_id):
194
# our previous tip is not merged into stop_revision
195
raise errors.DivergedBranches(self, other_branch)
196
# make a new revision history from the graph
197
parents_map = graph.get_parent_map([revision_id])
198
if revision_id not in parents_map:
199
raise errors.NoSuchRevision(self, revision_id)
200
current_rev_id = revision_id
202
check_not_reserved_id = _mod_revision.check_not_reserved_id
203
# Do not include ghosts or graph origin in revision_history
204
while (current_rev_id in parents_map and
205
len(parents_map[current_rev_id]) > 0):
206
check_not_reserved_id(current_rev_id)
207
new_history.append(current_rev_id)
208
current_rev_id = parents_map[current_rev_id][0]
209
parents_map = graph.get_parent_map([current_rev_id])
210
new_history.reverse()
177
213
def lock_write(self):
178
214
raise NotImplementedError(self.lock_write)
229
265
def revision_id_to_dotted_revno(self, revision_id):
230
266
"""Given a revision id, return its dotted revno.
232
268
:return: a tuple like (1,) or (400,1,3).
234
270
return self._do_revision_id_to_dotted_revno(revision_id)
398
434
def leave_lock_in_place(self):
399
435
"""Tell this branch object not to release the physical lock when this
400
436
object is unlocked.
402
438
If lock_write doesn't return a token, then this method is not supported.
404
440
self.control_files.leave_in_place()
464
500
def get_old_bound_location(self):
465
501
"""Return the URL of the branch we used to be bound to
467
503
raise errors.UpgradeRequired(self.base)
469
def get_commit_builder(self, parents, config=None, timestamp=None,
470
timezone=None, committer=None, revprops=None,
505
def get_commit_builder(self, parents, config=None, timestamp=None,
506
timezone=None, committer=None, revprops=None,
471
507
revision_id=None):
472
508
"""Obtain a CommitBuilder for this branch.
474
510
:param parents: Revision ids of the parents of the new revision.
475
511
:param config: Optional configuration to use.
476
512
:param timestamp: Optional timestamp recorded for commit.
483
519
if config is None:
484
520
config = self.get_config()
486
522
return self.repository.get_commit_builder(self, parents, config,
487
523
timestamp, timezone, committer, revprops, revision_id)
489
525
def get_master_branch(self, possible_transports=None):
490
526
"""Return the branch we are bound to.
492
528
:return: Either a Branch, or None
566
602
def _gen_revision_history(self):
567
603
"""Return sequence of revision hashes on to this branch.
569
605
Unlike revision_history, this method always regenerates or rereads the
570
606
revision history, i.e. it does not cache the result, so repeated calls
571
607
may be expensive.
573
609
Concrete subclasses should override this instead of revision_history so
574
610
that subclasses do not need to deal with caching logic.
576
612
This API is semi-public; it only for use by subclasses, all other code
577
613
should consider it to be private.
635
671
@deprecated_method(deprecated_in((1, 6, 0)))
636
672
def missing_revisions(self, other, stop_revision=None):
637
673
"""Return a list of new revisions that would perfectly fit.
639
675
If self and other have not diverged, return a list of the revisions
640
676
present in other, but missing from self.
684
720
last_rev = _mod_revision.ensure_null(self.last_revision())
685
721
# we fetch here so that we don't process data twice in the common
686
# case of having something to pull, and so that the check for
722
# case of having something to pull, and so that the check for
687
723
# already merged can operate on the just fetched graph, which will
688
724
# be cached in memory.
689
725
self.fetch(other, stop_revision)
751
787
def get_parent(self):
752
788
"""Return the parent location of the branch.
754
This is the default location for push/pull/missing. The usual
790
This is the default location for pull/missing. The usual
755
791
pattern is that the user can override it by specifying a
819
855
"""Set a new push location for this branch."""
820
856
raise NotImplementedError(self.set_push_location)
858
def _run_post_change_branch_tip_hooks(self, old_revno, old_revid):
859
"""Run the post_change_branch_tip hooks."""
860
hooks = Branch.hooks['post_change_branch_tip']
863
new_revno, new_revid = self.last_revision_info()
864
params = ChangeBranchTipParams(
865
self, old_revno, new_revno, old_revid, new_revid)
869
def _run_pre_change_branch_tip_hooks(self, new_revno, new_revid):
870
"""Run the pre_change_branch_tip hooks."""
871
hooks = Branch.hooks['pre_change_branch_tip']
874
old_revno, old_revid = self.last_revision_info()
875
params = ChangeBranchTipParams(
876
self, old_revno, new_revno, old_revid, new_revid)
880
except errors.TipChangeRejected:
883
exc_info = sys.exc_info()
884
hook_name = Branch.hooks.get_hook_name(hook)
885
raise errors.HookFailed(
886
'pre_change_branch_tip', hook_name, exc_info)
822
888
def set_parent(self, url):
823
889
raise NotImplementedError(self.set_parent)
825
891
@needs_write_lock
826
892
def update(self):
827
"""Synchronise this branch with the master branch if any.
893
"""Synchronise this branch with the master branch if any.
829
895
:return: None or the last_revision pivoted out during the update.
850
916
def clone(self, to_bzrdir, revision_id=None):
851
917
"""Clone this branch into to_bzrdir preserving all semantic values.
919
Most API users will want 'create_clone_on_transport', which creates a
920
new bzrdir and branch on the fly.
853
922
revision_id: if not None, the revision history in the new branch will
854
923
be truncated to end with revision_id.
899
968
revno = len(list(self.repository.iter_reverse_revision_history(
901
970
destination.set_last_revision_info(revno, revision_id)
904
973
def copy_content_into(self, destination, revision_id=None):
905
974
"""Copy the content of self into destination.
917
986
destination.set_parent(parent)
918
self.tags.merge_to(destination.tags)
987
if self._push_should_merge_tags():
988
self.tags.merge_to(destination.tags)
922
992
"""Check consistency of the branch.
924
994
In particular this checks that revisions given in the revision-history
925
do actually match up in the revision graph, and that they're all
995
do actually match up in the revision graph, and that they're all
926
996
present in the repository.
928
998
Callers will typically also want to check the repository.
930
1000
:return: A BranchCheckResult.
969
1039
format.set_branch_format(self._format)
1042
def create_clone_on_transport(self, to_transport, revision_id=None,
1044
"""Create a clone of this branch and its bzrdir.
1046
:param to_transport: The transport to clone onto.
1047
:param revision_id: The revision id to use as tip in the new branch.
1048
If None the tip is obtained from this branch.
1049
:param stacked_on: An optional URL to stack the clone on.
1051
# XXX: Fix the bzrdir API to allow getting the branch back from the
1052
# clone call. Or something. 20090224 RBC/spiv.
1053
dir_to = self.bzrdir.clone_on_transport(to_transport,
1054
revision_id=revision_id, stacked_on=stacked_on)
1055
return dir_to.open_branch()
972
1057
def create_checkout(self, to_location, revision_id=None,
973
1058
lightweight=False, accelerator_tree=None,
974
1059
hardlink=False):
975
1060
"""Create a checkout of a branch.
977
1062
:param to_location: The url to produce the checkout at
978
1063
:param revision_id: The revision to check out
979
1064
:param lightweight: If True, produce a lightweight checkout, otherwise,
998
1083
to_location, force_new_tree=False, format=format)
999
1084
checkout = checkout_branch.bzrdir
1000
1085
checkout_branch.bind(self)
1001
# pull up to the specified revision_id to set the initial
1086
# pull up to the specified revision_id to set the initial
1002
1087
# branch tip correctly, and seed it with history.
1003
1088
checkout_branch.pull(self, stop_revision=revision_id)
1004
1089
from_branch=None
1043
1128
"""Ensure that revision_b is a descendant of revision_a.
1045
1130
This is a helper function for update_revisions.
1047
1132
:raises: DivergedBranches if revision_b has diverged from revision_a.
1048
1133
:returns: True if revision_b is a descendant of revision_a.
1060
1145
def _revision_relations(self, revision_a, revision_b, graph):
1061
1146
"""Determine the relationship between two revisions.
1063
1148
:returns: One of: 'a_descends_from_b', 'b_descends_from_a', 'diverged'
1065
1150
heads = graph.heads([revision_a, revision_b])
1082
1167
* a format string,
1083
1168
* an open routine.
1085
Formats are placed in an dict by their format string for reference
1170
Formats are placed in an dict by their format string for reference
1086
1171
during branch opening. Its not required that these be instances, they
1087
can be classes themselves with class methods - it simply depends on
1172
can be classes themselves with class methods - it simply depends on
1088
1173
whether state is needed for a given format or not.
1090
1175
Once a format is deprecated, just deprecate the initialize and open
1091
methods on the format class. Do not deprecate the object, as the
1176
methods on the format class. Do not deprecate the object, as the
1092
1177
object will be created every time regardless.
1196
1281
"""Is this format supported?
1198
1283
Supported formats can be initialized and opened.
1199
Unsupported formats may not support initialization or committing or
1284
Unsupported formats may not support initialization or committing or
1200
1285
some other features depending on the reason for not being supported.
1289
def network_name(self):
1290
"""A simple byte string uniquely identifying this format for RPC calls.
1292
MetaDir branch formats use their disk format string to identify the
1293
repository over the wire. All in one formats such as bzr < 0.8, and
1294
foreign formats like svn/git and hg should use some marker which is
1295
unique and immutable.
1297
raise NotImplementedError(self.network_name)
1204
1299
def open(self, a_bzrdir, _found=False):
1205
1300
"""Return the branch object for a_bzrdir
1213
1308
def register_format(klass, format):
1309
"""Register a metadir format."""
1214
1310
klass._formats[format.get_format_string()] = format
1311
# Metadir formats have a network name of their format string.
1312
network_format_registry.register(format.get_format_string(), format)
1217
1315
def set_default_format(klass, format):
1260
1358
# (push_result)
1261
1359
# containing the members
1262
1360
# (source, local, master, old_revno, old_revid, new_revno, new_revid)
1263
# where local is the local target branch or None, master is the target
1361
# where local is the local target branch or None, master is the target
1264
1362
# master branch, and the rest should be self explanatory. The source
1265
1363
# is read locked and the target branches write locked. Source will
1266
1364
# be the local low-latency branch.
1270
1368
# (pull_result)
1271
1369
# containing the members
1272
1370
# (source, local, master, old_revno, old_revid, new_revno, new_revid)
1273
# where local is the local branch or None, master is the target
1371
# where local is the local branch or None, master is the target
1274
1372
# master branch, and the rest should be self explanatory. The source
1275
1373
# is read locked and the target branches write locked. The local
1276
1374
# branch is the low-latency branch.
1286
1384
# CommitBuilder.revision_tree() and hooks MUST NOT modify this tree
1287
1385
self['pre_commit'] = []
1288
1386
# invoked after a commit operation completes.
1289
# the api signature is
1387
# the api signature is
1290
1388
# (local, master, old_revno, old_revid, new_revno, new_revid)
1291
1389
# old_revid is NULL_REVISION for the first commit to a branch.
1292
1390
self['post_commit'] = []
1354
1452
def __eq__(self, other):
1355
1453
return self.__dict__ == other.__dict__
1357
1455
def __repr__(self):
1358
1456
return "<%s of %s from (%s, %s) to (%s, %s)>" % (
1359
self.__class__.__name__, self.branch,
1457
self.__class__.__name__, self.branch,
1360
1458
self.old_revno, self.old_revid, self.new_revno, self.new_revid)
1384
1482
super(BzrBranchFormat4, self).__init__()
1385
1483
self._matchingbzrdir = bzrdir.BzrDirFormat6()
1485
def network_name(self):
1486
"""The network name for this format is the control dirs disk label."""
1487
return self._matchingbzrdir.get_format_string()
1387
1489
def open(self, a_bzrdir, _found=False):
1388
1490
"""Return the branch object for a_bzrdir
1409
1511
"""What class to instantiate on open calls."""
1410
1512
raise NotImplementedError(self._branch_class)
1514
def network_name(self):
1515
"""A simple byte string uniquely identifying this format for RPC calls.
1517
Metadir branch formats use their format string.
1519
return self.get_format_string()
1412
1521
def open(self, a_bzrdir, _found=False):
1413
1522
"""Return the branch object for a_bzrdir.
1463
1572
def get_format_description(self):
1464
1573
"""See BranchFormat.get_format_description()."""
1465
1574
return "Branch format 5"
1467
1576
def initialize(self, a_bzrdir):
1468
1577
"""Create a branch of this format in a_bzrdir."""
1469
1578
utf8_files = [('revision-history', ''),
1743
network_format_registry = registry.FormatRegistry()
1744
"""Registry of formats indexed by their network name.
1746
The network name for a repository format is an identifier that can be used when
1747
referring to formats with smart server operations. See
1748
BranchFormat.network_name() for more detail.
1634
1752
# formats which have no format string are not discoverable
1635
1753
# and not independently creatable, so are not registered.
1636
1754
__format5 = BzrBranchFormat5()
1642
1760
BranchFormat.register_format(__format7)
1643
1761
BranchFormat.set_default_format(__format6)
1644
1762
_legacy_formats = [BzrBranchFormat4(),
1764
network_format_registry.register(
1765
_legacy_formats[0].network_name(), _legacy_formats[0])
1647
1768
class BzrBranch(Branch):
1648
1769
"""A branch stored in the actual filesystem.
1651
1772
really matter if it's on an nfs/smb/afs/coda/... share, as long as
1652
1773
it's writable, and can be accessed via the normal filesystem API.
1654
:ivar _transport: Transport for file operations on this branch's
1775
:ivar _transport: Transport for file operations on this branch's
1655
1776
control files, typically pointing to the .bzr/branch directory.
1656
1777
:ivar repository: Repository for this branch.
1657
:ivar base: The url of the base directory for this branch; the one
1778
:ivar base: The url of the base directory for this branch; the one
1658
1779
containing the .bzr directory.
1661
1782
def __init__(self, _format=None,
1662
1783
_control_files=None, a_bzrdir=None, _repository=None):
1663
1784
"""Create new branch object at a particular location."""
1717
1838
if not self.control_files.is_locked():
1718
1839
# we just released the lock
1719
1840
self._clear_cached_state()
1721
1842
def peek_lock_mode(self):
1722
1843
if self.control_files._lock_count == 0:
1795
1916
new_history = rev.get_history(self.repository)[1:]
1796
1917
destination.set_revision_history(new_history)
1798
def _run_pre_change_branch_tip_hooks(self, new_revno, new_revid):
1799
"""Run the pre_change_branch_tip hooks."""
1800
hooks = Branch.hooks['pre_change_branch_tip']
1803
old_revno, old_revid = self.last_revision_info()
1804
params = ChangeBranchTipParams(
1805
self, old_revno, new_revno, old_revid, new_revid)
1809
except errors.TipChangeRejected:
1812
exc_info = sys.exc_info()
1813
hook_name = Branch.hooks.get_hook_name(hook)
1814
raise errors.HookFailed(
1815
'pre_change_branch_tip', hook_name, exc_info)
1817
def _run_post_change_branch_tip_hooks(self, old_revno, old_revid):
1818
"""Run the post_change_branch_tip hooks."""
1819
hooks = Branch.hooks['post_change_branch_tip']
1822
new_revno, new_revid = self.last_revision_info()
1823
params = ChangeBranchTipParams(
1824
self, old_revno, new_revno, old_revid, new_revid)
1828
1919
@needs_write_lock
1829
1920
def set_last_revision_info(self, revno, revision_id):
1830
1921
"""Set the last revision of this branch.
1833
1924
for this revision id.
1835
1926
It may be possible to set the branch last revision to an id not
1836
present in the repository. However, branches can also be
1927
present in the repository. However, branches can also be
1837
1928
configured to check constraints on history, in which case this may not
1856
def _lefthand_history(self, revision_id, last_rev=None,
1858
if 'evil' in debug.debug_flags:
1859
mutter_callsite(4, "_lefthand_history scales with history.")
1860
# stop_revision must be a descendant of last_revision
1861
graph = self.repository.get_graph()
1862
if last_rev is not None:
1863
if not graph.is_ancestor(last_rev, revision_id):
1864
# our previous tip is not merged into stop_revision
1865
raise errors.DivergedBranches(self, other_branch)
1866
# make a new revision history from the graph
1867
parents_map = graph.get_parent_map([revision_id])
1868
if revision_id not in parents_map:
1869
raise errors.NoSuchRevision(self, revision_id)
1870
current_rev_id = revision_id
1872
check_not_reserved_id = _mod_revision.check_not_reserved_id
1873
# Do not include ghosts or graph origin in revision_history
1874
while (current_rev_id in parents_map and
1875
len(parents_map[current_rev_id]) > 0):
1876
check_not_reserved_id(current_rev_id)
1877
new_history.append(current_rev_id)
1878
current_rev_id = parents_map[current_rev_id][0]
1879
parents_map = graph.get_parent_map([current_rev_id])
1880
new_history.reverse()
1883
1947
@needs_write_lock
1884
1948
def generate_revision_history(self, revision_id, last_rev=None,
1885
1949
other_branch=None):
1904
1968
_override_hook_target=None):
1905
1969
"""See Branch.pull.
1907
:param _hook_master: Private parameter - set the branch to
1971
:param _hook_master: Private parameter - set the branch to
1908
1972
be supplied as the master to pull hooks.
1909
1973
:param run_hooks: Private parameter - if false, this branch
1910
1974
is being called because it's the master of the primary branch,
1958
2022
This is the basic concrete implementation of push()
1960
2024
:param _override_hook_source_branch: If specified, run
1961
the hooks passing this Branch as the source, rather than self.
2025
the hooks passing this Branch as the source, rather than self.
1962
2026
This is for use of RemoteBranch, where push is delegated to the
1963
underlying vfs-based Branch.
2027
underlying vfs-based Branch.
1965
2029
# TODO: Public option to disable running hooks - should be trivial but
1974
2038
_override_hook_source_branch=None):
1975
2039
"""Push from self into target, and into target's master if any.
1977
This is on the base BzrBranch class even though it doesn't support
2041
This is on the base BzrBranch class even though it doesn't support
1978
2042
bound branches because the *target* might be bound.
1980
2044
def _run_hooks():
2035
2099
result.new_revno, result.new_revid = target.last_revision_info()
2038
def _push_should_merge_tags(self):
2039
"""Should _basic_push merge this branch's tags into the target?
2041
The default implementation returns False if this branch has no tags,
2042
and True the rest of the time. Subclasses may override this.
2044
return self.tags.supports_tags() and self.tags.get_tag_dict()
2046
2102
def get_parent(self):
2047
2103
"""See Branch.get_parent."""
2048
2104
parent = self._get_parent_location()
2106
2162
run_hooks=True, possible_transports=None,
2107
2163
_override_hook_target=None):
2108
2164
"""Pull from source into self, updating my master if any.
2110
2166
:param run_hooks: Private parameter - if false, this branch
2111
2167
is being called because it's the master of the primary branch,
2112
2168
so it should not run its hooks.
2139
2195
@needs_read_lock
2140
2196
def get_master_branch(self, possible_transports=None):
2141
2197
"""Return the branch we are bound to.
2143
2199
:return: Either a Branch, or None
2145
2201
This could memoise the branch, but if thats done
2181
2237
check for divergence to raise an error when the branches are not
2182
2238
either the same, or one a prefix of the other. That behaviour may not
2183
2239
be useful, so that check may be removed in future.
2185
2241
:param other: The branch to bind to
2186
2242
:type other: Branch
2207
2263
@needs_write_lock
2208
2264
def update(self, possible_transports=None):
2209
"""Synchronise this branch with the master branch if any.
2265
"""Synchronise this branch with the master branch if any.
2211
2267
:return: None or the last_revision that was pivoted out during the
2304
2360
def _synchronize_history(self, destination, revision_id):
2305
2361
"""Synchronize last revision and revision history between branches.
2307
2363
:see: Branch._synchronize_history
2309
2365
# XXX: The base Branch has a fast implementation of this method based