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
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
39
from bzrlib.errors import (BzrError,
44
from bzrlib.revisionspec import RevisionSpec
36
from bzrlib.trace import mutter, note, log_error, warning
37
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
38
from bzrlib.branch import find_branch
45
39
from bzrlib import BZRDIR
46
from bzrlib.option import Option
51
def register_command(cmd, decorate=False):
44
def register_command(cmd):
52
45
"Utility function to help register a command"
79
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)
82
153
def _builtin_commands():
83
154
import bzrlib.builtins
168
239
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().
243
List of options that may be given for this command.
185
246
If true, this command isn't advertised. This is typically
186
247
for commands intended for expert users.
190
252
takes_options = []
196
258
if self.__doc__ == Command.__doc__:
197
259
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
262
def run_argv(self, argv):
212
263
"""Parse command line and run."""
213
args, opts = parse_args(self, argv)
264
args, opts = parse_args(argv)
214
266
if 'help' in opts: # e.g. bzr add --help
215
267
from bzrlib.help import help_on_command
216
268
help_on_command(self.name())
218
# XXX: This should be handled by the parser
219
allowed_names = self.options().keys()
271
# check options are reasonable
272
allowed = self.takes_options
220
273
for oname in opts:
221
if oname not in allowed_names:
274
if oname not in allowed:
222
275
raise BzrCommandError("option '--%s' is not allowed for command %r"
223
276
% (oname, self.name()))
224
278
# mix arguments and options into one dictionary
225
279
cmdargs = _match_argform(self.name(), self.takes_args, args)
286
341
parsed = [spec, None]
289
def parse_args(command, argv):
347
# list of all available options; the rhs can be either None for an
348
# option that takes no argument, or a constructor function that checks
361
'revision': _parse_revision_str,
373
'merge-type': get_merge_type,
387
def parse_args(argv):
290
388
"""Parse command line.
292
390
Arguments and options are parsed at this level before being passed
293
391
down to specific command handlers. This routine knows, from a
294
392
lookup table, something about the available options, what optargs
295
393
they take, and which commands will accept them.
395
>>> parse_args('--help'.split())
397
>>> parse_args('help -- --invalidcmd'.split())
398
(['help', '--invalidcmd'], {})
399
>>> parse_args('--version'.split())
400
([], {'version': True})
401
>>> parse_args('status --all'.split())
402
(['status'], {'all': True})
403
>>> parse_args('commit --message=biter'.split())
404
(['commit'], {'message': u'biter'})
405
>>> parse_args('log -r 500'.split())
406
(['log'], {'revision': [500]})
407
>>> parse_args('log -r500..600'.split())
408
(['log'], {'revision': [500, 600]})
409
>>> parse_args('log -vr500..600'.split())
410
(['log'], {'verbose': True, 'revision': [500, 600]})
411
>>> parse_args('log -rv500..600'.split()) #the r takes an argument
412
(['log'], {'revision': ['v500', 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
420
if not argsover and a[0] == '-':
313
421
# option names must not be unicode
317
mutter(" got option %r", a)
426
# We've received a standalone -- No more flags
429
mutter(" got option %r" % a)
319
431
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()))
434
if optname not in OPTIONS:
435
raise BzrError('unknown long option %r' % a)
327
if shortopt in Option.SHORT_OPTIONS:
438
if shortopt in SHORT_OPTIONS:
328
439
# Multi-character options must have a space to delimit
330
# ^^^ what does this mean? mbp 20051014
331
optname = Option.SHORT_OPTIONS[shortopt].name
441
optname = SHORT_OPTIONS[shortopt]
333
443
# Single character short options, can be chained,
334
444
# and have their value appended to their name
335
445
shortopt = a[1:2]
336
if shortopt not in Option.SHORT_OPTIONS:
446
if shortopt not in SHORT_OPTIONS:
337
447
# We didn't find the multi-character name, and we
338
448
# didn't find the single char name
339
449
raise BzrError('unknown short option %r' % a)
340
optname = Option.SHORT_OPTIONS[shortopt].name
450
optname = SHORT_OPTIONS[shortopt]
343
453
# There are extra things on this option
344
454
# see if it is the value, or if it is another
346
optargfn = Option.OPTIONS[optname].type
456
optargfn = OPTIONS[optname]
347
457
if optargfn is None:
348
458
# This option does not take an argument, so the
349
459
# next entry is another short option, pack it back
435
543
ret = prof.runcall(the_callable, *args, **kwargs) or 0
438
548
stats = hotshot.stats.load(pfname)
440
stats.sort_stats('cum') # 'time'
550
stats.sort_stats('time')
441
551
## XXX: Might like to write to stderr or the trace file instead but
442
552
## print_stats seems hardcoded to stdout
443
553
stats.print_stats(20)
446
557
os.close(pffileno)
447
558
os.remove(pfname)
450
def apply_lsprofiled(the_callable, *args, **kwargs):
451
from bzrlib.lsprof import profile
452
ret,stats = profile(the_callable,*args,**kwargs)
457
561
def run_bzr(argv):
458
562
"""Execute a command.
520
618
if not opt_no_plugins:
521
619
from bzrlib.plugin import load_plugins
524
from bzrlib.plugin import disable_plugins
527
622
cmd = str(argv.pop(0))
529
624
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
533
ret = apply_lsprofiled(cmd_obj.run_argv, argv)
535
ret = apply_profiled(cmd_obj.run_argv, argv)
537
ret = cmd_obj.run_argv(argv)
540
# reset, in case we may do other commands later within the same process
543
def display_command(func):
544
"""Decorator that suppresses pipe/interrupt errors."""
545
def ignore_pipe(*args, **kwargs):
547
result = func(*args, **kwargs)
551
if not hasattr(e, 'errno'):
553
if e.errno != errno.EPIPE:
556
except KeyboardInterrupt:
627
ret = apply_profiled(cmd_obj.run_argv, argv)
629
ret = cmd_obj.run_argv(argv)
563
from bzrlib.ui.text import TextUIFactory
564
## bzrlib.trace.enable_default_logging()
565
635
bzrlib.trace.log_startup(argv)
566
bzrlib.ui.ui_factory = TextUIFactory()
567
ret = run_bzr_catch_errors(argv[1:])
568
mutter("return code %d", ret)
572
def run_bzr_catch_errors(argv):
636
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
640
return run_bzr(argv[1:])
577
642
# do this here inside the exception wrappers to catch EPIPE
578
643
sys.stdout.flush()
644
except BzrCommandError, e:
645
# command line syntax error, etc
649
bzrlib.trace.log_exception()
651
except AssertionError, e:
652
bzrlib.trace.log_exception('assertion failed: ' + str(e))
654
except KeyboardInterrupt, e:
655
bzrlib.trace.note('interrupted')
579
657
except Exception, e:
580
# used to handle AssertionError and KeyboardInterrupt
581
# specially here, but hopefully they're handled ok by the logger now
583
659
if (isinstance(e, IOError)
584
660
and hasattr(e, 'errno')
585
661
and e.errno == errno.EPIPE):
586
662
bzrlib.trace.note('broken pipe')
589
665
bzrlib.trace.log_exception()
590
if os.environ.get('BZR_PDB'):
591
print '**** entering debugger'
593
pdb.post_mortem(sys.exc_traceback)
596
669
if __name__ == '__main__':
597
670
sys.exit(main(sys.argv))