18
18
# TODO: probably should say which arguments are candidates for glob
19
19
# expansion on windows and do that at the command level.
21
# TODO: Define arguments by objects, rather than just using names.
22
# Those objects can specify the expected type of the argument, which
23
# would help with validation and shell completion. They could also provide
24
# help/explanation for that argument in a structured way.
26
# TODO: Specific "examples" property on commands for consistent formatting.
28
# TODO: "--profile=cum", to change sort order. Is there any value in leaving
29
# the profile output behind so it can be interactively examined?
21
# TODO: Help messages for options.
23
# TODO: Define arguments by objects, rather than just using names.
24
# Those objects can specify the expected type of the argument, which
25
# would help with validation and shell completion.
28
# TODO: Help messages for options.
30
# TODO: Define arguments by objects, rather than just using names.
31
# Those objects can specify the expected type of the argument, which
32
# would help with validation and shell completion.
33
38
from warnings import warn
39
from inspect import getdoc
38
import bzrlib.errors as errors
39
from bzrlib.errors import (BzrError,
43
from bzrlib.option import Option
43
from bzrlib.trace import mutter, note, log_error, warning
44
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
45
45
from bzrlib.revisionspec import RevisionSpec
46
from bzrlib.symbol_versioning import (deprecated_method, zero_eight)
47
from bzrlib import trace
48
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
46
from bzrlib import BZRDIR
53
def register_command(cmd, decorate=False):
54
"""Utility function to help register a command
56
:param cmd: Command subclass to register
57
:param decorate: If true, allow overriding an existing command
58
of the same name; the old command is returned by this function.
59
Otherwise it is an error to try to override an existing command.
51
def register_command(cmd):
52
"Utility function to help register a command"
63
55
if k.startswith("cmd_"):
87
73
return cmd[4:].replace('_','-')
76
def _parse_revision_str(revstr):
77
"""This handles a revision string -> revno.
79
This always returns a list. The list will have one element for
82
>>> _parse_revision_str('234')
83
[<RevisionSpec_int 234>]
84
>>> _parse_revision_str('234..567')
85
[<RevisionSpec_int 234>, <RevisionSpec_int 567>]
86
>>> _parse_revision_str('..')
87
[<RevisionSpec None>, <RevisionSpec None>]
88
>>> _parse_revision_str('..234')
89
[<RevisionSpec None>, <RevisionSpec_int 234>]
90
>>> _parse_revision_str('234..')
91
[<RevisionSpec_int 234>, <RevisionSpec None>]
92
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
93
[<RevisionSpec_int 234>, <RevisionSpec_int 456>, <RevisionSpec_int 789>]
94
>>> _parse_revision_str('234....789') # Error?
95
[<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
96
>>> _parse_revision_str('revid:test@other.com-234234')
97
[<RevisionSpec_revid revid:test@other.com-234234>]
98
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
99
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
100
>>> _parse_revision_str('revid:test@other.com-234234..23')
101
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_int 23>]
102
>>> _parse_revision_str('date:2005-04-12')
103
[<RevisionSpec_date date:2005-04-12>]
104
>>> _parse_revision_str('date:2005-04-12 12:24:33')
105
[<RevisionSpec_date date:2005-04-12 12:24:33>]
106
>>> _parse_revision_str('date:2005-04-12T12:24:33')
107
[<RevisionSpec_date date:2005-04-12T12:24:33>]
108
>>> _parse_revision_str('date:2005-04-12,12:24:33')
109
[<RevisionSpec_date date:2005-04-12,12:24:33>]
110
>>> _parse_revision_str('-5..23')
111
[<RevisionSpec_int -5>, <RevisionSpec_int 23>]
112
>>> _parse_revision_str('-5')
113
[<RevisionSpec_int -5>]
114
>>> _parse_revision_str('123a')
115
Traceback (most recent call last):
117
BzrError: No namespace registered for string: '123a'
118
>>> _parse_revision_str('abc')
119
Traceback (most recent call last):
121
BzrError: No namespace registered for string: 'abc'
124
old_format_re = re.compile('\d*:\d*')
125
m = old_format_re.match(revstr)
128
warning('Colon separator for revision numbers is deprecated.'
130
for rev in revstr.split(':'):
132
revs.append(RevisionSpec(int(rev)))
134
revs.append(RevisionSpec(None))
136
for x in revstr.split('..'):
138
revs.append(RevisionSpec(None))
140
revs.append(RevisionSpec(x))
144
def get_merge_type(typestring):
145
"""Attempt to find the merge class/factory associated with a string."""
146
from merge import merge_types
148
return merge_types[typestring][0]
150
templ = '%s%%7s: %%s' % (' '*12)
151
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
152
type_list = '\n'.join(lines)
153
msg = "No known merge type %s. Supported types are:\n%s" %\
154
(typestring, type_list)
155
raise BzrCommandError(msg)
90
158
def _builtin_commands():
91
159
import bzrlib.builtins
93
161
builtins = bzrlib.builtins.__dict__
94
162
for name in builtins:
95
163
if name.startswith("cmd_"):
96
real_name = _unsquish_command_name(name)
164
real_name = _unsquish_command_name(name)
97
165
r[real_name] = builtins[name]
101
170
def builtin_command_names():
214
263
if self.__doc__ == Command.__doc__:
215
264
warn("No help message set for %r" % self)
218
"""Return dict of valid options for this command.
220
Maps from long option name to option object."""
222
r['help'] = Option.OPTIONS['help']
223
for o in self.takes_options:
224
if not isinstance(o, Option):
225
o = Option.OPTIONS[o]
229
def _setup_outf(self):
230
"""Return a file linked to stdout, which has proper encoding."""
231
assert self.encoding_type in ['strict', 'exact', 'replace']
233
# Originally I was using self.stdout, but that looks
234
# *way* too much like sys.stdout
235
if self.encoding_type == 'exact':
236
self.outf = sys.stdout
239
output_encoding = bzrlib.osutils.get_terminal_encoding()
241
# use 'replace' so that we don't abort if trying to write out
242
# in e.g. the default C locale.
243
self.outf = codecs.getwriter(output_encoding)(sys.stdout, errors=self.encoding_type)
244
# For whatever reason codecs.getwriter() does not advertise its encoding
245
# it just returns the encoding of the wrapped file, which is completely
246
# bogus. So set the attribute, so we can find the correct encoding later.
247
self.outf.encoding = output_encoding
249
@deprecated_method(zero_eight)
250
267
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)
268
"""Parse command line and run."""
269
args, opts = parse_args(argv)
257
def run_argv_aliases(self, argv, alias_argv=None):
258
"""Parse the command line and run with extra aliases in alias_argv."""
259
args, opts = parse_args(self, argv, alias_argv)
260
271
if 'help' in opts: # e.g. bzr add --help
261
272
from bzrlib.help import help_on_command
262
273
help_on_command(self.name())
264
# XXX: This should be handled by the parser
265
allowed_names = self.options().keys()
276
# check options are reasonable
277
allowed = self.takes_options
266
278
for oname in opts:
267
if oname not in allowed_names:
268
raise BzrOptionError("option '--%s' is not allowed for"
269
" command %r" % (oname, self.name()))
279
if oname not in allowed:
280
raise BzrCommandError("option '--%s' is not allowed for command %r"
281
% (oname, self.name()))
270
283
# mix arguments and options into one dictionary
271
284
cmdargs = _match_argform(self.name(), self.takes_args, args)
346
346
parsed = [spec, None]
349
def parse_args(command, argv, alias_argv=None):
350
# list of all available options; the rhs can be either None for an
351
# option that takes no argument, or a constructor function that checks
364
'revision': _parse_revision_str,
376
'merge-type': get_merge_type,
390
def parse_args(argv):
350
391
"""Parse command line.
352
393
Arguments and options are parsed at this level before being passed
353
394
down to specific command handlers. This routine knows, from a
354
395
lookup table, something about the available options, what optargs
355
396
they take, and which commands will accept them.
398
>>> parse_args('--help'.split())
400
>>> parse_args('help -- --invalidcmd'.split())
401
(['help', '--invalidcmd'], {})
402
>>> parse_args('--version'.split())
403
([], {'version': True})
404
>>> parse_args('status --all'.split())
405
(['status'], {'all': True})
406
>>> parse_args('commit --message=biter'.split())
407
(['commit'], {'message': u'biter'})
408
>>> parse_args('log -r 500'.split())
409
(['log'], {'revision': [<RevisionSpec_int 500>]})
410
>>> parse_args('log -r500..600'.split())
411
(['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
412
>>> parse_args('log -vr500..600'.split())
413
(['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
414
>>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
415
(['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
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:
372
# We've received a standalone -- No more flags
376
# option names must not be unicode
380
mutter(" got option %r", a)
382
optname, optarg = a[2:].split('=', 1)
385
if optname not in cmd_options:
386
raise BzrCommandError('unknown option "%s"' % a)
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 BzrCommandError('unknown option "%s"' % a)
402
optname = Option.SHORT_OPTIONS[shortopt].name
423
if not argsover and a[0] == '-':
424
# option names must not be unicode
429
# We've received a standalone -- No more flags
432
mutter(" got option %r" % a)
434
optname, optarg = a[2:].split('=', 1)
437
if optname not in OPTIONS:
438
raise BzrError('unknown long option %r' % a)
441
if shortopt in SHORT_OPTIONS:
442
# Multi-character options must have a space to delimit
444
optname = SHORT_OPTIONS[shortopt]
446
# Single character short options, can be chained,
447
# and have their value appended to their name
449
if shortopt not in SHORT_OPTIONS:
450
# We didn't find the multi-character name, and we
451
# didn't find the single char name
452
raise BzrError('unknown short option %r' % a)
453
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
418
if optname not in cmd_options:
419
raise BzrCommandError('unknown option "%s"' % shortopt)
421
# XXX: Do we ever want to support this, e.g. for -r?
423
raise BzrCommandError('repeated option %r' % a)
424
elif optname in alias_opts:
425
# Replace what's in the alias with what's in the real
427
del alias_opts[optname]
429
proc_argv.insert(0, a)
432
raise BzrCommandError('repeated option %r' % a)
434
option_obj = cmd_options[optname]
435
optargfn = option_obj.type
439
raise BzrCommandError('option %r needs an argument' % a)
456
# There are extra things on this option
457
# see if it is the value, or if it is another
459
optargfn = OPTIONS[optname]
461
# This option does not take an argument, so the
462
# next entry is another short option, pack it back
464
argv.insert(0, '-' + a[2:])
441
optarg = proc_argv.pop(0)
442
opts[optname] = optargfn(optarg)
444
alias_opts[optname] = optargfn(optarg)
447
raise BzrCommandError('option %r takes no argument' % optname)
450
alias_opts[optname] = True
466
# This option takes an argument, so pack it
471
# XXX: Do we ever want to support this, e.g. for -r?
472
raise BzrError('repeated option %r' % a)
474
optargfn = OPTIONS[optname]
478
raise BzrError('option %r needs an argument' % a)
481
opts[optname] = optargfn(optarg)
453
proc_aliasarg = False # Done with alias argv
484
raise BzrError('option %r takes no argument' % optname)
454
489
return args, opts
457
494
def _match_argform(cmd, takes_args, args):
565
579
Do not load plugin modules at all
571
582
Only use builtin commands. (Plugins are still allowed to change
572
583
other behaviour.)
575
Run under the Python hotshot profiler.
578
Run under the Python lsprof profiler.
586
Run under the Python profiler.
589
argv = [a.decode(bzrlib.user_encoding) for a in argv]
582
opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = \
583
opt_no_aliases = False
584
opt_lsprof_file = None
591
opt_profile = opt_no_plugins = opt_builtin = False
586
593
# --no-plugins is handled specially at a very early stage. We need
587
594
# to load plugins before doing other command parsing so that they
588
595
# can override commands, but this needs to happen first.
594
598
if a == '--profile':
595
599
opt_profile = True
596
elif a == '--lsprof':
598
elif a == '--lsprof-file':
599
opt_lsprof_file = argv[i + 1]
601
600
elif a == '--no-plugins':
602
601
opt_no_plugins = True
603
elif a == '--no-aliases':
604
opt_no_aliases = True
605
602
elif a == '--builtin':
606
603
opt_builtin = True
607
elif a in ('--quiet', '-q'):
615
from bzrlib.builtins import cmd_help
616
cmd_help().run_argv_aliases([])
608
if (not argv) or (argv[0] == '--help'):
609
from bzrlib.help import help
619
616
if argv[0] == '--version':
624
621
if not opt_no_plugins:
625
622
from bzrlib.plugin import load_plugins
628
from bzrlib.plugin import disable_plugins
633
if not opt_no_aliases:
634
alias_argv = get_alias(argv[0])
636
alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
637
argv[0] = alias_argv.pop(0)
639
625
cmd = str(argv.pop(0))
641
627
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
642
if not getattr(cmd_obj.run_argv, 'is_deprecated', False):
643
run = cmd_obj.run_argv
630
ret = apply_profiled(cmd_obj.run_argv, argv)
646
run = cmd_obj.run_argv_aliases
647
run_argv = [argv, alias_argv]
651
ret = apply_lsprofiled(opt_lsprof_file, run, *run_argv)
653
ret = apply_profiled(run, *run_argv)
658
# reset, in case we may do other commands later within the same process
661
def display_command(func):
662
"""Decorator that suppresses pipe/interrupt errors."""
663
def ignore_pipe(*args, **kwargs):
665
result = func(*args, **kwargs)
669
if not hasattr(e, 'errno'):
671
if e.errno != errno.EPIPE:
672
# Win32 raises IOError with errno=0 on a broken pipe
673
if sys.platform != 'win32' or e.errno != 0:
676
except KeyboardInterrupt:
632
ret = cmd_obj.run_argv(argv)
683
from bzrlib.ui.text import TextUIFactory
684
bzrlib.ui.ui_factory = TextUIFactory()
685
argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
686
ret = run_bzr_catch_errors(argv)
687
mutter("return code %d", ret)
638
bzrlib.trace.log_startup(argv)
639
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
641
return run_bzr_catch_errors(argv[1:])
691
644
def run_bzr_catch_errors(argv):
694
# do this here inside the exception wrappers to catch EPIPE
650
# do this here inside the exception wrappers to catch EPIPE
652
#wrap common errors as CommandErrors.
653
except (NotBranchError,), e:
654
raise BzrCommandError(str(e))
655
except BzrCommandError, e:
656
# command line syntax error, etc
660
bzrlib.trace.log_exception()
662
except AssertionError, e:
663
bzrlib.trace.log_exception('assertion failed: ' + str(e))
665
except KeyboardInterrupt, e:
666
bzrlib.trace.note('interrupted')
696
668
except Exception, e:
697
# used to handle AssertionError and KeyboardInterrupt
698
# specially here, but hopefully they're handled ok by the logger now
699
bzrlib.trace.report_exception(sys.exc_info(), sys.stderr)
700
if os.environ.get('BZR_PDB'):
701
print '**** entering debugger'
703
pdb.post_mortem(sys.exc_traceback)
670
if (isinstance(e, IOError)
671
and hasattr(e, 'errno')
672
and e.errno == errno.EPIPE):
673
bzrlib.trace.note('broken pipe')
676
bzrlib.trace.log_exception()
706
680
if __name__ == '__main__':
707
681
sys.exit(main(sys.argv))