33
33
from warnings import warn
38
import bzrlib.errors as errors
39
from bzrlib.errors import (BzrError,
37
from bzrlib.errors import (BzrError,
43
42
from bzrlib.option import Option
45
43
from bzrlib.revisionspec import RevisionSpec
46
from bzrlib.symbol_versioning import (deprecated_method, zero_eight)
47
from bzrlib import trace
44
from bzrlib.symbol_versioning import *
48
46
from bzrlib.trace import mutter, note, log_error, warning, be_quiet
192
190
If true, this command isn't advertised. This is typically
193
191
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
195
takes_options = []
208
encoding_type = 'strict'
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
216
@deprecated_method(zero_eight)
250
217
def run_argv(self, argv):
251
218
"""Parse command line and run.
265
232
allowed_names = self.options().keys()
266
233
for oname in opts:
267
234
if oname not in allowed_names:
268
raise BzrOptionError("option '--%s' is not allowed for"
269
" command %r" % (oname, self.name()))
235
raise BzrCommandError("option '--%s' is not allowed for"
236
" command %r" % (oname, self.name()))
270
237
# mix arguments and options into one dictionary
271
238
cmdargs = _match_argform(self.name(), self.takes_args, args)
304
269
return _unsquish_command_name(self.__class__.__name__)
306
def plugin_name(self):
307
"""Get the name of the plugin that provides this command.
309
:return: The name of the plugin or None if the command is builtin.
311
mod_parts = self.__module__.split('.')
312
if len(mod_parts) >= 3 and mod_parts[1] == 'plugins':
318
272
def parse_spec(spec):
401
354
if shortopt not in Option.SHORT_OPTIONS:
402
355
# We didn't find the multi-character name, and we
403
356
# didn't find the single char name
404
raise BzrCommandError('unknown option "%s"' % a)
357
raise BzrError('unknown short option %r' % a)
405
358
optname = Option.SHORT_OPTIONS[shortopt].name
418
371
# This option takes an argument, so pack it
421
375
if optname not in cmd_options:
422
raise BzrCommandError('unknown option "%s"' % shortopt)
376
raise BzrOptionError('unknown short option %r for'
378
(shortopt, command.name()))
423
379
if optname in opts:
424
380
# XXX: Do we ever want to support this, e.g. for -r?
425
381
if proc_aliasarg:
426
raise BzrCommandError('repeated option %r' % a)
382
raise BzrError('repeated option %r' % a)
427
383
elif optname in alias_opts:
428
384
# Replace what's in the alias with what's in the real
432
388
proc_argv.insert(0, a)
435
raise BzrCommandError('repeated option %r' % a)
391
raise BzrError('repeated option %r' % a)
437
393
option_obj = cmd_options[optname]
438
394
optargfn = option_obj.type
440
396
if optarg == None:
441
397
if not proc_argv:
442
raise BzrCommandError('option %r needs an argument' % a)
398
raise BzrError('option %r needs an argument' % a)
444
400
optarg = proc_argv.pop(0)
445
401
opts[optname] = optargfn(optarg)
558
514
The command-line arguments, without the program name from argv[0]
559
These should already be decoded. All library/test code calling
560
run_bzr should be passing valid strings (don't need decoding).
562
516
Returns a command status or raises an exception.
619
from bzrlib.builtins import cmd_help
620
cmd_help().run_argv_aliases([])
571
if (not argv) or (argv[0] == '--help'):
572
from bzrlib.help import help
623
579
if argv[0] == '--version':
673
629
if not hasattr(e, 'errno'):
675
631
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
634
except KeyboardInterrupt:
687
641
from bzrlib.ui.text import TextUIFactory
642
## bzrlib.trace.enable_default_logging()
643
bzrlib.trace.log_startup(argv)
688
644
bzrlib.ui.ui_factory = TextUIFactory()
689
argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
690
ret = run_bzr_catch_errors(argv)
645
ret = run_bzr_catch_errors(argv[1:])
691
646
mutter("return code %d", ret)
695
650
def run_bzr_catch_errors(argv):
698
# do this here inside the exception wrappers to catch EPIPE
655
# do this here inside the exception wrappers to catch EPIPE
700
657
except Exception, e:
701
658
# used to handle AssertionError and KeyboardInterrupt
702
659
# 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)
661
if (isinstance(e, IOError)
662
and hasattr(e, 'errno')
663
and e.errno == errno.EPIPE):
664
bzrlib.trace.note('broken pipe')
667
bzrlib.trace.log_exception()
668
if os.environ.get('BZR_PDB'):
669
print '**** entering debugger'
671
pdb.post_mortem(sys.exc_traceback)
710
674
if __name__ == '__main__':
711
675
sys.exit(main(sys.argv))