24
24
# Those objects can specify the expected type of the argument, which
25
25
# 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?
32
31
from warnings import warn
33
32
from inspect import getdoc
37
35
import bzrlib.trace
38
36
from bzrlib.trace import mutter, note, log_error, warning
39
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
40
from bzrlib.revisionspec import RevisionSpec
37
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
38
from bzrlib.branch import find_branch
41
39
from bzrlib import BZRDIR
42
from bzrlib.option import Option
69
66
return cmd[4:].replace('_','-')
69
def _parse_revision_str(revstr):
70
"""This handles a revision string -> revno.
72
This always returns a list. The list will have one element for
74
It supports integers directly, but everything else it
75
defers for passing to Branch.get_revision_info()
77
>>> _parse_revision_str('234')
79
>>> _parse_revision_str('234..567')
81
>>> _parse_revision_str('..')
83
>>> _parse_revision_str('..234')
85
>>> _parse_revision_str('234..')
87
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
89
>>> _parse_revision_str('234....789') # Error?
91
>>> _parse_revision_str('revid:test@other.com-234234')
92
['revid:test@other.com-234234']
93
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
94
['revid:test@other.com-234234', 'revid:test@other.com-234235']
95
>>> _parse_revision_str('revid:test@other.com-234234..23')
96
['revid:test@other.com-234234', 23]
97
>>> _parse_revision_str('date:2005-04-12')
99
>>> _parse_revision_str('date:2005-04-12 12:24:33')
100
['date:2005-04-12 12:24:33']
101
>>> _parse_revision_str('date:2005-04-12T12:24:33')
102
['date:2005-04-12T12:24:33']
103
>>> _parse_revision_str('date:2005-04-12,12:24:33')
104
['date:2005-04-12,12:24:33']
105
>>> _parse_revision_str('-5..23')
107
>>> _parse_revision_str('-5')
109
>>> _parse_revision_str('123a')
111
>>> _parse_revision_str('abc')
115
old_format_re = re.compile('\d*:\d*')
116
m = old_format_re.match(revstr)
118
warning('Colon separator for revision numbers is deprecated.'
121
for rev in revstr.split(':'):
123
revs.append(int(rev))
128
for x in revstr.split('..'):
139
def get_merge_type(typestring):
140
"""Attempt to find the merge class/factory associated with a string."""
141
from merge import merge_types
143
return merge_types[typestring][0]
145
templ = '%s%%7s: %%s' % (' '*12)
146
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
147
type_list = '\n'.join(lines)
148
msg = "No known merge type %s. Supported types are:\n%s" %\
149
(typestring, type_list)
150
raise BzrCommandError(msg)
153
def get_merge_type(typestring):
154
"""Attempt to find the merge class/factory associated with a string."""
155
from merge import merge_types
157
return merge_types[typestring][0]
159
templ = '%s%%7s: %%s' % (' '*12)
160
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
161
type_list = '\n'.join(lines)
162
msg = "No known merge type %s. Supported types are:\n%s" %\
163
(typestring, type_list)
164
raise BzrCommandError(msg)
72
167
def _builtin_commands():
73
168
import bzrlib.builtins
178
272
if self.__doc__ == Command.__doc__:
179
273
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]
193
276
def run_argv(self, argv):
194
277
"""Parse command line and run."""
195
args, opts = parse_args(self, argv)
278
args, opts = parse_args(argv)
196
280
if 'help' in opts: # e.g. bzr add --help
197
281
from bzrlib.help import help_on_command
198
282
help_on_command(self.name())
200
# XXX: This should be handled by the parser
201
allowed_names = self.options().keys()
285
# check options are reasonable
286
allowed = self.takes_options
202
287
for oname in opts:
203
if oname not in allowed_names:
288
if oname not in allowed:
204
289
raise BzrCommandError("option '--%s' is not allowed for command %r"
205
290
% (oname, self.name()))
206
292
# mix arguments and options into one dictionary
207
293
cmdargs = _match_argform(self.name(), self.takes_args, args)
268
355
parsed = [spec, None]
271
def parse_args(command, argv):
361
# list of all available options; the rhs can be either None for an
362
# option that takes no argument, or a constructor function that checks
375
'revision': _parse_revision_str,
387
'merge-type': get_merge_type,
401
def parse_args(argv):
272
402
"""Parse command line.
274
404
Arguments and options are parsed at this level before being passed
275
405
down to specific command handlers. This routine knows, from a
276
406
lookup table, something about the available options, what optargs
277
407
they take, and which commands will accept them.
409
>>> parse_args('--help'.split())
411
>>> parse_args('help -- --invalidcmd'.split())
412
(['help', '--invalidcmd'], {})
413
>>> parse_args('--version'.split())
414
([], {'version': True})
415
>>> parse_args('status --all'.split())
416
(['status'], {'all': True})
417
>>> parse_args('commit --message=biter'.split())
418
(['commit'], {'message': u'biter'})
419
>>> parse_args('log -r 500'.split())
420
(['log'], {'revision': [500]})
421
>>> parse_args('log -r500..600'.split())
422
(['log'], {'revision': [500, 600]})
423
>>> parse_args('log -vr500..600'.split())
424
(['log'], {'verbose': True, 'revision': [500, 600]})
425
>>> parse_args('log -rv500..600'.split()) #the r takes an argument
426
(['log'], {'revision': ['v500', 600]})
279
# TODO: chop up this beast; make it a method of the Command
283
cmd_options = command.options()
291
# We've received a standalone -- No more flags
434
if not argsover and a[0] == '-':
295
435
# option names must not be unicode
440
# We've received a standalone -- No more flags
299
443
mutter(" got option %r" % a)
301
445
optname, optarg = a[2:].split('=', 1)
304
if optname not in cmd_options:
305
raise BzrCommandError('unknown long option %r for command %s'
306
% (a, command.name()))
448
if optname not in OPTIONS:
449
raise BzrError('unknown long option %r' % a)
309
if shortopt in Option.SHORT_OPTIONS:
452
if shortopt in SHORT_OPTIONS:
310
453
# Multi-character options must have a space to delimit
312
# ^^^ what does this mean? mbp 20051014
313
optname = Option.SHORT_OPTIONS[shortopt].name
455
optname = SHORT_OPTIONS[shortopt]
315
457
# Single character short options, can be chained,
316
458
# and have their value appended to their name
317
459
shortopt = a[1:2]
318
if shortopt not in Option.SHORT_OPTIONS:
460
if shortopt not in SHORT_OPTIONS:
319
461
# We didn't find the multi-character name, and we
320
462
# didn't find the single char name
321
463
raise BzrError('unknown short option %r' % a)
322
optname = Option.SHORT_OPTIONS[shortopt].name
464
optname = SHORT_OPTIONS[shortopt]
325
467
# There are extra things on this option
326
468
# see if it is the value, or if it is another
328
optargfn = Option.OPTIONS[optname].type
470
optargfn = OPTIONS[optname]
329
471
if optargfn is None:
330
472
# This option does not take an argument, so the
331
473
# next entry is another short option, pack it back
496
643
ret = cmd_obj.run_argv(argv)
499
def display_command(func):
500
def ignore_pipe(*args, **kwargs):
502
return func(*args, **kwargs)
504
if e.errno != errno.EPIPE:
506
except KeyboardInterrupt:
512
649
bzrlib.trace.log_startup(argv)
513
650
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
515
return run_bzr_catch_errors(argv[1:])
518
def run_bzr_catch_errors(argv):
654
return run_bzr(argv[1:])
523
656
# do this here inside the exception wrappers to catch EPIPE
524
657
sys.stdout.flush()