import-bug-from-debian: handle multipart messages

With multipart messages, like #1073996, `import-bug-from-debian` would
produce bug description with this:
```
[<email.message.Message object at 0x7fbe14096fa0>, <email.message.Message object at 0x7fbe15143820>]
```
For that kind of bug, it now produces a correct description with the
plain text parts concatenated in the description, the attachments added
as attachments, and the inline images converted to attachments with an
inline message placeholder.

See #981577 for a particularly weird case now gracefully handled.
If something weirder happens, then the tool will now abort with a clear
message instead of producing garbage.

Closes: #969510
This commit is contained in:
Florent 'Skia' Jacquet 2024-06-24 18:48:04 +02:00 committed by Benjamin Drung
parent 47ab7b608b
commit 9a94c9dea1
2 changed files with 71 additions and 1 deletions

4
debian/changelog vendored
View File

@ -1,11 +1,15 @@
ubuntu-dev-tools (0.202ubuntu1) UNRELEASED; urgency=medium ubuntu-dev-tools (0.202ubuntu1) UNRELEASED; urgency=medium
[ Steve Langasek ]
* ubuntu-build: handle TOCTOU issue with the "can be retried" value on * ubuntu-build: handle TOCTOU issue with the "can be retried" value on
builds. builds.
* Recommend sbuild over pbuilder. sbuild is the tool recommended by * Recommend sbuild over pbuilder. sbuild is the tool recommended by
Ubuntu developers whose behavior most closely approximates Launchpad Ubuntu developers whose behavior most closely approximates Launchpad
builds. builds.
[ Florent 'Skia' Jacquet ]
* import-bug-from-debian: handle multipart message (Closes: #969510)
-- Steve Langasek <steve.langasek@ubuntu.com> Sun, 26 May 2024 12:58:38 -0700 -- Steve Langasek <steve.langasek@ubuntu.com> Sun, 26 May 2024 12:58:38 -0700
ubuntu-dev-tools (0.202) unstable; urgency=medium ubuntu-dev-tools (0.202) unstable; urgency=medium

View File

@ -37,6 +37,7 @@ from ubuntutools import getLogger
from ubuntutools.config import UDTConfig from ubuntutools.config import UDTConfig
Logger = getLogger() Logger = getLogger()
ATTACHMENT_MAX_SIZE = 2000
def main(): def main():
@ -118,7 +119,48 @@ def main():
bug_num = bug.bug_num bug_num = bug.bug_num
subject = bug.subject subject = bug.subject
log = debianbts.get_bug_log(bug_num) log = debianbts.get_bug_log(bug_num)
summary = log[0]["message"].get_payload() message = log[0]["message"]
attachments = []
if message.is_multipart():
summary = ""
i = 1
for part in message.walk():
content_type = part.get_content_type()
if content_type.startswith("multipart/"):
# we're already iterating on multipart items
# let's just skip the multipart extra metadata
continue
if content_type == "application/pgp-signature":
# we don't want to import pgp signature
continue
if part.is_attachment():
attachments.append((i, part))
elif content_type.startswith("image/"):
# images here are not attachment, they are inline, but Launchpad can't handle
# that, so let's add them as attachments
summary += f"Message part #{i}\n"
summary += f"[inline image '{part.get_filename()}']\n\n"
attachments.append((i, part))
elif content_type.startswith("text/html"):
summary += f"Message part #{i}\n"
summary += "[inline html]\n\n"
attachments.append((i, part))
elif content_type == "text/plain":
summary += f"Message part #{i}\n"
summary += part.get_content() + "\n"
else:
raise RuntimeError(
f"""Unknown message part
Your Debian bug is too weird to be imported in Launchpad, sorry.
You can fix that by patching this script in ubuntu-dev-tools.
Faulty message part:
{part}"""
)
i += 1
else:
summary = log[0]["message"].get_payload()
target = ubuntu.getSourcePackage(name=ubupackage) target = ubuntu.getSourcePackage(name=ubupackage)
if target is None: if target is None:
Logger.error( Logger.error(
@ -137,12 +179,36 @@ def main():
Logger.debug("Subject: %s", subject) Logger.debug("Subject: %s", subject)
Logger.debug("Description: ") Logger.debug("Description: ")
Logger.debug(description) Logger.debug(description)
for i, attachment in attachments:
Logger.debug("Attachment #%s (%s)", i, attachment.get_filename() or "inline")
Logger.debug("Content:")
if attachment.get_content_type() == "text/plain":
content = attachment.get_content()
if len(content) > ATTACHMENT_MAX_SIZE:
content = (
content[:ATTACHMENT_MAX_SIZE]
+ f" [attachment cropped after {ATTACHMENT_MAX_SIZE} characters...]"
)
Logger.debug(content)
else:
Logger.debug("[data]")
if options.dry_run: if options.dry_run:
Logger.info("Dry-Run: not creating Ubuntu bug.") Logger.info("Dry-Run: not creating Ubuntu bug.")
continue continue
u_bug = launchpad.bugs.createBug(target=target, title=subject, description=description) u_bug = launchpad.bugs.createBug(target=target, title=subject, description=description)
for i, attachment in attachments:
name = f"#{i}-{attachment.get_filename() or "inline"}"
content = attachment.get_content()
if isinstance(content, str):
# Launchpad only wants bytes
content = content.encode()
u_bug.addAttachment(
filename=name,
data=content,
comment=f"Imported from Debian bug http://bugs.debian.org/{bug_num}",
)
d_sp = debian.getSourcePackage(name=package) d_sp = debian.getSourcePackage(name=package)
if d_sp is None and options.package: if d_sp is None and options.package:
d_sp = debian.getSourcePackage(name=options.package) d_sp = debian.getSourcePackage(name=options.package)