~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Jelmer Vernooij
  • Date: 2012-02-18 16:55:04 UTC
  • mfrom: (6437.23.10 2.5)
  • mto: This revision was merged to the branch mainline in revision 6469.
  • Revision ID: jelmer@samba.org-20120218165504-c9oe5c5ue805y8wp
Merge bzr/2.5.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2012 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
 
19
21
import os
20
22
 
21
23
import bzrlib.bzrdir
22
24
 
23
 
from bzrlib.lazy_import import lazy_import
24
 
lazy_import(globals(), """
 
25
from bzrlib import lazy_import
 
26
lazy_import.lazy_import(globals(), """
25
27
import cStringIO
 
28
import errno
26
29
import sys
27
30
import time
28
31
 
80
83
    )
81
84
 
82
85
 
 
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
 
83
174
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
84
175
def tree_files(file_list, default_branch=u'.', canonicalize=True,
85
176
    apply_view=True):
558
649
    _see_also = ['info']
559
650
    takes_args = ['location?']
560
651
    takes_options = [
561
 
        Option('tree', help='Show revno of working tree'),
 
652
        Option('tree', help='Show revno of working tree.'),
562
653
        'revision',
563
654
        ]
564
655
 
606
697
        custom_help('directory',
607
698
            help='Branch to examine, '
608
699
                 'rather than the one containing the working directory.'),
609
 
        Option('tree', help='Show revno of working tree'),
 
700
        Option('tree', help='Show revno of working tree.'),
610
701
        ]
611
702
 
612
703
    @display_command
753
844
    """
754
845
 
755
846
    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
        ]
756
854
    encoding_type = 'replace'
757
855
 
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)
 
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
768
880
            else:
769
 
                raise errors.NotVersionedError(path=base)
 
881
                os.mkdir(dir)
 
882
            add_file(wt, relpath)
 
883
            if not is_quiet():
 
884
                self.outf.write(gettext('added %s\n') % dir)
770
885
 
771
886
 
772
887
class cmd_relpath(Command):
822
937
            tree = work_tree
823
938
            extra_trees = []
824
939
 
 
940
        self.add_cleanup(tree.lock_read().unlock)
825
941
        if file_list is not None:
826
942
            file_ids = tree.paths2ids(file_list, trees=extra_trees,
827
943
                                      require_versioned=True)
828
944
            # find_ids_across_trees may include some paths that don't
829
945
            # exist in 'tree'.
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))
 
946
            entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
833
947
        else:
834
 
            entries = tree.inventory.entries()
 
948
            entries = tree.iter_entries_by_dir()
835
949
 
836
 
        self.cleanup_now()
837
 
        for path, entry in entries:
 
950
        for path, entry in sorted(entries):
838
951
            if kind and kind != entry.kind:
839
952
                continue
 
953
            if path == "":
 
954
                continue
840
955
            if show_ids:
841
956
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
842
957
            else:
884
999
        if len(names_list) < 2:
885
1000
            raise errors.BzrCommandError(gettext("missing file argument"))
886
1001
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
 
1002
        for file_name in rel_names[0:-1]:
 
1003
            if file_name == '':
 
1004
                raise errors.BzrCommandError(gettext("can not move root of branch"))
887
1005
        self.add_cleanup(tree.lock_tree_write().unlock)
888
1006
        self._run(tree, names_list, rel_names, after)
889
1007
 
911
1029
                and rel_names[0].lower() == rel_names[1].lower()):
912
1030
                into_existing = False
913
1031
            else:
914
 
                inv = tree.inventory
915
1032
                # 'fix' the case of a potential 'from'
916
1033
                from_id = tree.path2id(
917
1034
                            tree.get_canonical_inventory_path(rel_names[0]))
918
1035
                if (not osutils.lexists(names_list[0]) and
919
 
                    from_id and inv.get_file_kind(from_id) == "directory"):
 
1036
                    from_id and tree.stored_kind(from_id) == "directory"):
920
1037
                    into_existing = False
921
1038
        # move/rename
922
1039
        if into_existing:
1088
1205
            # Remembers if asked explicitly or no previous location is set
1089
1206
            if (remember
1090
1207
                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
1091
1210
                branch_to.set_parent(branch_from.base)
1092
1211
 
1093
1212
        if revision is not None:
1221
1340
        if location is None:
1222
1341
            stored_loc = br_from.get_push_location()
1223
1342
            if stored_loc is None:
1224
 
                raise errors.BzrCommandError(gettext(
1225
 
                    "No push location known or specified."))
 
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."))
1226
1353
            else:
1227
1354
                display_url = urlutils.unescape_for_display(stored_loc,
1228
1355
                        self.outf.encoding)
1309
1436
            # RBC 20060209
1310
1437
            revision_id = br_from.last_revision()
1311
1438
        if to_location is None:
1312
 
            to_location = urlutils.derive_to_location(from_location)
 
1439
            to_location = getattr(br_from, "name", None)
 
1440
            if not to_location:
 
1441
                to_location = urlutils.derive_to_location(from_location)
1313
1442
        to_transport = transport.get_transport(to_location)
1314
1443
        try:
1315
1444
            to_transport.mkdir('.')
1316
1445
        except errors.FileExists:
1317
 
            if not use_existing_dir:
1318
 
                raise errors.BzrCommandError(gettext('Target directory "%s" '
1319
 
                    'already exists.') % to_location)
1320
 
            else:
1321
 
                try:
1322
 
                    to_dir = controldir.ControlDir.open_from_transport(
1323
 
                        to_transport)
1324
 
                except errors.NotBranchError:
 
1446
            try:
 
1447
                to_dir = controldir.ControlDir.open_from_transport(
 
1448
                    to_transport)
 
1449
            except errors.NotBranchError:
 
1450
                if not use_existing_dir:
 
1451
                    raise errors.BzrCommandError(gettext('Target directory "%s" '
 
1452
                        'already exists.') % to_location)
 
1453
                else:
1325
1454
                    to_dir = None
 
1455
            else:
 
1456
                try:
 
1457
                    to_dir.open_branch()
 
1458
                except errors.NotBranchError:
 
1459
                    pass
1326
1460
                else:
1327
 
                    try:
1328
 
                        to_dir.open_branch()
1329
 
                    except errors.NotBranchError:
1330
 
                        pass
1331
 
                    else:
1332
 
                        raise errors.AlreadyBranchError(to_location)
 
1461
                    raise errors.AlreadyBranchError(to_location)
1333
1462
        except errors.NoSuchFile:
1334
1463
            raise errors.BzrCommandError(gettext('Parent of "%s" does not exist.')
1335
1464
                                         % to_location)
1345
1474
                                            force_new_repo=standalone,
1346
1475
                                            create_tree_if_local=not no_tree,
1347
1476
                                            source_branch=br_from)
1348
 
                branch = to_dir.open_branch()
 
1477
                branch = to_dir.open_branch(
 
1478
                    possible_transports=[
 
1479
                        br_from.bzrdir.root_transport, to_transport])
1349
1480
            except errors.NoSuchRevision:
1350
1481
                to_transport.delete_tree('.')
1351
1482
                msg = gettext("The branch {0} has no revision {1}.").format(
1352
1483
                    from_location, revision)
1353
1484
                raise errors.BzrCommandError(msg)
1354
1485
        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)
1355
1491
            branch = br_from.sprout(to_dir, revision_id=revision_id)
1356
1492
        _merge_tags_if_possible(br_from, branch)
1357
1493
        # If the source branch is stacked, the new branch may
1401
1537
                    self.outf.encoding).rstrip("/"))
1402
1538
        else:
1403
1539
            dir = controldir.ControlDir.open_containing(location)[0]
1404
 
            for branch in dir.list_branches():
1405
 
                if branch.name is None:
1406
 
                    self.outf.write(gettext(" (default)\n"))
 
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 = "*"
1407
1560
                else:
1408
 
                    self.outf.write(" %s\n" % branch.name.encode(
1409
 
                        self.outf.encoding))
 
1561
                    prefix = " "
 
1562
                self.outf.write("%s %s\n" % (
 
1563
                    prefix, name.encode(self.outf.encoding)))
1410
1564
 
1411
1565
 
1412
1566
class cmd_checkout(Command):
1496
1650
    def run(self, dir=u'.'):
1497
1651
        tree = WorkingTree.open_containing(dir)[0]
1498
1652
        self.add_cleanup(tree.lock_read().unlock)
1499
 
        new_inv = tree.inventory
 
1653
        new_inv = tree.root_inventory
1500
1654
        old_tree = tree.basis_tree()
1501
1655
        self.add_cleanup(old_tree.lock_read().unlock)
1502
 
        old_inv = old_tree.inventory
 
1656
        old_inv = old_tree.root_inventory
1503
1657
        renames = []
1504
1658
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1505
1659
        for f, paths, c, v, p, n, k, e in iterator:
2026
2180
            location = '.'
2027
2181
 
2028
2182
        to_transport = transport.get_transport(location)
2029
 
        to_transport.ensure_base()
2030
2183
 
2031
 
        newdir = format.initialize_on_transport(to_transport)
2032
 
        repo = newdir.create_repository(shared=True)
2033
 
        repo.set_make_working_trees(not no_trees)
 
2184
        (repo, newdir, require_stacking, repository_policy) = (
 
2185
            format.initialize_on_transport_ex(to_transport,
 
2186
            create_prefix=True, make_working_trees=not no_trees,
 
2187
            shared_repo=True, force_new_repo=True,
 
2188
            use_existing_dir=True,
 
2189
            repo_format_name=format.repository_format.get_format_string()))
2034
2190
        if not is_quiet():
2035
2191
            from bzrlib.info import show_bzrdir_info
2036
 
            show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
 
2192
            show_bzrdir_info(newdir, verbose=0, outfile=self.outf)
2037
2193
 
2038
2194
 
2039
2195
class cmd_diff(Command):
2217
2373
        self.add_cleanup(tree.lock_read().unlock)
2218
2374
        old = tree.basis_tree()
2219
2375
        self.add_cleanup(old.lock_read().unlock)
2220
 
        for path, ie in old.inventory.iter_entries():
 
2376
        for path, ie in old.iter_entries_by_dir():
2221
2377
            if not tree.has_id(ie.file_id):
2222
2378
                self.outf.write(path)
2223
2379
                if show_ids:
2261
2417
        self.add_cleanup(wt.lock_read().unlock)
2262
2418
        basis = wt.basis_tree()
2263
2419
        self.add_cleanup(basis.lock_read().unlock)
2264
 
        basis_inv = basis.inventory
2265
 
        inv = wt.inventory
2266
 
        for file_id in inv:
2267
 
            if basis_inv.has_id(file_id):
2268
 
                continue
2269
 
            if inv.is_root(file_id) and len(basis_inv) == 0:
2270
 
                continue
2271
 
            path = inv.id2path(file_id)
 
2420
        root_id = wt.get_root_id()
 
2421
        for file_id in wt.all_file_ids():
 
2422
            if basis.has_id(file_id):
 
2423
                continue
 
2424
            if root_id == file_id:
 
2425
                continue
 
2426
            path = wt.id2path(file_id)
2272
2427
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2273
2428
                continue
2274
2429
            if null:
2509
2664
                   help='Do not report commits with more than one parent.'),
2510
2665
            Option('exclude-common-ancestry',
2511
2666
                   help='Display only the revisions that are not part'
2512
 
                   ' of both ancestries (require -rX..Y)'
 
2667
                   ' of both ancestries (require -rX..Y).'
2513
2668
                   ),
2514
2669
            Option('signatures',
2515
 
                   help='Show digital signature validity'),
 
2670
                   help='Show digital signature validity.'),
2516
2671
            ListOption('match',
2517
2672
                short_name='m',
2518
2673
                help='Show revisions whose properties match this '
2636
2791
            self.add_cleanup(b.lock_read().unlock)
2637
2792
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2638
2793
 
2639
 
        if b.get_config().validate_signatures_in_log():
 
2794
        if b.get_config_stack().get('validate_signatures_in_log'):
2640
2795
            signatures = True
2641
2796
 
2642
2797
        if signatures:
3141
3296
        Option('per-file-timestamps',
3142
3297
               help='Set modification time of files to that of the last '
3143
3298
                    'revision in which it was changed.'),
 
3299
        Option('uncommitted',
 
3300
               help='Export the working tree contents rather than that of the '
 
3301
                    'last revision.'),
3144
3302
        ]
3145
3303
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3146
 
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
 
3304
        root=None, filters=False, per_file_timestamps=False, uncommitted=False,
 
3305
        directory=u'.'):
3147
3306
        from bzrlib.export import export
3148
3307
 
3149
3308
        if branch_or_subdir is None:
3150
 
            tree = WorkingTree.open_containing(directory)[0]
3151
 
            b = tree.branch
3152
 
            subdir = None
 
3309
            branch_or_subdir = directory
 
3310
 
 
3311
        (tree, b, subdir) = controldir.ControlDir.open_containing_tree_or_branch(
 
3312
            branch_or_subdir)
 
3313
        if tree is not None:
 
3314
            self.add_cleanup(tree.lock_read().unlock)
 
3315
 
 
3316
        if uncommitted:
 
3317
            if tree is None:
 
3318
                raise errors.BzrCommandError(
 
3319
                    gettext("--uncommitted requires a working tree"))
 
3320
            export_tree = tree
3153
3321
        else:
3154
 
            b, subdir = Branch.open_containing(branch_or_subdir)
3155
 
            tree = None
3156
 
 
3157
 
        rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
 
3322
            export_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
3158
3323
        try:
3159
 
            export(rev_tree, dest, format, root, subdir, filtered=filters,
 
3324
            export(export_tree, dest, format, root, subdir, filtered=filters,
3160
3325
                   per_file_timestamps=per_file_timestamps)
3161
3326
        except errors.NoSuchExportFormat, e:
3162
 
            raise errors.BzrCommandError(gettext('Unsupported export format: %s') % e.format)
 
3327
            raise errors.BzrCommandError(
 
3328
                gettext('Unsupported export format: %s') % e.format)
3163
3329
 
3164
3330
 
3165
3331
class cmd_cat(Command):
3351
3517
            tokens = fixed_bug.split(':')
3352
3518
            if len(tokens) == 1:
3353
3519
                if default_bugtracker is None:
3354
 
                    branch_config = branch.get_config()
3355
 
                    default_bugtracker = branch_config.get_user_option(
 
3520
                    branch_config = branch.get_config_stack()
 
3521
                    default_bugtracker = branch_config.get(
3356
3522
                        "bugtracker")
3357
3523
                if default_bugtracker is None:
3358
3524
                    raise errors.BzrCommandError(gettext(
3668
3834
            if directory is None:
3669
3835
                # use branch if we're inside one; otherwise global config
3670
3836
                try:
3671
 
                    c = Branch.open_containing(u'.')[0].get_config()
 
3837
                    c = Branch.open_containing(u'.')[0].get_config_stack()
3672
3838
                except errors.NotBranchError:
3673
 
                    c = _mod_config.GlobalConfig()
 
3839
                    c = _mod_config.GlobalStack()
3674
3840
            else:
3675
 
                c = Branch.open(directory).get_config()
 
3841
                c = Branch.open(directory).get_config_stack()
 
3842
            identity = c.get('email')
3676
3843
            if email:
3677
 
                self.outf.write(c.user_email() + '\n')
 
3844
                self.outf.write(_mod_config.extract_email_address(identity)
 
3845
                                + '\n')
3678
3846
            else:
3679
 
                self.outf.write(c.username() + '\n')
 
3847
                self.outf.write(identity + '\n')
3680
3848
            return
3681
3849
 
3682
3850
        if email:
3693
3861
        # use global config unless --branch given
3694
3862
        if branch:
3695
3863
            if directory is None:
3696
 
                c = Branch.open_containing(u'.')[0].get_config()
 
3864
                c = Branch.open_containing(u'.')[0].get_config_stack()
3697
3865
            else:
3698
 
                c = Branch.open(directory).get_config()
 
3866
                b = Branch.open(directory)
 
3867
                self.add_cleanup(b.lock_write().unlock)
 
3868
                c = b.get_config_stack()
3699
3869
        else:
3700
 
            c = _mod_config.GlobalConfig()
3701
 
        c.set_user_option('email', name)
 
3870
            c = _mod_config.GlobalStack()
 
3871
        c.set('email', name)
3702
3872
 
3703
3873
 
3704
3874
class cmd_nick(Command):
3705
3875
    __doc__ = """Print or set the branch nickname.
3706
3876
 
3707
 
    If unset, the tree root directory name is used as the nickname.
3708
 
    To print the current nickname, execute with no argument.
 
3877
    If unset, the colocated branch name is used for colocated branches, and
 
3878
    the branch directory name is used for other branches.  To print the
 
3879
    current nickname, execute with no argument.
3709
3880
 
3710
3881
    Bound branches use the nickname of its master branch unless it is set
3711
3882
    locally.
3929
4100
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3930
4101
            parallel=None, lsprof_tests=False,
3931
4102
            sync=False):
 
4103
 
 
4104
        # During selftest, disallow proxying, as it can cause severe
 
4105
        # performance penalties and is only needed for thread
 
4106
        # safety. The selftest command is assumed to not use threads
 
4107
        # too heavily. The call should be as early as possible, as
 
4108
        # error reporting for past duplicate imports won't have useful
 
4109
        # backtraces.
 
4110
        lazy_import.disallow_proxying()
 
4111
 
3932
4112
        from bzrlib import tests
3933
4113
 
3934
4114
        if testspecs_list is not None:
4084
4264
    Merge will do its best to combine the changes in two branches, but there
4085
4265
    are some kinds of problems only a human can fix.  When it encounters those,
4086
4266
    it will mark a conflict.  A conflict means that you need to fix something,
4087
 
    before you should commit.
 
4267
    before you can commit.
4088
4268
 
4089
4269
    Use bzr resolve when you have fixed a problem.  See also bzr conflicts.
4090
4270
 
4498
4678
                if tree.kind(file_id) != "directory":
4499
4679
                    continue
4500
4680
 
4501
 
                for name, ie in tree.inventory.iter_entries(file_id):
 
4681
                # FIXME: Support nested trees
 
4682
                for name, ie in tree.root_inventory.iter_entries(file_id):
4502
4683
                    interesting_ids.add(ie.file_id)
4503
4684
            new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4504
4685
        else:
4648
4829
 
4649
4830
    @display_command
4650
4831
    def run(self, context=None):
4651
 
        import shellcomplete
 
4832
        from bzrlib import shellcomplete
4652
4833
        shellcomplete.shellcomplete(context)
4653
4834
 
4654
4835
 
5012
5193
 
5013
5194
    def _run(self, b, revision_id_list, revision):
5014
5195
        import bzrlib.gpg as gpg
5015
 
        gpg_strategy = gpg.GPGStrategy(b.get_config())
 
5196
        gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
5016
5197
        if revision_id_list is not None:
5017
5198
            b.repository.start_write_group()
5018
5199
            try:
5085
5266
            else:
5086
5267
                if location is None:
5087
5268
                    if b.get_bound_location() is not None:
5088
 
                        raise errors.BzrCommandError(gettext('Branch is already bound'))
 
5269
                        raise errors.BzrCommandError(
 
5270
                            gettext('Branch is already bound'))
5089
5271
                    else:
5090
 
                        raise errors.BzrCommandError(gettext('No location supplied '
5091
 
                            'and no previous location known'))
 
5272
                        raise errors.BzrCommandError(
 
5273
                            gettext('No location supplied'
 
5274
                                    ' and no previous location known'))
5092
5275
        b_other = Branch.open(location)
5093
5276
        try:
5094
5277
            b.bind(b_other)
5346
5529
        if protocol is None:
5347
5530
            protocol = transport.transport_server_registry.get()
5348
5531
        host, port = self.get_host_and_port(port)
5349
 
        url = urlutils.local_path_to_url(directory)
 
5532
        url = transport.location_to_url(directory)
5350
5533
        if not allow_writes:
5351
5534
            url = 'readonly+' + url
5352
 
        t = transport.get_transport(url)
 
5535
        t = transport.get_transport_from_url(url)
5353
5536
        try:
5354
5537
            protocol(t, host, port, inet, client_timeout)
5355
5538
        except TypeError, e:
5504
5687
        if public_branch is None:
5505
5688
            public_branch = stored_public_branch
5506
5689
        elif stored_public_branch is None:
 
5690
            # FIXME: Should be done only if we succeed ? -- vila 2012-01-03
5507
5691
            branch.set_public_branch(public_branch)
5508
5692
        if not include_bundle and public_branch is None:
5509
5693
            raise errors.BzrCommandError(gettext('No public branch specified or'
5534
5718
                self.outf.writelines(directive.to_lines())
5535
5719
        else:
5536
5720
            message = directive.to_email(mail_to, branch, sign)
5537
 
            s = SMTPConnection(branch.get_config())
 
5721
            s = SMTPConnection(branch.get_config_stack())
5538
5722
            s.send_email(message)
5539
5723
 
5540
5724
 
6044
6228
        from bzrlib import switch
6045
6229
        tree_location = directory
6046
6230
        revision = _get_one_revision('switch', revision)
6047
 
        control_dir = controldir.ControlDir.open_containing(tree_location)[0]
 
6231
        possible_transports = []
 
6232
        control_dir = controldir.ControlDir.open_containing(tree_location,
 
6233
            possible_transports=possible_transports)[0]
6048
6234
        if to_location is None:
6049
6235
            if revision is None:
6050
6236
                raise errors.BzrCommandError(gettext('You must supply either a'
6051
6237
                                             ' revision or a location'))
6052
6238
            to_location = tree_location
6053
6239
        try:
6054
 
            branch = control_dir.open_branch()
 
6240
            branch = control_dir.open_branch(
 
6241
                possible_transports=possible_transports)
6055
6242
            had_explicit_nick = branch.get_config().has_explicit_nickname()
6056
6243
        except errors.NotBranchError:
6057
6244
            branch = None
6058
6245
            had_explicit_nick = False
6059
6246
        if create_branch:
6060
6247
            if branch is None:
6061
 
                raise errors.BzrCommandError(gettext('cannot create branch without'
6062
 
                                             ' source branch'))
6063
 
            to_location = directory_service.directories.dereference(
6064
 
                              to_location)
6065
 
            if '/' not in to_location and '\\' not in to_location:
6066
 
                # This path is meant to be relative to the existing branch
6067
 
                this_url = self._get_branch_location(control_dir)
6068
 
                to_location = urlutils.join(this_url, '..', to_location)
 
6248
                raise errors.BzrCommandError(
 
6249
                    gettext('cannot create branch without source branch'))
 
6250
            to_location = lookup_new_sibling_branch(control_dir, to_location,
 
6251
                 possible_transports=possible_transports)
6069
6252
            to_branch = branch.bzrdir.sprout(to_location,
6070
 
                                 possible_transports=[branch.bzrdir.root_transport],
6071
 
                                 source_branch=branch).open_branch()
 
6253
                 possible_transports=possible_transports,
 
6254
                 source_branch=branch).open_branch()
6072
6255
        else:
6073
 
            try:
6074
 
                to_branch = Branch.open(to_location)
6075
 
            except errors.NotBranchError:
6076
 
                this_url = self._get_branch_location(control_dir)
6077
 
                to_branch = Branch.open(
6078
 
                    urlutils.join(this_url, '..', to_location))
 
6256
            to_branch = lookup_sibling_branch(control_dir, to_location)
6079
6257
        if revision is not None:
6080
6258
            revision = revision.as_revision_id(to_branch)
6081
6259
        switch.switch(control_dir, to_branch, force, revision_id=revision)
6085
6263
        note(gettext('Switched to branch: %s'),
6086
6264
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6087
6265
 
6088
 
    def _get_branch_location(self, control_dir):
6089
 
        """Return location of branch for this control dir."""
6090
 
        try:
6091
 
            this_branch = control_dir.open_branch()
6092
 
            # This may be a heavy checkout, where we want the master branch
6093
 
            master_location = this_branch.get_bound_location()
6094
 
            if master_location is not None:
6095
 
                return master_location
6096
 
            # If not, use a local sibling
6097
 
            return this_branch.base
6098
 
        except errors.NotBranchError:
6099
 
            format = control_dir.find_branch_format()
6100
 
            if getattr(format, 'get_reference', None) is not None:
6101
 
                return format.get_reference(control_dir)
6102
 
            else:
6103
 
                return control_dir.root_transport.base
6104
6266
 
6105
6267
 
6106
6268
class cmd_view(Command):
6299
6461
    def run(self, location=None):
6300
6462
        if location is None:
6301
6463
            location = "."
6302
 
        branch = Branch.open_containing(location)[0]
6303
 
        branch.bzrdir.destroy_branch()
 
6464
        cdir = controldir.ControlDir.open_containing(location)[0]
 
6465
        cdir.destroy_branch()
6304
6466
 
6305
6467
 
6306
6468
class cmd_shelve(Command):
6514
6676
    takes_options = [Option('plugin', 
6515
6677
                            help='Export help text from named command '\
6516
6678
                                 '(defaults to all built in commands).',
6517
 
                            type=str)]
 
6679
                            type=str),
 
6680
                     Option('include-duplicates',
 
6681
                            help='Output multiple copies of the same msgid '
 
6682
                                 'string if it appears more than once.'),
 
6683
                            ]
6518
6684
 
6519
 
    def run(self, plugin=None):
 
6685
    def run(self, plugin=None, include_duplicates=False):
6520
6686
        from bzrlib.export_pot import export_pot
6521
 
        export_pot(self.outf, plugin)
 
6687
        export_pot(self.outf, plugin, include_duplicates)
6522
6688
 
6523
6689
 
6524
6690
def _register_lazy_builtins():