Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package rpmlint for openSUSE:Factory checked in at 2026-03-28 20:13:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rpmlint (Old) and /work/SRC/openSUSE:Factory/.rpmlint.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rpmlint" Sat Mar 28 20:13:46 2026 rev:533 rq:1342753 version:2.9.0+git20260326.abd95437 Changes: -------- --- /work/SRC/openSUSE:Factory/rpmlint/rpmlint.changes 2026-03-09 16:11:12.092579292 +0100 +++ /work/SRC/openSUSE:Factory/.rpmlint.new.8177/rpmlint.changes 2026-03-28 20:15:20.346345882 +0100 @@ -1,0 +2,19 @@ +Thu Mar 26 10:15:07 UTC 2026 - Wolfgang Frisch <[email protected]> + +- Update to version 2.9.0+git20260326.abd95437: + * polkit-rules-whitelist: add cosmic-settings-daemon kbd layout rule (bsc#1259403) + * polkit-rules-whitelist: add cosmic-settings wheel/sudoers rules (bsc#1259402) + * SignatureCheck: Fix _check_no_signature for rpm v6 + * Bump github/codeql-action from 4.32.6 to 4.34.1 + * SourceCheck: update string format pyupgrade --py38-plus + * SourceCheck: update string format pyupgrade --py38-plus + * Fix: #1478: Use regex for file(1) magic matching; add .zip and .zstd support + * Bump github/codeql-action from 4.32.4 to 4.32.6 + * Fix rpmdiff flags + * Bump github/codeql-action from 4.32.3 to 4.32.4 + * test: Add more cases for the man page check + * FilesCheck: fix man_base_regex + * Bump github/codeql-action from 4.32.2 to 4.32.3 + * FilesCheck: fix manpage regex to support numbers + +------------------------------------------------------------------- Old: ---- rpmlint-2.9.0+git20260304.c77499bc.tar.xz New: ---- rpmlint-2.9.0+git20260326.abd95437.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rpmlint.spec ++++++ --- /var/tmp/diff_new_pack.DJlt3N/_old 2026-03-28 20:15:21.006373123 +0100 +++ /var/tmp/diff_new_pack.DJlt3N/_new 2026-03-28 20:15:21.010373288 +0100 @@ -23,7 +23,7 @@ %define name_suffix -%{flavor} %endif Name: rpmlint%{name_suffix} -Version: 2.9.0+git20260304.c77499bc +Version: 2.9.0+git20260326.abd95437 Release: 0 Summary: RPM file correctness checker License: GPL-2.0-or-later ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.DJlt3N/_old 2026-03-28 20:15:21.074375930 +0100 +++ /var/tmp/diff_new_pack.DJlt3N/_new 2026-03-28 20:15:21.078376095 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/rpm-software-management/rpmlint.git</param> - <param name="changesrevision">c77499bc7064bbee9396364b14c4fbaf4c26448a</param></service></servicedata> + <param name="changesrevision">abd954376a34bd6922a4f2bcada7fe131f24dd6b</param></service></servicedata> (No newline at EOF) ++++++ rpmlint-2.9.0+git20260304.c77499bc.tar.xz -> rpmlint-2.9.0+git20260326.abd95437.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/.github/workflows/codeql.yml new/rpmlint-2.9.0+git20260326.abd95437/.github/workflows/codeql.yml --- old/rpmlint-2.9.0+git20260304.c77499bc/.github/workflows/codeql.yml 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/.github/workflows/codeql.yml 2026-03-26 11:14:18.000000000 +0100 @@ -25,15 +25,15 @@ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Initialize CodeQL - uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/autobuild@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: category: "/language:${{ matrix.language }}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/configs/openSUSE/polkit-rules-whitelist.toml new/rpmlint-2.9.0+git20260326.abd95437/configs/openSUSE/polkit-rules-whitelist.toml --- old/rpmlint-2.9.0+git20260304.c77499bc/configs/openSUSE/polkit-rules-whitelist.toml 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/configs/openSUSE/polkit-rules-whitelist.toml 2026-03-26 11:14:18.000000000 +0100 @@ -288,3 +288,23 @@ path = "/usr/share/polkit-1/rules.d/50-run0-sudo.rules" digester = "default" hash = "452adce8b04a88b42d0d9621e9258b5b2325ef44d01da6f65e93794d2b5f3579" + +[[FileDigestGroup]] +package = "cosmic-settings" +note = "Allow members of wheel/sudoers in a local session to adjust the keyboard layout, change hostname or talk to ModemManager" +bug = "bsc#1259402" +type = "polkit" +[[FileDigestGroup.digests]] +path = "/usr/share/polkit-1/rules.d/cosmic-settings.rules" +digester = "default" +hash = "a3ae4a1b46a191d4d851b262420e1fd4f9c09f29c9a855f662690807421f4d28" + +[[FileDigestGroup]] +package = "cosmic-settings-daemon" +note = "Allow members of wheel/sudoers in a local session to adjust the keyboard layout" +bug = "bsc#1259403" +type = "polkit" +[[FileDigestGroup.digests]] +path = "/usr/share/polkit-1/rules.d/cosmic-settings-daemon.rules" +digester = "default" +hash = "60c0b0121450c90a2f3436396406c031f9c4916945e5e15fc23c00e10594203e" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/rpmlint/checks/FilesCheck.py new/rpmlint-2.9.0+git20260326.abd95437/rpmlint/checks/FilesCheck.py --- old/rpmlint-2.9.0+git20260304.c77499bc/rpmlint/checks/FilesCheck.py 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/rpmlint/checks/FilesCheck.py 2026-03-26 11:14:18.000000000 +0100 @@ -203,7 +203,7 @@ non_readable_regexs = (re.compile(r'^/var/log/'), re.compile(r'^/etc/(g?shadow-?|securetty)$')) -man_base_regex = re.compile(r'^/usr(?:/share)?/man(?:/overrides)?/man(?P<category>[^/]+)/(?P<filename>((?P<binary>[^.]+)\..+))') +man_base_regex = re.compile(r'^/usr(?:/share)?/man(?:/overrides)?/man(?P<category>[^/]+)/(?P<filename>((?P<binary>.+)\.\d.*))') fsf_license_regex = re.compile(br'(GNU((\s+(Library|Lesser|Affero))?(\s+General)?\s+Public|\s+Free\s+Documentation)\s+Licen[cs]e|(GP|FD)L)', re.IGNORECASE) fsf_wrong_address_regex = re.compile(br'(675\s+Mass\s+Ave|59\s+Temple\s+Place|02139|51\s+Franklin\s+St)', re.IGNORECASE) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/rpmlint/checks/SignatureCheck.py new/rpmlint-2.9.0+git20260326.abd95437/rpmlint/checks/SignatureCheck.py --- old/rpmlint-2.9.0+git20260304.c77499bc/rpmlint/checks/SignatureCheck.py 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/rpmlint/checks/SignatureCheck.py 2026-03-26 11:14:18.000000000 +0100 @@ -36,7 +36,9 @@ Print an error if there is no signature present. That means that there is no mention about any signature in the 'rpm -Kv' output. """ - if retcode == 0 and not SignatureCheck.any_sig_regex.search(output): + # retcode is 1 for no-signature in rpm v6 + # retcode is 0 for no-signature in rpm v4 + if not SignatureCheck.any_sig_regex.search(output): self.output.add_info('E', pkg, 'no-signature') def _check_unknown_key(self, pkg, retcode, output): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/rpmlint/checks/SourceCheck.py new/rpmlint-2.9.0+git20260326.abd95437/rpmlint/checks/SourceCheck.py --- old/rpmlint-2.9.0+git20260304.c77499bc/rpmlint/checks/SourceCheck.py 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/rpmlint/checks/SourceCheck.py 2026-03-26 11:14:18.000000000 +0100 @@ -8,12 +8,16 @@ Validate files in a source package. """ source_regex = re.compile(r'\.(tar|tgz)$') + + # Regex patterns. Applied to a string from file(1) tool. compressed_fileext_magic = { - 'xz': 'XZ compressed', - 'gz': 'gzip compressed', - 'tgz': 'gzip compressed', - 'bz2': 'bzip2 compressed', - 'zst': 'ZSTD compressed', + 'xz': r'XZ compressed', + 'gz': r'gzip compressed', + 'tgz': r'gzip compressed', + 'bz2': r'bzip2 compressed', + 'zst': r'(ZSTD|Zstandard) compressed', + 'zstd': r'(ZSTD|Zstandard) compressed', + 'zip': r'Zip archive data', } def __init__(self, config, output): @@ -45,12 +49,16 @@ """ Check if the filename extension is the same as what file(1) says. """ + if not pkgfile.magic: + return file_ext = fname.rpartition('.')[2] - - if (file_ext in self.compressed_fileext_magic and - pkgfile.magic and - self.compressed_fileext_magic[file_ext] not in pkgfile.magic): - self.output.add_info('W', pkg, 'inconsistent-file-extension', fname) + pattern = self.compressed_fileext_magic.get(file_ext) + if pattern is None: + return # file(1) pattern is unknown for given file extension + if re.match(pattern, pkgfile.magic, re.IGNORECASE): + return + self.output.add_info('W', pkg, 'inconsistent-file-extension', + f'file {fname!r} magic {pkgfile.magic!r} does not match {pattern!r}') def _check_permissions(self, fname, pkgfile, pkg): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/rpmlint/cli.py new/rpmlint-2.9.0+git20260326.abd95437/rpmlint/cli.py --- old/rpmlint-2.9.0+git20260304.c77499bc/rpmlint/cli.py 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/rpmlint/cli.py 2026-03-26 11:14:18.000000000 +0100 @@ -47,8 +47,8 @@ parser.add_argument('-i', '--ignore', nargs='+', default=None, choices=['S', 'M', '5', 'D', 'N', 'L', 'V', 'U', 'G', 'F', 'T'], help="""file property to ignore when calculating differences. Valid values are: S (size), M (mode), 5 (checksum), D (device), - N (inode), L (number of links), V (vflags), U (user), G (group), - F (digest), T (time)""") + N (number of links), L (state), V (vflags), U (user), G (group), + F (fflags), T (time)""") parser.add_argument('-e', '--exclude', metavar='GLOB', nargs='+', default=None, help="""Paths to exclude when showing differences. Takes a glob. When absolute (starting with /) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/test/files/magic/.gitignore new/rpmlint-2.9.0+git20260326.abd95437/test/files/magic/.gitignore --- old/rpmlint-2.9.0+git20260304.c77499bc/test/files/magic/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/test/files/magic/.gitignore 2026-03-26 11:14:18.000000000 +0100 @@ -0,0 +1 @@ +!* Binary files old/rpmlint-2.9.0+git20260304.c77499bc/test/files/magic/byte.bz2 and new/rpmlint-2.9.0+git20260326.abd95437/test/files/magic/byte.bz2 differ Binary files old/rpmlint-2.9.0+git20260304.c77499bc/test/files/magic/byte.gz and new/rpmlint-2.9.0+git20260326.abd95437/test/files/magic/byte.gz differ Binary files old/rpmlint-2.9.0+git20260304.c77499bc/test/files/magic/byte.xz and new/rpmlint-2.9.0+git20260326.abd95437/test/files/magic/byte.xz differ Binary files old/rpmlint-2.9.0+git20260304.c77499bc/test/files/magic/byte.zip and new/rpmlint-2.9.0+git20260326.abd95437/test/files/magic/byte.zip differ Binary files old/rpmlint-2.9.0+git20260304.c77499bc/test/files/magic/byte.zst and new/rpmlint-2.9.0+git20260326.abd95437/test/files/magic/byte.zst differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/test/mockdata/mock_files.py new/rpmlint-2.9.0+git20260326.abd95437/test/mockdata/mock_files.py --- old/rpmlint-2.9.0+git20260304.c77499bc/test/mockdata/mock_files.py 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/test/mockdata/mock_files.py 2026-03-26 11:14:18.000000000 +0100 @@ -219,6 +219,26 @@ ) +Pip3ManPagesPackage = get_tested_mock_package( + lazyload=True, + files={ + '/usr/bin/pip': {'content': '', 'metadata': {'mode': 0o755 | stat.S_IFREG}}, + '/usr/bin/pip3': {'content': '', 'metadata': {'mode': 0o755 | stat.S_IFREG}}, + '/usr/bin/pip3.13': {'content': '', 'metadata': {'mode': 0o755 | stat.S_IFREG}}, + '/usr/bin/pip3.13.3': {'content': '', 'metadata': {'mode': 0o755 | stat.S_IFREG}}, + '/usr/bin/pip3.14': {'content': '', 'metadata': {'mode': 0o755 | stat.S_IFREG}}, + '/usr/bin/pip-3.14': {'content': '', 'metadata': {'mode': 0o755 | stat.S_IFREG}}, + '/usr/share/man/man1/pip.2': {'content': 'text'}, + '/usr/share/man/man1/pip3.1posix': {'content': 'text'}, + '/usr/share/man/man1/pip3.13.1': {'content': 'text'}, + '/usr/share/man/man1/pip3.13.3.1posix.xz': {'content': 'xz'}, + '/usr/share/man/man1/pip3.14.1.gz': {'content': 'gz'}, + '/usr/share/man/man1/pip-3.14.1.gz': {'content': 'gz'}, + }, + header={'requires': []}, +) + + DevelopmentPackage = get_tested_mock_package( lazyload=True, name='my-package-devel', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/test/test_files.py new/rpmlint-2.9.0+git20260326.abd95437/test/test_files.py --- old/rpmlint-2.9.0+git20260304.c77499bc/test/test_files.py 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/test/test_files.py 2026-03-26 11:14:18.000000000 +0100 @@ -14,6 +14,7 @@ ManualPagesPackage, NetmaskDebugsourcePackage, NonReadableGhostPackage, + Pip3ManPagesPackage, Python3PowerBrokenPackage, Python3PowerPackage, PythonShebangLinkOkPackage, @@ -238,6 +239,14 @@ assert 'This manual page is not compressed with the bz2 compression' in out [email protected]('package', [Pip3ManPagesPackage]) +def test_manpages_pip3(package, filescheck): + output, test = filescheck + test.check(package) + out = output.print_results(output.results) + assert 'no-manual-page-for-binary' not in out + + @pytest.mark.parametrize('package', [DevelopmentPackage]) def test_provides_devel(package, filescheck): output, test = filescheck diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-2.9.0+git20260304.c77499bc/test/test_sources.py new/rpmlint-2.9.0+git20260326.abd95437/test/test_sources.py --- old/rpmlint-2.9.0+git20260304.c77499bc/test/test_sources.py 2026-03-04 10:25:52.000000000 +0100 +++ new/rpmlint-2.9.0+git20260326.abd95437/test/test_sources.py 2026-03-26 11:14:18.000000000 +0100 @@ -2,7 +2,7 @@ from rpmlint.checks.SourceCheck import SourceCheck from rpmlint.filter import Filter -from Testing import CONFIG, get_tested_package +from Testing import CONFIG, get_tested_mock_package, get_tested_package @pytest.fixture(scope='function', autouse=True) @@ -39,3 +39,91 @@ assert 'multiple-specfiles' in out assert 'package contains multiple spec files' in out + + +# ── Tests for _check_file_ext (compressed_fileext_magic matching) ── +# +# Test data: test/files/magic/ contains small compressed files, each holding +# a single byte 'x'. Created with standard CLI tools: +# +# echo -n x | gzip -n > byte.gz # -n omits filename/timestamp +# echo -n x | bzip2 > byte.bz2 +# echo -n x | xz > byte.xz +# echo -n x | zstd -q > byte.zst +# echo -n x > 0 # zip needs a file on disk +# touch -t 200001010000.00 0 # fixed timestamp for reproducibility +# TZ=UTC zip -0 -j byte.zip 0 # -0 store, -j junk paths +# rm 0 +# +# In Python (bz2 is byte-identical to CLI; others differ in internal +# flags but are functionally equivalent): +# gzip.compress(b'x', mtime=0) +# bz2.compress(b'x') +# lzma.compress(b'x', format=lzma.FORMAT_XZ) +# zstandard.ZstdCompressor().compress(b'x') + + [email protected]('ext, content_file', [ + ('gz', 'files/magic/byte.gz'), + ('tgz', 'files/magic/byte.gz'), # tgz is gzip too + ('bz2', 'files/magic/byte.bz2'), + ('xz', 'files/magic/byte.xz'), + ('zst', 'files/magic/byte.zst'), + ('zstd', 'files/magic/byte.zst'), # .zstd is the same format + ('zip', 'files/magic/byte.zip'), +]) +def test_file_ext_consistent(sourcescheck, ext, content_file): + """Extension matches actual compression format → no warning.""" + output, test = sourcescheck + pkg = get_tested_mock_package( + files={f'archive.{ext}': {'content-path': content_file}}, + ) + test.check_source(pkg) + out = output.print_results(output.results) + assert 'inconsistent-file-extension' not in out + + [email protected]('ext, content_file', [ + ('gz', 'files/magic/byte.bz2'), + ('bz2', 'files/magic/byte.gz'), + ('xz', 'files/magic/byte.zst'), + ('zst', 'files/magic/byte.gz'), + ('zstd', 'files/magic/byte.xz'), + ('zip', 'files/magic/byte.gz'), +]) +def test_file_ext_inconsistent(sourcescheck, ext, content_file): + """Extension does NOT match actual compression format → warning.""" + output, test = sourcescheck + pkg = get_tested_mock_package( + files={f'archive.{ext}': {'content-path': content_file}}, + ) + test.check_source(pkg) + out = output.print_results(output.results) + assert 'inconsistent-file-extension' in out + + [email protected]('fname', [ + 'archive.gz', + 'archive.tar', + 'archive.txt', +]) +def test_file_ext_no_magic(sourcescheck, fname): + """File with no magic string (empty content) → no crash, no warning.""" + output, test = sourcescheck + pkg = get_tested_mock_package( + files={fname: {'metadata': {'magic': None}}}, + ) + test.check_source(pkg) + out = output.print_results(output.results) + assert 'inconsistent-file-extension' not in out + + +def test_file_ext_unknown_extension(sourcescheck): + """Extension not in compressed_fileext_magic → no warning.""" + output, test = sourcescheck + pkg = get_tested_mock_package( + files={'archive.lz4': {'content-path': 'files/magic/byte.gz'}}, + ) + test.check_source(pkg) + out = output.print_results(output.results) + assert 'inconsistent-file-extension' not in out
