24
24
# Those objects can specify the expected type of the argument, which
25
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.
35
# TODO: Help messages for options.
37
# TODO: Define arguments by objects, rather than just using names.
38
# Those objects can specify the expected type of the argument, which
39
# would help with validation and shell completion.
27
# TODO: "--profile=cum", to change sort order. Is there any value in leaving
28
# the profile output behind so it can be interactively examined?
45
32
from warnings import warn
46
33
from inspect import getdoc
49
37
import bzrlib.trace
50
38
from bzrlib.trace import mutter, note, log_error, warning
51
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
39
from bzrlib.errors import (BzrError,
52
44
from bzrlib.revisionspec import RevisionSpec
53
45
from bzrlib import BZRDIR
46
from bzrlib.option import Option
58
def register_command(cmd):
51
def register_command(cmd, decorate=False):
59
52
"Utility function to help register a command"
80
79
return cmd[4:].replace('_','-')
83
def _parse_revision_str(revstr):
84
"""This handles a revision string -> revno.
86
This always returns a list. The list will have one element for
89
>>> _parse_revision_str('234')
90
[<RevisionSpec_int 234>]
91
>>> _parse_revision_str('234..567')
92
[<RevisionSpec_int 234>, <RevisionSpec_int 567>]
93
>>> _parse_revision_str('..')
94
[<RevisionSpec None>, <RevisionSpec None>]
95
>>> _parse_revision_str('..234')
96
[<RevisionSpec None>, <RevisionSpec_int 234>]
97
>>> _parse_revision_str('234..')
98
[<RevisionSpec_int 234>, <RevisionSpec None>]
99
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
100
[<RevisionSpec_int 234>, <RevisionSpec_int 456>, <RevisionSpec_int 789>]
101
>>> _parse_revision_str('234....789') # Error?
102
[<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
103
>>> _parse_revision_str('revid:test@other.com-234234')
104
[<RevisionSpec_revid revid:test@other.com-234234>]
105
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
106
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
107
>>> _parse_revision_str('revid:test@other.com-234234..23')
108
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_int 23>]
109
>>> _parse_revision_str('date:2005-04-12')
110
[<RevisionSpec_date date:2005-04-12>]
111
>>> _parse_revision_str('date:2005-04-12 12:24:33')
112
[<RevisionSpec_date date:2005-04-12 12:24:33>]
113
>>> _parse_revision_str('date:2005-04-12T12:24:33')
114
[<RevisionSpec_date date:2005-04-12T12:24:33>]
115
>>> _parse_revision_str('date:2005-04-12,12:24:33')
116
[<RevisionSpec_date date:2005-04-12,12:24:33>]
117
>>> _parse_revision_str('-5..23')
118
[<RevisionSpec_int -5>, <RevisionSpec_int 23>]
119
>>> _parse_revision_str('-5')
120
[<RevisionSpec_int -5>]
121
>>> _parse_revision_str('123a')
122
Traceback (most recent call last):
124
BzrError: No namespace registered for string: '123a'
125
>>> _parse_revision_str('abc')
126
Traceback (most recent call last):
128
BzrError: No namespace registered for string: 'abc'
131
old_format_re = re.compile('\d*:\d*')
132
m = old_format_re.match(revstr)
135
warning('Colon separator for revision numbers is deprecated.'
137
for rev in revstr.split(':'):
139
revs.append(RevisionSpec(int(rev)))
141
revs.append(RevisionSpec(None))
143
for x in revstr.split('..'):
145
revs.append(RevisionSpec(None))
147
revs.append(RevisionSpec(x))
151
82
def _builtin_commands():
152
83
import bzrlib.builtins
237
168
List of argument forms, marked with whether they are optional,
173
['to_location', 'from_branch?', 'file*']
175
'to_location' is required
176
'from_branch' is optional
177
'file' can be specified 0 or more times
241
List of options that may be given for this command.
180
List of options that may be given for this command. These can
181
be either strings, referring to globally-defined options,
182
or option objects. Retrieve through options().
244
185
If true, this command isn't advertised. This is typically
245
186
for commands intended for expert users.
250
190
takes_options = []
256
196
if self.__doc__ == Command.__doc__:
257
197
warn("No help message set for %r" % self)
200
"""Return dict of valid options for this command.
202
Maps from long option name to option object."""
204
r['help'] = Option.OPTIONS['help']
205
for o in self.takes_options:
206
if not isinstance(o, Option):
207
o = Option.OPTIONS[o]
260
211
def run_argv(self, argv):
261
212
"""Parse command line and run."""
262
args, opts = parse_args(argv)
213
args, opts = parse_args(self, argv)
264
214
if 'help' in opts: # e.g. bzr add --help
265
215
from bzrlib.help import help_on_command
266
216
help_on_command(self.name())
269
# check options are reasonable
270
allowed = self.takes_options
218
# XXX: This should be handled by the parser
219
allowed_names = self.options().keys()
271
220
for oname in opts:
272
if oname not in allowed:
221
if oname not in allowed_names:
273
222
raise BzrCommandError("option '--%s' is not allowed for command %r"
274
223
% (oname, self.name()))
276
224
# mix arguments and options into one dictionary
277
225
cmdargs = _match_argform(self.name(), self.takes_args, args)
339
286
parsed = [spec, None]
343
# list of all available options; the rhs can be either None for an
344
# option that takes no argument, or a constructor function that checks
358
'revision': _parse_revision_str,
383
def parse_args(argv):
289
def parse_args(command, argv):
384
290
"""Parse command line.
386
292
Arguments and options are parsed at this level before being passed
387
293
down to specific command handlers. This routine knows, from a
388
294
lookup table, something about the available options, what optargs
389
295
they take, and which commands will accept them.
391
>>> parse_args('--help'.split())
393
>>> parse_args('help -- --invalidcmd'.split())
394
(['help', '--invalidcmd'], {})
395
>>> parse_args('--version'.split())
396
([], {'version': True})
397
>>> parse_args('status --all'.split())
398
(['status'], {'all': True})
399
>>> parse_args('commit --message=biter'.split())
400
(['commit'], {'message': u'biter'})
401
>>> parse_args('log -r 500'.split())
402
(['log'], {'revision': [<RevisionSpec_int 500>]})
403
>>> parse_args('log -r500..600'.split())
404
(['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
405
>>> parse_args('log -vr500..600'.split())
406
(['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
407
>>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
408
(['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
297
# TODO: chop up this beast; make it a method of the Command
301
cmd_options = command.options()
416
if not argsover and a[0] == '-':
309
# We've received a standalone -- No more flags
417
313
# option names must not be unicode
422
# We've received a standalone -- No more flags
425
mutter(" got option %r" % a)
317
mutter(" got option %r", a)
427
319
optname, optarg = a[2:].split('=', 1)
430
if optname not in OPTIONS:
431
raise BzrError('unknown long option %r' % a)
322
if optname not in cmd_options:
323
raise BzrOptionError('unknown long option %r for command %s'
324
% (a, command.name()))
434
if shortopt in SHORT_OPTIONS:
327
if shortopt in Option.SHORT_OPTIONS:
435
328
# Multi-character options must have a space to delimit
437
optname = SHORT_OPTIONS[shortopt]
330
# ^^^ what does this mean? mbp 20051014
331
optname = Option.SHORT_OPTIONS[shortopt].name
439
333
# Single character short options, can be chained,
440
334
# and have their value appended to their name
441
335
shortopt = a[1:2]
442
if shortopt not in SHORT_OPTIONS:
336
if shortopt not in Option.SHORT_OPTIONS:
443
337
# We didn't find the multi-character name, and we
444
338
# didn't find the single char name
445
339
raise BzrError('unknown short option %r' % a)
446
optname = SHORT_OPTIONS[shortopt]
340
optname = Option.SHORT_OPTIONS[shortopt].name
449
343
# There are extra things on this option
450
344
# see if it is the value, or if it is another
452
optargfn = OPTIONS[optname]
346
optargfn = Option.OPTIONS[optname].type
453
347
if optargfn is None:
454
348
# This option does not take an argument, so the
455
349
# next entry is another short option, pack it back
639
545
def run_bzr_catch_errors(argv):
645
# do this here inside the exception wrappers to catch EPIPE
647
#wrap common errors as CommandErrors.
648
except (NotBranchError,), e:
649
raise BzrCommandError(str(e))
650
except BzrCommandError, e:
651
# command line syntax error, etc
655
bzrlib.trace.log_exception()
657
except AssertionError, e:
658
bzrlib.trace.log_exception('assertion failed: ' + str(e))
660
except KeyboardInterrupt, e:
661
bzrlib.trace.log_exception('interrupted')
550
# do this here inside the exception wrappers to catch EPIPE
663
552
except Exception, e:
553
# used to handle AssertionError and KeyboardInterrupt
554
# specially here, but hopefully they're handled ok by the logger now
665
556
if (isinstance(e, IOError)
666
557
and hasattr(e, 'errno')
667
558
and e.errno == errno.EPIPE):
668
559
bzrlib.trace.note('broken pipe')
671
562
bzrlib.trace.log_exception()
563
if os.environ.get('BZR_PDB'):
564
print '**** entering debugger'
566
pdb.post_mortem(sys.exc_traceback)
674
569
if __name__ == '__main__':
675
570
sys.exit(main(sys.argv))