/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/commands.py

  • Committer: Breezy landing bot
  • Author(s): Colin Watson
  • Date: 2020-11-16 21:47:08 UTC
  • mfrom: (7521.1.1 remove-lp-workaround)
  • Revision ID: breezy.the.bot@gmail.com-20201116214708-jos209mgxi41oy15
Remove breezy.git workaround for bazaar.launchpad.net.

Merged from https://code.launchpad.net/~cjwatson/brz/remove-lp-workaround/+merge/393710

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from __future__ import absolute_import
18
 
 
19
17
# TODO: Define arguments by objects, rather than just using names.
20
18
# Those objects can specify the expected type of the argument, which
21
19
# would help with validation and shell completion.  They could also provide
23
21
 
24
22
# TODO: Specific "examples" property on commands for consistent formatting.
25
23
 
 
24
import contextlib
26
25
import os
27
26
import sys
28
27
 
29
 
from bzrlib.lazy_import import lazy_import
 
28
from . import (
 
29
    i18n,
 
30
    option,
 
31
    osutils,
 
32
    )
 
33
 
 
34
from .lazy_import import lazy_import
30
35
lazy_import(globals(), """
31
36
import errno
32
 
import threading
33
37
 
34
 
import bzrlib
35
 
from bzrlib import (
36
 
    config,
37
 
    cleanup,
 
38
import breezy
 
39
from breezy import (
38
40
    cmdline,
39
41
    debug,
40
 
    errors,
41
 
    i18n,
42
 
    option,
43
 
    osutils,
44
42
    trace,
45
43
    ui,
46
44
    )
47
45
""")
48
46
 
49
 
from bzrlib.hooks import Hooks
50
 
from bzrlib.i18n import gettext
 
47
from .hooks import Hooks
 
48
from .i18n import gettext
51
49
# Compatibility - Option used to be in commands.
52
 
from bzrlib.option import Option
53
 
from bzrlib.plugin import disable_plugins, load_plugins
54
 
from bzrlib import registry
 
50
from .option import Option
 
51
from .plugin import disable_plugins, load_plugins, plugin_name
 
52
from . import errors, registry
 
53
 
 
54
 
 
55
class BzrOptionError(errors.CommandError):
 
56
 
 
57
    _fmt = "Error in command line options"
 
58
 
 
59
 
 
60
class CommandAvailableInPlugin(Exception):
 
61
 
 
62
    internal_error = False
 
63
 
 
64
    def __init__(self, cmd_name, plugin_metadata, provider):
 
65
 
 
66
        self.plugin_metadata = plugin_metadata
 
67
        self.cmd_name = cmd_name
 
68
        self.provider = provider
 
69
 
 
70
    def __str__(self):
 
71
 
 
72
        _fmt = ('"%s" is not a standard brz command. \n'
 
73
                'However, the following official plugin provides this command: %s\n'
 
74
                'You can install it by going to: %s'
 
75
                % (self.cmd_name, self.plugin_metadata['name'],
 
76
                    self.plugin_metadata['url']))
 
77
 
 
78
        return _fmt
55
79
 
56
80
 
57
81
class CommandInfo(object):
69
93
 
70
94
class CommandRegistry(registry.Registry):
71
95
    """Special registry mapping command names to command classes.
72
 
    
 
96
 
73
97
    :ivar overridden_registry: Look in this registry for commands being
74
98
        overridden by this registry.  This can be used to tell plugin commands
75
99
        about the builtin they're decorating.
118
142
        except KeyError:
119
143
            trace.warning('Two plugins defined the same command: %r' % k)
120
144
            trace.warning('Not loading the one in %r' %
121
 
                sys.modules[cmd.__module__])
 
145
                          sys.modules[cmd.__module__])
122
146
            trace.warning('Previously this command was registered from %r' %
123
 
                sys.modules[previous.__module__])
 
147
                          sys.modules[previous.__module__])
124
148
        for a in cmd.aliases:
125
149
            self._alias_dict[a] = k_unsquished
126
150
        return previous
147
171
def register_command(cmd, decorate=False):
148
172
    """Register a plugin command.
149
173
 
150
 
    Should generally be avoided in favor of lazy registration. 
 
174
    Should generally be avoided in favor of lazy registration.
151
175
    """
152
176
    global plugin_cmds
153
177
    return plugin_cmds.register(cmd, decorate)
158
182
 
159
183
 
160
184
def _unsquish_command_name(cmd):
161
 
    return cmd[4:].replace('_','-')
 
185
    return cmd[4:].replace('_', '-')
162
186
 
163
187
 
164
188
def _register_builtin_commands():
165
189
    if builtin_command_registry.keys():
166
190
        # only load once
167
191
        return
168
 
    import bzrlib.builtins
169
 
    for cmd_class in _scan_module_for_commands(bzrlib.builtins).values():
 
192
    import breezy.builtins
 
193
    for cmd_class in _scan_module_for_commands(breezy.builtins):
170
194
        builtin_command_registry.register(cmd_class)
171
 
    bzrlib.builtins._register_lazy_builtins()
 
195
    breezy.builtins._register_lazy_builtins()
172
196
 
173
197
 
174
198
def _scan_module_for_commands(module):
175
 
    r = {}
176
 
    for name, obj in module.__dict__.iteritems():
 
199
    module_dict = module.__dict__
 
200
    for name in module_dict:
177
201
        if name.startswith("cmd_"):
178
 
            real_name = _unsquish_command_name(name)
179
 
            r[real_name] = obj
180
 
    return r
 
202
            yield module_dict[name]
181
203
 
182
204
 
183
205
def _list_bzr_commands(names):
184
206
    """Find commands from bzr's core and plugins.
185
 
    
186
 
    This is not the public interface, just the default hook called by all_command_names.
 
207
 
 
208
    This is not the public interface, just the default hook called by
 
209
    all_command_names.
187
210
    """
188
211
    # to eliminate duplicates
189
212
    names.update(builtin_command_names())
204
227
 
205
228
def builtin_command_names():
206
229
    """Return list of builtin command names.
207
 
    
 
230
 
208
231
    Use of all_command_names() is encouraged rather than builtin_command_names
209
232
    and/or plugin_command_names.
210
233
    """
217
240
    return plugin_cmds.keys()
218
241
 
219
242
 
 
243
# Overrides for common mispellings that heuristics get wrong
 
244
_GUESS_OVERRIDES = {
 
245
    'ic': {'ci': 0},  # heuristic finds nick
 
246
    }
 
247
 
 
248
 
 
249
def guess_command(cmd_name):
 
250
    """Guess what command a user typoed.
 
251
 
 
252
    :param cmd_name: Command to search for
 
253
    :return: None if no command was found, name of a command otherwise
 
254
    """
 
255
    names = set()
 
256
    for name in all_command_names():
 
257
        names.add(name)
 
258
        cmd = get_cmd_object(name)
 
259
        names.update(cmd.aliases)
 
260
    # candidate: modified levenshtein distance against cmd_name.
 
261
    costs = {}
 
262
    import patiencediff
 
263
    for name in sorted(names):
 
264
        matcher = patiencediff.PatienceSequenceMatcher(None, cmd_name, name)
 
265
        distance = 0.0
 
266
        opcodes = matcher.get_opcodes()
 
267
        for opcode, l1, l2, r1, r2 in opcodes:
 
268
            if opcode == 'delete':
 
269
                distance += l2 - l1
 
270
            elif opcode == 'replace':
 
271
                distance += max(l2 - l1, r2 - l1)
 
272
            elif opcode == 'insert':
 
273
                distance += r2 - r1
 
274
            elif opcode == 'equal':
 
275
                # Score equal ranges lower, making similar commands of equal
 
276
                # length closer than arbitrary same length commands.
 
277
                distance -= 0.1 * (l2 - l1)
 
278
        costs[name] = distance
 
279
    costs.update(_GUESS_OVERRIDES.get(cmd_name, {}))
 
280
    costs = sorted((costs[key], key) for key in costs)
 
281
    if not costs:
 
282
        return
 
283
    if costs[0][0] > 4:
 
284
        return
 
285
    candidate = costs[0][1]
 
286
    return candidate
 
287
 
 
288
 
220
289
def get_cmd_object(cmd_name, plugins_override=True):
221
290
    """Return the command object for a command.
222
291
 
226
295
    try:
227
296
        return _get_cmd_object(cmd_name, plugins_override)
228
297
    except KeyError:
229
 
        raise errors.BzrCommandError(gettext('unknown command "%s"') % cmd_name)
 
298
        # No command found, see if this was a typo
 
299
        candidate = guess_command(cmd_name)
 
300
        if candidate is not None:
 
301
            raise errors.CommandError(
 
302
                gettext('unknown command "%s". Perhaps you meant "%s"')
 
303
                % (cmd_name, candidate))
 
304
        raise errors.CommandError(gettext('unknown command "%s"')
 
305
                                     % cmd_name)
230
306
 
231
307
 
232
308
def _get_cmd_object(cmd_name, plugins_override=True, check_missing=True):
267
343
    return cmd
268
344
 
269
345
 
 
346
class NoPluginAvailable(errors.BzrError):
 
347
    pass
 
348
 
 
349
 
270
350
def _try_plugin_provider(cmd_name):
271
351
    """Probe for a plugin provider having cmd_name."""
272
352
    try:
273
353
        plugin_metadata, provider = probe_for_provider(cmd_name)
274
 
        raise errors.CommandAvailableInPlugin(cmd_name,
275
 
            plugin_metadata, provider)
276
 
    except errors.NoPluginAvailable:
 
354
        raise CommandAvailableInPlugin(cmd_name, plugin_metadata, provider)
 
355
    except NoPluginAvailable:
277
356
        pass
278
357
 
279
358
 
288
367
    for provider in command_providers_registry:
289
368
        try:
290
369
            return provider.plugin_for_command(cmd_name), provider
291
 
        except errors.NoPluginAvailable:
 
370
        except NoPluginAvailable:
292
371
            pass
293
 
    raise errors.NoPluginAvailable(cmd_name)
 
372
    raise NoPluginAvailable(cmd_name)
294
373
 
295
374
 
296
375
def _get_bzr_command(cmd_or_None, cmd_name):
309
388
    # Only do external command lookups when no command is found so far.
310
389
    if cmd_or_None is not None:
311
390
        return cmd_or_None
312
 
    from bzrlib.externalcommand import ExternalCommand
 
391
    from breezy.externalcommand import ExternalCommand
313
392
    cmd_obj = ExternalCommand.find_command(cmd_name)
314
393
    if cmd_obj:
315
394
        return cmd_obj
316
395
 
317
396
 
318
397
def _get_plugin_command(cmd_or_None, cmd_name):
319
 
    """Get a command from bzr's plugins."""
 
398
    """Get a command from brz's plugins."""
320
399
    try:
321
400
        return plugin_cmds.get(cmd_name)()
322
401
    except KeyError:
331
410
class Command(object):
332
411
    """Base class for commands.
333
412
 
334
 
    Commands are the heart of the command-line bzr interface.
 
413
    Commands are the heart of the command-line brz interface.
335
414
 
336
415
    The command object mostly handles the mapping of command-line
337
 
    parameters into one or more bzrlib operations, and of the results
 
416
    parameters into one or more breezy operations, and of the results
338
417
    into textual output.
339
418
 
340
419
    Commands normally don't have any state.  All their arguments are
385
464
 
386
465
    :cvar hooks: An instance of CommandHooks.
387
466
 
388
 
    :cvar __doc__: The help shown by 'bzr help command' for this command.
 
467
    :cvar __doc__: The help shown by 'brz help command' for this command.
389
468
        This is set by assigning explicitly to __doc__ so that -OO can
390
469
        be used::
391
470
 
412
491
 
413
492
        Functions will be called in LIFO order.
414
493
        """
415
 
        self._operation.add_cleanup(cleanup_func, *args, **kwargs)
 
494
        self._exit_stack.callback(cleanup_func, *args, **kwargs)
416
495
 
417
496
    def cleanup_now(self):
418
497
        """Execute and empty pending cleanup functions immediately.
427
506
        as it releases all resources, this may release locks that the command
428
507
        wants to hold, so use should be done with care.
429
508
        """
430
 
        self._operation.cleanup_now()
 
509
        self._exit_stack.close()
 
510
 
 
511
    def enter_context(self, cm):
 
512
        return self._exit_stack.enter_context(cm)
431
513
 
432
514
    def _usage(self):
433
515
        """Return single-line grammar for this command.
434
516
 
435
517
        Only describes arguments, not options.
436
518
        """
437
 
        s = 'bzr ' + self.name() + ' '
 
519
        s = 'brz ' + self.name() + ' '
438
520
        for aname in self.takes_args:
439
521
            aname = aname.upper()
440
522
            if aname[-1] in ['$', '+']:
469
551
            # Note: If self.gettext() translates ':Usage:\n', the section will
470
552
            # be shown after "Description" section and we don't want to
471
553
            # translate the usage string.
472
 
            # Though, bzr export-pot don't exports :Usage: section and it must
 
554
            # Though, brz export-pot don't exports :Usage: section and it must
473
555
            # not be translated.
474
556
            doc = self.gettext(doc)
475
557
        else:
476
558
            doc = gettext("No help for this command.")
477
559
 
478
560
        # Extract the summary (purpose) and sections out from the text
479
 
        purpose,sections,order = self._get_help_parts(doc)
 
561
        purpose, sections, order = self._get_help_parts(doc)
480
562
 
481
563
        # If a custom usage section was provided, use it
482
 
        if sections.has_key('Usage'):
 
564
        if 'Usage' in sections:
483
565
            usage = sections.pop('Usage')
484
566
        else:
485
567
            usage = self._usage()
498
580
        # XXX: optparse implicitly rewraps the help, and not always perfectly,
499
581
        # so we get <https://bugs.launchpad.net/bzr/+bug/249908>.  -- mbp
500
582
        # 20090319
501
 
        parser = option.get_optparser(self.options())
 
583
        parser = option.get_optparser(
 
584
            [v for k, v in sorted(self.options().items())])
502
585
        options = parser.format_option_help()
503
586
        # FIXME: According to the spec, ReST option lists actually don't
504
587
        # support options like --1.14 so that causes syntax errors (in Sphinx
517
600
        if verbose:
518
601
            # Add the description, indenting it 2 spaces
519
602
            # to match the indentation of the options
520
 
            if sections.has_key(None):
 
603
            if None in sections:
521
604
                text = sections.pop(None)
522
605
                text = '\n  '.join(text.splitlines())
523
606
                result += gettext(':Description:\n  %s\n\n') % (text,)
530
613
                        result += ':%s:\n%s\n' % (label, sections[label])
531
614
                result += '\n'
532
615
        else:
533
 
            result += (gettext("See bzr help %s for more details and examples.\n\n")
534
 
                % self.name())
 
616
            result += (gettext("See brz help %s for more details and examples.\n\n")
 
617
                       % self.name())
535
618
 
536
619
        # Add the aliases, source (plug-in) and see also links, if any
537
620
        if self.aliases:
552
635
                    else:
553
636
                        # Use a Sphinx link for this entry
554
637
                        link_text = gettext(":doc:`{0} <{1}-help>`").format(
555
 
                                                                    item, item)
 
638
                            item, item)
556
639
                        see_also_links.append(link_text)
557
640
                see_also = see_also_links
558
641
            result += gettext(':See also: %s') % ', '.join(see_also) + '\n'
559
642
 
560
643
        # If this will be rendered as plain text, convert it
561
644
        if plain:
562
 
            import bzrlib.help_topics
563
 
            result = bzrlib.help_topics.help_as_plain_text(result)
 
645
            import breezy.help_topics
 
646
            result = breezy.help_topics.help_as_plain_text(result)
564
647
        return result
565
648
 
566
649
    @staticmethod
577
660
        """
578
661
        def save_section(sections, order, label, section):
579
662
            if len(section) > 0:
580
 
                if sections.has_key(label):
 
663
                if label in sections:
581
664
                    sections[label] += '\n' + section
582
665
                else:
583
666
                    order.append(label)
587
670
        summary = lines.pop(0)
588
671
        sections = {}
589
672
        order = []
590
 
        label,section = None,''
 
673
        label, section = None, ''
591
674
        for line in lines:
592
675
            if line.startswith(':') and line.endswith(':') and len(line) > 2:
593
676
                save_section(sections, order, label, section)
594
 
                label,section = line[1:-1],''
595
 
            elif (label is not None) and len(line) > 1 and not line[0].isspace():
 
677
                label, section = line[1:-1], ''
 
678
            elif (label is not None and len(line) > 1 and
 
679
                    not line[0].isspace()):
596
680
                save_section(sections, order, label, section)
597
 
                label,section = None,line
 
681
                label, section = None, line
598
682
            else:
599
683
                if len(section) > 0:
600
684
                    section += '\n' + line
625
709
 
626
710
        Maps from long option name to option object."""
627
711
        r = Option.STD_OPTIONS.copy()
628
 
        std_names = r.keys()
 
712
        std_names = set(r)
629
713
        for o in self.takes_options:
630
 
            if isinstance(o, basestring):
 
714
            if isinstance(o, str):
631
715
                o = option.Option.OPTIONS[o]
632
716
            r[o.name] = o
633
717
            if o.name in std_names:
645
729
        self._setup_outf()
646
730
 
647
731
        # Process the standard options
648
 
        if 'help' in opts:  # e.g. bzr add --help
 
732
        if 'help' in opts:  # e.g. brz add --help
649
733
            self.outf.write(self.get_help_text())
650
734
            return 0
651
 
        if 'usage' in opts:  # e.g. bzr add --usage
 
735
        if 'usage' in opts:  # e.g. brz add --usage
652
736
            self.outf.write(self.get_help_text(verbose=False))
653
737
            return 0
654
738
        trace.set_verbosity_level(option._verbosity_level)
655
739
        if 'verbose' in self.supported_std_options:
656
740
            opts['verbose'] = trace.is_verbose()
657
 
        elif opts.has_key('verbose'):
 
741
        elif 'verbose' in opts:
658
742
            del opts['verbose']
659
743
        if 'quiet' in self.supported_std_options:
660
744
            opts['quiet'] = trace.is_quiet()
661
 
        elif opts.has_key('quiet'):
 
745
        elif 'quiet' in opts:
662
746
            del opts['quiet']
663
747
        # mix arguments and options into one dictionary
664
748
        cmdargs = _match_argform(self.name(), self.takes_args, args)
689
773
        you can override this method.
690
774
        """
691
775
        class_run = self.run
 
776
 
692
777
        def run(*args, **kwargs):
693
778
            for hook in Command.hooks['pre_command']:
694
779
                hook(self)
695
 
            self._operation = cleanup.OperationWithCleanups(class_run)
696
780
            try:
697
 
                return self._operation.run_simple(*args, **kwargs)
 
781
                with contextlib.ExitStack() as self._exit_stack:
 
782
                    return class_run(*args, **kwargs)
698
783
            finally:
699
 
                del self._operation
700
784
                for hook in Command.hooks['post_command']:
701
785
                    hook(self)
702
786
        self.run = run
711
795
        shell error code if not.  It's OK for this method to allow
712
796
        an exception to raise up.
713
797
 
714
 
        This method is automatically wrapped by Command.__init__ with a 
715
 
        cleanup operation, stored as self._operation. This can be used
 
798
        This method is automatically wrapped by Command.__init__ with a
 
799
        ExitStack, stored as self._exit_stack. This can be used
716
800
        via self.add_cleanup to perform automatic cleanups at the end of
717
801
        run().
718
802
 
743
827
    def name(self):
744
828
        """Return the canonical name for this command.
745
829
 
746
 
        The name under which it was actually invoked is available in invoked_as.
 
830
        The name under which it was actually invoked is available in invoked_as
747
831
        """
748
832
        return _unsquish_command_name(self.__class__.__name__)
749
833
 
752
836
 
753
837
        :return: The name of the plugin or None if the command is builtin.
754
838
        """
755
 
        mod_parts = self.__module__.split('.')
756
 
        if len(mod_parts) >= 3 and mod_parts[1] == 'plugins':
757
 
            return mod_parts[2]
758
 
        else:
759
 
            return None
 
839
        return plugin_name(self.__module__)
760
840
 
761
841
 
762
842
class CommandHooks(Hooks):
768
848
        These are all empty initially, because by default nothing should get
769
849
        notified.
770
850
        """
771
 
        Hooks.__init__(self, "bzrlib.commands", "Command.hooks")
772
 
        self.add_hook('extend_command',
 
851
        Hooks.__init__(self, "breezy.commands", "Command.hooks")
 
852
        self.add_hook(
 
853
            'extend_command',
773
854
            "Called after creating a command object to allow modifications "
774
855
            "such as adding or removing options, docs etc. Called with the "
775
 
            "new bzrlib.commands.Command object.", (1, 13))
776
 
        self.add_hook('get_command',
 
856
            "new breezy.commands.Command object.", (1, 13))
 
857
        self.add_hook(
 
858
            'get_command',
777
859
            "Called when creating a single command. Called with "
778
860
            "(cmd_or_None, command_name). get_command should either return "
779
861
            "the cmd_or_None parameter, or a replacement Command object that "
780
862
            "should be used for the command. Note that the Command.hooks "
781
863
            "hooks are core infrastructure. Many users will prefer to use "
782
 
            "bzrlib.commands.register_command or plugin_cmds.register_lazy.",
 
864
            "breezy.commands.register_command or plugin_cmds.register_lazy.",
783
865
            (1, 17))
784
 
        self.add_hook('get_missing_command',
 
866
        self.add_hook(
 
867
            'get_missing_command',
785
868
            "Called when creating a single command if no command could be "
786
869
            "found. Called with (command_name). get_missing_command should "
787
870
            "either return None, or a Command object to be used for the "
788
871
            "command.", (1, 17))
789
 
        self.add_hook('list_commands',
 
872
        self.add_hook(
 
873
            'list_commands',
790
874
            "Called when enumerating commands. Called with a set of "
791
875
            "cmd_name strings for all the commands found so far. This set "
792
876
            " is safe to mutate - e.g. to remove a command. "
793
877
            "list_commands should return the updated set of command names.",
794
878
            (1, 17))
795
 
        self.add_hook('pre_command',
 
879
        self.add_hook(
 
880
            'pre_command',
796
881
            "Called prior to executing a command. Called with the command "
797
882
            "object.", (2, 6))
798
 
        self.add_hook('post_command',
 
883
        self.add_hook(
 
884
            'post_command',
799
885
            "Called after executing a command. Called with the command "
800
886
            "object.", (2, 6))
801
887
 
 
888
 
802
889
Command.hooks = CommandHooks()
803
890
 
804
891
 
811
898
    they take, and which commands will accept them.
812
899
    """
813
900
    # TODO: make it a method of the Command?
814
 
    parser = option.get_optparser(command.options())
 
901
    parser = option.get_optparser(
 
902
        [v for k, v in sorted(command.options().items())])
815
903
    if alias_argv is not None:
816
904
        args = alias_argv + argv
817
905
    else:
818
906
        args = argv
819
907
 
820
 
    # for python 2.5 and later, optparse raises this exception if a non-ascii
 
908
    # python 2's optparse raises this exception if a non-ascii
821
909
    # option name is given.  See http://bugs.python.org/issue2931
822
910
    try:
823
911
        options, args = parser.parse_args(args)
824
 
    except UnicodeEncodeError,e:
825
 
        raise errors.BzrCommandError(
 
912
    except UnicodeEncodeError:
 
913
        raise errors.CommandError(
826
914
            gettext('Only ASCII permitted in option names'))
827
915
 
828
 
    opts = dict([(k, v) for k, v in options.__dict__.iteritems() if
829
 
                 v is not option.OptionParser.DEFAULT_VALUE])
 
916
    opts = dict((k, v) for k, v in options.__dict__.items() if
 
917
                v is not option.OptionParser.DEFAULT_VALUE)
830
918
    return args, opts
831
919
 
832
920
 
839
927
        if ap[-1] == '?':
840
928
            if args:
841
929
                argdict[argname] = args.pop(0)
842
 
        elif ap[-1] == '*': # all remaining arguments
 
930
        elif ap[-1] == '*':  # all remaining arguments
843
931
            if args:
844
932
                argdict[argname + '_list'] = args[:]
845
933
                args = []
847
935
                argdict[argname + '_list'] = None
848
936
        elif ap[-1] == '+':
849
937
            if not args:
850
 
                raise errors.BzrCommandError(gettext(
851
 
                      "command {0!r} needs one or more {1}").format(
852
 
                      cmd, argname.upper()))
 
938
                raise errors.CommandError(gettext(
 
939
                    "command {0!r} needs one or more {1}").format(
 
940
                    cmd, argname.upper()))
853
941
            else:
854
942
                argdict[argname + '_list'] = args[:]
855
943
                args = []
856
 
        elif ap[-1] == '$': # all but one
 
944
        elif ap[-1] == '$':  # all but one
857
945
            if len(args) < 2:
858
 
                raise errors.BzrCommandError(
859
 
                      gettext("command {0!r} needs one or more {1}").format(
860
 
                                             cmd, argname.upper()))
 
946
                raise errors.CommandError(
 
947
                    gettext("command {0!r} needs one or more {1}").format(
 
948
                        cmd, argname.upper()))
861
949
            argdict[argname + '_list'] = args[:-1]
862
950
            args[:-1] = []
863
951
        else:
864
952
            # just a plain arg
865
953
            argname = ap
866
954
            if not args:
867
 
                raise errors.BzrCommandError(
868
 
                     gettext("command {0!r} requires argument {1}").format(
869
 
                               cmd, argname.upper()))
 
955
                raise errors.CommandError(
 
956
                    gettext("command {0!r} requires argument {1}").format(
 
957
                        cmd, argname.upper()))
870
958
            else:
871
959
                argdict[argname] = args.pop(0)
872
960
 
873
961
    if args:
874
 
        raise errors.BzrCommandError( gettext(
875
 
                              "extra argument to command {0}: {1}").format(
876
 
                                       cmd, args[0]) )
 
962
        raise errors.CommandError(gettext(
 
963
            "extra argument to command {0}: {1}").format(
 
964
            cmd, args[0]))
877
965
 
878
966
    return argdict
879
967
 
880
 
def apply_coveraged(dirname, the_callable, *args, **kwargs):
881
 
    # Cannot use "import trace", as that would import bzrlib.trace instead of
882
 
    # the standard library's trace.
883
 
    trace = __import__('trace')
884
 
 
885
 
    tracer = trace.Trace(count=1, trace=0)
886
 
    sys.settrace(tracer.globaltrace)
887
 
    threading.settrace(tracer.globaltrace)
888
 
 
 
968
 
 
969
def apply_coveraged(the_callable, *args, **kwargs):
 
970
    import coverage
 
971
    cov = coverage.Coverage()
 
972
    try:
 
973
        config_file = cov.config.config_file
 
974
    except AttributeError:  # older versions of coverage
 
975
        config_file = cov.config_file
 
976
    os.environ['COVERAGE_PROCESS_START'] = config_file
 
977
    cov.start()
889
978
    try:
890
979
        return exception_to_return_code(the_callable, *args, **kwargs)
891
980
    finally:
892
 
        sys.settrace(None)
893
 
        results = tracer.results()
894
 
        results.write_results(show_missing=1, summary=False,
895
 
                              coverdir=dirname)
 
981
        cov.stop()
 
982
        cov.save()
896
983
 
897
984
 
898
985
def apply_profiled(the_callable, *args, **kwargs):
904
991
        prof = hotshot.Profile(pfname)
905
992
        try:
906
993
            ret = prof.runcall(exception_to_return_code, the_callable, *args,
907
 
                **kwargs) or 0
 
994
                               **kwargs) or 0
908
995
        finally:
909
996
            prof.close()
910
997
        stats = hotshot.stats.load(pfname)
911
998
        stats.strip_dirs()
912
999
        stats.sort_stats('cum')   # 'time'
913
 
        ## XXX: Might like to write to stderr or the trace file instead but
914
 
        ## print_stats seems hardcoded to stdout
 
1000
        # XXX: Might like to write to stderr or the trace file instead but
 
1001
        # print_stats seems hardcoded to stdout
915
1002
        stats.print_stats(20)
916
1003
        return ret
917
1004
    finally:
928
1015
    """
929
1016
    try:
930
1017
        return the_callable(*args, **kwargs)
931
 
    except (KeyboardInterrupt, Exception), e:
 
1018
    except (KeyboardInterrupt, Exception):
932
1019
        # used to handle AssertionError and KeyboardInterrupt
933
1020
        # specially here, but hopefully they're handled ok by the logger now
934
1021
        exc_info = sys.exc_info()
935
1022
        exitcode = trace.report_exception(exc_info, sys.stderr)
936
 
        if os.environ.get('BZR_PDB'):
937
 
            print '**** entering debugger'
 
1023
        if os.environ.get('BRZ_PDB'):
 
1024
            print('**** entering debugger')
938
1025
            import pdb
939
1026
            pdb.post_mortem(exc_info[2])
940
1027
        return exitcode
941
1028
 
942
1029
 
943
1030
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
944
 
    from bzrlib.lsprof import profile
 
1031
    from breezy.lsprof import profile
945
1032
    ret, stats = profile(exception_to_return_code, the_callable,
946
1033
                         *args, **kwargs)
947
1034
    stats.sort()
964
1051
        If it is unspecified, the global config will be used.
965
1052
    """
966
1053
    if config is None:
967
 
        import bzrlib.config
968
 
        config = bzrlib.config.GlobalConfig()
 
1054
        import breezy.config
 
1055
        config = breezy.config.GlobalConfig()
969
1056
    alias = config.get_alias(cmd)
970
1057
    if (alias):
971
1058
        return cmdline.split(alias)
1008
1095
        Run under the Python lsprof profiler.
1009
1096
 
1010
1097
    --coverage
1011
 
        Generate line coverage report in the specified directory.
 
1098
        Generate code coverage report
1012
1099
 
1013
1100
    --concurrency
1014
 
        Specify the number of processes that can be run concurrently (selftest).
 
1101
        Specify the number of processes that can be run concurrently
 
1102
        (selftest).
1015
1103
    """
1016
 
    trace.mutter("bazaar version: " + bzrlib.__version__)
 
1104
    trace.mutter("breezy version: " + breezy.__version__)
1017
1105
    argv = _specified_or_unicode_argv(argv)
1018
 
    trace.mutter("bzr arguments: %r", argv)
 
1106
    trace.mutter("brz arguments: %r", argv)
1019
1107
 
1020
1108
    opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = \
1021
 
            opt_no_l10n = opt_no_aliases = False
1022
 
    opt_lsprof_file = opt_coverage_dir = None
 
1109
        opt_coverage = opt_no_l10n = opt_no_aliases = False
 
1110
    opt_lsprof_file = None
1023
1111
 
1024
1112
    # --no-plugins is handled specially at a very early stage. We need
1025
1113
    # to load plugins before doing other command parsing so that they
1047
1135
        elif a == '--builtin':
1048
1136
            opt_builtin = True
1049
1137
        elif a == '--concurrency':
1050
 
            os.environ['BZR_CONCURRENCY'] = argv[i + 1]
 
1138
            os.environ['BRZ_CONCURRENCY'] = argv[i + 1]
1051
1139
            i += 1
1052
1140
        elif a == '--coverage':
1053
 
            opt_coverage_dir = argv[i + 1]
1054
 
            i += 1
 
1141
            opt_coverage = True
1055
1142
        elif a == '--profile-imports':
1056
 
            pass # already handled in startup script Bug #588277
 
1143
            pass  # already handled in startup script Bug #588277
1057
1144
        elif a.startswith('-D'):
1058
1145
            debug.debug_flags.add(a[2:])
1059
1146
        elif a.startswith('-O'):
1062
1149
            argv_copy.append(a)
1063
1150
        i += 1
1064
1151
 
1065
 
    if bzrlib.global_state is None:
1066
 
        # FIXME: Workaround for users that imported bzrlib but didn't call
1067
 
        # bzrlib.initialize -- vila 2012-01-19
1068
 
        cmdline_overrides = config.CommandLineStore()
1069
 
    else:
1070
 
        cmdline_overrides = bzrlib.global_state.cmdline_overrides
 
1152
    cmdline_overrides = breezy.get_global_state().cmdline_overrides
1071
1153
    cmdline_overrides._from_cmdline(override_config)
1072
1154
 
1073
1155
    debug.set_debug_flags_from_config()
1074
1156
 
1075
1157
    if not opt_no_plugins:
1076
 
        load_plugins()
 
1158
        from breezy import config
 
1159
        c = config.GlobalConfig()
 
1160
        warn_load_problems = not c.suppress_warning('plugin_load_failure')
 
1161
        load_plugins(warn_load_problems=warn_load_problems)
1077
1162
    else:
1078
1163
        disable_plugins()
1079
1164
 
1096
1181
    cmd = argv.pop(0)
1097
1182
    cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
1098
1183
    if opt_no_l10n:
1099
 
        cmd.l10n = False
 
1184
        cmd_obj.l10n = False
1100
1185
    run = cmd_obj.run_argv_aliases
1101
1186
    run_argv = [argv, alias_argv]
1102
1187
 
1106
1191
        saved_verbosity_level = option._verbosity_level
1107
1192
        option._verbosity_level = 0
1108
1193
        if opt_lsprof:
1109
 
            if opt_coverage_dir:
 
1194
            if opt_coverage:
1110
1195
                trace.warning(
1111
1196
                    '--coverage ignored, because --lsprof is in use.')
1112
1197
            ret = apply_lsprofiled(opt_lsprof_file, run, *run_argv)
1113
1198
        elif opt_profile:
1114
 
            if opt_coverage_dir:
 
1199
            if opt_coverage:
1115
1200
                trace.warning(
1116
1201
                    '--coverage ignored, because --profile is in use.')
1117
1202
            ret = apply_profiled(run, *run_argv)
1118
 
        elif opt_coverage_dir:
1119
 
            ret = apply_coveraged(opt_coverage_dir, run, *run_argv)
 
1203
        elif opt_coverage:
 
1204
            ret = apply_coveraged(run, *run_argv)
1120
1205
        else:
1121
1206
            ret = run(*run_argv)
1122
1207
        return ret or 0
1127
1212
        if 'memory' in debug.debug_flags:
1128
1213
            trace.debug_memory('Process status after command:', short=False)
1129
1214
        option._verbosity_level = saved_verbosity_level
1130
 
        # Reset the overrides 
 
1215
        # Reset the overrides
1131
1216
        cmdline_overrides._reset()
1132
1217
 
1133
1218
 
1138
1223
            result = func(*args, **kwargs)
1139
1224
            sys.stdout.flush()
1140
1225
            return result
1141
 
        except IOError, e:
 
1226
        except IOError as e:
1142
1227
            if getattr(e, 'errno', None) is None:
1143
1228
                raise
1144
1229
            if e.errno != errno.EPIPE:
1156
1241
    if _list_bzr_commands in Command.hooks["list_commands"]:
1157
1242
        return
1158
1243
    Command.hooks.install_named_hook("list_commands", _list_bzr_commands,
1159
 
        "bzr commands")
 
1244
                                     "bzr commands")
1160
1245
    Command.hooks.install_named_hook("get_command", _get_bzr_command,
1161
 
        "bzr commands")
 
1246
                                     "bzr commands")
1162
1247
    Command.hooks.install_named_hook("get_command", _get_plugin_command,
1163
 
        "bzr plugin commands")
 
1248
                                     "bzr plugin commands")
1164
1249
    Command.hooks.install_named_hook("get_command", _get_external_command,
1165
 
        "bzr external command lookup")
 
1250
                                     "bzr external command lookup")
1166
1251
    Command.hooks.install_named_hook("get_missing_command",
1167
1252
                                     _try_plugin_provider,
1168
1253
                                     "bzr plugin-provider-db check")
1169
1254
 
1170
1255
 
1171
 
 
1172
1256
def _specified_or_unicode_argv(argv):
1173
1257
    # For internal or testing use, argv can be passed.  Otherwise, get it from
1174
 
    # the process arguments in a unicode-safe way.
 
1258
    # the process arguments.
1175
1259
    if argv is None:
1176
 
        return osutils.get_unicode_argv()
1177
 
    else:
1178
 
        new_argv = []
1179
 
        try:
1180
 
            # ensure all arguments are unicode strings
1181
 
            for a in argv:
1182
 
                if isinstance(a, unicode):
1183
 
                    new_argv.append(a)
1184
 
                else:
1185
 
                    new_argv.append(a.decode('ascii'))
1186
 
        except UnicodeDecodeError:
1187
 
            raise errors.BzrError("argv should be list of unicode strings.")
1188
 
        return new_argv
 
1260
        return sys.argv[1:]
 
1261
    new_argv = []
 
1262
    try:
 
1263
        # ensure all arguments are unicode strings
 
1264
        for a in argv:
 
1265
            if not isinstance(a, str):
 
1266
                raise ValueError('not native str or unicode: %r' % (a,))
 
1267
            new_argv.append(a)
 
1268
    except (ValueError, UnicodeDecodeError):
 
1269
        raise errors.BzrError("argv should be list of unicode strings.")
 
1270
    return new_argv
1189
1271
 
1190
1272
 
1191
1273
def main(argv=None):
1192
1274
    """Main entry point of command-line interface.
1193
1275
 
1194
 
    Typically `bzrlib.initialize` should be called first.
 
1276
    Typically `breezy.initialize` should be called first.
1195
1277
 
1196
1278
    :param argv: list of unicode command-line arguments similar to sys.argv.
1197
1279
        argv[0] is script name usually, it will be ignored.
1198
1280
        Don't pass here sys.argv because this list contains plain strings
1199
1281
        and not unicode; pass None instead.
1200
1282
 
1201
 
    :return: exit code of bzr command.
 
1283
    :return: exit code of brz command.
1202
1284
    """
1203
1285
    if argv is not None:
1204
1286
        argv = argv[1:]
1212
1294
    """Run a bzr command with parameters as described by argv.
1213
1295
 
1214
1296
    This function assumed that that UI layer is setup, that symbol deprecations
1215
 
    are already applied, and that unicode decoding has already been performed on argv.
 
1297
    are already applied, and that unicode decoding has already been performed
 
1298
    on argv.
1216
1299
    """
1217
1300
    # done here so that they're covered for every test run
1218
1301
    install_bzr_command_hooks()
1220
1303
 
1221
1304
 
1222
1305
def run_bzr_catch_user_errors(argv):
1223
 
    """Run bzr and report user errors, but let internal errors propagate.
 
1306
    """Run brz and report user errors, but let internal errors propagate.
1224
1307
 
1225
1308
    This is used for the test suite, and might be useful for other programs
1226
1309
    that want to wrap the commandline interface.
1229
1312
    install_bzr_command_hooks()
1230
1313
    try:
1231
1314
        return run_bzr(argv)
1232
 
    except Exception, e:
 
1315
    except Exception as e:
1233
1316
        if (isinstance(e, (OSError, IOError))
1234
 
            or not getattr(e, 'internal_error', True)):
 
1317
                or not getattr(e, 'internal_error', True)):
1235
1318
            trace.report_exception(sys.exc_info(), sys.stderr)
1236
1319
            return 3
1237
1320
        else:
1277
1360
    """This registry exists to allow other providers to exist"""
1278
1361
 
1279
1362
    def __iter__(self):
1280
 
        for key, provider in self.iteritems():
 
1363
        for key, provider in self.items():
1281
1364
            yield provider
1282
1365
 
 
1366
 
1283
1367
command_providers_registry = ProvidersRegistry()