33
33
from warnings import warn
38
import bzrlib.errors as errors
39
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)
44
from bzrlib.symbol_versioning import *
47
45
import bzrlib.trace
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.
673
626
if not hasattr(e, 'errno'):
675
628
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
631
except KeyboardInterrupt:
687
638
from bzrlib.ui.text import TextUIFactory
639
## bzrlib.trace.enable_default_logging()
640
bzrlib.trace.log_startup(argv)
688
641
bzrlib.ui.ui_factory = TextUIFactory()
689
argv = [a.decode(bzrlib.user_encoding) for a in argv[1:]]
690
ret = run_bzr_catch_errors(argv)
642
ret = run_bzr_catch_errors(argv[1:])
691
643
mutter("return code %d", ret)
695
647
def run_bzr_catch_errors(argv):
698
# do this here inside the exception wrappers to catch EPIPE
652
# do this here inside the exception wrappers to catch EPIPE
700
654
except Exception, e:
701
655
# used to handle AssertionError and KeyboardInterrupt
702
656
# 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)
658
if (isinstance(e, IOError)
659
and hasattr(e, 'errno')
660
and e.errno == errno.EPIPE):
661
bzrlib.trace.note('broken pipe')
664
bzrlib.trace.log_exception()
665
if os.environ.get('BZR_PDB'):
666
print '**** entering debugger'
668
pdb.post_mortem(sys.exc_traceback)
710
671
if __name__ == '__main__':
711
672
sys.exit(main(sys.argv))