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.
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?
38
32
from warnings import warn
39
33
from inspect import getdoc
42
37
import bzrlib.trace
73
69
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)
158
72
def _builtin_commands():
159
73
import bzrlib.builtins
263
178
if self.__doc__ == Command.__doc__:
264
179
warn("No help message set for %r" % self)
182
"""Return dict of valid options for this command.
184
Maps from long option name to option object."""
186
r['help'] = Option.OPTIONS['help']
187
for o in self.takes_options:
188
if not isinstance(o, Option):
189
o = Option.OPTIONS[o]
267
193
def run_argv(self, argv):
268
194
"""Parse command line and run."""
269
args, opts = parse_args(argv)
195
args, opts = parse_args(self, argv)
271
196
if 'help' in opts: # e.g. bzr add --help
272
197
from bzrlib.help import help_on_command
273
198
help_on_command(self.name())
276
# check options are reasonable
277
allowed = self.takes_options
200
# XXX: This should be handled by the parser
201
allowed_names = self.options().keys()
278
202
for oname in opts:
279
if oname not in allowed:
203
if oname not in allowed_names:
280
204
raise BzrCommandError("option '--%s' is not allowed for command %r"
281
205
% (oname, self.name()))
283
206
# mix arguments and options into one dictionary
284
207
cmdargs = _match_argform(self.name(), self.takes_args, args)
346
269
parsed = [spec, 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):
272
def parse_args(command, argv):
391
273
"""Parse command line.
393
275
Arguments and options are parsed at this level before being passed
394
276
down to specific command handlers. This routine knows, from a
395
277
lookup table, something about the available options, what optargs
396
278
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>]})
280
# TODO: chop up this beast; make it a method of the Command
284
cmd_options = command.options()
423
if not argsover and a[0] == '-':
292
# We've received a standalone -- No more flags
424
296
# option names must not be unicode
429
# We've received a standalone -- No more flags
432
300
mutter(" got option %r" % a)
434
302
optname, optarg = a[2:].split('=', 1)
437
if optname not in OPTIONS:
438
raise BzrError('unknown long option %r' % a)
305
if optname not in cmd_options:
306
raise BzrCommandError('unknown long option %r for command %s'
307
% (a, command.name()))
441
if shortopt in SHORT_OPTIONS:
310
if shortopt in Option.SHORT_OPTIONS:
442
311
# Multi-character options must have a space to delimit
444
optname = SHORT_OPTIONS[shortopt]
313
# ^^^ what does this mean? mbp 20051014
314
optname = Option.SHORT_OPTIONS[shortopt].name
446
316
# Single character short options, can be chained,
447
317
# and have their value appended to their name
448
318
shortopt = a[1:2]
449
if shortopt not in SHORT_OPTIONS:
319
if shortopt not in Option.SHORT_OPTIONS:
450
320
# We didn't find the multi-character name, and we
451
321
# didn't find the single char name
452
322
raise BzrError('unknown short option %r' % a)
453
optname = SHORT_OPTIONS[shortopt]
323
optname = Option.SHORT_OPTIONS[shortopt].name
456
326
# There are extra things on this option
457
327
# see if it is the value, or if it is another
459
optargfn = OPTIONS[optname]
329
optargfn = Option.OPTIONS[optname].type
460
330
if optargfn is None:
461
331
# This option does not take an argument, so the
462
332
# next entry is another short option, pack it back