/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/trace.py

  • Committer: Jelmer Vernooij
  • Date: 2019-03-05 07:32:38 UTC
  • mto: (7290.1.21 work)
  • mto: This revision was merged to the branch mainline in revision 7311.
  • Revision ID: jelmer@jelmer.uk-20190305073238-zlqn981opwnqsmzi
Add appveyor configuration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
Messages are classified by severity levels: critical, error, warning, info,
24
24
and debug.
25
25
 
26
 
They can be sent to two places: stderr, and `$XDG_CACHE_HOME/breezy/brz.log`.
27
 
For purposes such as running the test suite, they can also be redirected away
28
 
from both of those two places to another location.
 
26
They can be sent to two places: to stderr, and to ~/.brz.log.  For purposes
 
27
such as running the test suite, they can also be redirected away from both of
 
28
those two places to another location.
29
29
 
30
 
`brz.log` gets all messages, and full tracebacks for uncaught exceptions.
 
30
~/.brz.log gets all messages, and full tracebacks for uncaught exceptions.
31
31
This trace file is always in UTF-8, regardless of the user's default encoding,
32
32
so that we can always rely on writing any message.
33
33
 
45
45
form.
46
46
"""
47
47
 
 
48
from __future__ import absolute_import
 
49
 
48
50
# FIXME: Unfortunately it turns out that python's logging module
49
51
# is quite expensive, even when the message is not printed by any handlers.
50
52
# We should perhaps change back to just simply doing it here.
55
57
# that.
56
58
 
57
59
import errno
58
 
from io import StringIO
59
60
import logging
60
61
import os
61
62
import sys
71
72
 
72
73
lazy_import(globals(), """
73
74
from breezy import (
74
 
    bedding,
75
75
    debug,
 
76
    errors,
76
77
    osutils,
77
78
    ui,
78
79
    )
79
80
""")
80
 
from . import (
81
 
    errors,
 
81
 
 
82
from .sixish import (
 
83
    PY3,
 
84
    StringIO,
 
85
    text_type,
82
86
    )
83
87
 
84
88
 
92
96
# than push/pop_log_file.
93
97
_trace_file = None
94
98
 
95
 
# Absolute path for brz.log.  Not changed even if the log/trace output is
 
99
# Absolute path for ~/.brz.log.  Not changed even if the log/trace output is
96
100
# redirected elsewhere.  Used to show the location in --version.
97
101
_brz_log_filename = None
98
102
 
155
159
        fmt = fmt.decode('ascii', 'replace')
156
160
 
157
161
    if args:
 
162
        if not PY3:
 
163
            args = tuple(
 
164
                _Bytes(arg) if isinstance(arg, bytes) else arg for arg in args)
158
165
        out = fmt % args
159
166
    else:
160
167
        out = fmt
196
203
 
197
204
 
198
205
def _get_brz_log_filename():
199
 
    """Return the brz log filename.
200
 
 
201
 
    :return: A path to the log file
202
 
    :raise EnvironmentError: If the cache directory could not be created
203
 
    """
204
 
    brz_log = os.environ.get('BRZ_LOG')
 
206
    brz_log = osutils.path_from_environ('BRZ_LOG')
205
207
    if brz_log:
206
208
        return brz_log
207
 
    return os.path.join(bedding.cache_dir(), 'brz.log')
 
209
    home = osutils.path_from_environ('BRZ_HOME')
 
210
    if home is None:
 
211
        # GZ 2012-02-01: Logging to the home dir is bad, but XDG is unclear
 
212
        #                over what would be better. On windows, bug 240550
 
213
        #                suggests LOCALAPPDATA be used instead.
 
214
        home = osutils._get_home_dir()
 
215
    return os.path.join(home, '.brz.log')
208
216
 
209
217
 
210
218
def _open_brz_log():
211
 
    """Open the brz.log trace file.
 
219
    """Open the .brz.log trace file.
212
220
 
213
221
    If the log is more than a particular length, the old file is renamed to
214
 
    brz.log.old and a new file is started.  Otherwise, we append to the
 
222
    .brz.log.old and a new file is started.  Otherwise, we append to the
215
223
    existing file.
216
224
 
217
225
    This sets the global _brz_log_filename.
243
251
                break
244
252
        return os.fdopen(fd, 'ab', 0)  # unbuffered
245
253
 
 
254
    _brz_log_filename = _get_brz_log_filename()
 
255
    _rollover_trace_maybe(_brz_log_filename)
246
256
    try:
247
 
        _brz_log_filename = _get_brz_log_filename()
248
 
        _rollover_trace_maybe(_brz_log_filename)
249
 
 
250
257
        brz_log_file = _open_or_create_log_file(_brz_log_filename)
251
258
        brz_log_file.write(b'\n')
252
259
        if brz_log_file.tell() <= 2:
273
280
 
274
281
 
275
282
def enable_default_logging():
276
 
    """Configure default logging: messages to stderr and debug to brz.log
 
283
    """Configure default logging: messages to stderr and debug to .brz.log
277
284
 
278
285
    This should only be called once per process.
279
286
 
296
303
        r'%Y-%m-%d %H:%M:%S')
297
304
    # after hooking output into brz_log, we also need to attach a stderr
298
305
    # handler, writing only at level info and with encoding
299
 
    stderr_handler = logging.StreamHandler(stream=sys.stderr)
 
306
    if sys.version_info[0] == 2:
 
307
        stderr_handler = EncodedStreamHandler(
 
308
            sys.stderr, osutils.get_terminal_encoding(), 'replace',
 
309
            level=logging.INFO)
 
310
    else:
 
311
        stderr_handler = logging.StreamHandler(stream=sys.stderr)
300
312
    logging.getLogger('brz').addHandler(stderr_handler)
301
313
    return memento
302
314
 
478
490
 
479
491
 
480
492
def report_exception(exc_info, err_file):
481
 
    """Report an exception to err_file (typically stderr) and to brz.log.
 
493
    """Report an exception to err_file (typically stderr) and to .brz.log.
482
494
 
483
495
    This will show either a full traceback or a short message as appropriate.
484
496
 
485
497
    :return: The appropriate exit code for this error.
486
498
    """
487
 
    # Log the full traceback to brz.log
 
499
    # Log the full traceback to ~/.brz.log
488
500
    log_exception_quietly()
489
501
    if 'error' in debug.debug_flags:
490
502
        print_exception(exc_info, err_file)
509
521
    elif not getattr(exc_object, 'internal_error', True):
510
522
        report_user_error(exc_info, err_file)
511
523
        return errors.EXIT_ERROR
512
 
    elif isinstance(exc_object, EnvironmentError):
 
524
    elif osutils.is_environment_error(exc_object):
513
525
        if getattr(exc_object, 'errno', None) == errno.EPIPE:
514
526
            err_file.write("brz: broken pipe\n")
515
527
            return errors.EXIT_ERROR
600
612
 
601
613
    def emit(self, record):
602
614
        try:
603
 
            if not isinstance(record.msg, str):
 
615
            if not isinstance(record.msg, text_type):
604
616
                msg = record.msg.decode("utf-8")
605
 
                record.msg = msg
 
617
                if PY3:
 
618
                    record.msg = msg
606
619
            line = self.format(record)
607
 
            if not isinstance(line, str):
 
620
            if not isinstance(line, text_type):
608
621
                line = line.decode("utf-8")
609
622
            self.stream.write(line.encode(self.encoding, self.errors) + b"\n")
610
623
        except Exception: