33
32
from warnings import warn
33
from inspect import getdoc
38
from bzrlib.errors import (BzrError,
43
from bzrlib.option import Option
37
from bzrlib.trace import mutter, note, log_error, warning
38
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
44
39
from bzrlib.revisionspec import RevisionSpec
45
from bzrlib.symbol_versioning import *
47
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
40
from bzrlib import BZRDIR
52
def register_command(cmd, decorate=False):
53
"""Utility function to help register a command
55
:param cmd: Command subclass to register
56
:param decorate: If true, allow overriding an existing command
57
of the same name; the old command is returned by this function.
58
Otherwise it is an error to try to override an existing command.
45
def register_command(cmd):
46
"Utility function to help register a command"
62
49
if k.startswith("cmd_"):
86
67
return cmd[4:].replace('_','-')
70
def _parse_revision_str(revstr):
71
"""This handles a revision string -> revno.
73
This always returns a list. The list will have one element for
76
>>> _parse_revision_str('234')
77
[<RevisionSpec_int 234>]
78
>>> _parse_revision_str('234..567')
79
[<RevisionSpec_int 234>, <RevisionSpec_int 567>]
80
>>> _parse_revision_str('..')
81
[<RevisionSpec None>, <RevisionSpec None>]
82
>>> _parse_revision_str('..234')
83
[<RevisionSpec None>, <RevisionSpec_int 234>]
84
>>> _parse_revision_str('234..')
85
[<RevisionSpec_int 234>, <RevisionSpec None>]
86
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
87
[<RevisionSpec_int 234>, <RevisionSpec_int 456>, <RevisionSpec_int 789>]
88
>>> _parse_revision_str('234....789') # Error?
89
[<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
90
>>> _parse_revision_str('revid:test@other.com-234234')
91
[<RevisionSpec_revid revid:test@other.com-234234>]
92
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
93
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
94
>>> _parse_revision_str('revid:test@other.com-234234..23')
95
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_int 23>]
96
>>> _parse_revision_str('date:2005-04-12')
97
[<RevisionSpec_date date:2005-04-12>]
98
>>> _parse_revision_str('date:2005-04-12 12:24:33')
99
[<RevisionSpec_date date:2005-04-12 12:24:33>]
100
>>> _parse_revision_str('date:2005-04-12T12:24:33')
101
[<RevisionSpec_date date:2005-04-12T12:24:33>]
102
>>> _parse_revision_str('date:2005-04-12,12:24:33')
103
[<RevisionSpec_date date:2005-04-12,12:24:33>]
104
>>> _parse_revision_str('-5..23')
105
[<RevisionSpec_int -5>, <RevisionSpec_int 23>]
106
>>> _parse_revision_str('-5')
107
[<RevisionSpec_int -5>]
108
>>> _parse_revision_str('123a')
109
Traceback (most recent call last):
111
BzrError: No namespace registered for string: '123a'
112
>>> _parse_revision_str('abc')
113
Traceback (most recent call last):
115
BzrError: No namespace registered for string: 'abc'
118
old_format_re = re.compile('\d*:\d*')
119
m = old_format_re.match(revstr)
122
warning('Colon separator for revision numbers is deprecated.'
124
for rev in revstr.split(':'):
126
revs.append(RevisionSpec(int(rev)))
128
revs.append(RevisionSpec(None))
130
for x in revstr.split('..'):
132
revs.append(RevisionSpec(None))
134
revs.append(RevisionSpec(x))
89
138
def _builtin_commands():
90
139
import bzrlib.builtins
92
141
builtins = bzrlib.builtins.__dict__
93
142
for name in builtins:
94
143
if name.startswith("cmd_"):
95
real_name = _unsquish_command_name(name)
144
real_name = _unsquish_command_name(name)
96
145
r[real_name] = builtins[name]
100
150
def builtin_command_names():
213
243
if self.__doc__ == Command.__doc__:
214
244
warn("No help message set for %r" % self)
217
"""Return dict of valid options for this command.
219
Maps from long option name to option object."""
221
r['help'] = Option.OPTIONS['help']
222
for o in self.takes_options:
223
if not isinstance(o, Option):
224
o = Option.OPTIONS[o]
228
def _setup_outf(self):
229
"""Return a file linked to stdout, which has proper encoding."""
230
assert self.encoding_type in ['strict', 'exact', 'replace']
232
# Originally I was using self.stdout, but that looks
233
# *way* too much like sys.stdout
234
if self.encoding_type == 'exact':
235
self.outf = sys.stdout
238
output_encoding = getattr(sys.stdout, 'encoding', None)
239
if not output_encoding:
240
input_encoding = getattr(sys.stdin, 'encoding', None)
241
if not input_encoding:
242
output_encoding = bzrlib.user_encoding
243
mutter('encoding stdout as bzrlib.user_encoding %r', output_encoding)
245
output_encoding = input_encoding
246
mutter('encoding stdout as sys.stdin encoding %r', output_encoding)
248
mutter('encoding stdout as sys.stdout encoding %r', output_encoding)
250
# use 'replace' so that we don't abort if trying to write out
251
# in e.g. the default C locale.
252
self.outf = codecs.getwriter(output_encoding)(sys.stdout, errors=self.encoding_type)
253
# For whatever reason codecs.getwriter() does not advertise its encoding
254
# it just returns the encoding of the wrapped file, which is completely
255
# bogus. So set the attribute, so we can find the correct encoding later.
256
self.outf.encoding = output_encoding
258
@deprecated_method(zero_eight)
259
247
def run_argv(self, argv):
260
"""Parse command line and run.
262
See run_argv_aliases for the 0.8 and beyond api.
264
return self.run_argv_aliases(argv)
248
"""Parse command line and run."""
249
args, opts = parse_args(argv)
266
def run_argv_aliases(self, argv, alias_argv=None):
267
"""Parse the command line and run with extra aliases in alias_argv."""
268
args, opts = parse_args(self, argv, alias_argv)
269
251
if 'help' in opts: # e.g. bzr add --help
270
252
from bzrlib.help import help_on_command
271
253
help_on_command(self.name())
273
# XXX: This should be handled by the parser
274
allowed_names = self.options().keys()
256
# check options are reasonable
257
allowed = self.takes_options
275
258
for oname in opts:
276
if oname not in allowed_names:
277
raise BzrCommandError("option '--%s' is not allowed for"
278
" command %r" % (oname, self.name()))
259
if oname not in allowed:
260
raise BzrCommandError("option '--%s' is not allowed for command %r"
261
% (oname, self.name()))
279
263
# mix arguments and options into one dictionary
280
264
cmdargs = _match_argform(self.name(), self.takes_args, args)
344
326
parsed = [spec, None]
347
def parse_args(command, argv, alias_argv=None):
330
# list of all available options; the rhs can be either None for an
331
# option that takes no argument, or a constructor function that checks
345
'revision': _parse_revision_str,
371
def parse_args(argv):
348
372
"""Parse command line.
350
374
Arguments and options are parsed at this level before being passed
351
375
down to specific command handlers. This routine knows, from a
352
376
lookup table, something about the available options, what optargs
353
377
they take, and which commands will accept them.
379
>>> parse_args('--help'.split())
381
>>> parse_args('help -- --invalidcmd'.split())
382
(['help', '--invalidcmd'], {})
383
>>> parse_args('--version'.split())
384
([], {'version': True})
385
>>> parse_args('status --all'.split())
386
(['status'], {'all': True})
387
>>> parse_args('commit --message=biter'.split())
388
(['commit'], {'message': u'biter'})
389
>>> parse_args('log -r 500'.split())
390
(['log'], {'revision': [<RevisionSpec_int 500>]})
391
>>> parse_args('log -r500..600'.split())
392
(['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
393
>>> parse_args('log -vr500..600'.split())
394
(['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
395
>>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
396
(['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
355
# TODO: chop up this beast; make it a method of the Command
360
cmd_options = command.options()
362
proc_aliasarg = True # Are we processing alias_argv now?
363
for proc_argv in alias_argv, argv:
370
# We've received a standalone -- No more flags
374
# option names must not be unicode
378
mutter(" got option %r", a)
380
optname, optarg = a[2:].split('=', 1)
383
if optname not in cmd_options:
384
raise BzrOptionError('unknown long option %r for'
389
if shortopt in Option.SHORT_OPTIONS:
390
# Multi-character options must have a space to delimit
392
# ^^^ what does this mean? mbp 20051014
393
optname = Option.SHORT_OPTIONS[shortopt].name
395
# Single character short options, can be chained,
396
# and have their value appended to their name
398
if shortopt not in Option.SHORT_OPTIONS:
399
# We didn't find the multi-character name, and we
400
# didn't find the single char name
401
raise BzrError('unknown short option %r' % a)
402
optname = Option.SHORT_OPTIONS[shortopt].name
404
if not argsover and a[0] == '-':
405
# option names must not be unicode
410
# We've received a standalone -- No more flags
413
mutter(" got option %r" % a)
415
optname, optarg = a[2:].split('=', 1)
418
if optname not in OPTIONS:
419
raise BzrError('unknown long option %r' % a)
422
if shortopt in SHORT_OPTIONS:
423
# Multi-character options must have a space to delimit
425
optname = SHORT_OPTIONS[shortopt]
427
# Single character short options, can be chained,
428
# and have their value appended to their name
430
if shortopt not in SHORT_OPTIONS:
431
# We didn't find the multi-character name, and we
432
# didn't find the single char name
433
raise BzrError('unknown short option %r' % a)
434
optname = SHORT_OPTIONS[shortopt]
405
# There are extra things on this option
406
# see if it is the value, or if it is another
408
optargfn = Option.OPTIONS[optname].type
410
# This option does not take an argument, so the
411
# next entry is another short option, pack it
413
proc_argv.insert(0, '-' + a[2:])
415
# This option takes an argument, so pack it
437
# There are extra things on this option
438
# see if it is the value, or if it is another
440
optargfn = OPTIONS[optname]
442
# This option does not take an argument, so the
443
# next entry is another short option, pack it back
445
argv.insert(0, '-' + a[2:])
447
# This option takes an argument, so pack it
452
# XXX: Do we ever want to support this, e.g. for -r?
453
raise BzrError('repeated option %r' % a)
419
if optname not in cmd_options:
420
raise BzrOptionError('unknown short option %r for'
422
(shortopt, command.name()))
424
# XXX: Do we ever want to support this, e.g. for -r?
426
raise BzrError('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)
455
optargfn = OPTIONS[optname]
459
raise BzrError('option %r needs an argument' % a)
435
raise BzrError('repeated option %r' % a)
437
option_obj = cmd_options[optname]
438
optargfn = option_obj.type
442
raise BzrError('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 BzrError('option %r takes no argument' % optname)
453
alias_opts[optname] = True
462
opts[optname] = optargfn(optarg)
456
proc_aliasarg = False # Done with alias argv
465
raise BzrError('option %r takes no argument' % optname)
457
470
return args, opts
460
475
def _match_argform(cmd, takes_args, args):
568
558
Do not load plugin modules at all
574
561
Only use builtin commands. (Plugins are still allowed to change
575
562
other behaviour.)
578
Run under the Python hotshot profiler.
581
Run under the Python lsprof profiler.
565
Run under the Python profiler.
567
# Load all of the transport methods
568
import bzrlib.transport.local, bzrlib.transport.http
570
argv = [a.decode(bzrlib.user_encoding) for a in argv]
585
opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = \
586
opt_no_aliases = False
587
opt_lsprof_file = None
572
opt_profile = opt_no_plugins = opt_builtin = False
589
574
# --no-plugins is handled specially at a very early stage. We need
590
575
# to load plugins before doing other command parsing so that they
591
576
# can override commands, but this needs to happen first.
597
579
if a == '--profile':
598
580
opt_profile = True
599
elif a == '--lsprof':
601
elif a == '--lsprof-file':
602
opt_lsprof_file = argv[i + 1]
604
581
elif a == '--no-plugins':
605
582
opt_no_plugins = True
606
elif a == '--no-aliases':
607
opt_no_aliases = True
608
583
elif a == '--builtin':
609
584
opt_builtin = True
610
elif a in ('--quiet', '-q'):
618
from bzrlib.builtins import cmd_help
619
cmd_help().run_argv_aliases([])
589
if (not argv) or (argv[0] == '--help'):
590
from bzrlib.help import help
622
597
if argv[0] == '--version':
627
602
if not opt_no_plugins:
628
603
from bzrlib.plugin import load_plugins
631
from bzrlib.plugin import disable_plugins
636
if not opt_no_aliases:
637
alias_argv = get_alias(argv[0])
639
alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
640
argv[0] = alias_argv.pop(0)
642
606
cmd = str(argv.pop(0))
644
608
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
645
if not getattr(cmd_obj.run_argv, 'is_deprecated', False):
646
run = cmd_obj.run_argv
611
ret = apply_profiled(cmd_obj.run_argv, argv)
649
run = cmd_obj.run_argv_aliases
650
run_argv = [argv, alias_argv]
654
ret = apply_lsprofiled(opt_lsprof_file, run, *run_argv)
656
ret = apply_profiled(run, *run_argv)
661
# reset, in case we may do other commands later within the same process
664
def display_command(func):
665
"""Decorator that suppresses pipe/interrupt errors."""
666
def ignore_pipe(*args, **kwargs):
668
result = func(*args, **kwargs)
672
if not hasattr(e, 'errno'):
674
if e.errno != errno.EPIPE:
677
except KeyboardInterrupt:
613
ret = cmd_obj.run_argv(argv)
684
from bzrlib.ui.text import TextUIFactory
685
## bzrlib.trace.enable_default_logging()
686
619
bzrlib.trace.log_startup(argv)
687
bzrlib.ui.ui_factory = TextUIFactory()
620
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
689
argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
690
ret = run_bzr_catch_errors(argv)
691
mutter("return code %d", ret)
622
return run_bzr_catch_errors(argv[1:])
695
625
def run_bzr_catch_errors(argv):