48
from .hooks import Hooks
49
from .i18n import gettext
49
from bzrlib.hooks import Hooks
50
from bzrlib.i18n import gettext
50
51
# Compatibility - Option used to be in commands.
51
from .option import Option
52
from .plugin import disable_plugins, load_plugins, plugin_name
53
from . import errors, registry
60
class BzrOptionError(errors.BzrCommandError):
62
_fmt = "Error in command line options"
65
class CommandAvailableInPlugin(Exception):
67
internal_error = False
69
def __init__(self, cmd_name, plugin_metadata, provider):
71
self.plugin_metadata = plugin_metadata
72
self.cmd_name = cmd_name
73
self.provider = provider
77
_fmt = ('"%s" is not a standard brz command. \n'
78
'However, the following official plugin provides this command: %s\n'
79
'You can install it by going to: %s'
80
% (self.cmd_name, self.plugin_metadata['name'],
81
self.plugin_metadata['url']))
52
from bzrlib.option import Option
53
from bzrlib.plugin import disable_plugins, load_plugins
54
from bzrlib import registry
86
57
class CommandInfo(object):
189
160
def _unsquish_command_name(cmd):
190
return cmd[4:].replace('_', '-')
161
return cmd[4:].replace('_','-')
193
164
def _register_builtin_commands():
194
165
if builtin_command_registry.keys():
197
import breezy.builtins
198
for cmd_class in _scan_module_for_commands(breezy.builtins):
168
import bzrlib.builtins
169
for cmd_class in _scan_module_for_commands(bzrlib.builtins).values():
199
170
builtin_command_registry.register(cmd_class)
200
breezy.builtins._register_lazy_builtins()
171
bzrlib.builtins._register_lazy_builtins()
203
174
def _scan_module_for_commands(module):
204
module_dict = module.__dict__
205
for name in module_dict:
176
for name, obj in module.__dict__.iteritems():
206
177
if name.startswith("cmd_"):
207
yield module_dict[name]
178
real_name = _unsquish_command_name(name)
210
183
def _list_bzr_commands(names):
244
217
return plugin_cmds.keys()
247
# Overrides for common mispellings that heuristics get wrong
249
'ic': {'ci': 0}, # heuristic finds nick
253
def guess_command(cmd_name):
254
"""Guess what command a user typoed.
256
:param cmd_name: Command to search for
257
:return: None if no command was found, name of a command otherwise
260
for name in all_command_names():
262
cmd = get_cmd_object(name)
263
names.update(cmd.aliases)
264
# candidate: modified levenshtein distance against cmd_name.
266
from . import patiencediff
267
for name in sorted(names):
268
matcher = patiencediff.PatienceSequenceMatcher(None, cmd_name, name)
270
opcodes = matcher.get_opcodes()
271
for opcode, l1, l2, r1, r2 in opcodes:
272
if opcode == 'delete':
274
elif opcode == 'replace':
275
distance += max(l2-l1, r2-l1)
276
elif opcode == 'insert':
278
elif opcode == 'equal':
279
# Score equal ranges lower, making similar commands of equal
280
# length closer than arbitrary same length commands.
281
distance -= 0.1 * (l2-l1)
282
costs[name] = distance
283
costs.update(_GUESS_OVERRIDES.get(cmd_name, {}))
284
costs = sorted((costs[key], key) for key in costs)
289
candidate = costs[0][1]
293
220
def get_cmd_object(cmd_name, plugins_override=True):
294
221
"""Return the command object for a command.
300
227
return _get_cmd_object(cmd_name, plugins_override)
302
# No command found, see if this was a typo
303
candidate = guess_command(cmd_name)
304
if candidate is not None:
305
raise errors.BzrCommandError(
306
gettext('unknown command "%s". Perhaps you meant "%s"')
307
% (cmd_name, candidate))
308
raise errors.BzrCommandError(gettext('unknown command "%s"')
229
raise errors.BzrCommandError(gettext('unknown command "%s"') % cmd_name)
312
232
def _get_cmd_object(cmd_name, plugins_override=True, check_missing=True):
350
class NoPluginAvailable(errors.BzrError):
354
270
def _try_plugin_provider(cmd_name):
355
271
"""Probe for a plugin provider having cmd_name."""
357
273
plugin_metadata, provider = probe_for_provider(cmd_name)
358
raise CommandAvailableInPlugin(cmd_name, plugin_metadata, provider)
359
except NoPluginAvailable:
274
raise errors.CommandAvailableInPlugin(cmd_name,
275
plugin_metadata, provider)
276
except errors.NoPluginAvailable:
371
288
for provider in command_providers_registry:
373
290
return provider.plugin_for_command(cmd_name), provider
374
except NoPluginAvailable:
291
except errors.NoPluginAvailable:
376
raise NoPluginAvailable(cmd_name)
293
raise errors.NoPluginAvailable(cmd_name)
379
296
def _get_bzr_command(cmd_or_None, cmd_name):
392
309
# Only do external command lookups when no command is found so far.
393
310
if cmd_or_None is not None:
394
311
return cmd_or_None
395
from breezy.externalcommand import ExternalCommand
312
from bzrlib.externalcommand import ExternalCommand
396
313
cmd_obj = ExternalCommand.find_command(cmd_name)
401
318
def _get_plugin_command(cmd_or_None, cmd_name):
402
"""Get a command from brz's plugins."""
319
"""Get a command from bzr's plugins."""
404
321
return plugin_cmds.get(cmd_name)()
414
331
class Command(object):
415
332
"""Base class for commands.
417
Commands are the heart of the command-line brz interface.
334
Commands are the heart of the command-line bzr interface.
419
336
The command object mostly handles the mapping of command-line
420
parameters into one or more breezy operations, and of the results
337
parameters into one or more bzrlib operations, and of the results
421
338
into textual output.
423
340
Commands normally don't have any state. All their arguments are
469
386
:cvar hooks: An instance of CommandHooks.
471
:cvar __doc__: The help shown by 'brz help command' for this command.
388
:cvar __doc__: The help shown by 'bzr help command' for this command.
472
389
This is set by assigning explicitly to __doc__ so that -OO can
518
435
Only describes arguments, not options.
520
s = 'brz ' + self.name() + ' '
437
s = 'bzr ' + self.name() + ' '
521
438
for aname in self.takes_args:
522
439
aname = aname.upper()
523
440
if aname[-1] in ['$', '+']:
552
469
# Note: If self.gettext() translates ':Usage:\n', the section will
553
470
# be shown after "Description" section and we don't want to
554
471
# translate the usage string.
555
# Though, brz export-pot don't exports :Usage: section and it must
472
# Though, bzr export-pot don't exports :Usage: section and it must
556
473
# not be translated.
557
474
doc = self.gettext(doc)
559
476
doc = gettext("No help for this command.")
561
478
# Extract the summary (purpose) and sections out from the text
562
purpose, sections, order = self._get_help_parts(doc)
479
purpose,sections,order = self._get_help_parts(doc)
564
481
# If a custom usage section was provided, use it
565
if 'Usage' in sections:
482
if sections.has_key('Usage'):
566
483
usage = sections.pop('Usage')
568
485
usage = self._usage()
601
518
# Add the description, indenting it 2 spaces
602
519
# to match the indentation of the options
520
if sections.has_key(None):
604
521
text = sections.pop(None)
605
522
text = '\n '.join(text.splitlines())
606
523
result += gettext(':Description:\n %s\n\n') % (text,)
613
530
result += ':%s:\n%s\n' % (label, sections[label])
616
result += (gettext("See brz help %s for more details and examples.\n\n")
533
result += (gettext("See bzr help %s for more details and examples.\n\n")
619
536
# Add the aliases, source (plug-in) and see also links, if any
643
560
# If this will be rendered as plain text, convert it
645
import breezy.help_topics
646
result = breezy.help_topics.help_as_plain_text(result)
562
import bzrlib.help_topics
563
result = bzrlib.help_topics.help_as_plain_text(result)
661
578
def save_section(sections, order, label, section):
662
579
if len(section) > 0:
663
if label in sections:
580
if sections.has_key(label):
664
581
sections[label] += '\n' + section
666
583
order.append(label)
670
587
summary = lines.pop(0)
673
label, section = None, ''
590
label,section = None,''
674
591
for line in lines:
675
592
if line.startswith(':') and line.endswith(':') and len(line) > 2:
676
593
save_section(sections, order, label, section)
677
label, section = line[1:-1], ''
594
label,section = line[1:-1],''
678
595
elif (label is not None) and len(line) > 1 and not line[0].isspace():
679
596
save_section(sections, order, label, section)
680
label, section = None, line
597
label,section = None,line
682
599
if len(section) > 0:
683
600
section += '\n' + line
709
626
Maps from long option name to option object."""
710
627
r = Option.STD_OPTIONS.copy()
712
629
for o in self.takes_options:
713
if isinstance(o, string_types):
630
if isinstance(o, basestring):
714
631
o = option.Option.OPTIONS[o]
716
633
if o.name in std_names:
728
645
self._setup_outf()
730
647
# Process the standard options
731
if 'help' in opts: # e.g. brz add --help
648
if 'help' in opts: # e.g. bzr add --help
732
649
self.outf.write(self.get_help_text())
734
if 'usage' in opts: # e.g. brz add --usage
651
if 'usage' in opts: # e.g. bzr add --usage
735
652
self.outf.write(self.get_help_text(verbose=False))
737
654
trace.set_verbosity_level(option._verbosity_level)
738
655
if 'verbose' in self.supported_std_options:
739
656
opts['verbose'] = trace.is_verbose()
740
elif 'verbose' in opts:
657
elif opts.has_key('verbose'):
741
658
del opts['verbose']
742
659
if 'quiet' in self.supported_std_options:
743
660
opts['quiet'] = trace.is_quiet()
744
elif 'quiet' in opts:
661
elif opts.has_key('quiet'):
745
662
del opts['quiet']
746
663
# mix arguments and options into one dictionary
747
664
cmdargs = _match_argform(self.name(), self.takes_args, args)
836
753
:return: The name of the plugin or None if the command is builtin.
838
return plugin_name(self.__module__)
755
mod_parts = self.__module__.split('.')
756
if len(mod_parts) >= 3 and mod_parts[1] == 'plugins':
841
762
class CommandHooks(Hooks):
847
768
These are all empty initially, because by default nothing should get
850
Hooks.__init__(self, "breezy.commands", "Command.hooks")
771
Hooks.__init__(self, "bzrlib.commands", "Command.hooks")
851
772
self.add_hook('extend_command',
852
773
"Called after creating a command object to allow modifications "
853
774
"such as adding or removing options, docs etc. Called with the "
854
"new breezy.commands.Command object.", (1, 13))
775
"new bzrlib.commands.Command object.", (1, 13))
855
776
self.add_hook('get_command',
856
777
"Called when creating a single command. Called with "
857
778
"(cmd_or_None, command_name). get_command should either return "
858
779
"the cmd_or_None parameter, or a replacement Command object that "
859
780
"should be used for the command. Note that the Command.hooks "
860
781
"hooks are core infrastructure. Many users will prefer to use "
861
"breezy.commands.register_command or plugin_cmds.register_lazy.",
782
"bzrlib.commands.register_command or plugin_cmds.register_lazy.",
863
784
self.add_hook('get_missing_command',
864
785
"Called when creating a single command if no command could be "
900
821
# option name is given. See http://bugs.python.org/issue2931
902
823
options, args = parser.parse_args(args)
903
except UnicodeEncodeError as e:
824
except UnicodeEncodeError,e:
904
825
raise errors.BzrCommandError(
905
826
gettext('Only ASCII permitted in option names'))
907
opts = dict((k, v) for k, v in options.__dict__.items() if
908
v is not option.OptionParser.DEFAULT_VALUE)
828
opts = dict([(k, v) for k, v in options.__dict__.iteritems() if
829
v is not option.OptionParser.DEFAULT_VALUE])
909
830
return args, opts
960
880
def apply_coveraged(dirname, the_callable, *args, **kwargs):
881
# Cannot use "import trace", as that would import bzrlib.trace instead of
882
# the standard library's trace.
883
trace = __import__('trace')
962
885
tracer = trace.Trace(count=1, trace=0)
963
886
sys.settrace(tracer.globaltrace)
964
887
threading.settrace(tracer.globaltrace)
1007
930
return the_callable(*args, **kwargs)
1008
except (KeyboardInterrupt, Exception) as e:
931
except (KeyboardInterrupt, Exception), e:
1009
932
# used to handle AssertionError and KeyboardInterrupt
1010
933
# specially here, but hopefully they're handled ok by the logger now
1011
934
exc_info = sys.exc_info()
1012
935
exitcode = trace.report_exception(exc_info, sys.stderr)
1013
if os.environ.get('BRZ_PDB'):
1014
print('**** entering debugger')
936
if os.environ.get('BZR_PDB'):
937
print '**** entering debugger'
1016
939
pdb.post_mortem(exc_info[2])
1020
943
def apply_lsprofiled(filename, the_callable, *args, **kwargs):
1021
from breezy.lsprof import profile
944
from bzrlib.lsprof import profile
1022
945
ret, stats = profile(exception_to_return_code, the_callable,
1023
946
*args, **kwargs)
1041
964
If it is unspecified, the global config will be used.
1043
966
if config is None:
1044
import breezy.config
1045
config = breezy.config.GlobalConfig()
968
config = bzrlib.config.GlobalConfig()
1046
969
alias = config.get_alias(cmd)
1048
971
return cmdline.split(alias)
1091
1014
Specify the number of processes that can be run concurrently (selftest).
1093
trace.mutter("breezy version: " + breezy.__version__)
1016
trace.mutter("bazaar version: " + bzrlib.__version__)
1094
1017
argv = _specified_or_unicode_argv(argv)
1095
trace.mutter("brz arguments: %r", argv)
1018
trace.mutter("bzr arguments: %r", argv)
1097
1020
opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = \
1098
1021
opt_no_l10n = opt_no_aliases = False
1139
1062
argv_copy.append(a)
1142
cmdline_overrides = breezy.get_global_state().cmdline_overrides
1065
if bzrlib.global_state is None:
1066
# FIXME: Workaround for users that imported bzrlib but didn't call
1067
# bzrlib.initialize -- vila 2012-01-19
1068
cmdline_overrides = config.CommandLineStore()
1070
cmdline_overrides = bzrlib.global_state.cmdline_overrides
1143
1071
cmdline_overrides._from_cmdline(override_config)
1145
1073
debug.set_debug_flags_from_config()
1246
1174
# the process arguments in a unicode-safe way.
1247
1175
if argv is None:
1248
1176
return osutils.get_unicode_argv()
1251
# ensure all arguments are unicode strings
1253
if not isinstance(a, string_types):
1254
raise ValueError('not native str or unicode: %r' % (a,))
1255
if isinstance(a, bytes):
1256
# For Python 2 only allow ascii native strings
1257
a = a.decode('ascii')
1259
except (ValueError, UnicodeDecodeError):
1260
raise errors.BzrError("argv should be list of unicode strings.")
1180
# ensure all arguments are unicode strings
1182
if isinstance(a, unicode):
1185
new_argv.append(a.decode('ascii'))
1186
except UnicodeDecodeError:
1187
raise errors.BzrError("argv should be list of unicode strings.")
1264
1191
def main(argv=None):
1265
1192
"""Main entry point of command-line interface.
1267
Typically `breezy.initialize` should be called first.
1194
Typically `bzrlib.initialize` should be called first.
1269
1196
:param argv: list of unicode command-line arguments similar to sys.argv.
1270
1197
argv[0] is script name usually, it will be ignored.
1271
1198
Don't pass here sys.argv because this list contains plain strings
1272
1199
and not unicode; pass None instead.
1274
:return: exit code of brz command.
1201
:return: exit code of bzr command.
1276
1203
if argv is not None:
1277
1204
argv = argv[1:]
1295
1222
def run_bzr_catch_user_errors(argv):
1296
"""Run brz and report user errors, but let internal errors propagate.
1223
"""Run bzr and report user errors, but let internal errors propagate.
1298
1225
This is used for the test suite, and might be useful for other programs
1299
1226
that want to wrap the commandline interface.
1302
1229
install_bzr_command_hooks()
1304
1231
return run_bzr(argv)
1305
except Exception as e:
1232
except Exception, e:
1306
1233
if (isinstance(e, (OSError, IOError))
1307
1234
or not getattr(e, 'internal_error', True)):
1308
1235
trace.report_exception(sys.exc_info(), sys.stderr)
1350
1277
"""This registry exists to allow other providers to exist"""
1352
1279
def __iter__(self):
1353
for key, provider in self.items():
1280
for key, provider in self.iteritems():
1356
1283
command_providers_registry = ProvidersRegistry()