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?
31
32
from warnings import warn
32
33
from inspect import getdoc
35
37
import bzrlib.trace
36
from bzrlib.trace import mutter, note, log_error, warning
37
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
38
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
39
from bzrlib.errors import (BzrError,
38
44
from bzrlib.revisionspec import RevisionSpec
39
45
from bzrlib import BZRDIR
46
from bzrlib.option import Option
44
def register_command(cmd):
51
def register_command(cmd, decorate=False):
45
52
"Utility function to help register a command"
66
79
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
75
>>> _parse_revision_str('234')
76
[<RevisionSpec_int 234>]
77
>>> _parse_revision_str('234..567')
78
[<RevisionSpec_int 234>, <RevisionSpec_int 567>]
79
>>> _parse_revision_str('..')
80
[<RevisionSpec None>, <RevisionSpec None>]
81
>>> _parse_revision_str('..234')
82
[<RevisionSpec None>, <RevisionSpec_int 234>]
83
>>> _parse_revision_str('234..')
84
[<RevisionSpec_int 234>, <RevisionSpec None>]
85
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
86
[<RevisionSpec_int 234>, <RevisionSpec_int 456>, <RevisionSpec_int 789>]
87
>>> _parse_revision_str('234....789') # Error?
88
[<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
89
>>> _parse_revision_str('revid:test@other.com-234234')
90
[<RevisionSpec_revid revid:test@other.com-234234>]
91
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
92
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
93
>>> _parse_revision_str('revid:test@other.com-234234..23')
94
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_int 23>]
95
>>> _parse_revision_str('date:2005-04-12')
96
[<RevisionSpec_date date:2005-04-12>]
97
>>> _parse_revision_str('date:2005-04-12 12:24:33')
98
[<RevisionSpec_date date:2005-04-12 12:24:33>]
99
>>> _parse_revision_str('date:2005-04-12T12:24:33')
100
[<RevisionSpec_date date:2005-04-12T12:24:33>]
101
>>> _parse_revision_str('date:2005-04-12,12:24:33')
102
[<RevisionSpec_date date:2005-04-12,12:24:33>]
103
>>> _parse_revision_str('-5..23')
104
[<RevisionSpec_int -5>, <RevisionSpec_int 23>]
105
>>> _parse_revision_str('-5')
106
[<RevisionSpec_int -5>]
107
>>> _parse_revision_str('123a')
108
Traceback (most recent call last):
110
BzrError: No namespace registered for string: '123a'
111
>>> _parse_revision_str('abc')
112
Traceback (most recent call last):
114
BzrError: No namespace registered for string: 'abc'
117
old_format_re = re.compile('\d*:\d*')
118
m = old_format_re.match(revstr)
121
warning('Colon separator for revision numbers is deprecated.'
123
for rev in revstr.split(':'):
125
revs.append(RevisionSpec(int(rev)))
127
revs.append(RevisionSpec(None))
129
for x in revstr.split('..'):
131
revs.append(RevisionSpec(None))
133
revs.append(RevisionSpec(x))
137
def get_merge_type(typestring):
138
"""Attempt to find the merge class/factory associated with a string."""
139
from merge import merge_types
141
return merge_types[typestring][0]
143
templ = '%s%%7s: %%s' % (' '*12)
144
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
145
type_list = '\n'.join(lines)
146
msg = "No known merge type %s. Supported types are:\n%s" %\
147
(typestring, type_list)
148
raise BzrCommandError(msg)
151
def get_merge_type(typestring):
152
"""Attempt to find the merge class/factory associated with a string."""
153
from merge import merge_types
155
return merge_types[typestring][0]
157
templ = '%s%%7s: %%s' % (' '*12)
158
lines = [templ % (f[0], f[1][1]) for f in merge_types.iteritems()]
159
type_list = '\n'.join(lines)
160
msg = "No known merge type %s. Supported types are:\n%s" %\
161
(typestring, type_list)
162
raise BzrCommandError(msg)
165
82
def _builtin_commands():
166
83
import bzrlib.builtins
251
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
255
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().
258
185
If true, this command isn't advertised. This is typically
259
186
for commands intended for expert users.
264
190
takes_options = []
270
196
if self.__doc__ == Command.__doc__:
271
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]
274
211
def run_argv(self, argv):
275
212
"""Parse command line and run."""
276
args, opts = parse_args(argv)
213
args, opts = parse_args(self, argv)
278
214
if 'help' in opts: # e.g. bzr add --help
279
215
from bzrlib.help import help_on_command
280
216
help_on_command(self.name())
283
# check options are reasonable
284
allowed = self.takes_options
218
# XXX: This should be handled by the parser
219
allowed_names = self.options().keys()
285
220
for oname in opts:
286
if oname not in allowed:
221
if oname not in allowed_names:
287
222
raise BzrCommandError("option '--%s' is not allowed for command %r"
288
223
% (oname, self.name()))
290
224
# mix arguments and options into one dictionary
291
225
cmdargs = _match_argform(self.name(), self.takes_args, args)
353
286
parsed = [spec, None]
359
# list of all available options; the rhs can be either None for an
360
# option that takes no argument, or a constructor function that checks
373
'revision': _parse_revision_str,
385
'merge-type': get_merge_type,
399
def parse_args(argv):
289
def parse_args(command, argv):
400
290
"""Parse command line.
402
292
Arguments and options are parsed at this level before being passed
403
293
down to specific command handlers. This routine knows, from a
404
294
lookup table, something about the available options, what optargs
405
295
they take, and which commands will accept them.
407
>>> parse_args('--help'.split())
409
>>> parse_args('help -- --invalidcmd'.split())
410
(['help', '--invalidcmd'], {})
411
>>> parse_args('--version'.split())
412
([], {'version': True})
413
>>> parse_args('status --all'.split())
414
(['status'], {'all': True})
415
>>> parse_args('commit --message=biter'.split())
416
(['commit'], {'message': u'biter'})
417
>>> parse_args('log -r 500'.split())
418
(['log'], {'revision': [<RevisionSpec_int 500>]})
419
>>> parse_args('log -r500..600'.split())
420
(['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
421
>>> parse_args('log -vr500..600'.split())
422
(['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
423
>>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
424
(['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()
432
if not argsover and a[0] == '-':
309
# We've received a standalone -- No more flags
433
313
# option names must not be unicode
438
# We've received a standalone -- No more flags
441
mutter(" got option %r" % a)
317
mutter(" got option %r", a)
443
319
optname, optarg = a[2:].split('=', 1)
446
if optname not in OPTIONS:
447
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()))
450
if shortopt in SHORT_OPTIONS:
327
if shortopt in Option.SHORT_OPTIONS:
451
328
# Multi-character options must have a space to delimit
453
optname = SHORT_OPTIONS[shortopt]
330
# ^^^ what does this mean? mbp 20051014
331
optname = Option.SHORT_OPTIONS[shortopt].name
455
333
# Single character short options, can be chained,
456
334
# and have their value appended to their name
457
335
shortopt = a[1:2]
458
if shortopt not in SHORT_OPTIONS:
336
if shortopt not in Option.SHORT_OPTIONS:
459
337
# We didn't find the multi-character name, and we
460
338
# didn't find the single char name
461
339
raise BzrError('unknown short option %r' % a)
462
optname = SHORT_OPTIONS[shortopt]
340
optname = Option.SHORT_OPTIONS[shortopt].name
465
343
# There are extra things on this option
466
344
# see if it is the value, or if it is another
468
optargfn = OPTIONS[optname]
346
optargfn = Option.OPTIONS[optname].type
469
347
if optargfn is None:
470
348
# This option does not take an argument, so the
471
349
# next entry is another short option, pack it back
636
526
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
639
ret = apply_profiled(cmd_obj.run_argv, argv)
641
ret = cmd_obj.run_argv(argv)
530
ret = apply_lsprofiled(cmd_obj.run_argv, argv)
532
ret = apply_profiled(cmd_obj.run_argv, argv)
534
ret = cmd_obj.run_argv(argv)
537
# reset, in case we may do other commands later within the same process
540
def display_command(func):
541
"""Decorator that suppresses pipe/interrupt errors."""
542
def ignore_pipe(*args, **kwargs):
544
result = func(*args, **kwargs)
548
if not hasattr(e, 'errno'):
550
if e.errno != errno.EPIPE:
553
except KeyboardInterrupt:
560
from bzrlib.ui.text import TextUIFactory
561
## bzrlib.trace.enable_default_logging()
647
562
bzrlib.trace.log_startup(argv)
648
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
563
bzrlib.ui.ui_factory = TextUIFactory()
564
ret = run_bzr_catch_errors(argv[1:])
565
mutter("return code %d", ret)
569
def run_bzr_catch_errors(argv):
652
return run_bzr(argv[1:])
654
574
# do this here inside the exception wrappers to catch EPIPE
655
575
sys.stdout.flush()
656
except BzrCommandError, e:
657
# command line syntax error, etc
661
bzrlib.trace.log_exception()
663
except AssertionError, e:
664
bzrlib.trace.log_exception('assertion failed: ' + str(e))
666
except KeyboardInterrupt, e:
667
bzrlib.trace.note('interrupted')
669
576
except Exception, e:
577
# used to handle AssertionError and KeyboardInterrupt
578
# specially here, but hopefully they're handled ok by the logger now
671
580
if (isinstance(e, IOError)
672
581
and hasattr(e, 'errno')
673
582
and e.errno == errno.EPIPE):
674
583
bzrlib.trace.note('broken pipe')
677
586
bzrlib.trace.log_exception()
587
if os.environ.get('BZR_PDB'):
588
print '**** entering debugger'
590
pdb.post_mortem(sys.exc_traceback)
681
593
if __name__ == '__main__':
682
594
sys.exit(main(sys.argv))