51
from bzrlib import registry
51
from bzrlib.symbol_versioning import (
53
from bzrlib.hooks import Hooks
54
56
from bzrlib.option import Option
57
class CommandInfo(object):
58
"""Information about a command."""
60
def __init__(self, aliases):
61
"""The list of aliases for the command."""
62
self.aliases = aliases
65
def from_command(klass, command):
66
"""Factory to construct a CommandInfo from a command."""
67
return klass(command.aliases)
70
class CommandRegistry(registry.Registry):
73
def _get_name(command_name):
74
if command_name.startswith("cmd_"):
75
return _unsquish_command_name(command_name)
79
def register(self, cmd, decorate=False):
80
"""Utility function to help register a command
82
:param cmd: Command subclass to register
83
:param decorate: If true, allow overriding an existing command
84
of the same name; the old command is returned by this function.
85
Otherwise it is an error to try to override an existing command.
88
k_unsquished = self._get_name(k)
90
previous = self.get(k_unsquished)
92
previous = _builtin_commands().get(k_unsquished)
93
info = CommandInfo.from_command(cmd)
95
registry.Registry.register(self, k_unsquished, cmd,
96
override_existing=decorate, info=info)
98
trace.log_error('Two plugins defined the same command: %r' % k)
99
trace.log_error('Not loading the one in %r' %
100
sys.modules[cmd.__module__])
101
trace.log_error('Previously this command was registered from %r' %
102
sys.modules[previous.__module__])
105
def register_lazy(self, command_name, aliases, module_name):
106
"""Register a command without loading its module.
108
:param command_name: The primary name of the command.
109
:param aliases: A list of aliases for the command.
110
:module_name: The module that the command lives in.
112
key = self._get_name(command_name)
113
registry.Registry.register_lazy(self, key, module_name, command_name,
114
info=CommandInfo(aliases))
117
plugin_cmds = CommandRegistry()
120
62
def register_command(cmd, decorate=False):
63
"""Utility function to help register a command
65
:param cmd: Command subclass to register
66
:param decorate: If true, allow overriding an existing command
67
of the same name; the old command is returned by this function.
68
Otherwise it is an error to try to override an existing command.
121
70
global plugin_cmds
122
return plugin_cmds.register(cmd, decorate)
72
if k.startswith("cmd_"):
73
k_unsquished = _unsquish_command_name(k)
76
if k_unsquished not in plugin_cmds:
77
plugin_cmds[k_unsquished] = cmd
78
## trace.mutter('registered plugin command %s', k_unsquished)
79
if decorate and k_unsquished in builtin_command_names():
80
return _builtin_commands()[k_unsquished]
82
result = plugin_cmds[k_unsquished]
83
plugin_cmds[k_unsquished] = cmd
86
trace.log_error('Two plugins defined the same command: %r' % k)
87
trace.log_error('Not loading the one in %r' % sys.modules[cmd.__module__])
88
trace.log_error('Previously this command was registered from %r' %
89
sys.modules[plugin_cmds[k_unsquished].__module__])
125
92
def _squish_command_name(cmd):
190
154
# In the future, we may actually support Unicode command names.
192
156
# first look up this command under the specified name
195
return plugin_cmds.get(cmd_name)()
198
cmds = _get_cmd_dict(plugins_override=False)
157
cmds = _get_cmd_dict(plugins_override=plugins_override)
200
159
return cmds[cmd_name]()
204
for key in plugin_cmds.keys():
205
info = plugin_cmds.get_info(key)
206
if cmd_name in info.aliases:
207
return plugin_cmds.get(key)()
208
163
# look for any command which claims this as an alias
209
164
for real_cmd_name, cmd_class in cmds.iteritems():
210
165
if cmd_name in cmd_class.aliases:
421
367
def _get_help_parts(text):
422
368
"""Split help text into a summary and named sections.
424
:return: (summary,sections,order) where summary is the top line and
370
:return: (summary,sections) where summary is the top line and
425
371
sections is a dictionary of the rest indexed by section name.
426
order is the order the section appear in the text.
427
372
A section starts with a heading line of the form ":xxx:".
428
373
Indented text on following lines is the section value.
429
374
All text found outside a named section is assigned to the
430
375
default section which is given the key of None.
432
def save_section(sections, order, label, section):
377
def save_section(sections, label, section):
433
378
if len(section) > 0:
434
379
if sections.has_key(label):
435
380
sections[label] += '\n' + section
438
382
sections[label] = section
440
384
lines = text.rstrip().splitlines()
441
385
summary = lines.pop(0)
444
387
label,section = None,''
445
388
for line in lines:
446
389
if line.startswith(':') and line.endswith(':') and len(line) > 2:
447
save_section(sections, order, label, section)
390
save_section(sections, label, section)
448
391
label,section = line[1:-1],''
449
elif (label is not None) and len(line) > 1 and not line[0].isspace():
450
save_section(sections, order, label, section)
392
elif label != None and len(line) > 1 and not line[0].isspace():
393
save_section(sections, label, section)
451
394
label,section = None,line
453
396
if len(section) > 0:
454
397
section += '\n' + line
457
save_section(sections, order, label, section)
458
return summary, sections, order
400
save_section(sections, label, section)
401
return summary, sections
460
403
def get_help_topic(self):
461
404
"""Return the commands help topic - its name."""
584
class CommandHooks(Hooks):
585
"""Hooks related to Command object creation/enumeration."""
588
"""Create the default hooks.
590
These are all empty initially, because by default nothing should get
594
# Introduced in 1.13:
595
# invoked after creating a command object to allow modifications such
596
# as adding or removing options, docs etc. Invoked with the command
598
self['extend_command'] = []
600
Command.hooks = CommandHooks()
603
529
def parse_args(command, argv, alias_argv=None):
604
530
"""Parse command line.
667
def apply_coveraged(dirname, the_callable, *args, **kwargs):
668
# Cannot use "import trace", as that would import bzrlib.trace instead of
669
# the standard library's trace.
670
trace = __import__('trace')
672
tracer = trace.Trace(count=1, trace=0)
673
sys.settrace(tracer.globaltrace)
675
ret = the_callable(*args, **kwargs)
678
results = tracer.results()
679
results.write_results(show_missing=1, summary=False,
683
595
def apply_profiled(the_callable, *args, **kwargs):
846
750
run_argv = [argv, alias_argv]
849
# We can be called recursively (tests for example), but we don't want
850
# the verbosity level to propagate.
851
saved_verbosity_level = option._verbosity_level
852
option._verbosity_level = 0
856
'--coverage ignored, because --lsprof is in use.')
857
754
ret = apply_lsprofiled(opt_lsprof_file, run, *run_argv)
858
755
elif opt_profile:
861
'--coverage ignored, because --profile is in use.')
862
756
ret = apply_profiled(run, *run_argv)
863
elif opt_coverage_dir:
864
ret = apply_coveraged(opt_coverage_dir, run, *run_argv)
866
758
ret = run(*run_argv)
867
if 'memory' in debug.debug_flags:
868
trace.debug_memory('Process status after command:', short=False)
871
# reset, in case we may do other commands later within the same
872
# process. Commands that want to execute sub-commands must propagate
873
# --verbose in their own way.
874
option._verbosity_level = saved_verbosity_level
761
# reset, in case we may do other commands later within the same process
762
option._verbosity_level = 0
877
764
def display_command(func):
878
765
"""Decorator that suppresses pipe/interrupt errors."""
899
bzrlib.ui.ui_factory = bzrlib.ui.make_ui_for_terminal(
900
sys.stdin, sys.stdout, sys.stderr)
902
# Is this a final release version? If so, we should suppress warnings
903
if bzrlib.version_info[3] == 'final':
904
from bzrlib import symbol_versioning
905
symbol_versioning.suppress_deprecation_warnings(override=False)
786
from bzrlib.ui.text import TextUIFactory
787
bzrlib.ui.ui_factory = TextUIFactory()
907
user_encoding = osutils.get_user_encoding()
908
argv = [a.decode(user_encoding) for a in argv[1:]]
789
argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
909
790
except UnicodeDecodeError:
910
791
raise errors.BzrError(("Parameter '%r' is unsupported by the current "
911
792
"encoding." % a))
922
803
except (KeyboardInterrupt, Exception), e:
923
804
# used to handle AssertionError and KeyboardInterrupt
924
805
# specially here, but hopefully they're handled ok by the logger now
925
exc_info = sys.exc_info()
926
exitcode = trace.report_exception(exc_info, sys.stderr)
806
exitcode = trace.report_exception(sys.exc_info(), sys.stderr)
927
807
if os.environ.get('BZR_PDB'):
928
808
print '**** entering debugger'
931
if sys.version_info[:2] < (2, 6):
933
# pdb.post_mortem(tb)
934
# but because pdb.post_mortem gives bad results for tracebacks
935
# from inside generators, we do it manually.
936
# (http://bugs.python.org/issue4150, fixed in Python 2.6)
938
# Setup pdb on the traceback
941
p.setup(tb.tb_frame, tb)
942
# Point the debugger at the deepest frame of the stack
943
p.curindex = len(p.stack) - 1
944
p.curframe = p.stack[p.curindex]
945
# Start the pdb prompt.
946
p.print_stack_entry(p.stack[p.curindex])
810
pdb.post_mortem(sys.exc_traceback)
994
class Provider(object):
995
'''Generic class to be overriden by plugins'''
997
def plugin_for_command(self, cmd_name):
998
'''Takes a command and returns the information for that plugin
1000
:return: A dictionary with all the available information
1001
for the requested plugin
1003
raise NotImplementedError
1006
class ProvidersRegistry(registry.Registry):
1007
'''This registry exists to allow other providers to exist'''
1010
for key, provider in self.iteritems():
1013
command_providers_registry = ProvidersRegistry()
1016
854
if __name__ == '__main__':
1017
855
sys.exit(main(sys.argv))