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
17
from __future__ import absolute_import
18
21
from cStringIO import StringIO
21
23
from bzrlib.lazy_import import lazy_import
22
24
lazy_import(globals(), """
23
from itertools import chain
24
26
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 (
31
config as _mod_config,
40
revision as _mod_revision,
48
from bzrlib.i18n import gettext, ngettext
51
# Explicitly import bzrlib.bzrdir so that the BzrProber
52
# is guaranteed to be registered.
50
55
from bzrlib import (
66
71
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
74
class Branch(controldir.ControlComponent):
75
75
"""Branch holding a history of revisions.
93
93
def user_transport(self):
94
94
return self.bzrdir.user_transport
96
def __init__(self, *ignored, **ignored_too):
96
def __init__(self, possible_transports=None):
97
97
self.tags = self._format.make_tags(self)
98
98
self._revision_history_cache = None
99
99
self._revision_id_to_revno_cache = None
103
103
self._last_revision_info_cache = None
104
104
self._master_branch_cache = None
105
105
self._merge_sorted_revisions_cache = None
106
self._open_hook(possible_transports)
107
107
hooks = Branch.hooks['open']
108
108
for hook in hooks:
111
def _open_hook(self):
111
def _open_hook(self, possible_transports):
112
112
"""Called by init to allow simpler extension of the base class."""
114
def _activate_fallback_location(self, url):
114
def _activate_fallback_location(self, url, possible_transports):
115
115
"""Activate the branch/repository from url as a fallback repository."""
116
116
for existing_fallback_repo in self.repository._fallback_repositories:
117
117
if existing_fallback_repo.user_url == url:
118
118
# This fallback is already configured. This probably only
119
# happens because BzrDir.sprout is a horrible mess. To avoid
119
# happens because ControlDir.sprout is a horrible mess. To avoid
120
120
# confusing _unstack we don't add this a second time.
121
121
mutter('duplicate activation of fallback %r on %r', url, self)
123
repo = self._get_fallback_repository(url)
123
repo = self._get_fallback_repository(url, possible_transports)
124
124
if repo.has_same_location(self.repository):
125
125
raise errors.UnstackableLocationError(self.user_url, url)
126
126
self.repository.add_fallback_repository(repo)
180
180
For instance, if the branch is at URL/.bzr/branch,
181
181
Branch.open(URL) -> a Branch instance.
183
control = bzrdir.BzrDir.open(base, _unsupported,
183
control = controldir.ControlDir.open(base, _unsupported,
184
184
possible_transports=possible_transports)
185
return control.open_branch(unsupported=_unsupported)
185
return control.open_branch(unsupported=_unsupported,
186
possible_transports=possible_transports)
188
def open_from_transport(transport, name=None, _unsupported=False):
189
def open_from_transport(transport, name=None, _unsupported=False,
190
possible_transports=None):
189
191
"""Open the branch rooted at transport"""
190
control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
191
return control.open_branch(name=name, unsupported=_unsupported)
192
control = controldir.ControlDir.open_from_transport(transport, _unsupported)
193
return control.open_branch(name=name, unsupported=_unsupported,
194
possible_transports=possible_transports)
194
197
def open_containing(url, possible_transports=None):
202
205
format, UnknownFormatError or UnsupportedFormatError are raised.
203
206
If there is one, it is returned, along with the unused portion of url.
205
control, relpath = bzrdir.BzrDir.open_containing(url,
208
control, relpath = controldir.ControlDir.open_containing(url,
206
209
possible_transports)
207
return control.open_branch(), relpath
210
branch = control.open_branch(possible_transports=possible_transports)
211
return (branch, relpath)
209
213
def _push_should_merge_tags(self):
210
214
"""Should _basic_push merge this branch's tags into the target?
223
227
:return: A bzrlib.config.BranchConfig.
225
return BranchConfig(self)
229
return _mod_config.BranchConfig(self)
231
def get_config_stack(self):
232
"""Get a bzrlib.config.BranchStack for this Branch.
234
This can then be used to get and set configuration options for the
237
:return: A bzrlib.config.BranchStack.
239
return _mod_config.BranchStack(self)
227
241
def _get_config(self):
228
242
"""Get the concrete config for just the config in this branch.
237
251
raise NotImplementedError(self._get_config)
239
def _get_fallback_repository(self, url):
253
def _get_fallback_repository(self, url, possible_transports):
240
254
"""Get the repository we fallback to at url."""
241
255
url = urlutils.join(self.base, url)
242
a_branch = Branch.open(url,
243
possible_transports=[self.bzrdir.root_transport])
256
a_branch = Branch.open(url, possible_transports=possible_transports)
244
257
return a_branch.repository
652
665
raise errors.UpgradeRequired(self.user_url)
667
def get_append_revisions_only(self):
668
"""Whether it is only possible to append revisions to the history.
670
if not self._format.supports_set_append_revisions_only():
672
return self.get_config_stack().get('append_revisions_only')
654
674
def set_append_revisions_only(self, enabled):
655
675
if not self._format.supports_set_append_revisions_only():
656
676
raise errors.UpgradeRequired(self.user_url)
661
self.get_config().set_user_option('append_revisions_only', value,
677
self.get_config_stack().set('append_revisions_only', enabled)
664
679
def set_reference_info(self, file_id, tree_path, branch_location):
665
680
"""Set the branch location to use for a tree reference."""
695
710
raise errors.UpgradeRequired(self.user_url)
697
def get_commit_builder(self, parents, config=None, timestamp=None,
712
def get_commit_builder(self, parents, config_stack=None, timestamp=None,
698
713
timezone=None, committer=None, revprops=None,
699
714
revision_id=None, lossy=False):
700
715
"""Obtain a CommitBuilder for this branch.
710
725
represented, when pushing to a foreign VCS
714
config = self.get_config()
728
if config_stack is None:
729
config_stack = self.get_config_stack()
716
return self.repository.get_commit_builder(self, parents, config,
731
return self.repository.get_commit_builder(self, parents, config_stack,
717
732
timestamp, timezone, committer, revprops, revision_id,
742
@deprecated_method(deprecated_in((2, 5, 0)))
727
743
def get_revision_delta(self, revno):
728
744
"""Return the delta for one revision.
730
746
The delta is relative to its mainline predecessor, or the
731
747
empty tree for revision 1.
733
rh = self.revision_history()
734
if not (1 <= revno <= len(rh)):
750
revid = self.get_rev_id(revno)
751
except errors.NoSuchRevision:
735
752
raise errors.InvalidRevisionNumber(revno)
736
return self.repository.get_revision_delta(rh[revno-1])
753
return self.repository.get_revision_delta(revid)
738
755
def get_stacked_on_url(self):
739
756
"""Get the URL this branch is stacked against.
785
802
other_branch=None):
786
803
"""See Branch.generate_revision_history"""
787
804
graph = self.repository.get_graph()
805
(last_revno, last_revid) = self.last_revision_info()
788
806
known_revision_ids = [
789
self.last_revision_info(),
807
(last_revid, last_revno),
790
808
(_mod_revision.NULL_REVISION, 0),
792
810
if last_rev is not None:
869
888
# stream from one of them to the other. This does mean doing
870
889
# separate SSH connection setup, but unstacking is not a
871
890
# common operation so it's tolerable.
872
new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
891
new_bzrdir = controldir.ControlDir.open(
892
self.bzrdir.root_transport.base)
873
893
new_repository = new_bzrdir.find_repository()
874
894
if new_repository._fallback_repositories:
875
895
raise AssertionError("didn't expect %r to have "
918
938
tags_to_fetch = set(self.tags.get_reverse_tag_dict())
919
939
except errors.TagsNotSupported:
920
940
tags_to_fetch = set()
921
fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
941
fetch_spec = vf_search.NotInOtherForRevs(self.repository,
922
942
old_repository, required_ids=[self.last_revision()],
923
943
if_present_ids=tags_to_fetch, find_ghosts=True).execute()
924
944
self.repository.fetch(old_repository, fetch_spec=fetch_spec)
1293
1317
if repository_policy is not None:
1294
1318
repository_policy.configure_branch(result)
1295
1319
self.copy_content_into(result, revision_id=revision_id)
1296
master_branch = self.get_master_branch()
1297
if master_branch is None:
1320
master_url = self.get_bound_location()
1321
if master_url is None:
1298
1322
result.set_parent(self.bzrdir.root_transport.base)
1300
result.set_parent(master_branch.bzrdir.root_transport.base)
1324
result.set_parent(master_url)
1302
1326
result.unlock()
1377
1401
# TODO: We should probably also check that self.revision_history
1378
1402
# matches the repository for older branch formats.
1379
1403
# If looking for the code that cross-checks repository parents against
1380
# the iter_reverse_revision_history output, that is now a repository
1404
# the Graph.iter_lefthand_ancestry output, that is now a repository
1381
1405
# specific check.
1384
def _get_checkout_format(self):
1408
def _get_checkout_format(self, lightweight=False):
1385
1409
"""Return the most suitable metadir for a checkout of this branch.
1386
1410
Weaves are used if this branch's repository uses weaves.
1434
1458
t = transport.get_transport(to_location)
1435
1459
t.ensure_base()
1460
format = self._get_checkout_format(lightweight=lightweight)
1436
1461
if lightweight:
1437
format = self._get_checkout_format()
1438
1462
checkout = format.initialize_on_transport(t)
1439
1463
from_branch = BranchReferenceFormat().initialize(checkout,
1440
1464
target_branch=self)
1442
format = self._get_checkout_format()
1443
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
1466
checkout_branch = controldir.ControlDir.create_branch_convenience(
1444
1467
to_location, force_new_tree=False, format=format)
1445
1468
checkout = checkout_branch.bzrdir
1446
1469
checkout_branch.bind(self)
1545
1568
# For bzr native formats must_fetch is just the tip, and if_present_fetch
1546
1569
# are the tags.
1547
1570
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()
1571
if_present_fetch = set()
1572
c = self.get_config()
1573
include_tags = c.get_user_option_as_bool('branch.fetch_tags',
1577
if_present_fetch = set(self.tags.get_reverse_tag_dict())
1578
except errors.TagsNotSupported:
1552
1580
must_fetch.discard(_mod_revision.NULL_REVISION)
1553
1581
if_present_fetch.discard(_mod_revision.NULL_REVISION)
1554
1582
return must_fetch, if_present_fetch
1581
1607
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
1610
@deprecated_method(deprecated_in((2, 4, 0)))
1597
1611
def get_default_format(klass):
1598
1612
"""Return the current default format."""
1609
1623
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.
1625
def get_reference(self, controldir, name=None):
1626
"""Get the target reference of the branch in controldir.
1614
1628
format probing must have been completed before calling
1615
1629
this method - it is assumed that the format of the branch
1616
in a_bzrdir is correct.
1630
in controldir is correct.
1618
:param a_bzrdir: The bzrdir to get the branch data from.
1632
:param controldir: The controldir to get the branch data from.
1619
1633
:param name: Name of the colocated branch to fetch
1620
1634
: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.
1639
def set_reference(self, controldir, name, to_branch):
1640
"""Set the target reference of the branch in controldir.
1628
1642
format probing must have been completed before calling
1629
1643
this method - it is assumed that the format of the branch
1630
in a_bzrdir is correct.
1644
in controldir is correct.
1632
:param a_bzrdir: The bzrdir to set the branch reference for.
1646
:param controldir: The controldir to set the branch reference for.
1633
1647
:param name: Name of colocated branch to set, None for default
1634
1648
:param to_branch: branch that the checkout is to reference
1636
1650
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
1652
def get_format_description(self):
1643
1653
"""Return the short format description for this format."""
1644
1654
raise NotImplementedError(self.get_format_description)
1646
def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
1656
def _run_post_branch_init_hooks(self, controldir, name, branch):
1647
1657
hooks = Branch.hooks['post_branch_init']
1650
params = BranchInitHookParams(self, a_bzrdir, name, branch)
1660
params = BranchInitHookParams(self, controldir, name, branch)
1651
1661
for hook in hooks:
1654
def initialize(self, a_bzrdir, name=None, repository=None):
1655
"""Create a branch of this format in a_bzrdir.
1664
def initialize(self, controldir, name=None, repository=None,
1665
append_revisions_only=None):
1666
"""Create a branch of this format in controldir.
1657
1668
:param name: Name of the colocated branch to create.
1659
1670
raise NotImplementedError(self.initialize)
1692
1703
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
1705
def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
1706
found_repository=None, possible_transports=None):
1707
"""Return the branch object for controldir.
1698
:param a_bzrdir: A BzrDir that contains a branch.
1709
:param controldir: A ControlDir that contains a branch.
1699
1710
:param name: Name of colocated branch to open
1700
1711
:param _found: a private parameter, do not use it. It is used to
1701
1712
indicate if format probing has already be done.
1743
1754
"""True if this format supports tags stored in the branch"""
1744
1755
return False # by default
1757
def tags_are_versioned(self):
1758
"""Whether the tag container for this branch versions tags."""
1761
def supports_tags_referencing_ghosts(self):
1762
"""True if tags can reference ghost revisions."""
1747
1766
class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
1748
1767
"""A factory for a BranchFormat object, permitting simple lazy registration.
1922
1941
branch, which refer to the original branch.
1925
def __init__(self, format, a_bzrdir, name, branch):
1944
def __init__(self, format, controldir, name, branch):
1926
1945
"""Create a group of BranchInitHook parameters.
1928
1947
:param format: the branch format
1929
:param a_bzrdir: the BzrDir where the branch will be/has been
1948
:param controldir: the ControlDir where the branch will be/has been
1931
1950
:param name: name of colocated branch, if any (or None)
1932
1951
:param branch: the branch created
1961
1980
def __init__(self, control_dir, to_branch, force, revision_id):
1962
1981
"""Create a group of SwitchHook parameters.
1964
:param control_dir: BzrDir of the checkout to change
1983
:param control_dir: ControlDir of the checkout to change
1965
1984
:param to_branch: branch that the checkout is to reference
1966
1985
:param force: skip the check for local commits in a heavy checkout
1967
1986
:param revision_id: revision ID to switch to (or None)
1980
1999
self.revision_id)
1983
class BranchFormatMetadir(BranchFormat):
1984
"""Common logic for meta-dir based branch formats."""
2002
class BranchFormatMetadir(bzrdir.BzrDirMetaComponentFormat, BranchFormat):
2003
"""Base class for branch formats that live in meta directories.
2007
BranchFormat.__init__(self)
2008
bzrdir.BzrDirMetaComponentFormat.__init__(self)
2011
def find_format(klass, controldir, name=None):
2012
"""Return the format for the branch object in controldir."""
2014
transport = controldir.get_branch_transport(None, name=name)
2015
except errors.NoSuchFile:
2016
raise errors.NotBranchError(path=name, bzrdir=controldir)
2018
format_string = transport.get_bytes("format")
2019
except errors.NoSuchFile:
2020
raise errors.NotBranchError(path=transport.base, bzrdir=controldir)
2021
return klass._find_format(format_registry, 'branch', format_string)
1986
2023
def _branch_class(self):
1987
2024
"""What class to instantiate on open calls."""
1988
2025
raise NotImplementedError(self._branch_class)
2027
def _get_initial_config(self, append_revisions_only=None):
2028
if append_revisions_only:
2029
return "append_revisions_only = True\n"
2031
# Avoid writing anything if append_revisions_only is disabled,
2032
# as that is the default.
1990
2035
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1991
2036
repository=None):
1992
2037
"""Initialize a branch in a bzrdir, with specified files
2016
2061
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
2064
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2027
found_repository=None):
2065
found_repository=None, possible_transports=None):
2028
2066
"""See BranchFormat.open()."""
2030
format = BranchFormat.find_format(a_bzrdir, name=name)
2068
format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
2031
2069
if format.__class__ != self.__class__:
2032
2070
raise AssertionError("wrong format %r found for %r" %
2033
2071
(format, self))
2043
2081
a_bzrdir=a_bzrdir,
2044
2082
_repository=found_repository,
2045
ignore_fallbacks=ignore_fallbacks)
2083
ignore_fallbacks=ignore_fallbacks,
2084
possible_transports=possible_transports)
2046
2085
except errors.NoSuchFile:
2047
2086
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)
2089
def _matchingbzrdir(self):
2090
ret = bzrdir.BzrDirMetaFormat1()
2091
ret.set_branch_format(self)
2054
2094
def supports_tags(self):
2082
2123
"""See BranchFormat.get_format_description()."""
2083
2124
return "Branch format 5"
2085
def initialize(self, a_bzrdir, name=None, repository=None):
2126
def initialize(self, a_bzrdir, name=None, repository=None,
2127
append_revisions_only=None):
2086
2128
"""Create a branch of this format in a_bzrdir."""
2129
if append_revisions_only:
2130
raise errors.UpgradeRequired(a_bzrdir.user_url)
2087
2131
utf8_files = [('revision-history', ''),
2088
2132
('branch-name', ''),
2115
2160
"""See BranchFormat.get_format_description()."""
2116
2161
return "Branch format 6"
2118
def initialize(self, a_bzrdir, name=None, repository=None):
2163
def initialize(self, a_bzrdir, name=None, repository=None,
2164
append_revisions_only=None):
2119
2165
"""Create a branch of this format in a_bzrdir."""
2120
2166
utf8_files = [('last-revision', '0 null:\n'),
2121
('branch.conf', ''),
2168
self._get_initial_config(append_revisions_only)),
2124
2171
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2126
2173
def make_tags(self, branch):
2127
2174
"""See bzrlib.branch.BranchFormat.make_tags()."""
2128
return BasicTags(branch)
2175
return _mod_tag.BasicTags(branch)
2130
2177
def supports_set_append_revisions_only(self):
2145
2193
"""See BranchFormat.get_format_description()."""
2146
2194
return "Branch format 8"
2148
def initialize(self, a_bzrdir, name=None, repository=None):
2196
def initialize(self, a_bzrdir, name=None, repository=None,
2197
append_revisions_only=None):
2149
2198
"""Create a branch of this format in a_bzrdir."""
2150
2199
utf8_files = [('last-revision', '0 null:\n'),
2151
('branch.conf', ''),
2201
self._get_initial_config(append_revisions_only)),
2153
2203
('references', '')
2176
2226
This format was introduced in bzr 1.6.
2179
def initialize(self, a_bzrdir, name=None, repository=None):
2229
def initialize(self, a_bzrdir, name=None, repository=None,
2230
append_revisions_only=None):
2180
2231
"""Create a branch of this format in a_bzrdir."""
2181
2232
utf8_files = [('last-revision', '0 null:\n'),
2182
('branch.conf', ''),
2234
self._get_initial_config(append_revisions_only)),
2185
2237
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2204
2257
def make_tags(self, branch):
2205
2258
"""See bzrlib.branch.BranchFormat.make_tags()."""
2206
return BasicTags(branch)
2259
return _mod_tag.BasicTags(branch)
2208
2261
supports_reference_locations = False
2211
class BranchReferenceFormat(BranchFormat):
2264
class BranchReferenceFormat(BranchFormatMetadir):
2212
2265
"""Bzr branch reference format.
2214
2267
Branch references are used in implementing checkouts, they
2238
2292
location = transport.put_bytes('location', to_branch.base)
2240
2294
def initialize(self, a_bzrdir, name=None, target_branch=None,
2295
repository=None, append_revisions_only=None):
2242
2296
"""Create a branch of this format in a_bzrdir."""
2243
2297
if target_branch is None:
2244
2298
# this format does not implement branch itself, thus the implicit
2245
2299
# creation contract must see it as uninitializable
2246
2300
raise errors.UninitializableFormat(self)
2247
2301
mutter('creating branch reference in %s', a_bzrdir.user_url)
2302
if a_bzrdir._format.fixed_components:
2303
raise errors.IncompatibleFormat(self, a_bzrdir._format)
2248
2304
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2249
2305
branch_transport.put_bytes('location',
2250
target_branch.bzrdir.user_url)
2306
target_branch.user_url)
2251
2307
branch_transport.put_bytes('format', self.get_format_string())
2252
2308
branch = self.open(
2253
2309
a_bzrdir, name, _found=True,
2255
2311
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
2314
def _make_reference_clone_function(format, a_branch):
2264
2315
"""Create a clone() routine for a branch dynamically."""
2265
2316
def clone(to_bzrdir, revision_id=None,
2288
2339
:param possible_transports: An optional reusable transports list.
2291
format = BranchFormat.find_format(a_bzrdir, name=name)
2342
format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
2292
2343
if format.__class__ != self.__class__:
2293
2344
raise AssertionError("wrong format %r found for %r" %
2294
2345
(format, self))
2295
2346
if location is None:
2296
2347
location = self.get_reference(a_bzrdir, name)
2297
real_bzrdir = bzrdir.BzrDir.open(
2348
real_bzrdir = controldir.ControlDir.open(
2298
2349
location, possible_transports=possible_transports)
2299
2350
result = real_bzrdir.open_branch(name=name,
2300
ignore_fallbacks=ignore_fallbacks)
2351
ignore_fallbacks=ignore_fallbacks,
2352
possible_transports=possible_transports)
2301
2353
# this changes the behaviour of result.clone to create a new reference
2302
2354
# rather than a copy of the content of the branch.
2303
2355
# I did not use a proxy object because that needs much more extensive
2385
2437
def __init__(self, _format=None,
2386
2438
_control_files=None, a_bzrdir=None, name=None,
2387
_repository=None, ignore_fallbacks=False):
2439
_repository=None, ignore_fallbacks=False,
2440
possible_transports=None):
2388
2441
"""Create new branch object at a particular location."""
2389
2442
if a_bzrdir is None:
2390
2443
raise ValueError('a_bzrdir must be supplied')
2392
2445
self.bzrdir = a_bzrdir
2393
self._base = self.bzrdir.transport.clone('..').base
2446
self._user_transport = self.bzrdir.transport.clone('..')
2447
if name is not None:
2448
self._user_transport.set_segment_parameter(
2449
"branch", urlutils.escape(name))
2450
self._base = self._user_transport.base
2394
2451
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
2452
self._format = _format
2399
2453
if _control_files is None:
2400
2454
raise ValueError('BzrBranch _control_files is None')
2401
2455
self.control_files = _control_files
2402
2456
self._transport = _control_files._transport
2403
2457
self.repository = _repository
2404
Branch.__init__(self)
2458
Branch.__init__(self, possible_transports)
2406
2460
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,
2461
return '%s(%s)' % (self.__class__.__name__, self.user_url)
2413
2463
__repr__ = __str__
2419
2469
base = property(_get_base, doc="The URL for the root of this branch.")
2472
def user_transport(self):
2473
return self._user_transport
2421
2475
def _get_config(self):
2422
return TransportConfig(self._transport, 'branch.conf')
2476
return _mod_config.TransportConfig(self._transport, 'branch.conf')
2478
def _get_config_store(self):
2479
return _mod_config.BranchStore(self)
2424
2481
def is_locked(self):
2425
2482
return self.control_files.is_locked()
2506
2563
raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2507
2564
revision_id = _mod_revision.ensure_null(revision_id)
2508
2565
old_revno, old_revid = self.last_revision_info()
2509
if self._get_append_revisions_only():
2566
if self.get_append_revisions_only():
2510
2567
self._check_history_violation(revision_id)
2511
2568
self._run_pre_change_branch_tip_hooks(revno, revision_id)
2512
2569
self._write_last_revision_info(revno, revision_id)
2767
2824
class BzrBranch8(BzrBranch):
2768
2825
"""A branch that stores tree-reference locations."""
2770
def _open_hook(self):
2827
def _open_hook(self, possible_transports=None):
2771
2828
if self._ignore_fallbacks:
2830
if possible_transports is None:
2831
possible_transports = [self.bzrdir.root_transport]
2774
2833
url = self.get_stacked_on_url()
2775
2834
except (errors.UnstackableRepositoryFormat, errors.NotStacked,
2783
2842
raise AssertionError(
2784
2843
"'transform_fallback_location' hook %s returned "
2785
2844
"None, not a URL." % hook_name)
2786
self._activate_fallback_location(url)
2845
self._activate_fallback_location(url,
2846
possible_transports=possible_transports)
2788
2848
def __init__(self, *args, **kwargs):
2789
2849
self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
2989
3045
except errors.RevisionNotPresent, e:
2990
3046
raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
2991
3047
index = len(self._partial_revision_history_cache) - 1
3049
raise errors.NoSuchRevision(self, revision_id)
2992
3050
if self._partial_revision_history_cache[index] != revision_id:
2993
3051
raise errors.NoSuchRevision(self, revision_id)
2994
3052
return self.revno() - index
3057
3116
return self.new_revno - self.old_revno
3059
3118
def report(self, to_file):
3119
tag_conflicts = getattr(self, "tag_conflicts", None)
3120
tag_updates = getattr(self, "tag_updates", None)
3060
3121
if not is_quiet():
3061
if self.old_revid == self.new_revid:
3062
to_file.write('No revisions to pull.\n')
3122
if self.old_revid != self.new_revid:
3064
3123
to_file.write('Now on revision %d.\n' % self.new_revno)
3125
to_file.write('%d tag(s) updated.\n' % len(tag_updates))
3126
if self.old_revid == self.new_revid and not tag_updates:
3127
if not tag_conflicts:
3128
to_file.write('No revisions or tags to pull.\n')
3130
to_file.write('No revisions to pull.\n')
3065
3131
self._show_tag_conficts(to_file)
3093
3159
return self.new_revno - self.old_revno
3095
3161
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)
3162
# TODO: This function gets passed a to_file, but then
3163
# ignores it and calls note() instead. This is also
3164
# inconsistent with PullResult(), which writes to stdout.
3165
# -- JRV20110901, bug #838853
3166
tag_conflicts = getattr(self, "tag_conflicts", None)
3167
tag_updates = getattr(self, "tag_updates", None)
3169
if self.old_revid != self.new_revid:
3170
note(gettext('Pushed up to revision %d.') % self.new_revno)
3172
note(ngettext('%d tag updated.', '%d tags updated.', len(tag_updates)) % len(tag_updates))
3173
if self.old_revid == self.new_revid and not tag_updates:
3174
if not tag_conflicts:
3175
note(gettext('No new revisions or tags to push.'))
3177
note(gettext('No new revisions to push.'))
3101
3178
self._show_tag_conficts(to_file)
3117
3194
: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)
3197
note(gettext('checked branch {0} format {1}').format(
3198
self.branch.user_url, self.branch._format))
3122
3199
for error in self.errors:
3123
note('found error:%s', error)
3200
note(gettext('found error:%s'), error)
3126
3203
class Converter5to6(object):
3344
3421
if local and not bound_location:
3345
3422
raise errors.LocalRequiresBoundBranch()
3346
3423
master_branch = None
3347
source_is_master = (self.source.user_url == bound_location)
3424
source_is_master = False
3426
# bound_location comes from a config file, some care has to be
3427
# taken to relate it to source.user_url
3428
normalized = urlutils.normalize_url(bound_location)
3430
relpath = self.source.user_transport.relpath(normalized)
3431
source_is_master = (relpath == '')
3432
except (errors.PathNotChild, errors.InvalidURL):
3433
source_is_master = False
3348
3434
if not local and bound_location and not source_is_master:
3349
3435
# not pulling from master, so we need to update master.
3350
3436
master_branch = self.target.get_master_branch(possible_transports)
3402
3488
self._update_revisions(stop_revision, overwrite=overwrite,
3404
3490
if self.source._push_should_merge_tags():
3405
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3491
result.tag_updates, result.tag_conflicts = (
3492
self.source.tags.merge_to(self.target.tags, overwrite))
3407
3493
result.new_revno, result.new_revid = self.target.last_revision_info()
3492
3578
# TODO: The old revid should be specified when merging tags,
3493
3579
# so a tags implementation that versions tags can only
3494
3580
# 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)
3581
result.tag_updates, result.tag_conflicts = (
3582
self.source.tags.merge_to(self.target.tags, overwrite,
3583
ignore_master=not merge_tags_to_master))
3497
3584
result.new_revno, result.new_revid = self.target.last_revision_info()
3498
3585
if _hook_master:
3499
3586
result.master_branch = _hook_master