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