1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
1
# Copyright (C) 2005, 2006 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
50
50
# is quite expensive, even when the message is not printed by any handlers.
51
51
# We should perhaps change back to just simply doing it here.
59
57
from bzrlib.lazy_import import lazy_import
60
58
lazy_import(globals(), """
61
from cStringIO import StringIO
64
from bzrlib.symbol_versioning import (deprecated_function,
69
68
lazy_import(globals(), """
69
from bzrlib import debug
78
72
_file_handler = None
79
73
_stderr_handler = None
83
77
_bzr_log_file = None
132
125
#_trace_file.flush()
135
def mutter_callsite(stacklevel, fmt, *args):
136
"""Perform a mutter of fmt and args, logging the call trace.
138
:param stacklevel: The number of frames to show. None will show all
140
:param fmt: The format string to pass to mutter.
141
:param args: A list of substitution variables.
144
traceback.print_stack(limit=stacklevel + 1, file=outf)
145
formatted_lines = outf.getvalue().splitlines()
146
formatted_stack = '\n'.join(formatted_lines[:-2])
147
mutter(fmt + "\nCalled from:\n%s", *(args + (formatted_stack,)))
150
128
def _rollover_trace_maybe(trace_fname):
154
132
if size <= 4 << 20:
156
134
old_fname = trace_fname + '.old'
157
osutils.rename(trace_fname, old_fname)
135
from osutils import rename
136
rename(trace_fname, old_fname)
174
153
home = os.path.expanduser('~')
175
154
_bzr_log_filename = os.path.join(home, '.bzr.log')
177
_bzr_log_filename = tracefilename
179
156
_bzr_log_filename = os.path.expanduser(_bzr_log_filename)
180
157
_rollover_trace_maybe(_bzr_log_filename)
199
176
warning("failed to open trace file: %s" % (e))
179
@deprecated_function(zero_nine)
180
def log_exception(msg=None):
181
"""Log the last exception to stderr and the trace file.
183
The exception string representation is used as the error
184
summary, unless msg is given.
186
Please see log_exception_quietly() for the replacement API.
190
log_exception_quietly()
202
193
def log_exception_quietly():
203
194
"""Log the last exception to the trace file only.
214
205
"""Configure default logging to stderr and .bzr.log"""
215
206
# FIXME: if this is run twice, things get confused
216
207
global _stderr_handler, _file_handler, _trace_file, _bzr_log_file
217
# create encoded wrapper around stderr
218
stderr = codecs.getwriter(osutils.get_terminal_encoding())(sys.stderr,
220
_stderr_handler = logging.StreamHandler(stderr)
208
_stderr_handler = logging.StreamHandler()
221
209
logging.getLogger('').addHandler(_stderr_handler)
222
210
_stderr_handler.setLevel(logging.INFO)
223
211
if not _file_handler:
228
216
_bzr_logger.setLevel(logging.DEBUG)
231
def set_verbosity_level(level):
232
"""Set the verbosity level.
234
:param level: -ve for quiet, 0 for normal, +ve for verbose
236
global _verbosity_level
237
_verbosity_level = level
238
_update_logging_level(level < 0)
241
def get_verbosity_level():
242
"""Get the verbosity level.
244
See set_verbosity_level() for values.
246
return _verbosity_level
249
219
def be_quiet(quiet=True):
250
# Perhaps this could be deprecated now ...
252
set_verbosity_level(-1)
254
set_verbosity_level(0)
257
def _update_logging_level(quiet=True):
258
"""Hide INFO messages if quiet."""
220
global _stderr_handler, _stderr_quiet
222
_stderr_quiet = quiet
260
224
_stderr_handler.setLevel(logging.WARNING)
266
"""Is the verbosity level negative?"""
267
return _verbosity_level < 0
271
"""Is the verbosity level positive?"""
272
return _verbosity_level > 0
275
234
def disable_default_logging():
320
279
def report_exception(exc_info, err_file):
321
"""Report an exception to err_file (typically stderr) and to .bzr.log.
323
This will show either a full traceback or a short message as appropriate.
325
:return: The appropriate exit code for this error.
327
280
exc_type, exc_object, exc_tb = exc_info
328
281
# Log the full traceback to ~/.bzr.log
329
282
log_exception_quietly()
330
283
if (isinstance(exc_object, IOError)
331
284
and getattr(exc_object, 'errno', None) == errno.EPIPE):
332
err_file.write("bzr: broken pipe\n")
333
return errors.EXIT_ERROR
285
print >>err_file, "bzr: broken pipe"
334
286
elif isinstance(exc_object, KeyboardInterrupt):
335
err_file.write("bzr: interrupted\n")
336
return errors.EXIT_ERROR
287
print >>err_file, "bzr: interrupted"
337
288
elif not getattr(exc_object, 'internal_error', True):
338
289
report_user_error(exc_info, err_file)
339
return errors.EXIT_ERROR
340
290
elif isinstance(exc_object, (OSError, IOError)):
341
291
# Might be nice to catch all of these and show them as something more
342
292
# specific, but there are too many cases at the moment.
343
293
report_user_error(exc_info, err_file)
344
return errors.EXIT_ERROR
346
295
report_bug(exc_info, err_file)
347
return errors.EXIT_INTERNAL_ERROR
350
298
# TODO: Should these be specially encoding the output?
356
304
if 'error' in debug.debug_flags:
357
305
report_bug(exc_info, err_file)
359
err_file.write("bzr: ERROR: %s\n" % (exc_info[1],))
307
print >>err_file, "bzr: ERROR:", str(exc_info[1])
362
310
def report_bug(exc_info, err_file):
363
311
"""Report an exception that probably indicates a bug in bzr"""
365
313
exc_type, exc_object, exc_tb = exc_info
366
err_file.write("bzr: ERROR: %s.%s: %s\n" % (
367
exc_type.__module__, exc_type.__name__, exc_object))
314
print >>err_file, "bzr: ERROR: %s.%s: %s" % (
315
exc_type.__module__, exc_type.__name__, exc_object)
369
317
traceback.print_exception(exc_type, exc_object, exc_tb, file=err_file)
371
err_file.write('bzr %s on python %s (%s)\n' % \
319
print >>err_file, 'bzr %s on python %s (%s)' % \
372
320
(bzrlib.__version__,
373
321
'.'.join(map(str, sys.version_info)),
375
err_file.write('arguments: %r\n' % sys.argv)
377
'encoding: %r, fsenc: %r, lang: %r\n' % (
378
osutils.get_user_encoding(), sys.getfilesystemencoding(),
379
os.environ.get('LANG')))
380
err_file.write("plugins:\n")
381
for name, a_plugin in sorted(plugin.plugins().items()):
382
err_file.write(" %-20s %s [%s]\n" %
383
(name, a_plugin.path(), a_plugin.__version__))
386
"** Please send this report to bazaar@lists.ubuntu.com\n"
387
" with a description of what you were doing when the\n"
323
print >>err_file, 'arguments: %r' % sys.argv
325
print >>err_file, "** please send this report to bazaar@lists.ubuntu.com"