94
104
registry.Registry.register(self, k_unsquished, cmd,
95
105
override_existing=decorate, info=info)
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__])
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__])
104
114
def register_lazy(self, command_name, aliases, module_name):
132
142
def _builtin_commands():
133
143
import bzrlib.builtins
144
return _scan_module_for_commands(bzrlib.builtins)
147
def _scan_module_for_commands(module):
135
builtins = bzrlib.builtins.__dict__
136
for name in builtins:
149
for name, obj in module.__dict__.iteritems():
137
150
if name.startswith("cmd_"):
138
151
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))
143
175
def builtin_command_names():
144
"""Return list of 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.
145
181
return _builtin_commands().keys()
148
184
def plugin_command_names():
185
"""Returns command names from commands registered by plugins."""
149
186
return plugin_cmds.keys()
152
def _get_cmd_dict(plugins_override=True):
153
"""Return name->class mapping for all commands."""
189
@deprecated_function(deprecated_in((1, 17, 0)))
190
def get_all_cmds(plugins_override=False):
191
"""Return canonical name and class for most commands.
193
NB: This does not return all commands since the introduction of
194
command hooks, and returning the class is not sufficient to
195
get correctly setup commands, which is why it is deprecated.
197
Use 'all_command_names' + 'get_cmd_object' instead.
154
199
d = _builtin_commands()
155
200
if plugins_override:
156
201
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():
202
for k, v in d.iteritems():
166
206
def get_cmd_object(cmd_name, plugins_override=True):
167
"""Return the canonical name and command class for a command.
207
"""Return the command object for a command.
170
210
If true, plugin commands can override builtins.
178
218
def _get_cmd_object(cmd_name, plugins_override=True):
179
"""Worker for get_cmd_object which raises KeyError rather than BzrCommandError."""
180
from bzrlib.externalcommand import ExternalCommand
219
"""Get a command object.
221
:param cmd_name: The name of the command.
222
:param plugins_override: Allow plugins to override builtins.
223
:return: A Command object instance
224
:raises KeyError: If no command is found.
182
226
# We want only 'ascii' command names, but the user may have typed
183
227
# in a Unicode name. In that case, they should just get a
184
228
# 'command not found' error later.
185
229
# In the future, we may actually support Unicode command names.
187
# first look up this command under the specified name
232
for hook in Command.hooks['get_command']:
233
cmd = hook(cmd, cmd_name)
234
if cmd is not None and not plugins_override and not cmd.plugin_name():
235
# We've found a non-plugin command, don't permit it to be
239
for hook in Command.hooks['get_missing_command']:
246
# Allow plugins to extend commands
247
for hook in Command.hooks['extend_command']:
252
def _try_plugin_provider(cmd_name):
253
"""Probe for a plugin provider having cmd_name."""
255
plugin_metadata, provider = probe_for_provider(cmd_name)
256
raise errors.CommandAvailableInPlugin(cmd_name,
257
plugin_metadata, provider)
258
except errors.NoPluginAvailable:
262
def probe_for_provider(cmd_name):
263
"""Look for a provider for cmd_name.
265
:param cmd_name: The command name.
266
:return: plugin_metadata, provider for getting cmd_name.
267
:raises NoPluginAvailable: When no provider can supply the plugin.
269
# look for providers that provide this command but aren't installed
270
for provider in command_providers_registry:
190
return plugin_cmds.get(cmd_name)()
272
return provider.plugin_for_command(cmd_name), provider
273
except errors.NoPluginAvailable:
193
cmds = _get_cmd_dict(plugins_override=False)
275
raise errors.NoPluginAvailable(cmd_name)
278
def _get_bzr_command(cmd_or_None, cmd_name):
279
"""Get a command from bzr's core."""
280
cmds = _builtin_commands()
195
282
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)()
203
285
# look for any command which claims this as an alias
204
286
for real_cmd_name, cmd_class in cmds.iteritems():
205
287
if cmd_name in cmd_class.aliases:
206
288
return cmd_class()
292
def _get_external_command(cmd_or_None, cmd_name):
293
"""Lookup a command that is a shell script."""
294
# Only do external command lookups when no command is found so far.
295
if cmd_or_None is not None:
297
from bzrlib.externalcommand import ExternalCommand
208
298
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)
303
def _get_plugin_command(cmd_or_None, cmd_name):
304
"""Get a command from bzr's plugins."""
306
return plugin_cmds.get(cmd_name)()
309
for key in plugin_cmds.keys():
310
info = plugin_cmds.get_info(key)
311
if cmd_name in info.aliases:
312
return plugin_cmds.get(key)()
225
316
class Command(object):
286
378
encoding_type = 'strict'
290
382
def __init__(self):
291
383
"""Construct an instance of this command."""
292
384
if self.__doc__ == Command.__doc__:
293
385
warn("No help message set for %r" % self)
294
386
# List of standard options directly supported
295
387
self.supported_std_options = []
388
self._operation = cleanup.OperationWithCleanups(self.run)
390
def add_cleanup(self, cleanup_func, *args, **kwargs):
391
"""Register a function to call after self.run returns or raises.
393
Functions will be called in LIFO order.
395
self._operation.add_cleanup(cleanup_func, *args, **kwargs)
397
def cleanup_now(self):
398
"""Execute and empty pending cleanup functions immediately.
400
After cleanup_now all registered cleanups are forgotten. add_cleanup
401
may be called again after cleanup_now; these cleanups will be called
402
after self.run returns or raises (or when cleanup_now is next called).
404
This is useful for releasing expensive or contentious resources (such
405
as write locks) before doing further work that does not require those
406
resources (such as writing results to self.outf).
408
self._operation.cleanup_now()
410
@deprecated_method(deprecated_in((2, 1, 0)))
297
411
def _maybe_expand_globs(self, file_list):
298
412
"""Glob expand file_list if the platform does not do that itself.
414
Not used anymore, now that the bzr command-line parser globs on
300
417
:return: A possibly empty list of unicode paths.
302
419
Introduced in bzrlib 0.18.
306
if sys.platform == 'win32':
307
file_list = win32utils.glob_expand(file_list)
308
return list(file_list)
310
423
def _usage(self):
311
424
"""Return single-line grammar for this command.
328
441
def get_help_text(self, additional_see_also=None, plain=True,
329
see_also_as_links=False):
442
see_also_as_links=False, verbose=True):
330
443
"""Return a text string with help for this command.
332
445
:param additional_see_also: Additional help topics to be
333
446
cross-referenced.
334
447
:param plain: if False, raw help (reStructuredText) is
335
448
returned instead of plain text.
336
449
:param see_also_as_links: if True, convert items in 'See also'
337
450
list to internal links (used by bzr_man rstx generator)
451
:param verbose: if True, display the full help, otherwise
452
leave out the descriptive sections and just display
453
usage help (e.g. Purpose, Usage, Options) with a
454
message explaining how to obtain full help.
339
456
doc = self.help()
341
458
raise NotImplementedError("sorry, no detailed help yet for %r" % self.name())
343
460
# Extract the summary (purpose) and sections out from the text
344
purpose,sections = self._get_help_parts(doc)
461
purpose,sections,order = self._get_help_parts(doc)
346
463
# If a custom usage section was provided, use it
347
464
if sections.has_key('Usage'):
361
478
# Add the options
480
# XXX: optparse implicitly rewraps the help, and not always perfectly,
481
# so we get <https://bugs.launchpad.net/bzr/+bug/249908>. -- mbp
362
483
options = option.get_optparser(self.options()).format_option_help()
484
# XXX: According to the spec, ReST option lists actually don't support
485
# options like --1.9 so that causes syntax errors (in Sphinx at least).
486
# As that pattern always appears in the commands that break, we trap
487
# on that and then format that block of 'format' options as a literal
489
if not plain and options.find(' --1.9 ') != -1:
490
options = options.replace(' format:\n', ' format::\n\n', 1)
363
491
if options.startswith('Options:'):
364
492
result += ':' + options
365
493
elif options.startswith('options:'):
369
497
result += options
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)
501
# Add the description, indenting it 2 spaces
502
# to match the indentation of the options
503
if sections.has_key(None):
504
text = sections.pop(None)
505
text = '\n '.join(text.splitlines())
506
result += ':%s:\n %s\n\n' % ('Description',text)
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])
508
# Add the custom sections (e.g. Examples). Note that there's no need
509
# to indent these as they must be indented already in the source.
512
if sections.has_key(label):
513
result += ':%s:\n%s\n' % (label,sections[label])
516
result += ("See bzr help %s for more details and examples.\n\n"
386
519
# Add the aliases, source (plug-in) and see also links, if any
416
550
def _get_help_parts(text):
417
551
"""Split help text into a summary and named sections.
419
:return: (summary,sections) where summary is the top line and
553
:return: (summary,sections,order) where summary is the top line and
420
554
sections is a dictionary of the rest indexed by section name.
555
order is the order the section appear in the text.
421
556
A section starts with a heading line of the form ":xxx:".
422
557
Indented text on following lines is the section value.
423
558
All text found outside a named section is assigned to the
424
559
default section which is given the key of None.
426
def save_section(sections, label, section):
561
def save_section(sections, order, label, section):
427
562
if len(section) > 0:
428
563
if sections.has_key(label):
429
564
sections[label] += '\n' + section
431
567
sections[label] = section
433
569
lines = text.rstrip().splitlines()
434
570
summary = lines.pop(0)
436
573
label,section = None,''
437
574
for line in lines:
438
575
if line.startswith(':') and line.endswith(':') and len(line) > 2:
439
save_section(sections, label, section)
576
save_section(sections, order, label, section)
440
577
label,section = line[1:-1],''
441
578
elif (label is not None) and len(line) > 1 and not line[0].isspace():
442
save_section(sections, label, section)
579
save_section(sections, order, label, section)
443
580
label,section = None,line
445
582
if len(section) > 0:
446
583
section += '\n' + line
449
save_section(sections, label, section)
450
return summary, sections
586
save_section(sections, order, label, section)
587
return summary, sections, order
452
589
def get_help_topic(self):
453
590
"""Return the commands help topic - its name."""
483
620
def _setup_outf(self):
484
621
"""Return a file linked to stdout, which has proper encoding."""
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
622
self.outf = ui.ui_factory.make_output_stream(
623
encoding_type=self.encoding_type)
506
625
def run_argv_aliases(self, argv, alias_argv=None):
507
626
"""Parse the command line and run with extra aliases in alias_argv."""
702
class CommandHooks(Hooks):
703
"""Hooks related to Command object creation/enumeration."""
706
"""Create the default hooks.
708
These are all empty initially, because by default nothing should get
712
self.create_hook(HookPoint('extend_command',
713
"Called after creating a command object to allow modifications "
714
"such as adding or removing options, docs etc. Called with the "
715
"new bzrlib.commands.Command object.", (1, 13), None))
716
self.create_hook(HookPoint('get_command',
717
"Called when creating a single command. Called with "
718
"(cmd_or_None, command_name). get_command should either return "
719
"the cmd_or_None parameter, or a replacement Command object that "
720
"should be used for the command. Note that the Command.hooks "
721
"hooks are core infrastructure. Many users will prefer to use "
722
"bzrlib.commands.register_command or plugin_cmds.register_lazy.",
724
self.create_hook(HookPoint('get_missing_command',
725
"Called when creating a single command if no command could be "
726
"found. Called with (command_name). get_missing_command should "
727
"either return None, or a Command object to be used for the "
728
"command.", (1, 17), None))
729
self.create_hook(HookPoint('list_commands',
730
"Called when enumerating commands. Called with a set of "
731
"cmd_name strings for all the commands found so far. This set "
732
" is safe to mutate - e.g. to remove a command. "
733
"list_commands should return the updated set of command names.",
736
Command.hooks = CommandHooks()
576
739
def parse_args(command, argv, alias_argv=None):
577
740
"""Parse command line.
579
742
Arguments and options are parsed at this level before being passed
580
743
down to specific command handlers. This routine knows, from a
581
744
lookup table, something about the available options, what optargs
645
808
tracer = trace.Trace(count=1, trace=0)
646
809
sys.settrace(tracer.globaltrace)
648
ret = the_callable(*args, **kwargs)
651
results = tracer.results()
652
results.write_results(show_missing=1, summary=False,
810
threading.settrace(tracer.globaltrace)
813
return exception_to_return_code(the_callable, *args, **kwargs)
816
results = tracer.results()
817
results.write_results(show_missing=1, summary=False,
656
821
def apply_profiled(the_callable, *args, **kwargs):
676
842
os.remove(pfname)
845
def exception_to_return_code(the_callable, *args, **kwargs):
846
"""UI level helper for profiling and coverage.
848
This transforms exceptions into a return value of 3. As such its only
849
relevant to the UI layer, and should never be called where catching
850
exceptions may be desirable.
853
return the_callable(*args, **kwargs)
854
except (KeyboardInterrupt, Exception), e:
855
# used to handle AssertionError and KeyboardInterrupt
856
# specially here, but hopefully they're handled ok by the logger now
857
exc_info = sys.exc_info()
858
exitcode = trace.report_exception(exc_info, sys.stderr)
859
if os.environ.get('BZR_PDB'):
860
print '**** entering debugger'
863
if sys.version_info[:2] < (2, 6):
865
# pdb.post_mortem(tb)
866
# but because pdb.post_mortem gives bad results for tracebacks
867
# from inside generators, we do it manually.
868
# (http://bugs.python.org/issue4150, fixed in Python 2.6)
870
# Setup pdb on the traceback
873
p.setup(tb.tb_frame, tb)
874
# Point the debugger at the deepest frame of the stack
875
p.curindex = len(p.stack) - 1
876
p.curframe = p.stack[p.curindex][0]
877
# Start the pdb prompt.
878
p.print_stack_entry(p.stack[p.curindex])
679
886
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
680
887
from bzrlib.lsprof import profile
681
ret, stats = profile(the_callable, *args, **kwargs)
888
ret, stats = profile(exception_to_return_code, the_callable, *args, **kwargs)
683
890
if filename is None:
837
1053
ret = apply_coveraged(opt_coverage_dir, run, *run_argv)
839
1055
ret = run(*run_argv)
840
if 'memory' in debug.debug_flags:
841
trace.debug_memory('Process status after command:', short=False)
844
1058
# reset, in case we may do other commands later within the same
845
1059
# process. Commands that want to execute sub-commands must propagate
846
1060
# --verbose in their own way.
1061
if 'memory' in debug.debug_flags:
1062
trace.debug_memory('Process status after command:', short=False)
847
1063
option._verbosity_level = saved_verbosity_level
849
1066
def display_command(func):
850
1067
"""Decorator that suppresses pipe/interrupt errors."""
851
1068
def ignore_pipe(*args, **kwargs):
866
1083
return ignore_pipe
1086
def install_bzr_command_hooks():
1087
"""Install the hooks to supply bzr's own commands."""
1088
if _list_bzr_commands in Command.hooks["list_commands"]:
1090
Command.hooks.install_named_hook("list_commands", _list_bzr_commands,
1092
Command.hooks.install_named_hook("get_command", _get_bzr_command,
1094
Command.hooks.install_named_hook("get_command", _get_plugin_command,
1095
"bzr plugin commands")
1096
Command.hooks.install_named_hook("get_command", _get_external_command,
1097
"bzr external command lookup")
1098
Command.hooks.install_named_hook("get_missing_command", _try_plugin_provider,
1099
"bzr plugin-provider-db check")
1102
def main(argv=None):
1103
"""Main entry point of command-line interface.
1105
:param argv: list of unicode command-line arguments similar to sys.argv.
1106
argv[0] is script name usually, it will be ignored.
1107
Don't pass here sys.argv because this list contains plain strings
1108
and not unicode; pass None instead.
1110
:return: exit code of bzr command.
870
1112
import bzrlib.ui
871
1113
bzrlib.ui.ui_factory = bzrlib.ui.make_ui_for_terminal(
872
1114
sys.stdin, sys.stdout, sys.stderr)
874
1116
# Is this a final release version? If so, we should suppress warnings
875
1117
if bzrlib.version_info[3] == 'final':
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 "
1118
suppress_deprecation_warnings(override=True)
1120
argv = osutils.get_unicode_argv()
1124
# ensure all arguments are unicode strings
1126
if isinstance(a, unicode):
1129
new_argv.append(a.decode('ascii'))
1130
except UnicodeDecodeError:
1131
raise errors.BzrError("argv should be list of unicode strings.")
884
1133
ret = run_bzr_catch_errors(argv)
1134
bzrlib.ui.ui_factory.log_transport_activity(
1135
display=('bytes' in debug.debug_flags))
885
1136
trace.mutter("return code %d", ret)
1137
osutils.report_extension_load_failures()
889
1141
def run_bzr_catch_errors(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])
1142
"""Run a bzr command with parameters as described by argv.
1144
This function assumed that that UI layer is setup, that symbol deprecations
1145
are already applied, and that unicode decoding has already been performed on argv.
1147
install_bzr_command_hooks()
1148
return exception_to_return_code(run_bzr, argv)
926
1151
def run_bzr_catch_user_errors(argv):