24
26
# TODO: Specific "examples" property on commands for consistent formatting.
28
# TODO: "--profile=cum", to change sort order. Is there any value in leaving
29
# the profile output behind so it can be interactively examined?
35
from .lazy_import import lazy_import
34
from bzrlib.lazy_import import lazy_import
36
35
lazy_import(globals(), """
39
from warnings import warn
49
from .hooks import Hooks
50
from .i18n import gettext
54
from bzrlib.hooks import HookPoint, Hooks
51
55
# Compatibility - Option used to be in commands.
52
from .option import Option
53
from .plugin import disable_plugins, load_plugins, plugin_name
54
from . import errors, registry
56
from bzrlib.option import Option
57
from bzrlib import registry
58
from bzrlib.symbol_versioning import (
60
class BzrOptionError(errors.BzrCommandError):
62
_fmt = "Error in command line options"
65
class CommandAvailableInPlugin(Exception):
67
internal_error = False
69
def __init__(self, cmd_name, plugin_metadata, provider):
71
self.plugin_metadata = plugin_metadata
72
self.cmd_name = cmd_name
73
self.provider = provider
77
_fmt = ('"%s" is not a standard brz command. \n'
78
'However, the following official plugin provides this command: %s\n'
79
'You can install it by going to: %s'
80
% (self.cmd_name, self.plugin_metadata['name'],
81
self.plugin_metadata['url']))
86
65
class CommandInfo(object):
87
66
"""Information about a command."""
99
78
class CommandRegistry(registry.Registry):
100
"""Special registry mapping command names to command classes.
102
:ivar overridden_registry: Look in this registry for commands being
103
overridden by this registry. This can be used to tell plugin commands
104
about the builtin they're decorating.
108
registry.Registry.__init__(self)
109
self.overridden_registry = None
110
# map from aliases to the real command that implements the name
111
self._alias_dict = {}
113
def get(self, command_name):
114
real_name = self._alias_dict.get(command_name, command_name)
115
return registry.Registry.get(self, real_name)
118
81
def _get_name(command_name):
164
120
key = self._get_name(command_name)
165
121
registry.Registry.register_lazy(self, key, module_name, command_name,
166
122
info=CommandInfo(aliases))
168
self._alias_dict[a] = key
171
125
plugin_cmds = CommandRegistry()
172
builtin_command_registry = CommandRegistry()
173
plugin_cmds.overridden_registry = builtin_command_registry
176
128
def register_command(cmd, decorate=False):
177
"""Register a plugin command.
179
Should generally be avoided in favor of lazy registration.
181
129
global plugin_cmds
182
130
return plugin_cmds.register(cmd, decorate)
189
137
def _unsquish_command_name(cmd):
190
return cmd[4:].replace('_', '-')
193
def _register_builtin_commands():
194
if builtin_command_registry.keys():
197
import breezy.builtins
198
for cmd_class in _scan_module_for_commands(breezy.builtins):
199
builtin_command_registry.register(cmd_class)
200
breezy.builtins._register_lazy_builtins()
138
return cmd[4:].replace('_','-')
141
def _builtin_commands():
142
import bzrlib.builtins
143
return _scan_module_for_commands(bzrlib.builtins)
203
146
def _scan_module_for_commands(module):
204
module_dict = module.__dict__
205
for name in module_dict:
148
for name, obj in module.__dict__.iteritems():
206
149
if name.startswith("cmd_"):
207
yield module_dict[name]
150
real_name = _unsquish_command_name(name)
210
155
def _list_bzr_commands(names):
211
"""Find commands from bzr's core and plugins.
213
This is not the public interface, just the default hook called by
156
"""Find commands from bzr's core and plugins."""
216
157
# to eliminate duplicates
217
158
names.update(builtin_command_names())
218
159
names.update(plugin_command_names())
245
185
return plugin_cmds.keys()
248
# Overrides for common mispellings that heuristics get wrong
250
'ic': {'ci': 0}, # heuristic finds nick
254
def guess_command(cmd_name):
255
"""Guess what command a user typoed.
257
:param cmd_name: Command to search for
258
:return: None if no command was found, name of a command otherwise
261
for name in all_command_names():
263
cmd = get_cmd_object(name)
264
names.update(cmd.aliases)
265
# candidate: modified levenshtein distance against cmd_name.
268
for name in sorted(names):
269
matcher = patiencediff.PatienceSequenceMatcher(None, cmd_name, name)
271
opcodes = matcher.get_opcodes()
272
for opcode, l1, l2, r1, r2 in opcodes:
273
if opcode == 'delete':
275
elif opcode == 'replace':
276
distance += max(l2 - l1, r2 - l1)
277
elif opcode == 'insert':
279
elif opcode == 'equal':
280
# Score equal ranges lower, making similar commands of equal
281
# length closer than arbitrary same length commands.
282
distance -= 0.1 * (l2 - l1)
283
costs[name] = distance
284
costs.update(_GUESS_OVERRIDES.get(cmd_name, {}))
285
costs = sorted((costs[key], key) for key in costs)
290
candidate = costs[0][1]
294
188
def get_cmd_object(cmd_name, plugins_override=True):
295
189
"""Return the command object for a command.
301
195
return _get_cmd_object(cmd_name, plugins_override)
303
# No command found, see if this was a typo
304
candidate = guess_command(cmd_name)
305
if candidate is not None:
306
raise errors.BzrCommandError(
307
gettext('unknown command "%s". Perhaps you meant "%s"')
308
% (cmd_name, candidate))
309
raise errors.BzrCommandError(gettext('unknown command "%s"')
313
def _get_cmd_object(cmd_name, plugins_override=True, check_missing=True):
197
raise errors.BzrCommandError('unknown command "%s"' % cmd_name)
200
def _get_cmd_object(cmd_name, plugins_override=True):
314
201
"""Get a command object.
316
203
:param cmd_name: The name of the command.
317
204
:param plugins_override: Allow plugins to override builtins.
318
:param check_missing: Look up commands not found in the regular index via
319
the get_missing_command hook.
320
205
:return: A Command object instance
321
206
:raises KeyError: If no command is found.
343
228
# Allow plugins to extend commands
344
229
for hook in Command.hooks['extend_command']:
346
if getattr(cmd, 'invoked_as', None) is None:
347
cmd.invoked_as = cmd_name
351
class NoPluginAvailable(errors.BzrError):
355
234
def _try_plugin_provider(cmd_name):
356
235
"""Probe for a plugin provider having cmd_name."""
358
237
plugin_metadata, provider = probe_for_provider(cmd_name)
359
raise CommandAvailableInPlugin(cmd_name, plugin_metadata, provider)
360
except NoPluginAvailable:
238
raise errors.CommandAvailableInPlugin(cmd_name,
239
plugin_metadata, provider)
240
except errors.NoPluginAvailable:
372
252
for provider in command_providers_registry:
374
254
return provider.plugin_for_command(cmd_name), provider
375
except NoPluginAvailable:
255
except errors.NoPluginAvailable:
377
raise NoPluginAvailable(cmd_name)
257
raise errors.NoPluginAvailable(cmd_name)
380
260
def _get_bzr_command(cmd_or_None, cmd_name):
381
261
"""Get a command from bzr's core."""
262
cmds = _builtin_commands()
383
cmd_class = builtin_command_registry.get(cmd_name)
264
return cmds[cmd_name]()
267
# look for any command which claims this as an alias
268
for real_cmd_name, cmd_class in cmds.iteritems():
269
if cmd_name in cmd_class.aliases:
388
271
return cmd_or_None
430
313
summary, then a complete description of the command. A grammar
431
314
description will be inserted.
433
:cvar aliases: Other accepted names for this command.
435
:cvar takes_args: List of argument forms, marked with whether they are
436
optional, repeated, etc. Examples::
438
['to_location', 'from_branch?', 'file*']
440
* 'to_location' is required
441
* 'from_branch' is optional
442
* 'file' can be specified 0 or more times
444
:cvar takes_options: List of options that may be given for this command.
445
These can be either strings, referring to globally-defined options, or
446
option objects. Retrieve through options().
448
:cvar hidden: If true, this command isn't advertised. This is typically
317
Other accepted names for this command.
320
List of argument forms, marked with whether they are optional,
325
['to_location', 'from_branch?', 'file*']
327
'to_location' is required
328
'from_branch' is optional
329
'file' can be specified 0 or more times
332
List of options that may be given for this command. These can
333
be either strings, referring to globally-defined options,
334
or option objects. Retrieve through options().
337
If true, this command isn't advertised. This is typically
449
338
for commands intended for expert users.
451
:cvar encoding_type: Command objects will get a 'outf' attribute, which has
452
been setup to properly handle encoding of unicode strings.
453
encoding_type determines what will happen when characters cannot be
456
* strict - abort if we cannot decode
457
* replace - put in a bogus character (typically '?')
458
* exact - do not encode sys.stdout
460
NOTE: by default on Windows, sys.stdout is opened as a text stream,
461
therefore LF line-endings are converted to CRLF. When a command uses
462
encoding_type = 'exact', then sys.stdout is forced to be a binary
463
stream, and line-endings will not mangled.
466
A string indicating the real name under which this command was
467
invoked, before expansion of aliases.
468
(This may be None if the command was constructed and run in-process.)
341
Command objects will get a 'outf' attribute, which has been
342
setup to properly handle encoding of unicode strings.
343
encoding_type determines what will happen when characters cannot
345
strict - abort if we cannot decode
346
replace - put in a bogus character (typically '?')
347
exact - do not encode sys.stdout
349
NOTE: by default on Windows, sys.stdout is opened as a text
350
stream, therefore LF line-endings are converted to CRLF.
351
When a command uses encoding_type = 'exact', then
352
sys.stdout is forced to be a binary stream, and line-endings
470
355
:cvar hooks: An instance of CommandHooks.
472
:cvar __doc__: The help shown by 'brz help command' for this command.
473
This is set by assigning explicitly to __doc__ so that -OO can
477
__doc__ = "My help goes here"
481
359
takes_options = []
482
360
encoding_type = 'strict'
488
364
def __init__(self):
489
365
"""Construct an instance of this command."""
366
if self.__doc__ == Command.__doc__:
367
warn("No help message set for %r" % self)
490
368
# List of standard options directly supported
491
369
self.supported_std_options = []
370
self._operation = cleanup.OperationWithCleanups(self.run)
494
372
def add_cleanup(self, cleanup_func, *args, **kwargs):
495
373
"""Register a function to call after self.run returns or raises.
497
375
Functions will be called in LIFO order.
499
self._exit_stack.callback(cleanup_func, *args, **kwargs)
377
self._operation.add_cleanup(cleanup_func, *args, **kwargs)
501
379
def cleanup_now(self):
502
380
"""Execute and empty pending cleanup functions immediately.
508
386
This is useful for releasing expensive or contentious resources (such
509
387
as write locks) before doing further work that does not require those
510
resources (such as writing results to self.outf). Note though, that
511
as it releases all resources, this may release locks that the command
512
wants to hold, so use should be done with care.
514
self._exit_stack.close()
516
def enter_context(self, cm):
517
return self._exit_stack.enter_context(cm)
388
resources (such as writing results to self.outf).
390
self._operation.cleanup_now()
392
@deprecated_method(deprecated_in((2, 1, 0)))
393
def _maybe_expand_globs(self, file_list):
394
"""Glob expand file_list if the platform does not do that itself.
396
Not used anymore, now that the bzr command-line parser globs on
399
:return: A possibly empty list of unicode paths.
401
Introduced in bzrlib 0.18.
519
405
def _usage(self):
520
406
"""Return single-line grammar for this command.
522
408
Only describes arguments, not options.
524
s = 'brz ' + self.name() + ' '
410
s = 'bzr ' + self.name() + ' '
525
411
for aname in self.takes_args:
526
412
aname = aname.upper()
527
413
if aname[-1] in ['$', '+']:
549
435
usage help (e.g. Purpose, Usage, Options) with a
550
436
message explaining how to obtain full help.
553
i18n.install() # Install i18n only for get_help_text for now.
554
438
doc = self.help()
556
# Note: If self.gettext() translates ':Usage:\n', the section will
557
# be shown after "Description" section and we don't want to
558
# translate the usage string.
559
# Though, brz export-pot don't exports :Usage: section and it must
561
doc = self.gettext(doc)
563
doc = gettext("No help for this command.")
440
raise NotImplementedError("sorry, no detailed help yet for %r" % self.name())
565
442
# Extract the summary (purpose) and sections out from the text
566
purpose, sections, order = self._get_help_parts(doc)
443
purpose,sections,order = self._get_help_parts(doc)
568
445
# If a custom usage section was provided, use it
569
if 'Usage' in sections:
446
if sections.has_key('Usage'):
570
447
usage = sections.pop('Usage')
572
449
usage = self._usage()
574
451
# The header is the purpose and usage
576
result += gettext(':Purpose: %s\n') % (purpose,)
453
result += ':Purpose: %s\n' % purpose
577
454
if usage.find('\n') >= 0:
578
result += gettext(':Usage:\n%s\n') % (usage,)
455
result += ':Usage:\n%s\n' % usage
580
result += gettext(':Usage: %s\n') % (usage,)
457
result += ':Usage: %s\n' % usage
583
460
# Add the options
585
462
# XXX: optparse implicitly rewraps the help, and not always perfectly,
586
463
# so we get <https://bugs.launchpad.net/bzr/+bug/249908>. -- mbp
588
parser = option.get_optparser(
589
[v for k, v in sorted(self.options().items())])
590
options = parser.format_option_help()
591
# FIXME: According to the spec, ReST option lists actually don't
592
# support options like --1.14 so that causes syntax errors (in Sphinx
593
# at least). As that pattern always appears in the commands that
594
# break, we trap on that and then format that block of 'format' options
595
# as a literal block. We use the most recent format still listed so we
596
# don't have to do that too often -- vila 20110514
597
if not plain and options.find(' --1.14 ') != -1:
465
options = option.get_optparser(self.options()).format_option_help()
466
# XXX: According to the spec, ReST option lists actually don't support
467
# options like --1.9 so that causes syntax errors (in Sphinx at least).
468
# As that pattern always appears in the commands that break, we trap
469
# on that and then format that block of 'format' options as a literal
471
if not plain and options.find(' --1.9 ') != -1:
598
472
options = options.replace(' format:\n', ' format::\n\n', 1)
599
473
if options.startswith('Options:'):
600
result += gettext(':Options:%s') % (options[len('options:'):],)
474
result += ':' + options
475
elif options.startswith('options:'):
476
# Python 2.4 version of optparse
477
result += ':Options:' + options[len('options:'):]
602
479
result += options
606
483
# Add the description, indenting it 2 spaces
607
484
# to match the indentation of the options
485
if sections.has_key(None):
609
486
text = sections.pop(None)
610
487
text = '\n '.join(text.splitlines())
611
result += gettext(':Description:\n %s\n\n') % (text,)
488
result += ':%s:\n %s\n\n' % ('Description',text)
613
490
# Add the custom sections (e.g. Examples). Note that there's no need
614
491
# to indent these as they must be indented already in the source.
616
493
for label in order:
617
if label in sections:
618
result += ':%s:\n%s\n' % (label, sections[label])
494
if sections.has_key(label):
495
result += ':%s:\n%s\n' % (label,sections[label])
621
result += (gettext("See brz help %s for more details and examples.\n\n")
498
result += ("See bzr help %s for more details and examples.\n\n"
624
501
# Add the aliases, source (plug-in) and see also links, if any
626
result += gettext(':Aliases: ')
503
result += ':Aliases: '
627
504
result += ', '.join(self.aliases) + '\n'
628
505
plugin_name = self.plugin_name()
629
506
if plugin_name is not None:
630
result += gettext(':From: plugin "%s"\n') % plugin_name
507
result += ':From: plugin "%s"\n' % plugin_name
631
508
see_also = self.get_see_also(additional_see_also)
633
510
if not plain and see_also_as_links:
639
516
see_also_links.append(item)
641
518
# Use a Sphinx link for this entry
642
link_text = gettext(":doc:`{0} <{1}-help>`").format(
519
link_text = ":doc:`%s <%s-help>`" % (item, item)
644
520
see_also_links.append(link_text)
645
521
see_also = see_also_links
646
result += gettext(':See also: %s') % ', '.join(see_also) + '\n'
522
result += ':See also: '
523
result += ', '.join(see_also) + '\n'
648
525
# If this will be rendered as plain text, convert it
650
import breezy.help_topics
651
result = breezy.help_topics.help_as_plain_text(result)
527
import bzrlib.help_topics
528
result = bzrlib.help_topics.help_as_plain_text(result)
675
552
summary = lines.pop(0)
678
label, section = None, ''
555
label,section = None,''
679
556
for line in lines:
680
557
if line.startswith(':') and line.endswith(':') and len(line) > 2:
681
558
save_section(sections, order, label, section)
682
label, section = line[1:-1], ''
683
elif (label is not None and len(line) > 1 and
684
not line[0].isspace()):
559
label,section = line[1:-1],''
560
elif (label is not None) and len(line) > 1 and not line[0].isspace():
685
561
save_section(sections, order, label, section)
686
label, section = None, line
562
label,section = None,line
688
564
if len(section) > 0:
689
565
section += '\n' + line
731
607
def run_argv_aliases(self, argv, alias_argv=None):
732
608
"""Parse the command line and run with extra aliases in alias_argv."""
733
609
args, opts = parse_args(self, argv, alias_argv)
736
611
# Process the standard options
737
if 'help' in opts: # e.g. brz add --help
738
self.outf.write(self.get_help_text())
612
if 'help' in opts: # e.g. bzr add --help
613
sys.stdout.write(self.get_help_text())
740
if 'usage' in opts: # e.g. brz add --usage
741
self.outf.write(self.get_help_text(verbose=False))
615
if 'usage' in opts: # e.g. bzr add --usage
616
sys.stdout.write(self.get_help_text(verbose=False))
743
618
trace.set_verbosity_level(option._verbosity_level)
744
619
if 'verbose' in self.supported_std_options:
745
620
opts['verbose'] = trace.is_verbose()
746
elif 'verbose' in opts:
621
elif opts.has_key('verbose'):
747
622
del opts['verbose']
748
623
if 'quiet' in self.supported_std_options:
749
624
opts['quiet'] = trace.is_quiet()
750
elif 'quiet' in opts:
625
elif opts.has_key('quiet'):
751
626
del opts['quiet']
752
628
# mix arguments and options into one dictionary
753
629
cmdargs = _match_argform(self.name(), self.takes_args, args)
758
634
all_cmd_args = cmdargs.copy()
759
635
all_cmd_args.update(cmdopts)
762
return self.run(**all_cmd_args)
764
# reset it, so that other commands run in the same process won't
765
# inherit state. Before we reset it, log any activity, so that it
766
# gets properly tracked.
767
ui.ui_factory.log_transport_activity(
768
display=('bytes' in debug.debug_flags))
769
trace.set_verbosity_level(0)
771
def _setup_run(self):
772
"""Wrap the defined run method on self with a cleanup.
774
This is called by __init__ to make the Command be able to be run
775
by just calling run(), as it could be before cleanups were added.
777
If a different form of cleanups are in use by your Command subclass,
778
you can override this method.
782
def run(*args, **kwargs):
783
for hook in Command.hooks['pre_command']:
786
with cleanup.ExitStack() as self._exit_stack:
787
return class_run(*args, **kwargs)
789
for hook in Command.hooks['post_command']:
639
return self.run_direct(**all_cmd_args)
641
def run_direct(self, *args, **kwargs):
642
"""Call run directly with objects (without parsing an argv list)."""
643
return self._operation.run_simple(*args, **kwargs)
794
646
"""Actually run the command.
799
651
Return 0 or None if the command was successful, or a non-zero
800
652
shell error code if not. It's OK for this method to allow
801
653
an exception to raise up.
803
This method is automatically wrapped by Command.__init__ with a
804
ExitStack, stored as self._exit_stack. This can be used
805
via self.add_cleanup to perform automatic cleanups at the end of
808
The argument for run are assembled by introspection. So for instance,
809
if your command takes an argument files, you would declare::
811
def run(self, files=None):
814
655
raise NotImplementedError('no implementation of command %r'
853
686
These are all empty initially, because by default nothing should get
856
Hooks.__init__(self, "breezy.commands", "Command.hooks")
690
self.create_hook(HookPoint('extend_command',
859
691
"Called after creating a command object to allow modifications "
860
692
"such as adding or removing options, docs etc. Called with the "
861
"new breezy.commands.Command object.", (1, 13))
693
"new bzrlib.commands.Command object.", (1, 13), None))
694
self.create_hook(HookPoint('get_command',
864
695
"Called when creating a single command. Called with "
865
696
"(cmd_or_None, command_name). get_command should either return "
866
697
"the cmd_or_None parameter, or a replacement Command object that "
867
698
"should be used for the command. Note that the Command.hooks "
868
699
"hooks are core infrastructure. Many users will prefer to use "
869
"breezy.commands.register_command or plugin_cmds.register_lazy.",
872
'get_missing_command',
700
"bzrlib.commands.register_command or plugin_cmds.register_lazy.",
702
self.create_hook(HookPoint('get_missing_command',
873
703
"Called when creating a single command if no command could be "
874
704
"found. Called with (command_name). get_missing_command should "
875
705
"either return None, or a Command object to be used for the "
706
"command.", (1, 17), None))
707
self.create_hook(HookPoint('list_commands',
879
708
"Called when enumerating commands. Called with a set of "
880
709
"cmd_name strings for all the commands found so far. This set "
881
710
" is safe to mutate - e.g. to remove a command. "
882
711
"list_commands should return the updated set of command names.",
886
"Called prior to executing a command. Called with the command "
890
"Called after executing a command. Called with the command "
894
714
Command.hooks = CommandHooks()
903
723
they take, and which commands will accept them.
905
725
# TODO: make it a method of the Command?
906
parser = option.get_optparser(
907
[v for k, v in sorted(command.options().items())])
726
parser = option.get_optparser(command.options())
908
727
if alias_argv is not None:
909
728
args = alias_argv + argv
913
# python 2's optparse raises this exception if a non-ascii
914
# option name is given. See http://bugs.python.org/issue2931
916
options, args = parser.parse_args(args)
917
except UnicodeEncodeError:
918
raise errors.BzrCommandError(
919
gettext('Only ASCII permitted in option names'))
921
opts = dict((k, v) for k, v in options.__dict__.items() if
922
v is not option.OptionParser.DEFAULT_VALUE)
732
options, args = parser.parse_args(args)
733
opts = dict([(k, v) for k, v in options.__dict__.iteritems() if
734
v is not option.OptionParser.DEFAULT_VALUE])
923
735
return args, opts
940
752
argdict[argname + '_list'] = None
941
753
elif ap[-1] == '+':
943
raise errors.BzrCommandError(gettext(
944
"command {0!r} needs one or more {1}").format(
945
cmd, argname.upper()))
755
raise errors.BzrCommandError("command %r needs one or more %s"
756
% (cmd, argname.upper()))
947
758
argdict[argname + '_list'] = args[:]
949
elif ap[-1] == '$': # all but one
760
elif ap[-1] == '$': # all but one
950
761
if len(args) < 2:
951
raise errors.BzrCommandError(
952
gettext("command {0!r} needs one or more {1}").format(
953
cmd, argname.upper()))
762
raise errors.BzrCommandError("command %r needs one or more %s"
763
% (cmd, argname.upper()))
954
764
argdict[argname + '_list'] = args[:-1]
957
767
# just a plain arg
960
raise errors.BzrCommandError(
961
gettext("command {0!r} requires argument {1}").format(
962
cmd, argname.upper()))
770
raise errors.BzrCommandError("command %r requires argument %s"
771
% (cmd, argname.upper()))
964
773
argdict[argname] = args.pop(0)
967
raise errors.BzrCommandError(gettext(
968
"extra argument to command {0}: {1}").format(
776
raise errors.BzrCommandError("extra argument to command %s: %s"
974
def apply_coveraged(the_callable, *args, **kwargs):
976
cov = coverage.Coverage()
978
config_file = cov.config.config_file
979
except AttributeError: # older versions of coverage
980
config_file = cov.config_file
981
os.environ['COVERAGE_PROCESS_START'] = config_file
781
def apply_coveraged(dirname, the_callable, *args, **kwargs):
782
# Cannot use "import trace", as that would import bzrlib.trace instead of
783
# the standard library's trace.
784
trace = __import__('trace')
786
tracer = trace.Trace(count=1, trace=0)
787
sys.settrace(tracer.globaltrace)
788
threading.settrace(tracer.globaltrace)
984
791
return exception_to_return_code(the_callable, *args, **kwargs)
794
results = tracer.results()
795
results.write_results(show_missing=1, summary=False,
990
799
def apply_profiled(the_callable, *args, **kwargs):
1022
831
return the_callable(*args, **kwargs)
1023
except (KeyboardInterrupt, Exception):
832
except (KeyboardInterrupt, Exception), e:
1024
833
# used to handle AssertionError and KeyboardInterrupt
1025
834
# specially here, but hopefully they're handled ok by the logger now
1026
835
exc_info = sys.exc_info()
1027
836
exitcode = trace.report_exception(exc_info, sys.stderr)
1028
if os.environ.get('BRZ_PDB'):
1029
print('**** entering debugger')
837
if os.environ.get('BZR_PDB'):
838
print '**** entering debugger'
1031
pdb.post_mortem(exc_info[2])
841
if sys.version_info[:2] < (2, 6):
843
# pdb.post_mortem(tb)
844
# but because pdb.post_mortem gives bad results for tracebacks
845
# from inside generators, we do it manually.
846
# (http://bugs.python.org/issue4150, fixed in Python 2.6)
848
# Setup pdb on the traceback
851
p.setup(tb.tb_frame, tb)
852
# Point the debugger at the deepest frame of the stack
853
p.curindex = len(p.stack) - 1
854
p.curframe = p.stack[p.curindex][0]
855
# Start the pdb prompt.
856
p.print_stack_entry(p.stack[p.curindex])
1035
864
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
1036
from breezy.lsprof import profile
1037
ret, stats = profile(exception_to_return_code, the_callable,
865
from bzrlib.lsprof import profile
866
ret, stats = profile(exception_to_return_code, the_callable, *args, **kwargs)
1040
868
if filename is None:
1043
871
stats.save(filename)
1044
trace.note(gettext('Profile data written to "%s".'), filename)
872
trace.note('Profile data written to "%s".', filename)
876
def shlex_split_unicode(unsplit):
878
return [u.decode('utf-8') for u in shlex.split(unsplit.encode('utf-8'))]
1048
881
def get_alias(cmd, config=None):
1049
882
"""Return an expanded alias, or None if no alias exists.
1056
889
If it is unspecified, the global config will be used.
1058
891
if config is None:
1059
import breezy.config
1060
config = breezy.config.GlobalConfig()
893
config = bzrlib.config.GlobalConfig()
1061
894
alias = config.get_alias(cmd)
1063
return cmdline.split(alias)
896
return shlex_split_unicode(alias)
1067
def run_bzr(argv, load_plugins=load_plugins, disable_plugins=disable_plugins):
1068
901
"""Execute a command.
1070
:param argv: The command-line arguments, without the program name from
1071
argv[0] These should already be decoded. All library/test code calling
1072
run_bzr should be passing valid strings (don't need decoding).
1073
:param load_plugins: What function to call when triggering plugin loading.
1074
This function should take no arguments and cause all plugins to be
1076
:param disable_plugins: What function to call when disabling plugin
1077
loading. This function should take no arguments and cause all plugin
1078
loading to be prohibited (so that code paths in your application that
1079
know about some plugins possibly being present will fail to import
1080
those plugins even if they are installed.)
1081
:return: Returns a command exit code or raises an exception.
904
The command-line arguments, without the program name from argv[0]
905
These should already be decoded. All library/test code calling
906
run_bzr should be passing valid strings (don't need decoding).
908
Returns a command status or raises an exception.
1083
910
Special master options: these must come before the command because
1084
911
they control how the command is interpreted.
1100
927
Run under the Python lsprof profiler.
1103
Generate code coverage report
930
Generate line coverage report in the specified directory.
1106
Specify the number of processes that can be run concurrently
933
Specify the number of processes that can be run concurrently (selftest).
1109
trace.mutter("breezy version: " + breezy.__version__)
1110
argv = _specified_or_unicode_argv(argv)
1111
trace.mutter("brz arguments: %r", argv)
935
trace.mutter("bazaar version: " + bzrlib.__version__)
937
trace.mutter("bzr arguments: %r", argv)
1113
opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = \
1114
opt_coverage = opt_no_l10n = opt_no_aliases = False
1115
opt_lsprof_file = None
939
opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = \
940
opt_no_aliases = False
941
opt_lsprof_file = opt_coverage_dir = None
1117
943
# --no-plugins is handled specially at a very early stage. We need
1118
944
# to load plugins before doing other command parsing so that they
1135
960
opt_no_plugins = True
1136
961
elif a == '--no-aliases':
1137
962
opt_no_aliases = True
1138
elif a == '--no-l10n':
1140
963
elif a == '--builtin':
1141
964
opt_builtin = True
1142
965
elif a == '--concurrency':
1143
os.environ['BRZ_CONCURRENCY'] = argv[i + 1]
966
os.environ['BZR_CONCURRENCY'] = argv[i + 1]
1145
968
elif a == '--coverage':
1147
elif a == '--profile-imports':
1148
pass # already handled in startup script Bug #588277
969
opt_coverage_dir = argv[i + 1]
1149
971
elif a.startswith('-D'):
1150
972
debug.debug_flags.add(a[2:])
1151
elif a.startswith('-O'):
1152
override_config.append(a[2:])
1154
974
argv_copy.append(a)
1157
cmdline_overrides = breezy.get_global_state().cmdline_overrides
1158
cmdline_overrides._from_cmdline(override_config)
1160
977
debug.set_debug_flags_from_config()
981
from bzrlib.builtins import cmd_help
982
cmd_help().run_argv_aliases([])
985
if argv[0] == '--version':
986
from bzrlib.builtins import cmd_version
987
cmd_version().run_argv_aliases([])
1162
990
if not opt_no_plugins:
991
from bzrlib.plugin import load_plugins
994
from bzrlib.plugin import disable_plugins
1165
995
disable_plugins()
1169
get_cmd_object('help').run_argv_aliases([])
1172
if argv[0] == '--version':
1173
get_cmd_object('version').run_argv_aliases([])
1176
997
alias_argv = None
1178
999
if not opt_no_aliases:
1179
1000
alias_argv = get_alias(argv[0])
1002
user_encoding = osutils.get_user_encoding()
1003
alias_argv = [a.decode(user_encoding) for a in alias_argv]
1181
1004
argv[0] = alias_argv.pop(0)
1183
1006
cmd = argv.pop(0)
1007
# We want only 'ascii' command names, but the user may have typed
1008
# in a Unicode name. In that case, they should just get a
1009
# 'command not found' error later.
1184
1011
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
1186
cmd_obj.l10n = False
1187
1012
run = cmd_obj.run_argv_aliases
1188
1013
run_argv = [argv, alias_argv]
1243
1066
if _list_bzr_commands in Command.hooks["list_commands"]:
1245
1068
Command.hooks.install_named_hook("list_commands", _list_bzr_commands,
1247
1070
Command.hooks.install_named_hook("get_command", _get_bzr_command,
1249
1072
Command.hooks.install_named_hook("get_command", _get_plugin_command,
1250
"bzr plugin commands")
1073
"bzr plugin commands")
1251
1074
Command.hooks.install_named_hook("get_command", _get_external_command,
1252
"bzr external command lookup")
1253
Command.hooks.install_named_hook("get_missing_command",
1254
_try_plugin_provider,
1255
"bzr plugin-provider-db check")
1075
"bzr external command lookup")
1076
Command.hooks.install_named_hook("get_missing_command", _try_plugin_provider,
1077
"bzr plugin-provider-db check")
1258
1081
def _specified_or_unicode_argv(argv):
1260
1083
# the process arguments in a unicode-safe way.
1261
1084
if argv is None:
1262
1085
return osutils.get_unicode_argv()
1265
# ensure all arguments are unicode strings
1267
if not isinstance(a, string_types):
1268
raise ValueError('not native str or unicode: %r' % (a,))
1269
if isinstance(a, bytes):
1270
# For Python 2 only allow ascii native strings
1271
a = a.decode('ascii')
1273
except (ValueError, UnicodeDecodeError):
1274
raise errors.BzrError("argv should be list of unicode strings.")
1089
# ensure all arguments are unicode strings
1091
if isinstance(a, unicode):
1094
new_argv.append(a.decode('ascii'))
1095
except UnicodeDecodeError:
1096
raise errors.BzrError("argv should be list of unicode strings.")
1278
1100
def main(argv=None):
1279
1101
"""Main entry point of command-line interface.
1281
Typically `breezy.initialize` should be called first.
1103
Typically `bzrlib.initialize` should be called first.
1283
1105
:param argv: list of unicode command-line arguments similar to sys.argv.
1284
1106
argv[0] is script name usually, it will be ignored.
1285
1107
Don't pass here sys.argv because this list contains plain strings
1286
1108
and not unicode; pass None instead.
1288
:return: exit code of brz command.
1110
:return: exit code of bzr command.
1290
if argv is not None:
1292
_register_builtin_commands()
1112
argv = _specified_or_unicode_argv(argv)
1293
1113
ret = run_bzr_catch_errors(argv)
1114
bzrlib.ui.ui_factory.log_transport_activity(
1115
display=('bytes' in debug.debug_flags))
1294
1116
trace.mutter("return code %d", ret)
1352
1173
class Provider(object):
1353
"""Generic class to be overriden by plugins"""
1174
'''Generic class to be overriden by plugins'''
1355
1176
def plugin_for_command(self, cmd_name):
1356
"""Takes a command and returns the information for that plugin
1177
'''Takes a command and returns the information for that plugin
1358
1179
:return: A dictionary with all the available information
1359
for the requested plugin
1180
for the requested plugin
1361
1182
raise NotImplementedError
1364
1185
class ProvidersRegistry(registry.Registry):
1365
"""This registry exists to allow other providers to exist"""
1186
'''This registry exists to allow other providers to exist'''
1367
1188
def __iter__(self):
1368
for key, provider in self.items():
1189
for key, provider in self.iteritems():
1372
1192
command_providers_registry = ProvidersRegistry()