51
from bzrlib.symbol_versioning import (
52
from bzrlib import registry
54
from bzrlib.hooks import HookPoint, Hooks
58
55
from bzrlib.option import Option
58
class CommandInfo(object):
59
"""Information about a command."""
61
def __init__(self, aliases):
62
"""The list of aliases for the command."""
63
self.aliases = aliases
66
def from_command(klass, command):
67
"""Factory to construct a CommandInfo from a command."""
68
return klass(command.aliases)
71
class CommandRegistry(registry.Registry):
74
def _get_name(command_name):
75
if command_name.startswith("cmd_"):
76
return _unsquish_command_name(command_name)
80
def register(self, cmd, decorate=False):
81
"""Utility function to help register a command
83
:param cmd: Command subclass to register
84
:param decorate: If true, allow overriding an existing command
85
of the same name; the old command is returned by this function.
86
Otherwise it is an error to try to override an existing command.
89
k_unsquished = self._get_name(k)
91
previous = self.get(k_unsquished)
93
previous = _builtin_commands().get(k_unsquished)
94
info = CommandInfo.from_command(cmd)
96
registry.Registry.register(self, k_unsquished, cmd,
97
override_existing=decorate, info=info)
99
trace.log_error('Two plugins defined the same command: %r' % k)
100
trace.log_error('Not loading the one in %r' %
101
sys.modules[cmd.__module__])
102
trace.log_error('Previously this command was registered from %r' %
103
sys.modules[previous.__module__])
106
def register_lazy(self, command_name, aliases, module_name):
107
"""Register a command without loading its module.
109
:param command_name: The primary name of the command.
110
:param aliases: A list of aliases for the command.
111
:module_name: The module that the command lives in.
113
key = self._get_name(command_name)
114
registry.Registry.register_lazy(self, key, module_name, command_name,
115
info=CommandInfo(aliases))
118
plugin_cmds = CommandRegistry()
64
121
def register_command(cmd, decorate=False):
65
"""Utility function to help register a command
67
:param cmd: Command subclass to register
68
:param decorate: If true, allow overriding an existing command
69
of the same name; the old command is returned by this function.
70
Otherwise it is an error to try to override an existing command.
72
122
global plugin_cmds
74
if k.startswith("cmd_"):
75
k_unsquished = _unsquish_command_name(k)
78
if k_unsquished not in plugin_cmds:
79
plugin_cmds[k_unsquished] = cmd
80
## trace.mutter('registered plugin command %s', k_unsquished)
81
if decorate and k_unsquished in builtin_command_names():
82
return _builtin_commands()[k_unsquished]
84
result = plugin_cmds[k_unsquished]
85
plugin_cmds[k_unsquished] = cmd
88
trace.log_error('Two plugins defined the same command: %r' % k)
89
trace.log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
123
return plugin_cmds.register(cmd, decorate)
92
126
def _squish_command_name(cmd):
154
191
# In the future, we may actually support Unicode command names.
156
193
# first look up this command under the specified name
157
cmds = _get_cmd_dict(plugins_override=plugins_override)
196
return plugin_cmds.get(cmd_name)()
199
cmds = _get_cmd_dict(plugins_override=False)
159
201
return cmds[cmd_name]()
205
for key in plugin_cmds.keys():
206
info = plugin_cmds.get_info(key)
207
if cmd_name in info.aliases:
208
return plugin_cmds.get(key)()
163
209
# look for any command which claims this as an alias
164
210
for real_cmd_name, cmd_class in cmds.iteritems():
165
211
if cmd_name in cmd_class.aliases:
269
328
elif aname[-1] == '*':
270
329
aname = '[' + aname[:-1] + '...]'
331
s = s[:-1] # remove last space
277
334
def get_help_text(self, additional_see_also=None, plain=True,
278
see_also_as_links=False):
335
see_also_as_links=False, verbose=True):
279
336
"""Return a text string with help for this command.
281
338
:param additional_see_also: Additional help topics to be
282
339
cross-referenced.
283
340
:param plain: if False, raw help (reStructuredText) is
284
341
returned instead of plain text.
285
342
:param see_also_as_links: if True, convert items in 'See also'
286
343
list to internal links (used by bzr_man rstx generator)
344
:param verbose: if True, display the full help, otherwise
345
leave out the descriptive sections and just display
346
usage help (e.g. Purpose, Usage, Options) with a
347
message explaining how to obtain full help.
288
349
doc = self.help()
290
351
raise NotImplementedError("sorry, no detailed help yet for %r" % self.name())
292
353
# Extract the summary (purpose) and sections out from the text
293
purpose,sections = self._get_help_parts(doc)
354
purpose,sections,order = self._get_help_parts(doc)
295
356
# If a custom usage section was provided, use it
296
357
if sections.has_key('Usage'):
318
379
result += options
321
# Add the description, indenting it 2 spaces
322
# to match the indentation of the options
323
if sections.has_key(None):
324
text = sections.pop(None)
325
text = '\n '.join(text.splitlines())
326
result += ':%s:\n %s\n\n' % ('Description',text)
383
# Add the description, indenting it 2 spaces
384
# to match the indentation of the options
385
if sections.has_key(None):
386
text = sections.pop(None)
387
text = '\n '.join(text.splitlines())
388
result += ':%s:\n %s\n\n' % ('Description',text)
328
# Add the custom sections (e.g. Examples). Note that there's no need
329
# to indent these as they must be indented already in the source.
331
labels = sorted(sections.keys())
333
result += ':%s:\n%s\n\n' % (label,sections[label])
390
# Add the custom sections (e.g. Examples). Note that there's no need
391
# to indent these as they must be indented already in the source.
394
if sections.has_key(label):
395
result += ':%s:\n%s\n' % (label,sections[label])
398
result += ("See bzr help %s for more details and examples.\n\n"
335
401
# Add the aliases, source (plug-in) and see also links, if any
365
431
def _get_help_parts(text):
366
432
"""Split help text into a summary and named sections.
368
:return: (summary,sections) where summary is the top line and
434
:return: (summary,sections,order) where summary is the top line and
369
435
sections is a dictionary of the rest indexed by section name.
436
order is the order the section appear in the text.
370
437
A section starts with a heading line of the form ":xxx:".
371
438
Indented text on following lines is the section value.
372
439
All text found outside a named section is assigned to the
373
440
default section which is given the key of None.
375
def save_section(sections, label, section):
442
def save_section(sections, order, label, section):
376
443
if len(section) > 0:
377
444
if sections.has_key(label):
378
445
sections[label] += '\n' + section
380
448
sections[label] = section
382
450
lines = text.rstrip().splitlines()
383
451
summary = lines.pop(0)
385
454
label,section = None,''
386
455
for line in lines:
387
456
if line.startswith(':') and line.endswith(':') and len(line) > 2:
388
save_section(sections, label, section)
457
save_section(sections, order, label, section)
389
458
label,section = line[1:-1],''
390
elif label != None and len(line) > 1 and not line[0].isspace():
391
save_section(sections, label, section)
459
elif (label is not None) and len(line) > 1 and not line[0].isspace():
460
save_section(sections, order, label, section)
392
461
label,section = None,line
394
463
if len(section) > 0:
395
464
section += '\n' + line
398
save_section(sections, label, section)
399
return summary, sections
467
save_section(sections, order, label, section)
468
return summary, sections, order
401
470
def get_help_topic(self):
402
471
"""Return the commands help topic - its name."""
419
488
"""Return dict of valid options for this command.
421
490
Maps from long option name to option object."""
423
r['help'] = option._help_option
491
r = Option.STD_OPTIONS.copy()
424
493
for o in self.takes_options:
425
494
if isinstance(o, basestring):
426
495
o = option.Option.OPTIONS[o]
497
if o.name in std_names:
498
self.supported_std_options.append(o.name)
430
501
def _setup_outf(self):
431
502
"""Return a file linked to stdout, which has proper encoding."""
432
assert self.encoding_type in ['strict', 'exact', 'replace']
434
503
# Originally I was using self.stdout, but that looks
435
504
# *way* too much like sys.stdout
436
505
if self.encoding_type == 'exact':
446
515
output_encoding = osutils.get_terminal_encoding()
448
# use 'replace' so that we don't abort if trying to write out
449
# in e.g. the default C locale.
450
self.outf = codecs.getwriter(output_encoding)(sys.stdout, errors=self.encoding_type)
517
self.outf = codecs.getwriter(output_encoding)(sys.stdout,
518
errors=self.encoding_type)
451
519
# For whatever reason codecs.getwriter() does not advertise its encoding
452
520
# it just returns the encoding of the wrapped file, which is completely
453
521
# bogus. So set the attribute, so we can find the correct encoding later.
460
528
DeprecationWarning, stacklevel=2)
462
530
args, opts = parse_args(self, argv, alias_argv)
532
# Process the standard options
463
533
if 'help' in opts: # e.g. bzr add --help
464
534
sys.stdout.write(self.get_help_text())
536
if 'usage' in opts: # e.g. bzr add --usage
537
sys.stdout.write(self.get_help_text(verbose=False))
539
trace.set_verbosity_level(option._verbosity_level)
540
if 'verbose' in self.supported_std_options:
541
opts['verbose'] = trace.is_verbose()
542
elif opts.has_key('verbose'):
544
if 'quiet' in self.supported_std_options:
545
opts['quiet'] = trace.is_quiet()
546
elif opts.has_key('quiet'):
466
549
# mix arguments and options into one dictionary
467
550
cmdargs = _match_argform(self.name(), self.takes_args, args)
514
# Technically, this function hasn't been use in a *really* long time
515
# but we are only deprecating it now.
516
@deprecated_function(zero_eleven)
517
def parse_spec(spec):
523
>>> parse_spec("../@")
525
>>> parse_spec("../f/@35")
527
>>> parse_spec('./@revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67')
528
['.', 'revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67']
533
parsed = spec.split('/@')
534
assert len(parsed) == 2
539
parsed[1] = int(parsed[1])
541
pass # We can allow stuff like ./@revid:blahblahblah
545
parsed = [spec, None]
597
class CommandHooks(Hooks):
598
"""Hooks related to Command object creation/enumeration."""
601
"""Create the default hooks.
603
These are all empty initially, because by default nothing should get
607
self.create_hook(HookPoint('extend_command',
608
"Called after creating a command object to allow modifications "
609
"such as adding or removing options, docs etc. Called with the "
610
"new bzrlib.commands.Command object.", (1, 13), None))
612
Command.hooks = CommandHooks()
548
615
def parse_args(command, argv, alias_argv=None):
549
616
"""Parse command line.
551
618
Arguments and options are parsed at this level before being passed
552
619
down to specific command handlers. This routine knows, from a
553
620
lookup table, something about the available options, what optargs
602
669
% (cmd, argname.upper()))
604
671
argdict[argname] = args.pop(0)
607
674
raise errors.BzrCommandError("extra argument to command %s: %s"
608
675
% (cmd, args[0]))
679
def apply_coveraged(dirname, the_callable, *args, **kwargs):
680
# Cannot use "import trace", as that would import bzrlib.trace instead of
681
# the standard library's trace.
682
trace = __import__('trace')
684
tracer = trace.Trace(count=1, trace=0)
685
sys.settrace(tracer.globaltrace)
686
threading.settrace(tracer.globaltrace)
689
return exception_to_return_code(the_callable, *args, **kwargs)
692
results = tracer.results()
693
results.write_results(show_missing=1, summary=False,
614
697
def apply_profiled(the_callable, *args, **kwargs):
634
718
os.remove(pfname)
721
def exception_to_return_code(the_callable, *args, **kwargs):
722
"""UI level helper for profiling and coverage.
724
This transforms exceptions into a return value of 3. As such its only
725
relevant to the UI layer, and should never be called where catching
726
exceptions may be desirable.
729
return the_callable(*args, **kwargs)
730
except (KeyboardInterrupt, Exception), e:
731
# used to handle AssertionError and KeyboardInterrupt
732
# specially here, but hopefully they're handled ok by the logger now
733
exc_info = sys.exc_info()
734
exitcode = trace.report_exception(exc_info, sys.stderr)
735
if os.environ.get('BZR_PDB'):
736
print '**** entering debugger'
739
if sys.version_info[:2] < (2, 6):
741
# pdb.post_mortem(tb)
742
# but because pdb.post_mortem gives bad results for tracebacks
743
# from inside generators, we do it manually.
744
# (http://bugs.python.org/issue4150, fixed in Python 2.6)
746
# Setup pdb on the traceback
749
p.setup(tb.tb_frame, tb)
750
# Point the debugger at the deepest frame of the stack
751
p.curindex = len(p.stack) - 1
752
p.curframe = p.stack[p.curindex][0]
753
# Start the pdb prompt.
754
p.print_stack_entry(p.stack[p.curindex])
637
762
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
638
763
from bzrlib.lsprof import profile
639
ret, stats = profile(the_callable, *args, **kwargs)
764
ret, stats = profile(exception_to_return_code, the_callable, *args, **kwargs)
641
766
if filename is None:
661
791
config = bzrlib.config.GlobalConfig()
662
792
alias = config.get_alias(cmd)
665
return [a.decode('utf-8') for a in shlex.split(alias.encode('utf-8'))]
794
return shlex_split_unicode(alias)
669
798
def run_bzr(argv):
670
799
"""Execute a command.
672
This is similar to main(), but without all the trappings for
673
logging and error handling.
676
802
The command-line arguments, without the program name from argv[0]
677
803
These should already be decoded. All library/test code calling
678
804
run_bzr should be passing valid strings (don't need decoding).
680
806
Returns a command status or raises an exception.
682
808
Special master options: these must come before the command because
771
904
run_argv = [argv, alias_argv]
907
# We can be called recursively (tests for example), but we don't want
908
# the verbosity level to propagate.
909
saved_verbosity_level = option._verbosity_level
910
option._verbosity_level = 0
914
'--coverage ignored, because --lsprof is in use.')
775
915
ret = apply_lsprofiled(opt_lsprof_file, run, *run_argv)
776
916
elif opt_profile:
919
'--coverage ignored, because --profile is in use.')
777
920
ret = apply_profiled(run, *run_argv)
921
elif opt_coverage_dir:
922
ret = apply_coveraged(opt_coverage_dir, run, *run_argv)
779
924
ret = run(*run_argv)
925
if 'memory' in debug.debug_flags:
926
trace.debug_memory('Process status after command:', short=False)
782
# reset, in case we may do other commands later within the same process
783
trace.be_quiet(False)
929
# reset, in case we may do other commands later within the same
930
# process. Commands that want to execute sub-commands must propagate
931
# --verbose in their own way.
932
option._verbosity_level = saved_verbosity_level
785
935
def display_command(func):
786
936
"""Decorator that suppresses pipe/interrupt errors."""
802
952
return ignore_pipe
956
"""Main entry point of command-line interface.
958
:param argv: list of unicode command-line arguments similar to sys.argv.
959
argv[0] is script name usually, it will be ignored.
960
Don't pass here sys.argv because this list contains plain strings
961
and not unicode; pass None instead.
963
:return: exit code of bzr command.
807
from bzrlib.ui.text import TextUIFactory
808
bzrlib.ui.ui_factory = TextUIFactory()
809
argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
966
bzrlib.ui.ui_factory = bzrlib.ui.make_ui_for_terminal(
967
sys.stdin, sys.stdout, sys.stderr)
969
# Is this a final release version? If so, we should suppress warnings
970
if bzrlib.version_info[3] == 'final':
971
from bzrlib import symbol_versioning
972
symbol_versioning.suppress_deprecation_warnings(override=False)
974
argv = osutils.get_unicode_argv()
978
# ensure all arguments are unicode strings
980
if isinstance(a, unicode):
983
new_argv.append(a.decode('ascii'))
984
except UnicodeDecodeError:
985
raise errors.BzrError("argv should be list of unicode strings.")
810
987
ret = run_bzr_catch_errors(argv)
811
988
trace.mutter("return code %d", ret)
815
992
def run_bzr_catch_errors(argv):
993
"""Run a bzr command with parameters as described by argv.
995
This function assumed that that UI layer is setup, that symbol deprecations
996
are already applied, and that unicode decoding has already been performed on argv.
998
return exception_to_return_code(run_bzr, argv)
1001
def run_bzr_catch_user_errors(argv):
1002
"""Run bzr and report user errors, but let internal errors propagate.
1004
This is used for the test suite, and might be useful for other programs
1005
that want to wrap the commandline interface.
817
1008
return run_bzr(argv)
818
except (KeyboardInterrupt, Exception), e:
819
# used to handle AssertionError and KeyboardInterrupt
820
# specially here, but hopefully they're handled ok by the logger now
821
trace.report_exception(sys.exc_info(), sys.stderr)
822
if os.environ.get('BZR_PDB'):
823
print '**** entering debugger'
825
pdb.post_mortem(sys.exc_traceback)
1009
except Exception, e:
1010
if (isinstance(e, (OSError, IOError))
1011
or not getattr(e, 'internal_error', True)):
1012
trace.report_exception(sys.exc_info(), sys.stderr)
829
1018
class HelpCommandIndex(object):
1041
class Provider(object):
1042
'''Generic class to be overriden by plugins'''
1044
def plugin_for_command(self, cmd_name):
1045
'''Takes a command and returns the information for that plugin
1047
:return: A dictionary with all the available information
1048
for the requested plugin
1050
raise NotImplementedError
1053
class ProvidersRegistry(registry.Registry):
1054
'''This registry exists to allow other providers to exist'''
1057
for key, provider in self.iteritems():
1060
command_providers_registry = ProvidersRegistry()
852
1063
if __name__ == '__main__':
853
1064
sys.exit(main(sys.argv))