Commit 185077c8 authored by Chris Lamb's avatar Chris Lamb 💬

Support .deb archives that contain an uncompressed data.tar. Thanks to...

Support .deb archives that contain an uncompressed data.tar. Thanks to Roderich Schupp <roderich.schupp@gmail.com> for the bug report. (Closes: #903401)
parent 79d8c77f
Pipeline #12792 failed with stage
in 8 minutes and 47 seconds
......@@ -201,6 +201,6 @@ class DebDataTarFile(File):
isinstance(file.container.source.container.source, DebFile)
def compare_details(self, other, source=None):
return [Difference.from_text_readers(list_libarchive(self.path),
list_libarchive(other.path),
return [Difference.from_text_readers(list_libarchive(self.path, ignore_errors=True),
list_libarchive(other.path, ignore_errors=True),
self.path, other.path, source="file list")]
......@@ -95,32 +95,36 @@ libarchive.ArchiveEntry.pathname = property(lambda self: libarchive.ffi.entry_pa
self._entry_p).decode('utf-8', errors='surrogateescape'))
def list_libarchive(path):
with libarchive.file_reader(path) as archive:
for entry in archive:
if entry.isblk or entry.ischr:
size_or_dev = '{major:>3},{minor:>3}'.format(
major=entry.rdevmajor, minor=entry.rdevminor)
else:
size_or_dev = entry.size
mtime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(entry.mtime)
) + '.{:06d}'.format(entry.mtime_nsec // 1000)
if entry.issym:
name_and_link = '{entry.name} -> {entry.linkname}'.format(
entry=entry)
else:
name_and_link = entry.name
if entry.uname:
user = '{user:<8} {uid:>7}'.format(user=entry.uname.decode(
'utf-8', errors='surrogateescape'), uid='({})'.format(entry.uid))
else:
user = entry.uid
if entry.gname:
group = '{group:<8} {gid:>7}'.format(group=entry.gname.decode(
'utf-8', errors='surrogateescape'), gid='({})'.format(entry.gid))
else:
group = entry.gid
yield '{strmode} {entry.nlink:>3} {user:>8} {group:>8} {size_or_dev:>8} {mtime:>8} {name_and_link}\n'.format(strmode=entry.strmode.decode('us-ascii'), entry=entry, user=user, group=group, size_or_dev=size_or_dev, mtime=mtime, name_and_link=name_and_link)
def list_libarchive(path, ignore_errors=False):
try:
with libarchive.file_reader(path) as archive:
for entry in archive:
if entry.isblk or entry.ischr:
size_or_dev = '{major:>3},{minor:>3}'.format(
major=entry.rdevmajor, minor=entry.rdevminor)
else:
size_or_dev = entry.size
mtime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(entry.mtime)
) + '.{:06d}'.format(entry.mtime_nsec // 1000)
if entry.issym:
name_and_link = '{entry.name} -> {entry.linkname}'.format(
entry=entry)
else:
name_and_link = entry.name
if entry.uname:
user = '{user:<8} {uid:>7}'.format(user=entry.uname.decode(
'utf-8', errors='surrogateescape'), uid='({})'.format(entry.uid))
else:
user = entry.uid
if entry.gname:
group = '{group:<8} {gid:>7}'.format(group=entry.gname.decode(
'utf-8', errors='surrogateescape'), gid='({})'.format(entry.gid))
else:
group = entry.gid
yield '{strmode} {entry.nlink:>3} {user:>8} {group:>8} {size_or_dev:>8} {mtime:>8} {name_and_link}\n'.format(strmode=entry.strmode.decode('us-ascii'), entry=entry, user=user, group=group, size_or_dev=size_or_dev, mtime=mtime, name_and_link=name_and_link)
except libarchive.exception.ArchiveError:
if not ignore_errors:
raise
class LibarchiveMember(ArchiveMember):
......@@ -211,11 +215,14 @@ class LibarchiveContainer(Archive):
raise KeyError('%s not found in archive', member_name)
def get_filtered_members(self):
with libarchive.file_reader(self.source.path) as archive:
for entry in archive:
if any_excluded(entry.pathname):
continue
yield entry.pathname, self.get_subclass(entry)
try:
with libarchive.file_reader(self.source.path) as archive:
for entry in archive:
if any_excluded(entry.pathname):
continue
yield entry.pathname, self.get_subclass(entry)
except libarchive.exception.ArchiveError:
pass
def extract(self, member_name, dest_dir):
self.ensure_unpacked()
......
......@@ -132,6 +132,8 @@ bug881937_deb1 = load_fixture('bug881937_1.deb')
bug881937_deb2 = load_fixture('bug881937_2.deb')
bug903391_deb1 = load_fixture('bug903391_1.deb')
bug903391_deb2 = load_fixture('bug903391_2.deb')
bug903401_deb1 = load_fixture('bug903401_1.deb')
bug903401_deb2 = load_fixture('bug903401_2.deb')
@skip_unless_tools_exist('xz')
......@@ -143,5 +145,9 @@ def test_compare_different_compression(bug881937_deb1, bug881937_deb2):
assert difference.details[1].details[2].details[1].unified_diff == expected_diff
def test_uncompressed_data_tar(bug903401_deb1, bug903401_deb2):
bug903401_deb1.compare(bug903401_deb2)
def test_uncompressed_control_tar(bug903391_deb1, bug903391_deb2):
bug903391_deb1.compare(bug903391_deb2)
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