14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19
from cStringIO import StringIO
21
21
from bzrlib.lazy_import import lazy_import
22
22
lazy_import(globals(), """
23
from itertools import chain
24
24
from bzrlib import (
28
config as _mod_config,
37
revision as _mod_revision,
43
from bzrlib.config import BranchConfig, TransportConfig
44
from bzrlib.tag import (
29
config as _mod_config,
38
revision as _mod_revision,
46
from bzrlib.i18n import gettext, ngettext
50
49
from bzrlib import (
66
65
from bzrlib.trace import mutter, mutter_callsite, note, is_quiet
69
BZR_BRANCH_FORMAT_4 = "Bazaar-NG branch, format 0.0.4\n"
70
BZR_BRANCH_FORMAT_5 = "Bazaar-NG branch, format 5\n"
71
BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n"
74
68
class Branch(controldir.ControlComponent):
75
69
"""Branch holding a history of revisions.
93
87
def user_transport(self):
94
88
return self.bzrdir.user_transport
96
def __init__(self, *ignored, **ignored_too):
90
def __init__(self, possible_transports=None):
97
91
self.tags = self._format.make_tags(self)
98
92
self._revision_history_cache = None
99
93
self._revision_id_to_revno_cache = None
103
97
self._last_revision_info_cache = None
104
98
self._master_branch_cache = None
105
99
self._merge_sorted_revisions_cache = None
100
self._open_hook(possible_transports)
107
101
hooks = Branch.hooks['open']
108
102
for hook in hooks:
111
def _open_hook(self):
105
def _open_hook(self, possible_transports):
112
106
"""Called by init to allow simpler extension of the base class."""
114
def _activate_fallback_location(self, url):
108
def _activate_fallback_location(self, url, possible_transports):
115
109
"""Activate the branch/repository from url as a fallback repository."""
116
110
for existing_fallback_repo in self.repository._fallback_repositories:
117
111
if existing_fallback_repo.user_url == url:
118
112
# This fallback is already configured. This probably only
119
# happens because BzrDir.sprout is a horrible mess. To avoid
113
# happens because ControlDir.sprout is a horrible mess. To avoid
120
114
# confusing _unstack we don't add this a second time.
121
115
mutter('duplicate activation of fallback %r on %r', url, self)
123
repo = self._get_fallback_repository(url)
117
repo = self._get_fallback_repository(url, possible_transports)
124
118
if repo.has_same_location(self.repository):
125
119
raise errors.UnstackableLocationError(self.user_url, url)
126
120
self.repository.add_fallback_repository(repo)
180
174
For instance, if the branch is at URL/.bzr/branch,
181
175
Branch.open(URL) -> a Branch instance.
183
control = bzrdir.BzrDir.open(base, _unsupported,
177
control = controldir.ControlDir.open(base, _unsupported,
184
178
possible_transports=possible_transports)
185
return control.open_branch(unsupported=_unsupported)
179
return control.open_branch(unsupported=_unsupported,
180
possible_transports=possible_transports)
188
def open_from_transport(transport, name=None, _unsupported=False):
183
def open_from_transport(transport, name=None, _unsupported=False,
184
possible_transports=None):
189
185
"""Open the branch rooted at transport"""
190
control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
191
return control.open_branch(name=name, unsupported=_unsupported)
186
control = controldir.ControlDir.open_from_transport(transport, _unsupported)
187
return control.open_branch(name=name, unsupported=_unsupported,
188
possible_transports=possible_transports)
194
191
def open_containing(url, possible_transports=None):
202
199
format, UnknownFormatError or UnsupportedFormatError are raised.
203
200
If there is one, it is returned, along with the unused portion of url.
205
control, relpath = bzrdir.BzrDir.open_containing(url,
202
control, relpath = controldir.ControlDir.open_containing(url,
206
203
possible_transports)
207
return control.open_branch(), relpath
204
branch = control.open_branch(possible_transports=possible_transports)
205
return (branch, relpath)
209
207
def _push_should_merge_tags(self):
210
208
"""Should _basic_push merge this branch's tags into the target?
223
221
:return: A bzrlib.config.BranchConfig.
225
return BranchConfig(self)
223
return _mod_config.BranchConfig(self)
225
def get_config_stack(self):
226
"""Get a bzrlib.config.BranchStack for this Branch.
228
This can then be used to get and set configuration options for the
231
:return: A bzrlib.config.BranchStack.
233
return _mod_config.BranchStack(self)
227
235
def _get_config(self):
228
236
"""Get the concrete config for just the config in this branch.
237
245
raise NotImplementedError(self._get_config)
239
def _get_fallback_repository(self, url):
247
def _get_fallback_repository(self, url, possible_transports):
240
248
"""Get the repository we fallback to at url."""
241
249
url = urlutils.join(self.base, url)
242
a_branch = Branch.open(url,
243
possible_transports=[self.bzrdir.root_transport])
250
a_branch = Branch.open(url, possible_transports=possible_transports)
244
251
return a_branch.repository
652
659
raise errors.UpgradeRequired(self.user_url)
661
def get_append_revisions_only(self):
662
"""Whether it is only possible to append revisions to the history.
664
if not self._format.supports_set_append_revisions_only():
666
return self.get_config_stack().get('append_revisions_only')
654
668
def set_append_revisions_only(self, enabled):
655
669
if not self._format.supports_set_append_revisions_only():
656
670
raise errors.UpgradeRequired(self.user_url)
661
self.get_config().set_user_option('append_revisions_only', value,
671
self.get_config_stack().set('append_revisions_only', enabled)
664
673
def set_reference_info(self, file_id, tree_path, branch_location):
665
674
"""Set the branch location to use for a tree reference."""
695
704
raise errors.UpgradeRequired(self.user_url)
697
def get_commit_builder(self, parents, config=None, timestamp=None,
706
def get_commit_builder(self, parents, config_stack=None, timestamp=None,
698
707
timezone=None, committer=None, revprops=None,
699
708
revision_id=None, lossy=False):
700
709
"""Obtain a CommitBuilder for this branch.
710
719
represented, when pushing to a foreign VCS
714
config = self.get_config()
722
if config_stack is None:
723
config_stack = self.get_config_stack()
716
return self.repository.get_commit_builder(self, parents, config,
725
return self.repository.get_commit_builder(self, parents, config_stack,
717
726
timestamp, timezone, committer, revprops, revision_id,
736
@deprecated_method(deprecated_in((2, 5, 0)))
727
737
def get_revision_delta(self, revno):
728
738
"""Return the delta for one revision.
730
740
The delta is relative to its mainline predecessor, or the
731
741
empty tree for revision 1.
733
rh = self.revision_history()
734
if not (1 <= revno <= len(rh)):
744
revid = self.get_rev_id(revno)
745
except errors.NoSuchRevision:
735
746
raise errors.InvalidRevisionNumber(revno)
736
return self.repository.get_revision_delta(rh[revno-1])
747
return self.repository.get_revision_delta(revid)
738
749
def get_stacked_on_url(self):
739
750
"""Get the URL this branch is stacked against.
785
796
other_branch=None):
786
797
"""See Branch.generate_revision_history"""
787
798
graph = self.repository.get_graph()
799
(last_revno, last_revid) = self.last_revision_info()
788
800
known_revision_ids = [
789
self.last_revision_info(),
801
(last_revid, last_revno),
790
802
(_mod_revision.NULL_REVISION, 0),
792
804
if last_rev is not None:
869
882
# stream from one of them to the other. This does mean doing
870
883
# separate SSH connection setup, but unstacking is not a
871
884
# common operation so it's tolerable.
872
new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
885
new_bzrdir = controldir.ControlDir.open(
886
self.bzrdir.root_transport.base)
873
887
new_repository = new_bzrdir.find_repository()
874
888
if new_repository._fallback_repositories:
875
889
raise AssertionError("didn't expect %r to have "
918
932
tags_to_fetch = set(self.tags.get_reverse_tag_dict())
919
933
except errors.TagsNotSupported:
920
934
tags_to_fetch = set()
921
fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
935
fetch_spec = vf_search.NotInOtherForRevs(self.repository,
922
936
old_repository, required_ids=[self.last_revision()],
923
937
if_present_ids=tags_to_fetch, find_ghosts=True).execute()
924
938
self.repository.fetch(old_repository, fetch_spec=fetch_spec)
1293
1311
if repository_policy is not None:
1294
1312
repository_policy.configure_branch(result)
1295
1313
self.copy_content_into(result, revision_id=revision_id)
1296
master_branch = self.get_master_branch()
1297
if master_branch is None:
1314
master_url = self.get_bound_location()
1315
if master_url is None:
1298
1316
result.set_parent(self.bzrdir.root_transport.base)
1300
result.set_parent(master_branch.bzrdir.root_transport.base)
1318
result.set_parent(master_url)
1302
1320
result.unlock()
1377
1395
# TODO: We should probably also check that self.revision_history
1378
1396
# matches the repository for older branch formats.
1379
1397
# If looking for the code that cross-checks repository parents against
1380
# the iter_reverse_revision_history output, that is now a repository
1398
# the Graph.iter_lefthand_ancestry output, that is now a repository
1381
1399
# specific check.
1384
def _get_checkout_format(self):
1402
def _get_checkout_format(self, lightweight=False):
1385
1403
"""Return the most suitable metadir for a checkout of this branch.
1386
1404
Weaves are used if this branch's repository uses weaves.
1434
1452
t = transport.get_transport(to_location)
1435
1453
t.ensure_base()
1454
format = self._get_checkout_format(lightweight=lightweight)
1436
1455
if lightweight:
1437
format = self._get_checkout_format()
1438
1456
checkout = format.initialize_on_transport(t)
1439
1457
from_branch = BranchReferenceFormat().initialize(checkout,
1440
1458
target_branch=self)
1442
format = self._get_checkout_format()
1443
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
1460
checkout_branch = controldir.ControlDir.create_branch_convenience(
1444
1461
to_location, force_new_tree=False, format=format)
1445
1462
checkout = checkout_branch.bzrdir
1446
1463
checkout_branch.bind(self)
1545
1562
# For bzr native formats must_fetch is just the tip, and if_present_fetch
1546
1563
# are the tags.
1547
1564
must_fetch = set([self.last_revision()])
1549
if_present_fetch = set(self.tags.get_reverse_tag_dict())
1550
except errors.TagsNotSupported:
1551
if_present_fetch = set()
1565
if_present_fetch = set()
1566
c = self.get_config()
1567
include_tags = c.get_user_option_as_bool('branch.fetch_tags',
1571
if_present_fetch = set(self.tags.get_reverse_tag_dict())
1572
except errors.TagsNotSupported:
1552
1574
must_fetch.discard(_mod_revision.NULL_REVISION)
1553
1575
if_present_fetch.discard(_mod_revision.NULL_REVISION)
1554
1576
return must_fetch, if_present_fetch
1581
1601
return not (self == other)
1584
def find_format(klass, a_bzrdir, name=None):
1585
"""Return the format for the branch object in a_bzrdir."""
1587
transport = a_bzrdir.get_branch_transport(None, name=name)
1588
format_string = transport.get_bytes("format")
1589
return format_registry.get(format_string)
1590
except errors.NoSuchFile:
1591
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
1593
raise errors.UnknownFormatError(format=format_string, kind='branch')
1596
1604
@deprecated_method(deprecated_in((2, 4, 0)))
1597
1605
def get_default_format(klass):
1598
1606
"""Return the current default format."""
1609
1617
return format_registry._get_all()
1611
def get_reference(self, a_bzrdir, name=None):
1612
"""Get the target reference of the branch in a_bzrdir.
1619
def get_reference(self, controldir, name=None):
1620
"""Get the target reference of the branch in controldir.
1614
1622
format probing must have been completed before calling
1615
1623
this method - it is assumed that the format of the branch
1616
in a_bzrdir is correct.
1624
in controldir is correct.
1618
:param a_bzrdir: The bzrdir to get the branch data from.
1626
:param controldir: The controldir to get the branch data from.
1619
1627
:param name: Name of the colocated branch to fetch
1620
1628
:return: None if the branch is not a reference branch.
1625
def set_reference(self, a_bzrdir, name, to_branch):
1626
"""Set the target reference of the branch in a_bzrdir.
1633
def set_reference(self, controldir, name, to_branch):
1634
"""Set the target reference of the branch in controldir.
1628
1636
format probing must have been completed before calling
1629
1637
this method - it is assumed that the format of the branch
1630
in a_bzrdir is correct.
1638
in controldir is correct.
1632
:param a_bzrdir: The bzrdir to set the branch reference for.
1640
:param controldir: The controldir to set the branch reference for.
1633
1641
:param name: Name of colocated branch to set, None for default
1634
1642
:param to_branch: branch that the checkout is to reference
1636
1644
raise NotImplementedError(self.set_reference)
1638
def get_format_string(self):
1639
"""Return the ASCII format string that identifies this format."""
1640
raise NotImplementedError(self.get_format_string)
1642
1646
def get_format_description(self):
1643
1647
"""Return the short format description for this format."""
1644
1648
raise NotImplementedError(self.get_format_description)
1646
def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
1650
def _run_post_branch_init_hooks(self, controldir, name, branch):
1647
1651
hooks = Branch.hooks['post_branch_init']
1650
params = BranchInitHookParams(self, a_bzrdir, name, branch)
1654
params = BranchInitHookParams(self, controldir, name, branch)
1651
1655
for hook in hooks:
1654
def initialize(self, a_bzrdir, name=None, repository=None):
1655
"""Create a branch of this format in a_bzrdir.
1658
def initialize(self, controldir, name=None, repository=None,
1659
append_revisions_only=None):
1660
"""Create a branch of this format in controldir.
1657
1662
:param name: Name of the colocated branch to create.
1659
1664
raise NotImplementedError(self.initialize)
1692
1697
raise NotImplementedError(self.network_name)
1694
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
1695
found_repository=None):
1696
"""Return the branch object for a_bzrdir
1699
def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
1700
found_repository=None, possible_transports=None):
1701
"""Return the branch object for controldir.
1698
:param a_bzrdir: A BzrDir that contains a branch.
1703
:param controldir: A ControlDir that contains a branch.
1699
1704
:param name: Name of colocated branch to open
1700
1705
:param _found: a private parameter, do not use it. It is used to
1701
1706
indicate if format probing has already be done.
1743
1748
"""True if this format supports tags stored in the branch"""
1744
1749
return False # by default
1751
def tags_are_versioned(self):
1752
"""Whether the tag container for this branch versions tags."""
1755
def supports_tags_referencing_ghosts(self):
1756
"""True if tags can reference ghost revisions."""
1747
1760
class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
1748
1761
"""A factory for a BranchFormat object, permitting simple lazy registration.
1922
1935
branch, which refer to the original branch.
1925
def __init__(self, format, a_bzrdir, name, branch):
1938
def __init__(self, format, controldir, name, branch):
1926
1939
"""Create a group of BranchInitHook parameters.
1928
1941
:param format: the branch format
1929
:param a_bzrdir: the BzrDir where the branch will be/has been
1942
:param controldir: the ControlDir where the branch will be/has been
1931
1944
:param name: name of colocated branch, if any (or None)
1932
1945
:param branch: the branch created
1961
1974
def __init__(self, control_dir, to_branch, force, revision_id):
1962
1975
"""Create a group of SwitchHook parameters.
1964
:param control_dir: BzrDir of the checkout to change
1977
:param control_dir: ControlDir of the checkout to change
1965
1978
:param to_branch: branch that the checkout is to reference
1966
1979
:param force: skip the check for local commits in a heavy checkout
1967
1980
:param revision_id: revision ID to switch to (or None)
1980
1993
self.revision_id)
1983
class BranchFormatMetadir(BranchFormat):
1984
"""Common logic for meta-dir based branch formats."""
1996
class BranchFormatMetadir(bzrdir.BzrDirMetaComponentFormat, BranchFormat):
1997
"""Base class for branch formats that live in meta directories.
2001
BranchFormat.__init__(self)
2002
bzrdir.BzrDirMetaComponentFormat.__init__(self)
2005
def find_format(klass, controldir, name=None):
2006
"""Return the format for the branch object in controldir."""
2008
transport = controldir.get_branch_transport(None, name=name)
2009
except errors.NoSuchFile:
2010
raise errors.NotBranchError(path=name, bzrdir=controldir)
2012
format_string = transport.get_bytes("format")
2013
except errors.NoSuchFile:
2014
raise errors.NotBranchError(path=transport.base, bzrdir=controldir)
2015
return klass._find_format(format_registry, 'branch', format_string)
1986
2017
def _branch_class(self):
1987
2018
"""What class to instantiate on open calls."""
1988
2019
raise NotImplementedError(self._branch_class)
2021
def _get_initial_config(self, append_revisions_only=None):
2022
if append_revisions_only:
2023
return "append_revisions_only = True\n"
2025
# Avoid writing anything if append_revisions_only is disabled,
2026
# as that is the default.
1990
2029
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1991
2030
repository=None):
1992
2031
"""Initialize a branch in a bzrdir, with specified files
2016
2055
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2019
def network_name(self):
2020
"""A simple byte string uniquely identifying this format for RPC calls.
2022
Metadir branch formats use their format string.
2024
return self.get_format_string()
2026
2058
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2027
found_repository=None):
2059
found_repository=None, possible_transports=None):
2028
2060
"""See BranchFormat.open()."""
2030
format = BranchFormat.find_format(a_bzrdir, name=name)
2062
format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
2031
2063
if format.__class__ != self.__class__:
2032
2064
raise AssertionError("wrong format %r found for %r" %
2033
2065
(format, self))
2043
2075
a_bzrdir=a_bzrdir,
2044
2076
_repository=found_repository,
2045
ignore_fallbacks=ignore_fallbacks)
2077
ignore_fallbacks=ignore_fallbacks,
2078
possible_transports=possible_transports)
2046
2079
except errors.NoSuchFile:
2047
2080
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2050
super(BranchFormatMetadir, self).__init__()
2051
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
2052
self._matchingbzrdir.set_branch_format(self)
2083
def _matchingbzrdir(self):
2084
ret = bzrdir.BzrDirMetaFormat1()
2085
ret.set_branch_format(self)
2054
2088
def supports_tags(self):
2082
2117
"""See BranchFormat.get_format_description()."""
2083
2118
return "Branch format 5"
2085
def initialize(self, a_bzrdir, name=None, repository=None):
2120
def initialize(self, a_bzrdir, name=None, repository=None,
2121
append_revisions_only=None):
2086
2122
"""Create a branch of this format in a_bzrdir."""
2123
if append_revisions_only:
2124
raise errors.UpgradeRequired(a_bzrdir.user_url)
2087
2125
utf8_files = [('revision-history', ''),
2088
2126
('branch-name', ''),
2115
2154
"""See BranchFormat.get_format_description()."""
2116
2155
return "Branch format 6"
2118
def initialize(self, a_bzrdir, name=None, repository=None):
2157
def initialize(self, a_bzrdir, name=None, repository=None,
2158
append_revisions_only=None):
2119
2159
"""Create a branch of this format in a_bzrdir."""
2120
2160
utf8_files = [('last-revision', '0 null:\n'),
2121
('branch.conf', ''),
2162
self._get_initial_config(append_revisions_only)),
2124
2165
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2126
2167
def make_tags(self, branch):
2127
2168
"""See bzrlib.branch.BranchFormat.make_tags()."""
2128
return BasicTags(branch)
2169
return _mod_tag.BasicTags(branch)
2130
2171
def supports_set_append_revisions_only(self):
2145
2187
"""See BranchFormat.get_format_description()."""
2146
2188
return "Branch format 8"
2148
def initialize(self, a_bzrdir, name=None, repository=None):
2190
def initialize(self, a_bzrdir, name=None, repository=None,
2191
append_revisions_only=None):
2149
2192
"""Create a branch of this format in a_bzrdir."""
2150
2193
utf8_files = [('last-revision', '0 null:\n'),
2151
('branch.conf', ''),
2195
self._get_initial_config(append_revisions_only)),
2153
2197
('references', '')
2176
2220
This format was introduced in bzr 1.6.
2179
def initialize(self, a_bzrdir, name=None, repository=None):
2223
def initialize(self, a_bzrdir, name=None, repository=None,
2224
append_revisions_only=None):
2180
2225
"""Create a branch of this format in a_bzrdir."""
2181
2226
utf8_files = [('last-revision', '0 null:\n'),
2182
('branch.conf', ''),
2228
self._get_initial_config(append_revisions_only)),
2185
2231
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2204
2251
def make_tags(self, branch):
2205
2252
"""See bzrlib.branch.BranchFormat.make_tags()."""
2206
return BasicTags(branch)
2253
return _mod_tag.BasicTags(branch)
2208
2255
supports_reference_locations = False
2211
class BranchReferenceFormat(BranchFormat):
2258
class BranchReferenceFormat(BranchFormatMetadir):
2212
2259
"""Bzr branch reference format.
2214
2261
Branch references are used in implementing checkouts, they
2238
2286
location = transport.put_bytes('location', to_branch.base)
2240
2288
def initialize(self, a_bzrdir, name=None, target_branch=None,
2289
repository=None, append_revisions_only=None):
2242
2290
"""Create a branch of this format in a_bzrdir."""
2243
2291
if target_branch is None:
2244
2292
# this format does not implement branch itself, thus the implicit
2245
2293
# creation contract must see it as uninitializable
2246
2294
raise errors.UninitializableFormat(self)
2247
2295
mutter('creating branch reference in %s', a_bzrdir.user_url)
2296
if a_bzrdir._format.fixed_components:
2297
raise errors.IncompatibleFormat(self, a_bzrdir._format)
2248
2298
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2249
2299
branch_transport.put_bytes('location',
2250
target_branch.bzrdir.user_url)
2300
target_branch.user_url)
2251
2301
branch_transport.put_bytes('format', self.get_format_string())
2252
2302
branch = self.open(
2253
2303
a_bzrdir, name, _found=True,
2255
2305
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2259
super(BranchReferenceFormat, self).__init__()
2260
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
2261
self._matchingbzrdir.set_branch_format(self)
2263
2308
def _make_reference_clone_function(format, a_branch):
2264
2309
"""Create a clone() routine for a branch dynamically."""
2265
2310
def clone(to_bzrdir, revision_id=None,
2288
2333
:param possible_transports: An optional reusable transports list.
2291
format = BranchFormat.find_format(a_bzrdir, name=name)
2336
format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
2292
2337
if format.__class__ != self.__class__:
2293
2338
raise AssertionError("wrong format %r found for %r" %
2294
2339
(format, self))
2295
2340
if location is None:
2296
2341
location = self.get_reference(a_bzrdir, name)
2297
real_bzrdir = bzrdir.BzrDir.open(
2342
real_bzrdir = controldir.ControlDir.open(
2298
2343
location, possible_transports=possible_transports)
2299
2344
result = real_bzrdir.open_branch(name=name,
2300
ignore_fallbacks=ignore_fallbacks)
2345
ignore_fallbacks=ignore_fallbacks,
2346
possible_transports=possible_transports)
2301
2347
# this changes the behaviour of result.clone to create a new reference
2302
2348
# rather than a copy of the content of the branch.
2303
2349
# I did not use a proxy object because that needs much more extensive
2385
2431
def __init__(self, _format=None,
2386
2432
_control_files=None, a_bzrdir=None, name=None,
2387
_repository=None, ignore_fallbacks=False):
2433
_repository=None, ignore_fallbacks=False,
2434
possible_transports=None):
2388
2435
"""Create new branch object at a particular location."""
2389
2436
if a_bzrdir is None:
2390
2437
raise ValueError('a_bzrdir must be supplied')
2392
2439
self.bzrdir = a_bzrdir
2393
self._base = self.bzrdir.transport.clone('..').base
2440
self._user_transport = self.bzrdir.transport.clone('..')
2441
if name is not None:
2442
self._user_transport.set_segment_parameter(
2443
"branch", urlutils.escape(name))
2444
self._base = self._user_transport.base
2394
2445
self.name = name
2395
# XXX: We should be able to just do
2396
# self.base = self.bzrdir.root_transport.base
2397
# but this does not quite work yet -- mbp 20080522
2398
2446
self._format = _format
2399
2447
if _control_files is None:
2400
2448
raise ValueError('BzrBranch _control_files is None')
2401
2449
self.control_files = _control_files
2402
2450
self._transport = _control_files._transport
2403
2451
self.repository = _repository
2404
Branch.__init__(self)
2452
Branch.__init__(self, possible_transports)
2406
2454
def __str__(self):
2407
if self.name is None:
2408
return '%s(%s)' % (self.__class__.__name__, self.user_url)
2410
return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
2455
return '%s(%s)' % (self.__class__.__name__, self.user_url)
2413
2457
__repr__ = __str__
2419
2463
base = property(_get_base, doc="The URL for the root of this branch.")
2466
def user_transport(self):
2467
return self._user_transport
2421
2469
def _get_config(self):
2422
return TransportConfig(self._transport, 'branch.conf')
2470
return _mod_config.TransportConfig(self._transport, 'branch.conf')
2472
def _get_config_store(self):
2473
return _mod_config.BranchStore(self)
2424
2475
def is_locked(self):
2425
2476
return self.control_files.is_locked()
2506
2557
raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2507
2558
revision_id = _mod_revision.ensure_null(revision_id)
2508
2559
old_revno, old_revid = self.last_revision_info()
2509
if self._get_append_revisions_only():
2560
if self.get_append_revisions_only():
2510
2561
self._check_history_violation(revision_id)
2511
2562
self._run_pre_change_branch_tip_hooks(revno, revision_id)
2512
2563
self._write_last_revision_info(revno, revision_id)
2767
2818
class BzrBranch8(BzrBranch):
2768
2819
"""A branch that stores tree-reference locations."""
2770
def _open_hook(self):
2821
def _open_hook(self, possible_transports=None):
2771
2822
if self._ignore_fallbacks:
2824
if possible_transports is None:
2825
possible_transports = [self.bzrdir.root_transport]
2774
2827
url = self.get_stacked_on_url()
2775
2828
except (errors.UnstackableRepositoryFormat, errors.NotStacked,
2783
2836
raise AssertionError(
2784
2837
"'transform_fallback_location' hook %s returned "
2785
2838
"None, not a URL." % hook_name)
2786
self._activate_fallback_location(url)
2839
self._activate_fallback_location(url,
2840
possible_transports=possible_transports)
2788
2842
def __init__(self, *args, **kwargs):
2789
2843
self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
2989
3039
except errors.RevisionNotPresent, e:
2990
3040
raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
2991
3041
index = len(self._partial_revision_history_cache) - 1
3043
raise errors.NoSuchRevision(self, revision_id)
2992
3044
if self._partial_revision_history_cache[index] != revision_id:
2993
3045
raise errors.NoSuchRevision(self, revision_id)
2994
3046
return self.revno() - index
3057
3110
return self.new_revno - self.old_revno
3059
3112
def report(self, to_file):
3113
tag_conflicts = getattr(self, "tag_conflicts", None)
3114
tag_updates = getattr(self, "tag_updates", None)
3060
3115
if not is_quiet():
3061
if self.old_revid == self.new_revid:
3062
to_file.write('No revisions to pull.\n')
3116
if self.old_revid != self.new_revid:
3064
3117
to_file.write('Now on revision %d.\n' % self.new_revno)
3119
to_file.write('%d tag(s) updated.\n' % len(tag_updates))
3120
if self.old_revid == self.new_revid and not tag_updates:
3121
if not tag_conflicts:
3122
to_file.write('No revisions or tags to pull.\n')
3124
to_file.write('No revisions to pull.\n')
3065
3125
self._show_tag_conficts(to_file)
3093
3153
return self.new_revno - self.old_revno
3095
3155
def report(self, to_file):
3096
"""Write a human-readable description of the result."""
3097
if self.old_revid == self.new_revid:
3098
note('No new revisions to push.')
3100
note('Pushed up to revision %d.' % self.new_revno)
3156
# TODO: This function gets passed a to_file, but then
3157
# ignores it and calls note() instead. This is also
3158
# inconsistent with PullResult(), which writes to stdout.
3159
# -- JRV20110901, bug #838853
3160
tag_conflicts = getattr(self, "tag_conflicts", None)
3161
tag_updates = getattr(self, "tag_updates", None)
3163
if self.old_revid != self.new_revid:
3164
note(gettext('Pushed up to revision %d.') % self.new_revno)
3166
note(ngettext('%d tag updated.', '%d tags updated.', len(tag_updates)) % len(tag_updates))
3167
if self.old_revid == self.new_revid and not tag_updates:
3168
if not tag_conflicts:
3169
note(gettext('No new revisions or tags to push.'))
3171
note(gettext('No new revisions to push.'))
3101
3172
self._show_tag_conficts(to_file)
3117
3188
:param verbose: Requests more detailed display of what was checked,
3120
note('checked branch %s format %s', self.branch.user_url,
3121
self.branch._format)
3191
note(gettext('checked branch {0} format {1}').format(
3192
self.branch.user_url, self.branch._format))
3122
3193
for error in self.errors:
3123
note('found error:%s', error)
3194
note(gettext('found error:%s'), error)
3126
3197
class Converter5to6(object):
3344
3415
if local and not bound_location:
3345
3416
raise errors.LocalRequiresBoundBranch()
3346
3417
master_branch = None
3347
source_is_master = (self.source.user_url == bound_location)
3418
source_is_master = False
3420
# bound_location comes from a config file, some care has to be
3421
# taken to relate it to source.user_url
3422
normalized = urlutils.normalize_url(bound_location)
3424
relpath = self.source.user_transport.relpath(normalized)
3425
source_is_master = (relpath == '')
3426
except (errors.PathNotChild, errors.InvalidURL):
3427
source_is_master = False
3348
3428
if not local and bound_location and not source_is_master:
3349
3429
# not pulling from master, so we need to update master.
3350
3430
master_branch = self.target.get_master_branch(possible_transports)
3402
3482
self._update_revisions(stop_revision, overwrite=overwrite,
3404
3484
if self.source._push_should_merge_tags():
3405
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3485
result.tag_updates, result.tag_conflicts = (
3486
self.source.tags.merge_to(self.target.tags, overwrite))
3407
3487
result.new_revno, result.new_revid = self.target.last_revision_info()
3492
3572
# TODO: The old revid should be specified when merging tags,
3493
3573
# so a tags implementation that versions tags can only
3494
3574
# pull in the most recent changes. -- JRV20090506
3495
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3496
overwrite, ignore_master=not merge_tags_to_master)
3575
result.tag_updates, result.tag_conflicts = (
3576
self.source.tags.merge_to(self.target.tags, overwrite,
3577
ignore_master=not merge_tags_to_master))
3497
3578
result.new_revno, result.new_revid = self.target.last_revision_info()
3498
3579
if _hook_master:
3499
3580
result.master_branch = _hook_master