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
43
from bzrlib.trace import mutter, note, log_error, warning
44
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
38
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
39
from bzrlib.errors import (BzrError,
45
44
from bzrlib.revisionspec import RevisionSpec
46
45
from bzrlib import BZRDIR
46
from bzrlib.option import Option
51
def register_command(cmd):
51
def register_command(cmd, decorate=False):
52
52
"Utility function to help register a command"
73
79
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
82
def _builtin_commands():
159
83
import bzrlib.builtins
244
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
248
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().
251
185
If true, this command isn't advertised. This is typically
252
186
for commands intended for expert users.
257
190
takes_options = []
263
196
if self.__doc__ == Command.__doc__:
264
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]
267
211
def run_argv(self, argv):
268
212
"""Parse command line and run."""
269
args, opts = parse_args(argv)
213
args, opts = parse_args(self, argv)
271
214
if 'help' in opts: # e.g. bzr add --help
272
215
from bzrlib.help import help_on_command
273
216
help_on_command(self.name())
276
# check options are reasonable
277
allowed = self.takes_options
218
# XXX: This should be handled by the parser
219
allowed_names = self.options().keys()
278
220
for oname in opts:
279
if oname not in allowed:
221
if oname not in allowed_names:
280
222
raise BzrCommandError("option '--%s' is not allowed for command %r"
281
223
% (oname, self.name()))
283
224
# mix arguments and options into one dictionary
284
225
cmdargs = _match_argform(self.name(), self.takes_args, args)
346
286
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):
289
def parse_args(command, argv):
391
290
"""Parse command line.
393
292
Arguments and options are parsed at this level before being passed
394
293
down to specific command handlers. This routine knows, from a
395
294
lookup table, something about the available options, what optargs
396
295
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>]})
297
# TODO: chop up this beast; make it a method of the Command
301
cmd_options = command.options()
423
if not argsover and a[0] == '-':
309
# We've received a standalone -- No more flags
424
313
# option names must not be unicode
429
# We've received a standalone -- No more flags
432
mutter(" got option %r" % a)
317
mutter(" got option %r", a)
434
319
optname, optarg = a[2:].split('=', 1)
437
if optname not in OPTIONS:
438
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()))
441
if shortopt in SHORT_OPTIONS:
327
if shortopt in Option.SHORT_OPTIONS:
442
328
# Multi-character options must have a space to delimit
444
optname = SHORT_OPTIONS[shortopt]
330
# ^^^ what does this mean? mbp 20051014
331
optname = Option.SHORT_OPTIONS[shortopt].name
446
333
# Single character short options, can be chained,
447
334
# and have their value appended to their name
448
335
shortopt = a[1:2]
449
if shortopt not in SHORT_OPTIONS:
336
if shortopt not in Option.SHORT_OPTIONS:
450
337
# We didn't find the multi-character name, and we
451
338
# didn't find the single char name
452
339
raise BzrError('unknown short option %r' % a)
453
optname = SHORT_OPTIONS[shortopt]
340
optname = Option.SHORT_OPTIONS[shortopt].name
456
343
# There are extra things on this option
457
344
# see if it is the value, or if it is another
459
optargfn = OPTIONS[optname]
346
optargfn = Option.OPTIONS[optname].type
460
347
if optargfn is None:
461
348
# This option does not take an argument, so the
462
349
# next entry is another short option, pack it back
627
514
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
630
ret = apply_profiled(cmd_obj.run_argv, argv)
632
ret = cmd_obj.run_argv(argv)
518
ret = apply_profiled(cmd_obj.run_argv, argv)
520
ret = cmd_obj.run_argv(argv)
523
# reset, in case we may do other commands later within the same process
526
def display_command(func):
527
"""Decorator that suppresses pipe/interrupt errors."""
528
def ignore_pipe(*args, **kwargs):
530
result = func(*args, **kwargs)
534
if not hasattr(e, 'errno'):
536
if e.errno != errno.EPIPE:
539
except KeyboardInterrupt:
546
from bzrlib.ui.text import TextUIFactory
547
## bzrlib.trace.enable_default_logging()
638
548
bzrlib.trace.log_startup(argv)
639
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
641
return run_bzr_catch_errors(argv[1:])
549
bzrlib.ui.ui_factory = TextUIFactory()
550
ret = run_bzr_catch_errors(argv[1:])
551
mutter("return code %d", ret)
644
555
def run_bzr_catch_errors(argv):
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')
560
# do this here inside the exception wrappers to catch EPIPE
668
562
except Exception, e:
563
# used to handle AssertionError and KeyboardInterrupt
564
# specially here, but hopefully they're handled ok by the logger now
670
566
if (isinstance(e, IOError)
671
567
and hasattr(e, 'errno')
672
568
and e.errno == errno.EPIPE):
673
569
bzrlib.trace.note('broken pipe')
676
572
bzrlib.trace.log_exception()
573
if os.environ.get('BZR_PDB'):
574
print '**** entering debugger'
576
pdb.post_mortem(sys.exc_traceback)
680
579
if __name__ == '__main__':
681
580
sys.exit(main(sys.argv))