~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Vincent Ladeuil
  • Date: 2010-12-07 10:16:53 UTC
  • mto: (5575.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 5576.
  • Revision ID: v.ladeuil+lp@free.fr-20101207101653-20iiufih26buvmy3
Use assertLength as it provides a better ouput to debug tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2012 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""builtin bzr commands"""
18
18
 
19
 
from __future__ import absolute_import
20
 
 
21
19
import os
22
20
 
23
 
import bzrlib.bzrdir
24
 
 
25
 
from bzrlib import lazy_import
26
 
lazy_import.lazy_import(globals(), """
 
21
from bzrlib.lazy_import import lazy_import
 
22
lazy_import(globals(), """
27
23
import cStringIO
28
 
import errno
 
24
import itertools
 
25
import re
29
26
import sys
30
27
import time
31
28
 
34
31
    bugtracker,
35
32
    bundle,
36
33
    btree_index,
37
 
    controldir,
 
34
    bzrdir,
38
35
    directory_service,
39
36
    delta,
40
37
    config as _mod_config,
49
46
    rename_map,
50
47
    revision as _mod_revision,
51
48
    static_tuple,
 
49
    symbol_versioning,
52
50
    timestamp,
53
51
    transport,
54
52
    ui,
55
53
    urlutils,
56
54
    views,
57
 
    gpg,
58
55
    )
59
56
from bzrlib.branch import Branch
60
57
from bzrlib.conflicts import ConflictList
62
59
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
63
60
from bzrlib.smtp_connection import SMTPConnection
64
61
from bzrlib.workingtree import WorkingTree
65
 
from bzrlib.i18n import gettext, ngettext
66
62
""")
67
63
 
68
64
from bzrlib.commands import (
78
74
    _parse_revision_str,
79
75
    )
80
76
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
81
 
from bzrlib import (
82
 
    symbol_versioning,
83
 
    )
84
 
 
85
 
 
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
 
77
 
 
78
 
 
79
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
 
80
def tree_files(file_list, default_branch=u'.', canonicalize=True,
 
81
    apply_view=True):
 
82
    return internal_tree_files(file_list, default_branch, canonicalize,
 
83
        apply_view)
221
84
 
222
85
 
223
86
def tree_files_for_add(file_list):
248
111
            if view_files:
249
112
                file_list = view_files
250
113
                view_str = views.view_display_str(view_files)
251
 
                note(gettext("Ignoring files outside view. View is %s") % view_str)
 
114
                note("Ignoring files outside view. View is %s" % view_str)
252
115
    return tree, file_list
253
116
 
254
117
 
256
119
    if revisions is None:
257
120
        return None
258
121
    if len(revisions) != 1:
259
 
        raise errors.BzrCommandError(gettext(
260
 
            'bzr %s --revision takes exactly one revision identifier') % (
 
122
        raise errors.BzrCommandError(
 
123
            'bzr %s --revision takes exactly one revision identifier' % (
261
124
                command_name,))
262
125
    return revisions[0]
263
126
 
285
148
    return rev_tree
286
149
 
287
150
 
 
151
# XXX: Bad function name; should possibly also be a class method of
 
152
# WorkingTree rather than a function.
 
153
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
 
154
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
 
155
    apply_view=True):
 
156
    """Convert command-line paths to a WorkingTree and relative paths.
 
157
 
 
158
    Deprecated: use WorkingTree.open_containing_paths instead.
 
159
 
 
160
    This is typically used for command-line processors that take one or
 
161
    more filenames, and infer the workingtree that contains them.
 
162
 
 
163
    The filenames given are not required to exist.
 
164
 
 
165
    :param file_list: Filenames to convert.
 
166
 
 
167
    :param default_branch: Fallback tree path to use if file_list is empty or
 
168
        None.
 
169
 
 
170
    :param apply_view: if True and a view is set, apply it or check that
 
171
        specified files are within it
 
172
 
 
173
    :return: workingtree, [relative_paths]
 
174
    """
 
175
    return WorkingTree.open_containing_paths(
 
176
        file_list, default_directory='.',
 
177
        canonicalize=True,
 
178
        apply_view=True)
 
179
 
 
180
 
288
181
def _get_view_info_for_change_reporter(tree):
289
182
    """Get the view information from a tree for change reporting."""
290
183
    view_info = None
302
195
    the --directory option is used to specify a different branch."""
303
196
    if directory is not None:
304
197
        return (None, Branch.open(directory), filename)
305
 
    return controldir.ControlDir.open_containing_tree_or_branch(filename)
 
198
    return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
306
199
 
307
200
 
308
201
# TODO: Make sure no commands unconditionally use the working directory as a
338
231
    unknown
339
232
        Not versioned and not matching an ignore pattern.
340
233
 
341
 
    Additionally for directories, symlinks and files with a changed
342
 
    executable bit, Bazaar indicates their type using a trailing
343
 
    character: '/', '@' or '*' respectively. These decorations can be
344
 
    disabled using the '--no-classify' option.
 
234
    Additionally for directories, symlinks and files with an executable
 
235
    bit, Bazaar indicates their type using a trailing character: '/', '@'
 
236
    or '*' respectively.
345
237
 
346
238
    To see ignored files use 'bzr ignored'.  For details on the
347
239
    changes to file texts, use 'bzr diff'.
368
260
    This will produce the same results as calling 'bzr diff --summarize'.
369
261
    """
370
262
 
371
 
    # TODO: --no-recurse/-N, --recurse options
 
263
    # TODO: --no-recurse, --recurse options
372
264
 
373
265
    takes_args = ['file*']
374
266
    takes_options = ['show-ids', 'revision', 'change', 'verbose',
378
270
                            short_name='V'),
379
271
                     Option('no-pending', help='Don\'t show pending merges.',
380
272
                           ),
381
 
                     Option('no-classify',
382
 
                            help='Do not mark object type using indicator.',
383
 
                           ),
384
273
                     ]
385
274
    aliases = ['st', 'stat']
386
275
 
389
278
 
390
279
    @display_command
391
280
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
392
 
            versioned=False, no_pending=False, verbose=False,
393
 
            no_classify=False):
 
281
            versioned=False, no_pending=False, verbose=False):
394
282
        from bzrlib.status import show_tree_status
395
283
 
396
284
        if revision and len(revision) > 2:
397
 
            raise errors.BzrCommandError(gettext('bzr status --revision takes exactly'
398
 
                                         ' one or two revision specifiers'))
 
285
            raise errors.BzrCommandError('bzr status --revision takes exactly'
 
286
                                         ' one or two revision specifiers')
399
287
 
400
288
        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
401
289
        # Avoid asking for specific files when that is not needed.
410
298
        show_tree_status(tree, show_ids=show_ids,
411
299
                         specific_files=relfile_list, revision=revision,
412
300
                         to_file=self.outf, short=short, versioned=versioned,
413
 
                         show_pending=(not no_pending), verbose=verbose,
414
 
                         classify=not no_classify)
 
301
                         show_pending=(not no_pending), verbose=verbose)
415
302
 
416
303
 
417
304
class cmd_cat_revision(Command):
438
325
    @display_command
439
326
    def run(self, revision_id=None, revision=None, directory=u'.'):
440
327
        if revision_id is not None and revision is not None:
441
 
            raise errors.BzrCommandError(gettext('You can only supply one of'
442
 
                                         ' revision_id or --revision'))
 
328
            raise errors.BzrCommandError('You can only supply one of'
 
329
                                         ' revision_id or --revision')
443
330
        if revision_id is None and revision is None:
444
 
            raise errors.BzrCommandError(gettext('You must supply either'
445
 
                                         ' --revision or a revision_id'))
446
 
 
447
 
        b = controldir.ControlDir.open_containing_tree_or_branch(directory)[1]
 
331
            raise errors.BzrCommandError('You must supply either'
 
332
                                         ' --revision or a revision_id')
 
333
        b = WorkingTree.open_containing(directory)[0].branch
448
334
 
449
335
        revisions = b.repository.revisions
450
336
        if revisions is None:
451
 
            raise errors.BzrCommandError(gettext('Repository %r does not support '
452
 
                'access to raw revision texts'))
 
337
            raise errors.BzrCommandError('Repository %r does not support '
 
338
                'access to raw revision texts')
453
339
 
454
340
        b.repository.lock_read()
455
341
        try:
459
345
                try:
460
346
                    self.print_revision(revisions, revision_id)
461
347
                except errors.NoSuchRevision:
462
 
                    msg = gettext("The repository {0} contains no revision {1}.").format(
 
348
                    msg = "The repository %s contains no revision %s." % (
463
349
                        b.repository.base, revision_id)
464
350
                    raise errors.BzrCommandError(msg)
465
351
            elif revision is not None:
466
352
                for rev in revision:
467
353
                    if rev is None:
468
354
                        raise errors.BzrCommandError(
469
 
                            gettext('You cannot specify a NULL revision.'))
 
355
                            'You cannot specify a NULL revision.')
470
356
                    rev_id = rev.as_revision_id(b)
471
357
                    self.print_revision(revisions, rev_id)
472
358
        finally:
528
414
                self.outf.write(page_bytes[:header_end])
529
415
                page_bytes = data
530
416
            self.outf.write('\nPage %d\n' % (page_idx,))
531
 
            if len(page_bytes) == 0:
532
 
                self.outf.write('(empty)\n');
533
 
            else:
534
 
                decomp_bytes = zlib.decompress(page_bytes)
535
 
                self.outf.write(decomp_bytes)
536
 
                self.outf.write('\n')
 
417
            decomp_bytes = zlib.decompress(page_bytes)
 
418
            self.outf.write(decomp_bytes)
 
419
            self.outf.write('\n')
537
420
 
538
421
    def _dump_entries(self, trans, basename):
539
422
        try:
578
461
            location_list=['.']
579
462
 
580
463
        for location in location_list:
581
 
            d = controldir.ControlDir.open(location)
582
 
 
 
464
            d = bzrdir.BzrDir.open(location)
 
465
            
583
466
            try:
584
467
                working = d.open_workingtree()
585
468
            except errors.NoWorkingTree:
586
 
                raise errors.BzrCommandError(gettext("No working tree to remove"))
 
469
                raise errors.BzrCommandError("No working tree to remove")
587
470
            except errors.NotLocalUrl:
588
 
                raise errors.BzrCommandError(gettext("You cannot remove the working tree"
589
 
                                             " of a remote path"))
 
471
                raise errors.BzrCommandError("You cannot remove the working tree"
 
472
                                             " of a remote path")
590
473
            if not force:
591
474
                if (working.has_changes()):
592
475
                    raise errors.UncommittedChanges(working)
594
477
                    raise errors.ShelvedChanges(working)
595
478
 
596
479
            if working.user_url != working.branch.user_url:
597
 
                raise errors.BzrCommandError(gettext("You cannot remove the working tree"
598
 
                                             " from a lightweight checkout"))
 
480
                raise errors.BzrCommandError("You cannot remove the working tree"
 
481
                                             " from a lightweight checkout")
599
482
 
600
483
            d.destroy_workingtree()
601
484
 
602
485
 
603
 
class cmd_repair_workingtree(Command):
604
 
    __doc__ = """Reset the working tree state file.
605
 
 
606
 
    This is not meant to be used normally, but more as a way to recover from
607
 
    filesystem corruption, etc. This rebuilds the working inventory back to a
608
 
    'known good' state. Any new modifications (adding a file, renaming, etc)
609
 
    will be lost, though modified files will still be detected as such.
610
 
 
611
 
    Most users will want something more like "bzr revert" or "bzr update"
612
 
    unless the state file has become corrupted.
613
 
 
614
 
    By default this attempts to recover the current state by looking at the
615
 
    headers of the state file. If the state file is too corrupted to even do
616
 
    that, you can supply --revision to force the state of the tree.
617
 
    """
618
 
 
619
 
    takes_options = ['revision', 'directory',
620
 
        Option('force',
621
 
               help='Reset the tree even if it doesn\'t appear to be'
622
 
                    ' corrupted.'),
623
 
    ]
624
 
    hidden = True
625
 
 
626
 
    def run(self, revision=None, directory='.', force=False):
627
 
        tree, _ = WorkingTree.open_containing(directory)
628
 
        self.add_cleanup(tree.lock_tree_write().unlock)
629
 
        if not force:
630
 
            try:
631
 
                tree.check_state()
632
 
            except errors.BzrError:
633
 
                pass # There seems to be a real error here, so we'll reset
634
 
            else:
635
 
                # Refuse
636
 
                raise errors.BzrCommandError(gettext(
637
 
                    'The tree does not appear to be corrupt. You probably'
638
 
                    ' want "bzr revert" instead. Use "--force" if you are'
639
 
                    ' sure you want to reset the working tree.'))
640
 
        if revision is None:
641
 
            revision_ids = None
642
 
        else:
643
 
            revision_ids = [r.as_revision_id(tree.branch) for r in revision]
644
 
        try:
645
 
            tree.reset_state(revision_ids)
646
 
        except errors.BzrError, e:
647
 
            if revision_ids is None:
648
 
                extra = (gettext(', the header appears corrupt, try passing -r -1'
649
 
                         ' to set the state to the last commit'))
650
 
            else:
651
 
                extra = ''
652
 
            raise errors.BzrCommandError(gettext('failed to reset the tree state{0}').format(extra))
653
 
 
654
 
 
655
486
class cmd_revno(Command):
656
487
    __doc__ = """Show current revision number.
657
488
 
661
492
    _see_also = ['info']
662
493
    takes_args = ['location?']
663
494
    takes_options = [
664
 
        Option('tree', help='Show revno of working tree.'),
665
 
        'revision',
 
495
        Option('tree', help='Show revno of working tree'),
666
496
        ]
667
497
 
668
498
    @display_command
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
 
 
 
499
    def run(self, tree=False, location=u'.'):
674
500
        if tree:
675
501
            try:
676
502
                wt = WorkingTree.open_containing(location)[0]
677
503
                self.add_cleanup(wt.lock_read().unlock)
678
504
            except (errors.NoWorkingTree, errors.NotLocalUrl):
679
505
                raise errors.NoWorkingTree(location)
680
 
            b = wt.branch
681
506
            revid = wt.last_revision()
 
507
            try:
 
508
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
 
509
            except errors.NoSuchRevision:
 
510
                revno_t = ('???',)
 
511
            revno = ".".join(str(n) for n in revno_t)
682
512
        else:
683
513
            b = Branch.open_containing(location)[0]
684
514
            self.add_cleanup(b.lock_read().unlock)
685
 
            if revision:
686
 
                if len(revision) != 1:
687
 
                    raise errors.BzrCommandError(gettext(
688
 
                        "Tags can only be placed on a single revision, "
689
 
                        "not on a range"))
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)
 
515
            revno = b.revno()
698
516
        self.cleanup_now()
699
 
        self.outf.write(revno + '\n')
 
517
        self.outf.write(str(revno) + '\n')
700
518
 
701
519
 
702
520
class cmd_revision_info(Command):
709
527
        custom_help('directory',
710
528
            help='Branch to examine, '
711
529
                 'rather than the one containing the working directory.'),
712
 
        Option('tree', help='Show revno of working tree.'),
 
530
        Option('tree', help='Show revno of working tree'),
713
531
        ]
714
532
 
715
533
    @display_command
771
589
    are added.  This search proceeds recursively into versioned
772
590
    directories.  If no names are given '.' is assumed.
773
591
 
774
 
    A warning will be printed when nested trees are encountered,
775
 
    unless they are explicitly ignored.
776
 
 
777
592
    Therefore simply saying 'bzr add' will version all files that
778
593
    are currently unknown.
779
594
 
795
610
    
796
611
    Any files matching patterns in the ignore list will not be added
797
612
    unless they are explicitly mentioned.
798
 
    
799
 
    In recursive mode, files larger than the configuration option 
800
 
    add.maximum_file_size will be skipped. Named items are never skipped due
801
 
    to file size.
802
613
    """
803
614
    takes_args = ['file*']
804
615
    takes_options = [
805
616
        Option('no-recurse',
806
 
               help="Don't recursively add the contents of directories.",
807
 
               short_name='N'),
 
617
               help="Don't recursively add the contents of directories."),
808
618
        Option('dry-run',
809
619
               help="Show what would be done, but don't actually do anything."),
810
620
        'verbose',
832
642
            action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
833
643
                          to_file=self.outf, should_print=(not is_quiet()))
834
644
        else:
835
 
            action = bzrlib.add.AddWithSkipLargeAction(to_file=self.outf,
 
645
            action = bzrlib.add.AddAction(to_file=self.outf,
836
646
                should_print=(not is_quiet()))
837
647
 
838
648
        if base_tree:
845
655
            if verbose:
846
656
                for glob in sorted(ignored.keys()):
847
657
                    for path in ignored[glob]:
848
 
                        self.outf.write(
849
 
                         gettext("ignored {0} matching \"{1}\"\n").format(
850
 
                         path, glob))
 
658
                        self.outf.write("ignored %s matching \"%s\"\n"
 
659
                                        % (path, glob))
851
660
 
852
661
 
853
662
class cmd_mkdir(Command):
857
666
    """
858
667
 
859
668
    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
 
        ]
867
669
    encoding_type = 'replace'
868
670
 
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
 
671
    def run(self, dir_list):
 
672
        for d in dir_list:
 
673
            wt, dd = WorkingTree.open_containing(d)
 
674
            base = os.path.dirname(dd)
 
675
            id = wt.path2id(base)
 
676
            if id != None:
 
677
                os.mkdir(d)
 
678
                wt.add([dd])
 
679
                self.outf.write('added %s\n' % d)
893
680
            else:
894
 
                os.mkdir(dir)
895
 
            add_file(wt, relpath)
896
 
            if not is_quiet():
897
 
                self.outf.write(gettext('added %s\n') % dir)
 
681
                raise errors.NotVersionedError(path=base)
898
682
 
899
683
 
900
684
class cmd_relpath(Command):
936
720
    @display_command
937
721
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
938
722
        if kind and kind not in ['file', 'directory', 'symlink']:
939
 
            raise errors.BzrCommandError(gettext('invalid kind %r specified') % (kind,))
 
723
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
940
724
 
941
725
        revision = _get_one_revision('inventory', revision)
942
726
        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
950
734
            tree = work_tree
951
735
            extra_trees = []
952
736
 
953
 
        self.add_cleanup(tree.lock_read().unlock)
954
737
        if file_list is not None:
955
738
            file_ids = tree.paths2ids(file_list, trees=extra_trees,
956
739
                                      require_versioned=True)
957
740
            # find_ids_across_trees may include some paths that don't
958
741
            # exist in 'tree'.
959
 
            entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
 
742
            entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
 
743
                             for file_id in file_ids if file_id in tree)
960
744
        else:
961
 
            entries = tree.iter_entries_by_dir()
 
745
            entries = tree.inventory.entries()
962
746
 
963
 
        for path, entry in sorted(entries):
 
747
        self.cleanup_now()
 
748
        for path, entry in entries:
964
749
            if kind and kind != entry.kind:
965
750
                continue
966
 
            if path == "":
967
 
                continue
968
751
            if show_ids:
969
752
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
970
753
            else:
1006
789
        if auto:
1007
790
            return self.run_auto(names_list, after, dry_run)
1008
791
        elif dry_run:
1009
 
            raise errors.BzrCommandError(gettext('--dry-run requires --auto.'))
 
792
            raise errors.BzrCommandError('--dry-run requires --auto.')
1010
793
        if names_list is None:
1011
794
            names_list = []
1012
795
        if len(names_list) < 2:
1013
 
            raise errors.BzrCommandError(gettext("missing file argument"))
 
796
            raise errors.BzrCommandError("missing file argument")
1014
797
        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"))
1018
798
        self.add_cleanup(tree.lock_tree_write().unlock)
1019
799
        self._run(tree, names_list, rel_names, after)
1020
800
 
1021
801
    def run_auto(self, names_list, after, dry_run):
1022
802
        if names_list is not None and len(names_list) > 1:
1023
 
            raise errors.BzrCommandError(gettext('Only one path may be specified to'
1024
 
                                         ' --auto.'))
 
803
            raise errors.BzrCommandError('Only one path may be specified to'
 
804
                                         ' --auto.')
1025
805
        if after:
1026
 
            raise errors.BzrCommandError(gettext('--after cannot be specified with'
1027
 
                                         ' --auto.'))
 
806
            raise errors.BzrCommandError('--after cannot be specified with'
 
807
                                         ' --auto.')
1028
808
        work_tree, file_list = WorkingTree.open_containing_paths(
1029
809
            names_list, default_directory='.')
1030
810
        self.add_cleanup(work_tree.lock_tree_write().unlock)
1042
822
                and rel_names[0].lower() == rel_names[1].lower()):
1043
823
                into_existing = False
1044
824
            else:
 
825
                inv = tree.inventory
1045
826
                # 'fix' the case of a potential 'from'
1046
827
                from_id = tree.path2id(
1047
828
                            tree.get_canonical_inventory_path(rel_names[0]))
1048
829
                if (not osutils.lexists(names_list[0]) and
1049
 
                    from_id and tree.stored_kind(from_id) == "directory"):
 
830
                    from_id and inv.get_file_kind(from_id) == "directory"):
1050
831
                    into_existing = False
1051
832
        # move/rename
1052
833
        if into_existing:
1059
840
                    self.outf.write("%s => %s\n" % (src, dest))
1060
841
        else:
1061
842
            if len(names_list) != 2:
1062
 
                raise errors.BzrCommandError(gettext('to mv multiple files the'
 
843
                raise errors.BzrCommandError('to mv multiple files the'
1063
844
                                             ' destination must be a versioned'
1064
 
                                             ' directory'))
 
845
                                             ' directory')
1065
846
 
1066
847
            # for cicp file-systems: the src references an existing inventory
1067
848
            # item:
1126
907
    match the remote one, use pull --overwrite. This will work even if the two
1127
908
    branches have diverged.
1128
909
 
1129
 
    If there is no default location set, the first pull will set it (use
1130
 
    --no-remember to avoid setting it). After that, you can omit the
1131
 
    location to use the default.  To change the default, use --remember. The
1132
 
    value will only be saved if the remote location can be accessed.
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>.
 
910
    If there is no default location set, the first pull will set it.  After
 
911
    that, you can omit the location to use the default.  To change the
 
912
    default, use --remember. The value will only be saved if the remote
 
913
    location can be accessed.
1137
914
 
1138
915
    Note: The location can be specified either in the form of a branch,
1139
916
    or in the form of a path to a file containing a merge directive generated
1153
930
                 "the master branch."
1154
931
            ),
1155
932
        Option('show-base',
1156
 
            help="Show base revision text in conflicts."),
1157
 
        Option('overwrite-tags',
1158
 
            help="Overwrite tags only."),
 
933
            help="Show base revision text in conflicts.")
1159
934
        ]
1160
935
    takes_args = ['location?']
1161
936
    encoding_type = 'replace'
1162
937
 
1163
 
    def run(self, location=None, remember=None, overwrite=False,
 
938
    def run(self, location=None, remember=False, overwrite=False,
1164
939
            revision=None, verbose=False,
1165
940
            directory=None, local=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 = []
 
941
            show_base=False):
1174
942
        # FIXME: too much stuff is in the command class
1175
943
        revision_id = None
1176
944
        mergeable = None
1186
954
            self.add_cleanup(branch_to.lock_write().unlock)
1187
955
 
1188
956
        if tree_to is None and show_base:
1189
 
            raise errors.BzrCommandError(gettext("Need working tree for --show-base."))
 
957
            raise errors.BzrCommandError("Need working tree for --show-base.")
1190
958
 
1191
959
        if local and not branch_to.get_bound_location():
1192
960
            raise errors.LocalRequiresBoundBranch()
1202
970
        stored_loc = branch_to.get_parent()
1203
971
        if location is None:
1204
972
            if stored_loc is None:
1205
 
                raise errors.BzrCommandError(gettext("No pull location known or"
1206
 
                                             " specified."))
 
973
                raise errors.BzrCommandError("No pull location known or"
 
974
                                             " specified.")
1207
975
            else:
1208
976
                display_url = urlutils.unescape_for_display(stored_loc,
1209
977
                        self.outf.encoding)
1210
978
                if not is_quiet():
1211
 
                    self.outf.write(gettext("Using saved parent location: %s\n") % display_url)
 
979
                    self.outf.write("Using saved parent location: %s\n" % display_url)
1212
980
                location = stored_loc
1213
981
 
1214
982
        revision = _get_one_revision('pull', revision)
1215
983
        if mergeable is not None:
1216
984
            if revision is not None:
1217
 
                raise errors.BzrCommandError(gettext(
1218
 
                    'Cannot use -r with merge directives or bundles'))
 
985
                raise errors.BzrCommandError(
 
986
                    'Cannot use -r with merge directives or bundles')
1219
987
            mergeable.install_revisions(branch_to.repository)
1220
988
            base_revision_id, revision_id, verified = \
1221
989
                mergeable.get_merge_request(branch_to.repository)
1224
992
            branch_from = Branch.open(location,
1225
993
                possible_transports=possible_transports)
1226
994
            self.add_cleanup(branch_from.lock_read().unlock)
1227
 
            # Remembers if asked explicitly or no previous location is set
1228
 
            if (remember
1229
 
                or (remember is None and branch_to.get_parent() is None)):
1230
 
                # FIXME: This shouldn't be done before the pull
1231
 
                # succeeds... -- vila 2012-01-02
 
995
 
 
996
            if branch_to.get_parent() is None or remember:
1232
997
                branch_to.set_parent(branch_from.base)
1233
998
 
1234
999
        if revision is not None:
1241
1006
                view_info=view_info)
1242
1007
            result = tree_to.pull(
1243
1008
                branch_from, overwrite, revision_id, change_reporter,
1244
 
                local=local, show_base=show_base)
 
1009
                possible_transports=possible_transports, local=local,
 
1010
                show_base=show_base)
1245
1011
        else:
1246
1012
            result = branch_to.pull(
1247
1013
                branch_from, overwrite, revision_id, local=local)
1251
1017
            log.show_branch_change(
1252
1018
                branch_to, self.outf, result.old_revno,
1253
1019
                result.old_revid)
1254
 
        if getattr(result, 'tag_conflicts', None):
1255
 
            return 1
1256
 
        else:
1257
 
            return 0
1258
1020
 
1259
1021
 
1260
1022
class cmd_push(Command):
1277
1039
    do a merge (see bzr help merge) from the other branch, and commit that.
1278
1040
    After that you will be able to do a push without '--overwrite'.
1279
1041
 
1280
 
    If there is no default push location set, the first push will set it (use
1281
 
    --no-remember to avoid setting it).  After that, you can omit the
1282
 
    location to use the default.  To change the default, use --remember. The
1283
 
    value will only be saved if the remote location can be accessed.
1284
 
 
1285
 
    The --verbose option will display the revisions pushed using the log_format
1286
 
    configuration option. You can use a different format by overriding it with
1287
 
    -Olog_format=<other_format>.
 
1042
    If there is no default push location set, the first push will set it.
 
1043
    After that, you can omit the location to use the default.  To change the
 
1044
    default, use --remember. The value will only be saved if the remote
 
1045
    location can be accessed.
1288
1046
    """
1289
1047
 
1290
1048
    _see_also = ['pull', 'update', 'working-trees']
1314
1072
        Option('no-tree',
1315
1073
               help="Don't populate the working tree, even for protocols"
1316
1074
               " that support it."),
1317
 
        Option('overwrite-tags',
1318
 
              help="Overwrite tags only."),
1319
1075
        ]
1320
1076
    takes_args = ['location?']
1321
1077
    encoding_type = 'replace'
1322
1078
 
1323
 
    def run(self, location=None, remember=None, overwrite=False,
 
1079
    def run(self, location=None, remember=False, overwrite=False,
1324
1080
        create_prefix=False, verbose=False, revision=None,
1325
1081
        use_existing_dir=False, directory=None, stacked_on=None,
1326
 
        stacked=False, strict=None, no_tree=False,
1327
 
        overwrite_tags=False):
 
1082
        stacked=False, strict=None, no_tree=False):
1328
1083
        from bzrlib.push import _show_push_branch
1329
1084
 
1330
 
        if overwrite:
1331
 
            overwrite = ["history", "tags"]
1332
 
        elif overwrite_tags:
1333
 
            overwrite = ["tags"]
1334
 
        else:
1335
 
            overwrite = []
1336
 
 
1337
1085
        if directory is None:
1338
1086
            directory = '.'
1339
1087
        # Get the source branch
1340
1088
        (tree, br_from,
1341
 
         _unused) = controldir.ControlDir.open_containing_tree_or_branch(directory)
 
1089
         _unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1342
1090
        # Get the tip's revision_id
1343
1091
        revision = _get_one_revision('push', revision)
1344
1092
        if revision is not None:
1365
1113
                    # error by the feedback given to them. RBC 20080227.
1366
1114
                    stacked_on = parent_url
1367
1115
            if not stacked_on:
1368
 
                raise errors.BzrCommandError(gettext(
1369
 
                    "Could not determine branch to refer to."))
 
1116
                raise errors.BzrCommandError(
 
1117
                    "Could not determine branch to refer to.")
1370
1118
 
1371
1119
        # Get the destination location
1372
1120
        if location is None:
1373
1121
            stored_loc = br_from.get_push_location()
1374
1122
            if stored_loc is None:
1375
 
                parent_loc = br_from.get_parent()
1376
 
                if parent_loc:
1377
 
                    raise errors.BzrCommandError(gettext(
1378
 
                        "No push location known or specified. To push to the "
1379
 
                        "parent branch (at %s), use 'bzr push :parent'." %
1380
 
                        urlutils.unescape_for_display(parent_loc,
1381
 
                            self.outf.encoding)))
1382
 
                else:
1383
 
                    raise errors.BzrCommandError(gettext(
1384
 
                        "No push location known or specified."))
 
1123
                raise errors.BzrCommandError(
 
1124
                    "No push location known or specified.")
1385
1125
            else:
1386
1126
                display_url = urlutils.unescape_for_display(stored_loc,
1387
1127
                        self.outf.encoding)
1388
 
                note(gettext("Using saved push location: %s") % display_url)
 
1128
                self.outf.write("Using saved push location: %s\n" % display_url)
1389
1129
                location = stored_loc
1390
1130
 
1391
1131
        _show_push_branch(br_from, revision_id, location, self.outf,
1406
1146
 
1407
1147
    To retrieve the branch as of a particular revision, supply the --revision
1408
1148
    parameter, as in "branch foo/bar -r 5".
1409
 
 
1410
 
    The synonyms 'clone' and 'get' for this command are deprecated.
1411
1149
    """
1412
1150
 
1413
1151
    _see_also = ['checkout']
1443
1181
            files_from=None):
1444
1182
        from bzrlib import switch as _mod_switch
1445
1183
        from bzrlib.tag import _merge_tags_if_possible
1446
 
        if self.invoked_as in ['get', 'clone']:
1447
 
            ui.ui_factory.show_user_warning(
1448
 
                'deprecated_command',
1449
 
                deprecated_name=self.invoked_as,
1450
 
                recommended_name='branch',
1451
 
                deprecated_in_version='2.4')
1452
 
        accelerator_tree, br_from = controldir.ControlDir.open_tree_or_branch(
 
1184
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1453
1185
            from_location)
1454
1186
        if not (hardlink or files_from):
1455
1187
            # accelerator_tree is usually slower because you have to read N
1468
1200
            # RBC 20060209
1469
1201
            revision_id = br_from.last_revision()
1470
1202
        if to_location is None:
1471
 
            to_location = getattr(br_from, "name", None)
1472
 
            if not to_location:
1473
 
                to_location = urlutils.derive_to_location(from_location)
 
1203
            to_location = urlutils.derive_to_location(from_location)
1474
1204
        to_transport = transport.get_transport(to_location)
1475
1205
        try:
1476
1206
            to_transport.mkdir('.')
1477
1207
        except errors.FileExists:
1478
 
            try:
1479
 
                to_dir = controldir.ControlDir.open_from_transport(
1480
 
                    to_transport)
1481
 
            except errors.NotBranchError:
1482
 
                if not use_existing_dir:
1483
 
                    raise errors.BzrCommandError(gettext('Target directory "%s" '
1484
 
                        'already exists.') % to_location)
1485
 
                else:
1486
 
                    to_dir = None
 
1208
            if not use_existing_dir:
 
1209
                raise errors.BzrCommandError('Target directory "%s" '
 
1210
                    'already exists.' % to_location)
1487
1211
            else:
1488
1212
                try:
1489
 
                    to_dir.open_branch()
 
1213
                    bzrdir.BzrDir.open_from_transport(to_transport)
1490
1214
                except errors.NotBranchError:
1491
1215
                    pass
1492
1216
                else:
1493
1217
                    raise errors.AlreadyBranchError(to_location)
1494
1218
        except errors.NoSuchFile:
1495
 
            raise errors.BzrCommandError(gettext('Parent of "%s" does not exist.')
 
1219
            raise errors.BzrCommandError('Parent of "%s" does not exist.'
1496
1220
                                         % to_location)
1497
 
        else:
1498
 
            to_dir = None
1499
 
        if to_dir is None:
1500
 
            try:
1501
 
                # preserve whatever source format we have.
1502
 
                to_dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1503
 
                                            possible_transports=[to_transport],
1504
 
                                            accelerator_tree=accelerator_tree,
1505
 
                                            hardlink=hardlink, stacked=stacked,
1506
 
                                            force_new_repo=standalone,
1507
 
                                            create_tree_if_local=not no_tree,
1508
 
                                            source_branch=br_from)
1509
 
                branch = to_dir.open_branch(
1510
 
                    possible_transports=[
1511
 
                        br_from.bzrdir.root_transport, to_transport])
1512
 
            except errors.NoSuchRevision:
1513
 
                to_transport.delete_tree('.')
1514
 
                msg = gettext("The branch {0} has no revision {1}.").format(
1515
 
                    from_location, revision)
1516
 
                raise errors.BzrCommandError(msg)
1517
 
        else:
1518
 
            try:
1519
 
                to_repo = to_dir.open_repository()
1520
 
            except errors.NoRepositoryPresent:
1521
 
                to_repo = to_dir.create_repository()
1522
 
            to_repo.fetch(br_from.repository, revision_id=revision_id)
1523
 
            branch = br_from.sprout(to_dir, revision_id=revision_id)
 
1221
        try:
 
1222
            # preserve whatever source format we have.
 
1223
            dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
 
1224
                                        possible_transports=[to_transport],
 
1225
                                        accelerator_tree=accelerator_tree,
 
1226
                                        hardlink=hardlink, stacked=stacked,
 
1227
                                        force_new_repo=standalone,
 
1228
                                        create_tree_if_local=not no_tree,
 
1229
                                        source_branch=br_from)
 
1230
            branch = dir.open_branch()
 
1231
        except errors.NoSuchRevision:
 
1232
            to_transport.delete_tree('.')
 
1233
            msg = "The branch %s has no revision %s." % (from_location,
 
1234
                revision)
 
1235
            raise errors.BzrCommandError(msg)
1524
1236
        _merge_tags_if_possible(br_from, branch)
1525
1237
        # If the source branch is stacked, the new branch may
1526
1238
        # be stacked whether we asked for that explicitly or not.
1527
1239
        # We therefore need a try/except here and not just 'if stacked:'
1528
1240
        try:
1529
 
            note(gettext('Created new stacked branch referring to %s.') %
 
1241
            note('Created new stacked branch referring to %s.' %
1530
1242
                branch.get_stacked_on_url())
1531
1243
        except (errors.NotStacked, errors.UnstackableBranchFormat,
1532
1244
            errors.UnstackableRepositoryFormat), e:
1533
 
            note(ngettext('Branched %d revision.', 'Branched %d revisions.', branch.revno()) % branch.revno())
 
1245
            note('Branched %d revision(s).' % branch.revno())
1534
1246
        if bind:
1535
1247
            # Bind to the parent
1536
1248
            parent_branch = Branch.open(from_location)
1537
1249
            branch.bind(parent_branch)
1538
 
            note(gettext('New branch bound to %s') % from_location)
 
1250
            note('New branch bound to %s' % from_location)
1539
1251
        if switch:
1540
1252
            # Switch to the new branch
1541
1253
            wt, _ = WorkingTree.open_containing('.')
1542
1254
            _mod_switch.switch(wt.bzrdir, branch)
1543
 
            note(gettext('Switched to branch: %s'),
 
1255
            note('Switched to branch: %s',
1544
1256
                urlutils.unescape_for_display(branch.base, 'utf-8'))
1545
1257
 
1546
1258
 
1547
 
class cmd_branches(Command):
1548
 
    __doc__ = """List the branches available at the current location.
1549
 
 
1550
 
    This command will print the names of all the branches at the current
1551
 
    location.
1552
 
    """
1553
 
 
1554
 
    takes_args = ['location?']
1555
 
    takes_options = [
1556
 
                  Option('recursive', short_name='R',
1557
 
                         help='Recursively scan for branches rather than '
1558
 
                              'just looking in the specified location.')]
1559
 
 
1560
 
    def run(self, location=".", recursive=False):
1561
 
        if recursive:
1562
 
            t = transport.get_transport(location)
1563
 
            if not t.listable():
1564
 
                raise errors.BzrCommandError(
1565
 
                    "Can't scan this type of location.")
1566
 
            for b in controldir.ControlDir.find_branches(t):
1567
 
                self.outf.write("%s\n" % urlutils.unescape_for_display(
1568
 
                    urlutils.relative_url(t.base, b.base),
1569
 
                    self.outf.encoding).rstrip("/"))
1570
 
        else:
1571
 
            dir = controldir.ControlDir.open_containing(location)[0]
1572
 
            try:
1573
 
                active_branch = dir.open_branch(name="")
1574
 
            except errors.NotBranchError:
1575
 
                active_branch = None
1576
 
            names = {}
1577
 
            for name, branch in iter_sibling_branches(dir):
1578
 
                if name == "":
1579
 
                    continue
1580
 
                active = (active_branch is not None and
1581
 
                          active_branch.base == branch.base)
1582
 
                names[name] = active
1583
 
            # Only mention the current branch explicitly if it's not
1584
 
            # one of the colocated branches
1585
 
            if not any(names.values()) and active_branch is not None:
1586
 
                self.outf.write("* %s\n" % gettext("(default)"))
1587
 
            for name in sorted(names.keys()):
1588
 
                active = names[name]
1589
 
                if active:
1590
 
                    prefix = "*"
1591
 
                else:
1592
 
                    prefix = " "
1593
 
                self.outf.write("%s %s\n" % (
1594
 
                    prefix, name.encode(self.outf.encoding)))
1595
 
 
1596
 
 
1597
1259
class cmd_checkout(Command):
1598
1260
    __doc__ = """Create a new checkout of an existing branch.
1599
1261
 
1615
1277
    code.)
1616
1278
    """
1617
1279
 
1618
 
    _see_also = ['checkouts', 'branch', 'working-trees', 'remove-tree']
 
1280
    _see_also = ['checkouts', 'branch']
1619
1281
    takes_args = ['branch_location?', 'to_location?']
1620
1282
    takes_options = ['revision',
1621
1283
                     Option('lightweight',
1638
1300
        if branch_location is None:
1639
1301
            branch_location = osutils.getcwd()
1640
1302
            to_location = branch_location
1641
 
        accelerator_tree, source = controldir.ControlDir.open_tree_or_branch(
 
1303
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1642
1304
            branch_location)
1643
1305
        if not (hardlink or files_from):
1644
1306
            # accelerator_tree is usually slower because you have to read N
1681
1343
    def run(self, dir=u'.'):
1682
1344
        tree = WorkingTree.open_containing(dir)[0]
1683
1345
        self.add_cleanup(tree.lock_read().unlock)
 
1346
        new_inv = tree.inventory
1684
1347
        old_tree = tree.basis_tree()
1685
1348
        self.add_cleanup(old_tree.lock_read().unlock)
 
1349
        old_inv = old_tree.inventory
1686
1350
        renames = []
1687
1351
        iterator = tree.iter_changes(old_tree, include_unchanged=True)
1688
1352
        for f, paths, c, v, p, n, k, e in iterator:
1697
1361
 
1698
1362
 
1699
1363
class cmd_update(Command):
1700
 
    __doc__ = """Update a working tree to a new revision.
1701
 
 
1702
 
    This will perform a merge of the destination revision (the tip of the
1703
 
    branch, or the specified revision) into the working tree, and then make
1704
 
    that revision the basis revision for the working tree.  
1705
 
 
1706
 
    You can use this to visit an older revision, or to update a working tree
1707
 
    that is out of date from its branch.
1708
 
    
1709
 
    If there are any uncommitted changes in the tree, they will be carried
1710
 
    across and remain as uncommitted changes after the update.  To discard
1711
 
    these changes, use 'bzr revert'.  The uncommitted changes may conflict
1712
 
    with the changes brought in by the change in basis revision.
1713
 
 
1714
 
    If the tree's branch is bound to a master branch, bzr will also update
 
1364
    __doc__ = """Update a tree to have the latest code committed to its branch.
 
1365
 
 
1366
    This will perform a merge into the working tree, and may generate
 
1367
    conflicts. If you have any local changes, you will still
 
1368
    need to commit them after the update for the update to be complete.
 
1369
 
 
1370
    If you want to discard your local changes, you can just do a
 
1371
    'bzr revert' instead of 'bzr commit' after the update.
 
1372
 
 
1373
    If you want to restore a file that has been removed locally, use
 
1374
    'bzr revert' instead of 'bzr update'.
 
1375
 
 
1376
    If the tree's branch is bound to a master branch, it will also update
1715
1377
    the branch from the master.
1716
 
 
1717
 
    You cannot update just a single file or directory, because each Bazaar
1718
 
    working tree has just a single basis revision.  If you want to restore a
1719
 
    file that has been removed locally, use 'bzr revert' instead of 'bzr
1720
 
    update'.  If you want to restore a file to its state in a previous
1721
 
    revision, use 'bzr revert' with a '-r' option, or use 'bzr cat' to write
1722
 
    out the old content of that file to a new location.
1723
 
 
1724
 
    The 'dir' argument, if given, must be the location of the root of a
1725
 
    working tree to update.  By default, the working tree that contains the 
1726
 
    current working directory is used.
1727
1378
    """
1728
1379
 
1729
1380
    _see_also = ['pull', 'working-trees', 'status-flags']
1734
1385
                     ]
1735
1386
    aliases = ['up']
1736
1387
 
1737
 
    def run(self, dir=None, revision=None, show_base=None):
 
1388
    def run(self, dir='.', revision=None, show_base=None):
1738
1389
        if revision is not None and len(revision) != 1:
1739
 
            raise errors.BzrCommandError(gettext(
1740
 
                "bzr update --revision takes exactly one revision"))
1741
 
        if dir is None:
1742
 
            tree = WorkingTree.open_containing('.')[0]
1743
 
        else:
1744
 
            tree, relpath = WorkingTree.open_containing(dir)
1745
 
            if relpath:
1746
 
                # See bug 557886.
1747
 
                raise errors.BzrCommandError(gettext(
1748
 
                    "bzr update can only update a whole tree, "
1749
 
                    "not a file or subdirectory"))
 
1390
            raise errors.BzrCommandError(
 
1391
                        "bzr update --revision takes exactly one revision")
 
1392
        tree = WorkingTree.open_containing(dir)[0]
1750
1393
        branch = tree.branch
1751
1394
        possible_transports = []
1752
1395
        master = branch.get_master_branch(
1776
1419
            revision_id = branch.last_revision()
1777
1420
        if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1778
1421
            revno = branch.revision_id_to_dotted_revno(revision_id)
1779
 
            note(gettext("Tree is up to date at revision {0} of branch {1}"
1780
 
                        ).format('.'.join(map(str, revno)), branch_location))
 
1422
            note("Tree is up to date at revision %s of branch %s" %
 
1423
                ('.'.join(map(str, revno)), branch_location))
1781
1424
            return 0
1782
1425
        view_info = _get_view_info_for_change_reporter(tree)
1783
1426
        change_reporter = delta._ChangeReporter(
1791
1434
                old_tip=old_tip,
1792
1435
                show_base=show_base)
1793
1436
        except errors.NoSuchRevision, e:
1794
 
            raise errors.BzrCommandError(gettext(
 
1437
            raise errors.BzrCommandError(
1795
1438
                                  "branch has no revision %s\n"
1796
1439
                                  "bzr update --revision only works"
1797
 
                                  " for a revision in the branch history")
 
1440
                                  " for a revision in the branch history"
1798
1441
                                  % (e.revision))
1799
1442
        revno = tree.branch.revision_id_to_dotted_revno(
1800
1443
            _mod_revision.ensure_null(tree.last_revision()))
1801
 
        note(gettext('Updated to revision {0} of branch {1}').format(
1802
 
             '.'.join(map(str, revno)), branch_location))
 
1444
        note('Updated to revision %s of branch %s' %
 
1445
             ('.'.join(map(str, revno)), branch_location))
1803
1446
        parent_ids = tree.get_parent_ids()
1804
1447
        if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1805
 
            note(gettext('Your local commits will now show as pending merges with '
1806
 
                 "'bzr status', and can be committed with 'bzr commit'."))
 
1448
            note('Your local commits will now show as pending merges with '
 
1449
                 "'bzr status', and can be committed with 'bzr commit'.")
1807
1450
        if conflicts != 0:
1808
1451
            return 1
1809
1452
        else:
1850
1493
        else:
1851
1494
            noise_level = 0
1852
1495
        from bzrlib.info import show_bzrdir_info
1853
 
        show_bzrdir_info(controldir.ControlDir.open_containing(location)[0],
 
1496
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
1854
1497
                         verbose=noise_level, outfile=self.outf)
1855
1498
 
1856
1499
 
1859
1502
 
1860
1503
    This makes Bazaar stop tracking changes to the specified files. Bazaar will
1861
1504
    delete them if they can easily be recovered using revert otherwise they
1862
 
    will be backed up (adding an extension of the form .~#~). If no options or
 
1505
    will be backed up (adding an extention of the form .~#~). If no options or
1863
1506
    parameters are given Bazaar will scan for files that are being tracked by
1864
1507
    Bazaar but missing in your tree and stop tracking them for you.
1865
1508
    """
1881
1524
    def run(self, file_list, verbose=False, new=False,
1882
1525
        file_deletion_strategy='safe'):
1883
1526
        if file_deletion_strategy == 'force':
1884
 
            note(gettext("(The --force option is deprecated, rather use --no-backup "
1885
 
                "in future.)"))
 
1527
            note("(The --force option is deprecated, rather use --no-backup "
 
1528
                "in future.)")
1886
1529
            file_deletion_strategy = 'no-backup'
1887
1530
 
1888
1531
        tree, file_list = WorkingTree.open_containing_paths(file_list)
1898
1541
                specific_files=file_list).added
1899
1542
            file_list = sorted([f[0] for f in added], reverse=True)
1900
1543
            if len(file_list) == 0:
1901
 
                raise errors.BzrCommandError(gettext('No matching files.'))
 
1544
                raise errors.BzrCommandError('No matching files.')
1902
1545
        elif file_list is None:
1903
1546
            # missing files show up in iter_changes(basis) as
1904
1547
            # versioned-with-no-kind.
1988
1631
 
1989
1632
    def run(self, branch=".", canonicalize_chks=False):
1990
1633
        from bzrlib.reconcile import reconcile
1991
 
        dir = controldir.ControlDir.open(branch)
 
1634
        dir = bzrdir.BzrDir.open(branch)
1992
1635
        reconcile(dir, canonicalize_chks=canonicalize_chks)
1993
1636
 
1994
1637
 
2003
1646
    @display_command
2004
1647
    def run(self, location="."):
2005
1648
        branch = Branch.open_containing(location)[0]
2006
 
        self.add_cleanup(branch.lock_read().unlock)
2007
 
        graph = branch.repository.get_graph()
2008
 
        history = list(graph.iter_lefthand_ancestry(branch.last_revision(),
2009
 
            [_mod_revision.NULL_REVISION]))
2010
 
        for revid in reversed(history):
 
1649
        for revid in branch.revision_history():
2011
1650
            self.outf.write(revid)
2012
1651
            self.outf.write('\n')
2013
1652
 
2031
1670
            b = wt.branch
2032
1671
            last_revision = wt.last_revision()
2033
1672
 
2034
 
        self.add_cleanup(b.repository.lock_read().unlock)
2035
 
        graph = b.repository.get_graph()
2036
 
        revisions = [revid for revid, parents in
2037
 
            graph.iter_ancestry([last_revision])]
2038
 
        for revision_id in reversed(revisions):
2039
 
            if _mod_revision.is_null(revision_id):
2040
 
                continue
 
1673
        revision_ids = b.repository.get_ancestry(last_revision)
 
1674
        revision_ids.pop(0)
 
1675
        for revision_id in revision_ids:
2041
1676
            self.outf.write(revision_id + '\n')
2042
1677
 
2043
1678
 
2073
1708
         RegistryOption('format',
2074
1709
                help='Specify a format for this branch. '
2075
1710
                'See "help formats".',
2076
 
                lazy_registry=('bzrlib.controldir', 'format_registry'),
2077
 
                converter=lambda name: controldir.format_registry.make_bzrdir(name),
 
1711
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
 
1712
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
2078
1713
                value_switches=True,
2079
1714
                title="Branch format",
2080
1715
                ),
2087
1722
    def run(self, location=None, format=None, append_revisions_only=False,
2088
1723
            create_prefix=False, no_tree=False):
2089
1724
        if format is None:
2090
 
            format = controldir.format_registry.make_bzrdir('default')
 
1725
            format = bzrdir.format_registry.make_bzrdir('default')
2091
1726
        if location is None:
2092
1727
            location = u'.'
2093
1728
 
2102
1737
            to_transport.ensure_base()
2103
1738
        except errors.NoSuchFile:
2104
1739
            if not create_prefix:
2105
 
                raise errors.BzrCommandError(gettext("Parent directory of %s"
 
1740
                raise errors.BzrCommandError("Parent directory of %s"
2106
1741
                    " does not exist."
2107
1742
                    "\nYou may supply --create-prefix to create all"
2108
 
                    " leading parent directories.")
 
1743
                    " leading parent directories."
2109
1744
                    % location)
2110
1745
            to_transport.create_prefix()
2111
1746
 
2112
1747
        try:
2113
 
            a_bzrdir = controldir.ControlDir.open_from_transport(to_transport)
 
1748
            a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
2114
1749
        except errors.NotBranchError:
2115
1750
            # really a NotBzrDir error...
2116
 
            create_branch = controldir.ControlDir.create_branch_convenience
 
1751
            create_branch = bzrdir.BzrDir.create_branch_convenience
2117
1752
            if no_tree:
2118
1753
                force_new_tree = False
2119
1754
            else:
2130
1765
                        raise errors.BranchExistsWithoutWorkingTree(location)
2131
1766
                raise errors.AlreadyBranchError(location)
2132
1767
            branch = a_bzrdir.create_branch()
2133
 
            if not no_tree and not a_bzrdir.has_workingtree():
 
1768
            if not no_tree:
2134
1769
                a_bzrdir.create_workingtree()
2135
1770
        if append_revisions_only:
2136
1771
            try:
2137
1772
                branch.set_append_revisions_only(True)
2138
1773
            except errors.UpgradeRequired:
2139
 
                raise errors.BzrCommandError(gettext('This branch format cannot be set'
2140
 
                    ' to append-revisions-only.  Try --default.'))
 
1774
                raise errors.BzrCommandError('This branch format cannot be set'
 
1775
                    ' to append-revisions-only.  Try --default.')
2141
1776
        if not is_quiet():
2142
1777
            from bzrlib.info import describe_layout, describe_format
2143
1778
            try:
2147
1782
            repository = branch.repository
2148
1783
            layout = describe_layout(repository, branch, tree).lower()
2149
1784
            format = describe_format(a_bzrdir, repository, branch, tree)
2150
 
            self.outf.write(gettext("Created a {0} (format: {1})\n").format(
2151
 
                  layout, format))
 
1785
            self.outf.write("Created a %s (format: %s)\n" % (layout, format))
2152
1786
            if repository.is_shared():
2153
1787
                #XXX: maybe this can be refactored into transport.path_or_url()
2154
1788
                url = repository.bzrdir.root_transport.external_url()
2156
1790
                    url = urlutils.local_path_from_url(url)
2157
1791
                except errors.InvalidURL:
2158
1792
                    pass
2159
 
                self.outf.write(gettext("Using shared repository: %s\n") % url)
 
1793
                self.outf.write("Using shared repository: %s\n" % url)
2160
1794
 
2161
1795
 
2162
1796
class cmd_init_repository(Command):
2192
1826
    takes_options = [RegistryOption('format',
2193
1827
                            help='Specify a format for this repository. See'
2194
1828
                                 ' "bzr help formats" for details.',
2195
 
                            lazy_registry=('bzrlib.controldir', 'format_registry'),
2196
 
                            converter=lambda name: controldir.format_registry.make_bzrdir(name),
 
1829
                            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
 
1830
                            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
2197
1831
                            value_switches=True, title='Repository format'),
2198
1832
                     Option('no-trees',
2199
1833
                             help='Branches in the repository will default to'
2203
1837
 
2204
1838
    def run(self, location, format=None, no_trees=False):
2205
1839
        if format is None:
2206
 
            format = controldir.format_registry.make_bzrdir('default')
 
1840
            format = bzrdir.format_registry.make_bzrdir('default')
2207
1841
 
2208
1842
        if location is None:
2209
1843
            location = '.'
2210
1844
 
2211
1845
        to_transport = transport.get_transport(location)
 
1846
        to_transport.ensure_base()
2212
1847
 
2213
 
        (repo, newdir, require_stacking, repository_policy) = (
2214
 
            format.initialize_on_transport_ex(to_transport,
2215
 
            create_prefix=True, make_working_trees=not no_trees,
2216
 
            shared_repo=True, force_new_repo=True,
2217
 
            use_existing_dir=True,
2218
 
            repo_format_name=format.repository_format.get_format_string()))
 
1848
        newdir = format.initialize_on_transport(to_transport)
 
1849
        repo = newdir.create_repository(shared=True)
 
1850
        repo.set_make_working_trees(not no_trees)
2219
1851
        if not is_quiet():
2220
1852
            from bzrlib.info import show_bzrdir_info
2221
 
            show_bzrdir_info(newdir, verbose=0, outfile=self.outf)
 
1853
            show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
2222
1854
 
2223
1855
 
2224
1856
class cmd_diff(Command):
2331
1963
            type=unicode,
2332
1964
            ),
2333
1965
        RegistryOption('format',
2334
 
            short_name='F',
2335
1966
            help='Diff format to use.',
2336
1967
            lazy_registry=('bzrlib.diff', 'format_registry'),
2337
 
            title='Diff format'),
 
1968
            value_switches=False, title='Diff format'),
2338
1969
        ]
2339
1970
    aliases = ['di', 'dif']
2340
1971
    encoding_type = 'exact'
2355
1986
        elif ':' in prefix:
2356
1987
            old_label, new_label = prefix.split(":")
2357
1988
        else:
2358
 
            raise errors.BzrCommandError(gettext(
 
1989
            raise errors.BzrCommandError(
2359
1990
                '--prefix expects two values separated by a colon'
2360
 
                ' (eg "old/:new/")'))
 
1991
                ' (eg "old/:new/")')
2361
1992
 
2362
1993
        if revision and len(revision) > 2:
2363
 
            raise errors.BzrCommandError(gettext('bzr diff --revision takes exactly'
2364
 
                                         ' one or two revision specifiers'))
 
1994
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
 
1995
                                         ' one or two revision specifiers')
2365
1996
 
2366
1997
        if using is not None and format is not None:
2367
 
            raise errors.BzrCommandError(gettext(
2368
 
                '{0} and {1} are mutually exclusive').format(
2369
 
                '--using', '--format'))
 
1998
            raise errors.BzrCommandError('--using and --format are mutually '
 
1999
                'exclusive.')
2370
2000
 
2371
2001
        (old_tree, new_tree,
2372
2002
         old_branch, new_branch,
2402
2032
        self.add_cleanup(tree.lock_read().unlock)
2403
2033
        old = tree.basis_tree()
2404
2034
        self.add_cleanup(old.lock_read().unlock)
2405
 
        for path, ie in old.iter_entries_by_dir():
 
2035
        for path, ie in old.inventory.iter_entries():
2406
2036
            if not tree.has_id(ie.file_id):
2407
2037
                self.outf.write(path)
2408
2038
                if show_ids:
2422
2052
    @display_command
2423
2053
    def run(self, null=False, directory=u'.'):
2424
2054
        tree = WorkingTree.open_containing(directory)[0]
2425
 
        self.add_cleanup(tree.lock_read().unlock)
2426
2055
        td = tree.changes_from(tree.basis_tree())
2427
 
        self.cleanup_now()
2428
2056
        for path, id, kind, text_modified, meta_modified in td.modified:
2429
2057
            if null:
2430
2058
                self.outf.write(path + '\0')
2446
2074
        self.add_cleanup(wt.lock_read().unlock)
2447
2075
        basis = wt.basis_tree()
2448
2076
        self.add_cleanup(basis.lock_read().unlock)
2449
 
        root_id = wt.get_root_id()
2450
 
        for file_id in wt.all_file_ids():
2451
 
            if basis.has_id(file_id):
2452
 
                continue
2453
 
            if root_id == file_id:
2454
 
                continue
2455
 
            path = wt.id2path(file_id)
 
2077
        basis_inv = basis.inventory
 
2078
        inv = wt.inventory
 
2079
        for file_id in inv:
 
2080
            if file_id in basis_inv:
 
2081
                continue
 
2082
            if inv.is_root(file_id) and len(basis_inv) == 0:
 
2083
                continue
 
2084
            path = inv.id2path(file_id)
2456
2085
            if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2457
2086
                continue
2458
2087
            if null:
2479
2108
    try:
2480
2109
        return int(limitstring)
2481
2110
    except ValueError:
2482
 
        msg = gettext("The limit argument must be an integer.")
 
2111
        msg = "The limit argument must be an integer."
2483
2112
        raise errors.BzrCommandError(msg)
2484
2113
 
2485
2114
 
2487
2116
    try:
2488
2117
        return int(s)
2489
2118
    except ValueError:
2490
 
        msg = gettext("The levels argument must be an integer.")
 
2119
        msg = "The levels argument must be an integer."
2491
2120
        raise errors.BzrCommandError(msg)
2492
2121
 
2493
2122
 
2603
2232
 
2604
2233
    :Other filtering:
2605
2234
 
2606
 
      The --match option can be used for finding revisions that match a
2607
 
      regular expression in a commit message, committer, author or bug.
2608
 
      Specifying the option several times will match any of the supplied
2609
 
      expressions. --match-author, --match-bugs, --match-committer and
2610
 
      --match-message can be used to only match a specific field.
 
2235
      The --message option can be used for finding revisions that match a
 
2236
      regular expression in a commit message.
2611
2237
 
2612
2238
    :Tips & tricks:
2613
2239
 
2673
2299
                   argname='N',
2674
2300
                   type=_parse_levels),
2675
2301
            Option('message',
 
2302
                   short_name='m',
2676
2303
                   help='Show revisions whose message matches this '
2677
2304
                        'regular expression.',
2678
 
                   type=str,
2679
 
                   hidden=True),
 
2305
                   type=str),
2680
2306
            Option('limit',
2681
2307
                   short_name='l',
2682
2308
                   help='Limit the output to the first N revisions.',
2685
2311
            Option('show-diff',
2686
2312
                   short_name='p',
2687
2313
                   help='Show changes made in each revision as a patch.'),
2688
 
            Option('include-merged',
 
2314
            Option('include-merges',
2689
2315
                   help='Show merged revisions like --levels 0 does.'),
2690
 
            Option('include-merges', hidden=True,
2691
 
                   help='Historical alias for --include-merged.'),
2692
 
            Option('omit-merges',
2693
 
                   help='Do not report commits with more than one parent.'),
2694
2316
            Option('exclude-common-ancestry',
2695
2317
                   help='Display only the revisions that are not part'
2696
 
                   ' of both ancestries (require -rX..Y).'
2697
 
                   ),
2698
 
            Option('signatures',
2699
 
                   help='Show digital signature validity.'),
2700
 
            ListOption('match',
2701
 
                short_name='m',
2702
 
                help='Show revisions whose properties match this '
2703
 
                'expression.',
2704
 
                type=str),
2705
 
            ListOption('match-message',
2706
 
                   help='Show revisions whose message matches this '
2707
 
                   'expression.',
2708
 
                type=str),
2709
 
            ListOption('match-committer',
2710
 
                   help='Show revisions whose committer matches this '
2711
 
                   'expression.',
2712
 
                type=str),
2713
 
            ListOption('match-author',
2714
 
                   help='Show revisions whose authors match this '
2715
 
                   'expression.',
2716
 
                type=str),
2717
 
            ListOption('match-bugs',
2718
 
                   help='Show revisions whose bugs match this '
2719
 
                   'expression.',
2720
 
                type=str)
 
2318
                   ' of both ancestries (require -rX..Y)'
 
2319
                   )
2721
2320
            ]
2722
2321
    encoding_type = 'replace'
2723
2322
 
2733
2332
            message=None,
2734
2333
            limit=None,
2735
2334
            show_diff=False,
2736
 
            include_merged=None,
 
2335
            include_merges=False,
2737
2336
            authors=None,
2738
2337
            exclude_common_ancestry=False,
2739
 
            signatures=False,
2740
 
            match=None,
2741
 
            match_message=None,
2742
 
            match_committer=None,
2743
 
            match_author=None,
2744
 
            match_bugs=None,
2745
 
            omit_merges=False,
2746
 
            include_merges=symbol_versioning.DEPRECATED_PARAMETER,
2747
2338
            ):
2748
2339
        from bzrlib.log import (
2749
2340
            Logger,
2751
2342
            _get_info_for_log_files,
2752
2343
            )
2753
2344
        direction = (forward and 'forward') or 'reverse'
2754
 
        if symbol_versioning.deprecated_passed(include_merges):
2755
 
            ui.ui_factory.show_user_warning(
2756
 
                'deprecated_command_option',
2757
 
                deprecated_name='--include-merges',
2758
 
                recommended_name='--include-merged',
2759
 
                deprecated_in_version='2.5',
2760
 
                command=self.invoked_as)
2761
 
            if include_merged is None:
2762
 
                include_merged = include_merges
2763
 
            else:
2764
 
                raise errors.BzrCommandError(gettext(
2765
 
                    '{0} and {1} are mutually exclusive').format(
2766
 
                    '--include-merges', '--include-merged'))
2767
 
        if include_merged is None:
2768
 
            include_merged = False
2769
2345
        if (exclude_common_ancestry
2770
2346
            and (revision is None or len(revision) != 2)):
2771
 
            raise errors.BzrCommandError(gettext(
2772
 
                '--exclude-common-ancestry requires -r with two revisions'))
2773
 
        if include_merged:
 
2347
            raise errors.BzrCommandError(
 
2348
                '--exclude-common-ancestry requires -r with two revisions')
 
2349
        if include_merges:
2774
2350
            if levels is None:
2775
2351
                levels = 0
2776
2352
            else:
2777
 
                raise errors.BzrCommandError(gettext(
2778
 
                    '{0} and {1} are mutually exclusive').format(
2779
 
                    '--levels', '--include-merged'))
 
2353
                raise errors.BzrCommandError(
 
2354
                    '--levels and --include-merges are mutually exclusive')
2780
2355
 
2781
2356
        if change is not None:
2782
2357
            if len(change) > 1:
2783
2358
                raise errors.RangeInChangeOption()
2784
2359
            if revision is not None:
2785
 
                raise errors.BzrCommandError(gettext(
2786
 
                    '{0} and {1} are mutually exclusive').format(
2787
 
                    '--revision', '--change'))
 
2360
                raise errors.BzrCommandError(
 
2361
                    '--revision and --change are mutually exclusive')
2788
2362
            else:
2789
2363
                revision = change
2790
2364
 
2796
2370
                revision, file_list, self.add_cleanup)
2797
2371
            for relpath, file_id, kind in file_info_list:
2798
2372
                if file_id is None:
2799
 
                    raise errors.BzrCommandError(gettext(
2800
 
                        "Path unknown at end or start of revision range: %s") %
 
2373
                    raise errors.BzrCommandError(
 
2374
                        "Path unknown at end or start of revision range: %s" %
2801
2375
                        relpath)
2802
2376
                # If the relpath is the top of the tree, we log everything
2803
2377
                if relpath == '':
2815
2389
                location = revision[0].get_branch()
2816
2390
            else:
2817
2391
                location = '.'
2818
 
            dir, relpath = controldir.ControlDir.open_containing(location)
 
2392
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2819
2393
            b = dir.open_branch()
2820
2394
            self.add_cleanup(b.lock_read().unlock)
2821
2395
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2822
2396
 
2823
 
        if b.get_config_stack().get('validate_signatures_in_log'):
2824
 
            signatures = True
2825
 
 
2826
 
        if signatures:
2827
 
            if not gpg.GPGStrategy.verify_signatures_available():
2828
 
                raise errors.GpgmeNotInstalled(None)
2829
 
 
2830
2397
        # Decide on the type of delta & diff filtering to use
2831
2398
        # TODO: add an --all-files option to make this configurable & consistent
2832
2399
        if not verbose:
2869
2436
        match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2870
2437
            or delta_type or partial_history)
2871
2438
 
2872
 
        match_dict = {}
2873
 
        if match:
2874
 
            match_dict[''] = match
2875
 
        if match_message:
2876
 
            match_dict['message'] = match_message
2877
 
        if match_committer:
2878
 
            match_dict['committer'] = match_committer
2879
 
        if match_author:
2880
 
            match_dict['author'] = match_author
2881
 
        if match_bugs:
2882
 
            match_dict['bugs'] = match_bugs
2883
 
 
2884
2439
        # Build the LogRequest and execute it
2885
2440
        if len(file_ids) == 0:
2886
2441
            file_ids = None
2889
2444
            start_revision=rev1, end_revision=rev2, limit=limit,
2890
2445
            message_search=message, delta_type=delta_type,
2891
2446
            diff_type=diff_type, _match_using_deltas=match_using_deltas,
2892
 
            exclude_common_ancestry=exclude_common_ancestry, match=match_dict,
2893
 
            signature=signatures, omit_merges=omit_merges,
 
2447
            exclude_common_ancestry=exclude_common_ancestry,
2894
2448
            )
2895
2449
        Logger(b, rqst).show(lf)
2896
2450
 
2913
2467
            # b is taken from revision[0].get_branch(), and
2914
2468
            # show_log will use its revision_history. Having
2915
2469
            # different branches will lead to weird behaviors.
2916
 
            raise errors.BzrCommandError(gettext(
 
2470
            raise errors.BzrCommandError(
2917
2471
                "bzr %s doesn't accept two revisions in different"
2918
 
                " branches.") % command_name)
 
2472
                " branches." % command_name)
2919
2473
        if start_spec.spec is None:
2920
2474
            # Avoid loading all the history.
2921
2475
            rev1 = RevisionInfo(branch, None, None)
2929
2483
        else:
2930
2484
            rev2 = end_spec.in_history(branch)
2931
2485
    else:
2932
 
        raise errors.BzrCommandError(gettext(
2933
 
            'bzr %s --revision takes one or two values.') % command_name)
 
2486
        raise errors.BzrCommandError(
 
2487
            'bzr %s --revision takes one or two values.' % command_name)
2934
2488
    return rev1, rev2
2935
2489
 
2936
2490
 
3007
2561
            null=False, kind=None, show_ids=False, path=None, directory=None):
3008
2562
 
3009
2563
        if kind and kind not in ('file', 'directory', 'symlink'):
3010
 
            raise errors.BzrCommandError(gettext('invalid kind specified'))
 
2564
            raise errors.BzrCommandError('invalid kind specified')
3011
2565
 
3012
2566
        if verbose and null:
3013
 
            raise errors.BzrCommandError(gettext('Cannot set both --verbose and --null'))
 
2567
            raise errors.BzrCommandError('Cannot set both --verbose and --null')
3014
2568
        all = not (unknown or versioned or ignored)
3015
2569
 
3016
2570
        selection = {'I':ignored, '?':unknown, 'V':versioned}
3019
2573
            fs_path = '.'
3020
2574
        else:
3021
2575
            if from_root:
3022
 
                raise errors.BzrCommandError(gettext('cannot specify both --from-root'
3023
 
                                             ' and PATH'))
 
2576
                raise errors.BzrCommandError('cannot specify both --from-root'
 
2577
                                             ' and PATH')
3024
2578
            fs_path = path
3025
2579
        tree, branch, relpath = \
3026
2580
            _open_directory_or_containing_tree_or_branch(fs_path, directory)
3042
2596
            if view_files:
3043
2597
                apply_view = True
3044
2598
                view_str = views.view_display_str(view_files)
3045
 
                note(gettext("Ignoring files outside view. View is %s") % view_str)
 
2599
                note("Ignoring files outside view. View is %s" % view_str)
3046
2600
 
3047
2601
        self.add_cleanup(tree.lock_read().unlock)
3048
2602
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
3172
2726
            bzr ignore "RE:(?!debian/).*"
3173
2727
        
3174
2728
        Ignore everything except the "local" toplevel directory,
3175
 
        but always ignore autosave files ending in ~, even under local/::
 
2729
        but always ignore "*~" autosave files, even under local/::
3176
2730
        
3177
2731
            bzr ignore "*"
3178
2732
            bzr ignore "!./local"
3195
2749
                self.outf.write("%s\n" % pattern)
3196
2750
            return
3197
2751
        if not name_pattern_list:
3198
 
            raise errors.BzrCommandError(gettext("ignore requires at least one "
3199
 
                "NAME_PATTERN or --default-rules."))
 
2752
            raise errors.BzrCommandError("ignore requires at least one "
 
2753
                "NAME_PATTERN or --default-rules.")
3200
2754
        name_pattern_list = [globbing.normalize_pattern(p)
3201
2755
                             for p in name_pattern_list]
3202
2756
        bad_patterns = ''
3203
 
        bad_patterns_count = 0
3204
2757
        for p in name_pattern_list:
3205
2758
            if not globbing.Globster.is_pattern_valid(p):
3206
 
                bad_patterns_count += 1
3207
2759
                bad_patterns += ('\n  %s' % p)
3208
2760
        if bad_patterns:
3209
 
            msg = (ngettext('Invalid ignore pattern found. %s', 
3210
 
                            'Invalid ignore patterns found. %s',
3211
 
                            bad_patterns_count) % bad_patterns)
 
2761
            msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
3212
2762
            ui.ui_factory.show_error(msg)
3213
2763
            raise errors.InvalidPattern('')
3214
2764
        for name_pattern in name_pattern_list:
3215
2765
            if (name_pattern[0] == '/' or
3216
2766
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
3217
 
                raise errors.BzrCommandError(gettext(
3218
 
                    "NAME_PATTERN should not be an absolute path"))
 
2767
                raise errors.BzrCommandError(
 
2768
                    "NAME_PATTERN should not be an absolute path")
3219
2769
        tree, relpath = WorkingTree.open_containing(directory)
3220
2770
        ignores.tree_ignores_add_patterns(tree, name_pattern_list)
3221
2771
        ignored = globbing.Globster(name_pattern_list)
3228
2778
                if ignored.match(filename):
3229
2779
                    matches.append(filename)
3230
2780
        if len(matches) > 0:
3231
 
            self.outf.write(gettext("Warning: the following files are version "
3232
 
                  "controlled and match your ignore pattern:\n%s"
 
2781
            self.outf.write("Warning: the following files are version controlled and"
 
2782
                  " match your ignore pattern:\n%s"
3233
2783
                  "\nThese files will continue to be version controlled"
3234
 
                  " unless you 'bzr remove' them.\n") % ("\n".join(matches),))
 
2784
                  " unless you 'bzr remove' them.\n" % ("\n".join(matches),))
3235
2785
 
3236
2786
 
3237
2787
class cmd_ignored(Command):
3276
2826
        try:
3277
2827
            revno = int(revno)
3278
2828
        except ValueError:
3279
 
            raise errors.BzrCommandError(gettext("not a valid revision-number: %r")
 
2829
            raise errors.BzrCommandError("not a valid revision-number: %r"
3280
2830
                                         % revno)
3281
2831
        revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
3282
2832
        self.outf.write("%s\n" % revid)
3310
2860
         zip                          .zip
3311
2861
      =================       =========================
3312
2862
    """
3313
 
    encoding = 'exact'
3314
2863
    takes_args = ['dest', 'branch_or_subdir?']
3315
2864
    takes_options = ['directory',
3316
2865
        Option('format',
3325
2874
        Option('per-file-timestamps',
3326
2875
               help='Set modification time of files to that of the last '
3327
2876
                    'revision in which it was changed.'),
3328
 
        Option('uncommitted',
3329
 
               help='Export the working tree contents rather than that of the '
3330
 
                    'last revision.'),
3331
2877
        ]
3332
2878
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3333
 
        root=None, filters=False, per_file_timestamps=False, uncommitted=False,
3334
 
        directory=u'.'):
 
2879
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
3335
2880
        from bzrlib.export import export
3336
2881
 
3337
2882
        if branch_or_subdir is None:
3338
 
            branch_or_subdir = directory
3339
 
 
3340
 
        (tree, b, subdir) = controldir.ControlDir.open_containing_tree_or_branch(
3341
 
            branch_or_subdir)
3342
 
        if tree is not None:
3343
 
            self.add_cleanup(tree.lock_read().unlock)
3344
 
 
3345
 
        if uncommitted:
3346
 
            if tree is None:
3347
 
                raise errors.BzrCommandError(
3348
 
                    gettext("--uncommitted requires a working tree"))
3349
 
            export_tree = tree
 
2883
            tree = WorkingTree.open_containing(directory)[0]
 
2884
            b = tree.branch
 
2885
            subdir = None
3350
2886
        else:
3351
 
            export_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
 
2887
            b, subdir = Branch.open_containing(branch_or_subdir)
 
2888
            tree = None
 
2889
 
 
2890
        rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
3352
2891
        try:
3353
 
            export(export_tree, dest, format, root, subdir, filtered=filters,
 
2892
            export(rev_tree, dest, format, root, subdir, filtered=filters,
3354
2893
                   per_file_timestamps=per_file_timestamps)
3355
2894
        except errors.NoSuchExportFormat, e:
3356
 
            raise errors.BzrCommandError(
3357
 
                gettext('Unsupported export format: %s') % e.format)
 
2895
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
3358
2896
 
3359
2897
 
3360
2898
class cmd_cat(Command):
3380
2918
    def run(self, filename, revision=None, name_from_revision=False,
3381
2919
            filters=False, directory=None):
3382
2920
        if revision is not None and len(revision) != 1:
3383
 
            raise errors.BzrCommandError(gettext("bzr cat --revision takes exactly"
3384
 
                                         " one revision specifier"))
 
2921
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
 
2922
                                         " one revision specifier")
3385
2923
        tree, branch, relpath = \
3386
2924
            _open_directory_or_containing_tree_or_branch(filename, directory)
3387
2925
        self.add_cleanup(branch.lock_read().unlock)
3397
2935
 
3398
2936
        old_file_id = rev_tree.path2id(relpath)
3399
2937
 
3400
 
        # TODO: Split out this code to something that generically finds the
3401
 
        # best id for a path across one or more trees; it's like
3402
 
        # find_ids_across_trees but restricted to find just one. -- mbp
3403
 
        # 20110705.
3404
2938
        if name_from_revision:
3405
2939
            # Try in revision if requested
3406
2940
            if old_file_id is None:
3407
 
                raise errors.BzrCommandError(gettext(
3408
 
                    "{0!r} is not present in revision {1}").format(
 
2941
                raise errors.BzrCommandError(
 
2942
                    "%r is not present in revision %s" % (
3409
2943
                        filename, rev_tree.get_revision_id()))
3410
2944
            else:
3411
 
                actual_file_id = old_file_id
 
2945
                content = rev_tree.get_file_text(old_file_id)
3412
2946
        else:
3413
2947
            cur_file_id = tree.path2id(relpath)
3414
 
            if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3415
 
                actual_file_id = cur_file_id
3416
 
            elif old_file_id is not None:
3417
 
                actual_file_id = old_file_id
3418
 
            else:
3419
 
                raise errors.BzrCommandError(gettext(
3420
 
                    "{0!r} is not present in revision {1}").format(
 
2948
            found = False
 
2949
            if cur_file_id is not None:
 
2950
                # Then try with the actual file id
 
2951
                try:
 
2952
                    content = rev_tree.get_file_text(cur_file_id)
 
2953
                    found = True
 
2954
                except errors.NoSuchId:
 
2955
                    # The actual file id didn't exist at that time
 
2956
                    pass
 
2957
            if not found and old_file_id is not None:
 
2958
                # Finally try with the old file id
 
2959
                content = rev_tree.get_file_text(old_file_id)
 
2960
                found = True
 
2961
            if not found:
 
2962
                # Can't be found anywhere
 
2963
                raise errors.BzrCommandError(
 
2964
                    "%r is not present in revision %s" % (
3421
2965
                        filename, rev_tree.get_revision_id()))
3422
2966
        if filtered:
3423
 
            from bzrlib.filter_tree import ContentFilterTree
3424
 
            filter_tree = ContentFilterTree(rev_tree,
3425
 
                rev_tree._content_filter_stack)
3426
 
            content = filter_tree.get_file_text(actual_file_id)
 
2967
            from bzrlib.filters import (
 
2968
                ContentFilterContext,
 
2969
                filtered_output_bytes,
 
2970
                )
 
2971
            filters = rev_tree._content_filter_stack(relpath)
 
2972
            chunks = content.splitlines(True)
 
2973
            content = filtered_output_bytes(chunks, filters,
 
2974
                ContentFilterContext(relpath, rev_tree))
 
2975
            self.cleanup_now()
 
2976
            self.outf.writelines(content)
3427
2977
        else:
3428
 
            content = rev_tree.get_file_text(actual_file_id)
3429
 
        self.cleanup_now()
3430
 
        self.outf.write(content)
 
2978
            self.cleanup_now()
 
2979
            self.outf.write(content)
3431
2980
 
3432
2981
 
3433
2982
class cmd_local_time_offset(Command):
3494
3043
      to trigger updates to external systems like bug trackers. The --fixes
3495
3044
      option can be used to record the association between a revision and
3496
3045
      one or more bugs. See ``bzr help bugs`` for details.
 
3046
 
 
3047
      A selective commit may fail in some cases where the committed
 
3048
      tree would be invalid. Consider::
 
3049
  
 
3050
        bzr init foo
 
3051
        mkdir foo/bar
 
3052
        bzr add foo/bar
 
3053
        bzr commit foo -m "committing foo"
 
3054
        bzr mv foo/bar foo/baz
 
3055
        mkdir foo/bar
 
3056
        bzr add foo/bar
 
3057
        bzr commit foo/bar -m "committing bar but not baz"
 
3058
  
 
3059
      In the example above, the last commit will fail by design. This gives
 
3060
      the user the opportunity to decide whether they want to commit the
 
3061
      rename at the same time, separately first, or not at all. (As a general
 
3062
      rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
3497
3063
    """
 
3064
    # TODO: Run hooks on tree to-be-committed, and after commit.
 
3065
 
 
3066
    # TODO: Strict commit that fails if there are deleted files.
 
3067
    #       (what does "deleted files" mean ??)
 
3068
 
 
3069
    # TODO: Give better message for -s, --summary, used by tla people
 
3070
 
 
3071
    # XXX: verbose currently does nothing
3498
3072
 
3499
3073
    _see_also = ['add', 'bugs', 'hooks', 'uncommit']
3500
3074
    takes_args = ['selected*']
3532
3106
             Option('show-diff', short_name='p',
3533
3107
                    help='When no message is supplied, show the diff along'
3534
3108
                    ' with the status summary in the message editor.'),
3535
 
             Option('lossy', 
3536
 
                    help='When committing to a foreign version control '
3537
 
                    'system do not push data that can not be natively '
3538
 
                    'represented.'),
3539
3109
             ]
3540
3110
    aliases = ['ci', 'checkin']
3541
3111
 
3542
3112
    def _iter_bug_fix_urls(self, fixes, branch):
3543
 
        default_bugtracker  = None
3544
3113
        # Configure the properties for bug fixing attributes.
3545
3114
        for fixed_bug in fixes:
3546
3115
            tokens = fixed_bug.split(':')
3547
 
            if len(tokens) == 1:
3548
 
                if default_bugtracker is None:
3549
 
                    branch_config = branch.get_config_stack()
3550
 
                    default_bugtracker = branch_config.get(
3551
 
                        "bugtracker")
3552
 
                if default_bugtracker is None:
3553
 
                    raise errors.BzrCommandError(gettext(
3554
 
                        "No tracker specified for bug %s. Use the form "
3555
 
                        "'tracker:id' or specify a default bug tracker "
3556
 
                        "using the `bugtracker` option.\nSee "
3557
 
                        "\"bzr help bugs\" for more information on this "
3558
 
                        "feature. Commit refused.") % fixed_bug)
3559
 
                tag = default_bugtracker
3560
 
                bug_id = tokens[0]
3561
 
            elif len(tokens) != 2:
3562
 
                raise errors.BzrCommandError(gettext(
 
3116
            if len(tokens) != 2:
 
3117
                raise errors.BzrCommandError(
3563
3118
                    "Invalid bug %s. Must be in the form of 'tracker:id'. "
3564
3119
                    "See \"bzr help bugs\" for more information on this "
3565
 
                    "feature.\nCommit refused.") % fixed_bug)
3566
 
            else:
3567
 
                tag, bug_id = tokens
 
3120
                    "feature.\nCommit refused." % fixed_bug)
 
3121
            tag, bug_id = tokens
3568
3122
            try:
3569
3123
                yield bugtracker.get_bug_url(tag, branch, bug_id)
3570
3124
            except errors.UnknownBugTrackerAbbreviation:
3571
 
                raise errors.BzrCommandError(gettext(
3572
 
                    'Unrecognized bug %s. Commit refused.') % fixed_bug)
 
3125
                raise errors.BzrCommandError(
 
3126
                    'Unrecognized bug %s. Commit refused.' % fixed_bug)
3573
3127
            except errors.MalformedBugIdentifier, e:
3574
 
                raise errors.BzrCommandError(gettext(
3575
 
                    "%s\nCommit refused.") % (str(e),))
 
3128
                raise errors.BzrCommandError(
 
3129
                    "%s\nCommit refused." % (str(e),))
3576
3130
 
3577
3131
    def run(self, message=None, file=None, verbose=False, selected_list=None,
3578
3132
            unchanged=False, strict=False, local=False, fixes=None,
3579
 
            author=None, show_diff=False, exclude=None, commit_time=None,
3580
 
            lossy=False):
 
3133
            author=None, show_diff=False, exclude=None, commit_time=None):
3581
3134
        from bzrlib.errors import (
3582
3135
            PointlessCommit,
3583
3136
            ConflictsInTree,
3586
3139
        from bzrlib.msgeditor import (
3587
3140
            edit_commit_message_encoded,
3588
3141
            generate_commit_message_template,
3589
 
            make_commit_message_template_encoded,
3590
 
            set_commit_message,
 
3142
            make_commit_message_template_encoded
3591
3143
        )
3592
3144
 
3593
3145
        commit_stamp = offset = None
3595
3147
            try:
3596
3148
                commit_stamp, offset = timestamp.parse_patch_date(commit_time)
3597
3149
            except ValueError, e:
3598
 
                raise errors.BzrCommandError(gettext(
3599
 
                    "Could not parse --commit-time: " + str(e)))
 
3150
                raise errors.BzrCommandError(
 
3151
                    "Could not parse --commit-time: " + str(e))
 
3152
 
 
3153
        # TODO: Need a blackbox test for invoking the external editor; may be
 
3154
        # slightly problematic to run this cross-platform.
 
3155
 
 
3156
        # TODO: do more checks that the commit will succeed before
 
3157
        # spending the user's valuable time typing a commit message.
3600
3158
 
3601
3159
        properties = {}
3602
3160
 
3635
3193
                message = message.replace('\r\n', '\n')
3636
3194
                message = message.replace('\r', '\n')
3637
3195
            if file:
3638
 
                raise errors.BzrCommandError(gettext(
3639
 
                    "please specify either --message or --file"))
 
3196
                raise errors.BzrCommandError(
 
3197
                    "please specify either --message or --file")
3640
3198
 
3641
3199
        def get_message(commit_obj):
3642
3200
            """Callback to get commit message"""
3659
3217
                # make_commit_message_template_encoded returns user encoding.
3660
3218
                # We probably want to be using edit_commit_message instead to
3661
3219
                # avoid this.
3662
 
                my_message = set_commit_message(commit_obj)
3663
 
                if my_message is None:
3664
 
                    start_message = generate_commit_message_template(commit_obj)
3665
 
                    my_message = edit_commit_message_encoded(text,
3666
 
                        start_message=start_message)
3667
 
                if my_message is None:
3668
 
                    raise errors.BzrCommandError(gettext("please specify a commit"
3669
 
                        " message with either --message or --file"))
3670
 
                if my_message == "":
3671
 
                    raise errors.BzrCommandError(gettext("Empty commit message specified."
3672
 
                            " Please specify a commit message with either"
3673
 
                            " --message or --file or leave a blank message"
3674
 
                            " with --message \"\"."))
 
3220
                start_message = generate_commit_message_template(commit_obj)
 
3221
                my_message = edit_commit_message_encoded(text,
 
3222
                    start_message=start_message)
 
3223
                if my_message is None:
 
3224
                    raise errors.BzrCommandError("please specify a commit"
 
3225
                        " message with either --message or --file")
 
3226
            if my_message == "":
 
3227
                raise errors.BzrCommandError("empty commit message specified")
3675
3228
            return my_message
3676
3229
 
3677
3230
        # The API permits a commit with a filter of [] to mean 'select nothing'
3685
3238
                        reporter=None, verbose=verbose, revprops=properties,
3686
3239
                        authors=author, timestamp=commit_stamp,
3687
3240
                        timezone=offset,
3688
 
                        exclude=tree.safe_relpath_files(exclude),
3689
 
                        lossy=lossy)
 
3241
                        exclude=tree.safe_relpath_files(exclude))
3690
3242
        except PointlessCommit:
3691
 
            raise errors.BzrCommandError(gettext("No changes to commit."
3692
 
                " Please 'bzr add' the files you want to commit, or use"
3693
 
                " --unchanged to force an empty commit."))
 
3243
            raise errors.BzrCommandError("No changes to commit."
 
3244
                              " Use --unchanged to commit anyhow.")
3694
3245
        except ConflictsInTree:
3695
 
            raise errors.BzrCommandError(gettext('Conflicts detected in working '
 
3246
            raise errors.BzrCommandError('Conflicts detected in working '
3696
3247
                'tree.  Use "bzr conflicts" to list, "bzr resolve FILE" to'
3697
 
                ' resolve.'))
 
3248
                ' resolve.')
3698
3249
        except StrictCommitFailed:
3699
 
            raise errors.BzrCommandError(gettext("Commit refused because there are"
3700
 
                              " unknown files in the working tree."))
 
3250
            raise errors.BzrCommandError("Commit refused because there are"
 
3251
                              " unknown files in the working tree.")
3701
3252
        except errors.BoundBranchOutOfDate, e:
3702
 
            e.extra_help = (gettext("\n"
 
3253
            e.extra_help = ("\n"
3703
3254
                'To commit to master branch, run update and then commit.\n'
3704
3255
                'You can also pass --local to commit to continue working '
3705
 
                'disconnected.'))
 
3256
                'disconnected.')
3706
3257
            raise
3707
3258
 
3708
3259
 
3792
3343
    a one way process (e.g. changing from the 1.x default to the
3793
3344
    2.x default) so downgrading is not always possible.
3794
3345
 
3795
 
    A backup.bzr.~#~ directory is created at the start of the conversion
3796
 
    process (where # is a number). By default, this is left there on
3797
 
    completion. If the conversion fails, delete the new .bzr directory
3798
 
    and rename this one back in its place. Use the --clean option to ask
3799
 
    for the backup.bzr directory to be removed on successful conversion.
3800
 
    Alternatively, you can delete it by hand if everything looks good
3801
 
    afterwards.
 
3346
    A backup.bzr directory is created at the start of the conversion
 
3347
    process. By default, this is left there on completion. If the
 
3348
    conversion fails, delete the new .bzr directory and rename this
 
3349
    one back in its place. Use the --clean option to ask for the
 
3350
    backup.bzr directory to be removed on successful conversion.
 
3351
    Alternatively, you can delete it by hand if everything looks
 
3352
    good afterwards.
3802
3353
 
3803
3354
    If the location given is a shared repository, dependent branches
3804
3355
    are also converted provided the repository converts successfully.
3805
3356
    If the conversion of a branch fails, remaining branches are still
3806
3357
    tried.
3807
3358
 
3808
 
    For more information on upgrades, see the Bazaar Upgrade Guide,
 
3359
    For more information on upgrades, see the Bazaar 2.0 Upgrade Guide,
3809
3360
    http://doc.bazaar.canonical.com/latest/en/upgrade-guide/.
3810
3361
    """
3811
3362
 
3815
3366
        RegistryOption('format',
3816
3367
            help='Upgrade to a specific format.  See "bzr help'
3817
3368
                 ' formats" for details.',
3818
 
            lazy_registry=('bzrlib.controldir', 'format_registry'),
3819
 
            converter=lambda name: controldir.format_registry.make_bzrdir(name),
 
3369
            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
 
3370
            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
3820
3371
            value_switches=True, title='Branch format'),
3821
3372
        Option('clean',
3822
3373
            help='Remove the backup.bzr directory if successful.'),
3829
3380
        exceptions = upgrade(url, format, clean_up=clean, dry_run=dry_run)
3830
3381
        if exceptions:
3831
3382
            if len(exceptions) == 1:
3832
 
                # Compatibility with historical behavior
 
3383
                # This provides backwards compatibility
3833
3384
                raise exceptions[0]
3834
3385
            else:
3835
3386
                return 3
3863
3414
            if directory is None:
3864
3415
                # use branch if we're inside one; otherwise global config
3865
3416
                try:
3866
 
                    c = Branch.open_containing(u'.')[0].get_config_stack()
 
3417
                    c = Branch.open_containing(u'.')[0].get_config()
3867
3418
                except errors.NotBranchError:
3868
 
                    c = _mod_config.GlobalStack()
 
3419
                    c = _mod_config.GlobalConfig()
3869
3420
            else:
3870
 
                c = Branch.open(directory).get_config_stack()
3871
 
            identity = c.get('email')
 
3421
                c = Branch.open(directory).get_config()
3872
3422
            if email:
3873
 
                self.outf.write(_mod_config.extract_email_address(identity)
3874
 
                                + '\n')
 
3423
                self.outf.write(c.user_email() + '\n')
3875
3424
            else:
3876
 
                self.outf.write(identity + '\n')
 
3425
                self.outf.write(c.username() + '\n')
3877
3426
            return
3878
3427
 
3879
 
        if email:
3880
 
            raise errors.BzrCommandError(gettext("--email can only be used to display existing "
3881
 
                                         "identity"))
3882
 
 
3883
3428
        # display a warning if an email address isn't included in the given name.
3884
3429
        try:
3885
3430
            _mod_config.extract_email_address(name)
3890
3435
        # use global config unless --branch given
3891
3436
        if branch:
3892
3437
            if directory is None:
3893
 
                c = Branch.open_containing(u'.')[0].get_config_stack()
 
3438
                c = Branch.open_containing(u'.')[0].get_config()
3894
3439
            else:
3895
 
                b = Branch.open(directory)
3896
 
                self.add_cleanup(b.lock_write().unlock)
3897
 
                c = b.get_config_stack()
 
3440
                c = Branch.open(directory).get_config()
3898
3441
        else:
3899
 
            c = _mod_config.GlobalStack()
3900
 
        c.set('email', name)
 
3442
            c = _mod_config.GlobalConfig()
 
3443
        c.set_user_option('email', name)
3901
3444
 
3902
3445
 
3903
3446
class cmd_nick(Command):
3904
3447
    __doc__ = """Print or set the branch nickname.
3905
3448
 
3906
 
    If unset, the colocated branch name is used for colocated branches, and
3907
 
    the branch directory name is used for other branches.  To print the
3908
 
    current nickname, execute with no argument.
 
3449
    If unset, the tree root directory name is used as the nickname.
 
3450
    To print the current nickname, execute with no argument.
3909
3451
 
3910
3452
    Bound branches use the nickname of its master branch unless it is set
3911
3453
    locally.
3966
3508
 
3967
3509
    def remove_alias(self, alias_name):
3968
3510
        if alias_name is None:
3969
 
            raise errors.BzrCommandError(gettext(
3970
 
                'bzr alias --remove expects an alias to remove.'))
 
3511
            raise errors.BzrCommandError(
 
3512
                'bzr alias --remove expects an alias to remove.')
3971
3513
        # If alias is not found, print something like:
3972
3514
        # unalias: foo: not found
3973
3515
        c = _mod_config.GlobalConfig()
4052
3594
        if typestring == "sftp":
4053
3595
            from bzrlib.tests import stub_sftp
4054
3596
            return stub_sftp.SFTPAbsoluteServer
4055
 
        elif typestring == "memory":
 
3597
        if typestring == "memory":
4056
3598
            from bzrlib.tests import test_server
4057
3599
            return memory.MemoryServer
4058
 
        elif typestring == "fakenfs":
 
3600
        if typestring == "fakenfs":
4059
3601
            from bzrlib.tests import test_server
4060
3602
            return test_server.FakeNFSServer
4061
3603
        msg = "No known transport type %s. Supported types are: sftp\n" %\
4095
3637
                     Option('randomize', type=str, argname="SEED",
4096
3638
                            help='Randomize the order of tests using the given'
4097
3639
                                 ' seed or "now" for the current time.'),
4098
 
                     ListOption('exclude', type=str, argname="PATTERN",
4099
 
                                short_name='x',
4100
 
                                help='Exclude tests that match this regular'
4101
 
                                ' expression.'),
 
3640
                     Option('exclude', type=str, argname="PATTERN",
 
3641
                            short_name='x',
 
3642
                            help='Exclude tests that match this regular'
 
3643
                                 ' expression.'),
4102
3644
                     Option('subunit',
4103
3645
                        help='Output test progress via subunit.'),
4104
3646
                     Option('strict', help='Fail on missing dependencies or '
4111
3653
                                param_name='starting_with', short_name='s',
4112
3654
                                help=
4113
3655
                                'Load only the tests starting with TESTID.'),
4114
 
                     Option('sync',
4115
 
                            help="By default we disable fsync and fdatasync"
4116
 
                                 " while running the test suite.")
4117
3656
                     ]
4118
3657
    encoding_type = 'replace'
4119
3658
 
4127
3666
            first=False, list_only=False,
4128
3667
            randomize=None, exclude=None, strict=False,
4129
3668
            load_list=None, debugflag=None, starting_with=None, subunit=False,
4130
 
            parallel=None, lsprof_tests=False,
4131
 
            sync=False):
4132
 
 
4133
 
        # During selftest, disallow proxying, as it can cause severe
4134
 
        # performance penalties and is only needed for thread
4135
 
        # safety. The selftest command is assumed to not use threads
4136
 
        # too heavily. The call should be as early as possible, as
4137
 
        # error reporting for past duplicate imports won't have useful
4138
 
        # backtraces.
4139
 
        lazy_import.disallow_proxying()
4140
 
 
 
3669
            parallel=None, lsprof_tests=False):
4141
3670
        from bzrlib import tests
4142
3671
 
4143
3672
        if testspecs_list is not None:
4148
3677
            try:
4149
3678
                from bzrlib.tests import SubUnitBzrRunner
4150
3679
            except ImportError:
4151
 
                raise errors.BzrCommandError(gettext("subunit not available. subunit "
4152
 
                    "needs to be installed to use --subunit."))
 
3680
                raise errors.BzrCommandError("subunit not available. subunit "
 
3681
                    "needs to be installed to use --subunit.")
4153
3682
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
4154
3683
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
4155
3684
            # stdout, which would corrupt the subunit stream. 
4164
3693
            self.additional_selftest_args.setdefault(
4165
3694
                'suite_decorators', []).append(parallel)
4166
3695
        if benchmark:
4167
 
            raise errors.BzrCommandError(gettext(
 
3696
            raise errors.BzrCommandError(
4168
3697
                "--benchmark is no longer supported from bzr 2.2; "
4169
 
                "use bzr-usertest instead"))
 
3698
                "use bzr-usertest instead")
4170
3699
        test_suite_factory = None
4171
 
        if not exclude:
4172
 
            exclude_pattern = None
4173
 
        else:
4174
 
            exclude_pattern = '(' + '|'.join(exclude) + ')'
4175
 
        if not sync:
4176
 
            self._disable_fsync()
4177
3700
        selftest_kwargs = {"verbose": verbose,
4178
3701
                          "pattern": pattern,
4179
3702
                          "stop_on_failure": one,
4184
3707
                          "matching_tests_first": first,
4185
3708
                          "list_only": list_only,
4186
3709
                          "random_seed": randomize,
4187
 
                          "exclude_pattern": exclude_pattern,
 
3710
                          "exclude_pattern": exclude,
4188
3711
                          "strict": strict,
4189
3712
                          "load_list": load_list,
4190
3713
                          "debug_flags": debugflag,
4201
3724
            cleanup()
4202
3725
        return int(not result)
4203
3726
 
4204
 
    def _disable_fsync(self):
4205
 
        """Change the 'os' functionality to not synchronize."""
4206
 
        self._orig_fsync = getattr(os, 'fsync', None)
4207
 
        if self._orig_fsync is not None:
4208
 
            os.fsync = lambda filedes: None
4209
 
        self._orig_fdatasync = getattr(os, 'fdatasync', None)
4210
 
        if self._orig_fdatasync is not None:
4211
 
            os.fdatasync = lambda filedes: None
4212
 
 
4213
3727
 
4214
3728
class cmd_version(Command):
4215
3729
    __doc__ = """Show version of bzr."""
4235
3749
 
4236
3750
    @display_command
4237
3751
    def run(self):
4238
 
        self.outf.write(gettext("It sure does!\n"))
 
3752
        self.outf.write("It sure does!\n")
4239
3753
 
4240
3754
 
4241
3755
class cmd_find_merge_base(Command):
4259
3773
        graph = branch1.repository.get_graph(branch2.repository)
4260
3774
        base_rev_id = graph.find_unique_lca(last1, last2)
4261
3775
 
4262
 
        self.outf.write(gettext('merge base is revision %s\n') % base_rev_id)
 
3776
        self.outf.write('merge base is revision %s\n' % base_rev_id)
4263
3777
 
4264
3778
 
4265
3779
class cmd_merge(Command):
4268
3782
    The source of the merge can be specified either in the form of a branch,
4269
3783
    or in the form of a path to a file containing a merge directive generated
4270
3784
    with bzr send. If neither is specified, the default is the upstream branch
4271
 
    or the branch most recently merged using --remember.  The source of the
4272
 
    merge may also be specified in the form of a path to a file in another
4273
 
    branch:  in this case, only the modifications to that file are merged into
4274
 
    the current working tree.
 
3785
    or the branch most recently merged using --remember.
4275
3786
 
4276
3787
    When merging from a branch, by default bzr will try to merge in all new
4277
3788
    work from the other branch, automatically determining an appropriate base
4284
3795
    through OTHER, excluding BASE but including OTHER, will be merged.  If this
4285
3796
    causes some revisions to be skipped, i.e. if the destination branch does
4286
3797
    not already contain revision BASE, such a merge is commonly referred to as
4287
 
    a "cherrypick". Unlike a normal merge, Bazaar does not currently track
4288
 
    cherrypicks. The changes look like a normal commit, and the history of the
4289
 
    changes from the other branch is not stored in the commit.
 
3798
    a "cherrypick".
4290
3799
 
4291
3800
    Revision numbers are always relative to the source branch.
4292
3801
 
4293
3802
    Merge will do its best to combine the changes in two branches, but there
4294
3803
    are some kinds of problems only a human can fix.  When it encounters those,
4295
3804
    it will mark a conflict.  A conflict means that you need to fix something,
4296
 
    before you can commit.
 
3805
    before you should commit.
4297
3806
 
4298
3807
    Use bzr resolve when you have fixed a problem.  See also bzr conflicts.
4299
3808
 
4300
 
    If there is no default branch set, the first merge will set it (use
4301
 
    --no-remember to avoid setting it). After that, you can omit the branch
4302
 
    to use the default.  To change the default, use --remember. The value will
4303
 
    only be saved if the remote location can be accessed.
 
3809
    If there is no default branch set, the first merge will set it. After
 
3810
    that, you can omit the branch to use the default.  To change the
 
3811
    default, use --remember. The value will only be saved if the remote
 
3812
    location can be accessed.
4304
3813
 
4305
3814
    The results of the merge are placed into the destination working
4306
3815
    directory, where they can be reviewed (with bzr diff), tested, and then
4307
3816
    committed to record the result of the merge.
4308
3817
 
4309
3818
    merge refuses to run if there are any uncommitted changes, unless
4310
 
    --force is given.  If --force is given, then the changes from the source 
4311
 
    will be merged with the current working tree, including any uncommitted
4312
 
    changes in the tree.  The --force option can also be used to create a
 
3819
    --force is given. The --force option can also be used to create a
4313
3820
    merge revision which has more than two parents.
4314
3821
 
4315
3822
    If one would like to merge changes from the working tree of the other
4373
3880
    ]
4374
3881
 
4375
3882
    def run(self, location=None, revision=None, force=False,
4376
 
            merge_type=None, show_base=False, reprocess=None, remember=None,
 
3883
            merge_type=None, show_base=False, reprocess=None, remember=False,
4377
3884
            uncommitted=False, pull=False,
4378
3885
            directory=None,
4379
3886
            preview=False,
4387
3894
        merger = None
4388
3895
        allow_pending = True
4389
3896
        verified = 'inapplicable'
4390
 
 
4391
3897
        tree = WorkingTree.open_containing(directory)[0]
4392
 
        if tree.branch.revno() == 0:
4393
 
            raise errors.BzrCommandError(gettext('Merging into empty branches not currently supported, '
4394
 
                                         'https://bugs.launchpad.net/bzr/+bug/308562'))
4395
3898
 
4396
3899
        try:
4397
3900
            basis_tree = tree.revision_tree(tree.last_revision())
4417
3920
                mergeable = None
4418
3921
            else:
4419
3922
                if uncommitted:
4420
 
                    raise errors.BzrCommandError(gettext('Cannot use --uncommitted'
4421
 
                        ' with bundles or merge directives.'))
 
3923
                    raise errors.BzrCommandError('Cannot use --uncommitted'
 
3924
                        ' with bundles or merge directives.')
4422
3925
 
4423
3926
                if revision is not None:
4424
 
                    raise errors.BzrCommandError(gettext(
4425
 
                        'Cannot use -r with merge directives or bundles'))
 
3927
                    raise errors.BzrCommandError(
 
3928
                        'Cannot use -r with merge directives or bundles')
4426
3929
                merger, verified = _mod_merge.Merger.from_mergeable(tree,
4427
3930
                   mergeable, None)
4428
3931
 
4429
3932
        if merger is None and uncommitted:
4430
3933
            if revision is not None and len(revision) > 0:
4431
 
                raise errors.BzrCommandError(gettext('Cannot use --uncommitted and'
4432
 
                    ' --revision at the same time.'))
 
3934
                raise errors.BzrCommandError('Cannot use --uncommitted and'
 
3935
                    ' --revision at the same time.')
4433
3936
            merger = self.get_merger_from_uncommitted(tree, location, None)
4434
3937
            allow_pending = False
4435
3938
 
4443
3946
        self.sanity_check_merger(merger)
4444
3947
        if (merger.base_rev_id == merger.other_rev_id and
4445
3948
            merger.other_rev_id is not None):
4446
 
            # check if location is a nonexistent file (and not a branch) to
4447
 
            # disambiguate the 'Nothing to do'
4448
 
            if merger.interesting_files:
4449
 
                if not merger.other_tree.has_filename(
4450
 
                    merger.interesting_files[0]):
4451
 
                    note(gettext("merger: ") + str(merger))
4452
 
                    raise errors.PathsDoNotExist([location])
4453
 
            note(gettext('Nothing to do.'))
 
3949
            note('Nothing to do.')
4454
3950
            return 0
4455
 
        if pull and not preview:
 
3951
        if pull:
4456
3952
            if merger.interesting_files is not None:
4457
 
                raise errors.BzrCommandError(gettext('Cannot pull individual files'))
 
3953
                raise errors.BzrCommandError('Cannot pull individual files')
4458
3954
            if (merger.base_rev_id == tree.last_revision()):
4459
3955
                result = tree.pull(merger.other_branch, False,
4460
3956
                                   merger.other_rev_id)
4461
3957
                result.report(self.outf)
4462
3958
                return 0
4463
3959
        if merger.this_basis is None:
4464
 
            raise errors.BzrCommandError(gettext(
 
3960
            raise errors.BzrCommandError(
4465
3961
                "This branch has no commits."
4466
 
                " (perhaps you would prefer 'bzr pull')"))
 
3962
                " (perhaps you would prefer 'bzr pull')")
4467
3963
        if preview:
4468
3964
            return self._do_preview(merger)
4469
3965
        elif interactive:
4520
4016
    def sanity_check_merger(self, merger):
4521
4017
        if (merger.show_base and
4522
4018
            not merger.merge_type is _mod_merge.Merge3Merger):
4523
 
            raise errors.BzrCommandError(gettext("Show-base is not supported for this"
4524
 
                                         " merge type. %s") % merger.merge_type)
 
4019
            raise errors.BzrCommandError("Show-base is not supported for this"
 
4020
                                         " merge type. %s" % merger.merge_type)
4525
4021
        if merger.reprocess is None:
4526
4022
            if merger.show_base:
4527
4023
                merger.reprocess = False
4529
4025
                # Use reprocess if the merger supports it
4530
4026
                merger.reprocess = merger.merge_type.supports_reprocess
4531
4027
        if merger.reprocess and not merger.merge_type.supports_reprocess:
4532
 
            raise errors.BzrCommandError(gettext("Conflict reduction is not supported"
4533
 
                                         " for merge type %s.") %
 
4028
            raise errors.BzrCommandError("Conflict reduction is not supported"
 
4029
                                         " for merge type %s." %
4534
4030
                                         merger.merge_type)
4535
4031
        if merger.reprocess and merger.show_base:
4536
 
            raise errors.BzrCommandError(gettext("Cannot do conflict reduction and"
4537
 
                                         " show base."))
 
4032
            raise errors.BzrCommandError("Cannot do conflict reduction and"
 
4033
                                         " show base.")
4538
4034
 
4539
4035
    def _get_merger_from_branch(self, tree, location, revision, remember,
4540
4036
                                possible_transports, pb):
4567
4063
        if other_revision_id is None:
4568
4064
            other_revision_id = _mod_revision.ensure_null(
4569
4065
                other_branch.last_revision())
4570
 
        # Remember where we merge from. We need to remember if:
4571
 
        # - user specify a location (and we don't merge from the parent
4572
 
        #   branch)
4573
 
        # - user ask to remember or there is no previous location set to merge
4574
 
        #   from and user didn't ask to *not* remember
4575
 
        if (user_location is not None
4576
 
            and ((remember
4577
 
                  or (remember is None
4578
 
                      and tree.branch.get_submit_branch() is None)))):
 
4066
        # Remember where we merge from
 
4067
        if ((remember or tree.branch.get_submit_branch() is None) and
 
4068
             user_location is not None):
4579
4069
            tree.branch.set_submit_branch(other_branch.base)
4580
4070
        # Merge tags (but don't set them in the master branch yet, the user
4581
4071
        # might revert this merge).  Commit will propagate them.
4644
4134
            stored_location_type = "parent"
4645
4135
        mutter("%s", stored_location)
4646
4136
        if stored_location is None:
4647
 
            raise errors.BzrCommandError(gettext("No location specified or remembered"))
 
4137
            raise errors.BzrCommandError("No location specified or remembered")
4648
4138
        display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
4649
 
        note(gettext("{0} remembered {1} location {2}").format(verb_string,
4650
 
                stored_location_type, display_url))
 
4139
        note(u"%s remembered %s location %s", verb_string,
 
4140
                stored_location_type, display_url)
4651
4141
        return stored_location
4652
4142
 
4653
4143
 
4690
4180
        self.add_cleanup(tree.lock_write().unlock)
4691
4181
        parents = tree.get_parent_ids()
4692
4182
        if len(parents) != 2:
4693
 
            raise errors.BzrCommandError(gettext("Sorry, remerge only works after normal"
 
4183
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
4694
4184
                                         " merges.  Not cherrypicking or"
4695
 
                                         " multi-merges."))
 
4185
                                         " multi-merges.")
4696
4186
        repository = tree.branch.repository
4697
4187
        interesting_ids = None
4698
4188
        new_conflicts = []
4707
4197
                if tree.kind(file_id) != "directory":
4708
4198
                    continue
4709
4199
 
4710
 
                # FIXME: Support nested trees
4711
 
                for name, ie in tree.root_inventory.iter_entries(file_id):
 
4200
                for name, ie in tree.inventory.iter_entries(file_id):
4712
4201
                    interesting_ids.add(ie.file_id)
4713
4202
            new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4714
4203
        else:
4747
4236
 
4748
4237
 
4749
4238
class cmd_revert(Command):
4750
 
    __doc__ = """\
4751
 
    Set files in the working tree back to the contents of a previous revision.
 
4239
    __doc__ = """Revert files to a previous revision.
4752
4240
 
4753
4241
    Giving a list of files will revert only those files.  Otherwise, all files
4754
4242
    will be reverted.  If the revision is not specified with '--revision', the
4755
 
    working tree basis revision is used. A revert operation affects only the
4756
 
    working tree, not any revision history like the branch and repository or
4757
 
    the working tree basis revision.
 
4243
    last committed revision is used.
4758
4244
 
4759
4245
    To remove only some changes, without reverting to a prior version, use
4760
 
    merge instead.  For example, "merge . -r -2..-3" (don't forget the ".")
4761
 
    will remove the changes introduced by the second last commit (-2), without
4762
 
    affecting the changes introduced by the last commit (-1).  To remove
4763
 
    certain changes on a hunk-by-hunk basis, see the shelve command.
4764
 
    To update the branch to a specific revision or the latest revision and
4765
 
    update the working tree accordingly while preserving local changes, see the
4766
 
    update command.
 
4246
    merge instead.  For example, "merge . --revision -2..-3" will remove the
 
4247
    changes introduced by -2, without affecting the changes introduced by -1.
 
4248
    Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
4767
4249
 
4768
 
    Uncommitted changes to files that are reverted will be discarded.
4769
 
    Howver, by default, any files that have been manually changed will be
4770
 
    backed up first.  (Files changed only by merge are not backed up.)  Backup
4771
 
    files have '.~#~' appended to their name, where # is a number.
 
4250
    By default, any files that have been manually changed will be backed up
 
4251
    first.  (Files changed only by merge are not backed up.)  Backup files have
 
4252
    '.~#~' appended to their name, where # is a number.
4772
4253
 
4773
4254
    When you provide files, you can use their current pathname or the pathname
4774
4255
    from the target revision.  So you can use revert to "undelete" a file by
4800
4281
    target branches.
4801
4282
    """
4802
4283
 
4803
 
    _see_also = ['cat', 'export', 'merge', 'shelve']
 
4284
    _see_also = ['cat', 'export']
4804
4285
    takes_options = [
4805
4286
        'revision',
4806
4287
        Option('no-backup', "Do not save backups of reverted files."),
4865
4346
 
4866
4347
    @display_command
4867
4348
    def run(self, context=None):
4868
 
        from bzrlib import shellcomplete
 
4349
        import shellcomplete
4869
4350
        shellcomplete.shellcomplete(context)
4870
4351
 
4871
4352
 
4925
4406
            type=_parse_revision_str,
4926
4407
            help='Filter on local branch revisions (inclusive). '
4927
4408
                'See "help revisionspec" for details.'),
4928
 
        Option('include-merged',
 
4409
        Option('include-merges',
4929
4410
               'Show all revisions in addition to the mainline ones.'),
4930
 
        Option('include-merges', hidden=True,
4931
 
               help='Historical alias for --include-merged.'),
4932
4411
        ]
4933
4412
    encoding_type = 'replace'
4934
4413
 
4937
4416
            theirs_only=False,
4938
4417
            log_format=None, long=False, short=False, line=False,
4939
4418
            show_ids=False, verbose=False, this=False, other=False,
4940
 
            include_merged=None, revision=None, my_revision=None,
4941
 
            directory=u'.',
4942
 
            include_merges=symbol_versioning.DEPRECATED_PARAMETER):
 
4419
            include_merges=False, revision=None, my_revision=None,
 
4420
            directory=u'.'):
4943
4421
        from bzrlib.missing import find_unmerged, iter_log_revisions
4944
4422
        def message(s):
4945
4423
            if not is_quiet():
4946
4424
                self.outf.write(s)
4947
4425
 
4948
 
        if symbol_versioning.deprecated_passed(include_merges):
4949
 
            ui.ui_factory.show_user_warning(
4950
 
                'deprecated_command_option',
4951
 
                deprecated_name='--include-merges',
4952
 
                recommended_name='--include-merged',
4953
 
                deprecated_in_version='2.5',
4954
 
                command=self.invoked_as)
4955
 
            if include_merged is None:
4956
 
                include_merged = include_merges
4957
 
            else:
4958
 
                raise errors.BzrCommandError(gettext(
4959
 
                    '{0} and {1} are mutually exclusive').format(
4960
 
                    '--include-merges', '--include-merged'))
4961
 
        if include_merged is None:
4962
 
            include_merged = False
4963
4426
        if this:
4964
4427
            mine_only = this
4965
4428
        if other:
4980
4443
        if other_branch is None:
4981
4444
            other_branch = parent
4982
4445
            if other_branch is None:
4983
 
                raise errors.BzrCommandError(gettext("No peer location known"
4984
 
                                             " or specified."))
 
4446
                raise errors.BzrCommandError("No peer location known"
 
4447
                                             " or specified.")
4985
4448
            display_url = urlutils.unescape_for_display(parent,
4986
4449
                                                        self.outf.encoding)
4987
 
            message(gettext("Using saved parent location: {0}\n").format(
4988
 
                    display_url))
 
4450
            message("Using saved parent location: "
 
4451
                    + display_url + "\n")
4989
4452
 
4990
4453
        remote_branch = Branch.open(other_branch)
4991
4454
        if remote_branch.base == local_branch.base:
5004
4467
        local_extra, remote_extra = find_unmerged(
5005
4468
            local_branch, remote_branch, restrict,
5006
4469
            backward=not reverse,
5007
 
            include_merged=include_merged,
 
4470
            include_merges=include_merges,
5008
4471
            local_revid_range=local_revid_range,
5009
4472
            remote_revid_range=remote_revid_range)
5010
4473
 
5017
4480
 
5018
4481
        status_code = 0
5019
4482
        if local_extra and not theirs_only:
5020
 
            message(ngettext("You have %d extra revision:\n",
5021
 
                             "You have %d extra revisions:\n", 
5022
 
                             len(local_extra)) %
 
4483
            message("You have %d extra revision(s):\n" %
5023
4484
                len(local_extra))
5024
 
            rev_tag_dict = {}
5025
 
            if local_branch.supports_tags():
5026
 
                rev_tag_dict = local_branch.tags.get_reverse_tag_dict()
5027
4485
            for revision in iter_log_revisions(local_extra,
5028
4486
                                local_branch.repository,
5029
 
                                verbose,
5030
 
                                rev_tag_dict):
 
4487
                                verbose):
5031
4488
                lf.log_revision(revision)
5032
4489
            printed_local = True
5033
4490
            status_code = 1
5037
4494
        if remote_extra and not mine_only:
5038
4495
            if printed_local is True:
5039
4496
                message("\n\n\n")
5040
 
            message(ngettext("You are missing %d revision:\n",
5041
 
                             "You are missing %d revisions:\n",
5042
 
                             len(remote_extra)) %
 
4497
            message("You are missing %d revision(s):\n" %
5043
4498
                len(remote_extra))
5044
 
            if remote_branch.supports_tags():
5045
 
                rev_tag_dict = remote_branch.tags.get_reverse_tag_dict()
5046
4499
            for revision in iter_log_revisions(remote_extra,
5047
4500
                                remote_branch.repository,
5048
 
                                verbose,
5049
 
                                rev_tag_dict):
 
4501
                                verbose):
5050
4502
                lf.log_revision(revision)
5051
4503
            status_code = 1
5052
4504
 
5053
4505
        if mine_only and not local_extra:
5054
4506
            # We checked local, and found nothing extra
5055
 
            message(gettext('This branch has no new revisions.\n'))
 
4507
            message('This branch is up to date.\n')
5056
4508
        elif theirs_only and not remote_extra:
5057
4509
            # We checked remote, and found nothing extra
5058
 
            message(gettext('Other branch has no new revisions.\n'))
 
4510
            message('Other branch is up to date.\n')
5059
4511
        elif not (mine_only or theirs_only or local_extra or
5060
4512
                  remote_extra):
5061
4513
            # We checked both branches, and neither one had extra
5062
4514
            # revisions
5063
 
            message(gettext("Branches are up to date.\n"))
 
4515
            message("Branches are up to date.\n")
5064
4516
        self.cleanup_now()
5065
4517
        if not status_code and parent is None and other_branch is not None:
5066
4518
            self.add_cleanup(local_branch.lock_write().unlock)
5096
4548
        ]
5097
4549
 
5098
4550
    def run(self, branch_or_repo='.', clean_obsolete_packs=False):
5099
 
        dir = controldir.ControlDir.open_containing(branch_or_repo)[0]
 
4551
        dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
5100
4552
        try:
5101
4553
            branch = dir.open_branch()
5102
4554
            repository = branch.repository
5128
4580
 
5129
4581
    @display_command
5130
4582
    def run(self, verbose=False):
5131
 
        from bzrlib import plugin
5132
 
        # Don't give writelines a generator as some codecs don't like that
5133
 
        self.outf.writelines(
5134
 
            list(plugin.describe_plugins(show_paths=verbose)))
 
4583
        import bzrlib.plugin
 
4584
        from inspect import getdoc
 
4585
        result = []
 
4586
        for name, plugin in bzrlib.plugin.plugins().items():
 
4587
            version = plugin.__version__
 
4588
            if version == 'unknown':
 
4589
                version = ''
 
4590
            name_ver = '%s %s' % (name, version)
 
4591
            d = getdoc(plugin.module)
 
4592
            if d:
 
4593
                doc = d.split('\n')[0]
 
4594
            else:
 
4595
                doc = '(no description)'
 
4596
            result.append((name_ver, doc, plugin.path()))
 
4597
        for name_ver, doc, path in sorted(result):
 
4598
            self.outf.write("%s\n" % name_ver)
 
4599
            self.outf.write("   %s\n" % doc)
 
4600
            if verbose:
 
4601
                self.outf.write("   %s\n" % path)
 
4602
            self.outf.write("\n")
5135
4603
 
5136
4604
 
5137
4605
class cmd_testament(Command):
5190
4658
    @display_command
5191
4659
    def run(self, filename, all=False, long=False, revision=None,
5192
4660
            show_ids=False, directory=None):
5193
 
        from bzrlib.annotate import (
5194
 
            annotate_file_tree,
5195
 
            )
 
4661
        from bzrlib.annotate import annotate_file, annotate_file_tree
5196
4662
        wt, branch, relpath = \
5197
4663
            _open_directory_or_containing_tree_or_branch(filename, directory)
5198
4664
        if wt is not None:
5201
4667
            self.add_cleanup(branch.lock_read().unlock)
5202
4668
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
5203
4669
        self.add_cleanup(tree.lock_read().unlock)
5204
 
        if wt is not None and revision is None:
 
4670
        if wt is not None:
5205
4671
            file_id = wt.path2id(relpath)
5206
4672
        else:
5207
4673
            file_id = tree.path2id(relpath)
5208
4674
        if file_id is None:
5209
4675
            raise errors.NotVersionedError(filename)
 
4676
        file_version = tree.inventory[file_id].revision
5210
4677
        if wt is not None and revision is None:
5211
4678
            # If there is a tree and we're not annotating historical
5212
4679
            # versions, annotate the working tree's content.
5213
4680
            annotate_file_tree(wt, file_id, self.outf, long, all,
5214
4681
                show_ids=show_ids)
5215
4682
        else:
5216
 
            annotate_file_tree(tree, file_id, self.outf, long, all,
5217
 
                show_ids=show_ids, branch=branch)
 
4683
            annotate_file(branch, file_version, file_id, long, all, self.outf,
 
4684
                          show_ids=show_ids)
5218
4685
 
5219
4686
 
5220
4687
class cmd_re_sign(Command):
5227
4694
 
5228
4695
    def run(self, revision_id_list=None, revision=None, directory=u'.'):
5229
4696
        if revision_id_list is not None and revision is not None:
5230
 
            raise errors.BzrCommandError(gettext('You can only supply one of revision_id or --revision'))
 
4697
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
5231
4698
        if revision_id_list is None and revision is None:
5232
 
            raise errors.BzrCommandError(gettext('You must supply either --revision or a revision_id'))
 
4699
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
5233
4700
        b = WorkingTree.open_containing(directory)[0].branch
5234
4701
        self.add_cleanup(b.lock_write().unlock)
5235
4702
        return self._run(b, revision_id_list, revision)
5236
4703
 
5237
4704
    def _run(self, b, revision_id_list, revision):
5238
4705
        import bzrlib.gpg as gpg
5239
 
        gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
 
4706
        gpg_strategy = gpg.GPGStrategy(b.get_config())
5240
4707
        if revision_id_list is not None:
5241
4708
            b.repository.start_write_group()
5242
4709
            try:
5267
4734
                if to_revid is None:
5268
4735
                    to_revno = b.revno()
5269
4736
                if from_revno is None or to_revno is None:
5270
 
                    raise errors.BzrCommandError(gettext('Cannot sign a range of non-revision-history revisions'))
 
4737
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
5271
4738
                b.repository.start_write_group()
5272
4739
                try:
5273
4740
                    for revno in range(from_revno, to_revno + 1):
5279
4746
                else:
5280
4747
                    b.repository.commit_write_group()
5281
4748
            else:
5282
 
                raise errors.BzrCommandError(gettext('Please supply either one revision, or a range.'))
 
4749
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
5283
4750
 
5284
4751
 
5285
4752
class cmd_bind(Command):
5304
4771
            try:
5305
4772
                location = b.get_old_bound_location()
5306
4773
            except errors.UpgradeRequired:
5307
 
                raise errors.BzrCommandError(gettext('No location supplied.  '
5308
 
                    'This format does not remember old locations.'))
 
4774
                raise errors.BzrCommandError('No location supplied.  '
 
4775
                    'This format does not remember old locations.')
5309
4776
            else:
5310
4777
                if location is None:
5311
4778
                    if b.get_bound_location() is not None:
5312
 
                        raise errors.BzrCommandError(
5313
 
                            gettext('Branch is already bound'))
 
4779
                        raise errors.BzrCommandError('Branch is already bound')
5314
4780
                    else:
5315
 
                        raise errors.BzrCommandError(
5316
 
                            gettext('No location supplied'
5317
 
                                    ' and no previous location known'))
 
4781
                        raise errors.BzrCommandError('No location supplied '
 
4782
                            'and no previous location known')
5318
4783
        b_other = Branch.open(location)
5319
4784
        try:
5320
4785
            b.bind(b_other)
5321
4786
        except errors.DivergedBranches:
5322
 
            raise errors.BzrCommandError(gettext('These branches have diverged.'
5323
 
                                         ' Try merging, and then bind again.'))
 
4787
            raise errors.BzrCommandError('These branches have diverged.'
 
4788
                                         ' Try merging, and then bind again.')
5324
4789
        if b.get_config().has_explicit_nickname():
5325
4790
            b.nick = b_other.nick
5326
4791
 
5339
4804
    def run(self, directory=u'.'):
5340
4805
        b, relpath = Branch.open_containing(directory)
5341
4806
        if not b.unbind():
5342
 
            raise errors.BzrCommandError(gettext('Local branch is not bound'))
 
4807
            raise errors.BzrCommandError('Local branch is not bound')
5343
4808
 
5344
4809
 
5345
4810
class cmd_uncommit(Command):
5366
4831
    takes_options = ['verbose', 'revision',
5367
4832
                    Option('dry-run', help='Don\'t actually make changes.'),
5368
4833
                    Option('force', help='Say yes to all questions.'),
5369
 
                    Option('keep-tags',
5370
 
                           help='Keep tags that point to removed revisions.'),
5371
4834
                    Option('local',
5372
4835
                           help="Only remove the commits from the local branch"
5373
4836
                                " when in a checkout."
5377
4840
    aliases = []
5378
4841
    encoding_type = 'replace'
5379
4842
 
5380
 
    def run(self, location=None, dry_run=False, verbose=False,
5381
 
            revision=None, force=False, local=False, keep_tags=False):
 
4843
    def run(self, location=None,
 
4844
            dry_run=False, verbose=False,
 
4845
            revision=None, force=False, local=False):
5382
4846
        if location is None:
5383
4847
            location = u'.'
5384
 
        control, relpath = controldir.ControlDir.open_containing(location)
 
4848
        control, relpath = bzrdir.BzrDir.open_containing(location)
5385
4849
        try:
5386
4850
            tree = control.open_workingtree()
5387
4851
            b = tree.branch
5393
4857
            self.add_cleanup(tree.lock_write().unlock)
5394
4858
        else:
5395
4859
            self.add_cleanup(b.lock_write().unlock)
5396
 
        return self._run(b, tree, dry_run, verbose, revision, force,
5397
 
                         local, keep_tags)
 
4860
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
5398
4861
 
5399
 
    def _run(self, b, tree, dry_run, verbose, revision, force, local,
5400
 
             keep_tags):
 
4862
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
5401
4863
        from bzrlib.log import log_formatter, show_log
5402
4864
        from bzrlib.uncommit import uncommit
5403
4865
 
5418
4880
                rev_id = b.get_rev_id(revno)
5419
4881
 
5420
4882
        if rev_id is None or _mod_revision.is_null(rev_id):
5421
 
            self.outf.write(gettext('No revisions to uncommit.\n'))
 
4883
            self.outf.write('No revisions to uncommit.\n')
5422
4884
            return 1
5423
4885
 
5424
4886
        lf = log_formatter('short',
5433
4895
                 end_revision=last_revno)
5434
4896
 
5435
4897
        if dry_run:
5436
 
            self.outf.write(gettext('Dry-run, pretending to remove'
5437
 
                            ' the above revisions.\n'))
 
4898
            self.outf.write('Dry-run, pretending to remove'
 
4899
                            ' the above revisions.\n')
5438
4900
        else:
5439
 
            self.outf.write(gettext('The above revision(s) will be removed.\n'))
 
4901
            self.outf.write('The above revision(s) will be removed.\n')
5440
4902
 
5441
4903
        if not force:
5442
4904
            if not ui.ui_factory.confirm_action(
5443
 
                    gettext(u'Uncommit these revisions'),
 
4905
                    'Uncommit these revisions',
5444
4906
                    'bzrlib.builtins.uncommit',
5445
4907
                    {}):
5446
 
                self.outf.write(gettext('Canceled\n'))
 
4908
                self.outf.write('Canceled\n')
5447
4909
                return 0
5448
4910
 
5449
4911
        mutter('Uncommitting from {%s} to {%s}',
5450
4912
               last_rev_id, rev_id)
5451
4913
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
5452
 
                 revno=revno, local=local, keep_tags=keep_tags)
5453
 
        self.outf.write(gettext('You can restore the old tip by running:\n'
5454
 
             '  bzr pull . -r revid:%s\n') % last_rev_id)
 
4914
                 revno=revno, local=local)
 
4915
        self.outf.write('You can restore the old tip by running:\n'
 
4916
             '  bzr pull . -r revid:%s\n' % last_rev_id)
5455
4917
 
5456
4918
 
5457
4919
class cmd_break_lock(Command):
5491
4953
            conf = _mod_config.LockableConfig(file_name=location)
5492
4954
            conf.break_lock()
5493
4955
        else:
5494
 
            control, relpath = controldir.ControlDir.open_containing(location)
 
4956
            control, relpath = bzrdir.BzrDir.open_containing(location)
5495
4957
            try:
5496
4958
                control.break_lock()
5497
4959
            except NotImplementedError:
5524
4986
               help="Protocol to serve.",
5525
4987
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5526
4988
               value_switches=True),
5527
 
        Option('listen',
5528
 
               help='Listen for connections on nominated address.', type=str),
5529
4989
        Option('port',
5530
 
               help='Listen for connections on nominated port.  Passing 0 as '
5531
 
                    'the port number will result in a dynamically allocated '
5532
 
                    'port.  The default port depends on the protocol.',
5533
 
               type=int),
 
4990
               help='Listen for connections on nominated port of the form '
 
4991
                    '[hostname:]portnumber.  Passing 0 as the port number will '
 
4992
                    'result in a dynamically allocated port.  The default port '
 
4993
                    'depends on the protocol.',
 
4994
               type=str),
5534
4995
        custom_help('directory',
5535
4996
               help='Serve contents of this directory.'),
5536
4997
        Option('allow-writes',
5542
5003
                    'option leads to global uncontrolled write access to your '
5543
5004
                    'file system.'
5544
5005
                ),
5545
 
        Option('client-timeout', type=float,
5546
 
               help='Override the default idle client timeout (5min).'),
5547
5006
        ]
5548
5007
 
5549
 
    def run(self, listen=None, port=None, inet=False, directory=None,
5550
 
            allow_writes=False, protocol=None, client_timeout=None):
 
5008
    def get_host_and_port(self, port):
 
5009
        """Return the host and port to run the smart server on.
 
5010
 
 
5011
        If 'port' is None, None will be returned for the host and port.
 
5012
 
 
5013
        If 'port' has a colon in it, the string before the colon will be
 
5014
        interpreted as the host.
 
5015
 
 
5016
        :param port: A string of the port to run the server on.
 
5017
        :return: A tuple of (host, port), where 'host' is a host name or IP,
 
5018
            and port is an integer TCP/IP port.
 
5019
        """
 
5020
        host = None
 
5021
        if port is not None:
 
5022
            if ':' in port:
 
5023
                host, port = port.split(':')
 
5024
            port = int(port)
 
5025
        return host, port
 
5026
 
 
5027
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
 
5028
            protocol=None):
5551
5029
        from bzrlib import transport
5552
5030
        if directory is None:
5553
5031
            directory = os.getcwd()
5554
5032
        if protocol is None:
5555
5033
            protocol = transport.transport_server_registry.get()
5556
 
        url = transport.location_to_url(directory)
 
5034
        host, port = self.get_host_and_port(port)
 
5035
        url = urlutils.local_path_to_url(directory)
5557
5036
        if not allow_writes:
5558
5037
            url = 'readonly+' + url
5559
 
        t = transport.get_transport_from_url(url)
5560
 
        protocol(t, listen, port, inet, client_timeout)
 
5038
        t = transport.get_transport(url)
 
5039
        protocol(t, host, port, inet)
5561
5040
 
5562
5041
 
5563
5042
class cmd_join(Command):
5586
5065
        containing_tree = WorkingTree.open_containing(parent_dir)[0]
5587
5066
        repo = containing_tree.branch.repository
5588
5067
        if not repo.supports_rich_root():
5589
 
            raise errors.BzrCommandError(gettext(
 
5068
            raise errors.BzrCommandError(
5590
5069
                "Can't join trees because %s doesn't support rich root data.\n"
5591
 
                "You can use bzr upgrade on the repository.")
 
5070
                "You can use bzr upgrade on the repository."
5592
5071
                % (repo,))
5593
5072
        if reference:
5594
5073
            try:
5596
5075
            except errors.BadReferenceTarget, e:
5597
5076
                # XXX: Would be better to just raise a nicely printable
5598
5077
                # exception from the real origin.  Also below.  mbp 20070306
5599
 
                raise errors.BzrCommandError(
5600
 
                       gettext("Cannot join {0}.  {1}").format(tree, e.reason))
 
5078
                raise errors.BzrCommandError("Cannot join %s.  %s" %
 
5079
                                             (tree, e.reason))
5601
5080
        else:
5602
5081
            try:
5603
5082
                containing_tree.subsume(sub_tree)
5604
5083
            except errors.BadSubsumeSource, e:
5605
 
                raise errors.BzrCommandError(
5606
 
                       gettext("Cannot join {0}.  {1}").format(tree, e.reason))
 
5084
                raise errors.BzrCommandError("Cannot join %s.  %s" %
 
5085
                                             (tree, e.reason))
5607
5086
 
5608
5087
 
5609
5088
class cmd_split(Command):
5693
5172
        if submit_branch is None:
5694
5173
            submit_branch = branch.get_parent()
5695
5174
        if submit_branch is None:
5696
 
            raise errors.BzrCommandError(gettext('No submit branch specified or known'))
 
5175
            raise errors.BzrCommandError('No submit branch specified or known')
5697
5176
 
5698
5177
        stored_public_branch = branch.get_public_branch()
5699
5178
        if public_branch is None:
5700
5179
            public_branch = stored_public_branch
5701
5180
        elif stored_public_branch is None:
5702
 
            # FIXME: Should be done only if we succeed ? -- vila 2012-01-03
5703
5181
            branch.set_public_branch(public_branch)
5704
5182
        if not include_bundle and public_branch is None:
5705
 
            raise errors.BzrCommandError(gettext('No public branch specified or'
5706
 
                                         ' known'))
 
5183
            raise errors.BzrCommandError('No public branch specified or'
 
5184
                                         ' known')
5707
5185
        base_revision_id = None
5708
5186
        if revision is not None:
5709
5187
            if len(revision) > 2:
5710
 
                raise errors.BzrCommandError(gettext('bzr merge-directive takes '
5711
 
                    'at most two one revision identifiers'))
 
5188
                raise errors.BzrCommandError('bzr merge-directive takes '
 
5189
                    'at most two one revision identifiers')
5712
5190
            revision_id = revision[-1].as_revision_id(branch)
5713
5191
            if len(revision) == 2:
5714
5192
                base_revision_id = revision[0].as_revision_id(branch)
5716
5194
            revision_id = branch.last_revision()
5717
5195
        revision_id = ensure_null(revision_id)
5718
5196
        if revision_id == NULL_REVISION:
5719
 
            raise errors.BzrCommandError(gettext('No revisions to bundle.'))
 
5197
            raise errors.BzrCommandError('No revisions to bundle.')
5720
5198
        directive = merge_directive.MergeDirective2.from_objects(
5721
5199
            branch.repository, revision_id, time.time(),
5722
5200
            osutils.local_time_offset(), submit_branch,
5730
5208
                self.outf.writelines(directive.to_lines())
5731
5209
        else:
5732
5210
            message = directive.to_email(mail_to, branch, sign)
5733
 
            s = SMTPConnection(branch.get_config_stack())
 
5211
            s = SMTPConnection(branch.get_config())
5734
5212
            s.send_email(message)
5735
5213
 
5736
5214
 
5766
5244
    source branch defaults to that containing the working directory, but can
5767
5245
    be changed using --from.
5768
5246
 
5769
 
    Both the submit branch and the public branch follow the usual behavior with
5770
 
    respect to --remember: If there is no default location set, the first send
5771
 
    will set it (use --no-remember to avoid setting it). After that, you can
5772
 
    omit the location to use the default.  To change the default, use
5773
 
    --remember. The value will only be saved if the location can be accessed.
5774
 
 
5775
5247
    In order to calculate those changes, bzr must analyse the submit branch.
5776
5248
    Therefore it is most efficient for the submit branch to be a local mirror.
5777
5249
    If a public location is known for the submit_branch, that location is used
5846
5318
        ]
5847
5319
 
5848
5320
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5849
 
            no_patch=False, revision=None, remember=None, output=None,
 
5321
            no_patch=False, revision=None, remember=False, output=None,
5850
5322
            format=None, mail_to=None, message=None, body=None,
5851
5323
            strict=None, **kwargs):
5852
5324
        from bzrlib.send import send
5976
5448
        self.add_cleanup(branch.lock_write().unlock)
5977
5449
        if delete:
5978
5450
            if tag_name is None:
5979
 
                raise errors.BzrCommandError(gettext("No tag specified to delete."))
 
5451
                raise errors.BzrCommandError("No tag specified to delete.")
5980
5452
            branch.tags.delete_tag(tag_name)
5981
 
            note(gettext('Deleted tag %s.') % tag_name)
 
5453
            note('Deleted tag %s.' % tag_name)
5982
5454
        else:
5983
5455
            if revision:
5984
5456
                if len(revision) != 1:
5985
 
                    raise errors.BzrCommandError(gettext(
 
5457
                    raise errors.BzrCommandError(
5986
5458
                        "Tags can only be placed on a single revision, "
5987
 
                        "not on a range"))
 
5459
                        "not on a range")
5988
5460
                revision_id = revision[0].as_revision_id(branch)
5989
5461
            else:
5990
5462
                revision_id = branch.last_revision()
5991
5463
            if tag_name is None:
5992
5464
                tag_name = branch.automatic_tag_name(revision_id)
5993
5465
                if tag_name is None:
5994
 
                    raise errors.BzrCommandError(gettext(
5995
 
                        "Please specify a tag name."))
5996
 
            try:
5997
 
                existing_target = branch.tags.lookup_tag(tag_name)
5998
 
            except errors.NoSuchTag:
5999
 
                existing_target = None
6000
 
            if not force and existing_target not in (None, revision_id):
 
5466
                    raise errors.BzrCommandError(
 
5467
                        "Please specify a tag name.")
 
5468
            if (not force) and branch.tags.has_tag(tag_name):
6001
5469
                raise errors.TagAlreadyExists(tag_name)
6002
 
            if existing_target == revision_id:
6003
 
                note(gettext('Tag %s already exists for that revision.') % tag_name)
6004
 
            else:
6005
 
                branch.tags.set_tag(tag_name, revision_id)
6006
 
                if existing_target is None:
6007
 
                    note(gettext('Created tag %s.') % tag_name)
6008
 
                else:
6009
 
                    note(gettext('Updated tag %s.') % tag_name)
 
5470
            branch.tags.set_tag(tag_name, revision_id)
 
5471
            note('Created tag %s.' % tag_name)
6010
5472
 
6011
5473
 
6012
5474
class cmd_tags(Command):
6019
5481
    takes_options = [
6020
5482
        custom_help('directory',
6021
5483
            help='Branch whose tags should be displayed.'),
6022
 
        RegistryOption('sort',
 
5484
        RegistryOption.from_kwargs('sort',
6023
5485
            'Sort tags by different criteria.', title='Sorting',
6024
 
            lazy_registry=('bzrlib.tag', 'tag_sort_methods')
 
5486
            natural='Sort numeric substrings as numbers:'
 
5487
                    ' suitable for version numbers. (default)',
 
5488
            alpha='Sort tags lexicographically.',
 
5489
            time='Sort tags chronologically.',
6025
5490
            ),
6026
5491
        'show-ids',
6027
5492
        'revision',
6028
5493
    ]
6029
5494
 
6030
5495
    @display_command
6031
 
    def run(self, directory='.', sort=None, show_ids=False, revision=None):
6032
 
        from bzrlib.tag import tag_sort_methods
 
5496
    def run(self,
 
5497
            directory='.',
 
5498
            sort='natural',
 
5499
            show_ids=False,
 
5500
            revision=None,
 
5501
            ):
6033
5502
        branch, relpath = Branch.open_containing(directory)
6034
5503
 
6035
5504
        tags = branch.tags.get_tag_dict().items()
6038
5507
 
6039
5508
        self.add_cleanup(branch.lock_read().unlock)
6040
5509
        if revision:
6041
 
            # Restrict to the specified range
6042
 
            tags = self._tags_for_range(branch, revision)
6043
 
        if sort is None:
6044
 
            sort = tag_sort_methods.get()
6045
 
        sort(branch, tags)
 
5510
            graph = branch.repository.get_graph()
 
5511
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
 
5512
            revid1, revid2 = rev1.rev_id, rev2.rev_id
 
5513
            # only show revisions between revid1 and revid2 (inclusive)
 
5514
            tags = [(tag, revid) for tag, revid in tags if
 
5515
                graph.is_between(revid, revid1, revid2)]
 
5516
        if sort == 'natural':
 
5517
            def natural_sort_key(tag):
 
5518
                return [f(s) for f,s in 
 
5519
                        zip(itertools.cycle((unicode.lower,int)),
 
5520
                                            re.split('([0-9]+)', tag[0]))]
 
5521
            tags.sort(key=natural_sort_key)
 
5522
        elif sort == 'alpha':
 
5523
            tags.sort()
 
5524
        elif sort == 'time':
 
5525
            timestamps = {}
 
5526
            for tag, revid in tags:
 
5527
                try:
 
5528
                    revobj = branch.repository.get_revision(revid)
 
5529
                except errors.NoSuchRevision:
 
5530
                    timestamp = sys.maxint # place them at the end
 
5531
                else:
 
5532
                    timestamp = revobj.timestamp
 
5533
                timestamps[revid] = timestamp
 
5534
            tags.sort(key=lambda x: timestamps[x[1]])
6046
5535
        if not show_ids:
6047
5536
            # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
6048
5537
            for index, (tag, revid) in enumerate(tags):
6050
5539
                    revno = branch.revision_id_to_dotted_revno(revid)
6051
5540
                    if isinstance(revno, tuple):
6052
5541
                        revno = '.'.join(map(str, revno))
6053
 
                except (errors.NoSuchRevision,
6054
 
                        errors.GhostRevisionsHaveNoRevno,
6055
 
                        errors.UnsupportedOperation):
 
5542
                except errors.NoSuchRevision:
6056
5543
                    # Bad tag data/merges can lead to tagged revisions
6057
5544
                    # which are not in this branch. Fail gracefully ...
6058
5545
                    revno = '?'
6061
5548
        for tag, revspec in tags:
6062
5549
            self.outf.write('%-20s %s\n' % (tag, revspec))
6063
5550
 
6064
 
    def _tags_for_range(self, branch, revision):
6065
 
        range_valid = True
6066
 
        rev1, rev2 = _get_revision_range(revision, branch, self.name())
6067
 
        revid1, revid2 = rev1.rev_id, rev2.rev_id
6068
 
        # _get_revision_range will always set revid2 if it's not specified.
6069
 
        # If revid1 is None, it means we want to start from the branch
6070
 
        # origin which is always a valid ancestor. If revid1 == revid2, the
6071
 
        # ancestry check is useless.
6072
 
        if revid1 and revid1 != revid2:
6073
 
            # FIXME: We really want to use the same graph than
6074
 
            # branch.iter_merge_sorted_revisions below, but this is not
6075
 
            # easily available -- vila 2011-09-23
6076
 
            if branch.repository.get_graph().is_ancestor(revid2, revid1):
6077
 
                # We don't want to output anything in this case...
6078
 
                return []
6079
 
        # only show revisions between revid1 and revid2 (inclusive)
6080
 
        tagged_revids = branch.tags.get_reverse_tag_dict()
6081
 
        found = []
6082
 
        for r in branch.iter_merge_sorted_revisions(
6083
 
            start_revision_id=revid2, stop_revision_id=revid1,
6084
 
            stop_rule='include'):
6085
 
            revid_tags = tagged_revids.get(r[0], None)
6086
 
            if revid_tags:
6087
 
                found.extend([(tag, r[0]) for tag in revid_tags])
6088
 
        return found
6089
 
 
6090
5551
 
6091
5552
class cmd_reconfigure(Command):
6092
5553
    __doc__ = """Reconfigure the type of a bzr directory.
6106
5567
    takes_args = ['location?']
6107
5568
    takes_options = [
6108
5569
        RegistryOption.from_kwargs(
6109
 
            'tree_type',
6110
 
            title='Tree type',
6111
 
            help='The relation between branch and tree.',
 
5570
            'target_type',
 
5571
            title='Target type',
 
5572
            help='The type to reconfigure the directory to.',
6112
5573
            value_switches=True, enum_switch=False,
6113
5574
            branch='Reconfigure to be an unbound branch with no working tree.',
6114
5575
            tree='Reconfigure to be an unbound branch with a working tree.',
6115
5576
            checkout='Reconfigure to be a bound branch with a working tree.',
6116
5577
            lightweight_checkout='Reconfigure to be a lightweight'
6117
5578
                ' checkout (with no local history).',
6118
 
            ),
6119
 
        RegistryOption.from_kwargs(
6120
 
            'repository_type',
6121
 
            title='Repository type',
6122
 
            help='Location fo the repository.',
6123
 
            value_switches=True, enum_switch=False,
6124
5579
            standalone='Reconfigure to be a standalone branch '
6125
5580
                '(i.e. stop using shared repository).',
6126
5581
            use_shared='Reconfigure to use a shared repository.',
6127
 
            ),
6128
 
        RegistryOption.from_kwargs(
6129
 
            'repository_trees',
6130
 
            title='Trees in Repository',
6131
 
            help='Whether new branches in the repository have trees.',
6132
 
            value_switches=True, enum_switch=False,
6133
5582
            with_trees='Reconfigure repository to create '
6134
5583
                'working trees on branches by default.',
6135
5584
            with_no_trees='Reconfigure repository to not create '
6149
5598
            ),
6150
5599
        ]
6151
5600
 
6152
 
    def run(self, location=None, bind_to=None, force=False,
6153
 
            tree_type=None, repository_type=None, repository_trees=None,
6154
 
            stacked_on=None, unstacked=None):
6155
 
        directory = controldir.ControlDir.open(location)
 
5601
    def run(self, location=None, target_type=None, bind_to=None, force=False,
 
5602
            stacked_on=None,
 
5603
            unstacked=None):
 
5604
        directory = bzrdir.BzrDir.open(location)
6156
5605
        if stacked_on and unstacked:
6157
 
            raise errors.BzrCommandError(gettext("Can't use both --stacked-on and --unstacked"))
 
5606
            raise BzrCommandError("Can't use both --stacked-on and --unstacked")
6158
5607
        elif stacked_on is not None:
6159
5608
            reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
6160
5609
        elif unstacked:
6162
5611
        # At the moment you can use --stacked-on and a different
6163
5612
        # reconfiguration shape at the same time; there seems no good reason
6164
5613
        # to ban it.
6165
 
        if (tree_type is None and
6166
 
            repository_type is None and
6167
 
            repository_trees is None):
 
5614
        if target_type is None:
6168
5615
            if stacked_on or unstacked:
6169
5616
                return
6170
5617
            else:
6171
 
                raise errors.BzrCommandError(gettext('No target configuration '
6172
 
                    'specified'))
6173
 
        reconfiguration = None
6174
 
        if tree_type == 'branch':
 
5618
                raise errors.BzrCommandError('No target configuration '
 
5619
                    'specified')
 
5620
        elif target_type == 'branch':
6175
5621
            reconfiguration = reconfigure.Reconfigure.to_branch(directory)
6176
 
        elif tree_type == 'tree':
 
5622
        elif target_type == 'tree':
6177
5623
            reconfiguration = reconfigure.Reconfigure.to_tree(directory)
6178
 
        elif tree_type == 'checkout':
 
5624
        elif target_type == 'checkout':
6179
5625
            reconfiguration = reconfigure.Reconfigure.to_checkout(
6180
5626
                directory, bind_to)
6181
 
        elif tree_type == 'lightweight-checkout':
 
5627
        elif target_type == 'lightweight-checkout':
6182
5628
            reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
6183
5629
                directory, bind_to)
6184
 
        if reconfiguration:
6185
 
            reconfiguration.apply(force)
6186
 
            reconfiguration = None
6187
 
        if repository_type == 'use-shared':
 
5630
        elif target_type == 'use-shared':
6188
5631
            reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
6189
 
        elif repository_type == 'standalone':
 
5632
        elif target_type == 'standalone':
6190
5633
            reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
6191
 
        if reconfiguration:
6192
 
            reconfiguration.apply(force)
6193
 
            reconfiguration = None
6194
 
        if repository_trees == 'with-trees':
 
5634
        elif target_type == 'with-trees':
6195
5635
            reconfiguration = reconfigure.Reconfigure.set_repository_trees(
6196
5636
                directory, True)
6197
 
        elif repository_trees == 'with-no-trees':
 
5637
        elif target_type == 'with-no-trees':
6198
5638
            reconfiguration = reconfigure.Reconfigure.set_repository_trees(
6199
5639
                directory, False)
6200
 
        if reconfiguration:
6201
 
            reconfiguration.apply(force)
6202
 
            reconfiguration = None
 
5640
        reconfiguration.apply(force)
6203
5641
 
6204
5642
 
6205
5643
class cmd_switch(Command):
6240
5678
        from bzrlib import switch
6241
5679
        tree_location = directory
6242
5680
        revision = _get_one_revision('switch', revision)
6243
 
        possible_transports = []
6244
 
        control_dir = controldir.ControlDir.open_containing(tree_location,
6245
 
            possible_transports=possible_transports)[0]
 
5681
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
6246
5682
        if to_location is None:
6247
5683
            if revision is None:
6248
 
                raise errors.BzrCommandError(gettext('You must supply either a'
6249
 
                                             ' revision or a location'))
 
5684
                raise errors.BzrCommandError('You must supply either a'
 
5685
                                             ' revision or a location')
6250
5686
            to_location = tree_location
6251
5687
        try:
6252
 
            branch = control_dir.open_branch(
6253
 
                possible_transports=possible_transports)
 
5688
            branch = control_dir.open_branch()
6254
5689
            had_explicit_nick = branch.get_config().has_explicit_nickname()
6255
5690
        except errors.NotBranchError:
6256
5691
            branch = None
6257
5692
            had_explicit_nick = False
6258
5693
        if create_branch:
6259
5694
            if branch is None:
6260
 
                raise errors.BzrCommandError(
6261
 
                    gettext('cannot create branch without source branch'))
6262
 
            to_location = lookup_new_sibling_branch(control_dir, to_location,
6263
 
                 possible_transports=possible_transports)
 
5695
                raise errors.BzrCommandError('cannot create branch without'
 
5696
                                             ' source branch')
 
5697
            to_location = directory_service.directories.dereference(
 
5698
                              to_location)
 
5699
            if '/' not in to_location and '\\' not in to_location:
 
5700
                # This path is meant to be relative to the existing branch
 
5701
                this_url = self._get_branch_location(control_dir)
 
5702
                to_location = urlutils.join(this_url, '..', to_location)
6264
5703
            to_branch = branch.bzrdir.sprout(to_location,
6265
 
                 possible_transports=possible_transports,
6266
 
                 source_branch=branch).open_branch()
 
5704
                                 possible_transports=[branch.bzrdir.root_transport],
 
5705
                                 source_branch=branch).open_branch()
6267
5706
        else:
6268
5707
            try:
6269
 
                to_branch = Branch.open(to_location,
6270
 
                    possible_transports=possible_transports)
 
5708
                to_branch = Branch.open(to_location)
6271
5709
            except errors.NotBranchError:
6272
 
                to_branch = open_sibling_branch(control_dir, to_location,
6273
 
                    possible_transports=possible_transports)
 
5710
                this_url = self._get_branch_location(control_dir)
 
5711
                to_branch = Branch.open(
 
5712
                    urlutils.join(this_url, '..', to_location))
6274
5713
        if revision is not None:
6275
5714
            revision = revision.as_revision_id(to_branch)
6276
5715
        switch.switch(control_dir, to_branch, force, revision_id=revision)
6277
5716
        if had_explicit_nick:
6278
5717
            branch = control_dir.open_branch() #get the new branch!
6279
5718
            branch.nick = to_branch.nick
6280
 
        note(gettext('Switched to branch: %s'),
 
5719
        note('Switched to branch: %s',
6281
5720
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6282
5721
 
 
5722
    def _get_branch_location(self, control_dir):
 
5723
        """Return location of branch for this control dir."""
 
5724
        try:
 
5725
            this_branch = control_dir.open_branch()
 
5726
            # This may be a heavy checkout, where we want the master branch
 
5727
            master_location = this_branch.get_bound_location()
 
5728
            if master_location is not None:
 
5729
                return master_location
 
5730
            # If not, use a local sibling
 
5731
            return this_branch.base
 
5732
        except errors.NotBranchError:
 
5733
            format = control_dir.find_branch_format()
 
5734
            if getattr(format, 'get_reference', None) is not None:
 
5735
                return format.get_reference(control_dir)
 
5736
            else:
 
5737
                return control_dir.root_transport.base
6283
5738
 
6284
5739
 
6285
5740
class cmd_view(Command):
6376
5831
            name = current_view
6377
5832
        if delete:
6378
5833
            if file_list:
6379
 
                raise errors.BzrCommandError(gettext(
6380
 
                    "Both --delete and a file list specified"))
 
5834
                raise errors.BzrCommandError(
 
5835
                    "Both --delete and a file list specified")
6381
5836
            elif switch:
6382
 
                raise errors.BzrCommandError(gettext(
6383
 
                    "Both --delete and --switch specified"))
 
5837
                raise errors.BzrCommandError(
 
5838
                    "Both --delete and --switch specified")
6384
5839
            elif all:
6385
5840
                tree.views.set_view_info(None, {})
6386
 
                self.outf.write(gettext("Deleted all views.\n"))
 
5841
                self.outf.write("Deleted all views.\n")
6387
5842
            elif name is None:
6388
 
                raise errors.BzrCommandError(gettext("No current view to delete"))
 
5843
                raise errors.BzrCommandError("No current view to delete")
6389
5844
            else:
6390
5845
                tree.views.delete_view(name)
6391
 
                self.outf.write(gettext("Deleted '%s' view.\n") % name)
 
5846
                self.outf.write("Deleted '%s' view.\n" % name)
6392
5847
        elif switch:
6393
5848
            if file_list:
6394
 
                raise errors.BzrCommandError(gettext(
6395
 
                    "Both --switch and a file list specified"))
 
5849
                raise errors.BzrCommandError(
 
5850
                    "Both --switch and a file list specified")
6396
5851
            elif all:
6397
 
                raise errors.BzrCommandError(gettext(
6398
 
                    "Both --switch and --all specified"))
 
5852
                raise errors.BzrCommandError(
 
5853
                    "Both --switch and --all specified")
6399
5854
            elif switch == 'off':
6400
5855
                if current_view is None:
6401
 
                    raise errors.BzrCommandError(gettext("No current view to disable"))
 
5856
                    raise errors.BzrCommandError("No current view to disable")
6402
5857
                tree.views.set_view_info(None, view_dict)
6403
 
                self.outf.write(gettext("Disabled '%s' view.\n") % (current_view))
 
5858
                self.outf.write("Disabled '%s' view.\n" % (current_view))
6404
5859
            else:
6405
5860
                tree.views.set_view_info(switch, view_dict)
6406
5861
                view_str = views.view_display_str(tree.views.lookup_view())
6407
 
                self.outf.write(gettext("Using '{0}' view: {1}\n").format(switch, view_str))
 
5862
                self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
6408
5863
        elif all:
6409
5864
            if view_dict:
6410
 
                self.outf.write(gettext('Views defined:\n'))
 
5865
                self.outf.write('Views defined:\n')
6411
5866
                for view in sorted(view_dict):
6412
5867
                    if view == current_view:
6413
5868
                        active = "=>"
6416
5871
                    view_str = views.view_display_str(view_dict[view])
6417
5872
                    self.outf.write('%s %-20s %s\n' % (active, view, view_str))
6418
5873
            else:
6419
 
                self.outf.write(gettext('No views defined.\n'))
 
5874
                self.outf.write('No views defined.\n')
6420
5875
        elif file_list:
6421
5876
            if name is None:
6422
5877
                # No name given and no current view set
6423
5878
                name = 'my'
6424
5879
            elif name == 'off':
6425
 
                raise errors.BzrCommandError(gettext(
6426
 
                    "Cannot change the 'off' pseudo view"))
 
5880
                raise errors.BzrCommandError(
 
5881
                    "Cannot change the 'off' pseudo view")
6427
5882
            tree.views.set_view(name, sorted(file_list))
6428
5883
            view_str = views.view_display_str(tree.views.lookup_view())
6429
 
            self.outf.write(gettext("Using '{0}' view: {1}\n").format(name, view_str))
 
5884
            self.outf.write("Using '%s' view: %s\n" % (name, view_str))
6430
5885
        else:
6431
5886
            # list the files
6432
5887
            if name is None:
6433
5888
                # No name given and no current view set
6434
 
                self.outf.write(gettext('No current view.\n'))
 
5889
                self.outf.write('No current view.\n')
6435
5890
            else:
6436
5891
                view_str = views.view_display_str(tree.views.lookup_view(name))
6437
 
                self.outf.write(gettext("'{0}' view is: {1}\n").format(name, view_str))
 
5892
                self.outf.write("'%s' view is: %s\n" % (name, view_str))
6438
5893
 
6439
5894
 
6440
5895
class cmd_hooks(Command):
6454
5909
                        self.outf.write("    %s\n" %
6455
5910
                                        (some_hooks.get_hook_name(hook),))
6456
5911
                else:
6457
 
                    self.outf.write(gettext("    <no hooks installed>\n"))
 
5912
                    self.outf.write("    <no hooks installed>\n")
6458
5913
 
6459
5914
 
6460
5915
class cmd_remove_branch(Command):
6473
5928
 
6474
5929
    takes_args = ["location?"]
6475
5930
 
6476
 
    takes_options = ['directory',
6477
 
        Option('force', help='Remove branch even if it is the active branch.')]
6478
 
 
6479
5931
    aliases = ["rmbranch"]
6480
5932
 
6481
 
    def run(self, directory=None, location=None, force=False):
6482
 
        br = open_nearby_branch(near=directory, location=location)
6483
 
        if not force and br.bzrdir.has_workingtree():
6484
 
            try:
6485
 
                active_branch = br.bzrdir.open_branch(name="")
6486
 
            except errors.NotBranchError:
6487
 
                active_branch = None
6488
 
            if (active_branch is not None and
6489
 
                br.control_url == active_branch.control_url):
6490
 
                raise errors.BzrCommandError(
6491
 
                    gettext("Branch is active. Use --force to remove it."))
6492
 
        br.bzrdir.destroy_branch(br.name)
 
5933
    def run(self, location=None):
 
5934
        if location is None:
 
5935
            location = "."
 
5936
        branch = Branch.open_containing(location)[0]
 
5937
        branch.bzrdir.destroy_branch()
6493
5938
 
6494
5939
 
6495
5940
class cmd_shelve(Command):
6571
6016
        manager = tree.get_shelf_manager()
6572
6017
        shelves = manager.active_shelves()
6573
6018
        if len(shelves) == 0:
6574
 
            note(gettext('No shelved changes.'))
 
6019
            note('No shelved changes.')
6575
6020
            return 0
6576
6021
        for shelf_id in reversed(shelves):
6577
6022
            message = manager.get_metadata(shelf_id).get('message')
6631
6076
    """
6632
6077
    takes_options = ['directory',
6633
6078
                     Option('ignored', help='Delete all ignored files.'),
6634
 
                     Option('detritus', help='Delete conflict files, merge and revert'
 
6079
                     Option('detritus', help='Delete conflict files, merge'
6635
6080
                            ' backups, and failed selftest dirs.'),
6636
6081
                     Option('unknown',
6637
6082
                            help='Delete files unknown to bzr (default).'),
6666
6111
        if path is not None:
6667
6112
            branchdir = path
6668
6113
        tree, branch, relpath =(
6669
 
            controldir.ControlDir.open_containing_tree_or_branch(branchdir))
 
6114
            bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
6670
6115
        if path is not None:
6671
6116
            path = relpath
6672
6117
        if tree is None:
6696
6141
            self.outf.write('%s %s\n' % (path, location))
6697
6142
 
6698
6143
 
6699
 
class cmd_export_pot(Command):
6700
 
    __doc__ = """Export command helps and error messages in po format."""
6701
 
 
6702
 
    hidden = True
6703
 
    takes_options = [Option('plugin', 
6704
 
                            help='Export help text from named command '\
6705
 
                                 '(defaults to all built in commands).',
6706
 
                            type=str),
6707
 
                     Option('include-duplicates',
6708
 
                            help='Output multiple copies of the same msgid '
6709
 
                                 'string if it appears more than once.'),
6710
 
                            ]
6711
 
 
6712
 
    def run(self, plugin=None, include_duplicates=False):
6713
 
        from bzrlib.export_pot import export_pot
6714
 
        export_pot(self.outf, plugin, include_duplicates)
6715
 
 
6716
 
 
6717
6144
def _register_lazy_builtins():
6718
6145
    # register lazy builtins from other modules; called at startup and should
6719
6146
    # be only called once.
6724
6151
        ('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6725
6152
        ('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6726
6153
        ('cmd_conflicts', [], 'bzrlib.conflicts'),
6727
 
        ('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6728
 
        ('cmd_verify_signatures', [], 'bzrlib.commit_signature_commands'),
 
6154
        ('cmd_sign_my_commits', [], 'bzrlib.sign_my_commits'),
6729
6155
        ('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6730
6156
        ]:
6731
6157
        builtin_command_registry.register_lazy(name, aliases, module_name)