~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Patch Queue Manager
  • Date: 2011-10-09 13:52:06 UTC
  • mfrom: (6202.1.3 revno-revision)
  • Revision ID: pqm@pqm.ubuntu.com-20111009135206-t3utsln6mtzv9eut
(jelmer) Add a --revision argument to 'bzr revno'. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
 
18
18
from cStringIO import StringIO
19
 
import sys
20
19
 
21
20
from bzrlib.lazy_import import lazy_import
22
21
lazy_import(globals(), """
23
 
from itertools import chain
 
22
import itertools
24
23
from bzrlib import (
25
24
        bzrdir,
26
25
        cache_utf8,
36
35
        repository,
37
36
        revision as _mod_revision,
38
37
        rio,
 
38
        tag as _mod_tag,
39
39
        transport,
40
40
        ui,
41
41
        urlutils,
42
42
        )
43
 
from bzrlib.config import BranchConfig, TransportConfig
44
 
from bzrlib.tag import (
45
 
    BasicTags,
46
 
    DisabledTags,
47
 
    )
 
43
from bzrlib.i18n import gettext, ngettext
48
44
""")
49
45
 
50
46
from bzrlib import (
66
62
from bzrlib.trace import mutter, mutter_callsite, note, is_quiet
67
63
 
68
64
 
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
 
 
74
65
class Branch(controldir.ControlComponent):
75
66
    """Branch holding a history of revisions.
76
67
 
222
213
 
223
214
        :return: A bzrlib.config.BranchConfig.
224
215
        """
225
 
        return BranchConfig(self)
 
216
        return _mod_config.BranchConfig(self)
 
217
 
 
218
    def get_config_stack(self):
 
219
        """Get a bzrlib.config.BranchStack for this Branch.
 
220
 
 
221
        This can then be used to get and set configuration options for the
 
222
        branch.
 
223
 
 
224
        :return: A bzrlib.config.BranchStack.
 
225
        """
 
226
        return _mod_config.BranchStack(self)
226
227
 
227
228
    def _get_config(self):
228
229
        """Get the concrete config for just the config in this branch.
520
521
                    # The decision to include the start or not
521
522
                    # depends on the stop_rule if a stop is provided
522
523
                    # so pop this node back into the iterator
523
 
                    rev_iter = chain(iter([node]), rev_iter)
 
524
                    rev_iter = itertools.chain(iter([node]), rev_iter)
524
525
                    break
525
526
        if stop_revision_id is None:
526
527
            # Yield everything
651
652
        """
652
653
        raise errors.UpgradeRequired(self.user_url)
653
654
 
 
655
    def get_append_revisions_only(self):
 
656
        """Whether it is only possible to append revisions to the history.
 
657
        """
 
658
        if not self._format.supports_set_append_revisions_only():
 
659
            return False
 
660
        return self.get_config(
 
661
            ).get_user_option_as_bool('append_revisions_only')
 
662
 
654
663
    def set_append_revisions_only(self, enabled):
655
664
        if not self._format.supports_set_append_revisions_only():
656
665
            raise errors.UpgradeRequired(self.user_url)
724
733
        """
725
734
        return None
726
735
 
 
736
    @deprecated_method(deprecated_in((2, 5, 0)))
727
737
    def get_revision_delta(self, revno):
728
738
        """Return the delta for one revision.
729
739
 
730
740
        The delta is relative to its mainline predecessor, or the
731
741
        empty tree for revision 1.
732
742
        """
733
 
        rh = self.revision_history()
734
 
        if not (1 <= revno <= len(rh)):
 
743
        try:
 
744
            revid = self.get_rev_id(revno)
 
745
        except errors.NoSuchRevision:
735
746
            raise errors.InvalidRevisionNumber(revno)
736
 
        return self.repository.get_revision_delta(rh[revno-1])
 
747
        return self.repository.get_revision_delta(revid)
737
748
 
738
749
    def get_stacked_on_url(self):
739
750
        """Get the URL this branch is stacked against.
850
861
        """
851
862
        pb = ui.ui_factory.nested_progress_bar()
852
863
        try:
853
 
            pb.update("Unstacking")
 
864
            pb.update(gettext("Unstacking"))
854
865
            # The basic approach here is to fetch the tip of the branch,
855
866
            # including all available ghosts, from the existing stacked
856
867
            # repository into a new repository object without the fallbacks. 
1382
1393
        # specific check.
1383
1394
        return result
1384
1395
 
1385
 
    def _get_checkout_format(self):
 
1396
    def _get_checkout_format(self, lightweight=False):
1386
1397
        """Return the most suitable metadir for a checkout of this branch.
1387
1398
        Weaves are used if this branch's repository uses weaves.
1388
1399
        """
1434
1445
        """
1435
1446
        t = transport.get_transport(to_location)
1436
1447
        t.ensure_base()
 
1448
        format = self._get_checkout_format(lightweight=lightweight)
1437
1449
        if lightweight:
1438
 
            format = self._get_checkout_format()
1439
1450
            checkout = format.initialize_on_transport(t)
1440
1451
            from_branch = BranchReferenceFormat().initialize(checkout, 
1441
1452
                target_branch=self)
1442
1453
        else:
1443
 
            format = self._get_checkout_format()
1444
1454
            checkout_branch = bzrdir.BzrDir.create_branch_convenience(
1445
1455
                to_location, force_new_tree=False, format=format)
1446
1456
            checkout = checkout_branch.bzrdir
1578
1588
    object will be created every time regardless.
1579
1589
    """
1580
1590
 
1581
 
    can_set_append_revisions_only = True
1582
 
 
1583
1591
    def __eq__(self, other):
1584
1592
        return self.__class__ is other.__class__
1585
1593
 
1657
1665
        for hook in hooks:
1658
1666
            hook(params)
1659
1667
 
1660
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
1668
    def initialize(self, a_bzrdir, name=None, repository=None,
 
1669
                   append_revisions_only=None):
1661
1670
        """Create a branch of this format in a_bzrdir.
1662
1671
        
1663
1672
        :param name: Name of the colocated branch to create.
1685
1694
        Note that it is normal for branch to be a RemoteBranch when using tags
1686
1695
        on a RemoteBranch.
1687
1696
        """
1688
 
        return DisabledTags(branch)
 
1697
        return _mod_tag.DisabledTags(branch)
1689
1698
 
1690
1699
    def network_name(self):
1691
1700
        """A simple byte string uniquely identifying this format for RPC calls.
1749
1758
        """True if this format supports tags stored in the branch"""
1750
1759
        return False  # by default
1751
1760
 
 
1761
    def tags_are_versioned(self):
 
1762
        """Whether the tag container for this branch versions tags."""
 
1763
        return False
 
1764
 
 
1765
    def supports_tags_referencing_ghosts(self):
 
1766
        """True if tags can reference ghost revisions."""
 
1767
        return True
 
1768
 
1752
1769
 
1753
1770
class MetaDirBranchFormatFactory(registry._LazyObjectGetter):
1754
1771
    """A factory for a BranchFormat object, permitting simple lazy registration.
1993
2010
        """What class to instantiate on open calls."""
1994
2011
        raise NotImplementedError(self._branch_class)
1995
2012
 
 
2013
    def _get_initial_config(self, append_revisions_only=None):
 
2014
        if append_revisions_only:
 
2015
            return "append_revisions_only = True\n"
 
2016
        else:
 
2017
            # Avoid writing anything if append_revisions_only is disabled,
 
2018
            # as that is the default.
 
2019
            return ""
 
2020
 
1996
2021
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1997
2022
                           repository=None):
1998
2023
        """Initialize a branch in a bzrdir, with specified files
2088
2113
        """See BranchFormat.get_format_description()."""
2089
2114
        return "Branch format 5"
2090
2115
 
2091
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2116
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2117
                   append_revisions_only=None):
2092
2118
        """Create a branch of this format in a_bzrdir."""
 
2119
        if append_revisions_only:
 
2120
            raise errors.UpgradeRequired(a_bzrdir.user_url)
2093
2121
        utf8_files = [('revision-history', ''),
2094
2122
                      ('branch-name', ''),
2095
2123
                      ]
2121
2149
        """See BranchFormat.get_format_description()."""
2122
2150
        return "Branch format 6"
2123
2151
 
2124
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2152
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2153
                   append_revisions_only=None):
2125
2154
        """Create a branch of this format in a_bzrdir."""
2126
2155
        utf8_files = [('last-revision', '0 null:\n'),
2127
 
                      ('branch.conf', ''),
 
2156
                      ('branch.conf',
 
2157
                          self._get_initial_config(append_revisions_only)),
2128
2158
                      ('tags', ''),
2129
2159
                      ]
2130
2160
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2131
2161
 
2132
2162
    def make_tags(self, branch):
2133
2163
        """See bzrlib.branch.BranchFormat.make_tags()."""
2134
 
        return BasicTags(branch)
 
2164
        return _mod_tag.BasicTags(branch)
2135
2165
 
2136
2166
    def supports_set_append_revisions_only(self):
2137
2167
        return True
2151
2181
        """See BranchFormat.get_format_description()."""
2152
2182
        return "Branch format 8"
2153
2183
 
2154
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2184
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2185
                   append_revisions_only=None):
2155
2186
        """Create a branch of this format in a_bzrdir."""
2156
2187
        utf8_files = [('last-revision', '0 null:\n'),
2157
 
                      ('branch.conf', ''),
 
2188
                      ('branch.conf',
 
2189
                          self._get_initial_config(append_revisions_only)),
2158
2190
                      ('tags', ''),
2159
2191
                      ('references', '')
2160
2192
                      ]
2162
2194
 
2163
2195
    def make_tags(self, branch):
2164
2196
        """See bzrlib.branch.BranchFormat.make_tags()."""
2165
 
        return BasicTags(branch)
 
2197
        return _mod_tag.BasicTags(branch)
2166
2198
 
2167
2199
    def supports_set_append_revisions_only(self):
2168
2200
        return True
2182
2214
    This format was introduced in bzr 1.6.
2183
2215
    """
2184
2216
 
2185
 
    def initialize(self, a_bzrdir, name=None, repository=None):
 
2217
    def initialize(self, a_bzrdir, name=None, repository=None,
 
2218
                   append_revisions_only=None):
2186
2219
        """Create a branch of this format in a_bzrdir."""
2187
2220
        utf8_files = [('last-revision', '0 null:\n'),
2188
 
                      ('branch.conf', ''),
 
2221
                      ('branch.conf',
 
2222
                          self._get_initial_config(append_revisions_only)),
2189
2223
                      ('tags', ''),
2190
2224
                      ]
2191
2225
        return self._initialize_helper(a_bzrdir, utf8_files, name, repository)
2209
2243
 
2210
2244
    def make_tags(self, branch):
2211
2245
        """See bzrlib.branch.BranchFormat.make_tags()."""
2212
 
        return BasicTags(branch)
 
2246
        return _mod_tag.BasicTags(branch)
2213
2247
 
2214
2248
    supports_reference_locations = False
2215
2249
 
2244
2278
        location = transport.put_bytes('location', to_branch.base)
2245
2279
 
2246
2280
    def initialize(self, a_bzrdir, name=None, target_branch=None,
2247
 
            repository=None):
 
2281
            repository=None, append_revisions_only=None):
2248
2282
        """Create a branch of this format in a_bzrdir."""
2249
2283
        if target_branch is None:
2250
2284
            # this format does not implement branch itself, thus the implicit
2251
2285
            # creation contract must see it as uninitializable
2252
2286
            raise errors.UninitializableFormat(self)
2253
2287
        mutter('creating branch reference in %s', a_bzrdir.user_url)
 
2288
        if a_bzrdir._format.fixed_components:
 
2289
            raise errors.IncompatibleFormat(self, a_bzrdir._format)
2254
2290
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2255
2291
        branch_transport.put_bytes('location',
2256
2292
            target_branch.bzrdir.user_url)
2425
2461
    base = property(_get_base, doc="The URL for the root of this branch.")
2426
2462
 
2427
2463
    def _get_config(self):
2428
 
        return TransportConfig(self._transport, 'branch.conf')
 
2464
        return _mod_config.TransportConfig(self._transport, 'branch.conf')
2429
2465
 
2430
2466
    def is_locked(self):
2431
2467
        return self.control_files.is_locked()
2512
2548
            raise errors.InvalidRevisionId(revision_id=revision_id, branch=self)
2513
2549
        revision_id = _mod_revision.ensure_null(revision_id)
2514
2550
        old_revno, old_revid = self.last_revision_info()
2515
 
        if self._get_append_revisions_only():
 
2551
        if self.get_append_revisions_only():
2516
2552
            self._check_history_violation(revision_id)
2517
2553
        self._run_pre_change_branch_tip_hooks(revno, revision_id)
2518
2554
        self._write_last_revision_info(revno, revision_id)
2957
2993
            raise errors.NotStacked(self)
2958
2994
        return stacked_url
2959
2995
 
2960
 
    def _get_append_revisions_only(self):
2961
 
        return self.get_config(
2962
 
            ).get_user_option_as_bool('append_revisions_only')
2963
 
 
2964
2996
    @needs_read_lock
2965
2997
    def get_rev_id(self, revno, history=None):
2966
2998
        """Find the revision id of the specified revno."""
3052
3084
    :ivar local_branch: target branch if there is a Master, else None
3053
3085
    :ivar target_branch: Target/destination branch object. (write locked)
3054
3086
    :ivar tag_conflicts: A list of tag conflicts, see BasicTags.merge_to
 
3087
    :ivar tag_updates: A dict with new tags, see BasicTags.merge_to
3055
3088
    """
3056
3089
 
3057
3090
    @deprecated_method(deprecated_in((2, 3, 0)))
3063
3096
        return self.new_revno - self.old_revno
3064
3097
 
3065
3098
    def report(self, to_file):
 
3099
        tag_conflicts = getattr(self, "tag_conflicts", None)
 
3100
        tag_updates = getattr(self, "tag_updates", None)
3066
3101
        if not is_quiet():
3067
 
            if self.old_revid == self.new_revid:
3068
 
                to_file.write('No revisions to pull.\n')
3069
 
            else:
 
3102
            if self.old_revid != self.new_revid:
3070
3103
                to_file.write('Now on revision %d.\n' % self.new_revno)
 
3104
            if tag_updates:
 
3105
                to_file.write('%d tag(s) updated.\n' % len(tag_updates))
 
3106
            if self.old_revid == self.new_revid and not tag_updates:
 
3107
                if not tag_conflicts:
 
3108
                    to_file.write('No revisions or tags to pull.\n')
 
3109
                else:
 
3110
                    to_file.write('No revisions to pull.\n')
3071
3111
        self._show_tag_conficts(to_file)
3072
3112
 
3073
3113
 
3099
3139
        return self.new_revno - self.old_revno
3100
3140
 
3101
3141
    def report(self, to_file):
3102
 
        """Write a human-readable description of the result."""
3103
 
        if self.old_revid == self.new_revid:
3104
 
            note('No new revisions to push.')
3105
 
        else:
3106
 
            note('Pushed up to revision %d.' % self.new_revno)
 
3142
        # TODO: This function gets passed a to_file, but then
 
3143
        # ignores it and calls note() instead. This is also
 
3144
        # inconsistent with PullResult(), which writes to stdout.
 
3145
        # -- JRV20110901, bug #838853
 
3146
        tag_conflicts = getattr(self, "tag_conflicts", None)
 
3147
        tag_updates = getattr(self, "tag_updates", None)
 
3148
        if not is_quiet():
 
3149
            if self.old_revid != self.new_revid:
 
3150
                note(gettext('Pushed up to revision %d.') % self.new_revno)
 
3151
            if tag_updates:
 
3152
                note(ngettext('%d tag updated.', '%d tags updated.', len(tag_updates)) % len(tag_updates))
 
3153
            if self.old_revid == self.new_revid and not tag_updates:
 
3154
                if not tag_conflicts:
 
3155
                    note(gettext('No new revisions or tags to push.'))
 
3156
                else:
 
3157
                    note(gettext('No new revisions to push.'))
3107
3158
        self._show_tag_conficts(to_file)
3108
3159
 
3109
3160
 
3123
3174
        :param verbose: Requests more detailed display of what was checked,
3124
3175
            if any.
3125
3176
        """
3126
 
        note('checked branch %s format %s', self.branch.user_url,
3127
 
            self.branch._format)
 
3177
        note(gettext('checked branch {0} format {1}').format(
 
3178
                                self.branch.user_url, self.branch._format))
3128
3179
        for error in self.errors:
3129
 
            note('found error:%s', error)
 
3180
            note(gettext('found error:%s'), error)
3130
3181
 
3131
3182
 
3132
3183
class Converter5to6(object):
3171
3222
 
3172
3223
 
3173
3224
class Converter7to8(object):
3174
 
    """Perform an in-place upgrade of format 6 to format 7"""
 
3225
    """Perform an in-place upgrade of format 7 to format 8"""
3175
3226
 
3176
3227
    def convert(self, branch):
3177
3228
        format = BzrBranchFormat8()
3417
3468
            self._update_revisions(stop_revision, overwrite=overwrite,
3418
3469
                    graph=graph)
3419
3470
        if self.source._push_should_merge_tags():
3420
 
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3421
 
                overwrite)
 
3471
            result.tag_updates, result.tag_conflicts = (
 
3472
                self.source.tags.merge_to(self.target.tags, overwrite))
3422
3473
        result.new_revno, result.new_revid = self.target.last_revision_info()
3423
3474
        return result
3424
3475
 
3507
3558
            # TODO: The old revid should be specified when merging tags, 
3508
3559
            # so a tags implementation that versions tags can only 
3509
3560
            # pull in the most recent changes. -- JRV20090506
3510
 
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3511
 
                overwrite, ignore_master=not merge_tags_to_master)
 
3561
            result.tag_updates, result.tag_conflicts = (
 
3562
                self.source.tags.merge_to(self.target.tags, overwrite,
 
3563
                    ignore_master=not merge_tags_to_master))
3512
3564
            result.new_revno, result.new_revid = self.target.last_revision_info()
3513
3565
            if _hook_master:
3514
3566
                result.master_branch = _hook_master