diff -Nru diffoscope-136/debian/changelog diffoscope-137/debian/changelog --- diffoscope-136/debian/changelog 2020-01-24 15:38:57.000000000 +0000 +++ diffoscope-137/debian/changelog 2020-02-18 17:15:59.000000000 +0000 @@ -1,3 +1,14 @@ +diffoscope (137) unstable; urgency=medium + + * Also extract classes2.dex, classes3.dex etc. from .apk files. + (Closes: reproducible-builds/diffoscope#88) + * Add generalised support for "ignoring" returncodes and move special-casing + of returncodes in the zip comparator to this. + * Accommodate sng returning with a UNIX exit code of 1 even if there minor + errors in the file (discovered via #950806). + + -- Chris Lamb Tue, 18 Feb 2020 17:15:59 +0000 + diffoscope (136) unstable; urgency=medium [ Chris Lamb ] diff -Nru diffoscope-136/diffoscope/comparators/apk.py diffoscope-137/diffoscope/comparators/apk.py --- diffoscope-136/diffoscope/comparators/apk.py 2020-01-24 15:38:57.000000000 +0000 +++ diffoscope-137/diffoscope/comparators/apk.py 2020-02-18 17:15:59.000000000 +0000 @@ -20,6 +20,7 @@ import re import os.path import logging +import itertools import subprocess from diffoscope.tools import tool_required @@ -74,6 +75,23 @@ stdout=subprocess.PIPE, ) + # ... including "classes2.dex", "classes3.dex", etc. + for x in itertools.count(2): + try: + subprocess.check_call( + ( + 'unzip', + '-d', + self._unpacked, + self.source.path, + 'classes{}.dex'.format(x), + ), + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + except subprocess.CalledProcessError: + break + for root, _, files in os.walk(self._unpacked): current_dir = [] diff -Nru diffoscope-136/diffoscope/comparators/png.py diffoscope-137/diffoscope/comparators/png.py --- diffoscope-136/diffoscope/comparators/png.py 2020-01-24 15:38:57.000000000 +0000 +++ diffoscope-137/diffoscope/comparators/png.py 2020-02-18 17:15:59.000000000 +0000 @@ -33,6 +33,9 @@ class Sng(Command): + # sng will return 1 if there are even minor errors in the file + VALID_RETURNCODES = {0, 1} + @tool_required('sng') def cmdline(self): return ['sng'] diff -Nru diffoscope-136/diffoscope/comparators/utils/command.py diffoscope-137/diffoscope/comparators/utils/command.py --- diffoscope-136/diffoscope/comparators/utils/command.py 2020-01-24 15:38:57.000000000 +0000 +++ diffoscope-137/diffoscope/comparators/utils/command.py 2020-02-18 17:15:59.000000000 +0000 @@ -30,6 +30,7 @@ class Command(metaclass=abc.ABCMeta): MASK_STDERR = False MAX_STDERR_LINES = 50 + VALID_RETURNCODES = {0} def __init__(self, path): self._path = path @@ -109,7 +110,12 @@ @property def returncode(self): - return self._process.returncode + val = self._process.returncode + + if val in self.VALID_RETURNCODES: + return 0 + + return val @property def stdout(self): diff -Nru diffoscope-136/diffoscope/comparators/zip.py diffoscope-137/diffoscope/comparators/zip.py --- diffoscope-136/diffoscope/comparators/zip.py 2020-01-24 15:38:57.000000000 +0000 +++ diffoscope-137/diffoscope/comparators/zip.py 2020-02-18 17:15:59.000000000 +0000 @@ -36,6 +36,11 @@ class Zipinfo(Command): + # zipinfo returns with an exit code of 1 or 2 when reading + # Mozilla-optimized or Java "jmod" ZIPs as they have non-standard headers + # which are safe to ignore. + VALID_RETURNCODES = {0, 1, 2} + @tool_required('zipinfo') def cmdline(self): # zipinfo (without -v) puts warning messages (some of which contain @@ -43,18 +48,6 @@ # to work around it, we run it on /dev/stdin instead, seems to work ok. return ['zipinfo', '/dev/stdin'] - @property - def returncode(self): - returncode = super().returncode - - # zipinfo returns with an exit code of 1 or 2 when reading - # Mozilla-optimized or Java "jmod" ZIPs as they have non-standard - # headers which are safe to ignore. - if returncode in (1, 2): - returncode = 0 - - return returncode - def stdin(self): return open(self.path, 'rb') @@ -72,6 +65,9 @@ class Zipnote(Command): + # zipnote returns with an exit code of 3 for invalid archives + VALID_RETURNCODES = {0, 3} + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -85,13 +81,6 @@ shutil.copy(self.path, path) return ['zipnote', path] - @property - def returncode(self): - returncode = super().returncode - - # zipnote returns with an exit code of 3 for invalid archives - return 0 if returncode == 3 else returncode - def filter(self, line): """ Example output from zipnote(1): diff -Nru diffoscope-136/diffoscope/__init__.py diffoscope-137/diffoscope/__init__.py --- diffoscope-136/diffoscope/__init__.py 2020-01-24 15:38:57.000000000 +0000 +++ diffoscope-137/diffoscope/__init__.py 2020-02-18 17:15:59.000000000 +0000 @@ -17,4 +17,4 @@ # You should have received a copy of the GNU General Public License # along with diffoscope. If not, see . -VERSION = "136" +VERSION = "137"