[Reproducible-commits] [diffoscope] 03/21: XXX

Joachim Breitner nomeata at moszumanska.debian.org
Thu Dec 3 15:05:04 UTC 2015


This is an automated email from the git hooks/post-receive script.

nomeata pushed a commit to branch pu/parallel2
in repository diffoscope.

commit de457f2a46a7f36cb9c76f13574fdf71931a1e47
Author: Jérémy Bobbio <lunar at debian.org>
Date:   Tue Oct 6 10:04:40 2015 +0000

    XXX
---
 diffoscope/__init__.py               | 30 ++++++++++++++++++++
 diffoscope/__main__.py               |  4 ++-
 diffoscope/comparators/binary.py     | 18 ++++++++++--
 diffoscope/comparators/bzip2.py      | 18 ++++--------
 diffoscope/comparators/cbfs.py       |  8 +++---
 diffoscope/comparators/cpio.py       |  5 ++--
 diffoscope/comparators/deb.py        | 17 ++++++------
 diffoscope/comparators/debian.py     | 16 +++++------
 diffoscope/comparators/device.py     |  5 ++--
 diffoscope/comparators/dex.py        | 14 ++++------
 diffoscope/comparators/directory.py  | 45 +++++++++++++-----------------
 diffoscope/comparators/gzip.py       | 19 +++++--------
 diffoscope/comparators/iso9660.py    |  5 ++--
 diffoscope/comparators/libarchive.py |  2 +-
 diffoscope/comparators/rpm.py        | 17 ++++--------
 diffoscope/comparators/squashfs.py   |  9 +++---
 diffoscope/comparators/symlink.py    |  5 ++--
 diffoscope/comparators/tar.py        |  7 ++---
 diffoscope/comparators/utils.py      | 54 +++++++++++++-----------------------
 diffoscope/comparators/xz.py         | 18 ++++--------
 diffoscope/comparators/zip.py        |  9 +++---
 tests/comparators/test_cpio.py       |  2 ++
 22 files changed, 162 insertions(+), 165 deletions(-)

diff --git a/diffoscope/__init__.py b/diffoscope/__init__.py
index a493abb..ff3b2c8 100644
--- a/diffoscope/__init__.py
+++ b/diffoscope/__init__.py
@@ -21,6 +21,8 @@ from functools import wraps
 import logging
 from distutils.spawn import find_executable
 import os
+import shutil
+import tempfile
 
 VERSION = "42"
 
@@ -114,4 +116,32 @@ def set_locale():
     os.environ['TZ'] = 'UTC'
 
 
+temp_files = []
+temp_dirs = []
 
+
+def get_named_temporary_file(*args, **kwargs):
+    f = tempfile.NamedTemporaryFile(*args, **kwargs)
+    temp_files.append(f.name)
+    return f
+
+
+def get_temporary_directory(*args, **kwargs):
+    d = tempfile.TemporaryDirectory(*args, **kwargs)
+    temp_dirs.append(d)
+    return d
+
+
+def clean_all_temp_files():
+    for temp_file in temp_files:
+        try:
+            os.unlink(temp_file)
+        except FileNotFoundError:
+            pass
+        except:
+            logger.exception('Unable to delete %s', temp_file)
+    for temp_dir in temp_dirs:
+        try:
+            temp_dir.cleanup()
+        except:
+            logger.exception('Unable to delete %s', temp_dir)
diff --git a/diffoscope/__main__.py b/diffoscope/__main__.py
index ecb784c..c027b54 100644
--- a/diffoscope/__main__.py
+++ b/diffoscope/__main__.py
@@ -30,7 +30,7 @@ try:
     import tlsh
 except ImportError:
     tlsh = None
-from diffoscope import logger, VERSION, set_locale
+from diffoscope import logger, VERSION, set_locale, clean_all_temp_files
 import diffoscope.comparators
 from diffoscope.config import Config
 from diffoscope.presenters.html import output_html
@@ -153,6 +153,8 @@ def main(args=None):
             import pdb
             pdb.post_mortem()
         sys.exit(2)
+    finally:
+        clean_all_temp_files()
 
 if __name__ == '__main__':
     main()
diff --git a/diffoscope/comparators/binary.py b/diffoscope/comparators/binary.py
index b2a40cb..aa74277 100644
--- a/diffoscope/comparators/binary.py
+++ b/diffoscope/comparators/binary.py
@@ -110,10 +110,10 @@ class File(object, metaclass=ABCMeta):
         raise NotImplemented
 
     # Remove any temporary data associated with the file. The function
-    # should be idempotent and work during the destructor. It does nothing by
-    # default.
+    # should be idempotent and work during the destructor.
     def cleanup(self):
-        pass
+        if hasattr(self, '_as_container'):
+            del self._as_container
 
     def __del__(self):
         self.cleanup()
@@ -124,6 +124,18 @@ class File(object, metaclass=ABCMeta):
         return self._name
 
     @property
+    def as_container(self):
+        if not hasattr(self.__class__, 'CONTAINER_CLASS'):
+            if hasattr(self, '_other_file'):
+                return self._other_file.__class__.CONTAINER_CLASS(self)
+            raise NotImplemented('Not a container.')
+        if not hasattr(self, '_as_container'):
+            logger.debug('instanciating %s for %s', self.__class__.CONTAINER_CLASS, self)
+            self._as_container = self.__class__.CONTAINER_CLASS(self)
+        logger.debug('returning a %s for %s', self._as_container.__class__, self)
+        return self._as_container
+
+    @property
     def magic_file_type(self):
         if not hasattr(self, '_magic_file_type'):
             self._magic_file_type = File.guess_file_type(self.path)
diff --git a/diffoscope/comparators/bzip2.py b/diffoscope/comparators/bzip2.py
index aef9c46..6429847 100644
--- a/diffoscope/comparators/bzip2.py
+++ b/diffoscope/comparators/bzip2.py
@@ -27,22 +27,17 @@ from diffoscope import logger, tool_required
 
 
 class Bzip2Container(Archive):
-    @property
-    def path(self):
-        return self._path
-
-    def open_archive(self, path):
-        self._path = path
+    def open_archive(self):
         return self
 
     def close_archive(self):
-        self._path = None
+        pass
 
     def get_members(self):
         return {'bzip2-content': self.get_member(self.get_member_names()[0])}
 
     def get_member_names(self):
-        return [get_compressed_content_name(self.path, '.bz2')]
+        return [get_compressed_content_name(self.source.path, '.bz2')]
 
     @tool_required('bzip2')
     def extract(self, member_name, dest_dir):
@@ -50,12 +45,13 @@ class Bzip2Container(Archive):
         logger.debug('bzip2 extracting to %s', dest_path)
         with open(dest_path, 'wb') as fp:
             subprocess.check_call(
-                ["bzip2", "--decompress", "--stdout", self.path],
+                ["bzip2", "--decompress", "--stdout", self.source.path],
                 shell=False, stdout=fp, stderr=None)
         return dest_path
 
 
 class Bzip2File(File):
+    CONTAINER_CLASS = Bzip2Container
     RE_FILE_TYPE = re.compile(r'^bzip2 compressed data\b')
 
     @staticmethod
@@ -63,6 +59,4 @@ class Bzip2File(File):
         return Bzip2File.RE_FILE_TYPE.match(file.magic_file_type)
 
     def compare_details(self, other, source=None):
-        with Bzip2Container(self).open() as my_container, \
-             Bzip2Container(other).open() as other_container:
-            return my_container.compare(other_container)
+        return self.as_container.compare(other.as_container)
diff --git a/diffoscope/comparators/cbfs.py b/diffoscope/comparators/cbfs.py
index 00efa5a..a24230c 100644
--- a/diffoscope/comparators/cbfs.py
+++ b/diffoscope/comparators/cbfs.py
@@ -59,7 +59,7 @@ class CbfsContainer(Archive):
                 continue
             yield name
 
-    def open_archive(self, path):
+    def open_archive(self):
         return self
 
     def close_archive(self):
@@ -92,6 +92,8 @@ def is_header_valid(buf, size, offset=0):
 
 
 class CbfsFile(File):
+    CONTAINER_CLASS = CbfsContainer
+
     @staticmethod
     def recognizes(file):
         size = os.stat(file.path).st_size
@@ -129,7 +131,5 @@ class CbfsFile(File):
     def compare_details(self, other, source=None):
         differences = []
         differences.append(Difference.from_command(CbfsListing, self.path, other.path))
-        with CbfsContainer(self).open() as my_container, \
-             CbfsContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/diffoscope/comparators/cpio.py b/diffoscope/comparators/cpio.py
index 4f2f76b..536e80c 100644
--- a/diffoscope/comparators/cpio.py
+++ b/diffoscope/comparators/cpio.py
@@ -33,6 +33,7 @@ class CpioContent(Command):
 
 
 class CpioFile(File):
+    CONTAINER_CLASS = LibarchiveContainer
     RE_FILE_TYPE = re.compile(r'\bcpio archive\b')
 
     @staticmethod
@@ -43,7 +44,5 @@ class CpioFile(File):
         differences = []
         differences.append(Difference.from_command(
             CpioContent, self.path, other.path, source="file list"))
-        with LibarchiveContainer(self).open() as my_container, \
-             LibarchiveContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/diffoscope/comparators/deb.py b/diffoscope/comparators/deb.py
index ba1e529..8043389 100644
--- a/diffoscope/comparators/deb.py
+++ b/diffoscope/comparators/deb.py
@@ -33,6 +33,7 @@ class DebContainer(LibarchiveContainer):
 
 
 class DebFile(File):
+    CONTAINER_CLASS = DebContainer
     RE_FILE_TYPE = re.compile(r'^Debian binary package')
 
     @staticmethod
@@ -55,9 +56,7 @@ class DebFile(File):
         other_content = get_ar_content(other.path)
         differences.append(Difference.from_text(
                                my_content, other_content, self.path, other.path, source="metadata"))
-        with DebContainer(self).open() as my_container, \
-             DebContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
 
 
@@ -101,8 +100,9 @@ class Md5sumsFile(File):
 
 
 class DebTarContainer(TarContainer):
-    def __init__(self, archive, ignore_files):
+    def __init__(self, archive):
         super().__init__(archive)
+        ignore_files = archive.container.source.container.source.files_with_same_content_in_data
         assert type(ignore_files) is set
         self._ignore_files = ignore_files
 
@@ -113,6 +113,8 @@ class DebTarContainer(TarContainer):
 
 
 class DebDataTarFile(File):
+    CONTAINER_CLASS = DebTarContainer
+
     @staticmethod
     def recognizes(file):
         return isinstance(file, ArchiveMember) and \
@@ -122,9 +124,6 @@ class DebDataTarFile(File):
 
     def compare_details(self, other, source=None):
         differences = []
-        ignore_files = self.container.source.container.source.files_with_same_content_in_data
-        with DebTarContainer(self, ignore_files).open() as my_container, \
-             DebTarContainer(other, ignore_files).open() as other_container:
-            differences.append(Difference.from_command(TarListing, self.path, other.path))
-            differences.extend(my_container.compare(other_container))
+        differences.append(Difference.from_command(TarListing, self.path, other.path))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/diffoscope/comparators/debian.py b/diffoscope/comparators/debian.py
index d6a54ba..703804d 100644
--- a/diffoscope/comparators/debian.py
+++ b/diffoscope/comparators/debian.py
@@ -68,6 +68,10 @@ class DebControlMember(File):
 
 
 class DebControlContainer(Container):
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self._version_re = DebControlContainer.get_version_trimming_re(self)
+
     @staticmethod
     def get_version_trimming_re(dcc):
         version = dcc.source.deb822.get('Version')
@@ -79,12 +83,6 @@ class DebControlContainer(Container):
         else:
             return re.compile(re.escape(version))
 
-    @contextmanager
-    def open(self):
-        self._version_re = DebControlContainer.get_version_trimming_re(self)
-        yield self
-        del self._version_re
-
     def get_members(self):
         return {self._trim_version_number(name): self.get_member(name) for name in self.get_member_names()}
 
@@ -99,6 +97,8 @@ class DebControlContainer(Container):
 
 
 class DebControlFile(File):
+    CONTAINER_CLASS = DebControlContainer
+
     @property
     def deb822(self):
         return self._deb822
@@ -122,9 +122,7 @@ class DebControlFile(File):
         differences.append(Difference.from_text(self.deb822.get_as_string('Files'),
                                                 other.deb822.get_as_string('Files'),
                                                 self.path, other.path, source='Files'))
-        with DebControlContainer(self).open() as my_container, \
-             DebControlContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
 
         return differences
 
diff --git a/diffoscope/comparators/device.py b/diffoscope/comparators/device.py
index 14d0216..6416f50 100644
--- a/diffoscope/comparators/device.py
+++ b/diffoscope/comparators/device.py
@@ -23,7 +23,7 @@ import tempfile
 from diffoscope.comparators.binary import File, FilesystemFile
 from diffoscope.comparators.utils import format_device
 from diffoscope.difference import Difference
-from diffoscope import logger
+from diffoscope import logger, get_named_temporary_file
 
 
 class Device(File):
@@ -40,7 +40,7 @@ class Device(File):
         return self.get_device() == other.get_device()
 
     def create_placeholder(self):
-        with tempfile.NamedTemporaryFile(mode='w+', suffix='diffoscope', delete=False) as f:
+        with get_named_temporary_file(mode='w+', suffix='diffoscope', delete=False) as f:
             f.write(format_device(*self.get_device()))
             f.flush()
             return f.name
@@ -55,6 +55,7 @@ class Device(File):
         if hasattr(self, '_placeholder'):
             os.remove(self._placeholder)
             del self._placeholder
+        super().cleanup()
 
     def compare(self, other, source=None):
         with open(self.path) as my_content, \
diff --git a/diffoscope/comparators/dex.py b/diffoscope/comparators/dex.py
index 3e96324..017f1d4 100644
--- a/diffoscope/comparators/dex.py
+++ b/diffoscope/comparators/dex.py
@@ -31,35 +31,33 @@ class DexContainer(Archive):
     def path(self):
         return self._path
 
-    def open_archive(self, path):
-        self._path = path
+    def open_archive(self):
         return self
 
     def close_archive(self):
-        self._path = None
+        pass
 
     def get_members(self):
         return {'dex-content': self.get_member(self.get_member_names()[0])}
 
     def get_member_names(self):
-        return [get_compressed_content_name(self.path, '.dex') + '.jar']
+        return [get_compressed_content_name(self.source.path, '.dex') + '.jar']
 
     @tool_required('enjarify')
     def extract(self, member_name, dest_dir):
         dest_path = os.path.join(dest_dir, member_name)
         logger.debug('dex extracting to %s', dest_path)
-        subprocess.check_call(['enjarify', '-o', dest_path, self.path],
+        subprocess.check_call(['enjarify', '-o', dest_path, self.source.path],
             shell=False, stderr=None, stdout=subprocess.PIPE)
         return dest_path
 
 class DexFile(File):
     RE_FILE_TYPE = re.compile(r'^Dalvik dex file .*\b')
+    CONTAINER_CLASS = DexContainer
 
     @staticmethod
     def recognizes(file):
         return DexFile.RE_FILE_TYPE.match(file.magic_file_type)
 
     def compare_details(self, other, source=None):
-        with DexContainer(self).open() as my_container, \
-             DexContainer(other).open() as other_container:
-            return my_container.compare(other_container)
+        return self.as_container.compare(other.as_container)
diff --git a/diffoscope/comparators/directory.py b/diffoscope/comparators/directory.py
index 07d7d9a..cfabff8 100644
--- a/diffoscope/comparators/directory.py
+++ b/diffoscope/comparators/directory.py
@@ -129,21 +129,21 @@ class FilesystemDirectory(object):
         except RequiredToolNotFound:
             logger.info("Unable to find 'getfacl'.")
         differences.extend(compare_meta(self.name, other.name))
-        with DirectoryContainer(self).open() as my_container, \
-             DirectoryContainer(other).open() as other_container:
-            my_names = my_container.get_member_names()
-            other_names = other_container.get_member_names()
-            for name in sorted(set(my_names).intersection(other_names)):
-                my_file = my_container.get_member(name)
-                other_file = other_container.get_member(name)
-                inner_difference = diffoscope.comparators.compare_files(
-                                       my_file, other_file, source=name)
-                meta_differences = compare_meta(my_file.name, other_file.name)
-                if meta_differences and not inner_difference:
-                    inner_difference = Difference(None, my_file.path, other_file.path)
-                if inner_difference:
-                    inner_difference.add_details(meta_differences)
-                    differences.append(inner_difference)
+        my_container = DirectoryContainer(self)
+        other_container = DirectoryContainer(other)
+        my_names = my_container.get_member_names()
+        other_names = other_container.get_member_names()
+        for name in sorted(set(my_names).intersection(other_names)):
+            my_file = my_container.get_member(name)
+            other_file = other_container.get_member(name)
+            inner_difference = diffoscope.comparators.compare_files(
+                                   my_file, other_file, source=name)
+            meta_differences = compare_meta(my_file.name, other_file.name)
+            if meta_differences and not inner_difference:
+                inner_difference = Difference(None, my_file.path, other_file.path)
+            if inner_difference:
+                inner_difference.add_details(meta_differences)
+                differences.append(inner_difference)
         if not differences:
             return None
         difference = Difference(None, self.path, other.path, source)
@@ -152,21 +152,16 @@ class FilesystemDirectory(object):
 
 
 class DirectoryContainer(Container):
-    @contextmanager
-    def open(self):
-        self._path = self.source.path.rstrip('/') or '/'
-        yield self
-        self._path = None
-
     def get_member_names(self):
+        path = self.source.path
         names = []
-        for root, _, files in os.walk(self._path):
-            if root == self._path:
+        for root, _, files in os.walk(path):
+            if root == path:
                 root = ''
             else:
-                root = root[len(self._path) + 1:]
+                root = root[len(path) + 1:]
             names.extend([os.path.join(root, f) for f in files])
         return names
 
     def get_member(self, member_name):
-        return FilesystemFile(os.path.join(self._path, member_name))
+        return FilesystemFile(os.path.join(self.source.path, member_name))
diff --git a/diffoscope/comparators/gzip.py b/diffoscope/comparators/gzip.py
index 481b028..defb376 100644
--- a/diffoscope/comparators/gzip.py
+++ b/diffoscope/comparators/gzip.py
@@ -27,22 +27,18 @@ from diffoscope.difference import Difference
 
 
 class GzipContainer(Archive):
-    @property
-    def path(self):
-        return self._path
-
-    def open_archive(self, path):
-        self._path = path
+    def open_archive(self):
+        logger.debug('opening gzip %s', self)
         return self
 
     def close_archive(self):
-        self._path = None
+        pass
 
     def get_members(self):
         return {'gzip-content': self.get_member(self.get_member_names()[0])}
 
     def get_member_names(self):
-        return [get_compressed_content_name(self.path, '.gz')]
+        return [get_compressed_content_name(self.source.path, '.gz')]
 
     @tool_required('gzip')
     def extract(self, member_name, dest_dir):
@@ -50,12 +46,13 @@ class GzipContainer(Archive):
         logger.debug('gzip extracting to %s', dest_path)
         with open(dest_path, 'wb') as fp:
             subprocess.check_call(
-                ["gzip", "--decompress", "--stdout", self.path],
+                ["gzip", "--decompress", "--stdout", self.source.path],
                 shell=False, stdout=fp, stderr=None)
         return dest_path
 
 
 class GzipFile(object):
+    CONTAINER_CLASS = GzipContainer
     RE_FILE_TYPE = re.compile(r'^gzip compressed data\b')
 
     @staticmethod
@@ -66,7 +63,5 @@ class GzipFile(object):
         differences = []
         differences.append(Difference.from_text(
                                self.magic_file_type, other.magic_file_type, self, other, source='metadata'))
-        with GzipContainer(self).open() as my_container, \
-             GzipContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/diffoscope/comparators/iso9660.py b/diffoscope/comparators/iso9660.py
index 3eca892..f194fef 100644
--- a/diffoscope/comparators/iso9660.py
+++ b/diffoscope/comparators/iso9660.py
@@ -62,6 +62,7 @@ class ISO9660Listing(Command):
 
 
 class Iso9660File(File):
+    CONTAINER_CLASS = LibarchiveContainer
     RE_FILE_TYPE = re.compile(r'\bISO 9660\b')
 
     @staticmethod
@@ -77,7 +78,5 @@ class Iso9660File(File):
                 differences.append(Difference.from_command(ISO9660Listing, self.path, other.path, command_args=(extension,)))
             except subprocess.CalledProcessError:
                 pass # probably no joliet or rockridge data
-        with LibarchiveContainer(self).open() as my_container, \
-             LibarchiveContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/diffoscope/comparators/libarchive.py b/diffoscope/comparators/libarchive.py
index 9a79312..2a49d95 100644
--- a/diffoscope/comparators/libarchive.py
+++ b/diffoscope/comparators/libarchive.py
@@ -105,7 +105,7 @@ class LibarchiveDevice(Device, LibarchiveMember):
 
 
 class LibarchiveContainer(Archive):
-    def open_archive(self, path):
+    def open_archive(self):
         # libarchive is very very stream oriented an not for random access
         # so we are going to reopen the archive everytime
         # not nice, but it'll work
diff --git a/diffoscope/comparators/rpm.py b/diffoscope/comparators/rpm.py
index c693598..f6c638b 100644
--- a/diffoscope/comparators/rpm.py
+++ b/diffoscope/comparators/rpm.py
@@ -78,16 +78,11 @@ def compare_rpm_headers(path1, path2):
 
 
 class RpmContainer(Archive):
-    @property
-    def path(self):
-        return self._path
-
-    def open_archive(self, path):
-        self._path = path
+    def open_archive(self):
         return self
 
     def close_archive(self):
-        self._path = None
+        pass
 
     def get_member_names(self):
         return ['content']
@@ -96,17 +91,17 @@ class RpmContainer(Archive):
     def extract(self, member_name, dest_dir):
         assert member_name == 'content'
         dest_path = os.path.join(dest_dir, 'content')
-        cmd = ['rpm2cpio', self._path]
+        cmd = ['rpm2cpio', self.source.path]
         with open(dest_path, 'wb') as dest:
             subprocess.check_call(cmd, shell=False, stdout=dest, stderr=subprocess.PIPE)
         return dest_path
 
 
 class RpmFile(AbstractRpmFile):
+    CONTAINER_CLASS = RpmContainer
+
     def compare_details(self, other, source=None):
         differences = []
         differences.append(compare_rpm_headers(self.path, other.path))
-        with RpmContainer(self).open() as my_container, \
-             RpmContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/diffoscope/comparators/squashfs.py b/diffoscope/comparators/squashfs.py
index 81889a2..b2b5b2f 100644
--- a/diffoscope/comparators/squashfs.py
+++ b/diffoscope/comparators/squashfs.py
@@ -165,8 +165,8 @@ class SquashfsContainer(Archive):
             else:
                 logger.warning('Unknown squashfs entry: %s', line)
 
-    def open_archive(self, path):
-        return dict([(m.name, m) for m in self.entries(path)])
+    def open_archive(self):
+        return dict([(m.name, m) for m in self.entries(self.source.path)])
 
     def close_archive(self):
         pass
@@ -188,6 +188,7 @@ class SquashfsContainer(Archive):
 
 
 class SquashfsFile(File):
+    CONTAINER_CLASS = SquashfsContainer
     RE_FILE_TYPE = re.compile(r'^Squashfs filesystem\b')
 
     @staticmethod
@@ -198,7 +199,5 @@ class SquashfsFile(File):
         differences = []
         differences.append(Difference.from_command(SquashfsSuperblock, self.path, other.path))
         differences.append(Difference.from_command(SquashfsListing, self.path, other.path))
-        with SquashfsContainer(self).open() as my_container, \
-             SquashfsContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/diffoscope/comparators/symlink.py b/diffoscope/comparators/symlink.py
index defd89f..f9b4664 100644
--- a/diffoscope/comparators/symlink.py
+++ b/diffoscope/comparators/symlink.py
@@ -23,7 +23,7 @@ import tempfile
 from diffoscope.comparators.binary import File
 from diffoscope.comparators.utils import format_symlink
 from diffoscope.difference import Difference
-from diffoscope import logger
+from diffoscope import logger, get_named_temporary_file
 
 
 class Symlink(File):
@@ -36,7 +36,7 @@ class Symlink(File):
         return os.readlink(self.name)
 
     def create_placeholder(self):
-        with tempfile.NamedTemporaryFile('w+', suffix='diffoscope', delete=False) as f:
+        with get_named_temporary_file('w+', suffix='diffoscope', delete=False) as f:
             f.write(format_symlink(self.symlink_destination))
             f.flush()
             return f.name
@@ -51,6 +51,7 @@ class Symlink(File):
         if hasattr(self, '_placeholder'):
             os.remove(self._placeholder)
             del self._placeholder
+        super().cleanup()
 
     def compare(self, other, source=None):
         logger.debug('my_content %s', self.path)
diff --git a/diffoscope/comparators/tar.py b/diffoscope/comparators/tar.py
index 2aba6f7..a876bec 100644
--- a/diffoscope/comparators/tar.py
+++ b/diffoscope/comparators/tar.py
@@ -33,6 +33,7 @@ class TarListing(Command):
 
 
 class TarFile(File):
+    CONTAINER_CLASS = TarContainer
     RE_FILE_TYPE = re.compile(r'\btar archive\b')
 
     @staticmethod
@@ -41,8 +42,6 @@ class TarFile(File):
 
     def compare_details(self, other, source=None):
         differences = []
-        with TarContainer(self).open() as my_container, \
-             TarContainer(other).open() as other_container:
-            differences.append(Difference.from_command(TarListing, self.path, other.path))
-            differences.extend(my_container.compare(other_container))
+        differences.append(Difference.from_command(TarListing, self.path, other.path))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/diffoscope/comparators/utils.py b/diffoscope/comparators/utils.py
index b6132a0..b5716ea 100644
--- a/diffoscope/comparators/utils.py
+++ b/diffoscope/comparators/utils.py
@@ -26,14 +26,13 @@ import os
 import shutil
 from stat import S_ISCHR, S_ISBLK
 import subprocess
-from tempfile import TemporaryDirectory
 import tempfile
 from threading import Thread
 import diffoscope.comparators
 from diffoscope.comparators.binary import File, NonExistingFile
 from diffoscope.config import Config
 from diffoscope.difference import Difference
-from diffoscope import logger, tool_required
+from diffoscope import logger, tool_required, get_temporary_directory
 
 
 @tool_required('ar')
@@ -165,10 +164,6 @@ class Container(object, metaclass=ABCMeta):
     def source(self):
         return self._source
 
-    @contextmanager
-    def open(self):
-        raise NotImplemented
-
     def get_members(self):
         """Returns a directory. The key is what is used to match when comparing containers."""
         return {name: self.get_member(name) for name in self.get_member_names()}
@@ -182,9 +177,11 @@ class Container(object, metaclass=ABCMeta):
         raise NotImplemented
 
     def comparisons(self, other):
+        logger.debug('new comparisons %s vs. %s', self, other)
         my_members = self.get_members()
         other_members = other.get_members()
         for name in sorted(my_members.keys() & other_members.keys()):
+            logger.debug('comparisons %s', name)
             yield my_members.pop(name), other_members.pop(name), NO_COMMENT
         for my_name, other_name, score in diffoscope.comparators.perform_fuzzy_matching(my_members, other_members):
             comment = 'Files similar despite different names (difference score: %d)' % score
@@ -198,7 +195,7 @@ class Container(object, metaclass=ABCMeta):
                 yield NonExistingFile('/dev/null', other_file), other_file, NO_COMMENT
 
     def compare(self, other, source=None):
-        return list(starmap(diffoscope.comparators.compare_commented_files, self.comparisons(other)))
+        return starmap(diffoscope.comparators.compare_commented_files, self.comparisons(other))
 
 
 class ArchiveMember(File):
@@ -221,9 +218,8 @@ class ArchiveMember(File):
         if self._path is None:
             logger.debug('unpacking %s', self._name)
             assert self._temp_dir is None
-            self._temp_dir = TemporaryDirectory(suffix='diffoscope')
-            with self._container.open() as container:
-                self._path = container.extract(self._name, self._temp_dir.name)
+            self._temp_dir = get_temporary_directory(suffix='diffoscope')
+            self._path = self.container.extract(self._name, self._temp_dir.name)
         return self._path
 
     def cleanup(self):
@@ -232,6 +228,7 @@ class ArchiveMember(File):
         if self._temp_dir is not None:
             self._temp_dir.cleanup()
             self._temp_dir = None
+        super().cleanup()
 
     def is_directory(self):
         return False
@@ -244,30 +241,25 @@ class ArchiveMember(File):
 
 
 class Archive(Container, metaclass=ABCMeta):
+    def __new__(cls, source, *args, **kwargs):
+        if isinstance(source, NonExistingFile):
+            return super(Container, NonExistingArchive).__new__(NonExistingArchive)
+        else:
+            return super(Container, cls).__new__(cls)
+
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        self._archive = None
-
-    @contextmanager
-    def open(self):
-        if isinstance(self.source, NonExistingFile):
-            yield NonExistingArchive(self.source)
-        elif self._archive is not None:
-            yield self
-        else:
-            self._archive = self.open_archive(self.source.path)
-            try:
-                yield self
-            finally:
-                self.close_archive()
-                self._archive = None
+        self._archive = self.open_archive()
+
+    def __del__(self):
+        self.close_archive()
 
     @property
     def archive(self):
         return self._archive
 
     @abstractmethod
-    def open_archive(self, path):
+    def open_archive(self):
         raise NotImplemented
 
     @abstractmethod
@@ -298,17 +290,11 @@ class NonExistingArchiveLikeObject(object):
 
 
 class NonExistingArchive(Archive):
-    @property
-    def archive(self):
-        return NonExistingArchiveLikeObject()
-
     def open_archive(self):
-        # should never be called
-        raise NotImplemented
+        return NonExistingArchiveLikeObject()
 
     def close_archive(self):
-        # should never be called
-        raise NotImplemented
+        pass
 
     def get_member_names(self):
         return []
diff --git a/diffoscope/comparators/xz.py b/diffoscope/comparators/xz.py
index 9ff9713..98dc81d 100644
--- a/diffoscope/comparators/xz.py
+++ b/diffoscope/comparators/xz.py
@@ -27,22 +27,17 @@ from diffoscope import logger, tool_required
 
 
 class XzContainer(Archive):
-    @property
-    def path(self):
-        return self._path
-
-    def open_archive(self, path):
-        self._path = path
+    def open_archive(self):
         return self
 
     def close_archive(self):
-        self._path = None
+        pass
 
     def get_members(self):
         return {'xz-content': self.get_member(self.get_member_names()[0])}
 
     def get_member_names(self):
-        return [get_compressed_content_name(self.path, '.xz')]
+        return [get_compressed_content_name(self.source.path, '.xz')]
 
     @tool_required('xz')
     def extract(self, member_name, dest_dir):
@@ -50,12 +45,13 @@ class XzContainer(Archive):
         logger.debug('xz extracting to %s', dest_path)
         with open(dest_path, 'wb') as fp:
             subprocess.check_call(
-                ["xz", "--decompress", "--stdout", self.path],
+                ["xz", "--decompress", "--stdout", self.source.path],
                 shell=False, stdout=fp, stderr=None)
         return dest_path
 
 
 class XzFile(File):
+    CONTAINER_CLASS = XzContainer
     RE_FILE_TYPE = re.compile(r'^XZ compressed data$')
 
     @staticmethod
@@ -63,6 +59,4 @@ class XzFile(File):
         return XzFile.RE_FILE_TYPE.match(file.magic_file_type)
 
     def compare_details(self, other, source=None):
-        with XzContainer(self).open() as my_container, \
-             XzContainer(other).open() as other_container:
-            return my_container.compare(other_container)
+        return self.as_container.compare(other.as_container)
diff --git a/diffoscope/comparators/zip.py b/diffoscope/comparators/zip.py
index 00c80ca..103cbf3 100644
--- a/diffoscope/comparators/zip.py
+++ b/diffoscope/comparators/zip.py
@@ -73,8 +73,8 @@ class ZipDirectory(Directory, ArchiveMember):
 
 
 class ZipContainer(Archive):
-    def open_archive(self, path):
-        return zipfile.ZipFile(path, 'r')
+    def open_archive(self):
+        return zipfile.ZipFile(self.source.path, 'r')
 
     def close_archive(self):
         self.archive.close()
@@ -100,6 +100,7 @@ class ZipContainer(Archive):
 
 
 class ZipFile(File):
+    CONTAINER_CLASS = ZipContainer
     RE_FILE_TYPE = re.compile(r'^(Zip archive|Java archive|EPUB document)\b')
 
     @staticmethod
@@ -112,7 +113,5 @@ class ZipFile(File):
         zipinfo_difference = Difference.from_command(Zipinfo, self.path, other.path) or \
                              Difference.from_command(ZipinfoVerbose, self.path, other.path)
         differences.append(zipinfo_difference)
-        with ZipContainer(self).open() as my_container, \
-             ZipContainer(other).open() as other_container:
-            differences.extend(my_container.compare(other_container))
+        differences.extend(self.as_container.compare(other.as_container))
         return differences
diff --git a/tests/comparators/test_cpio.py b/tests/comparators/test_cpio.py
index 7fc0853..8430955 100644
--- a/tests/comparators/test_cpio.py
+++ b/tests/comparators/test_cpio.py
@@ -23,6 +23,7 @@ from diffoscope.comparators import specialize
 from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
 from diffoscope.comparators.cpio import CpioFile
 from diffoscope.config import Config
+from diffoscope.presenters.text import output_text
 from conftest import tool_missing
 
 TEST_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.cpio')
@@ -70,5 +71,6 @@ def test_compressed_files(differences):
 def test_compare_non_existing(monkeypatch, cpio1):
     monkeypatch.setattr(Config.general, 'new_file', True)
     difference = cpio1.compare(NonExistingFile('/nonexisting', cpio1))
+    output_text(difference, print_func=print)
     assert difference.source2 == '/nonexisting'
     assert difference.details[-1].source2 == '/dev/null'

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git



More information about the Reproducible-commits mailing list