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()
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.
152
def _get_cmd_dict(plugins_override=True):
153
"""Return name->class mapping for all commands."""
199
154
d = _builtin_commands()
200
155
if plugins_override:
201
156
d.update(plugin_cmds.iteritems())
202
for k, v in d.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():
206
166
def get_cmd_object(cmd_name, plugins_override=True):
207
"""Return the command object for a command.
167
"""Return the canonical name and command class for a command.
210
170
If true, plugin commands can override builtins.
218
178
def _get_cmd_object(cmd_name, plugins_override=True):
219
"""Get a command object.
179
"""Worker for get_cmd_object which raises KeyError rather than BzrCommandError."""
180
from bzrlib.externalcommand import ExternalCommand
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.
226
182
# We want only 'ascii' command names, but the user may have typed
227
183
# in a Unicode name. In that case, they should just get a
228
184
# 'command not found' error later.
229
185
# In the future, we may actually support Unicode command names.
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:
187
# first look up this command under the specified name
272
return provider.plugin_for_command(cmd_name), provider
273
except errors.NoPluginAvailable:
190
return plugin_cmds.get(cmd_name)()
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()
193
cmds = _get_cmd_dict(plugins_override=False)
282
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)()
285
203
# look for any command which claims this as an alias
286
204
for real_cmd_name, cmd_class in cmds.iteritems():
287
205
if cmd_name in cmd_class.aliases:
288
206
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
298
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)
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)()
316
225
class Command(object):
378
286
encoding_type = 'strict'
382
290
def __init__(self):
383
291
"""Construct an instance of this command."""
384
292
if self.__doc__ == Command.__doc__:
385
293
warn("No help message set for %r" % self)
386
294
# List of standard options directly supported
387
295
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)))
411
297
def _maybe_expand_globs(self, file_list):
412
298
"""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
417
300
:return: A possibly empty list of unicode paths.
419
302
Introduced in bzrlib 0.18.
306
if sys.platform == 'win32':
307
file_list = win32utils.glob_expand(file_list)
308
return list(file_list)
423
310
def _usage(self):
424
311
"""Return single-line grammar for this command.
441
328
def get_help_text(self, additional_see_also=None, plain=True,
442
see_also_as_links=False, verbose=True):
329
see_also_as_links=False):
443
330
"""Return a text string with help for this command.
445
332
:param additional_see_also: Additional help topics to be
446
333
cross-referenced.
447
334
:param plain: if False, raw help (reStructuredText) is
448
335
returned instead of plain text.
449
336
:param see_also_as_links: if True, convert items in 'See also'
450
337
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.
456
339
doc = self.help()
458
341
raise NotImplementedError("sorry, no detailed help yet for %r" % self.name())
460
343
# Extract the summary (purpose) and sections out from the text
461
purpose,sections,order = self._get_help_parts(doc)
344
purpose,sections = self._get_help_parts(doc)
463
346
# If a custom usage section was provided, use it
464
347
if sections.has_key('Usage'):
478
361
# 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
483
362
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)
491
363
if options.startswith('Options:'):
492
364
result += ':' + options
493
365
elif options.startswith('options:'):
497
369
result += options
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)
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)
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"
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])
519
386
# Add the aliases, source (plug-in) and see also links, if any
550
416
def _get_help_parts(text):
551
417
"""Split help text into a summary and named sections.
553
:return: (summary,sections,order) where summary is the top line and
419
:return: (summary,sections) where summary is the top line and
554
420
sections is a dictionary of the rest indexed by section name.
555
order is the order the section appear in the text.
556
421
A section starts with a heading line of the form ":xxx:".
557
422
Indented text on following lines is the section value.
558
423
All text found outside a named section is assigned to the
559
424
default section which is given the key of None.
561
def save_section(sections, order, label, section):
426
def save_section(sections, label, section):
562
427
if len(section) > 0:
563
428
if sections.has_key(label):
564
429
sections[label] += '\n' + section
567
431
sections[label] = section
569
433
lines = text.rstrip().splitlines()
570
434
summary = lines.pop(0)
573
436
label,section = None,''
574
437
for line in lines:
575
438
if line.startswith(':') and line.endswith(':') and len(line) > 2:
576
save_section(sections, order, label, section)
439
save_section(sections, label, section)
577
440
label,section = line[1:-1],''
578
441
elif (label is not None) and len(line) > 1 and not line[0].isspace():
579
save_section(sections, order, label, section)
442
save_section(sections, label, section)
580
443
label,section = None,line
582
445
if len(section) > 0:
583
446
section += '\n' + line
586
save_section(sections, order, label, section)
587
return summary, sections, order
449
save_section(sections, label, section)
450
return summary, sections
589
452
def get_help_topic(self):
590
453
"""Return the commands help topic - its name."""
620
483
def _setup_outf(self):
621
484
"""Return a file linked to stdout, which has proper encoding."""
622
self.outf = ui.ui_factory.make_output_stream(
623
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
625
506
def run_argv_aliases(self, argv, alias_argv=None):
626
507
"""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()
739
576
def parse_args(command, argv, alias_argv=None):
740
577
"""Parse command line.
742
579
Arguments and options are parsed at this level before being passed
743
580
down to specific command handlers. This routine knows, from a
744
581
lookup table, something about the available options, what optargs
808
645
tracer = trace.Trace(count=1, trace=0)
809
646
sys.settrace(tracer.globaltrace)
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,
648
ret = the_callable(*args, **kwargs)
651
results = tracer.results()
652
results.write_results(show_missing=1, summary=False,
821
656
def apply_profiled(the_callable, *args, **kwargs):
842
676
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])
886
679
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
887
680
from bzrlib.lsprof import profile
888
ret, stats = profile(exception_to_return_code, the_callable, *args, **kwargs)
681
ret, stats = profile(the_callable, *args, **kwargs)
890
683
if filename is None:
1053
837
ret = apply_coveraged(opt_coverage_dir, run, *run_argv)
1055
839
ret = run(*run_argv)
840
if 'memory' in debug.debug_flags:
841
trace.debug_memory('Process status after command:', short=False)
1058
844
# reset, in case we may do other commands later within the same
1059
845
# process. Commands that want to execute sub-commands must propagate
1060
846
# --verbose in their own way.
1061
if 'memory' in debug.debug_flags:
1062
trace.debug_memory('Process status after command:', short=False)
1063
847
option._verbosity_level = saved_verbosity_level
1066
849
def display_command(func):
1067
850
"""Decorator that suppresses pipe/interrupt errors."""
1068
851
def ignore_pipe(*args, **kwargs):
1083
866
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.
1112
870
import bzrlib.ui
1113
bzrlib.ui.ui_factory = bzrlib.ui.make_ui_for_terminal(
1114
sys.stdin, sys.stdout, sys.stderr)
871
from bzrlib.ui.text import TextUIFactory
872
bzrlib.ui.ui_factory = TextUIFactory()
1116
874
# Is this a final release version? If so, we should suppress warnings
1117
875
if bzrlib.version_info[3] == 'final':
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.")
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 "
1133
884
ret = run_bzr_catch_errors(argv)
1134
bzrlib.ui.ui_factory.log_transport_activity(
1135
display=('bytes' in debug.debug_flags))
1136
885
trace.mutter("return code %d", ret)
1137
osutils.report_extension_load_failures()
1141
889
def run_bzr_catch_errors(argv):
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)
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
exitcode = trace.report_exception(sys.exc_info(), sys.stderr)
898
if os.environ.get('BZR_PDB'):
899
print '**** entering debugger'
901
pdb.post_mortem(sys.exc_traceback)
1151
905
def run_bzr_catch_user_errors(argv):