33
32
from warnings import warn
33
from inspect import getdoc
38
import bzrlib.errors as errors
39
from bzrlib.errors import (BzrError,
43
from bzrlib.option import Option
37
from bzrlib.trace import mutter, note, log_error, warning
38
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
45
39
from bzrlib.revisionspec import RevisionSpec
46
from bzrlib.symbol_versioning import (deprecated_method, zero_eight)
48
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
40
from bzrlib import BZRDIR
53
def register_command(cmd, decorate=False):
54
"""Utility function to help register a command
56
:param cmd: Command subclass to register
57
:param decorate: If true, allow overriding an existing command
58
of the same name; the old command is returned by this function.
59
Otherwise it is an error to try to override an existing command.
45
def register_command(cmd):
46
"Utility function to help register a command"
63
49
if k.startswith("cmd_"):
87
67
return cmd[4:].replace('_','-')
70
def _parse_revision_str(revstr):
71
"""This handles a revision string -> revno.
73
This always returns a list. The list will have one element for
76
>>> _parse_revision_str('234')
77
[<RevisionSpec_int 234>]
78
>>> _parse_revision_str('234..567')
79
[<RevisionSpec_int 234>, <RevisionSpec_int 567>]
80
>>> _parse_revision_str('..')
81
[<RevisionSpec None>, <RevisionSpec None>]
82
>>> _parse_revision_str('..234')
83
[<RevisionSpec None>, <RevisionSpec_int 234>]
84
>>> _parse_revision_str('234..')
85
[<RevisionSpec_int 234>, <RevisionSpec None>]
86
>>> _parse_revision_str('234..456..789') # Maybe this should be an error
87
[<RevisionSpec_int 234>, <RevisionSpec_int 456>, <RevisionSpec_int 789>]
88
>>> _parse_revision_str('234....789') # Error?
89
[<RevisionSpec_int 234>, <RevisionSpec None>, <RevisionSpec_int 789>]
90
>>> _parse_revision_str('revid:test@other.com-234234')
91
[<RevisionSpec_revid revid:test@other.com-234234>]
92
>>> _parse_revision_str('revid:test@other.com-234234..revid:test@other.com-234235')
93
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_revid revid:test@other.com-234235>]
94
>>> _parse_revision_str('revid:test@other.com-234234..23')
95
[<RevisionSpec_revid revid:test@other.com-234234>, <RevisionSpec_int 23>]
96
>>> _parse_revision_str('date:2005-04-12')
97
[<RevisionSpec_date date:2005-04-12>]
98
>>> _parse_revision_str('date:2005-04-12 12:24:33')
99
[<RevisionSpec_date date:2005-04-12 12:24:33>]
100
>>> _parse_revision_str('date:2005-04-12T12:24:33')
101
[<RevisionSpec_date date:2005-04-12T12:24:33>]
102
>>> _parse_revision_str('date:2005-04-12,12:24:33')
103
[<RevisionSpec_date date:2005-04-12,12:24:33>]
104
>>> _parse_revision_str('-5..23')
105
[<RevisionSpec_int -5>, <RevisionSpec_int 23>]
106
>>> _parse_revision_str('-5')
107
[<RevisionSpec_int -5>]
108
>>> _parse_revision_str('123a')
109
Traceback (most recent call last):
111
BzrError: No namespace registered for string: '123a'
112
>>> _parse_revision_str('abc')
113
Traceback (most recent call last):
115
BzrError: No namespace registered for string: 'abc'
118
old_format_re = re.compile('\d*:\d*')
119
m = old_format_re.match(revstr)
122
warning('Colon separator for revision numbers is deprecated.'
124
for rev in revstr.split(':'):
126
revs.append(RevisionSpec(int(rev)))
128
revs.append(RevisionSpec(None))
130
for x in revstr.split('..'):
132
revs.append(RevisionSpec(None))
134
revs.append(RevisionSpec(x))
90
138
def _builtin_commands():
91
139
import bzrlib.builtins
93
141
builtins = bzrlib.builtins.__dict__
94
142
for name in builtins:
95
143
if name.startswith("cmd_"):
96
real_name = _unsquish_command_name(name)
144
real_name = _unsquish_command_name(name)
97
145
r[real_name] = builtins[name]
101
150
def builtin_command_names():
175
224
List of argument forms, marked with whether they are optional,
180
['to_location', 'from_branch?', 'file*']
182
'to_location' is required
183
'from_branch' is optional
184
'file' can be specified 0 or more times
187
List of options that may be given for this command. These can
188
be either strings, referring to globally-defined options,
189
or option objects. Retrieve through options().
228
List of options that may be given for this command.
192
231
If true, this command isn't advertised. This is typically
193
232
for commands intended for expert users.
196
Command objects will get a 'outf' attribute, which has been
197
setup to properly handle encoding of unicode strings.
198
encoding_type determines what will happen when characters cannot
200
strict - abort if we cannot decode
201
replace - put in a bogus character (typically '?')
202
exact - do not encode sys.stdout
207
237
takes_options = []
208
encoding_type = 'strict'
214
243
if self.__doc__ == Command.__doc__:
215
244
warn("No help message set for %r" % self)
218
"""Return dict of valid options for this command.
220
Maps from long option name to option object."""
222
r['help'] = Option.OPTIONS['help']
223
for o in self.takes_options:
224
if not isinstance(o, Option):
225
o = Option.OPTIONS[o]
229
def _setup_outf(self):
230
"""Return a file linked to stdout, which has proper encoding."""
231
assert self.encoding_type in ['strict', 'exact', 'replace']
233
# Originally I was using self.stdout, but that looks
234
# *way* too much like sys.stdout
235
if self.encoding_type == 'exact':
236
self.outf = sys.stdout
239
output_encoding = bzrlib.osutils.get_terminal_encoding()
241
# use 'replace' so that we don't abort if trying to write out
242
# in e.g. the default C locale.
243
self.outf = codecs.getwriter(output_encoding)(sys.stdout, errors=self.encoding_type)
244
# For whatever reason codecs.getwriter() does not advertise its encoding
245
# it just returns the encoding of the wrapped file, which is completely
246
# bogus. So set the attribute, so we can find the correct encoding later.
247
self.outf.encoding = output_encoding
249
@deprecated_method(zero_eight)
250
247
def run_argv(self, argv):
251
"""Parse command line and run.
253
See run_argv_aliases for the 0.8 and beyond api.
255
return self.run_argv_aliases(argv)
248
"""Parse command line and run."""
249
args, opts = parse_args(argv)
257
def run_argv_aliases(self, argv, alias_argv=None):
258
"""Parse the command line and run with extra aliases in alias_argv."""
259
args, opts = parse_args(self, argv, alias_argv)
260
251
if 'help' in opts: # e.g. bzr add --help
261
252
from bzrlib.help import help_on_command
262
253
help_on_command(self.name())
264
# XXX: This should be handled by the parser
265
allowed_names = self.options().keys()
256
# check options are reasonable
257
allowed = self.takes_options
266
258
for oname in opts:
267
if oname not in allowed_names:
268
raise BzrOptionError("option '--%s' is not allowed for"
269
" command %r" % (oname, self.name()))
259
if oname not in allowed:
260
raise BzrCommandError("option '--%s' is not allowed for command %r"
261
% (oname, self.name()))
270
263
# mix arguments and options into one dictionary
271
264
cmdargs = _match_argform(self.name(), self.takes_args, args)
346
326
parsed = [spec, None]
349
def parse_args(command, argv, alias_argv=None):
330
# list of all available options; the rhs can be either None for an
331
# option that takes no argument, or a constructor function that checks
345
'revision': _parse_revision_str,
370
def parse_args(argv):
350
371
"""Parse command line.
352
373
Arguments and options are parsed at this level before being passed
353
374
down to specific command handlers. This routine knows, from a
354
375
lookup table, something about the available options, what optargs
355
376
they take, and which commands will accept them.
378
>>> parse_args('--help'.split())
380
>>> parse_args('help -- --invalidcmd'.split())
381
(['help', '--invalidcmd'], {})
382
>>> parse_args('--version'.split())
383
([], {'version': True})
384
>>> parse_args('status --all'.split())
385
(['status'], {'all': True})
386
>>> parse_args('commit --message=biter'.split())
387
(['commit'], {'message': u'biter'})
388
>>> parse_args('log -r 500'.split())
389
(['log'], {'revision': [<RevisionSpec_int 500>]})
390
>>> parse_args('log -r500..600'.split())
391
(['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
392
>>> parse_args('log -vr500..600'.split())
393
(['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
394
>>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
395
(['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
357
# TODO: chop up this beast; make it a method of the Command
362
cmd_options = command.options()
364
proc_aliasarg = True # Are we processing alias_argv now?
365
for proc_argv in alias_argv, argv:
375
# We've received a standalone -- No more flags
379
# option names must not be unicode
383
mutter(" got option %r", a)
385
optname, optarg = a[2:].split('=', 1)
388
if optname not in cmd_options:
389
raise BzrCommandError('unknown option "%s"' % a)
392
if shortopt in Option.SHORT_OPTIONS:
393
# Multi-character options must have a space to delimit
395
# ^^^ what does this mean? mbp 20051014
396
optname = Option.SHORT_OPTIONS[shortopt].name
398
# Single character short options, can be chained,
399
# and have their value appended to their name
401
if shortopt not in Option.SHORT_OPTIONS:
402
# We didn't find the multi-character name, and we
403
# didn't find the single char name
404
raise BzrCommandError('unknown option "%s"' % a)
405
optname = Option.SHORT_OPTIONS[shortopt].name
403
if not argsover and a[0] == '-':
404
# option names must not be unicode
409
# We've received a standalone -- No more flags
412
mutter(" got option %r" % a)
414
optname, optarg = a[2:].split('=', 1)
417
if optname not in OPTIONS:
418
raise BzrError('unknown long option %r' % a)
421
if shortopt in SHORT_OPTIONS:
422
# Multi-character options must have a space to delimit
424
optname = SHORT_OPTIONS[shortopt]
426
# Single character short options, can be chained,
427
# and have their value appended to their name
429
if shortopt not in SHORT_OPTIONS:
430
# We didn't find the multi-character name, and we
431
# didn't find the single char name
432
raise BzrError('unknown short option %r' % a)
433
optname = SHORT_OPTIONS[shortopt]
408
# There are extra things on this option
409
# see if it is the value, or if it is another
411
optargfn = Option.OPTIONS[optname].type
413
# This option does not take an argument, so the
414
# next entry is another short option, pack it
416
proc_argv.insert(0, '-' + a[2:])
418
# This option takes an argument, so pack it
421
if optname not in cmd_options:
422
raise BzrCommandError('unknown option "%s"' % shortopt)
424
# XXX: Do we ever want to support this, e.g. for -r?
426
raise BzrCommandError('repeated option %r' % a)
427
elif optname in alias_opts:
428
# Replace what's in the alias with what's in the real
430
del alias_opts[optname]
432
proc_argv.insert(0, a)
435
raise BzrCommandError('repeated option %r' % a)
437
option_obj = cmd_options[optname]
438
optargfn = option_obj.type
442
raise BzrCommandError('option %r needs an argument' % a)
436
# There are extra things on this option
437
# see if it is the value, or if it is another
439
optargfn = OPTIONS[optname]
441
# This option does not take an argument, so the
442
# next entry is another short option, pack it back
444
argv.insert(0, '-' + a[2:])
444
optarg = proc_argv.pop(0)
445
opts[optname] = optargfn(optarg)
447
alias_opts[optname] = optargfn(optarg)
450
raise BzrCommandError('option %r takes no argument' % optname)
453
alias_opts[optname] = True
446
# This option takes an argument, so pack it
451
# XXX: Do we ever want to support this, e.g. for -r?
452
raise BzrError('repeated option %r' % a)
454
optargfn = OPTIONS[optname]
458
raise BzrError('option %r needs an argument' % a)
461
opts[optname] = optargfn(optarg)
456
proc_aliasarg = False # Done with alias argv
464
raise BzrError('option %r takes no argument' % optname)
457
469
return args, opts
460
474
def _match_argform(cmd, takes_args, args):
568
557
Do not load plugin modules at all
574
560
Only use builtin commands. (Plugins are still allowed to change
575
561
other behaviour.)
578
Run under the Python hotshot profiler.
581
Run under the Python lsprof profiler.
564
Run under the Python profiler.
566
# Load all of the transport methods
567
import bzrlib.transport.local, bzrlib.transport.http
569
argv = [a.decode(bzrlib.user_encoding) for a in argv]
585
opt_lsprof = opt_profile = opt_no_plugins = opt_builtin = \
586
opt_no_aliases = False
587
opt_lsprof_file = None
571
opt_profile = opt_no_plugins = opt_builtin = False
589
573
# --no-plugins is handled specially at a very early stage. We need
590
574
# to load plugins before doing other command parsing so that they
591
575
# can override commands, but this needs to happen first.
597
578
if a == '--profile':
598
579
opt_profile = True
599
elif a == '--lsprof':
601
elif a == '--lsprof-file':
603
opt_lsprof_file = argv[i + 1]
605
580
elif a == '--no-plugins':
606
581
opt_no_plugins = True
607
elif a == '--no-aliases':
608
opt_no_aliases = True
609
582
elif a == '--builtin':
610
583
opt_builtin = True
611
elif a in ('--quiet', '-q'):
619
from bzrlib.builtins import cmd_help
620
cmd_help().run_argv_aliases([])
588
if (not argv) or (argv[0] == '--help'):
589
from bzrlib.help import help
623
596
if argv[0] == '--version':
628
601
if not opt_no_plugins:
629
602
from bzrlib.plugin import load_plugins
632
from bzrlib.plugin import disable_plugins
637
if not opt_no_aliases:
638
alias_argv = get_alias(argv[0])
640
alias_argv = [a.decode(bzrlib.user_encoding) for a in alias_argv]
641
argv[0] = alias_argv.pop(0)
643
605
cmd = str(argv.pop(0))
645
607
cmd_obj = get_cmd_object(cmd, plugins_override=not opt_builtin)
646
if not getattr(cmd_obj.run_argv, 'is_deprecated', False):
647
run = cmd_obj.run_argv
610
ret = apply_profiled(cmd_obj.run_argv, argv)
650
run = cmd_obj.run_argv_aliases
651
run_argv = [argv, alias_argv]
655
ret = apply_lsprofiled(opt_lsprof_file, run, *run_argv)
657
ret = apply_profiled(run, *run_argv)
662
# reset, in case we may do other commands later within the same process
665
def display_command(func):
666
"""Decorator that suppresses pipe/interrupt errors."""
667
def ignore_pipe(*args, **kwargs):
669
result = func(*args, **kwargs)
673
if not hasattr(e, 'errno'):
675
if e.errno != errno.EPIPE:
676
# Win32 raises IOError with errno=0 on a broken pipe
677
if sys.platform != 'win32' or e.errno != 0:
680
except KeyboardInterrupt:
612
ret = cmd_obj.run_argv(argv)
687
from bzrlib.ui.text import TextUIFactory
688
bzrlib.ui.ui_factory = TextUIFactory()
689
argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
690
ret = run_bzr_catch_errors(argv)
691
mutter("return code %d", ret)
618
bzrlib.trace.log_startup(argv)
619
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
621
return run_bzr_catch_errors(argv[1:])
695
624
def run_bzr_catch_errors(argv):
698
# do this here inside the exception wrappers to catch EPIPE
630
# do this here inside the exception wrappers to catch EPIPE
632
#wrap common errors as CommandErrors.
633
except (NotBranchError,), e:
634
raise BzrCommandError(str(e))
635
except BzrCommandError, e:
636
# command line syntax error, etc
640
bzrlib.trace.log_exception()
642
except AssertionError, e:
643
bzrlib.trace.log_exception('assertion failed: ' + str(e))
645
except KeyboardInterrupt, e:
646
bzrlib.trace.log_exception('interrupted')
700
648
except Exception, e:
701
# used to handle AssertionError and KeyboardInterrupt
702
# specially here, but hopefully they're handled ok by the logger now
703
bzrlib.trace.report_exception(sys.exc_info(), sys.stderr)
704
if os.environ.get('BZR_PDB'):
705
print '**** entering debugger'
707
pdb.post_mortem(sys.exc_traceback)
650
if (isinstance(e, IOError)
651
and hasattr(e, 'errno')
652
and e.errno == errno.EPIPE):
653
bzrlib.trace.note('broken pipe')
656
bzrlib.trace.log_exception()
710
659
if __name__ == '__main__':
711
660
sys.exit(main(sys.argv))