28
28
# TODO: "--profile=cum", to change sort order. Is there any value in leaving
29
29
# the profile output behind so it can be interactively examined?
34
from bzrlib.lazy_import import lazy_import
35
lazy_import(globals(), """
33
38
from warnings import warn
38
import bzrlib.errors as errors
39
from bzrlib.errors import (BzrError,
50
from bzrlib.symbol_versioning import (
43
57
from bzrlib.option import Option
45
from bzrlib.revisionspec import RevisionSpec
46
from bzrlib.symbol_versioning import (deprecated_method, zero_eight)
48
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
64
74
k_unsquished = _unsquish_command_name(k)
67
if not plugin_cmds.has_key(k_unsquished):
77
if k_unsquished not in plugin_cmds:
68
78
plugin_cmds[k_unsquished] = cmd
69
mutter('registered plugin command %s', k_unsquished)
79
## trace.mutter('registered plugin command %s', k_unsquished)
70
80
if decorate and k_unsquished in builtin_command_names():
71
81
return _builtin_commands()[k_unsquished]
130
140
from bzrlib.externalcommand import ExternalCommand
132
cmd_name = str(cmd_name) # not unicode
142
# We want only 'ascii' command names, but the user may have typed
143
# in a Unicode name. In that case, they should just get a
144
# 'command not found' error later.
145
# In the future, we may actually support Unicode command names.
134
147
# first look up this command under the specified name
135
148
cmds = _get_cmd_dict(plugins_override=plugins_override)
233
252
# Originally I was using self.stdout, but that looks
234
253
# *way* too much like sys.stdout
235
254
if self.encoding_type == 'exact':
255
# force sys.stdout to be binary stream on win32
256
if sys.platform == 'win32':
257
fileno = getattr(sys.stdout, 'fileno', None)
260
msvcrt.setmode(fileno(), os.O_BINARY)
236
261
self.outf = sys.stdout
239
output_encoding = bzrlib.osutils.get_terminal_encoding()
264
output_encoding = osutils.get_terminal_encoding()
241
266
# use 'replace' so that we don't abort if trying to write out
242
267
# in e.g. the default C locale.
246
271
# bogus. So set the attribute, so we can find the correct encoding later.
247
272
self.outf.encoding = output_encoding
249
@deprecated_method(zero_eight)
250
def run_argv(self, argv):
251
"""Parse command line and run.
253
See run_argv_aliases for the 0.8 and beyond api.
255
return self.run_argv_aliases(argv)
257
274
def run_argv_aliases(self, argv, alias_argv=None):
258
275
"""Parse the command line and run with extra aliases in alias_argv."""
277
warn("Passing None for [] is deprecated from bzrlib 0.10",
278
DeprecationWarning, stacklevel=2)
259
280
args, opts = parse_args(self, argv, alias_argv)
260
281
if 'help' in opts: # e.g. bzr add --help
261
282
from bzrlib.help import help_on_command
262
283
help_on_command(self.name())
264
# XXX: This should be handled by the parser
265
allowed_names = self.options().keys()
267
if oname not in allowed_names:
268
raise BzrOptionError("option '--%s' is not allowed for"
269
" command %r" % (oname, self.name()))
270
285
# mix arguments and options into one dictionary
271
286
cmdargs = _match_argform(self.name(), self.takes_args, args)
354
372
lookup table, something about the available options, what optargs
355
373
they take, and which commands will accept them.
357
# TODO: chop up this beast; make it a method of the Command
362
cmd_options = command.options()
364
proc_aliasarg = True # Are we processing alias_argv now?
365
for proc_argv in alias_argv, argv:
375
# We've received a standalone -- No more flags
379
# option names must not be unicode
383
mutter(" got option %r", a)
385
optname, optarg = a[2:].split('=', 1)
388
if optname not in cmd_options:
389
raise BzrCommandError('unknown option "%s"' % a)
392
if shortopt in Option.SHORT_OPTIONS:
393
# Multi-character options must have a space to delimit
395
# ^^^ what does this mean? mbp 20051014
396
optname = Option.SHORT_OPTIONS[shortopt].name
398
# Single character short options, can be chained,
399
# and have their value appended to their name
401
if shortopt not in Option.SHORT_OPTIONS:
402
# We didn't find the multi-character name, and we
403
# didn't find the single char name
404
raise BzrCommandError('unknown option "%s"' % a)
405
optname = Option.SHORT_OPTIONS[shortopt].name
408
# There are extra things on this option
409
# see if it is the value, or if it is another
411
optargfn = Option.OPTIONS[optname].type
413
# This option does not take an argument, so the
414
# next entry is another short option, pack it
416
proc_argv.insert(0, '-' + a[2:])
418
# This option takes an argument, so pack it
421
if optname not in cmd_options:
422
raise BzrCommandError('unknown option "%s"' % shortopt)
424
# XXX: Do we ever want to support this, e.g. for -r?
426
raise BzrCommandError('repeated option %r' % a)
427
elif optname in alias_opts:
428
# Replace what's in the alias with what's in the real
430
del alias_opts[optname]
432
proc_argv.insert(0, a)
435
raise BzrCommandError('repeated option %r' % a)
437
option_obj = cmd_options[optname]
438
optargfn = option_obj.type
442
raise BzrCommandError('option %r needs an argument' % a)
444
optarg = proc_argv.pop(0)
445
opts[optname] = optargfn(optarg)
447
alias_opts[optname] = optargfn(optarg)
450
raise BzrCommandError('option %r takes no argument' % optname)
453
alias_opts[optname] = True
456
proc_aliasarg = False # Done with alias argv
375
# TODO: make it a method of the Command?
376
parser = option.get_optparser(command.options())
377
if alias_argv is not None:
378
args = alias_argv + argv
382
options, args = parser.parse_args(args)
383
opts = dict([(k, v) for k, v in options.__dict__.iteritems() if
384
v is not option.OptionParser.DEFAULT_VALUE])
457
385
return args, opts
474
402
argdict[argname + '_list'] = None
475
403
elif ap[-1] == '+':
477
raise BzrCommandError("command %r needs one or more %s"
478
% (cmd, argname.upper()))
405
raise errors.BzrCommandError("command %r needs one or more %s"
406
% (cmd, argname.upper()))
480
408
argdict[argname + '_list'] = args[:]
482
410
elif ap[-1] == '$': # all but one
483
411
if len(args) < 2:
484
raise BzrCommandError("command %r needs one or more %s"
485
% (cmd, argname.upper()))
412
raise errors.BzrCommandError("command %r needs one or more %s"
413
% (cmd, argname.upper()))
486
414
argdict[argname + '_list'] = args[:-1]
489
417
# just a plain arg
492
raise BzrCommandError("command %r requires argument %s"
493
% (cmd, argname.upper()))
420
raise errors.BzrCommandError("command %r requires argument %s"
421
% (cmd, argname.upper()))
495
423
argdict[argname] = args.pop(0)
498
raise BzrCommandError("extra argument to command %s: %s"
426
raise errors.BzrCommandError("extra argument to command %s: %s"
543
"""Return an expanded alias, or None if no alias exists"""
545
alias = bzrlib.config.GlobalConfig().get_alias(cmd)
470
def get_alias(cmd, config=None):
471
"""Return an expanded alias, or None if no alias exists.
474
Command to be checked for an alias.
476
Used to specify an alternative config to use,
477
which is especially useful for testing.
478
If it is unspecified, the global config will be used.
482
config = bzrlib.config.GlobalConfig()
483
alias = config.get_alias(cmd)
547
return alias.split(' ')
486
return [a.decode('utf-8') for a in shlex.split(alias.encode('utf-8'))]
640
582
alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
641
583
argv[0] = alias_argv.pop(0)
643
cmd = str(argv.pop(0))
586
# We want only 'ascii' command names, but the user may have typed
587
# in a Unicode name. In that case, they should just get a
588
# 'command not found' error later.
645
590
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
646
if not getattr(cmd_obj.run_argv, 'is_deprecated', False):
647
run = cmd_obj.run_argv
650
run = cmd_obj.run_argv_aliases
651
run_argv = [argv, alias_argv]
591
run = cmd_obj.run_argv_aliases
592
run_argv = [argv, alias_argv]
697
638
return run_bzr(argv)
698
639
# do this here inside the exception wrappers to catch EPIPE
699
640
sys.stdout.flush()
641
except (KeyboardInterrupt, Exception), e:
701
642
# used to handle AssertionError and KeyboardInterrupt
702
643
# specially here, but hopefully they're handled ok by the logger now
703
bzrlib.trace.report_exception(sys.exc_info(), sys.stderr)
644
trace.report_exception(sys.exc_info(), sys.stderr)
704
645
if os.environ.get('BZR_PDB'):
705
646
print '**** entering debugger'