125 lines
4.5 KiB
Python
125 lines
4.5 KiB
Python
"""Debian crash database interface."""
|
|
|
|
# Debian adaptation Copyright (C) 2012 Ritesh Raj Sarraf <rrs@debian.org>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify it
|
|
# under the terms of the GNU General Public License as published by the
|
|
# Free Software Foundation; either version 2 of the License, or (at your
|
|
# option) any later version. See http://www.gnu.org/copyleft/gpl.html for
|
|
# the full text of the license.
|
|
|
|
|
|
import email.mime.text
|
|
import smtplib
|
|
import tempfile
|
|
|
|
import apport.crashdb
|
|
|
|
|
|
class CrashDatabase(apport.crashdb.CrashDatabase):
|
|
"""Debian crash database.
|
|
|
|
This is a Apport CrashDB implementation for interacting with Debian BTS.
|
|
"""
|
|
|
|
# TODO: Implement several missing abstract methods from parent class
|
|
# pylint: disable=abstract-method
|
|
|
|
def __init__(self, auth_file, options):
|
|
"""Initialize crash database connection.
|
|
|
|
Debian implementation is pretty basic as most of its bug management
|
|
processes revolve around the email interface
|
|
"""
|
|
apport.crashdb.CrashDatabase.__init__(self, auth_file, options)
|
|
self.options = options
|
|
|
|
if not self.options.get("smtphost"):
|
|
self.options["smtphost"] = "reportbug.debian.org"
|
|
|
|
if not self.options.get("recipient"):
|
|
self.options["recipient"] = "submit@bugs.debian.org"
|
|
|
|
def accepts(self, report):
|
|
"""Check if this report can be uploaded to this database.
|
|
Checks for the proper settings of apport.
|
|
"""
|
|
if not self.options.get("sender") and "UnreportableReason" not in report:
|
|
report["UnreportableReason"] = (
|
|
"Please configure sender settings in /etc/apport/crashdb.conf"
|
|
)
|
|
|
|
# At this time, we are not ready to take CrashDumps
|
|
if "Stacktrace" in report and not report.has_useful_stacktrace():
|
|
report["UnreportableReason"] = (
|
|
"Incomplete backtrace. Please install the debug symbol packages"
|
|
)
|
|
|
|
return apport.crashdb.CrashDatabase.accepts(self, report)
|
|
|
|
def upload(self, report, progress_callback=None, user_message_callback=None):
|
|
"""Upload given problem report return a handle for it.
|
|
|
|
In Debian, we use BTS, which is heavily email oriented. This method
|
|
crafts the bug into an email report understood by Debian BTS.
|
|
"""
|
|
# first and foremost, let's check if the apport bug filing
|
|
# settings are set correct
|
|
assert self.accepts(report)
|
|
|
|
# Frame the report in the format the BTS understands
|
|
try:
|
|
(buggy_package, buggy_version) = report["Package"].split(" ")
|
|
except (KeyError, ValueError):
|
|
return False
|
|
|
|
with tempfile.NamedTemporaryFile() as temp:
|
|
temp.file.write(f"Package: {buggy_package}\n".encode("UTF-8"))
|
|
temp.file.write(f"Version: {buggy_version}\n\n\n".encode("UTF-8"))
|
|
temp.file.write(("=============================\n\n").encode("UTF-8"))
|
|
|
|
# Let's remove the CoreDump first
|
|
|
|
# Even if we have a valid backtrace, we already are reporting it
|
|
# as text. We don't want to send very large emails to the BTS.
|
|
# OTOH, if the backtrace is invalid, has_useful_backtrace() will
|
|
# already deny reporting of the bug report.
|
|
try:
|
|
del report["CoreDump"]
|
|
except KeyError:
|
|
pass
|
|
|
|
# Now write the apport bug report
|
|
report.write(temp)
|
|
|
|
temp.file.seek(0)
|
|
|
|
msg = email.mime.text.MIMEText(temp.file.read().decode("UTF-8"))
|
|
|
|
msg["Subject"] = report["Title"]
|
|
msg["From"] = self.options["sender"]
|
|
msg["To"] = self.options["recipient"]
|
|
|
|
# Subscribe the submitted to the bug report
|
|
msg.add_header("X-Debbugs-CC", self.options["sender"])
|
|
msg.add_header("Usertag", f"apport-{report['ProblemType'].lower()}")
|
|
|
|
smtp = smtplib.SMTP(self.options["smtphost"])
|
|
smtp.sendmail(
|
|
self.options["sender"],
|
|
self.options["recipient"],
|
|
msg.as_string().encode("UTF-8"),
|
|
)
|
|
smtp.quit()
|
|
return True
|
|
|
|
def get_comment_url(self, report, handle):
|
|
"""Return an URL that should be opened after report has been uploaded
|
|
and upload() returned handle.
|
|
|
|
Should return None if no URL should be opened (anonymous filing without
|
|
user comments); in that case this function should do whichever
|
|
interactive steps it wants to perform.
|
|
"""
|
|
return None
|