21
24
lazy_import(globals(), """
23
26
from bzrlib import (
27
config as _mod_config,
36
revision as _mod_revision,
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.
45
55
from bzrlib import (
48
59
from bzrlib.decorators import (
83
94
def user_transport(self):
84
95
return self.bzrdir.user_transport
86
def __init__(self, *ignored, **ignored_too):
97
def __init__(self, possible_transports=None):
87
98
self.tags = self._format.make_tags(self)
88
99
self._revision_history_cache = None
89
100
self._revision_id_to_revno_cache = None
93
104
self._last_revision_info_cache = None
94
105
self._master_branch_cache = None
95
106
self._merge_sorted_revisions_cache = None
107
self._open_hook(possible_transports)
97
108
hooks = Branch.hooks['open']
98
109
for hook in hooks:
101
def _open_hook(self):
112
def _open_hook(self, possible_transports):
102
113
"""Called by init to allow simpler extension of the base class."""
104
def _activate_fallback_location(self, url):
115
def _activate_fallback_location(self, url, possible_transports):
105
116
"""Activate the branch/repository from url as a fallback repository."""
106
117
for existing_fallback_repo in self.repository._fallback_repositories:
107
118
if existing_fallback_repo.user_url == url:
108
119
# This fallback is already configured. This probably only
109
# happens because BzrDir.sprout is a horrible mess. To avoid
120
# happens because ControlDir.sprout is a horrible mess. To avoid
110
121
# confusing _unstack we don't add this a second time.
111
122
mutter('duplicate activation of fallback %r on %r', url, self)
113
repo = self._get_fallback_repository(url)
124
repo = self._get_fallback_repository(url, possible_transports)
114
125
if repo.has_same_location(self.repository):
115
126
raise errors.UnstackableLocationError(self.user_url, url)
116
127
self.repository.add_fallback_repository(repo)
170
181
For instance, if the branch is at URL/.bzr/branch,
171
182
Branch.open(URL) -> a Branch instance.
173
control = bzrdir.BzrDir.open(base, _unsupported,
174
possible_transports=possible_transports)
175
return control.open_branch(unsupported=_unsupported)
184
control = controldir.ControlDir.open(base,
185
possible_transports=possible_transports, _unsupported=_unsupported)
186
return control.open_branch(unsupported=_unsupported,
187
possible_transports=possible_transports)
178
def open_from_transport(transport, name=None, _unsupported=False):
190
def open_from_transport(transport, name=None, _unsupported=False,
191
possible_transports=None):
179
192
"""Open the branch rooted at transport"""
180
control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
181
return control.open_branch(name=name, unsupported=_unsupported)
193
control = controldir.ControlDir.open_from_transport(transport, _unsupported)
194
return control.open_branch(name=name, unsupported=_unsupported,
195
possible_transports=possible_transports)
184
198
def open_containing(url, possible_transports=None):
192
206
format, UnknownFormatError or UnsupportedFormatError are raised.
193
207
If there is one, it is returned, along with the unused portion of url.
195
control, relpath = bzrdir.BzrDir.open_containing(url,
209
control, relpath = controldir.ControlDir.open_containing(url,
196
210
possible_transports)
197
return control.open_branch(), relpath
211
branch = control.open_branch(possible_transports=possible_transports)
212
return (branch, relpath)
199
214
def _push_should_merge_tags(self):
200
215
"""Should _basic_push merge this branch's tags into the target?
227
252
raise NotImplementedError(self._get_config)
229
def _get_fallback_repository(self, url):
254
def _get_fallback_repository(self, url, possible_transports):
230
255
"""Get the repository we fallback to at url."""
231
256
url = urlutils.join(self.base, url)
232
a_branch = Branch.open(url,
233
possible_transports=[self.bzrdir.root_transport])
257
a_branch = Branch.open(url, possible_transports=possible_transports)
234
258
return a_branch.repository
642
666
raise errors.UpgradeRequired(self.user_url)
668
def get_append_revisions_only(self):
669
"""Whether it is only possible to append revisions to the history.
671
if not self._format.supports_set_append_revisions_only():
673
return self.get_config_stack().get('append_revisions_only')
644
675
def set_append_revisions_only(self, enabled):
645
676
if not self._format.supports_set_append_revisions_only():
646
677
raise errors.UpgradeRequired(self.user_url)
651
self.get_config().set_user_option('append_revisions_only', value,
678
self.get_config_stack().set('append_revisions_only', enabled)
654
680
def set_reference_info(self, file_id, tree_path, branch_location):
655
681
"""Set the branch location to use for a tree reference."""
685
711
raise errors.UpgradeRequired(self.user_url)
687
def get_commit_builder(self, parents, config=None, timestamp=None,
713
def get_commit_builder(self, parents, config_stack=None, timestamp=None,
688
714
timezone=None, committer=None, revprops=None,
689
715
revision_id=None, lossy=False):
690
716
"""Obtain a CommitBuilder for this branch.
700
726
represented, when pushing to a foreign VCS
704
config = self.get_config()
729
if config_stack is None:
730
config_stack = self.get_config_stack()
706
return self.repository.get_commit_builder(self, parents, config,
732
return self.repository.get_commit_builder(self, parents, config_stack,
707
733
timestamp, timezone, committer, revprops, revision_id,
743
@deprecated_method(deprecated_in((2, 5, 0)))
717
744
def get_revision_delta(self, revno):
718
745
"""Return the delta for one revision.
720
747
The delta is relative to its mainline predecessor, or the
721
748
empty tree for revision 1.
723
rh = self.revision_history()
724
if not (1 <= revno <= len(rh)):
751
revid = self.get_rev_id(revno)
752
except errors.NoSuchRevision:
725
753
raise errors.InvalidRevisionNumber(revno)
726
return self.repository.get_revision_delta(rh[revno-1])
754
return self.repository.get_revision_delta(revid)
728
756
def get_stacked_on_url(self):
729
757
"""Get the URL this branch is stacked against.
860
889
# stream from one of them to the other. This does mean doing
861
890
# separate SSH connection setup, but unstacking is not a
862
891
# common operation so it's tolerable.
863
new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
892
new_bzrdir = controldir.ControlDir.open(
893
self.bzrdir.root_transport.base)
864
894
new_repository = new_bzrdir.find_repository()
865
895
if new_repository._fallback_repositories:
866
896
raise AssertionError("didn't expect %r to have "
909
939
tags_to_fetch = set(self.tags.get_reverse_tag_dict())
910
940
except errors.TagsNotSupported:
911
941
tags_to_fetch = set()
912
fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
942
fetch_spec = vf_search.NotInOtherForRevs(self.repository,
913
943
old_repository, required_ids=[self.last_revision()],
914
944
if_present_ids=tags_to_fetch, find_ghosts=True).execute()
915
945
self.repository.fetch(old_repository, fetch_spec=fetch_spec)
1136
1170
def _set_config_location(self, name, url, config=None,
1137
1171
make_relative=False):
1138
1172
if config is None:
1139
config = self.get_config()
1173
config = self.get_config_stack()
1140
1174
if url is None:
1142
1176
elif make_relative:
1143
1177
url = urlutils.relative_url(self.base, url)
1144
config.set_user_option(name, url, warn_masked=True)
1178
config.set(name, url)
1146
1180
def _get_config_location(self, name, config=None):
1147
1181
if config is None:
1148
config = self.get_config()
1149
location = config.get_user_option(name)
1182
config = self.get_config_stack()
1183
location = config.get(name)
1150
1184
if location == '':
1151
1185
location = None
1152
1186
return location
1368
1402
# TODO: We should probably also check that self.revision_history
1369
1403
# matches the repository for older branch formats.
1370
1404
# If looking for the code that cross-checks repository parents against
1371
# the iter_reverse_revision_history output, that is now a repository
1405
# the Graph.iter_lefthand_ancestry output, that is now a repository
1372
1406
# specific check.
1375
def _get_checkout_format(self):
1409
def _get_checkout_format(self, lightweight=False):
1376
1410
"""Return the most suitable metadir for a checkout of this branch.
1377
1411
Weaves are used if this branch's repository uses weaves.
1425
1459
t = transport.get_transport(to_location)
1426
1460
t.ensure_base()
1461
format = self._get_checkout_format(lightweight=lightweight)
1427
1462
if lightweight:
1428
format = self._get_checkout_format()
1429
1463
checkout = format.initialize_on_transport(t)
1430
1464
from_branch = BranchReferenceFormat().initialize(checkout,
1431
1465
target_branch=self)
1433
format = self._get_checkout_format()
1434
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
1467
checkout_branch = controldir.ControlDir.create_branch_convenience(
1435
1468
to_location, force_new_tree=False, format=format)
1436
1469
checkout = checkout_branch.bzrdir
1437
1470
checkout_branch.bind(self)
1533
1566
heads that must be fetched if present, but no error is necessary if
1534
1567
they are not present.
1536
# For bzr native formats must_fetch is just the tip, and if_present_fetch
1569
# For bzr native formats must_fetch is just the tip, and
1570
# if_present_fetch are the tags.
1538
1571
must_fetch = set([self.last_revision()])
1539
1572
if_present_fetch = set()
1540
c = self.get_config()
1541
include_tags = c.get_user_option_as_bool('branch.fetch_tags',
1573
if self.get_config_stack().get('branch.fetch_tags'):
1545
1575
if_present_fetch = set(self.tags.get_reverse_tag_dict())
1546
1576
except errors.TagsNotSupported:
1577
1605
return not (self == other)
1580
def find_format(klass, a_bzrdir, name=None):
1581
"""Return the format for the branch object in a_bzrdir."""
1583
transport = a_bzrdir.get_branch_transport(None, name=name)
1584
format_string = transport.get_bytes("format")
1585
return format_registry.get(format_string)
1586
except errors.NoSuchFile:
1587
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
1589
raise errors.UnknownFormatError(format=format_string, kind='branch')
1592
1608
@deprecated_method(deprecated_in((2, 4, 0)))
1593
1609
def get_default_format(klass):
1594
1610
"""Return the current default format."""
1605
1621
return format_registry._get_all()
1607
def get_reference(self, a_bzrdir, name=None):
1608
"""Get the target reference of the branch in a_bzrdir.
1623
def get_reference(self, controldir, name=None):
1624
"""Get the target reference of the branch in controldir.
1610
1626
format probing must have been completed before calling
1611
1627
this method - it is assumed that the format of the branch
1612
in a_bzrdir is correct.
1628
in controldir is correct.
1614
:param a_bzrdir: The bzrdir to get the branch data from.
1630
:param controldir: The controldir to get the branch data from.
1615
1631
:param name: Name of the colocated branch to fetch
1616
1632
:return: None if the branch is not a reference branch.
1621
def set_reference(self, a_bzrdir, name, to_branch):
1622
"""Set the target reference of the branch in a_bzrdir.
1637
def set_reference(self, controldir, name, to_branch):
1638
"""Set the target reference of the branch in controldir.
1624
1640
format probing must have been completed before calling
1625
1641
this method - it is assumed that the format of the branch
1626
in a_bzrdir is correct.
1642
in controldir is correct.
1628
:param a_bzrdir: The bzrdir to set the branch reference for.
1644
:param controldir: The controldir to set the branch reference for.
1629
1645
:param name: Name of colocated branch to set, None for default
1630
1646
:param to_branch: branch that the checkout is to reference
1632
1648
raise NotImplementedError(self.set_reference)
1634
def get_format_string(self):
1635
"""Return the ASCII format string that identifies this format."""
1636
raise NotImplementedError(self.get_format_string)
1638
1650
def get_format_description(self):
1639
1651
"""Return the short format description for this format."""
1640
1652
raise NotImplementedError(self.get_format_description)
1642
def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
1654
def _run_post_branch_init_hooks(self, controldir, name, branch):
1643
1655
hooks = Branch.hooks['post_branch_init']
1646
params = BranchInitHookParams(self, a_bzrdir, name, branch)
1658
params = BranchInitHookParams(self, controldir, name, branch)
1647
1659
for hook in hooks:
1650
def initialize(self, a_bzrdir, name=None, repository=None):
1651
"""Create a branch of this format in a_bzrdir.
1662
def initialize(self, controldir, name=None, repository=None,
1663
append_revisions_only=None):
1664
"""Create a branch of this format in controldir.
1653
1666
:param name: Name of the colocated branch to create.
1655
1668
raise NotImplementedError(self.initialize)
1688
1701
raise NotImplementedError(self.network_name)
1690
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
1691
found_repository=None):
1692
"""Return the branch object for a_bzrdir
1703
def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
1704
found_repository=None, possible_transports=None):
1705
"""Return the branch object for controldir.
1694
:param a_bzrdir: A BzrDir that contains a branch.
1707
:param controldir: A ControlDir that contains a branch.
1695
1708
:param name: Name of colocated branch to open
1696
1709
:param _found: a private parameter, do not use it. It is used to
1697
1710
indicate if format probing has already be done.
1739
1752
"""True if this format supports tags stored in the branch"""
1740
1753
return False # by default
1755
def tags_are_versioned(self):
1756
"""Whether the tag container for this branch versions tags."""
1759
def supports_tags_referencing_ghosts(self):
1760
"""True if tags can reference ghost revisions."""
1743
1764
class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
1744
1765
"""A factory for a BranchFormat object, permitting simple lazy registration.
1918
1939
branch, which refer to the original branch.
1921
def __init__(self, format, a_bzrdir, name, branch):
1942
def __init__(self, format, controldir, name, branch):
1922
1943
"""Create a group of BranchInitHook parameters.
1924
1945
:param format: the branch format
1925
:param a_bzrdir: the BzrDir where the branch will be/has been
1946
:param controldir: the ControlDir where the branch will be/has been
1927
1948
:param name: name of colocated branch, if any (or None)
1928
1949
:param branch: the branch created
1957
1978
def __init__(self, control_dir, to_branch, force, revision_id):
1958
1979
"""Create a group of SwitchHook parameters.
1960
:param control_dir: BzrDir of the checkout to change
1981
:param control_dir: ControlDir of the checkout to change
1961
1982
:param to_branch: branch that the checkout is to reference
1962
1983
:param force: skip the check for local commits in a heavy checkout
1963
1984
:param revision_id: revision ID to switch to (or None)
1976
1997
self.revision_id)
1979
class BranchFormatMetadir(BranchFormat):
1980
"""Common logic for meta-dir based branch formats."""
2000
class BranchFormatMetadir(bzrdir.BzrFormat, BranchFormat):
2001
"""Base class for branch formats that live in meta directories.
2005
BranchFormat.__init__(self)
2006
bzrdir.BzrFormat.__init__(self)
2009
def find_format(klass, controldir, name=None):
2010
"""Return the format for the branch object in controldir."""
2012
transport = controldir.get_branch_transport(None, name=name)
2013
except errors.NoSuchFile:
2014
raise errors.NotBranchError(path=name, bzrdir=controldir)
2016
format_string = transport.get_bytes("format")
2017
except errors.NoSuchFile:
2018
raise errors.NotBranchError(path=transport.base, bzrdir=controldir)
2019
return klass._find_format(format_registry, 'branch', format_string)
1982
2021
def _branch_class(self):
1983
2022
"""What class to instantiate on open calls."""
1984
2023
raise NotImplementedError(self._branch_class)
2025
def _get_initial_config(self, append_revisions_only=None):
2026
if append_revisions_only:
2027
return "append_revisions_only = True\n"
2029
# Avoid writing anything if append_revisions_only is disabled,
2030
# as that is the default.
1986
2033
def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1987
2034
repository=None):
1988
2035
"""Initialize a branch in a bzrdir, with specified files
2012
2059
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2015
def network_name(self):
2016
"""A simple byte string uniquely identifying this format for RPC calls.
2018
Metadir branch formats use their format string.
2020
return self.get_format_string()
2022
2062
def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2023
found_repository=None):
2063
found_repository=None, possible_transports=None):
2024
2064
"""See BranchFormat.open()."""
2026
format = BranchFormat.find_format(a_bzrdir, name=name)
2066
format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
2027
2067
if format.__class__ != self.__class__:
2028
2068
raise AssertionError("wrong format %r found for %r" %
2029
2069
(format, self))
2039
2079
a_bzrdir=a_bzrdir,
2040
2080
_repository=found_repository,
2041
ignore_fallbacks=ignore_fallbacks)
2081
ignore_fallbacks=ignore_fallbacks,
2082
possible_transports=possible_transports)
2042
2083
except errors.NoSuchFile:
2043
2084
raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2046
super(BranchFormatMetadir, self).__init__()
2047
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
2048
self._matchingbzrdir.set_branch_format(self)
2087
def _matchingbzrdir(self):
2088
ret = bzrdir.BzrDirMetaFormat1()
2089
ret.set_branch_format(self)
2050
2092
def supports_tags(self):
2053
2095
def supports_leaving_lock(self):
2098
def check_support_status(self, allow_unsupported, recommend_upgrade=True,
2100
BranchFormat.check_support_status(self,
2101
allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
2103
bzrdir.BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
2104
recommend_upgrade=recommend_upgrade, basedir=basedir)
2057
2107
class BzrBranchFormat5(BranchFormatMetadir):
2058
2108
"""Bzr branch format 5.
2078
2129
"""See BranchFormat.get_format_description()."""
2079
2130
return "Branch format 5"
2081
def initialize(self, a_bzrdir, name=None, repository=None):
2132
def initialize(self, a_bzrdir, name=None, repository=None,
2133
append_revisions_only=None):
2082
2134
"""Create a branch of this format in a_bzrdir."""
2135
if append_revisions_only:
2136
raise errors.UpgradeRequired(a_bzrdir.user_url)
2083
2137
utf8_files = [('revision-history', ''),
2084
2138
('branch-name', ''),
2111
2166
"""See BranchFormat.get_format_description()."""
2112
2167
return "Branch format 6"
2114
def initialize(self, a_bzrdir, name=None, repository=None):
2169
def initialize(self, a_bzrdir, name=None, repository=None,
2170
append_revisions_only=None):
2115
2171
"""Create a branch of this format in a_bzrdir."""
2116
2172
utf8_files = [('last-revision', '0 null:\n'),
2117
('branch.conf', ''),
2174
self._get_initial_config(append_revisions_only)),
2120
2177
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2141
2199
"""See BranchFormat.get_format_description()."""
2142
2200
return "Branch format 8"
2144
def initialize(self, a_bzrdir, name=None, repository=None):
2202
def initialize(self, a_bzrdir, name=None, repository=None,
2203
append_revisions_only=None):
2145
2204
"""Create a branch of this format in a_bzrdir."""
2146
2205
utf8_files = [('last-revision', '0 null:\n'),
2147
('branch.conf', ''),
2207
self._get_initial_config(append_revisions_only)),
2149
2209
('references', '')
2172
2232
This format was introduced in bzr 1.6.
2175
def initialize(self, a_bzrdir, name=None, repository=None):
2235
def initialize(self, a_bzrdir, name=None, repository=None,
2236
append_revisions_only=None):
2176
2237
"""Create a branch of this format in a_bzrdir."""
2177
2238
utf8_files = [('last-revision', '0 null:\n'),
2178
('branch.conf', ''),
2240
self._get_initial_config(append_revisions_only)),
2181
2243
return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2234
2298
location = transport.put_bytes('location', to_branch.base)
2236
2300
def initialize(self, a_bzrdir, name=None, target_branch=None,
2301
repository=None, append_revisions_only=None):
2238
2302
"""Create a branch of this format in a_bzrdir."""
2239
2303
if target_branch is None:
2240
2304
# this format does not implement branch itself, thus the implicit
2245
2309
raise errors.IncompatibleFormat(self, a_bzrdir._format)
2246
2310
branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2247
2311
branch_transport.put_bytes('location',
2248
target_branch.bzrdir.user_url)
2249
branch_transport.put_bytes('format', self.get_format_string())
2312
target_branch.user_url)
2313
branch_transport.put_bytes('format', self.as_string())
2250
2314
branch = self.open(
2251
2315
a_bzrdir, name, _found=True,
2252
2316
possible_transports=[target_branch.bzrdir.root_transport])
2253
2317
self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2257
super(BranchReferenceFormat, self).__init__()
2258
self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
2259
self._matchingbzrdir.set_branch_format(self)
2261
2320
def _make_reference_clone_function(format, a_branch):
2262
2321
"""Create a clone() routine for a branch dynamically."""
2263
2322
def clone(to_bzrdir, revision_id=None,
2286
2345
:param possible_transports: An optional reusable transports list.
2289
format = BranchFormat.find_format(a_bzrdir, name=name)
2348
format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
2290
2349
if format.__class__ != self.__class__:
2291
2350
raise AssertionError("wrong format %r found for %r" %
2292
2351
(format, self))
2293
2352
if location is None:
2294
2353
location = self.get_reference(a_bzrdir, name)
2295
real_bzrdir = bzrdir.BzrDir.open(
2354
real_bzrdir = controldir.ControlDir.open(
2296
2355
location, possible_transports=possible_transports)
2297
2356
result = real_bzrdir.open_branch(name=name,
2298
ignore_fallbacks=ignore_fallbacks)
2357
ignore_fallbacks=ignore_fallbacks,
2358
possible_transports=possible_transports)
2299
2359
# this changes the behaviour of result.clone to create a new reference
2300
2360
# rather than a copy of the content of the branch.
2301
2361
# I did not use a proxy object because that needs much more extensive
2383
2443
def __init__(self, _format=None,
2384
2444
_control_files=None, a_bzrdir=None, name=None,
2385
_repository=None, ignore_fallbacks=False):
2445
_repository=None, ignore_fallbacks=False,
2446
possible_transports=None):
2386
2447
"""Create new branch object at a particular location."""
2387
2448
if a_bzrdir is None:
2388
2449
raise ValueError('a_bzrdir must be supplied')
2390
2451
self.bzrdir = a_bzrdir
2391
self._base = self.bzrdir.transport.clone('..').base
2452
self._user_transport = self.bzrdir.transport.clone('..')
2453
if name is not None:
2454
self._user_transport.set_segment_parameter(
2455
"branch", urlutils.escape(name))
2456
self._base = self._user_transport.base
2392
2457
self.name = name
2393
# XXX: We should be able to just do
2394
# self.base = self.bzrdir.root_transport.base
2395
# but this does not quite work yet -- mbp 20080522
2396
2458
self._format = _format
2397
2459
if _control_files is None:
2398
2460
raise ValueError('BzrBranch _control_files is None')
2399
2461
self.control_files = _control_files
2400
2462
self._transport = _control_files._transport
2401
2463
self.repository = _repository
2402
Branch.__init__(self)
2464
Branch.__init__(self, possible_transports)
2404
2466
def __str__(self):
2405
if self.name is None:
2406
return '%s(%s)' % (self.__class__.__name__, self.user_url)
2408
return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
2467
return '%s(%s)' % (self.__class__.__name__, self.user_url)
2411
2469
__repr__ = __str__
2504
2569
raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2505
2570
revision_id = _mod_revision.ensure_null(revision_id)
2506
2571
old_revno, old_revid = self.last_revision_info()
2507
if self._get_append_revisions_only():
2572
if self.get_append_revisions_only():
2508
2573
self._check_history_violation(revision_id)
2509
2574
self._run_pre_change_branch_tip_hooks(revno, revision_id)
2510
2575
self._write_last_revision_info(revno, revision_id)
2653
2718
self._transport.put_bytes('last-revision', out_string,
2654
2719
mode=self.bzrdir._get_file_mode())
2722
def update_feature_flags(self, updated_flags):
2723
"""Update the feature flags for this branch.
2725
:param updated_flags: Dictionary mapping feature names to necessities
2726
A necessity can be None to indicate the feature should be removed
2728
self._format._update_feature_flags(updated_flags)
2729
self.control_transport.put_bytes('format', self._format.as_string())
2657
2732
class FullHistoryBzrBranch(BzrBranch):
2658
2733
"""Bzr branch which contains the full revision history."""
2765
2840
class BzrBranch8(BzrBranch):
2766
2841
"""A branch that stores tree-reference locations."""
2768
def _open_hook(self):
2843
def _open_hook(self, possible_transports=None):
2769
2844
if self._ignore_fallbacks:
2846
if possible_transports is None:
2847
possible_transports = [self.bzrdir.root_transport]
2772
2849
url = self.get_stacked_on_url()
2773
2850
except (errors.UnstackableRepositoryFormat, errors.NotStacked,
2781
2858
raise AssertionError(
2782
2859
"'transform_fallback_location' hook %s returned "
2783
2860
"None, not a URL." % hook_name)
2784
self._activate_fallback_location(url)
2861
self._activate_fallback_location(url,
2862
possible_transports=possible_transports)
2786
2864
def __init__(self, *args, **kwargs):
2787
2865
self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
2905
2983
"""See Branch.set_push_location."""
2906
2984
self._master_branch_cache = None
2908
config = self.get_config()
2986
conf = self.get_config_stack()
2909
2987
if location is None:
2910
if config.get_user_option('bound') != 'True':
2988
if not conf.get('bound'):
2913
config.set_user_option('bound', 'False', warn_masked=True)
2991
conf.set('bound', 'False')
2916
2994
self._set_config_location('bound_location', location,
2918
config.set_user_option('bound', 'True', warn_masked=True)
2996
conf.set('bound', 'True')
2921
2999
def _get_bound_location(self, bound):
2922
3000
"""Return the bound location in the config file.
2924
3002
Return None if the bound parameter does not match"""
2925
config = self.get_config()
2926
config_bound = (config.get_user_option('bound') == 'True')
2927
if config_bound != bound:
3003
conf = self.get_config_stack()
3004
if conf.get('bound') != bound:
2929
return self._get_config_location('bound_location', config=config)
3006
return self._get_config_location('bound_location', config=conf)
2931
3008
def get_bound_location(self):
2932
3009
"""See Branch.set_push_location."""
2942
3019
## self._check_stackable_repo()
2943
3020
# stacked_on_location is only ever defined in branch.conf, so don't
2944
3021
# waste effort reading the whole stack of config files.
2945
config = self.get_config()._get_branch_data_config()
3022
conf = _mod_config.BranchOnlyStack(self)
2946
3023
stacked_url = self._get_config_location('stacked_on_location',
2948
3025
if stacked_url is None:
2949
3026
raise errors.NotStacked(self)
2952
def _get_append_revisions_only(self):
2953
return self.get_config(
2954
).get_user_option_as_bool('append_revisions_only')
3027
return stacked_url.encode('utf-8')
2956
3029
@needs_read_lock
2957
3030
def get_rev_id(self, revno, history=None):
2987
3060
except errors.RevisionNotPresent, e:
2988
3061
raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
2989
3062
index = len(self._partial_revision_history_cache) - 1
3064
raise errors.NoSuchRevision(self, revision_id)
2990
3065
if self._partial_revision_history_cache[index] != revision_id:
2991
3066
raise errors.NoSuchRevision(self, revision_id)
2992
3067
return self.revno() - index
3055
3131
return self.new_revno - self.old_revno
3057
3133
def report(self, to_file):
3134
tag_conflicts = getattr(self, "tag_conflicts", None)
3135
tag_updates = getattr(self, "tag_updates", None)
3058
3136
if not is_quiet():
3059
if self.old_revid == self.new_revid:
3060
to_file.write('No revisions to pull.\n')
3137
if self.old_revid != self.new_revid:
3062
3138
to_file.write('Now on revision %d.\n' % self.new_revno)
3140
to_file.write('%d tag(s) updated.\n' % len(tag_updates))
3141
if self.old_revid == self.new_revid and not tag_updates:
3142
if not tag_conflicts:
3143
to_file.write('No revisions or tags to pull.\n')
3145
to_file.write('No revisions to pull.\n')
3063
3146
self._show_tag_conficts(to_file)
3091
3174
return self.new_revno - self.old_revno
3093
3176
def report(self, to_file):
3094
"""Write a human-readable description of the result."""
3095
if self.old_revid == self.new_revid:
3096
note('No new revisions to push.')
3098
note('Pushed up to revision %d.' % self.new_revno)
3177
# TODO: This function gets passed a to_file, but then
3178
# ignores it and calls note() instead. This is also
3179
# inconsistent with PullResult(), which writes to stdout.
3180
# -- JRV20110901, bug #838853
3181
tag_conflicts = getattr(self, "tag_conflicts", None)
3182
tag_updates = getattr(self, "tag_updates", None)
3184
if self.old_revid != self.new_revid:
3185
note(gettext('Pushed up to revision %d.') % self.new_revno)
3187
note(ngettext('%d tag updated.', '%d tags updated.', len(tag_updates)) % len(tag_updates))
3188
if self.old_revid == self.new_revid and not tag_updates:
3189
if not tag_conflicts:
3190
note(gettext('No new revisions or tags to push.'))
3192
note(gettext('No new revisions to push.'))
3099
3193
self._show_tag_conficts(to_file)
3115
3209
:param verbose: Requests more detailed display of what was checked,
3118
note('checked branch %s format %s', self.branch.user_url,
3119
self.branch._format)
3212
note(gettext('checked branch {0} format {1}').format(
3213
self.branch.user_url, self.branch._format))
3120
3214
for error in self.errors:
3121
note('found error:%s', error)
3215
note(gettext('found error:%s'), error)
3124
3218
class Converter5to6(object):
3409
3503
self._update_revisions(stop_revision, overwrite=overwrite,
3411
3505
if self.source._push_should_merge_tags():
3412
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3506
result.tag_updates, result.tag_conflicts = (
3507
self.source.tags.merge_to(self.target.tags, overwrite))
3414
3508
result.new_revno, result.new_revid = self.target.last_revision_info()
3499
3593
# TODO: The old revid should be specified when merging tags,
3500
3594
# so a tags implementation that versions tags can only
3501
3595
# pull in the most recent changes. -- JRV20090506
3502
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3503
overwrite, ignore_master=not merge_tags_to_master)
3596
result.tag_updates, result.tag_conflicts = (
3597
self.source.tags.merge_to(self.target.tags, overwrite,
3598
ignore_master=not merge_tags_to_master))
3504
3599
result.new_revno, result.new_revid = self.target.last_revision_info()
3505
3600
if _hook_master:
3506
3601
result.master_branch = _hook_master