104
94
registry.Registry.register(self, k_unsquished, cmd,
105
95
override_existing=decorate, info=info)
107
trace.warning('Two plugins defined the same command: %r' % k)
108
trace.warning('Not loading the one in %r' %
109
sys.modules[cmd.__module__])
110
trace.warning('Previously this command was registered from %r' %
111
sys.modules[previous.__module__])
97
trace.log_error('Two plugins defined the same command: %r' % k)
98
trace.log_error('Not loading the one in %r' %
99
sys.modules[cmd.__module__])
100
trace.log_error('Previously this command was registered from %r' %
101
sys.modules[previous.__module__])
114
104
def register_lazy(self, command_name, aliases, module_name):
142
132
def _builtin_commands():
143
133
import bzrlib.builtins
144
return _scan_module_for_commands(bzrlib.builtins)
147
def _scan_module_for_commands(module):
149
for name, obj in module.__dict__.iteritems():
135
builtins = bzrlib.builtins.__dict__
136
for name in builtins:
150
137
if name.startswith("cmd_"):
151
138
real_name = _unsquish_command_name(name)
139
r[real_name] = builtins[name]
156
def _list_bzr_commands(names):
157
"""Find commands from bzr's core and plugins."""
158
# to eliminate duplicates
159
names.update(builtin_command_names())
160
names.update(plugin_command_names())
164
def all_command_names():
165
"""Return a set of all command names."""
167
for hook in Command.hooks['list_commands']:
170
raise AssertionError(
171
'hook %s returned None' % Command.hooks.get_hook_name(hook))
175
143
def builtin_command_names():
176
"""Return list of builtin command names.
178
Use of all_command_names() is encouraged rather than builtin_command_names
179
and/or plugin_command_names.
144
"""Return list of builtin command names."""
181
145
return _builtin_commands().keys()
184
148
def plugin_command_names():
185
"""Returns command names from commands registered by plugins."""
186
149
return plugin_cmds.keys()
152
def _get_cmd_dict(plugins_override=True):
153
"""Return name->class mapping for all commands."""
154
d = _builtin_commands()
156
d.update(plugin_cmds.iteritems())
160
def get_all_cmds(plugins_override=True):
161
"""Return canonical name and class for all registered commands."""
162
for k, v in _get_cmd_dict(plugins_override=plugins_override).iteritems():
189
166
def get_cmd_object(cmd_name, plugins_override=True):
190
"""Return the command object for a command.
167
"""Return the canonical name and command class for a command.
193
170
If true, plugin commands can override builtins.
201
178
def _get_cmd_object(cmd_name, plugins_override=True):
202
"""Get a command object.
179
"""Worker for get_cmd_object which raises KeyError rather than BzrCommandError."""
180
from bzrlib.externalcommand import ExternalCommand
204
:param cmd_name: The name of the command.
205
:param plugins_override: Allow plugins to override builtins.
206
:return: A Command object instance
207
:raises KeyError: If no command is found.
209
182
# We want only 'ascii' command names, but the user may have typed
210
183
# in a Unicode name. In that case, they should just get a
211
184
# 'command not found' error later.
212
185
# In the future, we may actually support Unicode command names.
215
for hook in Command.hooks['get_command']:
216
cmd = hook(cmd, cmd_name)
217
if cmd is not None and not plugins_override and not cmd.plugin_name():
218
# We've found a non-plugin command, don't permit it to be
222
for hook in Command.hooks['get_missing_command']:
229
# Allow plugins to extend commands
230
for hook in Command.hooks['extend_command']:
235
def _try_plugin_provider(cmd_name):
236
"""Probe for a plugin provider having cmd_name."""
238
plugin_metadata, provider = probe_for_provider(cmd_name)
239
raise errors.CommandAvailableInPlugin(cmd_name,
240
plugin_metadata, provider)
241
except errors.NoPluginAvailable:
245
def probe_for_provider(cmd_name):
246
"""Look for a provider for cmd_name.
248
:param cmd_name: The command name.
249
:return: plugin_metadata, provider for getting cmd_name.
250
:raises NoPluginAvailable: When no provider can supply the plugin.
252
# look for providers that provide this command but aren't installed
253
for provider in command_providers_registry:
187
# first look up this command under the specified name
255
return provider.plugin_for_command(cmd_name), provider
256
except errors.NoPluginAvailable:
190
return plugin_cmds.get(cmd_name)()
258
raise errors.NoPluginAvailable(cmd_name)
261
def _get_bzr_command(cmd_or_None, cmd_name):
262
"""Get a command from bzr's core."""
263
cmds = _builtin_commands()
193
cmds = _get_cmd_dict(plugins_override=False)
265
195
return cmds[cmd_name]()
199
for key in plugin_cmds.keys():
200
info = plugin_cmds.get_info(key)
201
if cmd_name in info.aliases:
202
return plugin_cmds.get(key)()
268
203
# look for any command which claims this as an alias
269
204
for real_cmd_name, cmd_class in cmds.iteritems():
270
205
if cmd_name in cmd_class.aliases:
271
206
return cmd_class()
275
def _get_external_command(cmd_or_None, cmd_name):
276
"""Lookup a command that is a shell script."""
277
# Only do external command lookups when no command is found so far.
278
if cmd_or_None is not None:
280
from bzrlib.externalcommand import ExternalCommand
281
208
cmd_obj = ExternalCommand.find_command(cmd_name)
212
# look for plugins that provide this command but aren't installed
213
for provider in command_providers_registry:
215
plugin_metadata = provider.plugin_for_command(cmd_name)
216
except errors.NoPluginAvailable:
219
raise errors.CommandAvailableInPlugin(cmd_name,
220
plugin_metadata, provider)
286
def _get_plugin_command(cmd_or_None, cmd_name):
287
"""Get a command from bzr's plugins."""
289
return plugin_cmds.get(cmd_name)()
292
for key in plugin_cmds.keys():
293
info = plugin_cmds.get_info(key)
294
if cmd_name in info.aliases:
295
return plugin_cmds.get(key)()
299
225
class Command(object):
361
286
encoding_type = 'strict'
365
290
def __init__(self):
366
291
"""Construct an instance of this command."""
367
292
if self.__doc__ == Command.__doc__:
368
293
warn("No help message set for %r" % self)
369
294
# List of standard options directly supported
370
295
self.supported_std_options = []
371
self._operation = cleanup.OperationWithCleanups(self.run)
373
def add_cleanup(self, cleanup_func, *args, **kwargs):
374
"""Register a function to call after self.run returns or raises.
376
Functions will be called in LIFO order.
378
self._operation.add_cleanup(cleanup_func, *args, **kwargs)
380
def cleanup_now(self):
381
"""Execute and empty pending cleanup functions immediately.
383
After cleanup_now all registered cleanups are forgotten. add_cleanup
384
may be called again after cleanup_now; these cleanups will be called
385
after self.run returns or raises (or when cleanup_now is next called).
387
This is useful for releasing expensive or contentious resources (such
388
as write locks) before doing further work that does not require those
389
resources (such as writing results to self.outf).
391
self._operation.cleanup_now()
393
@deprecated_method(deprecated_in((2, 1, 0)))
394
297
def _maybe_expand_globs(self, file_list):
395
298
"""Glob expand file_list if the platform does not do that itself.
397
Not used anymore, now that the bzr command-line parser globs on
400
300
:return: A possibly empty list of unicode paths.
402
302
Introduced in bzrlib 0.18.
306
if sys.platform == 'win32':
307
file_list = win32utils.glob_expand(file_list)
308
return list(file_list)
406
310
def _usage(self):
407
311
"""Return single-line grammar for this command.
424
328
def get_help_text(self, additional_see_also=None, plain=True,
425
see_also_as_links=False, verbose=True):
329
see_also_as_links=False):
426
330
"""Return a text string with help for this command.
428
332
:param additional_see_also: Additional help topics to be
429
333
cross-referenced.
430
334
:param plain: if False, raw help (reStructuredText) is
431
335
returned instead of plain text.
432
336
:param see_also_as_links: if True, convert items in 'See also'
433
337
list to internal links (used by bzr_man rstx generator)
434
:param verbose: if True, display the full help, otherwise
435
leave out the descriptive sections and just display
436
usage help (e.g. Purpose, Usage, Options) with a
437
message explaining how to obtain full help.
439
339
doc = self.help()
441
341
raise NotImplementedError("sorry, no detailed help yet for %r" % self.name())
443
343
# Extract the summary (purpose) and sections out from the text
444
purpose,sections,order = self._get_help_parts(doc)
344
purpose,sections = self._get_help_parts(doc)
446
346
# If a custom usage section was provided, use it
447
347
if sections.has_key('Usage'):
461
361
# Add the options
463
# XXX: optparse implicitly rewraps the help, and not always perfectly,
464
# so we get <https://bugs.launchpad.net/bzr/+bug/249908>. -- mbp
466
362
options = option.get_optparser(self.options()).format_option_help()
467
# XXX: According to the spec, ReST option lists actually don't support
468
# options like --1.9 so that causes syntax errors (in Sphinx at least).
469
# As that pattern always appears in the commands that break, we trap
470
# on that and then format that block of 'format' options as a literal
472
if not plain and options.find(' --1.9 ') != -1:
473
options = options.replace(' format:\n', ' format::\n\n', 1)
474
363
if options.startswith('Options:'):
475
364
result += ':' + options
476
365
elif options.startswith('options:'):
480
369
result += options
484
# Add the description, indenting it 2 spaces
485
# to match the indentation of the options
486
if sections.has_key(None):
487
text = sections.pop(None)
488
text = '\n '.join(text.splitlines())
489
result += ':%s:\n %s\n\n' % ('Description',text)
372
# Add the description, indenting it 2 spaces
373
# to match the indentation of the options
374
if sections.has_key(None):
375
text = sections.pop(None)
376
text = '\n '.join(text.splitlines())
377
result += ':%s:\n %s\n\n' % ('Description',text)
491
# Add the custom sections (e.g. Examples). Note that there's no need
492
# to indent these as they must be indented already in the source.
495
if sections.has_key(label):
496
result += ':%s:\n%s\n' % (label,sections[label])
499
result += ("See bzr help %s for more details and examples.\n\n"
379
# Add the custom sections (e.g. Examples). Note that there's no need
380
# to indent these as they must be indented already in the source.
382
labels = sorted(sections.keys())
384
result += ':%s:\n%s\n\n' % (label,sections[label])
502
386
# Add the aliases, source (plug-in) and see also links, if any
533
416
def _get_help_parts(text):
534
417
"""Split help text into a summary and named sections.
536
:return: (summary,sections,order) where summary is the top line and
419
:return: (summary,sections) where summary is the top line and
537
420
sections is a dictionary of the rest indexed by section name.
538
order is the order the section appear in the text.
539
421
A section starts with a heading line of the form ":xxx:".
540
422
Indented text on following lines is the section value.
541
423
All text found outside a named section is assigned to the
542
424
default section which is given the key of None.
544
def save_section(sections, order, label, section):
426
def save_section(sections, label, section):
545
427
if len(section) > 0:
546
428
if sections.has_key(label):
547
429
sections[label] += '\n' + section
550
431
sections[label] = section
552
433
lines = text.rstrip().splitlines()
553
434
summary = lines.pop(0)
556
436
label,section = None,''
557
437
for line in lines:
558
438
if line.startswith(':') and line.endswith(':') and len(line) > 2:
559
save_section(sections, order, label, section)
439
save_section(sections, label, section)
560
440
label,section = line[1:-1],''
561
441
elif (label is not None) and len(line) > 1 and not line[0].isspace():
562
save_section(sections, order, label, section)
442
save_section(sections, label, section)
563
443
label,section = None,line
565
445
if len(section) > 0:
566
446
section += '\n' + line
569
save_section(sections, order, label, section)
570
return summary, sections, order
449
save_section(sections, label, section)
450
return summary, sections
572
452
def get_help_topic(self):
573
453
"""Return the commands help topic - its name."""
603
483
def _setup_outf(self):
604
484
"""Return a file linked to stdout, which has proper encoding."""
605
self.outf = ui.ui_factory.make_output_stream(
606
encoding_type=self.encoding_type)
485
# Originally I was using self.stdout, but that looks
486
# *way* too much like sys.stdout
487
if self.encoding_type == 'exact':
488
# force sys.stdout to be binary stream on win32
489
if sys.platform == 'win32':
490
fileno = getattr(sys.stdout, 'fileno', None)
493
msvcrt.setmode(fileno(), os.O_BINARY)
494
self.outf = sys.stdout
497
output_encoding = osutils.get_terminal_encoding()
499
self.outf = codecs.getwriter(output_encoding)(sys.stdout,
500
errors=self.encoding_type)
501
# For whatever reason codecs.getwriter() does not advertise its encoding
502
# it just returns the encoding of the wrapped file, which is completely
503
# bogus. So set the attribute, so we can find the correct encoding later.
504
self.outf.encoding = output_encoding
608
506
def run_argv_aliases(self, argv, alias_argv=None):
609
507
"""Parse the command line and run with extra aliases in alias_argv."""
509
warn("Passing None for [] is deprecated from bzrlib 0.10",
510
DeprecationWarning, stacklevel=2)
610
512
args, opts = parse_args(self, argv, alias_argv)
612
514
# Process the standard options
613
515
if 'help' in opts: # e.g. bzr add --help
614
516
sys.stdout.write(self.get_help_text())
616
if 'usage' in opts: # e.g. bzr add --usage
617
sys.stdout.write(self.get_help_text(verbose=False))
619
518
trace.set_verbosity_level(option._verbosity_level)
620
519
if 'verbose' in self.supported_std_options:
621
520
opts['verbose'] = trace.is_verbose()
681
class CommandHooks(Hooks):
682
"""Hooks related to Command object creation/enumeration."""
685
"""Create the default hooks.
687
These are all empty initially, because by default nothing should get
691
self.create_hook(HookPoint('extend_command',
692
"Called after creating a command object to allow modifications "
693
"such as adding or removing options, docs etc. Called with the "
694
"new bzrlib.commands.Command object.", (1, 13), None))
695
self.create_hook(HookPoint('get_command',
696
"Called when creating a single command. Called with "
697
"(cmd_or_None, command_name). get_command should either return "
698
"the cmd_or_None parameter, or a replacement Command object that "
699
"should be used for the command. Note that the Command.hooks "
700
"hooks are core infrastructure. Many users will prefer to use "
701
"bzrlib.commands.register_command or plugin_cmds.register_lazy.",
703
self.create_hook(HookPoint('get_missing_command',
704
"Called when creating a single command if no command could be "
705
"found. Called with (command_name). get_missing_command should "
706
"either return None, or a Command object to be used for the "
707
"command.", (1, 17), None))
708
self.create_hook(HookPoint('list_commands',
709
"Called when enumerating commands. Called with a set of "
710
"cmd_name strings for all the commands found so far. This set "
711
" is safe to mutate - e.g. to remove a command. "
712
"list_commands should return the updated set of command names.",
715
Command.hooks = CommandHooks()
718
576
def parse_args(command, argv, alias_argv=None):
719
577
"""Parse command line.
721
579
Arguments and options are parsed at this level before being passed
722
580
down to specific command handlers. This routine knows, from a
723
581
lookup table, something about the available options, what optargs
787
645
tracer = trace.Trace(count=1, trace=0)
788
646
sys.settrace(tracer.globaltrace)
789
threading.settrace(tracer.globaltrace)
792
return exception_to_return_code(the_callable, *args, **kwargs)
795
results = tracer.results()
796
results.write_results(show_missing=1, summary=False,
648
ret = the_callable(*args, **kwargs)
651
results = tracer.results()
652
results.write_results(show_missing=1, summary=False,
800
656
def apply_profiled(the_callable, *args, **kwargs):
821
676
os.remove(pfname)
824
def exception_to_return_code(the_callable, *args, **kwargs):
825
"""UI level helper for profiling and coverage.
827
This transforms exceptions into a return value of 3. As such its only
828
relevant to the UI layer, and should never be called where catching
829
exceptions may be desirable.
832
return the_callable(*args, **kwargs)
833
except (KeyboardInterrupt, Exception), e:
834
# used to handle AssertionError and KeyboardInterrupt
835
# specially here, but hopefully they're handled ok by the logger now
836
exc_info = sys.exc_info()
837
exitcode = trace.report_exception(exc_info, sys.stderr)
838
if os.environ.get('BZR_PDB'):
839
print '**** entering debugger'
842
if sys.version_info[:2] < (2, 6):
844
# pdb.post_mortem(tb)
845
# but because pdb.post_mortem gives bad results for tracebacks
846
# from inside generators, we do it manually.
847
# (http://bugs.python.org/issue4150, fixed in Python 2.6)
849
# Setup pdb on the traceback
852
p.setup(tb.tb_frame, tb)
853
# Point the debugger at the deepest frame of the stack
854
p.curindex = len(p.stack) - 1
855
p.curframe = p.stack[p.curindex][0]
856
# Start the pdb prompt.
857
p.print_stack_entry(p.stack[p.curindex])
865
679
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
866
680
from bzrlib.lsprof import profile
867
ret, stats = profile(exception_to_return_code, the_callable, *args, **kwargs)
681
ret, stats = profile(the_callable, *args, **kwargs)
869
683
if filename is None:
1032
837
ret = apply_coveraged(opt_coverage_dir, run, *run_argv)
1034
839
ret = run(*run_argv)
840
if 'memory' in debug.debug_flags:
841
trace.debug_memory('Process status after command:', short=False)
1037
844
# reset, in case we may do other commands later within the same
1038
845
# process. Commands that want to execute sub-commands must propagate
1039
846
# --verbose in their own way.
1040
if 'memory' in debug.debug_flags:
1041
trace.debug_memory('Process status after command:', short=False)
1042
847
option._verbosity_level = saved_verbosity_level
1045
849
def display_command(func):
1046
850
"""Decorator that suppresses pipe/interrupt errors."""
1047
851
def ignore_pipe(*args, **kwargs):
1062
866
return ignore_pipe
1065
def install_bzr_command_hooks():
1066
"""Install the hooks to supply bzr's own commands."""
1067
if _list_bzr_commands in Command.hooks["list_commands"]:
1069
Command.hooks.install_named_hook("list_commands", _list_bzr_commands,
1071
Command.hooks.install_named_hook("get_command", _get_bzr_command,
1073
Command.hooks.install_named_hook("get_command", _get_plugin_command,
1074
"bzr plugin commands")
1075
Command.hooks.install_named_hook("get_command", _get_external_command,
1076
"bzr external command lookup")
1077
Command.hooks.install_named_hook("get_missing_command", _try_plugin_provider,
1078
"bzr plugin-provider-db check")
1081
def main(argv=None):
1082
"""Main entry point of command-line interface.
1084
:param argv: list of unicode command-line arguments similar to sys.argv.
1085
argv[0] is script name usually, it will be ignored.
1086
Don't pass here sys.argv because this list contains plain strings
1087
and not unicode; pass None instead.
1089
:return: exit code of bzr command.
1091
870
import bzrlib.ui
1092
871
bzrlib.ui.ui_factory = bzrlib.ui.make_ui_for_terminal(
1093
872
sys.stdin, sys.stdout, sys.stderr)
1095
874
# Is this a final release version? If so, we should suppress warnings
1096
875
if bzrlib.version_info[3] == 'final':
1097
suppress_deprecation_warnings(override=True)
1099
argv = osutils.get_unicode_argv()
1103
# ensure all arguments are unicode strings
1105
if isinstance(a, unicode):
1108
new_argv.append(a.decode('ascii'))
1109
except UnicodeDecodeError:
1110
raise errors.BzrError("argv should be list of unicode strings.")
876
from bzrlib import symbol_versioning
877
symbol_versioning.suppress_deprecation_warnings(override=False)
879
user_encoding = osutils.get_user_encoding()
880
argv = [a.decode(user_encoding) for a in argv[1:]]
881
except UnicodeDecodeError:
882
raise errors.BzrError(("Parameter '%r' is unsupported by the current "
1112
884
ret = run_bzr_catch_errors(argv)
1113
bzrlib.ui.ui_factory.log_transport_activity(
1114
display=('bytes' in debug.debug_flags))
1115
885
trace.mutter("return code %d", ret)
1116
osutils.report_extension_load_failures()
1120
889
def run_bzr_catch_errors(argv):
1121
"""Run a bzr command with parameters as described by argv.
1123
This function assumed that that UI layer is setup, that symbol deprecations
1124
are already applied, and that unicode decoding has already been performed on argv.
1126
install_bzr_command_hooks()
1127
return exception_to_return_code(run_bzr, argv)
890
# Note: The except clause logic below should be kept in sync with the
891
# profile() routine in lsprof.py.
894
except (KeyboardInterrupt, Exception), e:
895
# used to handle AssertionError and KeyboardInterrupt
896
# specially here, but hopefully they're handled ok by the logger now
897
exc_info = sys.exc_info()
898
exitcode = trace.report_exception(exc_info, sys.stderr)
899
if os.environ.get('BZR_PDB'):
900
print '**** entering debugger'
903
if sys.version_info[:2] < (2, 6):
905
# pdb.post_mortem(tb)
906
# but because pdb.post_mortem gives bad results for tracebacks
907
# from inside generators, we do it manually.
908
# (http://bugs.python.org/issue4150, fixed in Python 2.6)
910
# Setup pdb on the traceback
913
p.setup(tb.tb_frame, tb)
914
# Point the debugger at the deepest frame of the stack
915
p.curindex = len(p.stack) - 1
916
p.curframe = p.stack[p.curindex]
917
# Start the pdb prompt.
918
p.print_stack_entry(p.stack[p.curindex])
1130
926
def run_bzr_catch_user_errors(argv):