Commit d494730e authored by Xavier Briand's avatar Xavier Briand

Add lz4 comparator

Closes: #901548
parent bac105b9
...@@ -57,6 +57,7 @@ Build-Depends: ...@@ -57,6 +57,7 @@ Build-Depends:
python3-guestfs <!nocheck>, python3-guestfs <!nocheck>,
python3-jsondiff <!nocheck>, python3-jsondiff <!nocheck>,
python3-libarchive-c, python3-libarchive-c,
python3-lz4 <!nocheck>,
python3-magic, python3-magic,
python3-progressbar <!nocheck>, python3-progressbar <!nocheck>,
python3-pytest <!nocheck>, python3-pytest <!nocheck>,
......
...@@ -64,6 +64,7 @@ class ComparatorManager(object): ...@@ -64,6 +64,7 @@ class ComparatorManager(object):
('icc.IccFile',), ('icc.IccFile',),
('iso9660.Iso9660File',), ('iso9660.Iso9660File',),
('java.ClassFile',), ('java.ClassFile',),
('lz4.Lz4File',),
('mono.MonoExeFile',), ('mono.MonoExeFile',),
('pdf.PdfFile',), ('pdf.PdfFile',),
('png.PngFile',), ('png.PngFile',),
......
# -*- coding: utf-8 -*-
#
# diffoscope: in-depth comparison of files, archives, and directories
#
# Copyright © 2018 Xavier Briand <xavierbriand@gmail.com>
#
# 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 <https://www.gnu.org/licenses/>.
import re
import os.path
import logging
import subprocess
from diffoscope.tools import tool_required
from .utils.file import File
from .utils.archive import Archive
logger = logging.getLogger(__name__)
class Lz4Container(Archive):
def open_archive(self):
return self
def close_archive(self):
pass
def get_member_names(self):
return [self.get_compressed_content_name('.lz4')]
@tool_required('lz4')
def extract(self, member_name, dest_dir):
dest_path = os.path.join(dest_dir, member_name)
logger.debug('lz4 extracting to %s', dest_path)
with open(dest_path, 'wb') as fp:
subprocess.check_call(
["lz4", "-d", "-c", self.source.path],
shell=False, stdout=fp, stderr=None)
return dest_path
class Lz4File(File):
DESCRIPTION = "LZ4 compressed files"
CONTAINER_CLASS = Lz4Container
FILE_TYPE_RE = re.compile(r'^LZ4 compressed data \([^\)]+\)$')
# Work around file(1) Debian bug #876316
FALLBACK_FILE_EXTENSION_SUFFIX = ".lz4"
FALLBACK_FILE_TYPE_HEADER_PREFIX = b"\x04\x22M\x18"
...@@ -145,6 +145,10 @@ EXTERNAL_TOOLS = { ...@@ -145,6 +145,10 @@ EXTERNAL_TOOLS = {
'arch': 'e2fsprogs', 'arch': 'e2fsprogs',
'FreeBSD': 'e2fsprogs', 'FreeBSD': 'e2fsprogs',
}, },
'lz4': {
'debian': 'lz4',
'FreeBSD': 'lz4',
},
'msgunfmt': { 'msgunfmt': {
'debian': 'gettext', 'debian': 'gettext',
'arch': 'gettext', 'arch': 'gettext',
......
# -*- coding: utf-8 -*-
#
# diffoscope: in-depth comparison of files, archives, and directories
#
# Copyright © 2018 Xavier Briand <xavierbriand@gmail.com>
#
# 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 <https://www.gnu.org/licenses/>.
import shutil
import pytest
from diffoscope.comparators.lz4 import Lz4File
from diffoscope.comparators.binary import FilesystemFile
from diffoscope.comparators.utils.specialize import specialize
from ..utils.data import load_fixture, get_data
from ..utils.tools import skip_unless_tools_exist
from ..utils.nonexisting import assert_non_existing
lz41 = load_fixture('test1.lz4')
lz42 = load_fixture('test2.lz4')
def test_identification(lz41):
assert isinstance(lz41, Lz4File)
def test_no_differences(lz41):
difference = lz41.compare(lz41)
assert difference is None
@pytest.fixture
def differences(lz41, lz42):
return lz41.compare(lz42).details
@skip_unless_tools_exist('lz4')
def test_content_source(differences):
assert differences[0].source1 == 'test1'
assert differences[0].source2 == 'test2'
@skip_unless_tools_exist('lz4')
def test_content_source_without_extension(tmpdir, lz41, lz42):
path1 = str(tmpdir.join('test1'))
path2 = str(tmpdir.join('test2'))
shutil.copy(lz41.path, path1)
shutil.copy(lz42.path, path2)
lz41 = specialize(FilesystemFile(path1))
lz42 = specialize(FilesystemFile(path2))
difference = lz41.compare(lz42).details
assert difference[0].source1 == 'test1-content'
assert difference[0].source2 == 'test2-content'
@skip_unless_tools_exist('lz4')
def test_content_diff(differences):
expected_diff = get_data('text_ascii_expected_diff')
assert differences[0].unified_diff == expected_diff
@skip_unless_tools_exist('lz4')
def test_compare_non_existing(monkeypatch, lz41):
assert_non_existing(monkeypatch, lz41)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment