Skip to content

Commit

Permalink
Merge #22, add proper device type parsing and regression test
Browse files Browse the repository at this point in the history
  • Loading branch information
xolox committed Apr 25, 2020
2 parents c3ef2b6 + 6369bfe commit aa3ce08
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 6 deletions.
36 changes: 31 additions & 5 deletions deb_pkg_tools/package.py
@@ -1,7 +1,7 @@
# Debian packaging tools: Package manipulation.
#
# Author: Peter Odding <peter@peterodding.com>
# Last Change: April 19, 2020
# Last Change: April 25, 2020
# URL: https://github.com/xolox/python-deb-pkg-tools

"""Functions to build and inspect Debian binary package archives (``*.deb`` files)."""
Expand Down Expand Up @@ -717,21 +717,30 @@ def inspect_package_contents(archive, cache=None):
# lrwxrwxrwx root/root 0 2013-09-26 22:29 ./usr/bin/pdb2.7 -> ../lib/python2.7/pdb.py
fields = line.split(None, 5)
permissions = fields[0]
owner, group = fields[1].split('/')
size = int(fields[2])
owner, _, group = fields[1].partition('/')
# The third field (index 2) is normally the file size, but for device
# files it gives the comma separated device type major / minor numbers.
# More details: https://github.com/xolox/python-deb-pkg-tools/pull/22
if fields[2].isdigit():
device_type = 0, 0
size = int(fields[2])
else:
major_nr, _, minor_nr = fields[2].partition(',')
device_type = int(major_nr), int(minor_nr)
size = 0
modified = fields[3] + ' ' + fields[4]
pathname = re.sub('^./', '/', fields[5])
pathname, _, target = pathname.partition(' -> ')
if not target:
pathname, _, target = pathname.partition(' link to ')
target = re.sub('^./', '/', target)
contents[pathname] = ArchiveEntry(permissions, owner, group, size, modified, target)
contents[pathname] = ArchiveEntry(permissions, owner, group, size, modified, target, device_type)
if cache:
entry.set_value(contents)
return contents


class ArchiveEntry(collections.namedtuple('ArchiveEntry', 'permissions, owner, group, size, modified, target')):
class ArchiveEntry(collections.namedtuple('ArchiveEntry', 'permissions, owner, group, size, modified, target, device_type')):

"""
A named tuple with the result of :func:`inspect_package()`.
Expand Down Expand Up @@ -759,6 +768,23 @@ class ArchiveEntry(collections.namedtuple('ArchiveEntry', 'permissions, owner, g
.. :attribute:: modified
A string like ``2013-09-26 22:28``.
.. :attribute:: target
If the entry represents a symbolic link this field gives the pathname of
the target of the symbolic link. Defaults to an empty string.
.. :attribute:: device_type
If the entry represents a device file this field gives the device type
major and minor numbers as a tuple of two integers. Defaults to a tuple
with two zeros.
.. note:: This defaults to a tuple with two zeros so that
:class:`ArchiveEntry` tuples can be reliably sorted just like
regular tuples (i.e. without getting
:exc:`~exceptions.TypeError` exceptions due to comparisons
between incompatible value types).
"""


Expand Down
32 changes: 31 additions & 1 deletion deb_pkg_tools/tests.py
@@ -1,7 +1,7 @@
# Debian packaging tools: Automated tests.
#
# Author: Peter Odding <peter@peterodding.com>
# Last Change: April 19, 2020
# Last Change: April 25, 2020
# URL: https://github.com/xolox/python-deb-pkg-tools

"""Test suite for the `deb-pkg-tools` package."""
Expand Down Expand Up @@ -59,6 +59,7 @@
find_system_dependencies,
group_by_latest_versions,
inspect_package,
inspect_package_contents,
parse_filename,
)
from deb_pkg_tools.printer import CustomPrettyPrinter
Expand Down Expand Up @@ -152,6 +153,35 @@ def test_package_cache_invalidation(self):
else:
self.load_package_cache()

def test_inspect_contents(self):
"""Test inspection of package contents."""
if os.getuid() != 0:
self.skipTest("need superuser privileges")
with Context() as finalizers:
build_directory = finalizers.mkdtemp()
create_control_file(os.path.join(build_directory, 'DEBIAN', 'control'), {
'Description': 'Bogus value for mandatory field',
'Maintainer': 'Peter Odding',
'Package': 'deb-pkg-tools-contents-test',
'Version': '1',
})
# Create a regular file entry.
touch(os.path.join(build_directory, 'regular-file-test'))
# Create a device file entry.
execute('cp', '-a', '/dev/null', os.path.join(build_directory, 'device-file-test'))
# Build the package and inspect its contents.
repository_directory = finalizers.mkdtemp()
package_file = build_package(build_directory, repository_directory)
contents = inspect_package_contents(package_file)
# Make sure the device type field is populated for the device file entry.
device_file_entry = contents['/device-file-test']
assert device_file_entry.device_type[0] > 0
assert device_file_entry.device_type[1] > 0
# Make sure the device type field is not populated for the regular entry.
regular_file_entry = contents['/regular-file-test']
assert regular_file_entry.device_type[0] == 0
assert regular_file_entry.device_type[1] == 0

def test_architecture_determination(self):
"""Make sure discovery of the current build architecture works properly."""
valid_architectures = execute('dpkg-architecture', '-L', capture=True).splitlines()
Expand Down

0 comments on commit aa3ce08

Please sign in to comment.