~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

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
 
from bzrlib.lazy_import import lazy_import
22
 
lazy_import(globals(), """
 
23
import bzrlib.bzrdir
 
24
 
 
25
from bzrlib import lazy_import
 
26
lazy_import.lazy_import(globals(), """
23
27
import cStringIO
 
28
import errno
24
29
import sys
25
30
import time
26
31
 
29
34
    bugtracker,
30
35
    bundle,
31
36
    btree_index,
32
 
    bzrdir,
 
37
    controldir,
33
38
    directory_service,
34
39
    delta,
35
40
    config as _mod_config,
78
83
    )
79
84
 
80
85
 
81
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
82
 
def tree_files(file_list, default_branch=u'.', canonicalize=True,
83
 
    apply_view=True):
84
 
    return internal_tree_files(file_list, default_branch, canonicalize,
85
 
        apply_view)
 
86
def _get_branch_location(control_dir, possible_transports=None):
 
87
    """Return location of branch for this control dir."""
 
88
    try:
 
89
        target = control_dir.get_branch_reference()
 
90
    except errors.NotBranchError:
 
91
        return control_dir.root_transport.base
 
92
    if target is not None:
 
93
        return target
 
94
    this_branch = control_dir.open_branch(
 
95
        possible_transports=possible_transports)
 
96
    # This may be a heavy checkout, where we want the master branch
 
97
    master_location = this_branch.get_bound_location()
 
98
    if master_location is not None:
 
99
        return master_location
 
100
    # If not, use a local sibling
 
101
    return this_branch.base
 
102
 
 
103
 
 
104
def _is_colocated(control_dir, possible_transports=None):
 
105
    """Check if the branch in control_dir is colocated.
 
106
 
 
107
    :param control_dir: Control directory
 
108
    :return: Tuple with boolean indicating whether the branch is colocated
 
109
        and the full URL to the actual branch
 
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 to find sibling branches from
 
136
    :param location: Name of the new branch
 
137
    :return: Full location to the new branch
 
138
    """
 
139
    location = directory_service.directories.dereference(location)
 
140
    if '/' not in location and '\\' not in location:
 
141
        (colocated, this_url) = _is_colocated(control_dir, possible_transports)
 
142
 
 
143
        if colocated:
 
144
            return urlutils.join_segment_parameters(this_url,
 
145
                {"branch": urlutils.escape(location)})
 
146
        else:
 
147
            return urlutils.join(this_url, '..', urlutils.escape(location))
 
148
    return location
 
149
 
 
150
 
 
151
def open_sibling_branch(control_dir, location, possible_transports=None):
 
152
    """Open a branch, possibly a sibling of another.
 
153
 
 
154
    :param control_dir: Control directory relative to which to lookup the
 
155
        location.
 
156
    :param location: Location to look up
 
157
    :return: branch to open
 
158
    """
 
159
    try:
 
160
        # Perhaps it's a colocated branch?
 
161
        return control_dir.open_branch(location, 
 
162
            possible_transports=possible_transports)
 
163
    except (errors.NotBranchError, errors.NoColocatedBranchSupport):
 
164
        this_url = _get_branch_location(control_dir)
 
165
        return Branch.open(
 
166
            urlutils.join(
 
167
                this_url, '..', urlutils.escape(location)))
 
168
 
 
169
 
 
170
def open_nearby_branch(near=None, location=None, possible_transports=None):
 
171
    """Open a nearby branch.
 
172
 
 
173
    :param near: Optional location of container from which to open branch
 
174
    :param location: Location of the branch
 
175
    :return: Branch instance
 
176
    """
 
177
    if near is None:
 
178
        if location is None:
 
179
            location = "."
 
180
        try:
 
181
            return Branch.open(location,
 
182
                possible_transports=possible_transports)
 
183
        except errors.NotBranchError:
 
184
            near = "."
 
185
    cdir = controldir.ControlDir.open(near,
 
186
        possible_transports=possible_transports)
 
187
    return open_sibling_branch(cdir, location,
 
188
        possible_transports=possible_transports)
 
189
 
 
190
 
 
191
def iter_sibling_branches(control_dir, possible_transports=None):
 
192
    """Iterate over the siblings of a branch.
 
193
 
 
194
    :param control_dir: Control directory for which to look up the siblings
 
195
    :return: Iterator over tuples with branch name and branch object
 
196
    """
 
197
    seen_urls = set()
 
198
    try:
 
199
        reference = control_dir.get_branch_reference()
 
200
    except errors.NotBranchError:
 
201
        # There is no active branch, just return the colocated branches.
 
202
        for name, branch in control_dir.get_branches().iteritems():
 
203
            yield name, branch
 
204
        return
 
205
    if reference is not None:
 
206
        ref_branch = Branch.open(reference,
 
207
            possible_transports=possible_transports)
 
208
    else:
 
209
        ref_branch = None
 
210
    if ref_branch is None or ref_branch.name:
 
211
        if ref_branch is not None:
 
212
            control_dir = ref_branch.bzrdir
 
213
        for name, branch in control_dir.get_branches().iteritems():
 
214
            yield name, branch
 
215
    else:
 
216
        repo = ref_branch.bzrdir.find_repository()
 
217
        for branch in repo.find_branches(using=True):
 
218
            name = urlutils.relative_url(repo.user_url,
 
219
                branch.user_url).rstrip("/")
 
220
            yield name, branch
86
221
 
87
222
 
88
223
def tree_files_for_add(file_list):
150
285
    return rev_tree
151
286
 
152
287
 
153
 
# XXX: Bad function name; should possibly also be a class method of
154
 
# WorkingTree rather than a function.
155
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
156
 
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
157
 
    apply_view=True):
158
 
    """Convert command-line paths to a WorkingTree and relative paths.
159
 
 
160
 
    Deprecated: use WorkingTree.open_containing_paths instead.
161
 
 
162
 
    This is typically used for command-line processors that take one or
163
 
    more filenames, and infer the workingtree that contains them.
164
 
 
165
 
    The filenames given are not required to exist.
166
 
 
167
 
    :param file_list: Filenames to convert.
168
 
 
169
 
    :param default_branch: Fallback tree path to use if file_list is empty or
170
 
        None.
171
 
 
172
 
    :param apply_view: if True and a view is set, apply it or check that
173
 
        specified files are within it
174
 
 
175
 
    :return: workingtree, [relative_paths]
176
 
    """
177
 
    return WorkingTree.open_containing_paths(
178
 
        file_list, default_directory='.',
179
 
        canonicalize=True,
180
 
        apply_view=True)
181
 
 
182
 
 
183
288
def _get_view_info_for_change_reporter(tree):
184
289
    """Get the view information from a tree for change reporting."""
185
290
    view_info = None
197
302
    the --directory option is used to specify a different branch."""
198
303
    if directory is not None:
199
304
        return (None, Branch.open(directory), filename)
200
 
    return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
305
    return controldir.ControlDir.open_containing_tree_or_branch(filename)
201
306
 
202
307
 
203
308
# TODO: Make sure no commands unconditionally use the working directory as a
263
368
    This will produce the same results as calling 'bzr diff --summarize'.
264
369
    """
265
370
 
266
 
    # TODO: --no-recurse, --recurse options
 
371
    # TODO: --no-recurse/-N, --recurse options
267
372
 
268
373
    takes_args = ['file*']
269
374
    takes_options = ['show-ids', 'revision', 'change', 'verbose',
339
444
            raise errors.BzrCommandError(gettext('You must supply either'
340
445
                                         ' --revision or a revision_id'))
341
446
 
342
 
        b = bzrdir.BzrDir.open_containing_tree_or_branch(directory)[1]
 
447
        b = controldir.ControlDir.open_containing_tree_or_branch(directory)[1]
343
448
 
344
449
        revisions = b.repository.revisions
345
450
        if revisions is None:
473
578
            location_list=['.']
474
579
 
475
580
        for location in location_list:
476
 
            d = bzrdir.BzrDir.open(location)
477
 
            
 
581
            d = controldir.ControlDir.open(location)
 
582
 
478
583
            try:
479
584
                working = d.open_workingtree()
480
585
            except errors.NoWorkingTree:
556
661
    _see_also = ['info']
557
662
    takes_args = ['location?']
558
663
    takes_options = [
559
 
        Option('tree', help='Show revno of working tree'),
 
664
        Option('tree', help='Show revno of working tree.'),
 
665
        'revision',
560
666
        ]
561
667
 
562
668
    @display_command
563
 
    def run(self, tree=False, location=u'.'):
 
669
    def run(self, tree=False, location=u'.', revision=None):
 
670
        if revision is not None and tree:
 
671
            raise errors.BzrCommandError(gettext("--tree and --revision can "
 
672
                "not be used together"))
 
673
 
564
674
        if tree:
565
675
            try:
566
676
                wt = WorkingTree.open_containing(location)[0]
567
677
                self.add_cleanup(wt.lock_read().unlock)
568
678
            except (errors.NoWorkingTree, errors.NotLocalUrl):
569
679
                raise errors.NoWorkingTree(location)
 
680
            b = wt.branch
570
681
            revid = wt.last_revision()
571
 
            try:
572
 
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
573
 
            except errors.NoSuchRevision:
574
 
                revno_t = ('???',)
575
 
            revno = ".".join(str(n) for n in revno_t)
576
682
        else:
577
683
            b = Branch.open_containing(location)[0]
578
684
            self.add_cleanup(b.lock_read().unlock)
579
 
            revno = b.revno()
 
685
            if revision:
 
686
                if len(revision) != 1:
 
687
                    raise errors.BzrCommandError(gettext(
 
688
                        "Revision numbers only make sense for single "
 
689
                        "revisions, not ranges"))
 
690
                revid = revision[0].as_revision_id(b)
 
691
            else:
 
692
                revid = b.last_revision()
 
693
        try:
 
694
            revno_t = b.revision_id_to_dotted_revno(revid)
 
695
        except errors.NoSuchRevision:
 
696
            revno_t = ('???',)
 
697
        revno = ".".join(str(n) for n in revno_t)
580
698
        self.cleanup_now()
581
 
        self.outf.write(str(revno) + '\n')
 
699
        self.outf.write(revno + '\n')
582
700
 
583
701
 
584
702
class cmd_revision_info(Command):
591
709
        custom_help('directory',
592
710
            help='Branch to examine, '
593
711
                 'rather than the one containing the working directory.'),
594
 
        Option('tree', help='Show revno of working tree'),
 
712
        Option('tree', help='Show revno of working tree.'),
595
713
        ]
596
714
 
597
715
    @display_command
685
803
    takes_args = ['file*']
686
804
    takes_options = [
687
805
        Option('no-recurse',
688
 
               help="Don't recursively add the contents of directories."),
 
806
               help="Don't recursively add the contents of directories.",
 
807
               short_name='N'),
689
808
        Option('dry-run',
690
809
               help="Show what would be done, but don't actually do anything."),
691
810
        'verbose',
738
857
    """
739
858
 
740
859
    takes_args = ['dir+']
 
860
    takes_options = [
 
861
        Option(
 
862
            'parents',
 
863
            help='No error if existing, make parent directories as needed.',
 
864
            short_name='p'
 
865
            )
 
866
        ]
741
867
    encoding_type = 'replace'
742
868
 
743
 
    def run(self, dir_list):
744
 
        for d in dir_list:
745
 
            wt, dd = WorkingTree.open_containing(d)
746
 
            base = os.path.dirname(dd)
747
 
            id = wt.path2id(base)
748
 
            if id != None:
749
 
                os.mkdir(d)
750
 
                wt.add([dd])
751
 
                self.outf.write(gettext('added %s\n') % d)
 
869
    @classmethod
 
870
    def add_file_with_parents(cls, wt, relpath):
 
871
        if wt.path2id(relpath) is not None:
 
872
            return
 
873
        cls.add_file_with_parents(wt, osutils.dirname(relpath))
 
874
        wt.add([relpath])
 
875
 
 
876
    @classmethod
 
877
    def add_file_single(cls, wt, relpath):
 
878
        wt.add([relpath])
 
879
 
 
880
    def run(self, dir_list, parents=False):
 
881
        if parents:
 
882
            add_file = self.add_file_with_parents
 
883
        else:
 
884
            add_file = self.add_file_single
 
885
        for dir in dir_list:
 
886
            wt, relpath = WorkingTree.open_containing(dir)
 
887
            if parents:
 
888
                try:
 
889
                    os.makedirs(dir)
 
890
                except OSError, e:
 
891
                    if e.errno != errno.EEXIST:
 
892
                        raise
752
893
            else:
753
 
                raise errors.NotVersionedError(path=base)
 
894
                os.mkdir(dir)
 
895
            add_file(wt, relpath)
 
896
            if not is_quiet():
 
897
                self.outf.write(gettext('added %s\n') % dir)
754
898
 
755
899
 
756
900
class cmd_relpath(Command):
806
950
            tree = work_tree
807
951
            extra_trees = []
808
952
 
 
953
        self.add_cleanup(tree.lock_read().unlock)
809
954
        if file_list is not None:
810
955
            file_ids = tree.paths2ids(file_list, trees=extra_trees,
811
956
                                      require_versioned=True)
812
957
            # find_ids_across_trees may include some paths that don't
813
958
            # exist in 'tree'.
814
 
            entries = sorted(
815
 
                (tree.id2path(file_id), tree.inventory[file_id])
816
 
                for file_id in file_ids if tree.has_id(file_id))
 
959
            entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
817
960
        else:
818
 
            entries = tree.inventory.entries()
 
961
            entries = tree.iter_entries_by_dir()
819
962
 
820
 
        self.cleanup_now()
821
 
        for path, entry in entries:
 
963
        for path, entry in sorted(entries):
822
964
            if kind and kind != entry.kind:
823
965
                continue
 
966
            if path == "":
 
967
                continue
824
968
            if show_ids:
825
969
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
826
970
            else:
868
1012
        if len(names_list) < 2:
869
1013
            raise errors.BzrCommandError(gettext("missing file argument"))
870
1014
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
 
1015
        for file_name in rel_names[0:-1]:
 
1016
            if file_name == '':
 
1017
                raise errors.BzrCommandError(gettext("can not move root of branch"))
871
1018
        self.add_cleanup(tree.lock_tree_write().unlock)
872
1019
        self._run(tree, names_list, rel_names, after)
873
1020
 
895
1042
                and rel_names[0].lower() == rel_names[1].lower()):
896
1043
                into_existing = False
897
1044
            else:
898
 
                inv = tree.inventory
899
1045
                # 'fix' the case of a potential 'from'
900
1046
                from_id = tree.path2id(
901
1047
                            tree.get_canonical_inventory_path(rel_names[0]))
902
1048
                if (not osutils.lexists(names_list[0]) and
903
 
                    from_id and inv.get_file_kind(from_id) == "directory"):
 
1049
                    from_id and tree.stored_kind(from_id) == "directory"):
904
1050
                    into_existing = False
905
1051
        # move/rename
906
1052
        if into_existing:
985
1131
    location to use the default.  To change the default, use --remember. The
986
1132
    value will only be saved if the remote location can be accessed.
987
1133
 
 
1134
    The --verbose option will display the revisions pulled using the log_format
 
1135
    configuration option. You can use a different format by overriding it with
 
1136
    -Olog_format=<other_format>.
 
1137
 
988
1138
    Note: The location can be specified either in the form of a branch,
989
1139
    or in the form of a path to a file containing a merge directive generated
990
1140
    with bzr send.
1003
1153
                 "the master branch."
1004
1154
            ),
1005
1155
        Option('show-base',
1006
 
            help="Show base revision text in conflicts.")
 
1156
            help="Show base revision text in conflicts."),
 
1157
        Option('overwrite-tags',
 
1158
            help="Overwrite tags only."),
1007
1159
        ]
1008
1160
    takes_args = ['location?']
1009
1161
    encoding_type = 'replace'
1011
1163
    def run(self, location=None, remember=None, overwrite=False,
1012
1164
            revision=None, verbose=False,
1013
1165
            directory=None, local=False,
1014
 
            show_base=False):
 
1166
            show_base=False, overwrite_tags=False):
 
1167
 
 
1168
        if overwrite:
 
1169
            overwrite = ["history", "tags"]
 
1170
        elif overwrite_tags:
 
1171
            overwrite = ["tags"]
 
1172
        else:
 
1173
            overwrite = []
1015
1174
        # FIXME: too much stuff is in the command class
1016
1175
        revision_id = None
1017
1176
        mergeable = None
1025
1184
            tree_to = None
1026
1185
            branch_to = Branch.open_containing(directory)[0]
1027
1186
            self.add_cleanup(branch_to.lock_write().unlock)
1028
 
 
1029
 
        if tree_to is None and show_base:
1030
 
            raise errors.BzrCommandError(gettext("Need working tree for --show-base."))
 
1187
            if show_base:
 
1188
                warning(gettext("No working tree, ignoring --show-base"))
1031
1189
 
1032
1190
        if local and not branch_to.get_bound_location():
1033
1191
            raise errors.LocalRequiresBoundBranch()
1068
1226
            # Remembers if asked explicitly or no previous location is set
1069
1227
            if (remember
1070
1228
                or (remember is None and branch_to.get_parent() is None)):
 
1229
                # FIXME: This shouldn't be done before the pull
 
1230
                # succeeds... -- vila 2012-01-02
1071
1231
                branch_to.set_parent(branch_from.base)
1072
1232
 
1073
1233
        if revision is not None:
1120
1280
    --no-remember to avoid setting it).  After that, you can omit the
1121
1281
    location to use the default.  To change the default, use --remember. The
1122
1282
    value will only be saved if the remote location can be accessed.
 
1283
 
 
1284
    The --verbose option will display the revisions pushed using the log_format
 
1285
    configuration option. You can use a different format by overriding it with
 
1286
    -Olog_format=<other_format>.
1123
1287
    """
1124
1288
 
1125
1289
    _see_also = ['pull', 'update', 'working-trees']
1149
1313
        Option('no-tree',
1150
1314
               help="Don't populate the working tree, even for protocols"
1151
1315
               " that support it."),
 
1316
        Option('overwrite-tags',
 
1317
              help="Overwrite tags only."),
1152
1318
        ]
1153
1319
    takes_args = ['location?']
1154
1320
    encoding_type = 'replace'
1156
1322
    def run(self, location=None, remember=None, overwrite=False,
1157
1323
        create_prefix=False, verbose=False, revision=None,
1158
1324
        use_existing_dir=False, directory=None, stacked_on=None,
1159
 
        stacked=False, strict=None, no_tree=False):
 
1325
        stacked=False, strict=None, no_tree=False,
 
1326
        overwrite_tags=False):
1160
1327
        from bzrlib.push import _show_push_branch
1161
1328
 
 
1329
        if overwrite:
 
1330
            overwrite = ["history", "tags"]
 
1331
        elif overwrite_tags:
 
1332
            overwrite = ["tags"]
 
1333
        else:
 
1334
            overwrite = []
 
1335
 
1162
1336
        if directory is None:
1163
1337
            directory = '.'
1164
1338
        # Get the source branch
1165
1339
        (tree, br_from,
1166
 
         _unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
 
1340
         _unused) = controldir.ControlDir.open_containing_tree_or_branch(directory)
1167
1341
        # Get the tip's revision_id
1168
1342
        revision = _get_one_revision('push', revision)
1169
1343
        if revision is not None:
1197
1371
        if location is None:
1198
1372
            stored_loc = br_from.get_push_location()
1199
1373
            if stored_loc is None:
1200
 
                raise errors.BzrCommandError(gettext(
1201
 
                    "No push location known or specified."))
 
1374
                parent_loc = br_from.get_parent()
 
1375
                if parent_loc:
 
1376
                    raise errors.BzrCommandError(gettext(
 
1377
                        "No push location known or specified. To push to the "
 
1378
                        "parent branch (at %s), use 'bzr push :parent'." %
 
1379
                        urlutils.unescape_for_display(parent_loc,
 
1380
                            self.outf.encoding)))
 
1381
                else:
 
1382
                    raise errors.BzrCommandError(gettext(
 
1383
                        "No push location known or specified."))
1202
1384
            else:
1203
1385
                display_url = urlutils.unescape_for_display(stored_loc,
1204
1386
                        self.outf.encoding)
1266
1448
                deprecated_name=self.invoked_as,
1267
1449
                recommended_name='branch',
1268
1450
                deprecated_in_version='2.4')
1269
 
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
 
1451
        accelerator_tree, br_from = controldir.ControlDir.open_tree_or_branch(
1270
1452
            from_location)
1271
1453
        if not (hardlink or files_from):
1272
1454
            # accelerator_tree is usually slower because you have to read N
1285
1467
            # RBC 20060209
1286
1468
            revision_id = br_from.last_revision()
1287
1469
        if to_location is None:
1288
 
            to_location = urlutils.derive_to_location(from_location)
 
1470
            to_location = getattr(br_from, "name", None)
 
1471
            if not to_location:
 
1472
                to_location = urlutils.derive_to_location(from_location)
1289
1473
        to_transport = transport.get_transport(to_location)
1290
1474
        try:
1291
1475
            to_transport.mkdir('.')
1292
1476
        except errors.FileExists:
1293
 
            if not use_existing_dir:
1294
 
                raise errors.BzrCommandError(gettext('Target directory "%s" '
1295
 
                    'already exists.') % to_location)
 
1477
            try:
 
1478
                to_dir = controldir.ControlDir.open_from_transport(
 
1479
                    to_transport)
 
1480
            except errors.NotBranchError:
 
1481
                if not use_existing_dir:
 
1482
                    raise errors.BzrCommandError(gettext('Target directory "%s" '
 
1483
                        'already exists.') % to_location)
 
1484
                else:
 
1485
                    to_dir = None
1296
1486
            else:
1297
1487
                try:
1298
 
                    bzrdir.BzrDir.open_from_transport(to_transport)
 
1488
                    to_dir.open_branch()
1299
1489
                except errors.NotBranchError:
1300
1490
                    pass
1301
1491
                else:
1303
1493
        except errors.NoSuchFile:
1304
1494
            raise errors.BzrCommandError(gettext('Parent of "%s" does not exist.')
1305
1495
                                         % to_location)
1306
 
        try:
1307
 
            # preserve whatever source format we have.
1308
 
            dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1309
 
                                        possible_transports=[to_transport],
1310
 
                                        accelerator_tree=accelerator_tree,
1311
 
                                        hardlink=hardlink, stacked=stacked,
1312
 
                                        force_new_repo=standalone,
1313
 
                                        create_tree_if_local=not no_tree,
1314
 
                                        source_branch=br_from)
1315
 
            branch = dir.open_branch()
1316
 
        except errors.NoSuchRevision:
1317
 
            to_transport.delete_tree('.')
1318
 
            msg = gettext("The branch {0} has no revision {1}.").format(
1319
 
                from_location, revision)
1320
 
            raise errors.BzrCommandError(msg)
 
1496
        else:
 
1497
            to_dir = None
 
1498
        if to_dir is None:
 
1499
            try:
 
1500
                # preserve whatever source format we have.
 
1501
                to_dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
 
1502
                                            possible_transports=[to_transport],
 
1503
                                            accelerator_tree=accelerator_tree,
 
1504
                                            hardlink=hardlink, stacked=stacked,
 
1505
                                            force_new_repo=standalone,
 
1506
                                            create_tree_if_local=not no_tree,
 
1507
                                            source_branch=br_from)
 
1508
                branch = to_dir.open_branch(
 
1509
                    possible_transports=[
 
1510
                        br_from.bzrdir.root_transport, to_transport])
 
1511
            except errors.NoSuchRevision:
 
1512
                to_transport.delete_tree('.')
 
1513
                msg = gettext("The branch {0} has no revision {1}.").format(
 
1514
                    from_location, revision)
 
1515
                raise errors.BzrCommandError(msg)
 
1516
        else:
 
1517
            try:
 
1518
                to_repo = to_dir.open_repository()
 
1519
            except errors.NoRepositoryPresent:
 
1520
                to_repo = to_dir.create_repository()
 
1521
            to_repo.fetch(br_from.repository, revision_id=revision_id)
 
1522
            branch = br_from.sprout(to_dir, revision_id=revision_id)
1321
1523
        _merge_tags_if_possible(br_from, branch)
1322
1524
        # If the source branch is stacked, the new branch may
1323
1525
        # be stacked whether we asked for that explicitly or not.
1360
1562
            if not t.listable():
1361
1563
                raise errors.BzrCommandError(
1362
1564
                    "Can't scan this type of location.")
1363
 
            for b in bzrdir.BzrDir.find_branches(t):
 
1565
            for b in controldir.ControlDir.find_branches(t):
1364
1566
                self.outf.write("%s\n" % urlutils.unescape_for_display(
1365
1567
                    urlutils.relative_url(t.base, b.base),
1366
1568
                    self.outf.encoding).rstrip("/"))
1367
1569
        else:
1368
 
            dir = bzrdir.BzrDir.open_containing(location)[0]
1369
 
            for branch in dir.list_branches():
1370
 
                if branch.name is None:
1371
 
                    self.outf.write(gettext(" (default)\n"))
 
1570
            dir = controldir.ControlDir.open_containing(location)[0]
 
1571
            try:
 
1572
                active_branch = dir.open_branch(name="")
 
1573
            except errors.NotBranchError:
 
1574
                active_branch = None
 
1575
            names = {}
 
1576
            for name, branch in iter_sibling_branches(dir):
 
1577
                if name == "":
 
1578
                    continue
 
1579
                active = (active_branch is not None and
 
1580
                          active_branch.base == branch.base)
 
1581
                names[name] = active
 
1582
            # Only mention the current branch explicitly if it's not
 
1583
            # one of the colocated branches
 
1584
            if not any(names.values()) and active_branch is not None:
 
1585
                self.outf.write("* %s\n" % gettext("(default)"))
 
1586
            for name in sorted(names.keys()):
 
1587
                active = names[name]
 
1588
                if active:
 
1589
                    prefix = "*"
1372
1590
                else:
1373
 
                    self.outf.write(" %s\n" % branch.name.encode(
1374
 
                        self.outf.encoding))
 
1591
                    prefix = " "
 
1592
                self.outf.write("%s %s\n" % (
 
1593
                    prefix, name.encode(self.outf.encoding)))
1375
1594
 
1376
1595
 
1377
1596
class cmd_checkout(Command):
1395
1614
    code.)
1396
1615
    """
1397
1616
 
1398
 
    _see_also = ['checkouts', 'branch']
 
1617
    _see_also = ['checkouts', 'branch', 'working-trees', 'remove-tree']
1399
1618
    takes_args = ['branch_location?', 'to_location?']
1400
1619
    takes_options = ['revision',
1401
1620
                     Option('lightweight',
1418
1637
        if branch_location is None:
1419
1638
            branch_location = osutils.getcwd()
1420
1639
            to_location = branch_location
1421
 
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
 
1640
        accelerator_tree, source = controldir.ControlDir.open_tree_or_branch(
1422
1641
            branch_location)
1423
1642
        if not (hardlink or files_from):
1424
1643
            # accelerator_tree is usually slower because you have to read N
1461
1680
    def run(self, dir=u'.'):
1462
1681
        tree = WorkingTree.open_containing(dir)[0]
1463
1682
        self.add_cleanup(tree.lock_read().unlock)
1464
 
        new_inv = tree.inventory
1465
1683
        old_tree = tree.basis_tree()
1466
1684
        self.add_cleanup(old_tree.lock_read().unlock)
1467
 
        old_inv = old_tree.inventory
1468
1685
        renames = []
1469
1686
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1470
1687
        for f, paths, c, v, p, n, k, e in iterator:
1479
1696
 
1480
1697
 
1481
1698
class cmd_update(Command):
1482
 
    __doc__ = """Update a tree to have the latest code committed to its branch.
1483
 
 
1484
 
    This will perform a merge into the working tree, and may generate
1485
 
    conflicts. If you have any local changes, you will still
1486
 
    need to commit them after the update for the update to be complete.
1487
 
 
1488
 
    If you want to discard your local changes, you can just do a
1489
 
    'bzr revert' instead of 'bzr commit' after the update.
1490
 
 
1491
 
    If you want to restore a file that has been removed locally, use
1492
 
    'bzr revert' instead of 'bzr update'.
1493
 
 
1494
 
    If the tree's branch is bound to a master branch, it will also update
 
1699
    __doc__ = """Update a working tree to a new revision.
 
1700
 
 
1701
    This will perform a merge of the destination revision (the tip of the
 
1702
    branch, or the specified revision) into the working tree, and then make
 
1703
    that revision the basis revision for the working tree.  
 
1704
 
 
1705
    You can use this to visit an older revision, or to update a working tree
 
1706
    that is out of date from its branch.
 
1707
    
 
1708
    If there are any uncommitted changes in the tree, they will be carried
 
1709
    across and remain as uncommitted changes after the update.  To discard
 
1710
    these changes, use 'bzr revert'.  The uncommitted changes may conflict
 
1711
    with the changes brought in by the change in basis revision.
 
1712
 
 
1713
    If the tree's branch is bound to a master branch, bzr will also update
1495
1714
    the branch from the master.
 
1715
 
 
1716
    You cannot update just a single file or directory, because each Bazaar
 
1717
    working tree has just a single basis revision.  If you want to restore a
 
1718
    file that has been removed locally, use 'bzr revert' instead of 'bzr
 
1719
    update'.  If you want to restore a file to its state in a previous
 
1720
    revision, use 'bzr revert' with a '-r' option, or use 'bzr cat' to write
 
1721
    out the old content of that file to a new location.
 
1722
 
 
1723
    The 'dir' argument, if given, must be the location of the root of a
 
1724
    working tree to update.  By default, the working tree that contains the 
 
1725
    current working directory is used.
1496
1726
    """
1497
1727
 
1498
1728
    _see_also = ['pull', 'working-trees', 'status-flags']
1503
1733
                     ]
1504
1734
    aliases = ['up']
1505
1735
 
1506
 
    def run(self, dir='.', revision=None, show_base=None):
 
1736
    def run(self, dir=None, revision=None, show_base=None):
1507
1737
        if revision is not None and len(revision) != 1:
1508
1738
            raise errors.BzrCommandError(gettext(
1509
 
                        "bzr update --revision takes exactly one revision"))
1510
 
        tree = WorkingTree.open_containing(dir)[0]
 
1739
                "bzr update --revision takes exactly one revision"))
 
1740
        if dir is None:
 
1741
            tree = WorkingTree.open_containing('.')[0]
 
1742
        else:
 
1743
            tree, relpath = WorkingTree.open_containing(dir)
 
1744
            if relpath:
 
1745
                # See bug 557886.
 
1746
                raise errors.BzrCommandError(gettext(
 
1747
                    "bzr update can only update a whole tree, "
 
1748
                    "not a file or subdirectory"))
1511
1749
        branch = tree.branch
1512
1750
        possible_transports = []
1513
1751
        master = branch.get_master_branch(
1611
1849
        else:
1612
1850
            noise_level = 0
1613
1851
        from bzrlib.info import show_bzrdir_info
1614
 
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
 
1852
        show_bzrdir_info(controldir.ControlDir.open_containing(location)[0],
1615
1853
                         verbose=noise_level, outfile=self.outf)
1616
1854
 
1617
1855
 
1620
1858
 
1621
1859
    This makes Bazaar stop tracking changes to the specified files. Bazaar will
1622
1860
    delete them if they can easily be recovered using revert otherwise they
1623
 
    will be backed up (adding an extention of the form .~#~). If no options or
 
1861
    will be backed up (adding an extension of the form .~#~). If no options or
1624
1862
    parameters are given Bazaar will scan for files that are being tracked by
1625
1863
    Bazaar but missing in your tree and stop tracking them for you.
1626
1864
    """
1632
1870
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1633
1871
            safe='Backup changed files (default).',
1634
1872
            keep='Delete from bzr but leave the working copy.',
1635
 
            no_backup='Don\'t backup changed files.',
1636
 
            force='Delete all the specified files, even if they can not be '
1637
 
                'recovered and even if they are non-empty directories. '
1638
 
                '(deprecated, use no-backup)')]
 
1873
            no_backup='Don\'t backup changed files.'),
 
1874
        ]
1639
1875
    aliases = ['rm', 'del']
1640
1876
    encoding_type = 'replace'
1641
1877
 
1642
1878
    def run(self, file_list, verbose=False, new=False,
1643
1879
        file_deletion_strategy='safe'):
1644
 
        if file_deletion_strategy == 'force':
1645
 
            note(gettext("(The --force option is deprecated, rather use --no-backup "
1646
 
                "in future.)"))
1647
 
            file_deletion_strategy = 'no-backup'
1648
1880
 
1649
1881
        tree, file_list = WorkingTree.open_containing_paths(file_list)
1650
1882
 
1749
1981
 
1750
1982
    def run(self, branch=".", canonicalize_chks=False):
1751
1983
        from bzrlib.reconcile import reconcile
1752
 
        dir = bzrdir.BzrDir.open(branch)
 
1984
        dir = controldir.ControlDir.open(branch)
1753
1985
        reconcile(dir, canonicalize_chks=canonicalize_chks)
1754
1986
 
1755
1987
 
1764
1996
    @display_command
1765
1997
    def run(self, location="."):
1766
1998
        branch = Branch.open_containing(location)[0]
1767
 
        for revid in branch.revision_history():
 
1999
        self.add_cleanup(branch.lock_read().unlock)
 
2000
        graph = branch.repository.get_graph()
 
2001
        history = list(graph.iter_lefthand_ancestry(branch.last_revision(),
 
2002
            [_mod_revision.NULL_REVISION]))
 
2003
        for revid in reversed(history):
1768
2004
            self.outf.write(revid)
1769
2005
            self.outf.write('\n')
1770
2006
 
1830
2066
         RegistryOption('format',
1831
2067
                help='Specify a format for this branch. '
1832
2068
                'See "help formats".',
1833
 
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1834
 
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
2069
                lazy_registry=('bzrlib.controldir', 'format_registry'),
 
2070
                converter=lambda name: controldir.format_registry.make_bzrdir(name),
1835
2071
                value_switches=True,
1836
2072
                title="Branch format",
1837
2073
                ),
1844
2080
    def run(self, location=None, format=None, append_revisions_only=False,
1845
2081
            create_prefix=False, no_tree=False):
1846
2082
        if format is None:
1847
 
            format = bzrdir.format_registry.make_bzrdir('default')
 
2083
            format = controldir.format_registry.make_bzrdir('default')
1848
2084
        if location is None:
1849
2085
            location = u'.'
1850
2086
 
1867
2103
            to_transport.create_prefix()
1868
2104
 
1869
2105
        try:
1870
 
            a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
 
2106
            a_bzrdir = controldir.ControlDir.open_from_transport(to_transport)
1871
2107
        except errors.NotBranchError:
1872
2108
            # really a NotBzrDir error...
1873
 
            create_branch = bzrdir.BzrDir.create_branch_convenience
 
2109
            create_branch = controldir.ControlDir.create_branch_convenience
1874
2110
            if no_tree:
1875
2111
                force_new_tree = False
1876
2112
            else:
1887
2123
                        raise errors.BranchExistsWithoutWorkingTree(location)
1888
2124
                raise errors.AlreadyBranchError(location)
1889
2125
            branch = a_bzrdir.create_branch()
1890
 
            if not no_tree:
 
2126
            if not no_tree and not a_bzrdir.has_workingtree():
1891
2127
                a_bzrdir.create_workingtree()
1892
2128
        if append_revisions_only:
1893
2129
            try:
1949
2185
    takes_options = [RegistryOption('format',
1950
2186
                            help='Specify a format for this repository. See'
1951
2187
                                 ' "bzr help formats" for details.',
1952
 
                            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1953
 
                            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
2188
                            lazy_registry=('bzrlib.controldir', 'format_registry'),
 
2189
                            converter=lambda name: controldir.format_registry.make_bzrdir(name),
1954
2190
                            value_switches=True, title='Repository format'),
1955
2191
                     Option('no-trees',
1956
2192
                             help='Branches in the repository will default to'
1960
2196
 
1961
2197
    def run(self, location, format=None, no_trees=False):
1962
2198
        if format is None:
1963
 
            format = bzrdir.format_registry.make_bzrdir('default')
 
2199
            format = controldir.format_registry.make_bzrdir('default')
1964
2200
 
1965
2201
        if location is None:
1966
2202
            location = '.'
1967
2203
 
1968
2204
        to_transport = transport.get_transport(location)
1969
 
        to_transport.ensure_base()
1970
2205
 
1971
 
        newdir = format.initialize_on_transport(to_transport)
1972
 
        repo = newdir.create_repository(shared=True)
1973
 
        repo.set_make_working_trees(not no_trees)
 
2206
        (repo, newdir, require_stacking, repository_policy) = (
 
2207
            format.initialize_on_transport_ex(to_transport,
 
2208
            create_prefix=True, make_working_trees=not no_trees,
 
2209
            shared_repo=True, force_new_repo=True,
 
2210
            use_existing_dir=True,
 
2211
            repo_format_name=format.repository_format.get_format_string()))
1974
2212
        if not is_quiet():
1975
2213
            from bzrlib.info import show_bzrdir_info
1976
 
            show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
 
2214
            show_bzrdir_info(newdir, verbose=0, outfile=self.outf)
1977
2215
 
1978
2216
 
1979
2217
class cmd_diff(Command):
2090
2328
            help='Diff format to use.',
2091
2329
            lazy_registry=('bzrlib.diff', 'format_registry'),
2092
2330
            title='Diff format'),
 
2331
        Option('context',
 
2332
            help='How many lines of context to show.',
 
2333
            type=int,
 
2334
            ),
2093
2335
        ]
2094
2336
    aliases = ['di', 'dif']
2095
2337
    encoding_type = 'exact'
2096
2338
 
2097
2339
    @display_command
2098
2340
    def run(self, revision=None, file_list=None, diff_options=None,
2099
 
            prefix=None, old=None, new=None, using=None, format=None):
 
2341
            prefix=None, old=None, new=None, using=None, format=None, 
 
2342
            context=None):
2100
2343
        from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
2101
2344
            show_diff_trees)
2102
2345
 
2135
2378
                               old_label=old_label, new_label=new_label,
2136
2379
                               extra_trees=extra_trees,
2137
2380
                               path_encoding=path_encoding,
2138
 
                               using=using,
 
2381
                               using=using, context=context,
2139
2382
                               format_cls=format)
2140
2383
 
2141
2384
 
2157
2400
        self.add_cleanup(tree.lock_read().unlock)
2158
2401
        old = tree.basis_tree()
2159
2402
        self.add_cleanup(old.lock_read().unlock)
2160
 
        for path, ie in old.inventory.iter_entries():
 
2403
        for path, ie in old.iter_entries_by_dir():
2161
2404
            if not tree.has_id(ie.file_id):
2162
2405
                self.outf.write(path)
2163
2406
                if show_ids:
2201
2444
        self.add_cleanup(wt.lock_read().unlock)
2202
2445
        basis = wt.basis_tree()
2203
2446
        self.add_cleanup(basis.lock_read().unlock)
2204
 
        basis_inv = basis.inventory
2205
 
        inv = wt.inventory
2206
 
        for file_id in inv:
2207
 
            if basis_inv.has_id(file_id):
2208
 
                continue
2209
 
            if inv.is_root(file_id) and len(basis_inv) == 0:
2210
 
                continue
2211
 
            path = inv.id2path(file_id)
 
2447
        root_id = wt.get_root_id()
 
2448
        for file_id in wt.all_file_ids():
 
2449
            if basis.has_id(file_id):
 
2450
                continue
 
2451
            if root_id == file_id:
 
2452
                continue
 
2453
            path = wt.id2path(file_id)
2212
2454
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2213
2455
                continue
2214
2456
            if null:
2449
2691
                   help='Do not report commits with more than one parent.'),
2450
2692
            Option('exclude-common-ancestry',
2451
2693
                   help='Display only the revisions that are not part'
2452
 
                   ' of both ancestries (require -rX..Y)'
 
2694
                   ' of both ancestries (require -rX..Y).'
2453
2695
                   ),
2454
2696
            Option('signatures',
2455
 
                   help='Show digital signature validity'),
 
2697
                   help='Show digital signature validity.'),
2456
2698
            ListOption('match',
2457
2699
                short_name='m',
2458
2700
                help='Show revisions whose properties match this '
2571
2813
                location = revision[0].get_branch()
2572
2814
            else:
2573
2815
                location = '.'
2574
 
            dir, relpath = bzrdir.BzrDir.open_containing(location)
 
2816
            dir, relpath = controldir.ControlDir.open_containing(location)
2575
2817
            b = dir.open_branch()
2576
2818
            self.add_cleanup(b.lock_read().unlock)
2577
2819
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2578
2820
 
2579
 
        if b.get_config().validate_signatures_in_log():
 
2821
        if b.get_config_stack().get('validate_signatures_in_log'):
2580
2822
            signatures = True
2581
2823
 
2582
2824
        if signatures:
3081
3323
        Option('per-file-timestamps',
3082
3324
               help='Set modification time of files to that of the last '
3083
3325
                    'revision in which it was changed.'),
 
3326
        Option('uncommitted',
 
3327
               help='Export the working tree contents rather than that of the '
 
3328
                    'last revision.'),
3084
3329
        ]
3085
3330
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3086
 
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
 
3331
        root=None, filters=False, per_file_timestamps=False, uncommitted=False,
 
3332
        directory=u'.'):
3087
3333
        from bzrlib.export import export
3088
3334
 
3089
3335
        if branch_or_subdir is None:
3090
 
            tree = WorkingTree.open_containing(directory)[0]
3091
 
            b = tree.branch
3092
 
            subdir = None
 
3336
            branch_or_subdir = directory
 
3337
 
 
3338
        (tree, b, subdir) = controldir.ControlDir.open_containing_tree_or_branch(
 
3339
            branch_or_subdir)
 
3340
        if tree is not None:
 
3341
            self.add_cleanup(tree.lock_read().unlock)
 
3342
 
 
3343
        if uncommitted:
 
3344
            if tree is None:
 
3345
                raise errors.BzrCommandError(
 
3346
                    gettext("--uncommitted requires a working tree"))
 
3347
            export_tree = tree
3093
3348
        else:
3094
 
            b, subdir = Branch.open_containing(branch_or_subdir)
3095
 
            tree = None
3096
 
 
3097
 
        rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
 
3349
            export_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
3098
3350
        try:
3099
 
            export(rev_tree, dest, format, root, subdir, filtered=filters,
 
3351
            export(export_tree, dest, format, root, subdir, filtered=filters,
3100
3352
                   per_file_timestamps=per_file_timestamps)
3101
3353
        except errors.NoSuchExportFormat, e:
3102
 
            raise errors.BzrCommandError(gettext('Unsupported export format: %s') % e.format)
 
3354
            raise errors.BzrCommandError(
 
3355
                gettext('Unsupported export format: %s') % e.format)
3103
3356
 
3104
3357
 
3105
3358
class cmd_cat(Command):
3291
3544
            tokens = fixed_bug.split(':')
3292
3545
            if len(tokens) == 1:
3293
3546
                if default_bugtracker is None:
3294
 
                    branch_config = branch.get_config()
3295
 
                    default_bugtracker = branch_config.get_user_option(
 
3547
                    branch_config = branch.get_config_stack()
 
3548
                    default_bugtracker = branch_config.get(
3296
3549
                        "bugtracker")
3297
3550
                if default_bugtracker is None:
3298
3551
                    raise errors.BzrCommandError(gettext(
3560
3813
        RegistryOption('format',
3561
3814
            help='Upgrade to a specific format.  See "bzr help'
3562
3815
                 ' formats" for details.',
3563
 
            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3564
 
            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
3816
            lazy_registry=('bzrlib.controldir', 'format_registry'),
 
3817
            converter=lambda name: controldir.format_registry.make_bzrdir(name),
3565
3818
            value_switches=True, title='Branch format'),
3566
3819
        Option('clean',
3567
3820
            help='Remove the backup.bzr directory if successful.'),
3608
3861
            if directory is None:
3609
3862
                # use branch if we're inside one; otherwise global config
3610
3863
                try:
3611
 
                    c = Branch.open_containing(u'.')[0].get_config()
 
3864
                    c = Branch.open_containing(u'.')[0].get_config_stack()
3612
3865
                except errors.NotBranchError:
3613
 
                    c = _mod_config.GlobalConfig()
 
3866
                    c = _mod_config.GlobalStack()
3614
3867
            else:
3615
 
                c = Branch.open(directory).get_config()
 
3868
                c = Branch.open(directory).get_config_stack()
 
3869
            identity = c.get('email')
3616
3870
            if email:
3617
 
                self.outf.write(c.user_email() + '\n')
 
3871
                self.outf.write(_mod_config.extract_email_address(identity)
 
3872
                                + '\n')
3618
3873
            else:
3619
 
                self.outf.write(c.username() + '\n')
 
3874
                self.outf.write(identity + '\n')
3620
3875
            return
3621
3876
 
3622
3877
        if email:
3633
3888
        # use global config unless --branch given
3634
3889
        if branch:
3635
3890
            if directory is None:
3636
 
                c = Branch.open_containing(u'.')[0].get_config()
 
3891
                c = Branch.open_containing(u'.')[0].get_config_stack()
3637
3892
            else:
3638
 
                c = Branch.open(directory).get_config()
 
3893
                b = Branch.open(directory)
 
3894
                self.add_cleanup(b.lock_write().unlock)
 
3895
                c = b.get_config_stack()
3639
3896
        else:
3640
 
            c = _mod_config.GlobalConfig()
3641
 
        c.set_user_option('email', name)
 
3897
            c = _mod_config.GlobalStack()
 
3898
        c.set('email', name)
3642
3899
 
3643
3900
 
3644
3901
class cmd_nick(Command):
3645
3902
    __doc__ = """Print or set the branch nickname.
3646
3903
 
3647
 
    If unset, the tree root directory name is used as the nickname.
3648
 
    To print the current nickname, execute with no argument.
 
3904
    If unset, the colocated branch name is used for colocated branches, and
 
3905
    the branch directory name is used for other branches.  To print the
 
3906
    current nickname, execute with no argument.
3649
3907
 
3650
3908
    Bound branches use the nickname of its master branch unless it is set
3651
3909
    locally.
3869
4127
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3870
4128
            parallel=None, lsprof_tests=False,
3871
4129
            sync=False):
 
4130
 
 
4131
        # During selftest, disallow proxying, as it can cause severe
 
4132
        # performance penalties and is only needed for thread
 
4133
        # safety. The selftest command is assumed to not use threads
 
4134
        # too heavily. The call should be as early as possible, as
 
4135
        # error reporting for past duplicate imports won't have useful
 
4136
        # backtraces.
 
4137
        lazy_import.disallow_proxying()
 
4138
 
3872
4139
        from bzrlib import tests
3873
4140
 
3874
4141
        if testspecs_list is not None:
4024
4291
    Merge will do its best to combine the changes in two branches, but there
4025
4292
    are some kinds of problems only a human can fix.  When it encounters those,
4026
4293
    it will mark a conflict.  A conflict means that you need to fix something,
4027
 
    before you should commit.
 
4294
    before you can commit.
4028
4295
 
4029
4296
    Use bzr resolve when you have fixed a problem.  See also bzr conflicts.
4030
4297
 
4438
4705
                if tree.kind(file_id) != "directory":
4439
4706
                    continue
4440
4707
 
4441
 
                for name, ie in tree.inventory.iter_entries(file_id):
 
4708
                # FIXME: Support nested trees
 
4709
                for name, ie in tree.root_inventory.iter_entries(file_id):
4442
4710
                    interesting_ids.add(ie.file_id)
4443
4711
            new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4444
4712
        else:
4477
4745
 
4478
4746
 
4479
4747
class cmd_revert(Command):
4480
 
    __doc__ = """Revert files to a previous revision.
 
4748
    __doc__ = """\
 
4749
    Set files in the working tree back to the contents of a previous revision.
4481
4750
 
4482
4751
    Giving a list of files will revert only those files.  Otherwise, all files
4483
4752
    will be reverted.  If the revision is not specified with '--revision', the
4484
 
    last committed revision is used.
 
4753
    working tree basis revision is used. A revert operation affects only the
 
4754
    working tree, not any revision history like the branch and repository or
 
4755
    the working tree basis revision.
4485
4756
 
4486
4757
    To remove only some changes, without reverting to a prior version, use
4487
4758
    merge instead.  For example, "merge . -r -2..-3" (don't forget the ".")
4488
4759
    will remove the changes introduced by the second last commit (-2), without
4489
4760
    affecting the changes introduced by the last commit (-1).  To remove
4490
4761
    certain changes on a hunk-by-hunk basis, see the shelve command.
 
4762
    To update the branch to a specific revision or the latest revision and
 
4763
    update the working tree accordingly while preserving local changes, see the
 
4764
    update command.
4491
4765
 
4492
 
    By default, any files that have been manually changed will be backed up
4493
 
    first.  (Files changed only by merge are not backed up.)  Backup files have
4494
 
    '.~#~' appended to their name, where # is a number.
 
4766
    Uncommitted changes to files that are reverted will be discarded.
 
4767
    Howver, by default, any files that have been manually changed will be
 
4768
    backed up first.  (Files changed only by merge are not backed up.)  Backup
 
4769
    files have '.~#~' appended to their name, where # is a number.
4495
4770
 
4496
4771
    When you provide files, you can use their current pathname or the pathname
4497
4772
    from the target revision.  So you can use revert to "undelete" a file by
4588
4863
 
4589
4864
    @display_command
4590
4865
    def run(self, context=None):
4591
 
        import shellcomplete
 
4866
        from bzrlib import shellcomplete
4592
4867
        shellcomplete.shellcomplete(context)
4593
4868
 
4594
4869
 
4744
5019
                             "You have %d extra revisions:\n", 
4745
5020
                             len(local_extra)) %
4746
5021
                len(local_extra))
 
5022
            rev_tag_dict = {}
 
5023
            if local_branch.supports_tags():
 
5024
                rev_tag_dict = local_branch.tags.get_reverse_tag_dict()
4747
5025
            for revision in iter_log_revisions(local_extra,
4748
5026
                                local_branch.repository,
4749
 
                                verbose):
 
5027
                                verbose,
 
5028
                                rev_tag_dict):
4750
5029
                lf.log_revision(revision)
4751
5030
            printed_local = True
4752
5031
            status_code = 1
4760
5039
                             "You are missing %d revisions:\n",
4761
5040
                             len(remote_extra)) %
4762
5041
                len(remote_extra))
 
5042
            if remote_branch.supports_tags():
 
5043
                rev_tag_dict = remote_branch.tags.get_reverse_tag_dict()
4763
5044
            for revision in iter_log_revisions(remote_extra,
4764
5045
                                remote_branch.repository,
4765
 
                                verbose):
 
5046
                                verbose,
 
5047
                                rev_tag_dict):
4766
5048
                lf.log_revision(revision)
4767
5049
            status_code = 1
4768
5050
 
4812
5094
        ]
4813
5095
 
4814
5096
    def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4815
 
        dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
 
5097
        dir = controldir.ControlDir.open_containing(branch_or_repo)[0]
4816
5098
        try:
4817
5099
            branch = dir.open_branch()
4818
5100
            repository = branch.repository
4858
5140
            Option('strict',
4859
5141
                   help='Produce a strict-format testament.')]
4860
5142
    takes_args = ['branch?']
 
5143
    encoding_type = 'exact'
4861
5144
    @display_command
4862
5145
    def run(self, branch=u'.', revision=None, long=False, strict=False):
4863
5146
        from bzrlib.testament import Testament, StrictTestament
4876
5159
            rev_id = revision[0].as_revision_id(b)
4877
5160
        t = testament_class.from_revision(b.repository, rev_id)
4878
5161
        if long:
4879
 
            sys.stdout.writelines(t.as_text_lines())
 
5162
            self.outf.writelines(t.as_text_lines())
4880
5163
        else:
4881
 
            sys.stdout.write(t.as_short_text())
 
5164
            self.outf.write(t.as_short_text())
4882
5165
 
4883
5166
 
4884
5167
class cmd_annotate(Command):
4952
5235
 
4953
5236
    def _run(self, b, revision_id_list, revision):
4954
5237
        import bzrlib.gpg as gpg
4955
 
        gpg_strategy = gpg.GPGStrategy(b.get_config())
 
5238
        gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
4956
5239
        if revision_id_list is not None:
4957
5240
            b.repository.start_write_group()
4958
5241
            try:
5025
5308
            else:
5026
5309
                if location is None:
5027
5310
                    if b.get_bound_location() is not None:
5028
 
                        raise errors.BzrCommandError(gettext('Branch is already bound'))
 
5311
                        raise errors.BzrCommandError(
 
5312
                            gettext('Branch is already bound'))
5029
5313
                    else:
5030
 
                        raise errors.BzrCommandError(gettext('No location supplied '
5031
 
                            'and no previous location known'))
 
5314
                        raise errors.BzrCommandError(
 
5315
                            gettext('No location supplied'
 
5316
                                    ' and no previous location known'))
5032
5317
        b_other = Branch.open(location)
5033
5318
        try:
5034
5319
            b.bind(b_other)
5095
5380
            revision=None, force=False, local=False, keep_tags=False):
5096
5381
        if location is None:
5097
5382
            location = u'.'
5098
 
        control, relpath = bzrdir.BzrDir.open_containing(location)
 
5383
        control, relpath = controldir.ControlDir.open_containing(location)
5099
5384
        try:
5100
5385
            tree = control.open_workingtree()
5101
5386
            b = tree.branch
5205
5490
            conf = _mod_config.LockableConfig(file_name=location)
5206
5491
            conf.break_lock()
5207
5492
        else:
5208
 
            control, relpath = bzrdir.BzrDir.open_containing(location)
 
5493
            control, relpath = controldir.ControlDir.open_containing(location)
5209
5494
            try:
5210
5495
                control.break_lock()
5211
5496
            except NotImplementedError:
5238
5523
               help="Protocol to serve.",
5239
5524
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5240
5525
               value_switches=True),
 
5526
        Option('listen',
 
5527
               help='Listen for connections on nominated address.', type=str),
5241
5528
        Option('port',
5242
 
               help='Listen for connections on nominated port of the form '
5243
 
                    '[hostname:]portnumber.  Passing 0 as the port number will '
5244
 
                    'result in a dynamically allocated port.  The default port '
5245
 
                    'depends on the protocol.',
5246
 
               type=str),
 
5529
               help='Listen for connections on nominated port.  Passing 0 as '
 
5530
                    'the port number will result in a dynamically allocated '
 
5531
                    'port.  The default port depends on the protocol.',
 
5532
               type=int),
5247
5533
        custom_help('directory',
5248
5534
               help='Serve contents of this directory.'),
5249
5535
        Option('allow-writes',
5259
5545
               help='Override the default idle client timeout (5min).'),
5260
5546
        ]
5261
5547
 
5262
 
    def get_host_and_port(self, port):
5263
 
        """Return the host and port to run the smart server on.
5264
 
 
5265
 
        If 'port' is None, None will be returned for the host and port.
5266
 
 
5267
 
        If 'port' has a colon in it, the string before the colon will be
5268
 
        interpreted as the host.
5269
 
 
5270
 
        :param port: A string of the port to run the server on.
5271
 
        :return: A tuple of (host, port), where 'host' is a host name or IP,
5272
 
            and port is an integer TCP/IP port.
5273
 
        """
5274
 
        host = None
5275
 
        if port is not None:
5276
 
            if ':' in port:
5277
 
                host, port = port.split(':')
5278
 
            port = int(port)
5279
 
        return host, port
5280
 
 
5281
 
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
5282
 
            protocol=None, client_timeout=None):
 
5548
    def run(self, listen=None, port=None, inet=False, directory=None,
 
5549
            allow_writes=False, protocol=None, client_timeout=None):
5283
5550
        from bzrlib import transport
5284
5551
        if directory is None:
5285
5552
            directory = os.getcwd()
5286
5553
        if protocol is None:
5287
5554
            protocol = transport.transport_server_registry.get()
5288
 
        host, port = self.get_host_and_port(port)
5289
 
        url = urlutils.local_path_to_url(directory)
 
5555
        url = transport.location_to_url(directory)
5290
5556
        if not allow_writes:
5291
5557
            url = 'readonly+' + url
5292
 
        t = transport.get_transport(url)
5293
 
        try:
5294
 
            protocol(t, host, port, inet, client_timeout)
5295
 
        except TypeError, e:
5296
 
            # We use symbol_versioning.deprecated_in just so that people
5297
 
            # grepping can find it here.
5298
 
            # symbol_versioning.deprecated_in((2, 5, 0))
5299
 
            symbol_versioning.warn(
5300
 
                'Got TypeError(%s)\ntrying to call protocol: %s.%s\n'
5301
 
                'Most likely it needs to be updated to support a'
5302
 
                ' "timeout" parameter (added in bzr 2.5.0)'
5303
 
                % (e, protocol.__module__, protocol),
5304
 
                DeprecationWarning)
5305
 
            protocol(t, host, port, inet)
 
5558
        t = transport.get_transport_from_url(url)
 
5559
        protocol(t, listen, port, inet, client_timeout)
5306
5560
 
5307
5561
 
5308
5562
class cmd_join(Command):
5444
5698
        if public_branch is None:
5445
5699
            public_branch = stored_public_branch
5446
5700
        elif stored_public_branch is None:
 
5701
            # FIXME: Should be done only if we succeed ? -- vila 2012-01-03
5447
5702
            branch.set_public_branch(public_branch)
5448
5703
        if not include_bundle and public_branch is None:
5449
5704
            raise errors.BzrCommandError(gettext('No public branch specified or'
5474
5729
                self.outf.writelines(directive.to_lines())
5475
5730
        else:
5476
5731
            message = directive.to_email(mail_to, branch, sign)
5477
 
            s = SMTPConnection(branch.get_config())
 
5732
            s = SMTPConnection(branch.get_config_stack())
5478
5733
            s.send_email(message)
5479
5734
 
5480
5735
 
5795
6050
                    if isinstance(revno, tuple):
5796
6051
                        revno = '.'.join(map(str, revno))
5797
6052
                except (errors.NoSuchRevision,
5798
 
                        errors.GhostRevisionsHaveNoRevno):
 
6053
                        errors.GhostRevisionsHaveNoRevno,
 
6054
                        errors.UnsupportedOperation):
5799
6055
                    # Bad tag data/merges can lead to tagged revisions
5800
6056
                    # which are not in this branch. Fail gracefully ...
5801
6057
                    revno = '?'
5895
6151
    def run(self, location=None, bind_to=None, force=False,
5896
6152
            tree_type=None, repository_type=None, repository_trees=None,
5897
6153
            stacked_on=None, unstacked=None):
5898
 
        directory = bzrdir.BzrDir.open(location)
 
6154
        directory = controldir.ControlDir.open(location)
5899
6155
        if stacked_on and unstacked:
5900
6156
            raise errors.BzrCommandError(gettext("Can't use both --stacked-on and --unstacked"))
5901
6157
        elif stacked_on is not None:
5976
6232
                     Option('create-branch', short_name='b',
5977
6233
                        help='Create the target branch from this one before'
5978
6234
                             ' switching to it.'),
 
6235
                     Option('store',
 
6236
                        help='Store and restore uncommitted changes in the'
 
6237
                             ' branch.'),
5979
6238
                    ]
5980
6239
 
5981
6240
    def run(self, to_location=None, force=False, create_branch=False,
5982
 
            revision=None, directory=u'.'):
 
6241
            revision=None, directory=u'.', store=False):
5983
6242
        from bzrlib import switch
5984
6243
        tree_location = directory
5985
6244
        revision = _get_one_revision('switch', revision)
5986
 
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
 
6245
        possible_transports = []
 
6246
        control_dir = controldir.ControlDir.open_containing(tree_location,
 
6247
            possible_transports=possible_transports)[0]
5987
6248
        if to_location is None:
5988
6249
            if revision is None:
5989
6250
                raise errors.BzrCommandError(gettext('You must supply either a'
5990
6251
                                             ' revision or a location'))
5991
6252
            to_location = tree_location
5992
6253
        try:
5993
 
            branch = control_dir.open_branch()
 
6254
            branch = control_dir.open_branch(
 
6255
                possible_transports=possible_transports)
5994
6256
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5995
6257
        except errors.NotBranchError:
5996
6258
            branch = None
5997
6259
            had_explicit_nick = False
5998
6260
        if create_branch:
5999
6261
            if branch is None:
6000
 
                raise errors.BzrCommandError(gettext('cannot create branch without'
6001
 
                                             ' source branch'))
6002
 
            to_location = directory_service.directories.dereference(
6003
 
                              to_location)
6004
 
            if '/' not in to_location and '\\' not in to_location:
6005
 
                # This path is meant to be relative to the existing branch
6006
 
                this_url = self._get_branch_location(control_dir)
6007
 
                to_location = urlutils.join(this_url, '..', to_location)
 
6262
                raise errors.BzrCommandError(
 
6263
                    gettext('cannot create branch without source branch'))
 
6264
            to_location = lookup_new_sibling_branch(control_dir, to_location,
 
6265
                 possible_transports=possible_transports)
6008
6266
            to_branch = branch.bzrdir.sprout(to_location,
6009
 
                                 possible_transports=[branch.bzrdir.root_transport],
6010
 
                                 source_branch=branch).open_branch()
 
6267
                 possible_transports=possible_transports,
 
6268
                 source_branch=branch).open_branch()
6011
6269
        else:
6012
6270
            try:
6013
 
                to_branch = Branch.open(to_location)
 
6271
                to_branch = Branch.open(to_location,
 
6272
                    possible_transports=possible_transports)
6014
6273
            except errors.NotBranchError:
6015
 
                this_url = self._get_branch_location(control_dir)
6016
 
                to_branch = Branch.open(
6017
 
                    urlutils.join(this_url, '..', to_location))
 
6274
                to_branch = open_sibling_branch(control_dir, to_location,
 
6275
                    possible_transports=possible_transports)
6018
6276
        if revision is not None:
6019
6277
            revision = revision.as_revision_id(to_branch)
6020
 
        switch.switch(control_dir, to_branch, force, revision_id=revision)
 
6278
        switch.switch(control_dir, to_branch, force, revision_id=revision,
 
6279
                      store_uncommitted=store)
6021
6280
        if had_explicit_nick:
6022
6281
            branch = control_dir.open_branch() #get the new branch!
6023
6282
            branch.nick = to_branch.nick
6024
6283
        note(gettext('Switched to branch: %s'),
6025
6284
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6026
6285
 
6027
 
    def _get_branch_location(self, control_dir):
6028
 
        """Return location of branch for this control dir."""
6029
 
        try:
6030
 
            this_branch = control_dir.open_branch()
6031
 
            # This may be a heavy checkout, where we want the master branch
6032
 
            master_location = this_branch.get_bound_location()
6033
 
            if master_location is not None:
6034
 
                return master_location
6035
 
            # If not, use a local sibling
6036
 
            return this_branch.base
6037
 
        except errors.NotBranchError:
6038
 
            format = control_dir.find_branch_format()
6039
 
            if getattr(format, 'get_reference', None) is not None:
6040
 
                return format.get_reference(control_dir)
6041
 
            else:
6042
 
                return control_dir.root_transport.base
6043
6286
 
6044
6287
 
6045
6288
class cmd_view(Command):
6233
6476
 
6234
6477
    takes_args = ["location?"]
6235
6478
 
 
6479
    takes_options = ['directory',
 
6480
        Option('force', help='Remove branch even if it is the active branch.')]
 
6481
 
6236
6482
    aliases = ["rmbranch"]
6237
6483
 
6238
 
    def run(self, location=None):
6239
 
        if location is None:
6240
 
            location = "."
6241
 
        branch = Branch.open_containing(location)[0]
6242
 
        branch.bzrdir.destroy_branch()
 
6484
    def run(self, directory=None, location=None, force=False):
 
6485
        br = open_nearby_branch(near=directory, location=location)
 
6486
        if not force and br.bzrdir.has_workingtree():
 
6487
            try:
 
6488
                active_branch = br.bzrdir.open_branch(name="")
 
6489
            except errors.NotBranchError:
 
6490
                active_branch = None
 
6491
            if (active_branch is not None and
 
6492
                br.control_url == active_branch.control_url):
 
6493
                raise errors.BzrCommandError(
 
6494
                    gettext("Branch is active. Use --force to remove it."))
 
6495
        br.bzrdir.destroy_branch(br.name)
6243
6496
 
6244
6497
 
6245
6498
class cmd_shelve(Command):
6416
6669
        if path is not None:
6417
6670
            branchdir = path
6418
6671
        tree, branch, relpath =(
6419
 
            bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
 
6672
            controldir.ControlDir.open_containing_tree_or_branch(branchdir))
6420
6673
        if path is not None:
6421
6674
            path = relpath
6422
6675
        if tree is None:
6450
6703
    __doc__ = """Export command helps and error messages in po format."""
6451
6704
 
6452
6705
    hidden = True
 
6706
    takes_options = [Option('plugin', 
 
6707
                            help='Export help text from named command '\
 
6708
                                 '(defaults to all built in commands).',
 
6709
                            type=str),
 
6710
                     Option('include-duplicates',
 
6711
                            help='Output multiple copies of the same msgid '
 
6712
                                 'string if it appears more than once.'),
 
6713
                            ]
6453
6714
 
6454
 
    def run(self):
 
6715
    def run(self, plugin=None, include_duplicates=False):
6455
6716
        from bzrlib.export_pot import export_pot
6456
 
        export_pot(self.outf)
 
6717
        export_pot(self.outf, plugin, include_duplicates)
6457
6718
 
6458
6719
 
6459
6720
def _register_lazy_builtins():
6466
6727
        ('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6467
6728
        ('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6468
6729
        ('cmd_conflicts', [], 'bzrlib.conflicts'),
 
6730
        ('cmd_ping', [], 'bzrlib.smart.ping'),
6469
6731
        ('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6470
 
        ('cmd_verify_signatures', [],
6471
 
                                        'bzrlib.commit_signature_commands'),
 
6732
        ('cmd_verify_signatures', [], 'bzrlib.commit_signature_commands'),
6472
6733
        ('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6473
6734
        ]:
6474
6735
        builtin_command_registry.register_lazy(name, aliases, module_name)