~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Jelmer Vernooij
  • Date: 2011-11-28 15:18:59 UTC
  • mto: This revision was merged to the branch mainline in revision 6317.
  • Revision ID: jelmer@samba.org-20111128151859-dw4nua1xiobilw4r
Fix tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2012 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""builtin bzr commands"""
18
18
 
19
 
from __future__ import absolute_import
20
 
 
21
19
import os
22
20
 
23
21
import bzrlib.bzrdir
24
22
 
25
 
from bzrlib import lazy_import
26
 
lazy_import.lazy_import(globals(), """
 
23
from bzrlib.lazy_import import lazy_import
 
24
lazy_import(globals(), """
27
25
import cStringIO
28
 
import errno
29
26
import sys
30
27
import time
31
28
 
83
80
    )
84
81
 
85
82
 
86
 
def _get_branch_location(control_dir, possible_transports=None):
87
 
    """Return location of branch for this control dir."""
88
 
    try:
89
 
        this_branch = control_dir.open_branch(
90
 
            possible_transports=possible_transports)
91
 
        # This may be a heavy checkout, where we want the master branch
92
 
        master_location = this_branch.get_bound_location()
93
 
        if master_location is not None:
94
 
            return master_location
95
 
        # If not, use a local sibling
96
 
        return this_branch.base
97
 
    except errors.NotBranchError:
98
 
        format = control_dir.find_branch_format()
99
 
        if getattr(format, 'get_reference', None) is not None:
100
 
            return format.get_reference(control_dir)
101
 
        else:
102
 
            return control_dir.root_transport.base
103
 
 
104
 
 
105
 
def _is_colocated(control_dir, possible_transports=None):
106
 
    """Check if the branch in control_dir is colocated.
107
 
 
108
 
    :param control_dir: Control directory
109
 
    :return: Boolean indicating whether 
110
 
    """
111
 
    # This path is meant to be relative to the existing branch
112
 
    this_url = _get_branch_location(control_dir,
113
 
        possible_transports=possible_transports)
114
 
    # Perhaps the target control dir supports colocated branches?
115
 
    try:
116
 
        root = controldir.ControlDir.open(this_url,
117
 
            possible_transports=possible_transports)
118
 
    except errors.NotBranchError:
119
 
        return (False, this_url)
120
 
    else:
121
 
        try:
122
 
            wt = control_dir.open_workingtree()
123
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
124
 
            return (False, this_url)
125
 
        else:
126
 
            return (
127
 
                root._format.colocated_branches and
128
 
                control_dir.control_url == root.control_url,
129
 
                this_url)
130
 
 
131
 
 
132
 
def lookup_new_sibling_branch(control_dir, location, possible_transports=None):
133
 
    """Lookup the location for a new sibling branch.
134
 
 
135
 
    :param control_dir: Control directory relative to which to look up
136
 
        the name.
137
 
    :param location: Name of the new branch
138
 
    :return: Full location to the new branch
139
 
    """
140
 
    location = directory_service.directories.dereference(location)
141
 
    if '/' not in location and '\\' not in location:
142
 
        (colocated, this_url) = _is_colocated(control_dir, possible_transports)
143
 
 
144
 
        if colocated:
145
 
            return urlutils.join_segment_parameters(this_url,
146
 
                {"branch": urlutils.escape(location)})
147
 
        else:
148
 
            return urlutils.join(this_url, '..', urlutils.escape(location))
149
 
    return location
150
 
 
151
 
 
152
 
def lookup_sibling_branch(control_dir, location, possible_transports=None):
153
 
    """Lookup sibling branch.
154
 
    
155
 
    :param control_dir: Control directory relative to which to lookup the
156
 
        location.
157
 
    :param location: Location to look up
158
 
    :return: branch to open
159
 
    """
160
 
    try:
161
 
        # Perhaps it's a colocated branch?
162
 
        return control_dir.open_branch(location, 
163
 
            possible_transports=possible_transports)
164
 
    except (errors.NotBranchError, errors.NoColocatedBranchSupport):
165
 
        try:
166
 
            return Branch.open(location)
167
 
        except errors.NotBranchError:
168
 
            this_url = _get_branch_location(control_dir)
169
 
            return Branch.open(
170
 
                urlutils.join(
171
 
                    this_url, '..', urlutils.escape(location)))
172
 
 
173
 
 
174
83
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
175
84
def tree_files(file_list, default_branch=u'.', canonicalize=True,
176
85
    apply_view=True):
844
753
    """
845
754
 
846
755
    takes_args = ['dir+']
847
 
    takes_options = [
848
 
        Option(
849
 
            'parents',
850
 
            help='No error if existing, make parent directories as needed.',
851
 
            short_name='p'
852
 
            )
853
 
        ]
854
756
    encoding_type = 'replace'
855
757
 
856
 
    @classmethod
857
 
    def add_file_with_parents(cls, wt, relpath):
858
 
        if wt.path2id(relpath) is not None:
859
 
            return
860
 
        cls.add_file_with_parents(wt, osutils.dirname(relpath))
861
 
        wt.add([relpath])
862
 
 
863
 
    @classmethod
864
 
    def add_file_single(cls, wt, relpath):
865
 
        wt.add([relpath])
866
 
 
867
 
    def run(self, dir_list, parents=False):
868
 
        if parents:
869
 
            add_file = self.add_file_with_parents
870
 
        else:
871
 
            add_file = self.add_file_single
872
 
        for dir in dir_list:
873
 
            wt, relpath = WorkingTree.open_containing(dir)
874
 
            if parents:
875
 
                try:
876
 
                    os.makedirs(dir)
877
 
                except OSError, e:
878
 
                    if e.errno != errno.EEXIST:
879
 
                        raise
 
758
    def run(self, dir_list):
 
759
        for d in dir_list:
 
760
            wt, dd = WorkingTree.open_containing(d)
 
761
            base = os.path.dirname(dd)
 
762
            id = wt.path2id(base)
 
763
            if id != None:
 
764
                os.mkdir(d)
 
765
                wt.add([dd])
 
766
                if not is_quiet():
 
767
                    self.outf.write(gettext('added %s\n') % d)
880
768
            else:
881
 
                os.mkdir(dir)
882
 
            add_file(wt, relpath)
883
 
            if not is_quiet():
884
 
                self.outf.write(gettext('added %s\n') % dir)
 
769
                raise errors.NotVersionedError(path=base)
885
770
 
886
771
 
887
772
class cmd_relpath(Command):
937
822
            tree = work_tree
938
823
            extra_trees = []
939
824
 
940
 
        self.add_cleanup(tree.lock_read().unlock)
941
825
        if file_list is not None:
942
826
            file_ids = tree.paths2ids(file_list, trees=extra_trees,
943
827
                                      require_versioned=True)
944
828
            # find_ids_across_trees may include some paths that don't
945
829
            # exist in 'tree'.
946
 
            entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
 
830
            entries = sorted(
 
831
                (tree.id2path(file_id), tree.inventory[file_id])
 
832
                for file_id in file_ids if tree.has_id(file_id))
947
833
        else:
948
 
            entries = tree.iter_entries_by_dir()
 
834
            entries = tree.inventory.entries()
949
835
 
950
 
        for path, entry in sorted(entries):
 
836
        self.cleanup_now()
 
837
        for path, entry in entries:
951
838
            if kind and kind != entry.kind:
952
839
                continue
953
 
            if path == "":
954
 
                continue
955
840
            if show_ids:
956
841
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
957
842
            else:
1029
914
                and rel_names[0].lower() == rel_names[1].lower()):
1030
915
                into_existing = False
1031
916
            else:
 
917
                inv = tree.inventory
1032
918
                # 'fix' the case of a potential 'from'
1033
919
                from_id = tree.path2id(
1034
920
                            tree.get_canonical_inventory_path(rel_names[0]))
1035
921
                if (not osutils.lexists(names_list[0]) and
1036
 
                    from_id and tree.stored_kind(from_id) == "directory"):
 
922
                    from_id and inv.get_file_kind(from_id) == "directory"):
1037
923
                    into_existing = False
1038
924
        # move/rename
1039
925
        if into_existing:
1205
1091
            # Remembers if asked explicitly or no previous location is set
1206
1092
            if (remember
1207
1093
                or (remember is None and branch_to.get_parent() is None)):
1208
 
                # FIXME: This shouldn't be done before the pull
1209
 
                # succeeds... -- vila 2012-01-02
1210
1094
                branch_to.set_parent(branch_from.base)
1211
1095
 
1212
1096
        if revision is not None:
1340
1224
        if location is None:
1341
1225
            stored_loc = br_from.get_push_location()
1342
1226
            if stored_loc is None:
1343
 
                parent_loc = br_from.get_parent()
1344
 
                if parent_loc:
1345
 
                    raise errors.BzrCommandError(gettext(
1346
 
                        "No push location known or specified. To push to the "
1347
 
                        "parent branch (at %s), use 'bzr push :parent'." %
1348
 
                        urlutils.unescape_for_display(parent_loc,
1349
 
                            self.outf.encoding)))
1350
 
                else:
1351
 
                    raise errors.BzrCommandError(gettext(
1352
 
                        "No push location known or specified."))
 
1227
                raise errors.BzrCommandError(gettext(
 
1228
                    "No push location known or specified."))
1353
1229
            else:
1354
1230
                display_url = urlutils.unescape_for_display(stored_loc,
1355
1231
                        self.outf.encoding)
1437
1313
            revision_id = br_from.last_revision()
1438
1314
        if to_location is None:
1439
1315
            to_location = getattr(br_from, "name", None)
1440
 
            if not to_location:
 
1316
            if to_location is None:
1441
1317
                to_location = urlutils.derive_to_location(from_location)
1442
1318
        to_transport = transport.get_transport(to_location)
1443
1319
        try:
1483
1359
                    from_location, revision)
1484
1360
                raise errors.BzrCommandError(msg)
1485
1361
        else:
1486
 
            try:
1487
 
                to_repo = to_dir.open_repository()
1488
 
            except errors.NoRepositoryPresent:
1489
 
                to_repo = to_dir.create_repository()
1490
 
            to_repo.fetch(br_from.repository, revision_id=revision_id)
1491
1362
            branch = br_from.sprout(to_dir, revision_id=revision_id)
1492
1363
        _merge_tags_if_possible(br_from, branch)
1493
1364
        # If the source branch is stacked, the new branch may
1537
1408
                    self.outf.encoding).rstrip("/"))
1538
1409
        else:
1539
1410
            dir = controldir.ControlDir.open_containing(location)[0]
1540
 
            try:
1541
 
                active_branch = dir.open_branch(name="")
1542
 
            except errors.NotBranchError:
1543
 
                active_branch = None
1544
 
            branches = dir.get_branches()
1545
 
            names = {}
1546
 
            for name, branch in branches.iteritems():
1547
 
                if name == "":
1548
 
                    continue
1549
 
                active = (active_branch is not None and
1550
 
                          active_branch.base == branch.base)
1551
 
                names[name] = active
1552
 
            # Only mention the current branch explicitly if it's not
1553
 
            # one of the colocated branches
1554
 
            if not any(names.values()) and active_branch is not None:
1555
 
                self.outf.write("* %s\n" % gettext("(default)"))
1556
 
            for name in sorted(names.keys()):
1557
 
                active = names[name]
1558
 
                if active:
1559
 
                    prefix = "*"
 
1411
            for branch in dir.list_branches():
 
1412
                if branch.name is None:
 
1413
                    self.outf.write(gettext(" (default)\n"))
1560
1414
                else:
1561
 
                    prefix = " "
1562
 
                self.outf.write("%s %s\n" % (
1563
 
                    prefix, name.encode(self.outf.encoding)))
 
1415
                    self.outf.write(" %s\n" % branch.name.encode(
 
1416
                        self.outf.encoding))
1564
1417
 
1565
1418
 
1566
1419
class cmd_checkout(Command):
1650
1503
    def run(self, dir=u'.'):
1651
1504
        tree = WorkingTree.open_containing(dir)[0]
1652
1505
        self.add_cleanup(tree.lock_read().unlock)
 
1506
        new_inv = tree.inventory
1653
1507
        old_tree = tree.basis_tree()
1654
1508
        self.add_cleanup(old_tree.lock_read().unlock)
 
1509
        old_inv = old_tree.inventory
1655
1510
        renames = []
1656
1511
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1657
1512
        for f, paths, c, v, p, n, k, e in iterator:
2178
2033
            location = '.'
2179
2034
 
2180
2035
        to_transport = transport.get_transport(location)
 
2036
        to_transport.ensure_base()
2181
2037
 
2182
 
        (repo, newdir, require_stacking, repository_policy) = (
2183
 
            format.initialize_on_transport_ex(to_transport,
2184
 
            create_prefix=True, make_working_trees=not no_trees,
2185
 
            shared_repo=True, force_new_repo=True,
2186
 
            use_existing_dir=True,
2187
 
            repo_format_name=format.repository_format.get_format_string()))
 
2038
        newdir = format.initialize_on_transport(to_transport)
 
2039
        repo = newdir.create_repository(shared=True)
 
2040
        repo.set_make_working_trees(not no_trees)
2188
2041
        if not is_quiet():
2189
2042
            from bzrlib.info import show_bzrdir_info
2190
 
            show_bzrdir_info(newdir, verbose=0, outfile=self.outf)
 
2043
            show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
2191
2044
 
2192
2045
 
2193
2046
class cmd_diff(Command):
2371
2224
        self.add_cleanup(tree.lock_read().unlock)
2372
2225
        old = tree.basis_tree()
2373
2226
        self.add_cleanup(old.lock_read().unlock)
2374
 
        for path, ie in old.iter_entries_by_dir():
 
2227
        for path, ie in old.inventory.iter_entries():
2375
2228
            if not tree.has_id(ie.file_id):
2376
2229
                self.outf.write(path)
2377
2230
                if show_ids:
2415
2268
        self.add_cleanup(wt.lock_read().unlock)
2416
2269
        basis = wt.basis_tree()
2417
2270
        self.add_cleanup(basis.lock_read().unlock)
2418
 
        root_id = wt.get_root_id()
2419
 
        for file_id in wt.all_file_ids():
2420
 
            if basis.has_id(file_id):
2421
 
                continue
2422
 
            if root_id == file_id:
2423
 
                continue
2424
 
            path = wt.id2path(file_id)
 
2271
        basis_inv = basis.inventory
 
2272
        inv = wt.inventory
 
2273
        for file_id in inv:
 
2274
            if basis_inv.has_id(file_id):
 
2275
                continue
 
2276
            if inv.is_root(file_id) and len(basis_inv) == 0:
 
2277
                continue
 
2278
            path = inv.id2path(file_id)
2425
2279
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2426
2280
                continue
2427
2281
            if null:
2789
2643
            self.add_cleanup(b.lock_read().unlock)
2790
2644
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2791
2645
 
2792
 
        if b.get_config_stack().get('validate_signatures_in_log'):
 
2646
        if b.get_config().validate_signatures_in_log():
2793
2647
            signatures = True
2794
2648
 
2795
2649
        if signatures:
3294
3148
        Option('per-file-timestamps',
3295
3149
               help='Set modification time of files to that of the last '
3296
3150
                    'revision in which it was changed.'),
3297
 
        Option('uncommitted',
3298
 
               help='Export the working tree contents rather than that of the '
3299
 
                    'last revision.'),
3300
3151
        ]
3301
3152
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3302
 
        root=None, filters=False, per_file_timestamps=False, uncommitted=False,
3303
 
        directory=u'.'):
 
3153
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
3304
3154
        from bzrlib.export import export
3305
3155
 
3306
3156
        if branch_or_subdir is None:
3307
 
            branch_or_subdir = directory
3308
 
 
3309
 
        (tree, b, subdir) = controldir.ControlDir.open_containing_tree_or_branch(
3310
 
            branch_or_subdir)
3311
 
        if tree is not None:
3312
 
            self.add_cleanup(tree.lock_read().unlock)
3313
 
 
3314
 
        if uncommitted:
3315
 
            if tree is None:
3316
 
                raise errors.BzrCommandError(
3317
 
                    gettext("--uncommitted requires a working tree"))
3318
 
            export_tree = tree
 
3157
            tree = WorkingTree.open_containing(directory)[0]
 
3158
            b = tree.branch
 
3159
            subdir = None
3319
3160
        else:
3320
 
            export_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
 
3161
            b, subdir = Branch.open_containing(branch_or_subdir)
 
3162
            tree = None
 
3163
 
 
3164
        rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
3321
3165
        try:
3322
 
            export(export_tree, dest, format, root, subdir, filtered=filters,
 
3166
            export(rev_tree, dest, format, root, subdir, filtered=filters,
3323
3167
                   per_file_timestamps=per_file_timestamps)
3324
3168
        except errors.NoSuchExportFormat, e:
3325
 
            raise errors.BzrCommandError(
3326
 
                gettext('Unsupported export format: %s') % e.format)
 
3169
            raise errors.BzrCommandError(gettext('Unsupported export format: %s') % e.format)
3327
3170
 
3328
3171
 
3329
3172
class cmd_cat(Command):
3515
3358
            tokens = fixed_bug.split(':')
3516
3359
            if len(tokens) == 1:
3517
3360
                if default_bugtracker is None:
3518
 
                    branch_config = branch.get_config_stack()
3519
 
                    default_bugtracker = branch_config.get(
 
3361
                    branch_config = branch.get_config()
 
3362
                    default_bugtracker = branch_config.get_user_option(
3520
3363
                        "bugtracker")
3521
3364
                if default_bugtracker is None:
3522
3365
                    raise errors.BzrCommandError(gettext(
3832
3675
            if directory is None:
3833
3676
                # use branch if we're inside one; otherwise global config
3834
3677
                try:
3835
 
                    c = Branch.open_containing(u'.')[0].get_config_stack()
 
3678
                    c = Branch.open_containing(u'.')[0].get_config()
3836
3679
                except errors.NotBranchError:
3837
 
                    c = _mod_config.GlobalStack()
 
3680
                    c = _mod_config.GlobalConfig()
3838
3681
            else:
3839
 
                c = Branch.open(directory).get_config_stack()
3840
 
            identity = c.get('email')
 
3682
                c = Branch.open(directory).get_config()
3841
3683
            if email:
3842
 
                self.outf.write(_mod_config.extract_email_address(identity)
3843
 
                                + '\n')
 
3684
                self.outf.write(c.user_email() + '\n')
3844
3685
            else:
3845
 
                self.outf.write(identity + '\n')
 
3686
                self.outf.write(c.username() + '\n')
3846
3687
            return
3847
3688
 
3848
3689
        if email:
3859
3700
        # use global config unless --branch given
3860
3701
        if branch:
3861
3702
            if directory is None:
3862
 
                c = Branch.open_containing(u'.')[0].get_config_stack()
 
3703
                c = Branch.open_containing(u'.')[0].get_config()
3863
3704
            else:
3864
 
                b = Branch.open(directory)
3865
 
                self.add_cleanup(b.lock_write().unlock)
3866
 
                c = b.get_config_stack()
 
3705
                c = Branch.open(directory).get_config()
3867
3706
        else:
3868
 
            c = _mod_config.GlobalStack()
3869
 
        c.set('email', name)
 
3707
            c = _mod_config.GlobalConfig()
 
3708
        c.set_user_option('email', name)
3870
3709
 
3871
3710
 
3872
3711
class cmd_nick(Command):
3873
3712
    __doc__ = """Print or set the branch nickname.
3874
3713
 
3875
 
    If unset, the colocated branch name is used for colocated branches, and
3876
 
    the branch directory name is used for other branches.  To print the
3877
 
    current nickname, execute with no argument.
 
3714
    If unset, the tree root directory name is used as the nickname.
 
3715
    To print the current nickname, execute with no argument.
3878
3716
 
3879
3717
    Bound branches use the nickname of its master branch unless it is set
3880
3718
    locally.
4098
3936
            load_list=None, debugflag=None, starting_with=None, subunit=False,
4099
3937
            parallel=None, lsprof_tests=False,
4100
3938
            sync=False):
4101
 
 
4102
 
        # During selftest, disallow proxying, as it can cause severe
4103
 
        # performance penalties and is only needed for thread
4104
 
        # safety. The selftest command is assumed to not use threads
4105
 
        # too heavily. The call should be as early as possible, as
4106
 
        # error reporting for past duplicate imports won't have useful
4107
 
        # backtraces.
4108
 
        lazy_import.disallow_proxying()
4109
 
 
4110
3939
        from bzrlib import tests
4111
3940
 
4112
3941
        if testspecs_list is not None:
4262
4091
    Merge will do its best to combine the changes in two branches, but there
4263
4092
    are some kinds of problems only a human can fix.  When it encounters those,
4264
4093
    it will mark a conflict.  A conflict means that you need to fix something,
4265
 
    before you can commit.
 
4094
    before you should commit.
4266
4095
 
4267
4096
    Use bzr resolve when you have fixed a problem.  See also bzr conflicts.
4268
4097
 
4676
4505
                if tree.kind(file_id) != "directory":
4677
4506
                    continue
4678
4507
 
4679
 
                # FIXME: Support nested trees
4680
 
                for name, ie in tree.root_inventory.iter_entries(file_id):
 
4508
                for name, ie in tree.inventory.iter_entries(file_id):
4681
4509
                    interesting_ids.add(ie.file_id)
4682
4510
            new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4683
4511
        else:
4827
4655
 
4828
4656
    @display_command
4829
4657
    def run(self, context=None):
4830
 
        from bzrlib import shellcomplete
 
4658
        import shellcomplete
4831
4659
        shellcomplete.shellcomplete(context)
4832
4660
 
4833
4661
 
5191
5019
 
5192
5020
    def _run(self, b, revision_id_list, revision):
5193
5021
        import bzrlib.gpg as gpg
5194
 
        gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
 
5022
        gpg_strategy = gpg.GPGStrategy(b.get_config())
5195
5023
        if revision_id_list is not None:
5196
5024
            b.repository.start_write_group()
5197
5025
            try:
5264
5092
            else:
5265
5093
                if location is None:
5266
5094
                    if b.get_bound_location() is not None:
5267
 
                        raise errors.BzrCommandError(
5268
 
                            gettext('Branch is already bound'))
 
5095
                        raise errors.BzrCommandError(gettext('Branch is already bound'))
5269
5096
                    else:
5270
 
                        raise errors.BzrCommandError(
5271
 
                            gettext('No location supplied'
5272
 
                                    ' and no previous location known'))
 
5097
                        raise errors.BzrCommandError(gettext('No location supplied '
 
5098
                            'and no previous location known'))
5273
5099
        b_other = Branch.open(location)
5274
5100
        try:
5275
5101
            b.bind(b_other)
5685
5511
        if public_branch is None:
5686
5512
            public_branch = stored_public_branch
5687
5513
        elif stored_public_branch is None:
5688
 
            # FIXME: Should be done only if we succeed ? -- vila 2012-01-03
5689
5514
            branch.set_public_branch(public_branch)
5690
5515
        if not include_bundle and public_branch is None:
5691
5516
            raise errors.BzrCommandError(gettext('No public branch specified or'
5716
5541
                self.outf.writelines(directive.to_lines())
5717
5542
        else:
5718
5543
            message = directive.to_email(mail_to, branch, sign)
5719
 
            s = SMTPConnection(branch.get_config_stack())
 
5544
            s = SMTPConnection(branch.get_config())
5720
5545
            s.send_email(message)
5721
5546
 
5722
5547
 
6226
6051
        from bzrlib import switch
6227
6052
        tree_location = directory
6228
6053
        revision = _get_one_revision('switch', revision)
6229
 
        possible_transports = []
6230
 
        control_dir = controldir.ControlDir.open_containing(tree_location,
6231
 
            possible_transports=possible_transports)[0]
 
6054
        control_dir = controldir.ControlDir.open_containing(tree_location)[0]
6232
6055
        if to_location is None:
6233
6056
            if revision is None:
6234
6057
                raise errors.BzrCommandError(gettext('You must supply either a'
6235
6058
                                             ' revision or a location'))
6236
6059
            to_location = tree_location
6237
6060
        try:
6238
 
            branch = control_dir.open_branch(
6239
 
                possible_transports=possible_transports)
 
6061
            branch = control_dir.open_branch()
6240
6062
            had_explicit_nick = branch.get_config().has_explicit_nickname()
6241
6063
        except errors.NotBranchError:
6242
6064
            branch = None
6243
6065
            had_explicit_nick = False
6244
6066
        if create_branch:
6245
6067
            if branch is None:
6246
 
                raise errors.BzrCommandError(
6247
 
                    gettext('cannot create branch without source branch'))
6248
 
            to_location = lookup_new_sibling_branch(control_dir, to_location,
6249
 
                 possible_transports=possible_transports)
 
6068
                raise errors.BzrCommandError(gettext('cannot create branch without'
 
6069
                                             ' source branch'))
 
6070
            to_location = directory_service.directories.dereference(
 
6071
                              to_location)
 
6072
            if '/' not in to_location and '\\' not in to_location:
 
6073
                # This path is meant to be relative to the existing branch
 
6074
                this_url = self._get_branch_location(control_dir)
 
6075
                # Perhaps the target control dir supports colocated branches?
 
6076
                try:
 
6077
                    root = controldir.ControlDir.open(this_url,
 
6078
                        possible_transports=[control_dir.user_transport])
 
6079
                except errors.NotBranchError:
 
6080
                    colocated = False
 
6081
                else:
 
6082
                    colocated = root._format.colocated_branches
 
6083
                if colocated:
 
6084
                    to_location = urlutils.join_segment_parameters(this_url,
 
6085
                        {"branch": urlutils.escape(to_location)})
 
6086
                else:
 
6087
                    to_location = urlutils.join(
 
6088
                        this_url, '..', urlutils.escape(to_location))
6250
6089
            to_branch = branch.bzrdir.sprout(to_location,
6251
 
                 possible_transports=possible_transports,
6252
 
                 source_branch=branch).open_branch()
 
6090
                                 possible_transports=[branch.bzrdir.root_transport],
 
6091
                                 source_branch=branch).open_branch()
6253
6092
        else:
6254
 
            to_branch = lookup_sibling_branch(control_dir, to_location)
 
6093
            # Perhaps it's a colocated branch?
 
6094
            try:
 
6095
                to_branch = control_dir.open_branch(to_location)
 
6096
            except (errors.NotBranchError, errors.NoColocatedBranchSupport):
 
6097
                try:
 
6098
                    to_branch = Branch.open(to_location)
 
6099
                except errors.NotBranchError:
 
6100
                    this_url = self._get_branch_location(control_dir)
 
6101
                    to_branch = Branch.open(
 
6102
                        urlutils.join(
 
6103
                            this_url, '..', urlutils.escape(to_location)))
6255
6104
        if revision is not None:
6256
6105
            revision = revision.as_revision_id(to_branch)
6257
6106
        switch.switch(control_dir, to_branch, force, revision_id=revision)
6261
6110
        note(gettext('Switched to branch: %s'),
6262
6111
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6263
6112
 
 
6113
    def _get_branch_location(self, control_dir):
 
6114
        """Return location of branch for this control dir."""
 
6115
        try:
 
6116
            this_branch = control_dir.open_branch()
 
6117
            # This may be a heavy checkout, where we want the master branch
 
6118
            master_location = this_branch.get_bound_location()
 
6119
            if master_location is not None:
 
6120
                return master_location
 
6121
            # If not, use a local sibling
 
6122
            return this_branch.base
 
6123
        except errors.NotBranchError:
 
6124
            format = control_dir.find_branch_format()
 
6125
            if getattr(format, 'get_reference', None) is not None:
 
6126
                return format.get_reference(control_dir)
 
6127
            else:
 
6128
                return control_dir.root_transport.base
6264
6129
 
6265
6130
 
6266
6131
class cmd_view(Command):
6459
6324
    def run(self, location=None):
6460
6325
        if location is None:
6461
6326
            location = "."
6462
 
        cdir = controldir.ControlDir.open_containing(location)[0]
6463
 
        cdir.destroy_branch()
 
6327
        branch = Branch.open_containing(location)[0]
 
6328
        branch.bzrdir.destroy_branch()
6464
6329
 
6465
6330
 
6466
6331
class cmd_shelve(Command):
6674
6539
    takes_options = [Option('plugin', 
6675
6540
                            help='Export help text from named command '\
6676
6541
                                 '(defaults to all built in commands).',
6677
 
                            type=str),
6678
 
                     Option('include-duplicates',
6679
 
                            help='Output multiple copies of the same msgid '
6680
 
                                 'string if it appears more than once.'),
6681
 
                            ]
 
6542
                            type=str)]
6682
6543
 
6683
 
    def run(self, plugin=None, include_duplicates=False):
 
6544
    def run(self, plugin=None):
6684
6545
        from bzrlib.export_pot import export_pot
6685
 
        export_pot(self.outf, plugin, include_duplicates)
 
6546
        export_pot(self.outf, plugin)
6686
6547
 
6687
6548
 
6688
6549
def _register_lazy_builtins():