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
74
each revision specifier supplied.
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'
116
>>> _parse_revision_str('branch:../branch2')
117
[<RevisionSpec_branch branch:../branch2>]
120
old_format_re = re.compile('\d*:\d*')
121
m = old_format_re.match(revstr)
124
warning('Colon separator for revision numbers is deprecated.'
126
for rev in revstr.split(':'):
128
revs.append(RevisionSpec(int(rev)))
130
revs.append(RevisionSpec(None))
133
for x in revstr.split('..'):
135
revs.append(RevisionSpec(None))
137
# looks like a namespace:.. has happened
138
next_prefix = x + '..'
140
if next_prefix is not None:
142
revs.append(RevisionSpec(x))
144
if next_prefix is not None:
145
revs.append(RevisionSpec(next_prefix))
90
149
def _builtin_commands():
91
150
import bzrlib.builtins
93
152
builtins = bzrlib.builtins.__dict__
94
153
for name in builtins:
95
154
if name.startswith("cmd_"):
96
real_name = _unsquish_command_name(name)
155
real_name = _unsquish_command_name(name)
97
156
r[real_name] = builtins[name]
101
161
def builtin_command_names():
175
235
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().
239
List of options that may be given for this command.
192
242
If true, this command isn't advertised. This is typically
193
243
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
248
takes_options = []
208
encoding_type = 'strict'
214
254
if self.__doc__ == Command.__doc__:
215
255
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
258
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)
259
"""Parse command line and run."""
260
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
262
if 'help' in opts: # e.g. bzr add --help
261
263
from bzrlib.help import help_on_command
262
264
help_on_command(self.name())
264
# XXX: This should be handled by the parser
265
allowed_names = self.options().keys()
267
# check options are reasonable
268
allowed = self.takes_options
266
269
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()))
270
if oname not in allowed:
271
raise BzrCommandError("option '--%s' is not allowed for command %r"
272
% (oname, self.name()))
270
274
# mix arguments and options into one dictionary
271
275
cmdargs = _match_argform(self.name(), self.takes_args, args)
346
337
parsed = [spec, None]
349
def parse_args(command, argv, alias_argv=None):
341
# list of all available options; the rhs can be either None for an
342
# option that takes no argument, or a constructor function that checks
357
'revision': _parse_revision_str,
384
def parse_args(argv):
350
385
"""Parse command line.
352
387
Arguments and options are parsed at this level before being passed
353
388
down to specific command handlers. This routine knows, from a
354
389
lookup table, something about the available options, what optargs
355
390
they take, and which commands will accept them.
392
>>> parse_args('--help'.split())
394
>>> parse_args('help -- --invalidcmd'.split())
395
(['help', '--invalidcmd'], {})
396
>>> parse_args('--version'.split())
397
([], {'version': True})
398
>>> parse_args('status --all'.split())
399
(['status'], {'all': True})
400
>>> parse_args('commit --message=biter'.split())
401
(['commit'], {'message': u'biter'})
402
>>> parse_args('log -r 500'.split())
403
(['log'], {'revision': [<RevisionSpec_int 500>]})
404
>>> parse_args('log -r500..600'.split())
405
(['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
406
>>> parse_args('log -vr500..600'.split())
407
(['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
408
>>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
409
(['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
417
if not argsover and a[0] == '-':
418
# option names must not be unicode
423
# We've received a standalone -- No more flags
426
mutter(" got option %r" % a)
428
optname, optarg = a[2:].split('=', 1)
431
if optname not in OPTIONS:
432
raise BzrError('unknown long option %r' % a)
435
if shortopt in SHORT_OPTIONS:
436
# Multi-character options must have a space to delimit
438
optname = SHORT_OPTIONS[shortopt]
440
# Single character short options, can be chained,
441
# and have their value appended to their name
443
if shortopt not in SHORT_OPTIONS:
444
# We didn't find the multi-character name, and we
445
# didn't find the single char name
446
raise BzrError('unknown short option %r' % a)
447
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)
450
# There are extra things on this option
451
# see if it is the value, or if it is another
453
optargfn = OPTIONS[optname]
455
# This option does not take an argument, so the
456
# next entry is another short option, pack it back
458
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
460
# This option takes an argument, so pack it
465
# XXX: Do we ever want to support this, e.g. for -r?
466
raise BzrError('repeated option %r' % a)
468
optargfn = OPTIONS[optname]
472
raise BzrError('option %r needs an argument' % a)
475
opts[optname] = optargfn(optarg)
456
proc_aliasarg = False # Done with alias argv
478
raise BzrError('option %r takes no argument' % optname)
457
483
return args, opts
460
488
def _match_argform(cmd, takes_args, args):
568
571
Do not load plugin modules at all
574
574
Only use builtin commands. (Plugins are still allowed to change
575
575
other behaviour.)
578
Run under the Python hotshot profiler.
581
Run under the Python lsprof profiler.
578
Run under the Python profiler.
580
# Load all of the transport methods
581
import bzrlib.transport.local, bzrlib.transport.http
583
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
585
opt_profile = opt_no_plugins = opt_builtin = False
589
587
# --no-plugins is handled specially at a very early stage. We need
590
588
# to load plugins before doing other command parsing so that they
591
589
# can override commands, but this needs to happen first.
597
592
if a == '--profile':
598
593
opt_profile = True
599
elif a == '--lsprof':
601
elif a == '--lsprof-file':
603
opt_lsprof_file = argv[i + 1]
605
594
elif a == '--no-plugins':
606
595
opt_no_plugins = True
607
elif a == '--no-aliases':
608
opt_no_aliases = True
609
596
elif a == '--builtin':
610
597
opt_builtin = True
611
elif a in ('--quiet', '-q'):
619
from bzrlib.builtins import cmd_help
620
cmd_help().run_argv_aliases([])
602
if (not argv) or (argv[0] == '--help'):
603
from bzrlib.help import help
623
610
if argv[0] == '--version':
628
615
if not opt_no_plugins:
629
616
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
619
cmd = str(argv.pop(0))
645
621
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
624
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:
626
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)
632
bzrlib.trace.log_startup(argv)
633
bzrlib.ui.ui_factory = bzrlib.ui.TextUIFactory()
635
return run_bzr_catch_errors(argv[1:])
695
638
def run_bzr_catch_errors(argv):
698
# do this here inside the exception wrappers to catch EPIPE
643
# do this here inside the exception wrappers to catch EPIPE
645
except BzrCommandError, e:
646
# command line syntax error, etc
650
bzrlib.trace.log_exception()
652
except AssertionError, e:
653
bzrlib.trace.log_exception('assertion failed: ' + str(e))
655
except KeyboardInterrupt, e:
656
bzrlib.trace.log_exception('interrupted')
700
658
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)
660
if (isinstance(e, IOError)
661
and hasattr(e, 'errno')
662
and e.errno == errno.EPIPE):
663
bzrlib.trace.note('broken pipe')
668
bzrlib.trace.log_exception()
710
671
if __name__ == '__main__':
711
672
sys.exit(main(sys.argv))