/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
1
# Copyright (C) 2009 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
17
18
"""Handling and reporting crashes.
19
"""
20
4584.3.17 by Martin Pool
Better message in apport crash
21
# for interactive testing, try the 'bzr assert-fail' command 
22
# or see http://code.launchpad.net/~mbp/bzr/bzr-fail
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
23
24
import os
4584.3.13 by Martin Pool
Refactor _format_plugin_list and include list of loaded modules in apport
25
import pprint
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
26
import sys
27
import time
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
28
from StringIO import StringIO
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
29
30
import bzrlib
31
from bzrlib import (
32
    config,
4584.3.16 by Martin Pool
Add -Dno_apport and fallback if apport fails
33
    debug,
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
34
    osutils,
35
    plugin,
36
    trace,
37
    )
38
39
40
def report_bug(exc_info, stderr):
4584.3.16 by Martin Pool
Add -Dno_apport and fallback if apport fails
41
    if 'no_apport' not in debug.debug_flags:
42
        try:
43
            report_bug_to_apport(exc_info, stderr)
44
            return
45
        except Exception, e:
4584.3.21 by Martin Pool
Start adding tests for apport
46
            # this should only happen if apport is installed but it didn't
47
            # work, eg because of an io error writing the crash file
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
48
            sys.stderr.write("bzr: failed to report crash using apport:\n "
49
                "    %r\n" % e)
4584.3.16 by Martin Pool
Add -Dno_apport and fallback if apport fails
50
            pass
51
    report_bug_legacy(exc_info, stderr)
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
52
53
54
def report_bug_legacy(exc_info, err_file):
55
    """Report a bug by just printing a message to the user."""
56
    trace.print_exception(exc_info, err_file)
57
    err_file.write('\n')
58
    err_file.write('bzr %s on python %s (%s)\n' % \
59
                       (bzrlib.__version__,
60
                        bzrlib._format_version_tuple(sys.version_info),
61
                        sys.platform))
62
    err_file.write('arguments: %r\n' % sys.argv)
63
    err_file.write(
64
        'encoding: %r, fsenc: %r, lang: %r\n' % (
65
            osutils.get_user_encoding(), sys.getfilesystemencoding(),
66
            os.environ.get('LANG')))
67
    err_file.write("plugins:\n")
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
68
    err_file.write(_format_plugin_list())
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
69
    err_file.write(
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
70
        "\n\n"
4584.3.19 by Martin Pool
Tweak crash message and use the same one with apport or without.
71
        "*** Bazaar has encountered an internal error.  This probably indicates a\n"
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
72
        "    bug in Bazaar.  You can help us fix it by filing a bug report at\n"
73
        "        https://bugs.launchpad.net/bzr/+filebug\n"
74
        "    including this traceback and a description of the problem.\n"
4584.3.19 by Martin Pool
Tweak crash message and use the same one with apport or without.
75
        )
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
76
77
78
def report_bug_to_apport(exc_info, stderr):
79
    """Report a bug to apport for optional automatic filing.
80
    
81
    :returns: True if the bug was filed or otherwise handled; 
82
        False to use a fallback method.
83
    """
84
    # this is based on apport_package_hook.py, but omitting some of the
85
    # Ubuntu-specific policy about what to report and when
86
    try:
4584.3.8 by Martin Pool
Remove code testing for unavailability of apport
87
        from apport.report import Report
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
88
    except ImportError, e:
89
        trace.warning("couldn't find apport bug-reporting library: %s" % e)
90
        return False
91
4584.3.21 by Martin Pool
Start adding tests for apport
92
    crash_file = _open_crash_file()
93
    try:
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
94
        _write_apport_report_to_file(exc_info, crash_file)
4584.3.21 by Martin Pool
Start adding tests for apport
95
    finally:
96
        crash_file.close()
97
98
    stderr.write("bzr: ERROR: %s.%s: %s\n" 
99
        "\n"
100
        "*** Bazaar has encountered an internal error.  This probably indicates a\n"
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
101
        "    bug in Bazaar.  You can help us fix it by filing a bug report at\n"
102
        "        https://bugs.launchpad.net/bzr/+filebug\n"
103
        "    attaching the crash file\n"
104
        "        %s\n"
105
        "    and including a description of the problem.\n"
106
        "\n"
107
        "    The crash file is plain text and you can inspect or edit it to remove\n"
108
        "    private information.\n"
4584.3.21 by Martin Pool
Start adding tests for apport
109
        % (exc_info[0].__module__, exc_info[0].__name__, exc_info[1],
110
           crash_file.name))
111
    return True
112
113
114
def _write_apport_report_to_file(exc_info, crash_file):
115
    import platform
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
116
    import traceback
4584.3.21 by Martin Pool
Start adding tests for apport
117
    from apport.report import Report
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
118
119
    exc_type, exc_object, exc_tb = exc_info
120
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
121
    pr = Report()
122
    # add_proc_info gives you the memory map of the process: this seems rarely
123
    # useful for Bazaar and it does make the report harder to scan, though it
124
    # does tell you what binary modules are loaded.
125
    # pr.add_proc_info()
126
    pr.add_user_info()
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
127
    pr['CommandLine'] = pprint.pformat(sys.argv)
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
128
    pr['BzrVersion'] = bzrlib.__version__
129
    pr['PythonVersion'] = bzrlib._format_version_tuple(sys.version_info)
130
    pr['Platform'] = platform.platform(aliased=1)
131
    pr['UserEncoding'] = osutils.get_user_encoding()
132
    pr['FileSystemEncoding'] = sys.getfilesystemencoding()
133
    pr['Locale'] = os.environ.get('LANG')
4584.3.13 by Martin Pool
Refactor _format_plugin_list and include list of loaded modules in apport
134
    pr['BzrPlugins'] = _format_plugin_list()
135
    pr['PythonLoadedModules'] = _format_module_list()
4584.3.22 by Martin Pool
further tweaks to and tests of bzr apport reporting
136
    pr['BzrDebugFlags'] = pprint.pformat(debug.debug_flags)
137
138
    tb_file = StringIO()
139
    traceback.print_exception(exc_type, exc_object, exc_tb, file=tb_file)
140
    pr['Traceback'] = tb_file.getvalue()
141
4584.3.21 by Martin Pool
Start adding tests for apport
142
    pr.write(crash_file)
4584.3.6 by Martin Pool
Move apport integration to bzrlib.crash and send output to a file.
143
144
145
def _open_crash_file():
146
    crash_dir = config.crash_dir()
147
    # user-readable only, just in case the contents are sensitive.
148
    if not osutils.isdir(crash_dir):
149
        os.makedirs(crash_dir, mode=0700)
150
    filename = 'bzr-%s-%s.crash' % (
151
        osutils.compact_date(time.time()),
152
        os.getpid(),)
153
    return open(osutils.pathjoin(crash_dir, filename), 'wt')
4584.3.13 by Martin Pool
Refactor _format_plugin_list and include list of loaded modules in apport
154
155
156
def _format_plugin_list():
157
    plugin_lines = []
158
    for name, a_plugin in sorted(plugin.plugins().items()):
159
        plugin_lines.append("  %-20s %s [%s]" %
160
            (name, a_plugin.path(), a_plugin.__version__))
161
    return '\n'.join(plugin_lines)
162
163
164
def _format_module_list():
165
    return pprint.pformat(sys.modules)