[Reproducible-commits] [diffoscope] 01/01: Added comparator for filesystem images
Reiner Herrmann
reiner at reiner-h.de
Wed Dec 2 22:08:15 UTC 2015
This is an automated email from the git hooks/post-receive script.
deki-guest pushed a commit to branch master
in repository diffoscope.
commit 9593b9bade96713a6efc99b96f39438818a54d2f
Author: Reiner Herrmann <reiner at reiner-h.de>
Date: Wed Dec 2 22:56:25 2015 +0100
Added comparator for filesystem images
---
debian/control | 1 +
diffoscope/comparators/__init__.py | 2 +
diffoscope/comparators/fsimage.py | 91 +++++++++++++++++++++++++++++++++++++
tests/comparators/test_fsimage.py | 76 +++++++++++++++++++++++++++++++
tests/data/ext4_expected_diffs | 12 +++++
tests/data/test1.ext4 | Bin 0 -> 256000 bytes
tests/data/test2.ext4 | Bin 0 -> 256000 bytes
7 files changed, 182 insertions(+)
diff --git a/debian/control b/debian/control
index 28bed7e..29fadd2 100644
--- a/debian/control
+++ b/debian/control
@@ -11,6 +11,7 @@ Build-Depends: binutils-multiarch,
python3-all,
python3-debian,
python3-docutils,
+ python3-guestfs,
python3-libarchive-c,
python3-magic,
python3-pytest,
diff --git a/diffoscope/comparators/__init__.py b/diffoscope/comparators/__init__.py
index efa85c7..00cd242 100644
--- a/diffoscope/comparators/__init__.py
+++ b/diffoscope/comparators/__init__.py
@@ -47,6 +47,7 @@ from diffoscope.comparators.device import Device
from diffoscope.comparators.dex import DexFile
from diffoscope.comparators.directory import Directory, compare_directories
from diffoscope.comparators.elf import ElfFile, StaticLibFile
+from diffoscope.comparators.fsimage import FsImageFile
from diffoscope.comparators.fonts import TtfFile
from diffoscope.comparators.gettext import MoFile
from diffoscope.comparators.gzip import GzipFile
@@ -132,6 +133,7 @@ FILE_CLASSES = (
DebFile,
DexFile,
ElfFile,
+ FsImageFile,
StaticLibFile,
Sqlite3Database,
TtfFile,
diff --git a/diffoscope/comparators/fsimage.py b/diffoscope/comparators/fsimage.py
new file mode 100644
index 0000000..f6dd8b3
--- /dev/null
+++ b/diffoscope/comparators/fsimage.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+#
+# diffoscope: in-depth comparison of files, archives, and directories
+#
+# Copyright © 2015 Reiner Herrmann <reiner at reiner-h.de>
+#
+# diffoscope 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 3 of the License, or
+# (at your option) any later version.
+#
+# diffoscope is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with diffoscope. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import os.path
+try:
+ import guestfs
+except ImportError:
+ guestfs = None
+from diffoscope import logger
+from diffoscope.comparators.binary import File, needs_content
+from diffoscope.comparators.utils import Archive, get_compressed_content_name
+from diffoscope.difference import Difference
+
+
+class FsImageContainer(Archive):
+ @property
+ def path(self):
+ return self._path
+
+ def open_archive(self, path):
+ self._path = path
+
+ if not guestfs:
+ return None
+
+ self.g = guestfs.GuestFS (python_return_dict=True)
+ self.g.add_drive_opts (self.path, format="raw", readonly=1)
+ self.g.launch()
+ devices = self.g.list_devices()
+ self.g.mount(devices[0], "/")
+ self.fs = self.g.list_filesystems()[devices[0]]
+ return self
+
+ def close_archive(self):
+ self.g.umount_all()
+ self.g.close()
+ self._path = None
+
+ def get_members(self):
+ return {'fsimage-content': self.get_member(self.get_member_names()[0])}
+
+ def get_member_names(self):
+ return [os.path.basename(self.path) + '.tar']
+
+ def extract(self, member_name, dest_dir):
+ dest_path = os.path.join(dest_dir, member_name)
+ logger.debug('filesystem image extracting to %s', dest_path)
+ self.g.tar_out("/", dest_path)
+
+ return dest_path
+
+class FsImageFile(File):
+ RE_FILE_TYPE = re.compile(r'^(Linux.*filesystem data|BTRFS Filesystem).*')
+
+ @staticmethod
+ def recognizes(file):
+ return FsImageFile.RE_FILE_TYPE.match(file.magic_file_type)
+
+ @needs_content
+ def compare_details(self, other, source=None):
+ differences = []
+ with FsImageContainer(self).open() as my_container, \
+ FsImageContainer(other).open() as other_container:
+ my_fs = ''
+ other_fs = ''
+ if hasattr(my_container, 'fs'):
+ my_fs = my_container.fs
+ if hasattr(other_container, 'fs'):
+ other_fs = other_container.fs
+ if my_fs != other_fs:
+ differences.append(Difference.from_text(my_fs, other_fs,
+ None, None, source="filesystem"))
+ differences.extend(my_container.compare(other_container))
+ return differences
diff --git a/tests/comparators/test_fsimage.py b/tests/comparators/test_fsimage.py
new file mode 100644
index 0000000..91d6cec
--- /dev/null
+++ b/tests/comparators/test_fsimage.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+#
+# diffoscope: in-depth comparison of files, archives, and directories
+#
+# Copyright © 2015 Reiner Herrmann <reiner at reiner-h.de>
+#
+# diffoscope 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 3 of the License, or
+# (at your option) any later version.
+#
+# diffoscope is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with diffoscope. If not, see <http://www.gnu.org/licenses/>.
+
+import os.path
+import pytest
+try:
+ import guestfs
+ miss_guestfs = False
+except ImportError:
+ miss_guestfs = True
+from diffoscope.comparators import specialize
+from diffoscope.comparators.binary import FilesystemFile, NonExistingFile
+from diffoscope.comparators.fsimage import FsImageFile
+from diffoscope.config import Config
+from conftest import tool_missing
+
+TEST_FILE1_PATH = os.path.join(os.path.dirname(__file__), '../data/test1.ext4')
+TEST_FILE2_PATH = os.path.join(os.path.dirname(__file__), '../data/test2.ext4')
+
+ at pytest.fixture
+def img1():
+ return specialize(FilesystemFile(TEST_FILE1_PATH))
+
+ at pytest.fixture
+def img2():
+ return specialize(FilesystemFile(TEST_FILE2_PATH))
+
+def test_identification(img1):
+ assert isinstance(img1, FsImageFile)
+
+def test_no_differences(img1):
+ difference = img1.compare(img1)
+ assert difference is None
+
+ at pytest.fixture
+def differences(img1, img2):
+ return img1.compare(img2).details
+
+ at pytest.mark.skipif(miss_guestfs, reason='guestfs is missing')
+def test_differences(differences):
+ assert differences[0].source1 == 'test1.ext4.tar'
+ tarinfo = differences[0].details[0]
+ tardiff = differences[0].details[1]
+ encodingdiff = tardiff.details[0]
+ assert tarinfo.source1 == 'tar --full-time -tvf {}'
+ assert tarinfo.source2 == 'tar --full-time -tvf {}'
+ assert tardiff.source1 == './date.txt'
+ assert tardiff.source2 == './date.txt'
+ assert encodingdiff.source1 == 'encoding'
+ assert encodingdiff.source2 == 'encoding'
+ expected_diff = open(os.path.join(os.path.dirname(__file__), '../data/ext4_expected_diffs')).read()
+ found_diff = tarinfo.unified_diff + tardiff.unified_diff + encodingdiff.unified_diff
+ assert expected_diff == found_diff
+
+ at pytest.mark.skipif(miss_guestfs, reason='guestfs is missing')
+def test_compare_non_existing(monkeypatch, img1):
+ monkeypatch.setattr(Config.general, 'new_file', True)
+ difference = img1.compare(NonExistingFile('/nonexisting', img1))
+ assert difference.source2 == '/nonexisting'
+ assert difference.details[-1].source2 == '/dev/null'
diff --git a/tests/data/ext4_expected_diffs b/tests/data/ext4_expected_diffs
new file mode 100644
index 0000000..3b0ff80
--- /dev/null
+++ b/tests/data/ext4_expected_diffs
@@ -0,0 +1,12 @@
+@@ -1,3 +1,3 @@
+-drwxr-xr-x 0/0 0 2015-12-02 16:01:40 ./
++drwxr-xr-x 0/0 0 2015-12-02 16:03:11 ./
+ drwx------ 0/0 0 2015-12-02 16:00:55 ./lost+found/
+--rw-rw-rw- 1234/1234 28 2015-12-02 16:01:40 ./date.txt
++-r--r--r-- 4321/4321 44 2015-12-02 16:03:11 ./date.txt
+@@ -1 +1 @@
+-Wed Dec 2 17:01:40 CET 2015
++jeudi 3 décembre 2015, 06:03:11 (UTC+1400)
+@@ -1 +1 @@
+-us-ascii
++utf-8
diff --git a/tests/data/test1.ext4 b/tests/data/test1.ext4
new file mode 100644
index 0000000..3674521
Binary files /dev/null and b/tests/data/test1.ext4 differ
diff --git a/tests/data/test2.ext4 b/tests/data/test2.ext4
new file mode 100644
index 0000000..3183c03
Binary files /dev/null and b/tests/data/test2.ext4 differ
--
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