[Collab-qa-commits] r2410 - multi-arch
Jakub Wilk
jwilk at alioth.debian.org
Mon Jul 9 11:23:30 UTC 2012
Author: jwilk
Date: 2012-07-09 11:23:30 +0000 (Mon, 09 Jul 2012)
New Revision: 2410
Added:
multi-arch/report-multiarch-bug
Log:
New tool to help filing multi-arch bugs.
Added: multi-arch/report-multiarch-bug
===================================================================
--- multi-arch/report-multiarch-bug (rev 0)
+++ multi-arch/report-multiarch-bug 2012-07-09 11:23:30 UTC (rev 2410)
@@ -0,0 +1,189 @@
+#!/usr/bin/python3
+
+# Copyright © 2012 Jakub Wilk <jwilk at debian.org>
+
+# Redistribution and use in source and compiled forms, with or without
+# modification, are permitted under any circumstances. No warranty.
+
+import argparse
+import os
+import pwd
+import re
+import shutil
+import socket
+import subprocess as ipc
+import sys
+import tempfile
+
+import apt
+import apt_pkg
+
+import jinja2
+
+template = jinja2.Template('''\
+From: {{name}} <{{email}}>
+To: submit at bugs.debian.org
+Subject: {{package}}: arch-dependent {{plural("file", "files", files|length)}} in "Multi-Arch: same" package
+X-Debbugs-No-Ack: please
+X-Debbugs-CC: {{email}}
+
+Package: {{package}}
+Version: {{version}}
+Severity: important
+User: multiarch-devel at lists.alioth.debian.org
+Usertags: multiarch
+
+{{package}} is marked as "Multi-Arch: same", but the following {{plural("file is", "files are", files|length)}} architecture-dependent:
+{% for file in files %}
+{{file}}\
+{% endfor %}
+
+An example diff between {{architectures[0]}} and {{architectures[1]}} {% if ungzipped %}(after ungzipping) {% endif %}is attached.
+
+''')
+
+extract_filenames_from_archdiff = re.compile(b'^diff -ur [^/]+([^ ]+)', re.MULTILINE).findall
+extract_binary_filenames_from_archdiff = re.compile(b'^Binary files [^/]+([^ ]+)', re.MULTILINE).findall
+subst_archdiff_junk = re.compile(b'^Only in .*\n', re.MULTILINE).sub
+
+subst_architecture = re.compile('(?<=_)[a-z0-9-]+(?=[.]deb$)').sub
+
+def strip_deb_suffix(s, regex=re.compile('[.]deb$')):
+ return regex.sub('', s)
+
+def get_full_name():
+ return (
+ os.getenv('DEBFULLNAME') or
+ pwd.getpwuid(os.getuid()).pw_gecos.split(',')[0]
+ )
+
+def get_email():
+ return (
+ os.getenv('DEBEMAIL') or
+ '{login}@{domain}'.format(login=pwd.getpwduid(os.getuid()).pw_name, domain=socket.getfqdn())
+ )
+
+def plural(x, y, n):
+ return x if n == 1 else y
+
+class UserError(Exception):
+ pass
+
+class VersionError(UserError):
+ pass
+
+class NotMultiArchSame(UserError):
+ pass
+
+def main(options):
+ cache = apt.Cache()
+ packages = cache[options.package].versions
+ try:
+ [package] = [
+ pkg for pkg in packages
+ if options.version is None or options.version == pkg.version
+ ]
+ except ValueError:
+ raise VersionError('select a version: {0}'.format(
+ ', '.join(pkg.version for pkg in packages))
+ )
+ [uri] = package.uris
+ uris = [
+ subst_architecture(arch, uri)
+ for arch in options.architectures
+ ]
+ tmpdir = tempfile.mkdtemp(prefix='report-multiarch-bug.')
+ progress = apt.progress.text.AcquireProgress()
+ fetcher = apt_pkg.Acquire(progress)
+ files = {}
+ for uri in uris:
+ filename = os.path.basename(uri)
+ files[filename] = apt_pkg.AcquireFile(
+ fetcher,
+ uri=uri,
+ descr=filename,
+ destfile=os.path.join(tmpdir, filename),
+ )
+ rc = fetcher.run()
+ if rc != fetcher.RESULT_CONTINUE:
+ raise RuntimeError('fetching files failed')
+ os.chdir(tmpdir)
+ for filename, file in files.items():
+ if file.status != file.STAT_DONE:
+ raise RuntimeError('fetching file failed ({0})'.format(filename))
+ commandline = ['dpkg-deb', '-I', filename, 'control']
+ control = ipc.check_output(commandline)
+ if b'\nMulti-Arch: same\n' not in control:
+ raise NotMultiArchSame('{file} is not "Multi-Arch: same"'.format(file=filename))
+ commandline = ['dpkg-deb', '-x',
+ filename,
+ strip_deb_suffix(filename)
+ ]
+ ipc.check_call(commandline)
+ diff_commandline = ['diff', '-ur'] + [strip_deb_suffix(f) for f in files.keys()]
+ child = ipc.Popen(diff_commandline, stdout=ipc.PIPE)
+ (archdiff, stderr) = child.communicate()
+ child = None
+ archdiff = subst_archdiff_junk(b'', archdiff)
+ ungzipped = [
+ s.decode('ASCII')
+ for s in extract_binary_filenames_from_archdiff(archdiff)
+ if s.endswith(b'.gz')
+ ]
+ ungzipped = dict((f[:-3], f) for f in ungzipped)
+ if ungzipped:
+ ungzip_commandline = ['find', '-type', 'f', '-name', '*.gz', '-exec', 'gzip', '-d', '{}', '+']
+ ipc.check_call(ungzip_commandline)
+ child = ipc.Popen(diff_commandline, stdout=ipc.PIPE)
+ (archdiff, stderr) = child.communicate()
+ child = None
+ archdiff = subst_archdiff_junk(b'', archdiff)
+ archdiff_affected = [
+ s.decode('ASCII')
+ for s in extract_filenames_from_archdiff(archdiff)
+ ]
+ archdiff_affected += [
+ s.decode('ASCII')
+ for s in extract_binary_filenames_from_archdiff(archdiff)
+ ]
+ archdiff_affected = [ungzipped.get(file, file) for file in archdiff_affected]
+ archdiff_filename = '{0}.archdiff'.format(os.path.commonprefix(files.keys())[:-1])
+ with open(archdiff_filename, 'wb') as file:
+ file.write(archdiff)
+ del archdiff
+ mail = template.render(
+ name=get_full_name(),
+ email=get_email(),
+ package=options.package,
+ version=package.version,
+ architectures=options.architectures,
+ plural=plural,
+ files=archdiff_affected,
+ ungzipped=ungzipped,
+ )
+ if options.mutt:
+ with open('template', 'wt') as file:
+ file.write(mail)
+ commandline = ['mutt', '-H', 'template', '-a', archdiff_filename]
+ ipc.check_call(commandline)
+ else:
+ print(mail)
+ os.chdir('/')
+ shutil.rmtree(tmpdir)
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-m', '--mutt', action='store_true')
+ parser.add_argument('-a', '--architectures', metavar='<arch>', nargs=2, default=['i386', 'amd64'])
+ parser.add_argument('package', metavar='<package>')
+ parser.add_argument('version', metavar='<version>', nargs='?')
+ options = parser.parse_args()
+ try:
+ main(options)
+ except VersionError as exc:
+ parser.error(exc)
+ except UserError as exc:
+ print('Error: {exc}'.format(exc=exc), file=sys.stderr)
+ sys.exit(1)
+
+# vim:ts=4 sw=4 et
Property changes on: multi-arch/report-multiarch-bug
___________________________________________________________________
Added: svn:executable
+ *
More information about the Collab-qa-commits
mailing list