~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

(gz) Fix deprecations of win32utils path function unicode wrappers (Martin
 Packman)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""builtin bzr commands"""
18
18
 
 
19
from __future__ import absolute_import
 
20
 
19
21
import os
20
22
 
 
23
import bzrlib.bzrdir
 
24
 
21
25
from bzrlib.lazy_import import lazy_import
22
26
lazy_import(globals(), """
23
27
import cStringIO
 
28
import errno
24
29
import sys
25
30
import time
26
31
 
29
34
    bugtracker,
30
35
    bundle,
31
36
    btree_index,
32
 
    bzrdir,
 
37
    controldir,
33
38
    directory_service,
34
39
    delta,
35
40
    config as _mod_config,
57
62
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
58
63
from bzrlib.smtp_connection import SMTPConnection
59
64
from bzrlib.workingtree import WorkingTree
 
65
from bzrlib.i18n import gettext, ngettext
60
66
""")
61
67
 
62
68
from bzrlib.commands import (
112
118
            if view_files:
113
119
                file_list = view_files
114
120
                view_str = views.view_display_str(view_files)
115
 
                note("Ignoring files outside view. View is %s" % view_str)
 
121
                note(gettext("Ignoring files outside view. View is %s") % view_str)
116
122
    return tree, file_list
117
123
 
118
124
 
120
126
    if revisions is None:
121
127
        return None
122
128
    if len(revisions) != 1:
123
 
        raise errors.BzrCommandError(
124
 
            'bzr %s --revision takes exactly one revision identifier' % (
 
129
        raise errors.BzrCommandError(gettext(
 
130
            'bzr %s --revision takes exactly one revision identifier') % (
125
131
                command_name,))
126
132
    return revisions[0]
127
133
 
196
202
    the --directory option is used to specify a different branch."""
197
203
    if directory is not None:
198
204
        return (None, Branch.open(directory), filename)
199
 
    return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
205
    return controldir.ControlDir.open_containing_tree_or_branch(filename)
200
206
 
201
207
 
202
208
# TODO: Make sure no commands unconditionally use the working directory as a
232
238
    unknown
233
239
        Not versioned and not matching an ignore pattern.
234
240
 
235
 
    Additionally for directories, symlinks and files with an executable
236
 
    bit, Bazaar indicates their type using a trailing character: '/', '@'
237
 
    or '*' respectively.
 
241
    Additionally for directories, symlinks and files with a changed
 
242
    executable bit, Bazaar indicates their type using a trailing
 
243
    character: '/', '@' or '*' respectively. These decorations can be
 
244
    disabled using the '--no-classify' option.
238
245
 
239
246
    To see ignored files use 'bzr ignored'.  For details on the
240
247
    changes to file texts, use 'bzr diff'.
271
278
                            short_name='V'),
272
279
                     Option('no-pending', help='Don\'t show pending merges.',
273
280
                           ),
 
281
                     Option('no-classify',
 
282
                            help='Do not mark object type using indicator.',
 
283
                           ),
274
284
                     ]
275
285
    aliases = ['st', 'stat']
276
286
 
279
289
 
280
290
    @display_command
281
291
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
282
 
            versioned=False, no_pending=False, verbose=False):
 
292
            versioned=False, no_pending=False, verbose=False,
 
293
            no_classify=False):
283
294
        from bzrlib.status import show_tree_status
284
295
 
285
296
        if revision and len(revision) > 2:
286
 
            raise errors.BzrCommandError('bzr status --revision takes exactly'
287
 
                                         ' one or two revision specifiers')
 
297
            raise errors.BzrCommandError(gettext('bzr status --revision takes exactly'
 
298
                                         ' one or two revision specifiers'))
288
299
 
289
300
        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
290
301
        # Avoid asking for specific files when that is not needed.
299
310
        show_tree_status(tree, show_ids=show_ids,
300
311
                         specific_files=relfile_list, revision=revision,
301
312
                         to_file=self.outf, short=short, versioned=versioned,
302
 
                         show_pending=(not no_pending), verbose=verbose)
 
313
                         show_pending=(not no_pending), verbose=verbose,
 
314
                         classify=not no_classify)
303
315
 
304
316
 
305
317
class cmd_cat_revision(Command):
326
338
    @display_command
327
339
    def run(self, revision_id=None, revision=None, directory=u'.'):
328
340
        if revision_id is not None and revision is not None:
329
 
            raise errors.BzrCommandError('You can only supply one of'
330
 
                                         ' revision_id or --revision')
 
341
            raise errors.BzrCommandError(gettext('You can only supply one of'
 
342
                                         ' revision_id or --revision'))
331
343
        if revision_id is None and revision is None:
332
 
            raise errors.BzrCommandError('You must supply either'
333
 
                                         ' --revision or a revision_id')
 
344
            raise errors.BzrCommandError(gettext('You must supply either'
 
345
                                         ' --revision or a revision_id'))
334
346
 
335
 
        b = bzrdir.BzrDir.open_containing_tree_or_branch(directory)[1]
 
347
        b = controldir.ControlDir.open_containing_tree_or_branch(directory)[1]
336
348
 
337
349
        revisions = b.repository.revisions
338
350
        if revisions is None:
339
 
            raise errors.BzrCommandError('Repository %r does not support '
340
 
                'access to raw revision texts')
 
351
            raise errors.BzrCommandError(gettext('Repository %r does not support '
 
352
                'access to raw revision texts'))
341
353
 
342
354
        b.repository.lock_read()
343
355
        try:
347
359
                try:
348
360
                    self.print_revision(revisions, revision_id)
349
361
                except errors.NoSuchRevision:
350
 
                    msg = "The repository %s contains no revision %s." % (
 
362
                    msg = gettext("The repository {0} contains no revision {1}.").format(
351
363
                        b.repository.base, revision_id)
352
364
                    raise errors.BzrCommandError(msg)
353
365
            elif revision is not None:
354
366
                for rev in revision:
355
367
                    if rev is None:
356
368
                        raise errors.BzrCommandError(
357
 
                            'You cannot specify a NULL revision.')
 
369
                            gettext('You cannot specify a NULL revision.'))
358
370
                    rev_id = rev.as_revision_id(b)
359
371
                    self.print_revision(revisions, rev_id)
360
372
        finally:
466
478
            location_list=['.']
467
479
 
468
480
        for location in location_list:
469
 
            d = bzrdir.BzrDir.open(location)
470
 
            
 
481
            d = controldir.ControlDir.open(location)
 
482
 
471
483
            try:
472
484
                working = d.open_workingtree()
473
485
            except errors.NoWorkingTree:
474
 
                raise errors.BzrCommandError("No working tree to remove")
 
486
                raise errors.BzrCommandError(gettext("No working tree to remove"))
475
487
            except errors.NotLocalUrl:
476
 
                raise errors.BzrCommandError("You cannot remove the working tree"
477
 
                                             " of a remote path")
 
488
                raise errors.BzrCommandError(gettext("You cannot remove the working tree"
 
489
                                             " of a remote path"))
478
490
            if not force:
479
491
                if (working.has_changes()):
480
492
                    raise errors.UncommittedChanges(working)
482
494
                    raise errors.ShelvedChanges(working)
483
495
 
484
496
            if working.user_url != working.branch.user_url:
485
 
                raise errors.BzrCommandError("You cannot remove the working tree"
486
 
                                             " from a lightweight checkout")
 
497
                raise errors.BzrCommandError(gettext("You cannot remove the working tree"
 
498
                                             " from a lightweight checkout"))
487
499
 
488
500
            d.destroy_workingtree()
489
501
 
521
533
                pass # There seems to be a real error here, so we'll reset
522
534
            else:
523
535
                # Refuse
524
 
                raise errors.BzrCommandError(
 
536
                raise errors.BzrCommandError(gettext(
525
537
                    'The tree does not appear to be corrupt. You probably'
526
538
                    ' want "bzr revert" instead. Use "--force" if you are'
527
 
                    ' sure you want to reset the working tree.')
 
539
                    ' sure you want to reset the working tree.'))
528
540
        if revision is None:
529
541
            revision_ids = None
530
542
        else:
533
545
            tree.reset_state(revision_ids)
534
546
        except errors.BzrError, e:
535
547
            if revision_ids is None:
536
 
                extra = (', the header appears corrupt, try passing -r -1'
537
 
                         ' to set the state to the last commit')
 
548
                extra = (gettext(', the header appears corrupt, try passing -r -1'
 
549
                         ' to set the state to the last commit'))
538
550
            else:
539
551
                extra = ''
540
 
            raise errors.BzrCommandError('failed to reset the tree state'
541
 
                                         + extra)
 
552
            raise errors.BzrCommandError(gettext('failed to reset the tree state{0}').format(extra))
542
553
 
543
554
 
544
555
class cmd_revno(Command):
550
561
    _see_also = ['info']
551
562
    takes_args = ['location?']
552
563
    takes_options = [
553
 
        Option('tree', help='Show revno of working tree'),
 
564
        Option('tree', help='Show revno of working tree.'),
 
565
        'revision',
554
566
        ]
555
567
 
556
568
    @display_command
557
 
    def run(self, tree=False, location=u'.'):
 
569
    def run(self, tree=False, location=u'.', revision=None):
 
570
        if revision is not None and tree:
 
571
            raise errors.BzrCommandError(gettext("--tree and --revision can "
 
572
                "not be used together"))
 
573
 
558
574
        if tree:
559
575
            try:
560
576
                wt = WorkingTree.open_containing(location)[0]
561
577
                self.add_cleanup(wt.lock_read().unlock)
562
578
            except (errors.NoWorkingTree, errors.NotLocalUrl):
563
579
                raise errors.NoWorkingTree(location)
 
580
            b = wt.branch
564
581
            revid = wt.last_revision()
565
 
            try:
566
 
                revno_t = wt.branch.revision_id_to_dotted_revno(revid)
567
 
            except errors.NoSuchRevision:
568
 
                revno_t = ('???',)
569
 
            revno = ".".join(str(n) for n in revno_t)
570
582
        else:
571
583
            b = Branch.open_containing(location)[0]
572
584
            self.add_cleanup(b.lock_read().unlock)
573
 
            revno = b.revno()
 
585
            if revision:
 
586
                if len(revision) != 1:
 
587
                    raise errors.BzrCommandError(gettext(
 
588
                        "Tags can only be placed on a single revision, "
 
589
                        "not on a range"))
 
590
                revid = revision[0].as_revision_id(b)
 
591
            else:
 
592
                revid = b.last_revision()
 
593
        try:
 
594
            revno_t = b.revision_id_to_dotted_revno(revid)
 
595
        except errors.NoSuchRevision:
 
596
            revno_t = ('???',)
 
597
        revno = ".".join(str(n) for n in revno_t)
574
598
        self.cleanup_now()
575
 
        self.outf.write(str(revno) + '\n')
 
599
        self.outf.write(revno + '\n')
576
600
 
577
601
 
578
602
class cmd_revision_info(Command):
585
609
        custom_help('directory',
586
610
            help='Branch to examine, '
587
611
                 'rather than the one containing the working directory.'),
588
 
        Option('tree', help='Show revno of working tree'),
 
612
        Option('tree', help='Show revno of working tree.'),
589
613
        ]
590
614
 
591
615
    @display_command
647
671
    are added.  This search proceeds recursively into versioned
648
672
    directories.  If no names are given '.' is assumed.
649
673
 
 
674
    A warning will be printed when nested trees are encountered,
 
675
    unless they are explicitly ignored.
 
676
 
650
677
    Therefore simply saying 'bzr add' will version all files that
651
678
    are currently unknown.
652
679
 
668
695
    
669
696
    Any files matching patterns in the ignore list will not be added
670
697
    unless they are explicitly mentioned.
 
698
    
 
699
    In recursive mode, files larger than the configuration option 
 
700
    add.maximum_file_size will be skipped. Named items are never skipped due
 
701
    to file size.
671
702
    """
672
703
    takes_args = ['file*']
673
704
    takes_options = [
700
731
            action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
701
732
                          to_file=self.outf, should_print=(not is_quiet()))
702
733
        else:
703
 
            action = bzrlib.add.AddAction(to_file=self.outf,
 
734
            action = bzrlib.add.AddWithSkipLargeAction(to_file=self.outf,
704
735
                should_print=(not is_quiet()))
705
736
 
706
737
        if base_tree:
713
744
            if verbose:
714
745
                for glob in sorted(ignored.keys()):
715
746
                    for path in ignored[glob]:
716
 
                        self.outf.write("ignored %s matching \"%s\"\n"
717
 
                                        % (path, glob))
 
747
                        self.outf.write(
 
748
                         gettext("ignored {0} matching \"{1}\"\n").format(
 
749
                         path, glob))
718
750
 
719
751
 
720
752
class cmd_mkdir(Command):
724
756
    """
725
757
 
726
758
    takes_args = ['dir+']
 
759
    takes_options = [
 
760
        Option(
 
761
            'parents',
 
762
            help='No error if existing, make parent directories as needed.',
 
763
            short_name='p'
 
764
            )
 
765
        ]
727
766
    encoding_type = 'replace'
728
767
 
729
 
    def run(self, dir_list):
730
 
        for d in dir_list:
731
 
            wt, dd = WorkingTree.open_containing(d)
732
 
            base = os.path.dirname(dd)
733
 
            id = wt.path2id(base)
734
 
            if id != None:
735
 
                os.mkdir(d)
736
 
                wt.add([dd])
737
 
                self.outf.write('added %s\n' % d)
 
768
    @classmethod
 
769
    def add_file_with_parents(cls, wt, relpath):
 
770
        if wt.path2id(relpath) is not None:
 
771
            return
 
772
        cls.add_file_with_parents(wt, osutils.dirname(relpath))
 
773
        wt.add([relpath])
 
774
 
 
775
    @classmethod
 
776
    def add_file_single(cls, wt, relpath):
 
777
        wt.add([relpath])
 
778
 
 
779
    def run(self, dir_list, parents=False):
 
780
        if parents:
 
781
            add_file = self.add_file_with_parents
 
782
        else:
 
783
            add_file = self.add_file_single
 
784
        for dir in dir_list:
 
785
            wt, relpath = WorkingTree.open_containing(dir)
 
786
            if parents:
 
787
                try:
 
788
                    os.makedirs(dir)
 
789
                except OSError, e:
 
790
                    if e.errno != errno.EEXIST:
 
791
                        raise
738
792
            else:
739
 
                raise errors.NotVersionedError(path=base)
 
793
                os.mkdir(dir)
 
794
            add_file(wt, relpath)
 
795
            if not is_quiet():
 
796
                self.outf.write(gettext('added %s\n') % dir)
740
797
 
741
798
 
742
799
class cmd_relpath(Command):
778
835
    @display_command
779
836
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
780
837
        if kind and kind not in ['file', 'directory', 'symlink']:
781
 
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
 
838
            raise errors.BzrCommandError(gettext('invalid kind %r specified') % (kind,))
782
839
 
783
840
        revision = _get_one_revision('inventory', revision)
784
841
        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
848
905
        if auto:
849
906
            return self.run_auto(names_list, after, dry_run)
850
907
        elif dry_run:
851
 
            raise errors.BzrCommandError('--dry-run requires --auto.')
 
908
            raise errors.BzrCommandError(gettext('--dry-run requires --auto.'))
852
909
        if names_list is None:
853
910
            names_list = []
854
911
        if len(names_list) < 2:
855
 
            raise errors.BzrCommandError("missing file argument")
 
912
            raise errors.BzrCommandError(gettext("missing file argument"))
856
913
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
 
914
        for file_name in rel_names[0:-1]:
 
915
            if file_name == '':
 
916
                raise errors.BzrCommandError(gettext("can not move root of branch"))
857
917
        self.add_cleanup(tree.lock_tree_write().unlock)
858
918
        self._run(tree, names_list, rel_names, after)
859
919
 
860
920
    def run_auto(self, names_list, after, dry_run):
861
921
        if names_list is not None and len(names_list) > 1:
862
 
            raise errors.BzrCommandError('Only one path may be specified to'
863
 
                                         ' --auto.')
 
922
            raise errors.BzrCommandError(gettext('Only one path may be specified to'
 
923
                                         ' --auto.'))
864
924
        if after:
865
 
            raise errors.BzrCommandError('--after cannot be specified with'
866
 
                                         ' --auto.')
 
925
            raise errors.BzrCommandError(gettext('--after cannot be specified with'
 
926
                                         ' --auto.'))
867
927
        work_tree, file_list = WorkingTree.open_containing_paths(
868
928
            names_list, default_directory='.')
869
929
        self.add_cleanup(work_tree.lock_tree_write().unlock)
899
959
                    self.outf.write("%s => %s\n" % (src, dest))
900
960
        else:
901
961
            if len(names_list) != 2:
902
 
                raise errors.BzrCommandError('to mv multiple files the'
 
962
                raise errors.BzrCommandError(gettext('to mv multiple files the'
903
963
                                             ' destination must be a versioned'
904
 
                                             ' directory')
 
964
                                             ' directory'))
905
965
 
906
966
            # for cicp file-systems: the src references an existing inventory
907
967
            # item:
967
1027
    branches have diverged.
968
1028
 
969
1029
    If there is no default location set, the first pull will set it (use
970
 
    --no-remember to avoid settting it). After that, you can omit the
 
1030
    --no-remember to avoid setting it). After that, you can omit the
971
1031
    location to use the default.  To change the default, use --remember. The
972
1032
    value will only be saved if the remote location can be accessed.
973
1033
 
 
1034
    The --verbose option will display the revisions pulled using the log_format
 
1035
    configuration option. You can use a different format by overriding it with
 
1036
    -Olog_format=<other_format>.
 
1037
 
974
1038
    Note: The location can be specified either in the form of a branch,
975
1039
    or in the form of a path to a file containing a merge directive generated
976
1040
    with bzr send.
1013
1077
            self.add_cleanup(branch_to.lock_write().unlock)
1014
1078
 
1015
1079
        if tree_to is None and show_base:
1016
 
            raise errors.BzrCommandError("Need working tree for --show-base.")
 
1080
            raise errors.BzrCommandError(gettext("Need working tree for --show-base."))
1017
1081
 
1018
1082
        if local and not branch_to.get_bound_location():
1019
1083
            raise errors.LocalRequiresBoundBranch()
1029
1093
        stored_loc = branch_to.get_parent()
1030
1094
        if location is None:
1031
1095
            if stored_loc is None:
1032
 
                raise errors.BzrCommandError("No pull location known or"
1033
 
                                             " specified.")
 
1096
                raise errors.BzrCommandError(gettext("No pull location known or"
 
1097
                                             " specified."))
1034
1098
            else:
1035
1099
                display_url = urlutils.unescape_for_display(stored_loc,
1036
1100
                        self.outf.encoding)
1037
1101
                if not is_quiet():
1038
 
                    self.outf.write("Using saved parent location: %s\n" % display_url)
 
1102
                    self.outf.write(gettext("Using saved parent location: %s\n") % display_url)
1039
1103
                location = stored_loc
1040
1104
 
1041
1105
        revision = _get_one_revision('pull', revision)
1042
1106
        if mergeable is not None:
1043
1107
            if revision is not None:
1044
 
                raise errors.BzrCommandError(
1045
 
                    'Cannot use -r with merge directives or bundles')
 
1108
                raise errors.BzrCommandError(gettext(
 
1109
                    'Cannot use -r with merge directives or bundles'))
1046
1110
            mergeable.install_revisions(branch_to.repository)
1047
1111
            base_revision_id, revision_id, verified = \
1048
1112
                mergeable.get_merge_request(branch_to.repository)
1066
1130
                view_info=view_info)
1067
1131
            result = tree_to.pull(
1068
1132
                branch_from, overwrite, revision_id, change_reporter,
1069
 
                possible_transports=possible_transports, local=local,
1070
 
                show_base=show_base)
 
1133
                local=local, show_base=show_base)
1071
1134
        else:
1072
1135
            result = branch_to.pull(
1073
1136
                branch_from, overwrite, revision_id, local=local)
1104
1167
    After that you will be able to do a push without '--overwrite'.
1105
1168
 
1106
1169
    If there is no default push location set, the first push will set it (use
1107
 
    --no-remember to avoid settting it).  After that, you can omit the
 
1170
    --no-remember to avoid setting it).  After that, you can omit the
1108
1171
    location to use the default.  To change the default, use --remember. The
1109
1172
    value will only be saved if the remote location can be accessed.
 
1173
 
 
1174
    The --verbose option will display the revisions pushed using the log_format
 
1175
    configuration option. You can use a different format by overriding it with
 
1176
    -Olog_format=<other_format>.
1110
1177
    """
1111
1178
 
1112
1179
    _see_also = ['pull', 'update', 'working-trees']
1150
1217
            directory = '.'
1151
1218
        # Get the source branch
1152
1219
        (tree, br_from,
1153
 
         _unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
 
1220
         _unused) = controldir.ControlDir.open_containing_tree_or_branch(directory)
1154
1221
        # Get the tip's revision_id
1155
1222
        revision = _get_one_revision('push', revision)
1156
1223
        if revision is not None:
1177
1244
                    # error by the feedback given to them. RBC 20080227.
1178
1245
                    stacked_on = parent_url
1179
1246
            if not stacked_on:
1180
 
                raise errors.BzrCommandError(
1181
 
                    "Could not determine branch to refer to.")
 
1247
                raise errors.BzrCommandError(gettext(
 
1248
                    "Could not determine branch to refer to."))
1182
1249
 
1183
1250
        # Get the destination location
1184
1251
        if location is None:
1185
1252
            stored_loc = br_from.get_push_location()
1186
1253
            if stored_loc is None:
1187
 
                raise errors.BzrCommandError(
1188
 
                    "No push location known or specified.")
 
1254
                raise errors.BzrCommandError(gettext(
 
1255
                    "No push location known or specified."))
1189
1256
            else:
1190
1257
                display_url = urlutils.unescape_for_display(stored_loc,
1191
1258
                        self.outf.encoding)
1192
 
                self.outf.write("Using saved push location: %s\n" % display_url)
 
1259
                note(gettext("Using saved push location: %s") % display_url)
1193
1260
                location = stored_loc
1194
1261
 
1195
1262
        _show_push_branch(br_from, revision_id, location, self.outf,
1253
1320
                deprecated_name=self.invoked_as,
1254
1321
                recommended_name='branch',
1255
1322
                deprecated_in_version='2.4')
1256
 
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
 
1323
        accelerator_tree, br_from = controldir.ControlDir.open_tree_or_branch(
1257
1324
            from_location)
1258
1325
        if not (hardlink or files_from):
1259
1326
            # accelerator_tree is usually slower because you have to read N
1272
1339
            # RBC 20060209
1273
1340
            revision_id = br_from.last_revision()
1274
1341
        if to_location is None:
1275
 
            to_location = urlutils.derive_to_location(from_location)
 
1342
            to_location = getattr(br_from, "name", None)
 
1343
            if to_location is None:
 
1344
                to_location = urlutils.derive_to_location(from_location)
1276
1345
        to_transport = transport.get_transport(to_location)
1277
1346
        try:
1278
1347
            to_transport.mkdir('.')
1279
1348
        except errors.FileExists:
1280
 
            if not use_existing_dir:
1281
 
                raise errors.BzrCommandError('Target directory "%s" '
1282
 
                    'already exists.' % to_location)
 
1349
            try:
 
1350
                to_dir = controldir.ControlDir.open_from_transport(
 
1351
                    to_transport)
 
1352
            except errors.NotBranchError:
 
1353
                if not use_existing_dir:
 
1354
                    raise errors.BzrCommandError(gettext('Target directory "%s" '
 
1355
                        'already exists.') % to_location)
 
1356
                else:
 
1357
                    to_dir = None
1283
1358
            else:
1284
1359
                try:
1285
 
                    bzrdir.BzrDir.open_from_transport(to_transport)
 
1360
                    to_dir.open_branch()
1286
1361
                except errors.NotBranchError:
1287
1362
                    pass
1288
1363
                else:
1289
1364
                    raise errors.AlreadyBranchError(to_location)
1290
1365
        except errors.NoSuchFile:
1291
 
            raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
1366
            raise errors.BzrCommandError(gettext('Parent of "%s" does not exist.')
1292
1367
                                         % to_location)
1293
 
        try:
1294
 
            # preserve whatever source format we have.
1295
 
            dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1296
 
                                        possible_transports=[to_transport],
1297
 
                                        accelerator_tree=accelerator_tree,
1298
 
                                        hardlink=hardlink, stacked=stacked,
1299
 
                                        force_new_repo=standalone,
1300
 
                                        create_tree_if_local=not no_tree,
1301
 
                                        source_branch=br_from)
1302
 
            branch = dir.open_branch()
1303
 
        except errors.NoSuchRevision:
1304
 
            to_transport.delete_tree('.')
1305
 
            msg = "The branch %s has no revision %s." % (from_location,
1306
 
                revision)
1307
 
            raise errors.BzrCommandError(msg)
 
1368
        else:
 
1369
            to_dir = None
 
1370
        if to_dir is None:
 
1371
            try:
 
1372
                # preserve whatever source format we have.
 
1373
                to_dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
 
1374
                                            possible_transports=[to_transport],
 
1375
                                            accelerator_tree=accelerator_tree,
 
1376
                                            hardlink=hardlink, stacked=stacked,
 
1377
                                            force_new_repo=standalone,
 
1378
                                            create_tree_if_local=not no_tree,
 
1379
                                            source_branch=br_from)
 
1380
                branch = to_dir.open_branch(
 
1381
                    possible_transports=[
 
1382
                        br_from.bzrdir.root_transport, to_transport])
 
1383
            except errors.NoSuchRevision:
 
1384
                to_transport.delete_tree('.')
 
1385
                msg = gettext("The branch {0} has no revision {1}.").format(
 
1386
                    from_location, revision)
 
1387
                raise errors.BzrCommandError(msg)
 
1388
        else:
 
1389
            branch = br_from.sprout(to_dir, revision_id=revision_id)
1308
1390
        _merge_tags_if_possible(br_from, branch)
1309
1391
        # If the source branch is stacked, the new branch may
1310
1392
        # be stacked whether we asked for that explicitly or not.
1311
1393
        # We therefore need a try/except here and not just 'if stacked:'
1312
1394
        try:
1313
 
            note('Created new stacked branch referring to %s.' %
 
1395
            note(gettext('Created new stacked branch referring to %s.') %
1314
1396
                branch.get_stacked_on_url())
1315
1397
        except (errors.NotStacked, errors.UnstackableBranchFormat,
1316
1398
            errors.UnstackableRepositoryFormat), e:
1317
 
            note('Branched %d revision(s).' % branch.revno())
 
1399
            note(ngettext('Branched %d revision.', 'Branched %d revisions.', branch.revno()) % branch.revno())
1318
1400
        if bind:
1319
1401
            # Bind to the parent
1320
1402
            parent_branch = Branch.open(from_location)
1321
1403
            branch.bind(parent_branch)
1322
 
            note('New branch bound to %s' % from_location)
 
1404
            note(gettext('New branch bound to %s') % from_location)
1323
1405
        if switch:
1324
1406
            # Switch to the new branch
1325
1407
            wt, _ = WorkingTree.open_containing('.')
1326
1408
            _mod_switch.switch(wt.bzrdir, branch)
1327
 
            note('Switched to branch: %s',
 
1409
            note(gettext('Switched to branch: %s'),
1328
1410
                urlutils.unescape_for_display(branch.base, 'utf-8'))
1329
1411
 
1330
1412
 
 
1413
class cmd_branches(Command):
 
1414
    __doc__ = """List the branches available at the current location.
 
1415
 
 
1416
    This command will print the names of all the branches at the current
 
1417
    location.
 
1418
    """
 
1419
 
 
1420
    takes_args = ['location?']
 
1421
    takes_options = [
 
1422
                  Option('recursive', short_name='R',
 
1423
                         help='Recursively scan for branches rather than '
 
1424
                              'just looking in the specified location.')]
 
1425
 
 
1426
    def run(self, location=".", recursive=False):
 
1427
        if recursive:
 
1428
            t = transport.get_transport(location)
 
1429
            if not t.listable():
 
1430
                raise errors.BzrCommandError(
 
1431
                    "Can't scan this type of location.")
 
1432
            for b in controldir.ControlDir.find_branches(t):
 
1433
                self.outf.write("%s\n" % urlutils.unescape_for_display(
 
1434
                    urlutils.relative_url(t.base, b.base),
 
1435
                    self.outf.encoding).rstrip("/"))
 
1436
        else:
 
1437
            dir = controldir.ControlDir.open_containing(location)[0]
 
1438
            for branch in dir.list_branches():
 
1439
                if branch.name is None:
 
1440
                    self.outf.write(gettext(" (default)\n"))
 
1441
                else:
 
1442
                    self.outf.write(" %s\n" % branch.name.encode(
 
1443
                        self.outf.encoding))
 
1444
 
 
1445
 
1331
1446
class cmd_checkout(Command):
1332
1447
    __doc__ = """Create a new checkout of an existing branch.
1333
1448
 
1372
1487
        if branch_location is None:
1373
1488
            branch_location = osutils.getcwd()
1374
1489
            to_location = branch_location
1375
 
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
 
1490
        accelerator_tree, source = controldir.ControlDir.open_tree_or_branch(
1376
1491
            branch_location)
1377
1492
        if not (hardlink or files_from):
1378
1493
            # accelerator_tree is usually slower because you have to read N
1433
1548
 
1434
1549
 
1435
1550
class cmd_update(Command):
1436
 
    __doc__ = """Update a tree to have the latest code committed to its branch.
1437
 
 
1438
 
    This will perform a merge into the working tree, and may generate
1439
 
    conflicts. If you have any local changes, you will still
1440
 
    need to commit them after the update for the update to be complete.
1441
 
 
1442
 
    If you want to discard your local changes, you can just do a
1443
 
    'bzr revert' instead of 'bzr commit' after the update.
1444
 
 
1445
 
    If you want to restore a file that has been removed locally, use
1446
 
    'bzr revert' instead of 'bzr update'.
1447
 
 
1448
 
    If the tree's branch is bound to a master branch, it will also update
 
1551
    __doc__ = """Update a working tree to a new revision.
 
1552
 
 
1553
    This will perform a merge of the destination revision (the tip of the
 
1554
    branch, or the specified revision) into the working tree, and then make
 
1555
    that revision the basis revision for the working tree.  
 
1556
 
 
1557
    You can use this to visit an older revision, or to update a working tree
 
1558
    that is out of date from its branch.
 
1559
    
 
1560
    If there are any uncommitted changes in the tree, they will be carried
 
1561
    across and remain as uncommitted changes after the update.  To discard
 
1562
    these changes, use 'bzr revert'.  The uncommitted changes may conflict
 
1563
    with the changes brought in by the change in basis revision.
 
1564
 
 
1565
    If the tree's branch is bound to a master branch, bzr will also update
1449
1566
    the branch from the master.
 
1567
 
 
1568
    You cannot update just a single file or directory, because each Bazaar
 
1569
    working tree has just a single basis revision.  If you want to restore a
 
1570
    file that has been removed locally, use 'bzr revert' instead of 'bzr
 
1571
    update'.  If you want to restore a file to its state in a previous
 
1572
    revision, use 'bzr revert' with a '-r' option, or use 'bzr cat' to write
 
1573
    out the old content of that file to a new location.
 
1574
 
 
1575
    The 'dir' argument, if given, must be the location of the root of a
 
1576
    working tree to update.  By default, the working tree that contains the 
 
1577
    current working directory is used.
1450
1578
    """
1451
1579
 
1452
1580
    _see_also = ['pull', 'working-trees', 'status-flags']
1457
1585
                     ]
1458
1586
    aliases = ['up']
1459
1587
 
1460
 
    def run(self, dir='.', revision=None, show_base=None):
 
1588
    def run(self, dir=None, revision=None, show_base=None):
1461
1589
        if revision is not None and len(revision) != 1:
1462
 
            raise errors.BzrCommandError(
1463
 
                        "bzr update --revision takes exactly one revision")
1464
 
        tree = WorkingTree.open_containing(dir)[0]
 
1590
            raise errors.BzrCommandError(gettext(
 
1591
                "bzr update --revision takes exactly one revision"))
 
1592
        if dir is None:
 
1593
            tree = WorkingTree.open_containing('.')[0]
 
1594
        else:
 
1595
            tree, relpath = WorkingTree.open_containing(dir)
 
1596
            if relpath:
 
1597
                # See bug 557886.
 
1598
                raise errors.BzrCommandError(gettext(
 
1599
                    "bzr update can only update a whole tree, "
 
1600
                    "not a file or subdirectory"))
1465
1601
        branch = tree.branch
1466
1602
        possible_transports = []
1467
1603
        master = branch.get_master_branch(
1491
1627
            revision_id = branch.last_revision()
1492
1628
        if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1493
1629
            revno = branch.revision_id_to_dotted_revno(revision_id)
1494
 
            note("Tree is up to date at revision %s of branch %s" %
1495
 
                ('.'.join(map(str, revno)), branch_location))
 
1630
            note(gettext("Tree is up to date at revision {0} of branch {1}"
 
1631
                        ).format('.'.join(map(str, revno)), branch_location))
1496
1632
            return 0
1497
1633
        view_info = _get_view_info_for_change_reporter(tree)
1498
1634
        change_reporter = delta._ChangeReporter(
1506
1642
                old_tip=old_tip,
1507
1643
                show_base=show_base)
1508
1644
        except errors.NoSuchRevision, e:
1509
 
            raise errors.BzrCommandError(
 
1645
            raise errors.BzrCommandError(gettext(
1510
1646
                                  "branch has no revision %s\n"
1511
1647
                                  "bzr update --revision only works"
1512
 
                                  " for a revision in the branch history"
 
1648
                                  " for a revision in the branch history")
1513
1649
                                  % (e.revision))
1514
1650
        revno = tree.branch.revision_id_to_dotted_revno(
1515
1651
            _mod_revision.ensure_null(tree.last_revision()))
1516
 
        note('Updated to revision %s of branch %s' %
1517
 
             ('.'.join(map(str, revno)), branch_location))
 
1652
        note(gettext('Updated to revision {0} of branch {1}').format(
 
1653
             '.'.join(map(str, revno)), branch_location))
1518
1654
        parent_ids = tree.get_parent_ids()
1519
1655
        if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1520
 
            note('Your local commits will now show as pending merges with '
1521
 
                 "'bzr status', and can be committed with 'bzr commit'.")
 
1656
            note(gettext('Your local commits will now show as pending merges with '
 
1657
                 "'bzr status', and can be committed with 'bzr commit'."))
1522
1658
        if conflicts != 0:
1523
1659
            return 1
1524
1660
        else:
1565
1701
        else:
1566
1702
            noise_level = 0
1567
1703
        from bzrlib.info import show_bzrdir_info
1568
 
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
 
1704
        show_bzrdir_info(controldir.ControlDir.open_containing(location)[0],
1569
1705
                         verbose=noise_level, outfile=self.outf)
1570
1706
 
1571
1707
 
1596
1732
    def run(self, file_list, verbose=False, new=False,
1597
1733
        file_deletion_strategy='safe'):
1598
1734
        if file_deletion_strategy == 'force':
1599
 
            note("(The --force option is deprecated, rather use --no-backup "
1600
 
                "in future.)")
 
1735
            note(gettext("(The --force option is deprecated, rather use --no-backup "
 
1736
                "in future.)"))
1601
1737
            file_deletion_strategy = 'no-backup'
1602
1738
 
1603
1739
        tree, file_list = WorkingTree.open_containing_paths(file_list)
1613
1749
                specific_files=file_list).added
1614
1750
            file_list = sorted([f[0] for f in added], reverse=True)
1615
1751
            if len(file_list) == 0:
1616
 
                raise errors.BzrCommandError('No matching files.')
 
1752
                raise errors.BzrCommandError(gettext('No matching files.'))
1617
1753
        elif file_list is None:
1618
1754
            # missing files show up in iter_changes(basis) as
1619
1755
            # versioned-with-no-kind.
1703
1839
 
1704
1840
    def run(self, branch=".", canonicalize_chks=False):
1705
1841
        from bzrlib.reconcile import reconcile
1706
 
        dir = bzrdir.BzrDir.open(branch)
 
1842
        dir = controldir.ControlDir.open(branch)
1707
1843
        reconcile(dir, canonicalize_chks=canonicalize_chks)
1708
1844
 
1709
1845
 
1718
1854
    @display_command
1719
1855
    def run(self, location="."):
1720
1856
        branch = Branch.open_containing(location)[0]
1721
 
        for revid in branch.revision_history():
 
1857
        self.add_cleanup(branch.lock_read().unlock)
 
1858
        graph = branch.repository.get_graph()
 
1859
        history = list(graph.iter_lefthand_ancestry(branch.last_revision(),
 
1860
            [_mod_revision.NULL_REVISION]))
 
1861
        for revid in reversed(history):
1722
1862
            self.outf.write(revid)
1723
1863
            self.outf.write('\n')
1724
1864
 
1785
1925
                help='Specify a format for this branch. '
1786
1926
                'See "help formats".',
1787
1927
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1788
 
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
1928
                converter=lambda name: controldir.format_registry.make_bzrdir(name),
1789
1929
                value_switches=True,
1790
1930
                title="Branch format",
1791
1931
                ),
1798
1938
    def run(self, location=None, format=None, append_revisions_only=False,
1799
1939
            create_prefix=False, no_tree=False):
1800
1940
        if format is None:
1801
 
            format = bzrdir.format_registry.make_bzrdir('default')
 
1941
            format = controldir.format_registry.make_bzrdir('default')
1802
1942
        if location is None:
1803
1943
            location = u'.'
1804
1944
 
1813
1953
            to_transport.ensure_base()
1814
1954
        except errors.NoSuchFile:
1815
1955
            if not create_prefix:
1816
 
                raise errors.BzrCommandError("Parent directory of %s"
 
1956
                raise errors.BzrCommandError(gettext("Parent directory of %s"
1817
1957
                    " does not exist."
1818
1958
                    "\nYou may supply --create-prefix to create all"
1819
 
                    " leading parent directories."
 
1959
                    " leading parent directories.")
1820
1960
                    % location)
1821
1961
            to_transport.create_prefix()
1822
1962
 
1823
1963
        try:
1824
 
            a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
 
1964
            a_bzrdir = controldir.ControlDir.open_from_transport(to_transport)
1825
1965
        except errors.NotBranchError:
1826
1966
            # really a NotBzrDir error...
1827
 
            create_branch = bzrdir.BzrDir.create_branch_convenience
 
1967
            create_branch = controldir.ControlDir.create_branch_convenience
1828
1968
            if no_tree:
1829
1969
                force_new_tree = False
1830
1970
            else:
1841
1981
                        raise errors.BranchExistsWithoutWorkingTree(location)
1842
1982
                raise errors.AlreadyBranchError(location)
1843
1983
            branch = a_bzrdir.create_branch()
1844
 
            if not no_tree:
 
1984
            if not no_tree and not a_bzrdir.has_workingtree():
1845
1985
                a_bzrdir.create_workingtree()
1846
1986
        if append_revisions_only:
1847
1987
            try:
1848
1988
                branch.set_append_revisions_only(True)
1849
1989
            except errors.UpgradeRequired:
1850
 
                raise errors.BzrCommandError('This branch format cannot be set'
1851
 
                    ' to append-revisions-only.  Try --default.')
 
1990
                raise errors.BzrCommandError(gettext('This branch format cannot be set'
 
1991
                    ' to append-revisions-only.  Try --default.'))
1852
1992
        if not is_quiet():
1853
1993
            from bzrlib.info import describe_layout, describe_format
1854
1994
            try:
1858
1998
            repository = branch.repository
1859
1999
            layout = describe_layout(repository, branch, tree).lower()
1860
2000
            format = describe_format(a_bzrdir, repository, branch, tree)
1861
 
            self.outf.write("Created a %s (format: %s)\n" % (layout, format))
 
2001
            self.outf.write(gettext("Created a {0} (format: {1})\n").format(
 
2002
                  layout, format))
1862
2003
            if repository.is_shared():
1863
2004
                #XXX: maybe this can be refactored into transport.path_or_url()
1864
2005
                url = repository.bzrdir.root_transport.external_url()
1866
2007
                    url = urlutils.local_path_from_url(url)
1867
2008
                except errors.InvalidURL:
1868
2009
                    pass
1869
 
                self.outf.write("Using shared repository: %s\n" % url)
 
2010
                self.outf.write(gettext("Using shared repository: %s\n") % url)
1870
2011
 
1871
2012
 
1872
2013
class cmd_init_repository(Command):
1902
2043
    takes_options = [RegistryOption('format',
1903
2044
                            help='Specify a format for this repository. See'
1904
2045
                                 ' "bzr help formats" for details.',
1905
 
                            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1906
 
                            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
2046
                            lazy_registry=('bzrlib.controldir', 'format_registry'),
 
2047
                            converter=lambda name: controldir.format_registry.make_bzrdir(name),
1907
2048
                            value_switches=True, title='Repository format'),
1908
2049
                     Option('no-trees',
1909
2050
                             help='Branches in the repository will default to'
1913
2054
 
1914
2055
    def run(self, location, format=None, no_trees=False):
1915
2056
        if format is None:
1916
 
            format = bzrdir.format_registry.make_bzrdir('default')
 
2057
            format = controldir.format_registry.make_bzrdir('default')
1917
2058
 
1918
2059
        if location is None:
1919
2060
            location = '.'
2063
2204
        elif ':' in prefix:
2064
2205
            old_label, new_label = prefix.split(":")
2065
2206
        else:
2066
 
            raise errors.BzrCommandError(
 
2207
            raise errors.BzrCommandError(gettext(
2067
2208
                '--prefix expects two values separated by a colon'
2068
 
                ' (eg "old/:new/")')
 
2209
                ' (eg "old/:new/")'))
2069
2210
 
2070
2211
        if revision and len(revision) > 2:
2071
 
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
2072
 
                                         ' one or two revision specifiers')
 
2212
            raise errors.BzrCommandError(gettext('bzr diff --revision takes exactly'
 
2213
                                         ' one or two revision specifiers'))
2073
2214
 
2074
2215
        if using is not None and format is not None:
2075
 
            raise errors.BzrCommandError('--using and --format are mutually '
2076
 
                'exclusive.')
 
2216
            raise errors.BzrCommandError(gettext(
 
2217
                '{0} and {1} are mutually exclusive').format(
 
2218
                '--using', '--format'))
2077
2219
 
2078
2220
        (old_tree, new_tree,
2079
2221
         old_branch, new_branch,
2187
2329
    try:
2188
2330
        return int(limitstring)
2189
2331
    except ValueError:
2190
 
        msg = "The limit argument must be an integer."
 
2332
        msg = gettext("The limit argument must be an integer.")
2191
2333
        raise errors.BzrCommandError(msg)
2192
2334
 
2193
2335
 
2195
2337
    try:
2196
2338
        return int(s)
2197
2339
    except ValueError:
2198
 
        msg = "The levels argument must be an integer."
 
2340
        msg = gettext("The levels argument must be an integer.")
2199
2341
        raise errors.BzrCommandError(msg)
2200
2342
 
2201
2343
 
2311
2453
 
2312
2454
    :Other filtering:
2313
2455
 
2314
 
      The --message option can be used for finding revisions that match a
2315
 
      regular expression in a commit message.
 
2456
      The --match option can be used for finding revisions that match a
 
2457
      regular expression in a commit message, committer, author or bug.
 
2458
      Specifying the option several times will match any of the supplied
 
2459
      expressions. --match-author, --match-bugs, --match-committer and
 
2460
      --match-message can be used to only match a specific field.
2316
2461
 
2317
2462
    :Tips & tricks:
2318
2463
 
2378
2523
                   argname='N',
2379
2524
                   type=_parse_levels),
2380
2525
            Option('message',
2381
 
                   short_name='m',
2382
2526
                   help='Show revisions whose message matches this '
2383
2527
                        'regular expression.',
2384
 
                   type=str),
 
2528
                   type=str,
 
2529
                   hidden=True),
2385
2530
            Option('limit',
2386
2531
                   short_name='l',
2387
2532
                   help='Limit the output to the first N revisions.',
2390
2535
            Option('show-diff',
2391
2536
                   short_name='p',
2392
2537
                   help='Show changes made in each revision as a patch.'),
2393
 
            Option('include-merges',
 
2538
            Option('include-merged',
2394
2539
                   help='Show merged revisions like --levels 0 does.'),
 
2540
            Option('include-merges', hidden=True,
 
2541
                   help='Historical alias for --include-merged.'),
 
2542
            Option('omit-merges',
 
2543
                   help='Do not report commits with more than one parent.'),
2395
2544
            Option('exclude-common-ancestry',
2396
2545
                   help='Display only the revisions that are not part'
2397
 
                   ' of both ancestries (require -rX..Y)'
 
2546
                   ' of both ancestries (require -rX..Y).'
2398
2547
                   ),
2399
2548
            Option('signatures',
2400
 
                   help='Show digital signature validity'),
 
2549
                   help='Show digital signature validity.'),
 
2550
            ListOption('match',
 
2551
                short_name='m',
 
2552
                help='Show revisions whose properties match this '
 
2553
                'expression.',
 
2554
                type=str),
 
2555
            ListOption('match-message',
 
2556
                   help='Show revisions whose message matches this '
 
2557
                   'expression.',
 
2558
                type=str),
 
2559
            ListOption('match-committer',
 
2560
                   help='Show revisions whose committer matches this '
 
2561
                   'expression.',
 
2562
                type=str),
 
2563
            ListOption('match-author',
 
2564
                   help='Show revisions whose authors match this '
 
2565
                   'expression.',
 
2566
                type=str),
 
2567
            ListOption('match-bugs',
 
2568
                   help='Show revisions whose bugs match this '
 
2569
                   'expression.',
 
2570
                type=str)
2401
2571
            ]
2402
2572
    encoding_type = 'replace'
2403
2573
 
2413
2583
            message=None,
2414
2584
            limit=None,
2415
2585
            show_diff=False,
2416
 
            include_merges=False,
 
2586
            include_merged=None,
2417
2587
            authors=None,
2418
2588
            exclude_common_ancestry=False,
2419
2589
            signatures=False,
 
2590
            match=None,
 
2591
            match_message=None,
 
2592
            match_committer=None,
 
2593
            match_author=None,
 
2594
            match_bugs=None,
 
2595
            omit_merges=False,
 
2596
            include_merges=symbol_versioning.DEPRECATED_PARAMETER,
2420
2597
            ):
2421
2598
        from bzrlib.log import (
2422
2599
            Logger,
2424
2601
            _get_info_for_log_files,
2425
2602
            )
2426
2603
        direction = (forward and 'forward') or 'reverse'
 
2604
        if symbol_versioning.deprecated_passed(include_merges):
 
2605
            ui.ui_factory.show_user_warning(
 
2606
                'deprecated_command_option',
 
2607
                deprecated_name='--include-merges',
 
2608
                recommended_name='--include-merged',
 
2609
                deprecated_in_version='2.5',
 
2610
                command=self.invoked_as)
 
2611
            if include_merged is None:
 
2612
                include_merged = include_merges
 
2613
            else:
 
2614
                raise errors.BzrCommandError(gettext(
 
2615
                    '{0} and {1} are mutually exclusive').format(
 
2616
                    '--include-merges', '--include-merged'))
 
2617
        if include_merged is None:
 
2618
            include_merged = False
2427
2619
        if (exclude_common_ancestry
2428
2620
            and (revision is None or len(revision) != 2)):
2429
 
            raise errors.BzrCommandError(
2430
 
                '--exclude-common-ancestry requires -r with two revisions')
2431
 
        if include_merges:
 
2621
            raise errors.BzrCommandError(gettext(
 
2622
                '--exclude-common-ancestry requires -r with two revisions'))
 
2623
        if include_merged:
2432
2624
            if levels is None:
2433
2625
                levels = 0
2434
2626
            else:
2435
 
                raise errors.BzrCommandError(
2436
 
                    '--levels and --include-merges are mutually exclusive')
 
2627
                raise errors.BzrCommandError(gettext(
 
2628
                    '{0} and {1} are mutually exclusive').format(
 
2629
                    '--levels', '--include-merged'))
2437
2630
 
2438
2631
        if change is not None:
2439
2632
            if len(change) > 1:
2440
2633
                raise errors.RangeInChangeOption()
2441
2634
            if revision is not None:
2442
 
                raise errors.BzrCommandError(
2443
 
                    '--revision and --change are mutually exclusive')
 
2635
                raise errors.BzrCommandError(gettext(
 
2636
                    '{0} and {1} are mutually exclusive').format(
 
2637
                    '--revision', '--change'))
2444
2638
            else:
2445
2639
                revision = change
2446
2640
 
2452
2646
                revision, file_list, self.add_cleanup)
2453
2647
            for relpath, file_id, kind in file_info_list:
2454
2648
                if file_id is None:
2455
 
                    raise errors.BzrCommandError(
2456
 
                        "Path unknown at end or start of revision range: %s" %
 
2649
                    raise errors.BzrCommandError(gettext(
 
2650
                        "Path unknown at end or start of revision range: %s") %
2457
2651
                        relpath)
2458
2652
                # If the relpath is the top of the tree, we log everything
2459
2653
                if relpath == '':
2471
2665
                location = revision[0].get_branch()
2472
2666
            else:
2473
2667
                location = '.'
2474
 
            dir, relpath = bzrdir.BzrDir.open_containing(location)
 
2668
            dir, relpath = controldir.ControlDir.open_containing(location)
2475
2669
            b = dir.open_branch()
2476
2670
            self.add_cleanup(b.lock_read().unlock)
2477
2671
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2525
2719
        match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2526
2720
            or delta_type or partial_history)
2527
2721
 
 
2722
        match_dict = {}
 
2723
        if match:
 
2724
            match_dict[''] = match
 
2725
        if match_message:
 
2726
            match_dict['message'] = match_message
 
2727
        if match_committer:
 
2728
            match_dict['committer'] = match_committer
 
2729
        if match_author:
 
2730
            match_dict['author'] = match_author
 
2731
        if match_bugs:
 
2732
            match_dict['bugs'] = match_bugs
 
2733
 
2528
2734
        # Build the LogRequest and execute it
2529
2735
        if len(file_ids) == 0:
2530
2736
            file_ids = None
2533
2739
            start_revision=rev1, end_revision=rev2, limit=limit,
2534
2740
            message_search=message, delta_type=delta_type,
2535
2741
            diff_type=diff_type, _match_using_deltas=match_using_deltas,
2536
 
            exclude_common_ancestry=exclude_common_ancestry,
2537
 
            signature=signatures
 
2742
            exclude_common_ancestry=exclude_common_ancestry, match=match_dict,
 
2743
            signature=signatures, omit_merges=omit_merges,
2538
2744
            )
2539
2745
        Logger(b, rqst).show(lf)
2540
2746
 
2557
2763
            # b is taken from revision[0].get_branch(), and
2558
2764
            # show_log will use its revision_history. Having
2559
2765
            # different branches will lead to weird behaviors.
2560
 
            raise errors.BzrCommandError(
 
2766
            raise errors.BzrCommandError(gettext(
2561
2767
                "bzr %s doesn't accept two revisions in different"
2562
 
                " branches." % command_name)
 
2768
                " branches.") % command_name)
2563
2769
        if start_spec.spec is None:
2564
2770
            # Avoid loading all the history.
2565
2771
            rev1 = RevisionInfo(branch, None, None)
2573
2779
        else:
2574
2780
            rev2 = end_spec.in_history(branch)
2575
2781
    else:
2576
 
        raise errors.BzrCommandError(
2577
 
            'bzr %s --revision takes one or two values.' % command_name)
 
2782
        raise errors.BzrCommandError(gettext(
 
2783
            'bzr %s --revision takes one or two values.') % command_name)
2578
2784
    return rev1, rev2
2579
2785
 
2580
2786
 
2651
2857
            null=False, kind=None, show_ids=False, path=None, directory=None):
2652
2858
 
2653
2859
        if kind and kind not in ('file', 'directory', 'symlink'):
2654
 
            raise errors.BzrCommandError('invalid kind specified')
 
2860
            raise errors.BzrCommandError(gettext('invalid kind specified'))
2655
2861
 
2656
2862
        if verbose and null:
2657
 
            raise errors.BzrCommandError('Cannot set both --verbose and --null')
 
2863
            raise errors.BzrCommandError(gettext('Cannot set both --verbose and --null'))
2658
2864
        all = not (unknown or versioned or ignored)
2659
2865
 
2660
2866
        selection = {'I':ignored, '?':unknown, 'V':versioned}
2663
2869
            fs_path = '.'
2664
2870
        else:
2665
2871
            if from_root:
2666
 
                raise errors.BzrCommandError('cannot specify both --from-root'
2667
 
                                             ' and PATH')
 
2872
                raise errors.BzrCommandError(gettext('cannot specify both --from-root'
 
2873
                                             ' and PATH'))
2668
2874
            fs_path = path
2669
2875
        tree, branch, relpath = \
2670
2876
            _open_directory_or_containing_tree_or_branch(fs_path, directory)
2686
2892
            if view_files:
2687
2893
                apply_view = True
2688
2894
                view_str = views.view_display_str(view_files)
2689
 
                note("Ignoring files outside view. View is %s" % view_str)
 
2895
                note(gettext("Ignoring files outside view. View is %s") % view_str)
2690
2896
 
2691
2897
        self.add_cleanup(tree.lock_read().unlock)
2692
2898
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2839
3045
                self.outf.write("%s\n" % pattern)
2840
3046
            return
2841
3047
        if not name_pattern_list:
2842
 
            raise errors.BzrCommandError("ignore requires at least one "
2843
 
                "NAME_PATTERN or --default-rules.")
 
3048
            raise errors.BzrCommandError(gettext("ignore requires at least one "
 
3049
                "NAME_PATTERN or --default-rules."))
2844
3050
        name_pattern_list = [globbing.normalize_pattern(p)
2845
3051
                             for p in name_pattern_list]
2846
3052
        bad_patterns = ''
 
3053
        bad_patterns_count = 0
2847
3054
        for p in name_pattern_list:
2848
3055
            if not globbing.Globster.is_pattern_valid(p):
 
3056
                bad_patterns_count += 1
2849
3057
                bad_patterns += ('\n  %s' % p)
2850
3058
        if bad_patterns:
2851
 
            msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
 
3059
            msg = (ngettext('Invalid ignore pattern found. %s', 
 
3060
                            'Invalid ignore patterns found. %s',
 
3061
                            bad_patterns_count) % bad_patterns)
2852
3062
            ui.ui_factory.show_error(msg)
2853
3063
            raise errors.InvalidPattern('')
2854
3064
        for name_pattern in name_pattern_list:
2855
3065
            if (name_pattern[0] == '/' or
2856
3066
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
2857
 
                raise errors.BzrCommandError(
2858
 
                    "NAME_PATTERN should not be an absolute path")
 
3067
                raise errors.BzrCommandError(gettext(
 
3068
                    "NAME_PATTERN should not be an absolute path"))
2859
3069
        tree, relpath = WorkingTree.open_containing(directory)
2860
3070
        ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2861
3071
        ignored = globbing.Globster(name_pattern_list)
2868
3078
                if ignored.match(filename):
2869
3079
                    matches.append(filename)
2870
3080
        if len(matches) > 0:
2871
 
            self.outf.write("Warning: the following files are version controlled and"
2872
 
                  " match your ignore pattern:\n%s"
 
3081
            self.outf.write(gettext("Warning: the following files are version "
 
3082
                  "controlled and match your ignore pattern:\n%s"
2873
3083
                  "\nThese files will continue to be version controlled"
2874
 
                  " unless you 'bzr remove' them.\n" % ("\n".join(matches),))
 
3084
                  " unless you 'bzr remove' them.\n") % ("\n".join(matches),))
2875
3085
 
2876
3086
 
2877
3087
class cmd_ignored(Command):
2916
3126
        try:
2917
3127
            revno = int(revno)
2918
3128
        except ValueError:
2919
 
            raise errors.BzrCommandError("not a valid revision-number: %r"
 
3129
            raise errors.BzrCommandError(gettext("not a valid revision-number: %r")
2920
3130
                                         % revno)
2921
3131
        revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2922
3132
        self.outf.write("%s\n" % revid)
2965
3175
        Option('per-file-timestamps',
2966
3176
               help='Set modification time of files to that of the last '
2967
3177
                    'revision in which it was changed.'),
 
3178
        Option('uncommitted',
 
3179
               help='Export the working tree contents rather than that of the '
 
3180
                    'last revision.'),
2968
3181
        ]
2969
3182
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2970
 
        root=None, filters=False, per_file_timestamps=False, directory=u'.'):
 
3183
        root=None, filters=False, per_file_timestamps=False, uncommitted=False,
 
3184
        directory=u'.'):
2971
3185
        from bzrlib.export import export
2972
3186
 
2973
3187
        if branch_or_subdir is None:
2974
 
            tree = WorkingTree.open_containing(directory)[0]
2975
 
            b = tree.branch
2976
 
            subdir = None
 
3188
            branch_or_subdir = directory
 
3189
 
 
3190
        (tree, b, subdir) = controldir.ControlDir.open_containing_tree_or_branch(
 
3191
            branch_or_subdir)
 
3192
        if tree is not None:
 
3193
            self.add_cleanup(tree.lock_read().unlock)
 
3194
 
 
3195
        if uncommitted:
 
3196
            if tree is None:
 
3197
                raise errors.BzrCommandError(
 
3198
                    gettext("--uncommitted requires a working tree"))
 
3199
            export_tree = tree
2977
3200
        else:
2978
 
            b, subdir = Branch.open_containing(branch_or_subdir)
2979
 
            tree = None
2980
 
 
2981
 
        rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
 
3201
            export_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2982
3202
        try:
2983
 
            export(rev_tree, dest, format, root, subdir, filtered=filters,
 
3203
            export(export_tree, dest, format, root, subdir, filtered=filters,
2984
3204
                   per_file_timestamps=per_file_timestamps)
2985
3205
        except errors.NoSuchExportFormat, e:
2986
 
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
 
3206
            raise errors.BzrCommandError(
 
3207
                gettext('Unsupported export format: %s') % e.format)
2987
3208
 
2988
3209
 
2989
3210
class cmd_cat(Command):
3009
3230
    def run(self, filename, revision=None, name_from_revision=False,
3010
3231
            filters=False, directory=None):
3011
3232
        if revision is not None and len(revision) != 1:
3012
 
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
3013
 
                                         " one revision specifier")
 
3233
            raise errors.BzrCommandError(gettext("bzr cat --revision takes exactly"
 
3234
                                         " one revision specifier"))
3014
3235
        tree, branch, relpath = \
3015
3236
            _open_directory_or_containing_tree_or_branch(filename, directory)
3016
3237
        self.add_cleanup(branch.lock_read().unlock)
3026
3247
 
3027
3248
        old_file_id = rev_tree.path2id(relpath)
3028
3249
 
 
3250
        # TODO: Split out this code to something that generically finds the
 
3251
        # best id for a path across one or more trees; it's like
 
3252
        # find_ids_across_trees but restricted to find just one. -- mbp
 
3253
        # 20110705.
3029
3254
        if name_from_revision:
3030
3255
            # Try in revision if requested
3031
3256
            if old_file_id is None:
3032
 
                raise errors.BzrCommandError(
3033
 
                    "%r is not present in revision %s" % (
 
3257
                raise errors.BzrCommandError(gettext(
 
3258
                    "{0!r} is not present in revision {1}").format(
3034
3259
                        filename, rev_tree.get_revision_id()))
3035
3260
            else:
3036
 
                content = rev_tree.get_file_text(old_file_id)
 
3261
                actual_file_id = old_file_id
3037
3262
        else:
3038
3263
            cur_file_id = tree.path2id(relpath)
3039
 
            found = False
3040
 
            if cur_file_id is not None:
3041
 
                # Then try with the actual file id
3042
 
                try:
3043
 
                    content = rev_tree.get_file_text(cur_file_id)
3044
 
                    found = True
3045
 
                except errors.NoSuchId:
3046
 
                    # The actual file id didn't exist at that time
3047
 
                    pass
3048
 
            if not found and old_file_id is not None:
3049
 
                # Finally try with the old file id
3050
 
                content = rev_tree.get_file_text(old_file_id)
3051
 
                found = True
3052
 
            if not found:
3053
 
                # Can't be found anywhere
3054
 
                raise errors.BzrCommandError(
3055
 
                    "%r is not present in revision %s" % (
 
3264
            if cur_file_id is not None and rev_tree.has_id(cur_file_id):
 
3265
                actual_file_id = cur_file_id
 
3266
            elif old_file_id is not None:
 
3267
                actual_file_id = old_file_id
 
3268
            else:
 
3269
                raise errors.BzrCommandError(gettext(
 
3270
                    "{0!r} is not present in revision {1}").format(
3056
3271
                        filename, rev_tree.get_revision_id()))
3057
3272
        if filtered:
3058
 
            from bzrlib.filters import (
3059
 
                ContentFilterContext,
3060
 
                filtered_output_bytes,
3061
 
                )
3062
 
            filters = rev_tree._content_filter_stack(relpath)
3063
 
            chunks = content.splitlines(True)
3064
 
            content = filtered_output_bytes(chunks, filters,
3065
 
                ContentFilterContext(relpath, rev_tree))
3066
 
            self.cleanup_now()
3067
 
            self.outf.writelines(content)
 
3273
            from bzrlib.filter_tree import ContentFilterTree
 
3274
            filter_tree = ContentFilterTree(rev_tree,
 
3275
                rev_tree._content_filter_stack)
 
3276
            content = filter_tree.get_file_text(actual_file_id)
3068
3277
        else:
3069
 
            self.cleanup_now()
3070
 
            self.outf.write(content)
 
3278
            content = rev_tree.get_file_text(actual_file_id)
 
3279
        self.cleanup_now()
 
3280
        self.outf.write(content)
3071
3281
 
3072
3282
 
3073
3283
class cmd_local_time_offset(Command):
3180
3390
    aliases = ['ci', 'checkin']
3181
3391
 
3182
3392
    def _iter_bug_fix_urls(self, fixes, branch):
 
3393
        default_bugtracker  = None
3183
3394
        # Configure the properties for bug fixing attributes.
3184
3395
        for fixed_bug in fixes:
3185
3396
            tokens = fixed_bug.split(':')
3186
 
            if len(tokens) != 2:
3187
 
                raise errors.BzrCommandError(
 
3397
            if len(tokens) == 1:
 
3398
                if default_bugtracker is None:
 
3399
                    branch_config = branch.get_config()
 
3400
                    default_bugtracker = branch_config.get_user_option(
 
3401
                        "bugtracker")
 
3402
                if default_bugtracker is None:
 
3403
                    raise errors.BzrCommandError(gettext(
 
3404
                        "No tracker specified for bug %s. Use the form "
 
3405
                        "'tracker:id' or specify a default bug tracker "
 
3406
                        "using the `bugtracker` option.\nSee "
 
3407
                        "\"bzr help bugs\" for more information on this "
 
3408
                        "feature. Commit refused.") % fixed_bug)
 
3409
                tag = default_bugtracker
 
3410
                bug_id = tokens[0]
 
3411
            elif len(tokens) != 2:
 
3412
                raise errors.BzrCommandError(gettext(
3188
3413
                    "Invalid bug %s. Must be in the form of 'tracker:id'. "
3189
3414
                    "See \"bzr help bugs\" for more information on this "
3190
 
                    "feature.\nCommit refused." % fixed_bug)
3191
 
            tag, bug_id = tokens
 
3415
                    "feature.\nCommit refused.") % fixed_bug)
 
3416
            else:
 
3417
                tag, bug_id = tokens
3192
3418
            try:
3193
3419
                yield bugtracker.get_bug_url(tag, branch, bug_id)
3194
3420
            except errors.UnknownBugTrackerAbbreviation:
3195
 
                raise errors.BzrCommandError(
3196
 
                    'Unrecognized bug %s. Commit refused.' % fixed_bug)
 
3421
                raise errors.BzrCommandError(gettext(
 
3422
                    'Unrecognized bug %s. Commit refused.') % fixed_bug)
3197
3423
            except errors.MalformedBugIdentifier, e:
3198
 
                raise errors.BzrCommandError(
3199
 
                    "%s\nCommit refused." % (str(e),))
 
3424
                raise errors.BzrCommandError(gettext(
 
3425
                    "%s\nCommit refused.") % (str(e),))
3200
3426
 
3201
3427
    def run(self, message=None, file=None, verbose=False, selected_list=None,
3202
3428
            unchanged=False, strict=False, local=False, fixes=None,
3219
3445
            try:
3220
3446
                commit_stamp, offset = timestamp.parse_patch_date(commit_time)
3221
3447
            except ValueError, e:
3222
 
                raise errors.BzrCommandError(
3223
 
                    "Could not parse --commit-time: " + str(e))
 
3448
                raise errors.BzrCommandError(gettext(
 
3449
                    "Could not parse --commit-time: " + str(e)))
3224
3450
 
3225
3451
        properties = {}
3226
3452
 
3259
3485
                message = message.replace('\r\n', '\n')
3260
3486
                message = message.replace('\r', '\n')
3261
3487
            if file:
3262
 
                raise errors.BzrCommandError(
3263
 
                    "please specify either --message or --file")
 
3488
                raise errors.BzrCommandError(gettext(
 
3489
                    "please specify either --message or --file"))
3264
3490
 
3265
3491
        def get_message(commit_obj):
3266
3492
            """Callback to get commit message"""
3289
3515
                    my_message = edit_commit_message_encoded(text,
3290
3516
                        start_message=start_message)
3291
3517
                if my_message is None:
3292
 
                    raise errors.BzrCommandError("please specify a commit"
3293
 
                        " message with either --message or --file")
3294
 
            if my_message == "":
3295
 
                raise errors.BzrCommandError("empty commit message specified")
 
3518
                    raise errors.BzrCommandError(gettext("please specify a commit"
 
3519
                        " message with either --message or --file"))
 
3520
                if my_message == "":
 
3521
                    raise errors.BzrCommandError(gettext("Empty commit message specified."
 
3522
                            " Please specify a commit message with either"
 
3523
                            " --message or --file or leave a blank message"
 
3524
                            " with --message \"\"."))
3296
3525
            return my_message
3297
3526
 
3298
3527
        # The API permits a commit with a filter of [] to mean 'select nothing'
3309
3538
                        exclude=tree.safe_relpath_files(exclude),
3310
3539
                        lossy=lossy)
3311
3540
        except PointlessCommit:
3312
 
            raise errors.BzrCommandError("No changes to commit."
 
3541
            raise errors.BzrCommandError(gettext("No changes to commit."
3313
3542
                " Please 'bzr add' the files you want to commit, or use"
3314
 
                " --unchanged to force an empty commit.")
 
3543
                " --unchanged to force an empty commit."))
3315
3544
        except ConflictsInTree:
3316
 
            raise errors.BzrCommandError('Conflicts detected in working '
 
3545
            raise errors.BzrCommandError(gettext('Conflicts detected in working '
3317
3546
                'tree.  Use "bzr conflicts" to list, "bzr resolve FILE" to'
3318
 
                ' resolve.')
 
3547
                ' resolve.'))
3319
3548
        except StrictCommitFailed:
3320
 
            raise errors.BzrCommandError("Commit refused because there are"
3321
 
                              " unknown files in the working tree.")
 
3549
            raise errors.BzrCommandError(gettext("Commit refused because there are"
 
3550
                              " unknown files in the working tree."))
3322
3551
        except errors.BoundBranchOutOfDate, e:
3323
 
            e.extra_help = ("\n"
 
3552
            e.extra_help = (gettext("\n"
3324
3553
                'To commit to master branch, run update and then commit.\n'
3325
3554
                'You can also pass --local to commit to continue working '
3326
 
                'disconnected.')
 
3555
                'disconnected.'))
3327
3556
            raise
3328
3557
 
3329
3558
 
3436
3665
        RegistryOption('format',
3437
3666
            help='Upgrade to a specific format.  See "bzr help'
3438
3667
                 ' formats" for details.',
3439
 
            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3440
 
            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
3668
            lazy_registry=('bzrlib.controldir', 'format_registry'),
 
3669
            converter=lambda name: controldir.format_registry.make_bzrdir(name),
3441
3670
            value_switches=True, title='Branch format'),
3442
3671
        Option('clean',
3443
3672
            help='Remove the backup.bzr directory if successful.'),
3484
3713
            if directory is None:
3485
3714
                # use branch if we're inside one; otherwise global config
3486
3715
                try:
3487
 
                    c = Branch.open_containing(u'.')[0].get_config()
 
3716
                    c = Branch.open_containing(u'.')[0].get_config_stack()
3488
3717
                except errors.NotBranchError:
3489
 
                    c = _mod_config.GlobalConfig()
 
3718
                    c = _mod_config.GlobalStack()
3490
3719
            else:
3491
 
                c = Branch.open(directory).get_config()
 
3720
                c = Branch.open(directory).get_config_stack()
 
3721
            identity = c.get('email')
3492
3722
            if email:
3493
 
                self.outf.write(c.user_email() + '\n')
 
3723
                self.outf.write(_mod_config.extract_email_address(identity)
 
3724
                                + '\n')
3494
3725
            else:
3495
 
                self.outf.write(c.username() + '\n')
 
3726
                self.outf.write(identity + '\n')
3496
3727
            return
3497
3728
 
3498
3729
        if email:
3499
 
            raise errors.BzrCommandError("--email can only be used to display existing "
3500
 
                                         "identity")
 
3730
            raise errors.BzrCommandError(gettext("--email can only be used to display existing "
 
3731
                                         "identity"))
3501
3732
 
3502
3733
        # display a warning if an email address isn't included in the given name.
3503
3734
        try:
3509
3740
        # use global config unless --branch given
3510
3741
        if branch:
3511
3742
            if directory is None:
3512
 
                c = Branch.open_containing(u'.')[0].get_config()
 
3743
                c = Branch.open_containing(u'.')[0].get_config_stack()
3513
3744
            else:
3514
 
                c = Branch.open(directory).get_config()
 
3745
                c = Branch.open(directory).get_config_stack()
3515
3746
        else:
3516
 
            c = _mod_config.GlobalConfig()
3517
 
        c.set_user_option('email', name)
 
3747
            c = _mod_config.GlobalStack()
 
3748
        c.set('email', name)
3518
3749
 
3519
3750
 
3520
3751
class cmd_nick(Command):
3582
3813
 
3583
3814
    def remove_alias(self, alias_name):
3584
3815
        if alias_name is None:
3585
 
            raise errors.BzrCommandError(
3586
 
                'bzr alias --remove expects an alias to remove.')
 
3816
            raise errors.BzrCommandError(gettext(
 
3817
                'bzr alias --remove expects an alias to remove.'))
3587
3818
        # If alias is not found, print something like:
3588
3819
        # unalias: foo: not found
3589
3820
        c = _mod_config.GlobalConfig()
3727
3958
                                param_name='starting_with', short_name='s',
3728
3959
                                help=
3729
3960
                                'Load only the tests starting with TESTID.'),
 
3961
                     Option('sync',
 
3962
                            help="By default we disable fsync and fdatasync"
 
3963
                                 " while running the test suite.")
3730
3964
                     ]
3731
3965
    encoding_type = 'replace'
3732
3966
 
3740
3974
            first=False, list_only=False,
3741
3975
            randomize=None, exclude=None, strict=False,
3742
3976
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3743
 
            parallel=None, lsprof_tests=False):
 
3977
            parallel=None, lsprof_tests=False,
 
3978
            sync=False):
3744
3979
        from bzrlib import tests
3745
3980
 
3746
3981
        if testspecs_list is not None:
3751
3986
            try:
3752
3987
                from bzrlib.tests import SubUnitBzrRunner
3753
3988
            except ImportError:
3754
 
                raise errors.BzrCommandError("subunit not available. subunit "
3755
 
                    "needs to be installed to use --subunit.")
 
3989
                raise errors.BzrCommandError(gettext("subunit not available. subunit "
 
3990
                    "needs to be installed to use --subunit."))
3756
3991
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3757
3992
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
3758
3993
            # stdout, which would corrupt the subunit stream. 
3767
4002
            self.additional_selftest_args.setdefault(
3768
4003
                'suite_decorators', []).append(parallel)
3769
4004
        if benchmark:
3770
 
            raise errors.BzrCommandError(
 
4005
            raise errors.BzrCommandError(gettext(
3771
4006
                "--benchmark is no longer supported from bzr 2.2; "
3772
 
                "use bzr-usertest instead")
 
4007
                "use bzr-usertest instead"))
3773
4008
        test_suite_factory = None
3774
4009
        if not exclude:
3775
4010
            exclude_pattern = None
3776
4011
        else:
3777
4012
            exclude_pattern = '(' + '|'.join(exclude) + ')'
 
4013
        if not sync:
 
4014
            self._disable_fsync()
3778
4015
        selftest_kwargs = {"verbose": verbose,
3779
4016
                          "pattern": pattern,
3780
4017
                          "stop_on_failure": one,
3802
4039
            cleanup()
3803
4040
        return int(not result)
3804
4041
 
 
4042
    def _disable_fsync(self):
 
4043
        """Change the 'os' functionality to not synchronize."""
 
4044
        self._orig_fsync = getattr(os, 'fsync', None)
 
4045
        if self._orig_fsync is not None:
 
4046
            os.fsync = lambda filedes: None
 
4047
        self._orig_fdatasync = getattr(os, 'fdatasync', None)
 
4048
        if self._orig_fdatasync is not None:
 
4049
            os.fdatasync = lambda filedes: None
 
4050
 
3805
4051
 
3806
4052
class cmd_version(Command):
3807
4053
    __doc__ = """Show version of bzr."""
3827
4073
 
3828
4074
    @display_command
3829
4075
    def run(self):
3830
 
        self.outf.write("It sure does!\n")
 
4076
        self.outf.write(gettext("It sure does!\n"))
3831
4077
 
3832
4078
 
3833
4079
class cmd_find_merge_base(Command):
3851
4097
        graph = branch1.repository.get_graph(branch2.repository)
3852
4098
        base_rev_id = graph.find_unique_lca(last1, last2)
3853
4099
 
3854
 
        self.outf.write('merge base is revision %s\n' % base_rev_id)
 
4100
        self.outf.write(gettext('merge base is revision %s\n') % base_rev_id)
3855
4101
 
3856
4102
 
3857
4103
class cmd_merge(Command):
3890
4136
    Use bzr resolve when you have fixed a problem.  See also bzr conflicts.
3891
4137
 
3892
4138
    If there is no default branch set, the first merge will set it (use
3893
 
    --no-remember to avoid settting it). After that, you can omit the branch
 
4139
    --no-remember to avoid setting it). After that, you can omit the branch
3894
4140
    to use the default.  To change the default, use --remember. The value will
3895
4141
    only be saved if the remote location can be accessed.
3896
4142
 
3982
4228
 
3983
4229
        tree = WorkingTree.open_containing(directory)[0]
3984
4230
        if tree.branch.revno() == 0:
3985
 
            raise errors.BzrCommandError('Merging into empty branches not currently supported, '
3986
 
                                         'https://bugs.launchpad.net/bzr/+bug/308562')
 
4231
            raise errors.BzrCommandError(gettext('Merging into empty branches not currently supported, '
 
4232
                                         'https://bugs.launchpad.net/bzr/+bug/308562'))
3987
4233
 
3988
4234
        try:
3989
4235
            basis_tree = tree.revision_tree(tree.last_revision())
4009
4255
                mergeable = None
4010
4256
            else:
4011
4257
                if uncommitted:
4012
 
                    raise errors.BzrCommandError('Cannot use --uncommitted'
4013
 
                        ' with bundles or merge directives.')
 
4258
                    raise errors.BzrCommandError(gettext('Cannot use --uncommitted'
 
4259
                        ' with bundles or merge directives.'))
4014
4260
 
4015
4261
                if revision is not None:
4016
 
                    raise errors.BzrCommandError(
4017
 
                        'Cannot use -r with merge directives or bundles')
 
4262
                    raise errors.BzrCommandError(gettext(
 
4263
                        'Cannot use -r with merge directives or bundles'))
4018
4264
                merger, verified = _mod_merge.Merger.from_mergeable(tree,
4019
4265
                   mergeable, None)
4020
4266
 
4021
4267
        if merger is None and uncommitted:
4022
4268
            if revision is not None and len(revision) > 0:
4023
 
                raise errors.BzrCommandError('Cannot use --uncommitted and'
4024
 
                    ' --revision at the same time.')
 
4269
                raise errors.BzrCommandError(gettext('Cannot use --uncommitted and'
 
4270
                    ' --revision at the same time.'))
4025
4271
            merger = self.get_merger_from_uncommitted(tree, location, None)
4026
4272
            allow_pending = False
4027
4273
 
4040
4286
            if merger.interesting_files:
4041
4287
                if not merger.other_tree.has_filename(
4042
4288
                    merger.interesting_files[0]):
4043
 
                    note("merger: " + str(merger))
 
4289
                    note(gettext("merger: ") + str(merger))
4044
4290
                    raise errors.PathsDoNotExist([location])
4045
 
            note('Nothing to do.')
 
4291
            note(gettext('Nothing to do.'))
4046
4292
            return 0
4047
4293
        if pull and not preview:
4048
4294
            if merger.interesting_files is not None:
4049
 
                raise errors.BzrCommandError('Cannot pull individual files')
 
4295
                raise errors.BzrCommandError(gettext('Cannot pull individual files'))
4050
4296
            if (merger.base_rev_id == tree.last_revision()):
4051
4297
                result = tree.pull(merger.other_branch, False,
4052
4298
                                   merger.other_rev_id)
4053
4299
                result.report(self.outf)
4054
4300
                return 0
4055
4301
        if merger.this_basis is None:
4056
 
            raise errors.BzrCommandError(
 
4302
            raise errors.BzrCommandError(gettext(
4057
4303
                "This branch has no commits."
4058
 
                " (perhaps you would prefer 'bzr pull')")
 
4304
                " (perhaps you would prefer 'bzr pull')"))
4059
4305
        if preview:
4060
4306
            return self._do_preview(merger)
4061
4307
        elif interactive:
4112
4358
    def sanity_check_merger(self, merger):
4113
4359
        if (merger.show_base and
4114
4360
            not merger.merge_type is _mod_merge.Merge3Merger):
4115
 
            raise errors.BzrCommandError("Show-base is not supported for this"
4116
 
                                         " merge type. %s" % merger.merge_type)
 
4361
            raise errors.BzrCommandError(gettext("Show-base is not supported for this"
 
4362
                                         " merge type. %s") % merger.merge_type)
4117
4363
        if merger.reprocess is None:
4118
4364
            if merger.show_base:
4119
4365
                merger.reprocess = False
4121
4367
                # Use reprocess if the merger supports it
4122
4368
                merger.reprocess = merger.merge_type.supports_reprocess
4123
4369
        if merger.reprocess and not merger.merge_type.supports_reprocess:
4124
 
            raise errors.BzrCommandError("Conflict reduction is not supported"
4125
 
                                         " for merge type %s." %
 
4370
            raise errors.BzrCommandError(gettext("Conflict reduction is not supported"
 
4371
                                         " for merge type %s.") %
4126
4372
                                         merger.merge_type)
4127
4373
        if merger.reprocess and merger.show_base:
4128
 
            raise errors.BzrCommandError("Cannot do conflict reduction and"
4129
 
                                         " show base.")
 
4374
            raise errors.BzrCommandError(gettext("Cannot do conflict reduction and"
 
4375
                                         " show base."))
4130
4376
 
4131
4377
    def _get_merger_from_branch(self, tree, location, revision, remember,
4132
4378
                                possible_transports, pb):
4236
4482
            stored_location_type = "parent"
4237
4483
        mutter("%s", stored_location)
4238
4484
        if stored_location is None:
4239
 
            raise errors.BzrCommandError("No location specified or remembered")
 
4485
            raise errors.BzrCommandError(gettext("No location specified or remembered"))
4240
4486
        display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
4241
 
        note(u"%s remembered %s location %s", verb_string,
4242
 
                stored_location_type, display_url)
 
4487
        note(gettext("{0} remembered {1} location {2}").format(verb_string,
 
4488
                stored_location_type, display_url))
4243
4489
        return stored_location
4244
4490
 
4245
4491
 
4282
4528
        self.add_cleanup(tree.lock_write().unlock)
4283
4529
        parents = tree.get_parent_ids()
4284
4530
        if len(parents) != 2:
4285
 
            raise errors.BzrCommandError("Sorry, remerge only works after normal"
 
4531
            raise errors.BzrCommandError(gettext("Sorry, remerge only works after normal"
4286
4532
                                         " merges.  Not cherrypicking or"
4287
 
                                         " multi-merges.")
 
4533
                                         " multi-merges."))
4288
4534
        repository = tree.branch.repository
4289
4535
        interesting_ids = None
4290
4536
        new_conflicts = []
4509
4755
            type=_parse_revision_str,
4510
4756
            help='Filter on local branch revisions (inclusive). '
4511
4757
                'See "help revisionspec" for details.'),
4512
 
        Option('include-merges',
 
4758
        Option('include-merged',
4513
4759
               'Show all revisions in addition to the mainline ones.'),
 
4760
        Option('include-merges', hidden=True,
 
4761
               help='Historical alias for --include-merged.'),
4514
4762
        ]
4515
4763
    encoding_type = 'replace'
4516
4764
 
4519
4767
            theirs_only=False,
4520
4768
            log_format=None, long=False, short=False, line=False,
4521
4769
            show_ids=False, verbose=False, this=False, other=False,
4522
 
            include_merges=False, revision=None, my_revision=None,
4523
 
            directory=u'.'):
 
4770
            include_merged=None, revision=None, my_revision=None,
 
4771
            directory=u'.',
 
4772
            include_merges=symbol_versioning.DEPRECATED_PARAMETER):
4524
4773
        from bzrlib.missing import find_unmerged, iter_log_revisions
4525
4774
        def message(s):
4526
4775
            if not is_quiet():
4527
4776
                self.outf.write(s)
4528
4777
 
 
4778
        if symbol_versioning.deprecated_passed(include_merges):
 
4779
            ui.ui_factory.show_user_warning(
 
4780
                'deprecated_command_option',
 
4781
                deprecated_name='--include-merges',
 
4782
                recommended_name='--include-merged',
 
4783
                deprecated_in_version='2.5',
 
4784
                command=self.invoked_as)
 
4785
            if include_merged is None:
 
4786
                include_merged = include_merges
 
4787
            else:
 
4788
                raise errors.BzrCommandError(gettext(
 
4789
                    '{0} and {1} are mutually exclusive').format(
 
4790
                    '--include-merges', '--include-merged'))
 
4791
        if include_merged is None:
 
4792
            include_merged = False
4529
4793
        if this:
4530
4794
            mine_only = this
4531
4795
        if other:
4546
4810
        if other_branch is None:
4547
4811
            other_branch = parent
4548
4812
            if other_branch is None:
4549
 
                raise errors.BzrCommandError("No peer location known"
4550
 
                                             " or specified.")
 
4813
                raise errors.BzrCommandError(gettext("No peer location known"
 
4814
                                             " or specified."))
4551
4815
            display_url = urlutils.unescape_for_display(parent,
4552
4816
                                                        self.outf.encoding)
4553
 
            message("Using saved parent location: "
4554
 
                    + display_url + "\n")
 
4817
            message(gettext("Using saved parent location: {0}\n").format(
 
4818
                    display_url))
4555
4819
 
4556
4820
        remote_branch = Branch.open(other_branch)
4557
4821
        if remote_branch.base == local_branch.base:
4570
4834
        local_extra, remote_extra = find_unmerged(
4571
4835
            local_branch, remote_branch, restrict,
4572
4836
            backward=not reverse,
4573
 
            include_merges=include_merges,
 
4837
            include_merged=include_merged,
4574
4838
            local_revid_range=local_revid_range,
4575
4839
            remote_revid_range=remote_revid_range)
4576
4840
 
4583
4847
 
4584
4848
        status_code = 0
4585
4849
        if local_extra and not theirs_only:
4586
 
            message("You have %d extra revision(s):\n" %
 
4850
            message(ngettext("You have %d extra revision:\n",
 
4851
                             "You have %d extra revisions:\n", 
 
4852
                             len(local_extra)) %
4587
4853
                len(local_extra))
4588
4854
            for revision in iter_log_revisions(local_extra,
4589
4855
                                local_branch.repository,
4597
4863
        if remote_extra and not mine_only:
4598
4864
            if printed_local is True:
4599
4865
                message("\n\n\n")
4600
 
            message("You are missing %d revision(s):\n" %
 
4866
            message(ngettext("You are missing %d revision:\n",
 
4867
                             "You are missing %d revisions:\n",
 
4868
                             len(remote_extra)) %
4601
4869
                len(remote_extra))
4602
4870
            for revision in iter_log_revisions(remote_extra,
4603
4871
                                remote_branch.repository,
4607
4875
 
4608
4876
        if mine_only and not local_extra:
4609
4877
            # We checked local, and found nothing extra
4610
 
            message('This branch is up to date.\n')
 
4878
            message(gettext('This branch has no new revisions.\n'))
4611
4879
        elif theirs_only and not remote_extra:
4612
4880
            # We checked remote, and found nothing extra
4613
 
            message('Other branch is up to date.\n')
 
4881
            message(gettext('Other branch has no new revisions.\n'))
4614
4882
        elif not (mine_only or theirs_only or local_extra or
4615
4883
                  remote_extra):
4616
4884
            # We checked both branches, and neither one had extra
4617
4885
            # revisions
4618
 
            message("Branches are up to date.\n")
 
4886
            message(gettext("Branches are up to date.\n"))
4619
4887
        self.cleanup_now()
4620
4888
        if not status_code and parent is None and other_branch is not None:
4621
4889
            self.add_cleanup(local_branch.lock_write().unlock)
4651
4919
        ]
4652
4920
 
4653
4921
    def run(self, branch_or_repo='.', clean_obsolete_packs=False):
4654
 
        dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
 
4922
        dir = controldir.ControlDir.open_containing(branch_or_repo)[0]
4655
4923
        try:
4656
4924
            branch = dir.open_branch()
4657
4925
            repository = branch.repository
4782
5050
 
4783
5051
    def run(self, revision_id_list=None, revision=None, directory=u'.'):
4784
5052
        if revision_id_list is not None and revision is not None:
4785
 
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
 
5053
            raise errors.BzrCommandError(gettext('You can only supply one of revision_id or --revision'))
4786
5054
        if revision_id_list is None and revision is None:
4787
 
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
 
5055
            raise errors.BzrCommandError(gettext('You must supply either --revision or a revision_id'))
4788
5056
        b = WorkingTree.open_containing(directory)[0].branch
4789
5057
        self.add_cleanup(b.lock_write().unlock)
4790
5058
        return self._run(b, revision_id_list, revision)
4791
5059
 
4792
5060
    def _run(self, b, revision_id_list, revision):
4793
5061
        import bzrlib.gpg as gpg
4794
 
        gpg_strategy = gpg.GPGStrategy(b.get_config())
 
5062
        gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
4795
5063
        if revision_id_list is not None:
4796
5064
            b.repository.start_write_group()
4797
5065
            try:
4822
5090
                if to_revid is None:
4823
5091
                    to_revno = b.revno()
4824
5092
                if from_revno is None or to_revno is None:
4825
 
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
 
5093
                    raise errors.BzrCommandError(gettext('Cannot sign a range of non-revision-history revisions'))
4826
5094
                b.repository.start_write_group()
4827
5095
                try:
4828
5096
                    for revno in range(from_revno, to_revno + 1):
4834
5102
                else:
4835
5103
                    b.repository.commit_write_group()
4836
5104
            else:
4837
 
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
 
5105
                raise errors.BzrCommandError(gettext('Please supply either one revision, or a range.'))
4838
5106
 
4839
5107
 
4840
5108
class cmd_bind(Command):
4859
5127
            try:
4860
5128
                location = b.get_old_bound_location()
4861
5129
            except errors.UpgradeRequired:
4862
 
                raise errors.BzrCommandError('No location supplied.  '
4863
 
                    'This format does not remember old locations.')
 
5130
                raise errors.BzrCommandError(gettext('No location supplied.  '
 
5131
                    'This format does not remember old locations.'))
4864
5132
            else:
4865
5133
                if location is None:
4866
5134
                    if b.get_bound_location() is not None:
4867
 
                        raise errors.BzrCommandError('Branch is already bound')
 
5135
                        raise errors.BzrCommandError(gettext('Branch is already bound'))
4868
5136
                    else:
4869
 
                        raise errors.BzrCommandError('No location supplied '
4870
 
                            'and no previous location known')
 
5137
                        raise errors.BzrCommandError(gettext('No location supplied '
 
5138
                            'and no previous location known'))
4871
5139
        b_other = Branch.open(location)
4872
5140
        try:
4873
5141
            b.bind(b_other)
4874
5142
        except errors.DivergedBranches:
4875
 
            raise errors.BzrCommandError('These branches have diverged.'
4876
 
                                         ' Try merging, and then bind again.')
 
5143
            raise errors.BzrCommandError(gettext('These branches have diverged.'
 
5144
                                         ' Try merging, and then bind again.'))
4877
5145
        if b.get_config().has_explicit_nickname():
4878
5146
            b.nick = b_other.nick
4879
5147
 
4892
5160
    def run(self, directory=u'.'):
4893
5161
        b, relpath = Branch.open_containing(directory)
4894
5162
        if not b.unbind():
4895
 
            raise errors.BzrCommandError('Local branch is not bound')
 
5163
            raise errors.BzrCommandError(gettext('Local branch is not bound'))
4896
5164
 
4897
5165
 
4898
5166
class cmd_uncommit(Command):
4919
5187
    takes_options = ['verbose', 'revision',
4920
5188
                    Option('dry-run', help='Don\'t actually make changes.'),
4921
5189
                    Option('force', help='Say yes to all questions.'),
 
5190
                    Option('keep-tags',
 
5191
                           help='Keep tags that point to removed revisions.'),
4922
5192
                    Option('local',
4923
5193
                           help="Only remove the commits from the local branch"
4924
5194
                                " when in a checkout."
4928
5198
    aliases = []
4929
5199
    encoding_type = 'replace'
4930
5200
 
4931
 
    def run(self, location=None,
4932
 
            dry_run=False, verbose=False,
4933
 
            revision=None, force=False, local=False):
 
5201
    def run(self, location=None, dry_run=False, verbose=False,
 
5202
            revision=None, force=False, local=False, keep_tags=False):
4934
5203
        if location is None:
4935
5204
            location = u'.'
4936
 
        control, relpath = bzrdir.BzrDir.open_containing(location)
 
5205
        control, relpath = controldir.ControlDir.open_containing(location)
4937
5206
        try:
4938
5207
            tree = control.open_workingtree()
4939
5208
            b = tree.branch
4945
5214
            self.add_cleanup(tree.lock_write().unlock)
4946
5215
        else:
4947
5216
            self.add_cleanup(b.lock_write().unlock)
4948
 
        return self._run(b, tree, dry_run, verbose, revision, force, local=local)
 
5217
        return self._run(b, tree, dry_run, verbose, revision, force,
 
5218
                         local, keep_tags)
4949
5219
 
4950
 
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
 
5220
    def _run(self, b, tree, dry_run, verbose, revision, force, local,
 
5221
             keep_tags):
4951
5222
        from bzrlib.log import log_formatter, show_log
4952
5223
        from bzrlib.uncommit import uncommit
4953
5224
 
4968
5239
                rev_id = b.get_rev_id(revno)
4969
5240
 
4970
5241
        if rev_id is None or _mod_revision.is_null(rev_id):
4971
 
            self.outf.write('No revisions to uncommit.\n')
 
5242
            self.outf.write(gettext('No revisions to uncommit.\n'))
4972
5243
            return 1
4973
5244
 
4974
5245
        lf = log_formatter('short',
4983
5254
                 end_revision=last_revno)
4984
5255
 
4985
5256
        if dry_run:
4986
 
            self.outf.write('Dry-run, pretending to remove'
4987
 
                            ' the above revisions.\n')
 
5257
            self.outf.write(gettext('Dry-run, pretending to remove'
 
5258
                            ' the above revisions.\n'))
4988
5259
        else:
4989
 
            self.outf.write('The above revision(s) will be removed.\n')
 
5260
            self.outf.write(gettext('The above revision(s) will be removed.\n'))
4990
5261
 
4991
5262
        if not force:
4992
5263
            if not ui.ui_factory.confirm_action(
4993
 
                    u'Uncommit these revisions',
 
5264
                    gettext(u'Uncommit these revisions'),
4994
5265
                    'bzrlib.builtins.uncommit',
4995
5266
                    {}):
4996
 
                self.outf.write('Canceled\n')
 
5267
                self.outf.write(gettext('Canceled\n'))
4997
5268
                return 0
4998
5269
 
4999
5270
        mutter('Uncommitting from {%s} to {%s}',
5000
5271
               last_rev_id, rev_id)
5001
5272
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
5002
 
                 revno=revno, local=local)
5003
 
        self.outf.write('You can restore the old tip by running:\n'
5004
 
             '  bzr pull . -r revid:%s\n' % last_rev_id)
 
5273
                 revno=revno, local=local, keep_tags=keep_tags)
 
5274
        self.outf.write(gettext('You can restore the old tip by running:\n'
 
5275
             '  bzr pull . -r revid:%s\n') % last_rev_id)
5005
5276
 
5006
5277
 
5007
5278
class cmd_break_lock(Command):
5041
5312
            conf = _mod_config.LockableConfig(file_name=location)
5042
5313
            conf.break_lock()
5043
5314
        else:
5044
 
            control, relpath = bzrdir.BzrDir.open_containing(location)
 
5315
            control, relpath = controldir.ControlDir.open_containing(location)
5045
5316
            try:
5046
5317
                control.break_lock()
5047
5318
            except NotImplementedError:
5091
5362
                    'option leads to global uncontrolled write access to your '
5092
5363
                    'file system.'
5093
5364
                ),
 
5365
        Option('client-timeout', type=float,
 
5366
               help='Override the default idle client timeout (5min).'),
5094
5367
        ]
5095
5368
 
5096
5369
    def get_host_and_port(self, port):
5113
5386
        return host, port
5114
5387
 
5115
5388
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
5116
 
            protocol=None):
 
5389
            protocol=None, client_timeout=None):
5117
5390
        from bzrlib import transport
5118
5391
        if directory is None:
5119
5392
            directory = os.getcwd()
5120
5393
        if protocol is None:
5121
5394
            protocol = transport.transport_server_registry.get()
5122
5395
        host, port = self.get_host_and_port(port)
5123
 
        url = urlutils.local_path_to_url(directory)
 
5396
        url = transport.location_to_url(directory)
5124
5397
        if not allow_writes:
5125
5398
            url = 'readonly+' + url
5126
 
        t = transport.get_transport(url)
5127
 
        protocol(t, host, port, inet)
 
5399
        t = transport.get_transport_from_url(url)
 
5400
        try:
 
5401
            protocol(t, host, port, inet, client_timeout)
 
5402
        except TypeError, e:
 
5403
            # We use symbol_versioning.deprecated_in just so that people
 
5404
            # grepping can find it here.
 
5405
            # symbol_versioning.deprecated_in((2, 5, 0))
 
5406
            symbol_versioning.warn(
 
5407
                'Got TypeError(%s)\ntrying to call protocol: %s.%s\n'
 
5408
                'Most likely it needs to be updated to support a'
 
5409
                ' "timeout" parameter (added in bzr 2.5.0)'
 
5410
                % (e, protocol.__module__, protocol),
 
5411
                DeprecationWarning)
 
5412
            protocol(t, host, port, inet)
5128
5413
 
5129
5414
 
5130
5415
class cmd_join(Command):
5153
5438
        containing_tree = WorkingTree.open_containing(parent_dir)[0]
5154
5439
        repo = containing_tree.branch.repository
5155
5440
        if not repo.supports_rich_root():
5156
 
            raise errors.BzrCommandError(
 
5441
            raise errors.BzrCommandError(gettext(
5157
5442
                "Can't join trees because %s doesn't support rich root data.\n"
5158
 
                "You can use bzr upgrade on the repository."
 
5443
                "You can use bzr upgrade on the repository.")
5159
5444
                % (repo,))
5160
5445
        if reference:
5161
5446
            try:
5163
5448
            except errors.BadReferenceTarget, e:
5164
5449
                # XXX: Would be better to just raise a nicely printable
5165
5450
                # exception from the real origin.  Also below.  mbp 20070306
5166
 
                raise errors.BzrCommandError("Cannot join %s.  %s" %
5167
 
                                             (tree, e.reason))
 
5451
                raise errors.BzrCommandError(
 
5452
                       gettext("Cannot join {0}.  {1}").format(tree, e.reason))
5168
5453
        else:
5169
5454
            try:
5170
5455
                containing_tree.subsume(sub_tree)
5171
5456
            except errors.BadSubsumeSource, e:
5172
 
                raise errors.BzrCommandError("Cannot join %s.  %s" %
5173
 
                                             (tree, e.reason))
 
5457
                raise errors.BzrCommandError(
 
5458
                       gettext("Cannot join {0}.  {1}").format(tree, e.reason))
5174
5459
 
5175
5460
 
5176
5461
class cmd_split(Command):
5260
5545
        if submit_branch is None:
5261
5546
            submit_branch = branch.get_parent()
5262
5547
        if submit_branch is None:
5263
 
            raise errors.BzrCommandError('No submit branch specified or known')
 
5548
            raise errors.BzrCommandError(gettext('No submit branch specified or known'))
5264
5549
 
5265
5550
        stored_public_branch = branch.get_public_branch()
5266
5551
        if public_branch is None:
5268
5553
        elif stored_public_branch is None:
5269
5554
            branch.set_public_branch(public_branch)
5270
5555
        if not include_bundle and public_branch is None:
5271
 
            raise errors.BzrCommandError('No public branch specified or'
5272
 
                                         ' known')
 
5556
            raise errors.BzrCommandError(gettext('No public branch specified or'
 
5557
                                         ' known'))
5273
5558
        base_revision_id = None
5274
5559
        if revision is not None:
5275
5560
            if len(revision) > 2:
5276
 
                raise errors.BzrCommandError('bzr merge-directive takes '
5277
 
                    'at most two one revision identifiers')
 
5561
                raise errors.BzrCommandError(gettext('bzr merge-directive takes '
 
5562
                    'at most two one revision identifiers'))
5278
5563
            revision_id = revision[-1].as_revision_id(branch)
5279
5564
            if len(revision) == 2:
5280
5565
                base_revision_id = revision[0].as_revision_id(branch)
5282
5567
            revision_id = branch.last_revision()
5283
5568
        revision_id = ensure_null(revision_id)
5284
5569
        if revision_id == NULL_REVISION:
5285
 
            raise errors.BzrCommandError('No revisions to bundle.')
 
5570
            raise errors.BzrCommandError(gettext('No revisions to bundle.'))
5286
5571
        directive = merge_directive.MergeDirective2.from_objects(
5287
5572
            branch.repository, revision_id, time.time(),
5288
5573
            osutils.local_time_offset(), submit_branch,
5296
5581
                self.outf.writelines(directive.to_lines())
5297
5582
        else:
5298
5583
            message = directive.to_email(mail_to, branch, sign)
5299
 
            s = SMTPConnection(branch.get_config())
 
5584
            s = SMTPConnection(branch.get_config_stack())
5300
5585
            s.send_email(message)
5301
5586
 
5302
5587
 
5334
5619
 
5335
5620
    Both the submit branch and the public branch follow the usual behavior with
5336
5621
    respect to --remember: If there is no default location set, the first send
5337
 
    will set it (use --no-remember to avoid settting it). After that, you can
 
5622
    will set it (use --no-remember to avoid setting it). After that, you can
5338
5623
    omit the location to use the default.  To change the default, use
5339
5624
    --remember. The value will only be saved if the location can be accessed.
5340
5625
 
5542
5827
        self.add_cleanup(branch.lock_write().unlock)
5543
5828
        if delete:
5544
5829
            if tag_name is None:
5545
 
                raise errors.BzrCommandError("No tag specified to delete.")
 
5830
                raise errors.BzrCommandError(gettext("No tag specified to delete."))
5546
5831
            branch.tags.delete_tag(tag_name)
5547
 
            note('Deleted tag %s.' % tag_name)
 
5832
            note(gettext('Deleted tag %s.') % tag_name)
5548
5833
        else:
5549
5834
            if revision:
5550
5835
                if len(revision) != 1:
5551
 
                    raise errors.BzrCommandError(
 
5836
                    raise errors.BzrCommandError(gettext(
5552
5837
                        "Tags can only be placed on a single revision, "
5553
 
                        "not on a range")
 
5838
                        "not on a range"))
5554
5839
                revision_id = revision[0].as_revision_id(branch)
5555
5840
            else:
5556
5841
                revision_id = branch.last_revision()
5557
5842
            if tag_name is None:
5558
5843
                tag_name = branch.automatic_tag_name(revision_id)
5559
5844
                if tag_name is None:
5560
 
                    raise errors.BzrCommandError(
5561
 
                        "Please specify a tag name.")
5562
 
            if (not force) and branch.tags.has_tag(tag_name):
 
5845
                    raise errors.BzrCommandError(gettext(
 
5846
                        "Please specify a tag name."))
 
5847
            try:
 
5848
                existing_target = branch.tags.lookup_tag(tag_name)
 
5849
            except errors.NoSuchTag:
 
5850
                existing_target = None
 
5851
            if not force and existing_target not in (None, revision_id):
5563
5852
                raise errors.TagAlreadyExists(tag_name)
5564
 
            branch.tags.set_tag(tag_name, revision_id)
5565
 
            note('Created tag %s.' % tag_name)
 
5853
            if existing_target == revision_id:
 
5854
                note(gettext('Tag %s already exists for that revision.') % tag_name)
 
5855
            else:
 
5856
                branch.tags.set_tag(tag_name, revision_id)
 
5857
                if existing_target is None:
 
5858
                    note(gettext('Created tag %s.') % tag_name)
 
5859
                else:
 
5860
                    note(gettext('Updated tag %s.') % tag_name)
5566
5861
 
5567
5862
 
5568
5863
class cmd_tags(Command):
5594
5889
 
5595
5890
        self.add_cleanup(branch.lock_read().unlock)
5596
5891
        if revision:
5597
 
            graph = branch.repository.get_graph()
5598
 
            rev1, rev2 = _get_revision_range(revision, branch, self.name())
5599
 
            revid1, revid2 = rev1.rev_id, rev2.rev_id
5600
 
            # only show revisions between revid1 and revid2 (inclusive)
5601
 
            tags = [(tag, revid) for tag, revid in tags if
5602
 
                graph.is_between(revid, revid1, revid2)]
 
5892
            # Restrict to the specified range
 
5893
            tags = self._tags_for_range(branch, revision)
5603
5894
        if sort is None:
5604
5895
            sort = tag_sort_methods.get()
5605
5896
        sort(branch, tags)
5610
5901
                    revno = branch.revision_id_to_dotted_revno(revid)
5611
5902
                    if isinstance(revno, tuple):
5612
5903
                        revno = '.'.join(map(str, revno))
5613
 
                except (errors.NoSuchRevision, errors.GhostRevisionsHaveNoRevno):
 
5904
                except (errors.NoSuchRevision,
 
5905
                        errors.GhostRevisionsHaveNoRevno,
 
5906
                        errors.UnsupportedOperation):
5614
5907
                    # Bad tag data/merges can lead to tagged revisions
5615
5908
                    # which are not in this branch. Fail gracefully ...
5616
5909
                    revno = '?'
5619
5912
        for tag, revspec in tags:
5620
5913
            self.outf.write('%-20s %s\n' % (tag, revspec))
5621
5914
 
 
5915
    def _tags_for_range(self, branch, revision):
 
5916
        range_valid = True
 
5917
        rev1, rev2 = _get_revision_range(revision, branch, self.name())
 
5918
        revid1, revid2 = rev1.rev_id, rev2.rev_id
 
5919
        # _get_revision_range will always set revid2 if it's not specified.
 
5920
        # If revid1 is None, it means we want to start from the branch
 
5921
        # origin which is always a valid ancestor. If revid1 == revid2, the
 
5922
        # ancestry check is useless.
 
5923
        if revid1 and revid1 != revid2:
 
5924
            # FIXME: We really want to use the same graph than
 
5925
            # branch.iter_merge_sorted_revisions below, but this is not
 
5926
            # easily available -- vila 2011-09-23
 
5927
            if branch.repository.get_graph().is_ancestor(revid2, revid1):
 
5928
                # We don't want to output anything in this case...
 
5929
                return []
 
5930
        # only show revisions between revid1 and revid2 (inclusive)
 
5931
        tagged_revids = branch.tags.get_reverse_tag_dict()
 
5932
        found = []
 
5933
        for r in branch.iter_merge_sorted_revisions(
 
5934
            start_revision_id=revid2, stop_revision_id=revid1,
 
5935
            stop_rule='include'):
 
5936
            revid_tags = tagged_revids.get(r[0], None)
 
5937
            if revid_tags:
 
5938
                found.extend([(tag, r[0]) for tag in revid_tags])
 
5939
        return found
 
5940
 
5622
5941
 
5623
5942
class cmd_reconfigure(Command):
5624
5943
    __doc__ = """Reconfigure the type of a bzr directory.
5638
5957
    takes_args = ['location?']
5639
5958
    takes_options = [
5640
5959
        RegistryOption.from_kwargs(
5641
 
            'target_type',
5642
 
            title='Target type',
5643
 
            help='The type to reconfigure the directory to.',
 
5960
            'tree_type',
 
5961
            title='Tree type',
 
5962
            help='The relation between branch and tree.',
5644
5963
            value_switches=True, enum_switch=False,
5645
5964
            branch='Reconfigure to be an unbound branch with no working tree.',
5646
5965
            tree='Reconfigure to be an unbound branch with a working tree.',
5647
5966
            checkout='Reconfigure to be a bound branch with a working tree.',
5648
5967
            lightweight_checkout='Reconfigure to be a lightweight'
5649
5968
                ' checkout (with no local history).',
 
5969
            ),
 
5970
        RegistryOption.from_kwargs(
 
5971
            'repository_type',
 
5972
            title='Repository type',
 
5973
            help='Location fo the repository.',
 
5974
            value_switches=True, enum_switch=False,
5650
5975
            standalone='Reconfigure to be a standalone branch '
5651
5976
                '(i.e. stop using shared repository).',
5652
5977
            use_shared='Reconfigure to use a shared repository.',
 
5978
            ),
 
5979
        RegistryOption.from_kwargs(
 
5980
            'repository_trees',
 
5981
            title='Trees in Repository',
 
5982
            help='Whether new branches in the repository have trees.',
 
5983
            value_switches=True, enum_switch=False,
5653
5984
            with_trees='Reconfigure repository to create '
5654
5985
                'working trees on branches by default.',
5655
5986
            with_no_trees='Reconfigure repository to not create '
5669
6000
            ),
5670
6001
        ]
5671
6002
 
5672
 
    def run(self, location=None, target_type=None, bind_to=None, force=False,
5673
 
            stacked_on=None,
5674
 
            unstacked=None):
5675
 
        directory = bzrdir.BzrDir.open(location)
 
6003
    def run(self, location=None, bind_to=None, force=False,
 
6004
            tree_type=None, repository_type=None, repository_trees=None,
 
6005
            stacked_on=None, unstacked=None):
 
6006
        directory = controldir.ControlDir.open(location)
5676
6007
        if stacked_on and unstacked:
5677
 
            raise errors.BzrCommandError("Can't use both --stacked-on and --unstacked")
 
6008
            raise errors.BzrCommandError(gettext("Can't use both --stacked-on and --unstacked"))
5678
6009
        elif stacked_on is not None:
5679
6010
            reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5680
6011
        elif unstacked:
5682
6013
        # At the moment you can use --stacked-on and a different
5683
6014
        # reconfiguration shape at the same time; there seems no good reason
5684
6015
        # to ban it.
5685
 
        if target_type is None:
 
6016
        if (tree_type is None and
 
6017
            repository_type is None and
 
6018
            repository_trees is None):
5686
6019
            if stacked_on or unstacked:
5687
6020
                return
5688
6021
            else:
5689
 
                raise errors.BzrCommandError('No target configuration '
5690
 
                    'specified')
5691
 
        elif target_type == 'branch':
 
6022
                raise errors.BzrCommandError(gettext('No target configuration '
 
6023
                    'specified'))
 
6024
        reconfiguration = None
 
6025
        if tree_type == 'branch':
5692
6026
            reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5693
 
        elif target_type == 'tree':
 
6027
        elif tree_type == 'tree':
5694
6028
            reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5695
 
        elif target_type == 'checkout':
 
6029
        elif tree_type == 'checkout':
5696
6030
            reconfiguration = reconfigure.Reconfigure.to_checkout(
5697
6031
                directory, bind_to)
5698
 
        elif target_type == 'lightweight-checkout':
 
6032
        elif tree_type == 'lightweight-checkout':
5699
6033
            reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5700
6034
                directory, bind_to)
5701
 
        elif target_type == 'use-shared':
 
6035
        if reconfiguration:
 
6036
            reconfiguration.apply(force)
 
6037
            reconfiguration = None
 
6038
        if repository_type == 'use-shared':
5702
6039
            reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5703
 
        elif target_type == 'standalone':
 
6040
        elif repository_type == 'standalone':
5704
6041
            reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5705
 
        elif target_type == 'with-trees':
 
6042
        if reconfiguration:
 
6043
            reconfiguration.apply(force)
 
6044
            reconfiguration = None
 
6045
        if repository_trees == 'with-trees':
5706
6046
            reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5707
6047
                directory, True)
5708
 
        elif target_type == 'with-no-trees':
 
6048
        elif repository_trees == 'with-no-trees':
5709
6049
            reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5710
6050
                directory, False)
5711
 
        reconfiguration.apply(force)
 
6051
        if reconfiguration:
 
6052
            reconfiguration.apply(force)
 
6053
            reconfiguration = None
5712
6054
 
5713
6055
 
5714
6056
class cmd_switch(Command):
5749
6091
        from bzrlib import switch
5750
6092
        tree_location = directory
5751
6093
        revision = _get_one_revision('switch', revision)
5752
 
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
 
6094
        control_dir = controldir.ControlDir.open_containing(tree_location)[0]
5753
6095
        if to_location is None:
5754
6096
            if revision is None:
5755
 
                raise errors.BzrCommandError('You must supply either a'
5756
 
                                             ' revision or a location')
 
6097
                raise errors.BzrCommandError(gettext('You must supply either a'
 
6098
                                             ' revision or a location'))
5757
6099
            to_location = tree_location
5758
6100
        try:
5759
6101
            branch = control_dir.open_branch()
5763
6105
            had_explicit_nick = False
5764
6106
        if create_branch:
5765
6107
            if branch is None:
5766
 
                raise errors.BzrCommandError('cannot create branch without'
5767
 
                                             ' source branch')
 
6108
                raise errors.BzrCommandError(gettext('cannot create branch without'
 
6109
                                             ' source branch'))
5768
6110
            to_location = directory_service.directories.dereference(
5769
6111
                              to_location)
5770
6112
            if '/' not in to_location and '\\' not in to_location:
5771
6113
                # This path is meant to be relative to the existing branch
5772
6114
                this_url = self._get_branch_location(control_dir)
5773
 
                to_location = urlutils.join(this_url, '..', to_location)
 
6115
                # Perhaps the target control dir supports colocated branches?
 
6116
                try:
 
6117
                    root = controldir.ControlDir.open(this_url,
 
6118
                        possible_transports=[control_dir.user_transport])
 
6119
                except errors.NotBranchError:
 
6120
                    colocated = False
 
6121
                else:
 
6122
                    colocated = root._format.colocated_branches
 
6123
                if colocated:
 
6124
                    to_location = urlutils.join_segment_parameters(this_url,
 
6125
                        {"branch": urlutils.escape(to_location)})
 
6126
                else:
 
6127
                    to_location = urlutils.join(
 
6128
                        this_url, '..', urlutils.escape(to_location))
5774
6129
            to_branch = branch.bzrdir.sprout(to_location,
5775
6130
                                 possible_transports=[branch.bzrdir.root_transport],
5776
6131
                                 source_branch=branch).open_branch()
5777
6132
        else:
 
6133
            # Perhaps it's a colocated branch?
5778
6134
            try:
5779
 
                to_branch = Branch.open(to_location)
5780
 
            except errors.NotBranchError:
5781
 
                this_url = self._get_branch_location(control_dir)
5782
 
                to_branch = Branch.open(
5783
 
                    urlutils.join(this_url, '..', to_location))
 
6135
                to_branch = control_dir.open_branch(to_location)
 
6136
            except (errors.NotBranchError, errors.NoColocatedBranchSupport):
 
6137
                try:
 
6138
                    to_branch = Branch.open(to_location)
 
6139
                except errors.NotBranchError:
 
6140
                    this_url = self._get_branch_location(control_dir)
 
6141
                    to_branch = Branch.open(
 
6142
                        urlutils.join(
 
6143
                            this_url, '..', urlutils.escape(to_location)))
5784
6144
        if revision is not None:
5785
6145
            revision = revision.as_revision_id(to_branch)
5786
6146
        switch.switch(control_dir, to_branch, force, revision_id=revision)
5787
6147
        if had_explicit_nick:
5788
6148
            branch = control_dir.open_branch() #get the new branch!
5789
6149
            branch.nick = to_branch.nick
5790
 
        note('Switched to branch: %s',
 
6150
        note(gettext('Switched to branch: %s'),
5791
6151
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5792
6152
 
5793
6153
    def _get_branch_location(self, control_dir):
5902
6262
            name = current_view
5903
6263
        if delete:
5904
6264
            if file_list:
5905
 
                raise errors.BzrCommandError(
5906
 
                    "Both --delete and a file list specified")
 
6265
                raise errors.BzrCommandError(gettext(
 
6266
                    "Both --delete and a file list specified"))
5907
6267
            elif switch:
5908
 
                raise errors.BzrCommandError(
5909
 
                    "Both --delete and --switch specified")
 
6268
                raise errors.BzrCommandError(gettext(
 
6269
                    "Both --delete and --switch specified"))
5910
6270
            elif all:
5911
6271
                tree.views.set_view_info(None, {})
5912
 
                self.outf.write("Deleted all views.\n")
 
6272
                self.outf.write(gettext("Deleted all views.\n"))
5913
6273
            elif name is None:
5914
 
                raise errors.BzrCommandError("No current view to delete")
 
6274
                raise errors.BzrCommandError(gettext("No current view to delete"))
5915
6275
            else:
5916
6276
                tree.views.delete_view(name)
5917
 
                self.outf.write("Deleted '%s' view.\n" % name)
 
6277
                self.outf.write(gettext("Deleted '%s' view.\n") % name)
5918
6278
        elif switch:
5919
6279
            if file_list:
5920
 
                raise errors.BzrCommandError(
5921
 
                    "Both --switch and a file list specified")
 
6280
                raise errors.BzrCommandError(gettext(
 
6281
                    "Both --switch and a file list specified"))
5922
6282
            elif all:
5923
 
                raise errors.BzrCommandError(
5924
 
                    "Both --switch and --all specified")
 
6283
                raise errors.BzrCommandError(gettext(
 
6284
                    "Both --switch and --all specified"))
5925
6285
            elif switch == 'off':
5926
6286
                if current_view is None:
5927
 
                    raise errors.BzrCommandError("No current view to disable")
 
6287
                    raise errors.BzrCommandError(gettext("No current view to disable"))
5928
6288
                tree.views.set_view_info(None, view_dict)
5929
 
                self.outf.write("Disabled '%s' view.\n" % (current_view))
 
6289
                self.outf.write(gettext("Disabled '%s' view.\n") % (current_view))
5930
6290
            else:
5931
6291
                tree.views.set_view_info(switch, view_dict)
5932
6292
                view_str = views.view_display_str(tree.views.lookup_view())
5933
 
                self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
 
6293
                self.outf.write(gettext("Using '{0}' view: {1}\n").format(switch, view_str))
5934
6294
        elif all:
5935
6295
            if view_dict:
5936
 
                self.outf.write('Views defined:\n')
 
6296
                self.outf.write(gettext('Views defined:\n'))
5937
6297
                for view in sorted(view_dict):
5938
6298
                    if view == current_view:
5939
6299
                        active = "=>"
5942
6302
                    view_str = views.view_display_str(view_dict[view])
5943
6303
                    self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5944
6304
            else:
5945
 
                self.outf.write('No views defined.\n')
 
6305
                self.outf.write(gettext('No views defined.\n'))
5946
6306
        elif file_list:
5947
6307
            if name is None:
5948
6308
                # No name given and no current view set
5949
6309
                name = 'my'
5950
6310
            elif name == 'off':
5951
 
                raise errors.BzrCommandError(
5952
 
                    "Cannot change the 'off' pseudo view")
 
6311
                raise errors.BzrCommandError(gettext(
 
6312
                    "Cannot change the 'off' pseudo view"))
5953
6313
            tree.views.set_view(name, sorted(file_list))
5954
6314
            view_str = views.view_display_str(tree.views.lookup_view())
5955
 
            self.outf.write("Using '%s' view: %s\n" % (name, view_str))
 
6315
            self.outf.write(gettext("Using '{0}' view: {1}\n").format(name, view_str))
5956
6316
        else:
5957
6317
            # list the files
5958
6318
            if name is None:
5959
6319
                # No name given and no current view set
5960
 
                self.outf.write('No current view.\n')
 
6320
                self.outf.write(gettext('No current view.\n'))
5961
6321
            else:
5962
6322
                view_str = views.view_display_str(tree.views.lookup_view(name))
5963
 
                self.outf.write("'%s' view is: %s\n" % (name, view_str))
 
6323
                self.outf.write(gettext("'{0}' view is: {1}\n").format(name, view_str))
5964
6324
 
5965
6325
 
5966
6326
class cmd_hooks(Command):
5980
6340
                        self.outf.write("    %s\n" %
5981
6341
                                        (some_hooks.get_hook_name(hook),))
5982
6342
                else:
5983
 
                    self.outf.write("    <no hooks installed>\n")
 
6343
                    self.outf.write(gettext("    <no hooks installed>\n"))
5984
6344
 
5985
6345
 
5986
6346
class cmd_remove_branch(Command):
6087
6447
        manager = tree.get_shelf_manager()
6088
6448
        shelves = manager.active_shelves()
6089
6449
        if len(shelves) == 0:
6090
 
            note('No shelved changes.')
 
6450
            note(gettext('No shelved changes.'))
6091
6451
            return 0
6092
6452
        for shelf_id in reversed(shelves):
6093
6453
            message = manager.get_metadata(shelf_id).get('message')
6182
6542
        if path is not None:
6183
6543
            branchdir = path
6184
6544
        tree, branch, relpath =(
6185
 
            bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
 
6545
            controldir.ControlDir.open_containing_tree_or_branch(branchdir))
6186
6546
        if path is not None:
6187
6547
            path = relpath
6188
6548
        if tree is None:
6216
6576
    __doc__ = """Export command helps and error messages in po format."""
6217
6577
 
6218
6578
    hidden = True
 
6579
    takes_options = [Option('plugin', 
 
6580
                            help='Export help text from named command '\
 
6581
                                 '(defaults to all built in commands).',
 
6582
                            type=str),
 
6583
                     Option('include-duplicates',
 
6584
                            help='Output multiple copies of the same msgid '
 
6585
                                 'string if it appears more than once.'),
 
6586
                            ]
6219
6587
 
6220
 
    def run(self):
 
6588
    def run(self, plugin=None, include_duplicates=False):
6221
6589
        from bzrlib.export_pot import export_pot
6222
 
        export_pot(self.outf)
 
6590
        export_pot(self.outf, plugin, include_duplicates)
6223
6591
 
6224
6592
 
6225
6593
def _register_lazy_builtins():