~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Samuel Bronson
  • Date: 2012-08-30 20:36:18 UTC
  • mto: (6015.57.3 2.4)
  • mto: This revision was merged to the branch mainline in revision 6558.
  • Revision ID: naesten@gmail.com-20120830203618-y2dzw91nqpvpgxvx
Update INSTALL for switch to Python 2.6 and up.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
16
16
 
17
 
from __future__ import absolute_import
18
 
 
19
 
import bzrlib.bzrdir
20
17
 
21
18
from cStringIO import StringIO
 
19
import sys
22
20
 
23
21
from bzrlib.lazy_import import lazy_import
24
22
lazy_import(globals(), """
25
 
import itertools
 
23
from itertools import chain
26
24
from bzrlib import (
27
 
    bzrdir,
28
 
    controldir,
29
 
    cache_utf8,
30
 
    cleanup,
31
 
    config as _mod_config,
32
 
    debug,
33
 
    errors,
34
 
    fetch,
35
 
    graph as _mod_graph,
36
 
    lockdir,
37
 
    lockable_files,
38
 
    remote,
39
 
    repository,
40
 
    revision as _mod_revision,
41
 
    rio,
42
 
    tag as _mod_tag,
43
 
    transport,
44
 
    ui,
45
 
    urlutils,
46
 
    vf_search,
 
25
        bzrdir,
 
26
        cache_utf8,
 
27
        cleanup,
 
28
        config as _mod_config,
 
29
        debug,
 
30
        errors,
 
31
        fetch,
 
32
        graph as _mod_graph,
 
33
        lockdir,
 
34
        lockable_files,
 
35
        remote,
 
36
        repository,
 
37
        revision as _mod_revision,
 
38
        rio,
 
39
        transport,
 
40
        ui,
 
41
        urlutils,
 
42
        )
 
43
from bzrlib.config import BranchConfig, TransportConfig
 
44
from bzrlib.tag import (
 
45
    BasicTags,
 
46
    DisabledTags,
47
47
    )
48
 
from bzrlib.i18n import gettext, ngettext
49
48
""")
50
49
 
51
 
# Explicitly import bzrlib.bzrdir so that the BzrProber
52
 
# is guaranteed to be registered.
53
 
import bzrlib.bzrdir
54
 
 
55
50
from bzrlib import (
56
 
    bzrdir,
57
51
    controldir,
58
52
    )
59
53
from bzrlib.decorators import (
72
66
from bzrlib.trace import mutter, mutter_callsite, note, is_quiet
73
67
 
74
68
 
 
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"
 
72
 
 
73
 
75
74
class Branch(controldir.ControlComponent):
76
75
    """Branch holding a history of revisions.
77
76
 
94
93
    def user_transport(self):
95
94
        return self.bzrdir.user_transport
96
95
 
97
 
    def __init__(self, possible_transports=None):
 
96
    def __init__(self, *ignored, **ignored_too):
98
97
        self.tags = self._format.make_tags(self)
99
98
        self._revision_history_cache = None
100
99
        self._revision_id_to_revno_cache = None
104
103
        self._last_revision_info_cache = None
105
104
        self._master_branch_cache = None
106
105
        self._merge_sorted_revisions_cache = None
107
 
        self._open_hook(possible_transports)
 
106
        self._open_hook()
108
107
        hooks = Branch.hooks['open']
109
108
        for hook in hooks:
110
109
            hook(self)
111
110
 
112
 
    def _open_hook(self, possible_transports):
 
111
    def _open_hook(self):
113
112
        """Called by init to allow simpler extension of the base class."""
114
113
 
115
 
    def _activate_fallback_location(self, url, possible_transports):
 
114
    def _activate_fallback_location(self, url):
116
115
        """Activate the branch/repository from url as a fallback repository."""
117
116
        for existing_fallback_repo in self.repository._fallback_repositories:
118
117
            if existing_fallback_repo.user_url == url:
119
118
                # This fallback is already configured.  This probably only
120
 
                # happens because ControlDir.sprout is a horrible mess.  To avoid
 
119
                # happens because BzrDir.sprout is a horrible mess.  To avoid
121
120
                # confusing _unstack we don't add this a second time.
122
121
                mutter('duplicate activation of fallback %r on %r', url, self)
123
122
                return
124
 
        repo = self._get_fallback_repository(url, possible_transports)
 
123
        repo = self._get_fallback_repository(url)
125
124
        if repo.has_same_location(self.repository):
126
125
            raise errors.UnstackableLocationError(self.user_url, url)
127
126
        self.repository.add_fallback_repository(repo)
181
180
        For instance, if the branch is at URL/.bzr/branch,
182
181
        Branch.open(URL) -> a Branch instance.
183
182
        """
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)
 
183
        control = bzrdir.BzrDir.open(base, _unsupported,
 
184
                                     possible_transports=possible_transports)
 
185
        return control.open_branch(unsupported=_unsupported)
188
186
 
189
187
    @staticmethod
190
 
    def open_from_transport(transport, name=None, _unsupported=False,
191
 
            possible_transports=None):
 
188
    def open_from_transport(transport, name=None, _unsupported=False):
192
189
        """Open the branch rooted at transport"""
193
 
        control = controldir.ControlDir.open_from_transport(transport, _unsupported)
194
 
        return control.open_branch(name=name, unsupported=_unsupported,
195
 
            possible_transports=possible_transports)
 
190
        control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
 
191
        return control.open_branch(name=name, unsupported=_unsupported)
196
192
 
197
193
    @staticmethod
198
194
    def open_containing(url, possible_transports=None):
206
202
        format, UnknownFormatError or UnsupportedFormatError are raised.
207
203
        If there is one, it is returned, along with the unused portion of url.
208
204
        """
209
 
        control, relpath = controldir.ControlDir.open_containing(url,
 
205
        control, relpath = bzrdir.BzrDir.open_containing(url,
210
206
                                                         possible_transports)
211
 
        branch = control.open_branch(possible_transports=possible_transports)
212
 
        return (branch, relpath)
 
207
        return control.open_branch(), relpath
213
208
 
214
209
    def _push_should_merge_tags(self):
215
210
        """Should _basic_push merge this branch's tags into the target?
227
222
 
228
223
        :return: A bzrlib.config.BranchConfig.
229
224
        """
230
 
        return _mod_config.BranchConfig(self)
231
 
 
232
 
    def get_config_stack(self):
233
 
        """Get a bzrlib.config.BranchStack for this Branch.
234
 
 
235
 
        This can then be used to get and set configuration options for the
236
 
        branch.
237
 
 
238
 
        :return: A bzrlib.config.BranchStack.
239
 
        """
240
 
        return _mod_config.BranchStack(self)
 
225
        return BranchConfig(self)
241
226
 
242
227
    def _get_config(self):
243
228
        """Get the concrete config for just the config in this branch.
251
236
        """
252
237
        raise NotImplementedError(self._get_config)
253
238
 
254
 
    def _get_fallback_repository(self, url, possible_transports):
 
239
    def _get_fallback_repository(self, url):
255
240
        """Get the repository we fallback to at url."""
256
241
        url = urlutils.join(self.base, url)
257
 
        a_branch = Branch.open(url, possible_transports=possible_transports)
 
242
        a_branch = Branch.open(url,
 
243
            possible_transports=[self.bzrdir.root_transport])
258
244
        return a_branch.repository
259
245
 
260
246
    @needs_read_lock
534
520
                    # The decision to include the start or not
535
521
                    # depends on the stop_rule if a stop is provided
536
522
                    # so pop this node back into the iterator
537
 
                    rev_iter = itertools.chain(iter([node]), rev_iter)
 
523
                    rev_iter = chain(iter([node]), rev_iter)
538
524
                    break
539
525
        if stop_revision_id is None:
540
526
            # Yield everything
665
651
        """
666
652
        raise errors.UpgradeRequired(self.user_url)
667
653
 
668
 
    def get_append_revisions_only(self):
669
 
        """Whether it is only possible to append revisions to the history.
670
 
        """
671
 
        if not self._format.supports_set_append_revisions_only():
672
 
            return False
673
 
        return self.get_config_stack().get('append_revisions_only')
674
 
 
675
654
    def set_append_revisions_only(self, enabled):
676
655
        if not self._format.supports_set_append_revisions_only():
677
656
            raise errors.UpgradeRequired(self.user_url)
678
 
        self.get_config_stack().set('append_revisions_only', enabled)
 
657
        if enabled:
 
658
            value = 'True'
 
659
        else:
 
660
            value = 'False'
 
661
        self.get_config().set_user_option('append_revisions_only', value,
 
662
            warn_masked=True)
679
663
 
680
664
    def set_reference_info(self, file_id, tree_path, branch_location):
681
665
        """Set the branch location to use for a tree reference."""
710
694
        """
711
695
        raise errors.UpgradeRequired(self.user_url)
712
696
 
713
 
    def get_commit_builder(self, parents, config_stack=None, timestamp=None,
 
697
    def get_commit_builder(self, parents, config=None, timestamp=None,
714
698
                           timezone=None, committer=None, revprops=None,
715
699
                           revision_id=None, lossy=False):
716
700
        """Obtain a CommitBuilder for this branch.
726
710
            represented, when pushing to a foreign VCS 
727
711
        """
728
712
 
729
 
        if config_stack is None:
730
 
            config_stack = self.get_config_stack()
 
713
        if config is None:
 
714
            config = self.get_config()
731
715
 
732
 
        return self.repository.get_commit_builder(self, parents, config_stack,
 
716
        return self.repository.get_commit_builder(self, parents, config,
733
717
            timestamp, timezone, committer, revprops, revision_id,
734
718
            lossy)
735
719
 
740
724
        """
741
725
        return None
742
726
 
743
 
    @deprecated_method(deprecated_in((2, 5, 0)))
744
727
    def get_revision_delta(self, revno):
745
728
        """Return the delta for one revision.
746
729
 
747
730
        The delta is relative to its mainline predecessor, or the
748
731
        empty tree for revision 1.
749
732
        """
750
 
        try:
751
 
            revid = self.get_rev_id(revno)
752
 
        except errors.NoSuchRevision:
 
733
        rh = self.revision_history()
 
734
        if not (1 <= revno <= len(rh)):
753
735
            raise errors.InvalidRevisionNumber(revno)
754
 
        return self.repository.get_revision_delta(revid)
 
736
        return self.repository.get_revision_delta(rh[revno-1])
755
737
 
756
738
    def get_stacked_on_url(self):
757
739
        """Get the URL this branch is stacked against.
856
838
                return
857
839
            self._unstack()
858
840
        else:
859
 
            self._activate_fallback_location(url,
860
 
                possible_transports=[self.bzrdir.root_transport])
 
841
            self._activate_fallback_location(url)
861
842
        # write this out after the repository is stacked to avoid setting a
862
843
        # stacked config that doesn't work.
863
844
        self._set_config_location('stacked_on_location', url)
869
850
        """
870
851
        pb = ui.ui_factory.nested_progress_bar()
871
852
        try:
872
 
            pb.update(gettext("Unstacking"))
 
853
            pb.update("Unstacking")
873
854
            # The basic approach here is to fetch the tip of the branch,
874
855
            # including all available ghosts, from the existing stacked
875
856
            # repository into a new repository object without the fallbacks. 
889
870
            # stream from one of them to the other.  This does mean doing
890
871
            # separate SSH connection setup, but unstacking is not a
891
872
            # common operation so it's tolerable.
892
 
            new_bzrdir = controldir.ControlDir.open(
893
 
                self.bzrdir.root_transport.base)
 
873
            new_bzrdir = bzrdir.BzrDir.open(self.bzrdir.root_transport.base)
894
874
            new_repository = new_bzrdir.find_repository()
895
875
            if new_repository._fallback_repositories:
896
876
                raise AssertionError("didn't expect %r to have "
939
919
                    tags_to_fetch = set(self.tags.get_reverse_tag_dict())
940
920
                except errors.TagsNotSupported:
941
921
                    tags_to_fetch = set()
942
 
                fetch_spec = vf_search.NotInOtherForRevs(self.repository,
 
922
                fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
943
923
                    old_repository, required_ids=[self.last_revision()],
944
924
                    if_present_ids=tags_to_fetch, find_ghosts=True).execute()
945
925
                self.repository.fetch(old_repository, fetch_spec=fetch_spec)
1013
993
        """
1014
994
        raise NotImplementedError(self._gen_revision_history)
1015
995
 
1016
 
    @deprecated_method(deprecated_in((2, 5, 0)))
1017
996
    @needs_read_lock
1018
997
    def revision_history(self):
1019
998
        """Return sequence of revision ids on this branch.
1021
1000
        This method will cache the revision history for as long as it is safe to
1022
1001
        do so.
1023
1002
        """
1024
 
        return self._revision_history()
1025
 
 
1026
 
    def _revision_history(self):
1027
1003
        if 'evil' in debug.debug_flags:
1028
1004
            mutter_callsite(3, "revision_history scales with history.")
1029
1005
        if self._revision_history_cache is not None:
1099
1075
        """Given a revision id, return its revno"""
1100
1076
        if _mod_revision.is_null(revision_id):
1101
1077
            return 0
1102
 
        history = self._revision_history()
 
1078
        history = self.revision_history()
1103
1079
        try:
1104
1080
            return history.index(revision_id) + 1
1105
1081
        except ValueError:
1170
1146
    def _set_config_location(self, name, url, config=None,
1171
1147
                             make_relative=False):
1172
1148
        if config is None:
1173
 
            config = self.get_config_stack()
 
1149
            config = self.get_config()
1174
1150
        if url is None:
1175
1151
            url = ''
1176
1152
        elif make_relative:
1177
1153
            url = urlutils.relative_url(self.base, url)
1178
 
        config.set(name, url)
 
1154
        config.set_user_option(name, url, warn_masked=True)
1179
1155
 
1180
1156
    def _get_config_location(self, name, config=None):
1181
1157
        if config is None:
1182
 
            config = self.get_config_stack()
1183
 
        location = config.get(name)
 
1158
            config = self.get_config()
 
1159
        location = config.get_user_option(name)
1184
1160
        if location == '':
1185
1161
            location = None
1186
1162
        return location
1187
1163
 
1188
1164
    def get_child_submit_format(self):
1189
1165
        """Return the preferred format of submissions to this branch."""
1190
 
        return self.get_config_stack().get('child_submit_format')
 
1166
        return self.get_config().get_user_option("child_submit_format")
1191
1167
 
1192
1168
    def get_submit_branch(self):
1193
1169
        """Return the submit location of the branch.
1196
1172
        pattern is that the user can override it by specifying a
1197
1173
        location.
1198
1174
        """
1199
 
        return self.get_config_stack().get('submit_branch')
 
1175
        return self.get_config().get_user_option('submit_branch')
1200
1176
 
1201
1177
    def set_submit_branch(self, location):
1202
1178
        """Return the submit location of the branch.
1205
1181
        pattern is that the user can override it by specifying a
1206
1182
        location.
1207
1183
        """
1208
 
        self.get_config_stack().set('submit_branch', location)
 
1184
        self.get_config().set_user_option('submit_branch', location,
 
1185
            warn_masked=True)
1209
1186
 
1210
1187
    def get_public_branch(self):
1211
1188
        """Return the public location of the branch.
1224
1201
        self._set_config_location('public_branch', location)
1225
1202
 
1226
1203
    def get_push_location(self):
1227
 
        """Return None or the location to push this branch to."""
1228
 
        return self.get_config_stack().get('push_location')
 
1204
        """Return the None or the location to push this branch to."""
 
1205
        push_loc = self.get_config().get_user_option('push_location')
 
1206
        return push_loc
1229
1207
 
1230
1208
    def set_push_location(self, location):
1231
1209
        """Set a new push location for this branch."""
1400
1378
        # TODO: We should probably also check that self.revision_history
1401
1379
        # matches the repository for older branch formats.
1402
1380
        # If looking for the code that cross-checks repository parents against
1403
 
        # the Graph.iter_lefthand_ancestry output, that is now a repository
 
1381
        # the iter_reverse_revision_history output, that is now a repository
1404
1382
        # specific check.
1405
1383
        return result
1406
1384
 
1407
 
    def _get_checkout_format(self, lightweight=False):
 
1385
    def _get_checkout_format(self):
1408
1386
        """Return the most suitable metadir for a checkout of this branch.
1409
1387
        Weaves are used if this branch's repository uses weaves.
1410
1388
        """
1456
1434
        """
1457
1435
        t = transport.get_transport(to_location)
1458
1436
        t.ensure_base()
1459
 
        format = self._get_checkout_format(lightweight=lightweight)
1460
 
        try:
 
1437
        if lightweight:
 
1438
            format = self._get_checkout_format()
1461
1439
            checkout = format.initialize_on_transport(t)
1462
 
        except errors.AlreadyControlDirError:
1463
 
            # It's fine if the control directory already exists,
1464
 
            # as long as there is no existing branch and working tree.
1465
 
            checkout = controldir.ControlDir.open_from_transport(t)
1466
 
            try:
1467
 
                checkout.open_branch()
1468
 
            except errors.NotBranchError:
1469
 
                pass
1470
 
            else:
1471
 
                raise errors.AlreadyControlDirError(t.base)
1472
 
            if checkout.control_transport.base == self.bzrdir.control_transport.base:
1473
 
                # When checking out to the same control directory,
1474
 
                # always create a lightweight checkout
1475
 
                lightweight = True
1476
 
 
1477
 
        if lightweight:
1478
 
            from_branch = checkout.set_branch_reference(target_branch=self)
 
1440
            from_branch = BranchReferenceFormat().initialize(checkout, 
 
1441
                target_branch=self)
1479
1442
        else:
1480
 
            policy = checkout.determine_repository_policy()
1481
 
            repo = policy.acquire_repository()[0]
1482
 
            checkout_branch = checkout.create_branch()
 
1443
            format = self._get_checkout_format()
 
1444
            checkout_branch = bzrdir.BzrDir.create_branch_convenience(
 
1445
                to_location, force_new_tree=False, format=format)
 
1446
            checkout = checkout_branch.bzrdir
1483
1447
            checkout_branch.bind(self)
1484
1448
            # pull up to the specified revision_id to set the initial
1485
1449
            # branch tip correctly, and seed it with history.
1486
1450
            checkout_branch.pull(self, stop_revision=revision_id)
1487
 
            from_branch = None
 
1451
            from_branch=None
1488
1452
        tree = checkout.create_workingtree(revision_id,
1489
1453
                                           from_branch=from_branch,
1490
1454
                                           accelerator_tree=accelerator_tree,
1579
1543
            heads that must be fetched if present, but no error is necessary if
1580
1544
            they are not present.
1581
1545
        """
1582
 
        # For bzr native formats must_fetch is just the tip, and
1583
 
        # if_present_fetch are the tags.
 
1546
        # For bzr native formats must_fetch is just the tip, and if_present_fetch
 
1547
        # are the tags.
1584
1548
        must_fetch = set([self.last_revision()])
1585
1549
        if_present_fetch = set()
1586
 
        if self.get_config_stack().get('branch.fetch_tags'):
 
1550
        c = self.get_config()
 
1551
        include_tags = c.get_user_option_as_bool('branch.fetch_tags',
 
1552
                                                 default=False)
 
1553
        if include_tags:
1587
1554
            try:
1588
1555
                if_present_fetch = set(self.tags.get_reverse_tag_dict())
1589
1556
            except errors.TagsNotSupported:
1598
1565
 
1599
1566
    Formats provide three things:
1600
1567
     * An initialization routine,
1601
 
     * a format description
 
1568
     * a format string,
1602
1569
     * an open routine.
1603
1570
 
1604
1571
    Formats are placed in an dict by their format string for reference
1611
1578
    object will be created every time regardless.
1612
1579
    """
1613
1580
 
 
1581
    can_set_append_revisions_only = True
 
1582
 
1614
1583
    def __eq__(self, other):
1615
1584
        return self.__class__ is other.__class__
1616
1585
 
1618
1587
        return not (self == other)
1619
1588
 
1620
1589
    @classmethod
 
1590
    def find_format(klass, a_bzrdir, name=None):
 
1591
        """Return the format for the branch object in a_bzrdir."""
 
1592
        try:
 
1593
            transport = a_bzrdir.get_branch_transport(None, name=name)
 
1594
            format_string = bzrdir.extract_format_string(
 
1595
                transport.get_bytes("format"))
 
1596
            return format_registry.get(format_string)
 
1597
        except errors.NoSuchFile:
 
1598
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
 
1599
        except KeyError:
 
1600
            raise errors.UnknownFormatError(format=format_string, kind='branch')
 
1601
 
 
1602
    @classmethod
1621
1603
    @deprecated_method(deprecated_in((2, 4, 0)))
1622
1604
    def get_default_format(klass):
1623
1605
        """Return the current default format."""
1633
1615
        """
1634
1616
        return format_registry._get_all()
1635
1617
 
1636
 
    def get_reference(self, controldir, name=None):
1637
 
        """Get the target reference of the branch in controldir.
 
1618
    def get_reference(self, a_bzrdir, name=None):
 
1619
        """Get the target reference of the branch in a_bzrdir.
1638
1620
 
1639
1621
        format probing must have been completed before calling
1640
1622
        this method - it is assumed that the format of the branch
1641
 
        in controldir is correct.
 
1623
        in a_bzrdir is correct.
1642
1624
 
1643
 
        :param controldir: The controldir to get the branch data from.
 
1625
        :param a_bzrdir: The bzrdir to get the branch data from.
1644
1626
        :param name: Name of the colocated branch to fetch
1645
1627
        :return: None if the branch is not a reference branch.
1646
1628
        """
1647
1629
        return None
1648
1630
 
1649
1631
    @classmethod
1650
 
    def set_reference(self, controldir, name, to_branch):
1651
 
        """Set the target reference of the branch in controldir.
 
1632
    def set_reference(self, a_bzrdir, name, to_branch):
 
1633
        """Set the target reference of the branch in a_bzrdir.
1652
1634
 
1653
1635
        format probing must have been completed before calling
1654
1636
        this method - it is assumed that the format of the branch
1655
 
        in controldir is correct.
 
1637
        in a_bzrdir is correct.
1656
1638
 
1657
 
        :param controldir: The controldir to set the branch reference for.
 
1639
        :param a_bzrdir: The bzrdir to set the branch reference for.
1658
1640
        :param name: Name of colocated branch to set, None for default
1659
1641
        :param to_branch: branch that the checkout is to reference
1660
1642
        """
1661
1643
        raise NotImplementedError(self.set_reference)
1662
1644
 
 
1645
    def get_format_string(self):
 
1646
        """Return the ASCII format string that identifies this format."""
 
1647
        raise NotImplementedError(self.get_format_string)
 
1648
 
1663
1649
    def get_format_description(self):
1664
1650
        """Return the short format description for this format."""
1665
1651
        raise NotImplementedError(self.get_format_description)
1666
1652
 
1667
 
    def _run_post_branch_init_hooks(self, controldir, name, branch):
 
1653
    def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
1668
1654
        hooks = Branch.hooks['post_branch_init']
1669
1655
        if not hooks:
1670
1656
            return
1671
 
        params = BranchInitHookParams(self, controldir, name, branch)
 
1657
        params = BranchInitHookParams(self, a_bzrdir, name, branch)
1672
1658
        for hook in hooks:
1673
1659
            hook(params)
1674
1660
 
1675
 
    def initialize(self, controldir, name=None, repository=None,
1676
 
                   append_revisions_only=None):
1677
 
        """Create a branch of this format in controldir.
1678
 
 
 
1661
    def initialize(self, a_bzrdir, name=None, repository=None):
 
1662
        """Create a branch of this format in a_bzrdir.
 
1663
        
1679
1664
        :param name: Name of the colocated branch to create.
1680
1665
        """
1681
1666
        raise NotImplementedError(self.initialize)
1701
1686
        Note that it is normal for branch to be a RemoteBranch when using tags
1702
1687
        on a RemoteBranch.
1703
1688
        """
1704
 
        return _mod_tag.DisabledTags(branch)
 
1689
        return DisabledTags(branch)
1705
1690
 
1706
1691
    def network_name(self):
1707
1692
        """A simple byte string uniquely identifying this format for RPC calls.
1713
1698
        """
1714
1699
        raise NotImplementedError(self.network_name)
1715
1700
 
1716
 
    def open(self, controldir, name=None, _found=False, ignore_fallbacks=False,
1717
 
            found_repository=None, possible_transports=None):
1718
 
        """Return the branch object for controldir.
 
1701
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
 
1702
            found_repository=None):
 
1703
        """Return the branch object for a_bzrdir
1719
1704
 
1720
 
        :param controldir: A ControlDir that contains a branch.
 
1705
        :param a_bzrdir: A BzrDir that contains a branch.
1721
1706
        :param name: Name of colocated branch to open
1722
1707
        :param _found: a private parameter, do not use it. It is used to
1723
1708
            indicate if format probing has already be done.
1765
1750
        """True if this format supports tags stored in the branch"""
1766
1751
        return False  # by default
1767
1752
 
1768
 
    def tags_are_versioned(self):
1769
 
        """Whether the tag container for this branch versions tags."""
1770
 
        return False
1771
 
 
1772
 
    def supports_tags_referencing_ghosts(self):
1773
 
        """True if tags can reference ghost revisions."""
1774
 
        return True
1775
 
 
1776
1753
 
1777
1754
class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
1778
1755
    """A factory for a BranchFormat object, permitting simple lazy registration.
1792
1769
        """
1793
1770
        registry._LazyObjectGetter.__init__(self, module_name, member_name)
1794
1771
        self._format_string = format_string
1795
 
 
 
1772
        
1796
1773
    def get_format_string(self):
1797
1774
        """See BranchFormat.get_format_string."""
1798
1775
        return self._format_string
1943
1920
    There are 4 fields that hooks may wish to access:
1944
1921
 
1945
1922
    :ivar format: the branch format
1946
 
    :ivar bzrdir: the ControlDir where the branch will be/has been initialized
 
1923
    :ivar bzrdir: the BzrDir where the branch will be/has been initialized
1947
1924
    :ivar name: name of colocated branch, if any (or None)
1948
1925
    :ivar branch: the branch created
1949
1926
 
1952
1929
    branch, which refer to the original branch.
1953
1930
    """
1954
1931
 
1955
 
    def __init__(self, format, controldir, name, branch):
 
1932
    def __init__(self, format, a_bzrdir, name, branch):
1956
1933
        """Create a group of BranchInitHook parameters.
1957
1934
 
1958
1935
        :param format: the branch format
1959
 
        :param controldir: the ControlDir where the branch will be/has been
 
1936
        :param a_bzrdir: the BzrDir where the branch will be/has been
1960
1937
            initialized
1961
1938
        :param name: name of colocated branch, if any (or None)
1962
1939
        :param branch: the branch created
1966
1943
        in branch, which refer to the original branch.
1967
1944
        """
1968
1945
        self.format = format
1969
 
        self.bzrdir = controldir
 
1946
        self.bzrdir = a_bzrdir
1970
1947
        self.name = name
1971
1948
        self.branch = branch
1972
1949
 
1982
1959
 
1983
1960
    There are 4 fields that hooks may wish to access:
1984
1961
 
1985
 
    :ivar control_dir: ControlDir of the checkout to change
 
1962
    :ivar control_dir: BzrDir of the checkout to change
1986
1963
    :ivar to_branch: branch that the checkout is to reference
1987
1964
    :ivar force: skip the check for local commits in a heavy checkout
1988
1965
    :ivar revision_id: revision ID to switch to (or None)
1991
1968
    def __init__(self, control_dir, to_branch, force, revision_id):
1992
1969
        """Create a group of SwitchHook parameters.
1993
1970
 
1994
 
        :param control_dir: ControlDir of the checkout to change
 
1971
        :param control_dir: BzrDir of the checkout to change
1995
1972
        :param to_branch: branch that the checkout is to reference
1996
1973
        :param force: skip the check for local commits in a heavy checkout
1997
1974
        :param revision_id: revision ID to switch to (or None)
2010
1987
            self.revision_id)
2011
1988
 
2012
1989
 
2013
 
class BranchFormatMetadir(bzrdir.BzrFormat, BranchFormat):
2014
 
    """Base class for branch formats that live in meta directories.
2015
 
    """
2016
 
 
2017
 
    def __init__(self):
2018
 
        BranchFormat.__init__(self)
2019
 
        bzrdir.BzrFormat.__init__(self)
2020
 
 
2021
 
    @classmethod
2022
 
    def find_format(klass, controldir, name=None):
2023
 
        """Return the format for the branch object in controldir."""
2024
 
        try:
2025
 
            transport = controldir.get_branch_transport(None, name=name)
2026
 
        except errors.NoSuchFile:
2027
 
            raise errors.NotBranchError(path=name, bzrdir=controldir)
2028
 
        try:
2029
 
            format_string = transport.get_bytes("format")
2030
 
        except errors.NoSuchFile:
2031
 
            raise errors.NotBranchError(path=transport.base, bzrdir=controldir)
2032
 
        return klass._find_format(format_registry, 'branch', format_string)
 
1990
class BranchFormatMetadir(BranchFormat):
 
1991
    """Common logic for meta-dir based branch formats."""
2033
1992
 
2034
1993
    def _branch_class(self):
2035
1994
        """What class to instantiate on open calls."""
2036
1995
        raise NotImplementedError(self._branch_class)
2037
1996
 
2038
 
    def _get_initial_config(self, append_revisions_only=None):
2039
 
        if append_revisions_only:
2040
 
            return "append_revisions_only = True\n"
2041
 
        else:
2042
 
            # Avoid writing anything if append_revisions_only is disabled,
2043
 
            # as that is the default.
2044
 
            return ""
2045
 
 
2046
1997
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
2047
1998
                           repository=None):
2048
1999
        """Initialize a branch in a bzrdir, with specified files
2053
2004
        :param name: Name of colocated branch to create, if any
2054
2005
        :return: a branch in this format
2055
2006
        """
2056
 
        if name is None:
2057
 
            name = a_bzrdir._get_selected_branch()
2058
2007
        mutter('creating branch %r in %s', self, a_bzrdir.user_url)
2059
2008
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2060
2009
        control_files = lockable_files.LockableFiles(branch_transport,
2062
2011
        control_files.create_lock()
2063
2012
        control_files.lock_write()
2064
2013
        try:
2065
 
            utf8_files += [('format', self.as_string())]
 
2014
            utf8_files += [('format', self.get_format_string())]
2066
2015
            for (filename, content) in utf8_files:
2067
2016
                branch_transport.put_bytes(
2068
2017
                    filename, content,
2074
2023
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2075
2024
        return branch
2076
2025
 
 
2026
    def network_name(self):
 
2027
        """A simple byte string uniquely identifying this format for RPC calls.
 
2028
 
 
2029
        Metadir branch formats use their format string.
 
2030
        """
 
2031
        return self.get_format_string()
 
2032
 
2077
2033
    def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False,
2078
 
            found_repository=None, possible_transports=None):
 
2034
            found_repository=None):
2079
2035
        """See BranchFormat.open()."""
2080
 
        if name is None:
2081
 
            name = a_bzrdir._get_selected_branch()
2082
2036
        if not _found:
2083
 
            format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
 
2037
            format = BranchFormat.find_format(a_bzrdir, name=name)
2084
2038
            if format.__class__ != self.__class__:
2085
2039
                raise AssertionError("wrong format %r found for %r" %
2086
2040
                    (format, self))
2095
2049
                              name=name,
2096
2050
                              a_bzrdir=a_bzrdir,
2097
2051
                              _repository=found_repository,
2098
 
                              ignore_fallbacks=ignore_fallbacks,
2099
 
                              possible_transports=possible_transports)
 
2052
                              ignore_fallbacks=ignore_fallbacks)
2100
2053
        except errors.NoSuchFile:
2101
2054
            raise errors.NotBranchError(path=transport.base, bzrdir=a_bzrdir)
2102
2055
 
2103
 
    @property
2104
 
    def _matchingbzrdir(self):
2105
 
        ret = bzrdir.BzrDirMetaFormat1()
2106
 
        ret.set_branch_format(self)
2107
 
        return ret
 
2056
    def __init__(self):
 
2057
        super(BranchFormatMetadir, self).__init__()
 
2058
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
 
2059
        self._matchingbzrdir.set_branch_format(self)
2108
2060
 
2109
2061
    def supports_tags(self):
2110
2062
        return True
2112
2064
    def supports_leaving_lock(self):
2113
2065
        return True
2114
2066
 
2115
 
    def check_support_status(self, allow_unsupported, recommend_upgrade=True,
2116
 
            basedir=None):
2117
 
        BranchFormat.check_support_status(self,
2118
 
            allow_unsupported=allow_unsupported, recommend_upgrade=recommend_upgrade,
2119
 
            basedir=basedir)
2120
 
        bzrdir.BzrFormat.check_support_status(self, allow_unsupported=allow_unsupported,
2121
 
            recommend_upgrade=recommend_upgrade, basedir=basedir)
2122
 
 
2123
2067
 
2124
2068
class BzrBranchFormat5(BranchFormatMetadir):
2125
2069
    """Bzr branch format 5.
2137
2081
    def _branch_class(self):
2138
2082
        return BzrBranch5
2139
2083
 
2140
 
    @classmethod
2141
 
    def get_format_string(cls):
 
2084
    def get_format_string(self):
2142
2085
        """See BranchFormat.get_format_string()."""
2143
2086
        return "Bazaar-NG branch format 5\n"
2144
2087
 
2146
2089
        """See BranchFormat.get_format_description()."""
2147
2090
        return "Branch format 5"
2148
2091
 
2149
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2150
 
                   append_revisions_only=None):
 
2092
    def initialize(self, a_bzrdir, name=None, repository=None):
2151
2093
        """Create a branch of this format in a_bzrdir."""
2152
 
        if append_revisions_only:
2153
 
            raise errors.UpgradeRequired(a_bzrdir.user_url)
2154
2094
        utf8_files = [('revision-history', ''),
2155
2095
                      ('branch-name', ''),
2156
2096
                      ]
2174
2114
    def _branch_class(self):
2175
2115
        return BzrBranch6
2176
2116
 
2177
 
    @classmethod
2178
 
    def get_format_string(cls):
 
2117
    def get_format_string(self):
2179
2118
        """See BranchFormat.get_format_string()."""
2180
2119
        return "Bazaar Branch Format 6 (bzr 0.15)\n"
2181
2120
 
2183
2122
        """See BranchFormat.get_format_description()."""
2184
2123
        return "Branch format 6"
2185
2124
 
2186
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2187
 
                   append_revisions_only=None):
 
2125
    def initialize(self, a_bzrdir, name=None, repository=None):
2188
2126
        """Create a branch of this format in a_bzrdir."""
2189
2127
        utf8_files = [('last-revision', '0 null:\n'),
2190
 
                      ('branch.conf',
2191
 
                          self._get_initial_config(append_revisions_only)),
 
2128
                      ('branch.conf', ''),
2192
2129
                      ('tags', ''),
2193
2130
                      ]
2194
2131
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2195
2132
 
2196
2133
    def make_tags(self, branch):
2197
2134
        """See bzrlib.branch.BranchFormat.make_tags()."""
2198
 
        return _mod_tag.BasicTags(branch)
 
2135
        return BasicTags(branch)
2199
2136
 
2200
2137
    def supports_set_append_revisions_only(self):
2201
2138
        return True
2207
2144
    def _branch_class(self):
2208
2145
        return BzrBranch8
2209
2146
 
2210
 
    @classmethod
2211
 
    def get_format_string(cls):
 
2147
    def get_format_string(self):
2212
2148
        """See BranchFormat.get_format_string()."""
2213
2149
        return "Bazaar Branch Format 8 (needs bzr 1.15)\n"
2214
2150
 
2216
2152
        """See BranchFormat.get_format_description()."""
2217
2153
        return "Branch format 8"
2218
2154
 
2219
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2220
 
                   append_revisions_only=None):
 
2155
    def initialize(self, a_bzrdir, name=None, repository=None):
2221
2156
        """Create a branch of this format in a_bzrdir."""
2222
2157
        utf8_files = [('last-revision', '0 null:\n'),
2223
 
                      ('branch.conf',
2224
 
                          self._get_initial_config(append_revisions_only)),
 
2158
                      ('branch.conf', ''),
2225
2159
                      ('tags', ''),
2226
2160
                      ('references', '')
2227
2161
                      ]
2229
2163
 
2230
2164
    def make_tags(self, branch):
2231
2165
        """See bzrlib.branch.BranchFormat.make_tags()."""
2232
 
        return _mod_tag.BasicTags(branch)
 
2166
        return BasicTags(branch)
2233
2167
 
2234
2168
    def supports_set_append_revisions_only(self):
2235
2169
        return True
2249
2183
    This format was introduced in bzr 1.6.
2250
2184
    """
2251
2185
 
2252
 
    def initialize(self, a_bzrdir, name=None, repository=None,
2253
 
                   append_revisions_only=None):
 
2186
    def initialize(self, a_bzrdir, name=None, repository=None):
2254
2187
        """Create a branch of this format in a_bzrdir."""
2255
2188
        utf8_files = [('last-revision', '0 null:\n'),
2256
 
                      ('branch.conf',
2257
 
                          self._get_initial_config(append_revisions_only)),
 
2189
                      ('branch.conf', ''),
2258
2190
                      ('tags', ''),
2259
2191
                      ]
2260
2192
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2262
2194
    def _branch_class(self):
2263
2195
        return BzrBranch7
2264
2196
 
2265
 
    @classmethod
2266
 
    def get_format_string(cls):
 
2197
    def get_format_string(self):
2267
2198
        """See BranchFormat.get_format_string()."""
2268
2199
        return "Bazaar Branch Format 7 (needs bzr 1.6)\n"
2269
2200
 
2279
2210
 
2280
2211
    def make_tags(self, branch):
2281
2212
        """See bzrlib.branch.BranchFormat.make_tags()."""
2282
 
        return _mod_tag.BasicTags(branch)
 
2213
        return BasicTags(branch)
2283
2214
 
2284
2215
    supports_reference_locations = False
2285
2216
 
2286
2217
 
2287
 
class BranchReferenceFormat(BranchFormatMetadir):
 
2218
class BranchReferenceFormat(BranchFormat):
2288
2219
    """Bzr branch reference format.
2289
2220
 
2290
2221
    Branch references are used in implementing checkouts, they
2295
2226
     - a format string
2296
2227
    """
2297
2228
 
2298
 
    @classmethod
2299
 
    def get_format_string(cls):
 
2229
    def get_format_string(self):
2300
2230
        """See BranchFormat.get_format_string()."""
2301
2231
        return "Bazaar-NG Branch Reference Format 1\n"
2302
2232
 
2315
2245
        location = transport.put_bytes('location', to_branch.base)
2316
2246
 
2317
2247
    def initialize(self, a_bzrdir, name=None, target_branch=None,
2318
 
            repository=None, append_revisions_only=None):
 
2248
            repository=None):
2319
2249
        """Create a branch of this format in a_bzrdir."""
2320
2250
        if target_branch is None:
2321
2251
            # this format does not implement branch itself, thus the implicit
2322
2252
            # creation contract must see it as uninitializable
2323
2253
            raise errors.UninitializableFormat(self)
2324
2254
        mutter('creating branch reference in %s', a_bzrdir.user_url)
2325
 
        if a_bzrdir._format.fixed_components:
2326
 
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
2327
 
        if name is None:
2328
 
            name = a_bzrdir._get_selected_branch()
2329
2255
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2330
2256
        branch_transport.put_bytes('location',
2331
 
            target_branch.user_url)
2332
 
        branch_transport.put_bytes('format', self.as_string())
2333
 
        branch = self.open(a_bzrdir, name, _found=True,
 
2257
            target_branch.bzrdir.user_url)
 
2258
        branch_transport.put_bytes('format', self.get_format_string())
 
2259
        branch = self.open(
 
2260
            a_bzrdir, name, _found=True,
2334
2261
            possible_transports=[target_branch.bzrdir.root_transport])
2335
2262
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
2336
2263
        return branch
2337
2264
 
 
2265
    def __init__(self):
 
2266
        super(BranchReferenceFormat, self).__init__()
 
2267
        self._matchingbzrdir = bzrdir.BzrDirMetaFormat1()
 
2268
        self._matchingbzrdir.set_branch_format(self)
 
2269
 
2338
2270
    def _make_reference_clone_function(format, a_branch):
2339
2271
        """Create a clone() routine for a branch dynamically."""
2340
2272
        def clone(to_bzrdir, revision_id=None,
2362
2294
            a_bzrdir.
2363
2295
        :param possible_transports: An optional reusable transports list.
2364
2296
        """
2365
 
        if name is None:
2366
 
            name = a_bzrdir._get_selected_branch()
2367
2297
        if not _found:
2368
 
            format = BranchFormatMetadir.find_format(a_bzrdir, name=name)
 
2298
            format = BranchFormat.find_format(a_bzrdir, name=name)
2369
2299
            if format.__class__ != self.__class__:
2370
2300
                raise AssertionError("wrong format %r found for %r" %
2371
2301
                    (format, self))
2372
2302
        if location is None:
2373
2303
            location = self.get_reference(a_bzrdir, name)
2374
 
        real_bzrdir = controldir.ControlDir.open(
 
2304
        real_bzrdir = bzrdir.BzrDir.open(
2375
2305
            location, possible_transports=possible_transports)
2376
 
        result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks,
2377
 
            possible_transports=possible_transports)
 
2306
        result = real_bzrdir.open_branch(name=name, 
 
2307
            ignore_fallbacks=ignore_fallbacks)
2378
2308
        # this changes the behaviour of result.clone to create a new reference
2379
2309
        # rather than a copy of the content of the branch.
2380
2310
        # I did not use a proxy object because that needs much more extensive
2461
2391
 
2462
2392
    def __init__(self, _format=None,
2463
2393
                 _control_files=None, a_bzrdir=None, name=None,
2464
 
                 _repository=None, ignore_fallbacks=False,
2465
 
                 possible_transports=None):
 
2394
                 _repository=None, ignore_fallbacks=False):
2466
2395
        """Create new branch object at a particular location."""
2467
2396
        if a_bzrdir is None:
2468
2397
            raise ValueError('a_bzrdir must be supplied')
2469
 
        if name is None:
2470
 
            raise ValueError('name must be supplied')
2471
 
        self.bzrdir = a_bzrdir
2472
 
        self._user_transport = self.bzrdir.transport.clone('..')
2473
 
        if name != "":
2474
 
            self._user_transport.set_segment_parameter(
2475
 
                "branch", urlutils.escape(name))
2476
 
        self._base = self._user_transport.base
 
2398
        else:
 
2399
            self.bzrdir = a_bzrdir
 
2400
        self._base = self.bzrdir.transport.clone('..').base
2477
2401
        self.name = name
 
2402
        # XXX: We should be able to just do
 
2403
        #   self.base = self.bzrdir.root_transport.base
 
2404
        # but this does not quite work yet -- mbp 20080522
2478
2405
        self._format = _format
2479
2406
        if _control_files is None:
2480
2407
            raise ValueError('BzrBranch _control_files is None')
2481
2408
        self.control_files = _control_files
2482
2409
        self._transport = _control_files._transport
2483
2410
        self.repository = _repository
2484
 
        Branch.__init__(self, possible_transports)
 
2411
        Branch.__init__(self)
2485
2412
 
2486
2413
    def __str__(self):
2487
 
        return '%s(%s)' % (self.__class__.__name__, self.user_url)
 
2414
        if self.name is None:
 
2415
            return '%s(%s)' % (self.__class__.__name__, self.user_url)
 
2416
        else:
 
2417
            return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
 
2418
                self.name)
2488
2419
 
2489
2420
    __repr__ = __str__
2490
2421
 
2494
2425
 
2495
2426
    base = property(_get_base, doc="The URL for the root of this branch.")
2496
2427
 
2497
 
    @property
2498
 
    def user_transport(self):
2499
 
        return self._user_transport
2500
 
 
2501
2428
    def _get_config(self):
2502
 
        return _mod_config.TransportConfig(self._transport, 'branch.conf')
2503
 
 
2504
 
    def _get_config_store(self):
2505
 
        return _mod_config.BranchStore(self)
 
2429
        return TransportConfig(self._transport, 'branch.conf')
2506
2430
 
2507
2431
    def is_locked(self):
2508
2432
        return self.control_files.is_locked()
2589
2513
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2590
2514
        revision_id = _mod_revision.ensure_null(revision_id)
2591
2515
        old_revno, old_revid = self.last_revision_info()
2592
 
        if self.get_append_revisions_only():
 
2516
        if self._get_append_revisions_only():
2593
2517
            self._check_history_violation(revision_id)
2594
2518
        self._run_pre_change_branch_tip_hooks(revno, revision_id)
2595
2519
        self._write_last_revision_info(revno, revision_id)
2738
2662
        self._transport.put_bytes('last-revision', out_string,
2739
2663
            mode=self.bzrdir._get_file_mode())
2740
2664
 
2741
 
    @needs_write_lock
2742
 
    def update_feature_flags(self, updated_flags):
2743
 
        """Update the feature flags for this branch.
2744
 
 
2745
 
        :param updated_flags: Dictionary mapping feature names to necessities
2746
 
            A necessity can be None to indicate the feature should be removed
2747
 
        """
2748
 
        self._format._update_feature_flags(updated_flags)
2749
 
        self.control_transport.put_bytes('format', self._format.as_string())
2750
 
 
2751
2665
 
2752
2666
class FullHistoryBzrBranch(BzrBranch):
2753
2667
    """Bzr branch which contains the full revision history."""
2766
2680
        self._set_revision_history(history)
2767
2681
 
2768
2682
    def _read_last_revision_info(self):
2769
 
        rh = self._revision_history()
 
2683
        rh = self.revision_history()
2770
2684
        revno = len(rh)
2771
2685
        if revno:
2772
2686
            return (revno, rh[-1])
2826
2740
        if revision_id == _mod_revision.NULL_REVISION:
2827
2741
            new_history = []
2828
2742
        else:
2829
 
            new_history = self._revision_history()
 
2743
            new_history = self.revision_history()
2830
2744
        if revision_id is not None and new_history != []:
2831
2745
            try:
2832
2746
                new_history = new_history[:new_history.index(revision_id) + 1]
2860
2774
class BzrBranch8(BzrBranch):
2861
2775
    """A branch that stores tree-reference locations."""
2862
2776
 
2863
 
    def _open_hook(self, possible_transports=None):
 
2777
    def _open_hook(self):
2864
2778
        if self._ignore_fallbacks:
2865
2779
            return
2866
 
        if possible_transports is None:
2867
 
            possible_transports = [self.bzrdir.root_transport]
2868
2780
        try:
2869
2781
            url = self.get_stacked_on_url()
2870
2782
        except (errors.UnstackableRepositoryFormat, errors.NotStacked,
2878
2790
                    raise AssertionError(
2879
2791
                        "'transform_fallback_location' hook %s returned "
2880
2792
                        "None, not a URL." % hook_name)
2881
 
            self._activate_fallback_location(url,
2882
 
                possible_transports=possible_transports)
 
2793
            self._activate_fallback_location(url)
2883
2794
 
2884
2795
    def __init__(self, *args, **kwargs):
2885
2796
        self._ignore_fallbacks = kwargs.get('ignore_fallbacks', False)
3003
2914
        """See Branch.set_push_location."""
3004
2915
        self._master_branch_cache = None
3005
2916
        result = None
3006
 
        conf = self.get_config_stack()
 
2917
        config = self.get_config()
3007
2918
        if location is None:
3008
 
            if not conf.get('bound'):
 
2919
            if config.get_user_option('bound') != 'True':
3009
2920
                return False
3010
2921
            else:
3011
 
                conf.set('bound', 'False')
 
2922
                config.set_user_option('bound', 'False', warn_masked=True)
3012
2923
                return True
3013
2924
        else:
3014
2925
            self._set_config_location('bound_location', location,
3015
 
                                      config=conf)
3016
 
            conf.set('bound', 'True')
 
2926
                                      config=config)
 
2927
            config.set_user_option('bound', 'True', warn_masked=True)
3017
2928
        return True
3018
2929
 
3019
2930
    def _get_bound_location(self, bound):
3020
2931
        """Return the bound location in the config file.
3021
2932
 
3022
2933
        Return None if the bound parameter does not match"""
3023
 
        conf = self.get_config_stack()
3024
 
        if conf.get('bound') != bound:
 
2934
        config = self.get_config()
 
2935
        config_bound = (config.get_user_option('bound') == 'True')
 
2936
        if config_bound != bound:
3025
2937
            return None
3026
 
        return self._get_config_location('bound_location', config=conf)
 
2938
        return self._get_config_location('bound_location', config=config)
3027
2939
 
3028
2940
    def get_bound_location(self):
3029
 
        """See Branch.get_bound_location."""
 
2941
        """See Branch.set_push_location."""
3030
2942
        return self._get_bound_location(True)
3031
2943
 
3032
2944
    def get_old_bound_location(self):
3039
2951
        ## self._check_stackable_repo()
3040
2952
        # stacked_on_location is only ever defined in branch.conf, so don't
3041
2953
        # waste effort reading the whole stack of config files.
3042
 
        conf = _mod_config.BranchOnlyStack(self)
 
2954
        config = self.get_config()._get_branch_data_config()
3043
2955
        stacked_url = self._get_config_location('stacked_on_location',
3044
 
                                                config=conf)
 
2956
            config=config)
3045
2957
        if stacked_url is None:
3046
2958
            raise errors.NotStacked(self)
3047
 
        return stacked_url.encode('utf-8')
 
2959
        return stacked_url
 
2960
 
 
2961
    def _get_append_revisions_only(self):
 
2962
        return self.get_config(
 
2963
            ).get_user_option_as_bool('append_revisions_only')
3048
2964
 
3049
2965
    @needs_read_lock
3050
2966
    def get_rev_id(self, revno, history=None):
3080
2996
            except errors.RevisionNotPresent, e:
3081
2997
                raise errors.GhostRevisionsHaveNoRevno(revision_id, e.revision_id)
3082
2998
            index = len(self._partial_revision_history_cache) - 1
3083
 
            if index < 0:
3084
 
                raise errors.NoSuchRevision(self, revision_id)
3085
2999
            if self._partial_revision_history_cache[index] != revision_id:
3086
3000
                raise errors.NoSuchRevision(self, revision_id)
3087
3001
        return self.revno() - index
3139
3053
    :ivar local_branch: target branch if there is a Master, else None
3140
3054
    :ivar target_branch: Target/destination branch object. (write locked)
3141
3055
    :ivar tag_conflicts: A list of tag conflicts, see BasicTags.merge_to
3142
 
    :ivar tag_updates: A dict with new tags, see BasicTags.merge_to
3143
3056
    """
3144
3057
 
3145
3058
    @deprecated_method(deprecated_in((2, 3, 0)))
3151
3064
        return self.new_revno - self.old_revno
3152
3065
 
3153
3066
    def report(self, to_file):
3154
 
        tag_conflicts = getattr(self, "tag_conflicts", None)
3155
 
        tag_updates = getattr(self, "tag_updates", None)
3156
3067
        if not is_quiet():
3157
 
            if self.old_revid != self.new_revid:
 
3068
            if self.old_revid == self.new_revid:
 
3069
                to_file.write('No revisions to pull.\n')
 
3070
            else:
3158
3071
                to_file.write('Now on revision %d.\n' % self.new_revno)
3159
 
            if tag_updates:
3160
 
                to_file.write('%d tag(s) updated.\n' % len(tag_updates))
3161
 
            if self.old_revid == self.new_revid and not tag_updates:
3162
 
                if not tag_conflicts:
3163
 
                    to_file.write('No revisions or tags to pull.\n')
3164
 
                else:
3165
 
                    to_file.write('No revisions to pull.\n')
3166
3072
        self._show_tag_conficts(to_file)
3167
3073
 
3168
3074
 
3194
3100
        return self.new_revno - self.old_revno
3195
3101
 
3196
3102
    def report(self, to_file):
3197
 
        # TODO: This function gets passed a to_file, but then
3198
 
        # ignores it and calls note() instead. This is also
3199
 
        # inconsistent with PullResult(), which writes to stdout.
3200
 
        # -- JRV20110901, bug #838853
3201
 
        tag_conflicts = getattr(self, "tag_conflicts", None)
3202
 
        tag_updates = getattr(self, "tag_updates", None)
3203
 
        if not is_quiet():
3204
 
            if self.old_revid != self.new_revid:
3205
 
                note(gettext('Pushed up to revision %d.') % self.new_revno)
3206
 
            if tag_updates:
3207
 
                note(ngettext('%d tag updated.', '%d tags updated.', len(tag_updates)) % len(tag_updates))
3208
 
            if self.old_revid == self.new_revid and not tag_updates:
3209
 
                if not tag_conflicts:
3210
 
                    note(gettext('No new revisions or tags to push.'))
3211
 
                else:
3212
 
                    note(gettext('No new revisions to push.'))
 
3103
        """Write a human-readable description of the result."""
 
3104
        if self.old_revid == self.new_revid:
 
3105
            note('No new revisions to push.')
 
3106
        else:
 
3107
            note('Pushed up to revision %d.' % self.new_revno)
3213
3108
        self._show_tag_conficts(to_file)
3214
3109
 
3215
3110
 
3229
3124
        :param verbose: Requests more detailed display of what was checked,
3230
3125
            if any.
3231
3126
        """
3232
 
        note(gettext('checked branch {0} format {1}').format(
3233
 
                                self.branch.user_url, self.branch._format))
 
3127
        note('checked branch %s format %s', self.branch.user_url,
 
3128
            self.branch._format)
3234
3129
        for error in self.errors:
3235
 
            note(gettext('found error:%s'), error)
 
3130
            note('found error:%s', error)
3236
3131
 
3237
3132
 
3238
3133
class Converter5to6(object):
3254
3149
 
3255
3150
        # Copying done; now update target format
3256
3151
        new_branch._transport.put_bytes('format',
3257
 
            format.as_string(),
 
3152
            format.get_format_string(),
3258
3153
            mode=new_branch.bzrdir._get_file_mode())
3259
3154
 
3260
3155
        # Clean up old files
3273
3168
        format = BzrBranchFormat7()
3274
3169
        branch._set_config_location('stacked_on_location', '')
3275
3170
        # update target format
3276
 
        branch._transport.put_bytes('format', format.as_string())
 
3171
        branch._transport.put_bytes('format', format.get_format_string())
3277
3172
 
3278
3173
 
3279
3174
class Converter7to8(object):
3280
 
    """Perform an in-place upgrade of format 7 to format 8"""
 
3175
    """Perform an in-place upgrade of format 6 to format 7"""
3281
3176
 
3282
3177
    def convert(self, branch):
3283
3178
        format = BzrBranchFormat8()
3284
3179
        branch._transport.put_bytes('references', '')
3285
3180
        # update target format
3286
 
        branch._transport.put_bytes('format', format.as_string())
 
3181
        branch._transport.put_bytes('format', format.get_format_string())
3287
3182
 
3288
3183
 
3289
3184
class InterBranch(InterObject):
3523
3418
            self._update_revisions(stop_revision, overwrite=overwrite,
3524
3419
                    graph=graph)
3525
3420
        if self.source._push_should_merge_tags():
3526
 
            result.tag_updates, result.tag_conflicts = (
3527
 
                self.source.tags.merge_to(self.target.tags, overwrite))
 
3421
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
 
3422
                overwrite)
3528
3423
        result.new_revno, result.new_revid = self.target.last_revision_info()
3529
3424
        return result
3530
3425
 
3613
3508
            # TODO: The old revid should be specified when merging tags, 
3614
3509
            # so a tags implementation that versions tags can only 
3615
3510
            # pull in the most recent changes. -- JRV20090506
3616
 
            result.tag_updates, result.tag_conflicts = (
3617
 
                self.source.tags.merge_to(self.target.tags, overwrite,
3618
 
                    ignore_master=not merge_tags_to_master))
 
3511
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
 
3512
                overwrite, ignore_master=not merge_tags_to_master)
3619
3513
            result.new_revno, result.new_revid = self.target.last_revision_info()
3620
3514
            if _hook_master:
3621
3515
                result.master_branch = _hook_master