commit rpmlint for openSUSE:Factory
Hello community, here is the log from the commit of package rpmlint for openSUSE:Factory checked in at Thu Apr 21 12:12:10 CEST 2011. -------- --- rpmlint/rpmlint.changes 2011-03-21 17:09:41.000000000 +0100 +++ /mounts/work_src_done/STABLE/rpmlint/rpmlint.changes 2011-04-20 17:31:56.000000000 +0200 @@ -1,0 +2,48 @@ +Wed Apr 20 17:31:23 CEST 2011 - dmueller@suse.de + +- fix sysv5-init-check.diff to check for preun, not postin + +------------------------------------------------------------------- +Tue Apr 19 14:05:01 UTC 2011 - lnussel@suse.de + +- update CheckInitScripts.py: + * add check for runlevel 4 + * clarify boot.* error + * accept $null in start/stop tags +- also check for %run_permissions if package doesn't actually need permissions + handling +- merge suse-binarieschecks.diff and suse-hide-unstripped-outside-build.diff + and fix the former + +------------------------------------------------------------------- +Tue Apr 19 08:35:47 UTC 2011 - lnussel@suse.de + +- ignore dir-or-file-in-usr-local as it's handled by CheckFilelist.py +- non-standard-dir-in-usr dito + +------------------------------------------------------------------- +Tue Apr 19 07:26:44 UTC 2011 - lnussel@suse.de + +- add urfkill (bnc#688328)) + +------------------------------------------------------------------- +Fri Apr 15 10:22:15 CEST 2011 - dmueller@suse.de + +- update to 1.1: + - remove upstreamed patches + * FilesCheck.py: Don't crash if a file cannot be opened + * FilesCheck.py: Update expected Python 3.2 bytecode magic value + * TagsCheck.py: Improve no-description-tag info message + * TagsCheck.py: Improve changelog related info messages. + * Pkg.py: Treat 'Unspecified' as a valid Group + * TagsCheck.py: Add future and overflow checks for changelog + * FilesCheck.py: Don't emit spurious executable perm warnings for + docs with shebangs + * FilesCheck.py: Don't read "head" of files for in each test + * SpecCheck.py: Check source and patch file sizes and MD5 hashes + * Pkg.py: Fix traceback when stringifying epoch-only versions + * TagsCheck.py: Fix TypeError when outputting + * Pkg.py: Make file capabilities available in PkgFile +- add check for missing rcXXX symlinks (FATE#310641) + +------------------------------------------------------------------- @@ -10,0 +59,5 @@ + +------------------------------------------------------------------- +Thu Mar 10 11:10:15 UTC 2011 - lnussel@suse.de + +- add better help message for non-standard-uid calling whatdependson for head-i586 Old: ---- incoherent-warning-fix.diff rpmlint-1.0.tar.bz2 rpmlint-badness-info.diff rpmlint-fscaps.diff suse-hide-unstripped-outside-build.diff New: ---- rpmlint-1.1.tar.bz2 rpmlint-add-details.diff suse-rclink-check.diff ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rpmlint.spec ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -22,8 +22,8 @@ Name: rpmlint BuildRequires: rpm-python Summary: Rpm correctness checker -Version: 1.0 -Release: 25 +Version: 1.1 +Release: 1 Source0: %{name}-%{version}.tar.bz2 Source1: config Source1001: config.in @@ -75,12 +75,10 @@ Patch13: script-interpreter-only-for-exec-scripts.diff Patch14: sourced-dirs.diff Patch17: docdata-examples.diff -Patch18: suse-hide-unstripped-outside-build.diff Patch19: yast-provides.diff Patch20: xdg-paths-update.diff Patch22: better-wrong-script.diff Patch23: buildroot-doc.diff -# bogus, fails with aaa_base. disabled Patch24: sysv5-init-checks.diff Patch26: ignore-non-readable-in-etc.diff Patch29: rpmgroup-checks.diff @@ -117,13 +115,13 @@ Patch76: confusing-invalid-spec-name.patch Patch77: rpmlint-pkg-quoting.diff Patch78: suse-g-ir-chech.diff -Patch79: rpmlint-fscaps.diff Patch80: remove-expand-macros.diff Patch81: suse-whitelist-opensuse.diff -Patch82: rpmlint-badness-info.diff -Patch83: incoherent-warning-fix.diff Patch84: extend-suse-conffiles-check.diff Patch85: suse-changelog.patch +Patch86: suse-rclink-check.diff +# already upstream +Patch87: rpmlint-add-details.diff %py_requires %description @@ -155,13 +153,11 @@ %patch13 %patch14 %patch17 -%patch18 %patch19 %patch20 %patch22 %patch23 -# bogus, fails with aaa_base. disabled -#patch24 +%patch24 #%patch26 %patch29 %patch30 @@ -197,14 +193,12 @@ %patch76 -p1 %patch77 %patch78 -%patch79 -p1 %patch80 %patch81 -%patch82 -p1 -%patch83 %patch84 -# suse-changelog.patch -%patch85 -p1 +%patch85 +%patch86 +%patch87 -p1 cp -p %{SOURCE1} . cp -p %{SOURCE2} . cp -p %{SOURCE3} . ++++++ CheckInitScripts.py ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -50,9 +50,11 @@ '$portmap', '$remote_fs', '$syslog', - '$time', '$ALL'): + '$time', + '$null', + '$ALL'): printError(pkg, "init-script-undefined-dependency", f, dep) - if dep in ('portmap', 'syslog', 'named', 'network', 'xntpd'): + if dep in ('portmap', 'syslog', 'named', 'network', 'ntp', 'ntpd', 'xntpd'): printWarning(pkg, "init-script-non-var-dependency", f, dep) if dep in ('$remote_fs'): found_remote_fs = True @@ -61,9 +63,11 @@ if l.startswith('# Default-Start'): for dep in l.split()[2:]: if boot_script and dep not in ('B', 'S'): - printError(pkg, "init-script-wrong-start-level", f, dep) + printError(pkg, "init-script-boot_d", f) if not boot_script and dep in ('B'): - printError(pkg, "init-script-wrong-start-level", f, dep) + printError(pkg, "init-script-not-boot_d", f, dep) + if dep == '4': + printError(pkg, "init-script-runlevel-4", f) if not found_remote_fs and bins_list: printWarning(pkg, "non-remote_fs-dependency", f) @@ -77,21 +81,34 @@ """Your package contains a /etc/init.d script that specifies a dependency that is not listed in /etc/insserv.conf. Check for typos.""", + 'init-script-non-var-dependency', """Your package contains a /etc/init.d script that specifies a hardcoded dependency that likely should be a variable dependency. For example portmap should actually be $portmap, and similar.""", 'obsolete-init-keyword', + """Your package contains a /etc/init.d script that specifies an obsolete keyword, like X-UnitedLinux-Should-Start. Consider using the LSB equivalent Should-Start instead.""", -'init-script-wrong-start-level', -"""Your package contains a /etc/init.d script that specifies -that it should be run in boot level but isn't named with a boot prefix -or specifies a non-boot level but has boot prefix. Fix your script.""", + +'init-script-boot_d', +"""The init script has a "boot." prefix but actually lacks 'B' in +'Default-Start'. Either rename the script or add +'B' to 'Default-Start'""", + +'init-script-not-boot_d', +"""The init script specifies that it should be run in level 'B' but +doesn't have a "boot." prefix. Either rename the script or remove +the 'B' from 'Default-Start'""", + 'non-remote_fs-dependency', """Your package contains a /etc/init.d script that does not specify $remote_fs as a start dependency, but the package also contains files packaged in /usr. Make sure that your start script does not -call any of them, or add the missing $remote_fs dependency.""" +call any of them, or add the missing $remote_fs dependency.""", + +'init-script-runlevel-4', +"""The init script refers to runlevel 4 which is admin defined. No +distribution script must use it. Remove '4' from 'Default-Start'.""", ) ++++++ CheckSUIDPermissions.py ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -165,8 +165,26 @@ '%(file)s is packaged with world writable permissions (0%(mode)o)' % \ { 'file':f, 'mode':mode }) + script = pkg[rpm.RPMTAG_POSTIN] or pkg[rpm.RPMTAG_POSTINPROG] + found = False + if script: + for line in script.split("\n"): + if "chkstat -n" in line and f in line: + found = True + break + + if "SuSEconfig --module permissions" in line: + found = True + found_suseconfig = True + break + if need_verifyscript and \ (not f in self.perms or not 'static' in self.perms[f]): + + if not script or not found: + printError(pkg, 'permissions-missing-postin', \ + "missing %%set_permissions %s in %%post" % f) + need_set_permissions = True script = pkg[rpm.RPMTAG_VERIFYSCRIPT] or pkg[rpm.RPMTAG_VERIFYSCRIPTPROG] @@ -182,23 +200,6 @@ "missing %%verify_permissions -e %s" % f) - script = pkg[rpm.RPMTAG_POSTIN] or pkg[rpm.RPMTAG_POSTINPROG] - found = False - if script: - for line in script.split("\n"): - if "chkstat -n" in line and f in line: - found = True - break - - if "SuSEconfig --module permissions" in line: - found = True - found_suseconfig = True - break - - if not script and not found: - printError(pkg, 'permissions-missing-postin', \ - "missing %%set_permissions %s in %%post" % f) - if need_set_permissions: if not 'permissions' in map(lambda x: x[0], pkg.prereq()): printError(pkg, 'permissions-missing-requires', \ ++++++ add-weak-dependencies.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- Pkg.py.orig +++ Pkg.py -@@ -425,6 +425,10 @@ class Pkg: +@@ -429,6 +429,10 @@ class Pkg: self._missingok_files = None self._files = None self._requires = None @@ -13,7 +13,7 @@ self._req_names = -1 if header: -@@ -656,6 +660,22 @@ class Pkg: +@@ -666,6 +670,22 @@ class Pkg: self._gatherDepInfo() return self._requires @@ -36,7 +36,7 @@ def prereq(self): """Get package PreReqs as list of (name, flags, (epoch, version, release)) tuples.""" -@@ -692,7 +712,7 @@ class Pkg: +@@ -702,7 +722,7 @@ class Pkg: # internal function to gather dependency info used by the above ones def _gather_aux(self, header, list, nametag, flagstag, versiontag, @@ -45,7 +45,7 @@ names = header[nametag] flags = header[flagstag] versions = header[versiontag] -@@ -703,7 +723,11 @@ class Pkg: +@@ -713,7 +733,11 @@ class Pkg: if prereq is not None and flags[loop] & PREREQ_FLAG: prereq.append((names[loop], flags[loop] & (~PREREQ_FLAG), evr)) @@ -58,7 +58,7 @@ list.append((names[loop], flags[loop], evr)) def _gatherDepInfo(self): -@@ -713,6 +737,10 @@ class Pkg: +@@ -723,6 +747,10 @@ class Pkg: self._provides = [] self._conflicts = [] self._obsoletes = [] @@ -69,7 +69,7 @@ self._gather_aux(self.header, self._requires, rpm.RPMTAG_REQUIRENAME, -@@ -732,6 +760,32 @@ class Pkg: +@@ -742,6 +770,32 @@ class Pkg: rpm.RPMTAG_OBSOLETEFLAGS, rpm.RPMTAG_OBSOLETEVERSION) ++++++ better-wrong-script.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- FilesCheck.py.orig +++ FilesCheck.py -@@ -1665,7 +1665,10 @@ executed.''', +@@ -1679,7 +1679,10 @@ executed.''', executed.''', 'wrong-script-interpreter', ++++++ buildroot-doc.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- SpecCheck.py.orig +++ SpecCheck.py -@@ -594,7 +594,7 @@ versions you can ignore this warning.''' +@@ -619,7 +619,7 @@ versions you can ignore this warning.''' 'hardcoded-path-in-buildroot-tag', '''A path is hardcoded in your Buildroot tag. It should be replaced ++++++ buildroot-in-scripts.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -1,6 +1,8 @@ ---- SpecCheck.py +Index: SpecCheck.py +=================================================================== +--- SpecCheck.py.orig +++ SpecCheck.py -@@ -223,7 +223,9 @@ +@@ -223,7 +223,9 @@ class SpecCheck(AbstractCheck.AbstractCh continue ++++++ config ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -1,10 +1,12 @@ # -*- python -*- +# vim: syntax=python # Configuration for the rpmlint utility. # Loaded before ~/.rpmlintrc # $Id: config,v 1.39 2003/12/22 11:20:55 flepied Exp $ # This line is mandatory to access the configuration functions from Config import * +from Filter import addDetails # Additionale path to look for checks @@ -256,6 +258,16 @@ 'zope', )) +addDetails('non-standard-uid', +'''A file in this package is owned by an unregistered user id. +Please contact opensuse-packaging@opensuse.org to register the user. +''', +'non-standard-gid', +'''A file in this package is owned by an unregistered group id. +Please contact opensuse-packaging@opensuse.org to register the group. +''' +) + setOption('DanglingSymlinkExceptions', (['/usr/share/doc/licenses/', 'licenses'], ['consolehelper$', 'usermode-consoleonly'], @@ -399,12 +411,17 @@ # kdebase4-runtime, bnc#672145 "org.kde.powerdevil.backlighthelper.service", "org.kde.powerdevil.backlighthelper.conf", + # urfkill (bnc#688328) + "org.freedesktop.URfkill.service", + "org.freedesktop.URfkill.conf", )) # Output filters addFilter(".*spurious-bracket-in-.*") addFilter(".*one-line-command-in-.*") -addFilter(" dir-or-file-in-opt") +addFilter(" dir-or-file-in-opt ") # handled by CheckFilelist.py +addFilter(" dir-or-file-in-usr-local ") # handled by CheckFilelist.py +addFilter(" non-standard-dir-in-usr ") # handled by CheckFilelist.py addFilter("incoherent-version-in-changelog") addFilter(" no-signature") addFilter(" symlink-crontab-file") #bnc591431 ++++++ confusing-invalid-spec-name.patch ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:50.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:50.000000000 +0200 @@ -1,10 +1,10 @@ # Confusing message. The problem is not that the file does not end # with ".spec", but that there is a mismatch of specname and pkg name. -Index: rpmlint-0.99/SpecCheck.py +Index: rpmlint-1.1/SpecCheck.py =================================================================== ---- rpmlint-0.99.orig/SpecCheck.py -+++ rpmlint-0.99/SpecCheck.py -@@ -568,8 +568,8 @@ addDetails( +--- rpmlint-1.1.orig/SpecCheck.py ++++ rpmlint-1.1/SpecCheck.py +@@ -593,8 +593,8 @@ addDetails( SPEC file to build a valid RPM package.''', 'invalid-spec-name', ++++++ description-check.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- TagsCheck.py.orig +++ TagsCheck.py -@@ -698,6 +698,9 @@ class TagsCheck(AbstractCheck.AbstractCh +@@ -702,6 +702,9 @@ class TagsCheck(AbstractCheck.AbstractCh if not description: printError(pkg, 'no-description-tag') else: @@ -12,7 +12,7 @@ if not pkg[rpm.RPMTAG_HEADERI18NTABLE]: self._unexpanded_macros(pkg, '%description', description) else: -@@ -969,6 +972,10 @@ Name tag.''', +@@ -983,6 +986,10 @@ Name tag.''', '''The major number of the library isn't included in the package's name. ''', ++++++ devel-provide-is-devel-package.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- FilesCheck.py.orig +++ FilesCheck.py -@@ -826,6 +826,10 @@ class FilesCheck(AbstractCheck.AbstractC +@@ -842,6 +842,10 @@ class FilesCheck(AbstractCheck.AbstractC # Check if the package is a development package devel_pkg = devel_regex.search(pkg.name) ++++++ docdata-examples.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -10,7 +10,7 @@ # room for improvement with catching more -R, but also for false positives... buildconfig_rpath_regex = re.compile('(?:-rpath|Wl,-R)\\b') sofile_regex = re.compile('/lib(64)?/(.+/)?lib[^/]+\.so$') -@@ -1168,7 +1169,7 @@ class FilesCheck(AbstractCheck.AbstractC +@@ -1188,7 +1189,7 @@ class FilesCheck(AbstractCheck.AbstractC includefile_regex.search(f) or \ develfile_regex.search(f) or \ logrotate_regex.search(f) @@ -19,7 +19,7 @@ printWarning(pkg, 'spurious-executable-perm', f) elif f.startswith('/etc/') and f not in config_files and \ f not in ghost_files: -@@ -1539,7 +1540,10 @@ included in your package.''', +@@ -1553,7 +1554,10 @@ included in your package.''', 'spurious-executable-perm', '''The file is installed with executable permissions, but was identified as one that probably should not be executable. Verify if the executable bits are ++++++ extend-suse-conffiles-check.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- FilesCheck.py +Index: FilesCheck.py +=================================================================== +--- FilesCheck.py.orig +++ FilesCheck.py -@@ -1200,7 +1200,7 @@ +@@ -1206,7 +1206,7 @@ class FilesCheck(AbstractCheck.AbstractC if nonexec_file and not docdir_examples_regex.search(f): printWarning(pkg, 'spurious-executable-perm', f) elif f.startswith('/etc/') and f not in config_files and \ ++++++ filename-non-utf8-exception.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- Filter.py +Index: Filter.py +=================================================================== +--- Filter.py.orig +++ Filter.py -@@ -22,13 +22,8 @@ +@@ -22,13 +22,8 @@ _diagnostic = list() _badness_score = 0 printed_messages = { "I": 0, "W": 0, "E": 0 } ++++++ invalid-filerequires.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- TagsCheck.py +Index: TagsCheck.py +=================================================================== +--- TagsCheck.py.orig +++ TagsCheck.py -@@ -419,6 +419,7 @@ +@@ -421,6 +421,7 @@ invalid_version_regex = re.compile('([0- # () are here for grouping purpose in the regexp forbidden_words_regex = re.compile('(' + Config.getOption('ForbiddenWords') + ')', re.IGNORECASE) valid_buildhost_regex = re.compile(Config.getOption('ValidBuildHost')) @@ -8,7 +10,7 @@ use_epoch = Config.getOption('UseEpoch', False) use_utf8 = Config.getOption('UseUTF8', Config.USEUTF8_DEFAULT) max_line_len = Config.getOption('MaxLineLength', 79) -@@ -597,6 +598,9 @@ +@@ -601,6 +602,9 @@ class TagsCheck(AbstractCheck.AbstractCh if d[0].startswith('/usr/local/'): printError(pkg, 'invalid-dependency', d[0]) @@ -18,7 +20,7 @@ if not devel_depend and not is_devel and not is_source and \ FilesCheck.devel_regex.search(d[0]): printError(pkg, 'devel-dependency', d[0]) -@@ -1063,6 +1067,12 @@ +@@ -1085,6 +1089,12 @@ explicit Requires: tags.''', '''This package provides 2 times the same capacity. It should only provide it once.''', ++++++ no-badness-return.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- Filter.py.orig +++ Filter.py -@@ -104,7 +104,7 @@ def printAllReasons(): +@@ -109,7 +109,7 @@ def printAllReasons(): if len(last_reason): printDescriptions(last_reason) last_reason = reason @@ -11,11 +11,11 @@ if Config.info and len(last_reason): printDescriptions(last_reason) _diagnostic = list() -Index: rpmlint.py +Index: rpmlint =================================================================== ---- rpmlint.py.orig -+++ rpmlint.py -@@ -202,7 +202,7 @@ def main(): +--- rpmlint.orig ++++ rpmlint +@@ -211,7 +211,7 @@ def main(): % (packages_checked, specfiles_checked, printed_messages["E"], printed_messages["W"]) ++++++ no-doc-for-lib.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- FilesCheck.py.orig +++ FilesCheck.py -@@ -843,7 +843,7 @@ class FilesCheck(AbstractCheck.AbstractC +@@ -859,7 +859,7 @@ class FilesCheck(AbstractCheck.AbstractC debuginfo_srcs = False debuginfo_debugs = False ++++++ only-reg-files-are-scripts.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -11,7 +11,7 @@ chkconfig_content_regex = re.compile('^\s*#\s*chkconfig:\s*([-0-9]+)\s+[-0-9]+\s+[-0-9]+') subsys_regex = re.compile('/var/lock/subsys/([^/"\'\n\s;&|]+)', re.MULTILINE) -@@ -53,6 +53,9 @@ class InitScriptCheck(AbstractCheck.Abst +@@ -64,6 +64,9 @@ class InitScriptCheck(AbstractCheck.Abst not fname.startswith('/etc/rc.d/init.d/'): continue ++++++ remove-expand-macros.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,8 +1,10 @@ ---- TagsCheck.py +Index: TagsCheck.py +=================================================================== +--- TagsCheck.py.orig +++ TagsCheck.py -@@ -427,13 +427,6 @@ - sentence_break_regex = re.compile(r'(^|[.:;!?])\s*$') - so_dep_regex = re.compile(r'\.so(\.[0-9a-zA-z]+)*(\([^)]*\))*$') +@@ -433,13 +433,6 @@ so_dep_regex = re.compile(r'\.so(\.[0-9a + # we assume that no rpm packages existed before rpm itself existed... + oldest_changelog_timestamp = calendar.timegm(time.strptime("1995-01-01", "%Y-%m-%d")) -private_so_paths = set() -for path in ('%perl_archlib', '%perl_vendorarch', '%perl_sitearch', @@ -14,7 +16,7 @@ _enchant_checkers = {} def spell_check(pkg, str, fmt, lang, ignored): -@@ -814,30 +807,12 @@ +@@ -852,30 +845,12 @@ class TagsCheck(AbstractCheck.AbstractCh (apply(Pkg.formatRequire, obs), apply(Pkg.formatRequire, prov))) ++++++ rpmgroup-checks.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- TagsCheck.py.orig +++ TagsCheck.py -@@ -708,6 +708,8 @@ class TagsCheck(AbstractCheck.AbstractCh +@@ -712,6 +712,8 @@ class TagsCheck(AbstractCheck.AbstractCh self._unexpanded_macros(pkg, 'Group', group) if not group: printError(pkg, 'no-group-tag') @@ -11,7 +11,7 @@ elif VALID_GROUPS and group not in VALID_GROUPS: printWarning(pkg, 'non-standard-group', group) -@@ -1008,6 +1010,10 @@ won't fool the specfile parser, and rebu +@@ -1022,6 +1024,10 @@ won't fool the specfile parser, and rebu '''There is no Group tag in your package. You have to specify a valid group in your spec file using the Group tag.''', ++++++ rpmlint-1.0.tar.bz2 -> rpmlint-1.1.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/AbstractCheck.py new/rpmlint-1.1/AbstractCheck.py --- old/rpmlint-1.0/AbstractCheck.py 2010-04-01 21:19:08.000000000 +0200 +++ new/rpmlint-1.1/AbstractCheck.py 2010-12-11 13:07:19.000000000 +0100 @@ -4,7 +4,7 @@ # Package : rpmlint # Author : Frederic Lepied # Created on : Tue Sep 28 00:22:38 1999 -# Version : $Id: AbstractCheck.py 1753 2010-03-19 21:48:21Z scop $ +# Version : $Id: AbstractCheck.py 1822 2010-12-11 12:07:18Z scop $ # Purpose : Abstract class to hold all the derived classes. ############################################################################# @@ -43,7 +43,8 @@ raise NotImplementedError('check must be implemented in subclass') def check_url(self, pkg, tag, url): - """Check that URL points to something that seems to exist.""" + """Check that URL points to something that seems to exist. + Return info() of the response if available.""" if not self.network_enabled: if self.verbose: printInfo(pkg, 'network-checks-disabled', url) @@ -64,7 +65,11 @@ except Exception, e: errstr = str(e) or repr(e) or type(e) printWarning(pkg, 'invalid-url', '%s:' % tag, url, errstr) - res and res.close() + info = None + if res: + info = res.info() + res.close() + return info class AbstractFilesCheck(AbstractCheck): def __init__(self, name, file_regexp): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/ChangeLog new/rpmlint-1.1/ChangeLog --- old/rpmlint-1.0/ChangeLog 2010-11-01 22:15:40.000000000 +0100 +++ new/rpmlint-1.1/ChangeLog 2011-01-25 20:13:56.000000000 +0100 @@ -1,3 +1,87 @@ +2011-01-25 Ville Skyttä <ville.skytta at iki.fi> + + * Makefile: Release 1.1. + * FilesCheck.py: Don't crash if a file cannot be opened when trying + to peek into it. + +2011-01-24 Ville Skyttä <ville.skytta at iki.fi> + + * FilesCheck.py: Update expected Python 3.2 bytecode magic value to + 3180. + + https://bugzilla.redhat.com/672352 + * TagsCheck.py: Improve no-description-tag info message. + * TagsCheck.py: Improve changelog related info messages. + * Pkg.py: Treat 'Unspecified' as a valid Group the same way as + 'Development/Debug'. + + rpmbuild >= 4.6.0 adds it automatically if not specified in + specfiles. + * TagsCheck.py: Add future and overflow checks for changelog + timestamps. + + http://lists.fedoraproject.org/pipermail/buildsys/2010-July/003174.html + +2011-01-14 Ville Skyttä <ville.skytta at iki.fi> + + * Pkg.py: stringToVersion cleanups, ignore dash before colon as + version/release separator. + +2010-12-15 Ville Skyttä <ville.skytta at iki.fi> + + * FilesCheck.py: Don't emit spurious executable perm warnings for + docs with shebangs. + * FilesCheck.py: Don't read "head" of files for in each test that + needs to peek into them. + + Do it only once instead. istextfile() is now called peek(). + +2010-12-11 Ville Skyttä <ville.skytta at iki.fi> + + * SpecCheck.py: Check source and patch file sizes and MD5 hashes + against Content-Length and Content-MD5 from their URLs. + * AbstractCheck.py: Return urllib info() from check_url() if + available. + +2010-12-08 Ville Skyttä <ville.skytta at iki.fi> + + * rpmlint: Be smarter when deciding whether arguments are rpm files + or installed packages. + + Arguments that are existing files (not directories) but do not + contain slashes and do not end with .rpm, .spm or .spec are now + treated as installed packages. + +2010-12-07 Ville Skyttä <ville.skytta at iki.fi> + + * rpmlint: Make rpmlint executable again. + * README.devel, rpmlint, rpmlint.py, test.sh: Get rid of shell + script wrapper to make prefixed executables easier to set up. + * rpmlint.1: Improve --checkdir documentation. + +2010-12-02 Ville Skyttä <ville.skytta at iki.fi> + + * ., Makefile: Use xz to compress tarball. + +2010-11-27 Ville Skyttä <ville.skytta at iki.fi> + + * Pkg.py: Fix traceback when stringifying epoch-only versions + (Roman Rakus). + + https://bugzilla.redhat.com/657593 + +2010-11-19 Ville Skyttä <ville.skytta at iki.fi> + + * TagsCheck.py: Fix TypeError when outputting + incoherent-version-dependency-on messages (#192). + * Filter.py: Allow info messages even if badness scoring is used + (Ludwig Nussel). + +2010-11-04 Ville Skyttä <ville.skytta at iki.fi> + + * Pkg.py: Make file capabilities available in PkgFile (rpm >= + 4.7.0, Ludwig Nussel). + 2010-11-01 Ville Skyttä <ville.skytta at iki.fi> * Makefile: Release 1.0. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/FilesCheck.py new/rpmlint-1.1/FilesCheck.py --- old/rpmlint-1.0/FilesCheck.py 2010-10-25 19:38:28.000000000 +0200 +++ new/rpmlint-1.1/FilesCheck.py 2011-01-25 08:16:40.000000000 +0100 @@ -4,7 +4,7 @@ # Package : rpmlint # Author : Frederic Lepied # Created on : Mon Oct 4 19:32:49 1999 -# Version : $Id: FilesCheck.py 1810 2010-10-25 17:38:26Z scop $ +# Version : $Id: FilesCheck.py 1832 2011-01-25 07:16:40Z scop $ # Purpose : test various aspects on files: locations, owner, groups, # permission, setuid, setgid... ############################################################################# @@ -211,7 +211,7 @@ lib_package_regex = re.compile('^(lib|.+-libs)') hidden_file_regex = re.compile('/\.[^/]*$') manifest_perl_regex = re.compile('^/usr/share/doc/perl-.*/MANIFEST(\.SKIP)?$') -shebang_regex = re.compile('^#!\s*(\S*)') +shebang_regex = re.compile('^#!\s*(\S+)') interpreter_regex = re.compile('^/(usr/)?(s?bin|games|libexec(/.+)?|(lib(64)?|share)/.+)/[^/]+$') script_regex = re.compile('^/((usr/)?s?bin|etc/(rc\.d/init\.d|X11/xinit\.d|cron\.(hourly|daily|monthly|weekly)))/') sourced_script_regex = re.compile('^/etc/(bash_completion\.d|profile\.d)/') @@ -248,37 +248,38 @@ text_characters = "".join(map(chr, range(32, 127)) + list("\n\r\t\b")) _null_trans = string.maketrans("", "") -def istextfile(filename, pkg): +def peek(filename, pkg, length=512): + """Peek into a file, return a chunk from its beginning and a flag if it + seems to be a text file.""" fobj = None + chunk = None try: - fobj = open(filename, 'r') - s = fobj.read(512) + fobj = open(filename, 'rb') + chunk = fobj.read(length) fobj.close() except Exception, e: # eg. https://bugzilla.redhat.com/209876 printWarning(pkg, 'read-error', e) if fobj: fobj.close() - return False + return (chunk, False) - if "\0" in s: - return False + if "\0" in chunk: + return (chunk, False) - if not s: # Empty files are considered text - return True + if not chunk: # Empty files are considered text + return (chunk, True) # PDF's are binary but often detected as text by the algorithm below - if filename.lower().endswith('.pdf') and s.startswith('%PDF-'): - return False + if filename.lower().endswith('.pdf') and chunk.startswith('%PDF-'): + return (chunk, False) # Get the non-text characters (maps a character to itself then # use the 'remove' option to get rid of the text characters.) - t = s.translate(_null_trans, text_characters) + t = chunk.translate(_null_trans, text_characters) - # If more than 30% non-text characters, then - # this is considered a binary file - if float(len(t))/len(s) > 0.30: - return False - return True + # If more than 30% non-text characters, then consider it a binary file + istext = float(len(t))/len(chunk) <= 0.30 + return (chunk, istext) # See Python/import.c (in the trunk and py3k branches) for a full list of # the values here. @@ -291,7 +292,7 @@ '2.7': 62211, '3.0': 3130, '3.1': 3150, - '3.2': 3160, + '3.2': 3180, } def get_expected_pyc_magic(path): @@ -526,8 +527,20 @@ if f not in ghost_files: printError(pkg, 'non-ghost-file', f) + chunk = None + istext = False + if os.access(pkgfile.path, os.R_OK): + (chunk, istext) = peek(pkgfile.path, pkg) + + interpreter = None + if chunk: + res = shebang_regex.search(chunk) + if res: + interpreter = res.group(1) + if doc_regex.search(f): - nonexec_file = True + if not interpreter: + nonexec_file = True if not is_doc: printError(pkg, 'not-listed-as-documentation', f) @@ -649,16 +662,9 @@ source_file = python_bytecode_to_script(f) if source_file: if source_file in files: - # Extract header of .pyc file: - pyc_fobj = open(pkgfile.path, 'rb') - try: - pyc_bytes = pyc_fobj.read(8) - finally: - pyc_fobj.close() - # Verify that the magic ABI value embedded in the .pyc # header is correct - found_magic = py_demarshal_long(pyc_bytes[:4]) & 0xffff + found_magic = py_demarshal_long(chunk[:4]) & 0xffff exp_magic, exp_version = get_expected_pyc_magic(f) if exp_magic and found_magic != exp_magic: found_version = 'unknown' @@ -680,7 +686,7 @@ # Verify that the timestamp embedded in the .pyc header # matches the mtime of the .py file: - pyc_timestamp = py_demarshal_long(pyc_bytes[4:8]) + pyc_timestamp = py_demarshal_long(chunk[4:8]) if pyc_timestamp != files[source_file].mtime: cts = datetime.fromtimestamp( pyc_timestamp).isoformat() @@ -741,60 +747,53 @@ line[res.end(1):]) # text file checks - if os.access(pkgfile.path, os.R_OK): - if istextfile(pkgfile.path, pkg): - fobj = open(pkgfile.path, 'r') - try: - line = fobj.readline() - finally: - fobj.close() - res = None - # ignore perl module shebang -- TODO: disputed... - if not f.endswith('.pm'): - res = shebang_regex.search(line) - # sourced scripts should not be executable - if sourced_script_regex.search(f): - if res: - printError(pkg, - 'sourced-script-with-shebang', f) - if mode & 0111 != 0: - printError(pkg, 'executable-sourced-script', - f, oct(perm)) - # ...but executed ones should - elif res or mode & 0111 != 0 or script_regex.search(f): - interpreter = None - if res: - interpreter = res.group(1) - if not interpreter_regex.search(interpreter): - printError(pkg, 'wrong-script-interpreter', - f, interpreter) - elif not nonexec_file and not \ - (lib_path_regex.search(f) and - f.endswith('.la')): - printError(pkg, 'script-without-shebang', f) - - if mode & 0111 == 0 and not is_doc: - printError(pkg, 'non-executable-script', f, - oct(perm), interpreter) - if line.endswith('\r\n') or line.endswith('\r'): - printError( - pkg, 'wrong-script-end-of-line-encoding', f) - elif is_doc and not skipdocs_regex.search(f): - if line.endswith('\r\n') or line.endswith('\r'): - printWarning( - pkg, 'wrong-file-end-of-line-encoding', f) - # We check only doc text files for UTF-8-ness; - # checking everything may be slow and can generate - # lots of unwanted noise. - if use_utf8 and not is_utf8(pkgfile.path): - printWarning(pkg, 'file-not-utf8', f) - - elif is_doc and compr_regex.search(f): - ff = compr_regex.sub('', f) - if not skipdocs_regex.search(ff): - # compressed docs, eg. info and man files etc - if use_utf8 and not is_utf8(pkgfile.path): - printWarning(pkg, 'file-not-utf8', f) + if istext: + # ignore perl module shebang -- TODO: disputed... + if f.endswith('.pm'): + interpreter = None + # sourced scripts should not be executable + if sourced_script_regex.search(f): + if interpreter: + printError(pkg, + 'sourced-script-with-shebang', f, + interpreter) + if mode & 0111 != 0: + printError(pkg, 'executable-sourced-script', + f, oct(perm)) + # ...but executed ones should + elif interpreter or mode & 0111 != 0 or \ + script_regex.search(f): + if interpreter: + if not interpreter_regex.search(interpreter): + printError(pkg, 'wrong-script-interpreter', + f, interpreter) + elif not nonexec_file and not \ + (lib_path_regex.search(f) and + f.endswith('.la')): + printError(pkg, 'script-without-shebang', f) + + if mode & 0111 == 0 and not is_doc: + printError(pkg, 'non-executable-script', f, + oct(perm), interpreter) + if '\r' in chunk: + printError( + pkg, 'wrong-script-end-of-line-encoding', f) + elif is_doc and not skipdocs_regex.search(f): + if '\r' in chunk: + printWarning( + pkg, 'wrong-file-end-of-line-encoding', f) + # We check only doc text files for UTF-8-ness; + # checking everything may be slow and can generate + # lots of unwanted noise. + if use_utf8 and not is_utf8(pkgfile.path): + printWarning(pkg, 'file-not-utf8', f) + + elif is_doc and compr_regex.search(f): + ff = compr_regex.sub('', f) + if not skipdocs_regex.search(ff): + # compressed docs, eg. info and man files etc + if use_utf8 and not is_utf8(pkgfile.path): + printWarning(pkg, 'file-not-utf8', f) # normal dir check elif stat.S_ISDIR(mode): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/Filter.py new/rpmlint-1.1/Filter.py --- old/rpmlint-1.0/Filter.py 2010-02-23 21:19:22.000000000 +0100 +++ new/rpmlint-1.1/Filter.py 2010-11-19 18:06:59.000000000 +0100 @@ -4,7 +4,7 @@ # Package : rpmlint # Author : Frederic Lepied # Created on : Sat Oct 23 15:52:27 1999 -# Version : $Id: Filter.py 1734 2010-02-23 20:19:22Z scop $ +# Version : $Id: Filter.py 1814 2010-11-19 17:06:59Z scop $ # Purpose : filter the output of rpmlint to allow exceptions. ############################################################################# @@ -47,7 +47,12 @@ badness = 0 if threshold >= 0: badness = Config.badness(reason) - msgtype = badness and "E" or "W" + # anything with badness is an error + if badness: + msgtype == 'E' + # errors without badness become warnings + elif msgtype == 'E': + msgtype = 'W' ln = "" if pkg.current_linenum is not None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/Makefile new/rpmlint-1.1/Makefile --- old/rpmlint-1.0/Makefile 2010-11-01 22:15:22.000000000 +0100 +++ new/rpmlint-1.1/Makefile 2011-01-25 20:11:16.000000000 +0100 @@ -3,7 +3,7 @@ # Package : rpmlint # Author : Frederic Lepied # Created on : Mon Sep 30 13:20:18 1999 -# Version : $Id: Makefile 1811 2010-11-01 21:15:22Z scop $ +# Version : $Id: Makefile 1833 2011-01-25 19:11:15Z scop $ # Purpose : rules to manage the files. ############################################################################# @@ -21,7 +21,7 @@ PYTHON = python # update this variable to create a new release -VERSION := 1.0 +VERSION := 1.1 TAG := $(shell echo "V$(VERSION)" | tr -- '-.' '__') SVNBASE = $(shell svn info . | grep URL | sed -e 's/[^:]*:\s*//' -e 's,/\(trunk\|tags/.\+\)$$,,') @@ -62,7 +62,7 @@ dist: cleandist localcopy tar cleandist: - rm -rf $(PACKAGE)-$(VERSION) $(PACKAGE)-$(VERSION).tar.bz2 + rm -rf $(PACKAGE)-$(VERSION) $(PACKAGE)-$(VERSION).tar.xz localcopy: $(FILES) $(GENERATED) mkdir $(PACKAGE)-$(VERSION) @@ -70,7 +70,7 @@ tar: localcopy tar cv --owner=root --group=root -f $(PACKAGE)-$(VERSION).tar $(PACKAGE)-$(VERSION) - bzip2 -9vf $(PACKAGE)-$(VERSION).tar + xz -9evf $(PACKAGE)-$(VERSION).tar rm -rf $(PACKAGE)-$(VERSION) export: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/Pkg.py new/rpmlint-1.1/Pkg.py --- old/rpmlint-1.0/Pkg.py 2010-06-05 21:55:53.000000000 +0200 +++ new/rpmlint-1.1/Pkg.py 2011-01-24 22:23:44.000000000 +0100 @@ -4,7 +4,7 @@ # Package : rpmlint # Author : Frederic Lepied # Created on : Tue Sep 28 07:18:06 1999 -# Version : $Id: Pkg.py 1794 2010-06-05 19:55:53Z scop $ +# Version : $Id: Pkg.py 1828 2011-01-24 21:23:44Z scop $ # Purpose : provide an API to handle a rpm package either by accessing # the rpm file or by accessing the files contained inside. ############################################################################# @@ -191,6 +191,8 @@ fobj.close() if 'Development/Debug' not in groups: groups.append('Development/Debug') + if 'Unspecified' not in groups: # auto-added by rpm >= 4.6.0 + groups.append('Unspecified') groups.sort() return groups @@ -312,14 +314,15 @@ ret = "" if evr[0] is not None and evr[0] != "": ret += str(evr[0]) + ":" - ret += evr[1] - if evr[2] is not None and evr[2] != "": - ret += "-" + evr[2] + if evr[1] is not None: + ret += evr[1] + if evr[2] is not None and evr[2] != "": + ret += "-" + evr[2] return ret # from yum 3.2.23, rpmUtils.miscutils, with some rpmlint modifications def stringToVersion(verstring): - if verstring in [None, '']: + if verstring in (None, ''): return (None, None, None) epoch = None i = verstring.find(':') @@ -329,18 +332,19 @@ except ValueError: # garbage in epoch, ignore it pass - j = verstring.find('-') + i += 1 + j = verstring.find('-', i) if j != -1: - if verstring[i + 1:j] == '': + if verstring[i:j] == '': version = None else: - version = verstring[i + 1:j] - release = verstring[j + 1:] + version = verstring[i:j] + release = verstring[j+1:] else: - if verstring[i + 1:] == '': + if verstring[i:] == '': version = None else: - version = verstring[i + 1:] + version = verstring[i:] release = None return (epoch, version, release) @@ -603,6 +607,10 @@ provides = self.header[rpm.RPMTAG_FILEPROVIDE] files = self.header[rpm.RPMTAG_FILENAMES] magics = self.header[rpm.RPMTAG_FILECLASS] + try: # rpm >= 4.7.0 + filecaps = self.header[rpm.RPMTAG_FILECAPS] + except: + filecaps = None # rpm-python < 4.6 does not return a list for this (or FILEDEVICES, # FWIW) for packages containing exactly one file @@ -641,6 +649,8 @@ # for example Fedora's rpmbuild as of F-11's 4.7.1 is # patched so it generates them. pkgfile.magic = '' + if filecaps: + pkgfile.filecaps = filecaps[idx] self._files[pkgfile.name] = pkgfile # API to access dependency information @@ -806,6 +816,7 @@ self.provides = [] self.lang = '' self.magic = '' + self.filecaps = None # TODO: decompression support diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/README.devel new/rpmlint-1.1/README.devel --- old/rpmlint-1.0/README.devel 2009-08-19 11:21:02.000000000 +0200 +++ new/rpmlint-1.1/README.devel 2010-12-07 00:01:26.000000000 +0100 @@ -4,12 +4,12 @@ To run rpmlint from the working tree or in place from an unpacked tarball: -$ python -O -u rpmlint.py -C . <rpms> +$ ./rpmlint -C . <rpms> ...and to run only a single check, for example to test only FHSCheck: -$ python -O -u rpmlint.py -C . -c FHSCheck <rpms> +$ ./rpmlint -C . -c FHSCheck <rpms> For profiling, use something like: -$ python -O -u -m cProfile -s cumulative rpmlint.py -C . [...] +$ python -O -u -m cProfile -s cumulative rpmlint -C . [...] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/SpecCheck.py new/rpmlint-1.1/SpecCheck.py --- old/rpmlint-1.0/SpecCheck.py 2010-10-06 20:31:34.000000000 +0200 +++ new/rpmlint-1.1/SpecCheck.py 2010-12-11 13:15:54.000000000 +0100 @@ -4,7 +4,7 @@ # Package : rpmlint # Author : Frederic Lepied # Created on : Thu Oct 7 17:06:14 1999 -# Version : $Id: SpecCheck.py 1789 2010-06-03 21:30:26Z scop $ +# Version : $Id: SpecCheck.py 1823 2010-12-11 12:15:54Z scop $ # Purpose : check the spec file of a source rpm. ############################################################################# @@ -541,7 +541,32 @@ srctype = "Patch" tag = '%s%s' % (srctype, num) if scheme and netloc: - self.check_url(pkg, tag, url) + info = self.check_url(pkg, tag, url) + clen = info.get("Content-Length") + if clen is not None: + clen = int(clen) + cmd5 = info.get("Content-MD5") + if cmd5 is not None: + cmd5 = cmd5.lower() + if (clen is not None or cmd5 is not None) \ + and hasattr(pkg, 'files'): + # Not using path from urlparse results to match how + # rpm itself parses the basename. + pkgfile = pkg.files()[url.split("/")[-1]] + if pkgfile: + if clen is not None and pkgfile.size != clen: + printWarning(pkg, 'file-size-mismatch', + '%s = %s, %s = %s' % + (pkgfile.name, pkgfile.size, + url, clen)) + # pkgfile.md5 could be some other digest than + # MD5, treat as MD5 only if it's 32 chars long + if cmd5 and len(pkgfile.md5) == 32 \ + and pkgfile.md5 != cmd5: + printWarning(pkg, 'file-md5-mismatch', + '%s = %s, %s = %s' % + (pkgfile.name, pkgfile.md5, + url, cmd5)) elif srctype == "Source" and tarball_regex.search(url): printWarning(pkg, 'invalid-url', '%s:' % tag, url) @@ -748,6 +773,16 @@ '''There is a unescaped macro after a shell style comment in the specfile. Macros are expanded everywhere, so check if it can cause a problem in this case and escape the macro with another leading % if appropriate.''', + +'file-size-mismatch', +'''The size of the file in the package does not match the size indicated by +peeking at its URL. Verify that the file in the package has the intended +contents.''', + +'file-md5-mismatch', +'''The MD5 hash of the file in the package does not match the MD5 hash +indicated by peeking at its URL. Verify that the file in the package has the +intended contents.''', ) # SpecCheck.py ends here diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/TagsCheck.py new/rpmlint-1.1/TagsCheck.py --- old/rpmlint-1.0/TagsCheck.py 2010-06-23 20:34:28.000000000 +0200 +++ new/rpmlint-1.1/TagsCheck.py 2011-01-24 22:26:21.000000000 +0100 @@ -4,12 +4,14 @@ # Package : rpmlint # Author : Frederic Lepied # Created on : Tue Sep 28 00:03:24 1999 -# Version : $Id: TagsCheck.py 1791 2010-06-04 21:33:17Z scop $ +# Version : $Id: TagsCheck.py 1830 2011-01-24 21:26:21Z scop $ # Purpose : Check a package to see if some rpm tags are present ############################################################################# +import calendar import os import re +import time try: from urlparse import urlparse except ImportError: # Python 3 @@ -426,6 +428,8 @@ punct = '.,:;!?' sentence_break_regex = re.compile(r'(^|[.:;!?])\s*$') so_dep_regex = re.compile(r'\.so(\.[0-9a-zA-z]+)*(\([^)]*\))*$') +# we assume that no rpm packages existed before rpm itself existed... +oldest_changelog_timestamp = calendar.timegm(time.strptime("1995-01-01", "%Y-%m-%d")) private_so_paths = set() for path in ('%perl_archlib', '%perl_vendorarch', '%perl_sitearch', @@ -644,8 +648,8 @@ printWarning(pkg, 'incoherent-version-dependency-on', base_or_libs, - Pkg.versionToString(dep[2][0], - dep[2][1], None), + Pkg.versionToString((dep[2][0], + dep[2][1], None)), sexp) res = devel_number_regex.search(name) if not res: @@ -737,6 +741,16 @@ if use_utf8 and not Pkg.is_utf8_str(' '.join(changelog)): printError(pkg, 'tag-not-utf8', '%changelog') + clt = pkg[rpm.RPMTAG_CHANGELOGTIME][0] + if clt: + clt -= 12 * 3600 # rpm timestamps appear to be at noon + if clt < oldest_changelog_timestamp: + printWarning(pkg, 'changelog-time-overflow', + time.strftime("%Y-%m-%d", time.gmtime(clt))) + elif clt > time.time(): + printError(pkg, 'changelog-time-in-future', + time.strftime("%Y-%m-%d", time.gmtime(clt))) + # for provide_name in (x[0] for x in pkg.provides()): # if name == provide_name: # printWarning(pkg, 'package-provides-itself') @@ -973,9 +987,9 @@ '''Summary begins with whitespace which will waste space when displayed.''', 'no-description-tag', -'''There is no %description tag in your spec file. To insert it, just insert a -'%description' tag in your spec file, add a textual description of the package -after it, and rebuild the package.''', +'''The description of the package is empty or missing. To add it, insert a +%description section in your spec file, add a textual description of the +package after it, and rebuild the package.''', 'description-line-too-long', '''Your description lines must not exceed %d characters. If a line is exceeding @@ -1001,13 +1015,21 @@ '%changelog' in your spec file and rebuild it.''', 'no-version-in-last-changelog', -'''The last changelog entry doesn't contain a version. Please insert the +'''The latest changelog entry doesn't contain a version. Please insert the version that is coherent with the version of the package and rebuild it.''', 'incoherent-version-in-changelog', -'''The last entry in %changelog contains a version identifier that is not +'''The latest entry in %changelog contains a version identifier that is not coherent with the epoch:version-release tuple of the package.''', +'changelog-time-overflow', +'''The timestamp of the latest entry in %changelog is suspiciously far away in +the past; it is possible that it is actually so much in the future that it +has overflowed rpm's timestamp representation.''', + +'changelog-time-in-future', +'''The timestamp of the latest entry in %changelog is in the future.''', + 'no-license', '''There is no License tag in your spec file. You have to specify one license for your program (eg. GPL). To insert this tag, just insert a 'License' in diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/__version__.py new/rpmlint-1.1/__version__.py --- old/rpmlint-1.0/__version__.py 2010-11-01 22:15:29.000000000 +0100 +++ new/rpmlint-1.1/__version__.py 2011-01-25 20:13:56.000000000 +0100 @@ -1,2 +1,2 @@ # Automatically generated, do not edit -__version__ = '1.0' +__version__ = '1.1' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/rpmlint new/rpmlint-1.1/rpmlint --- old/rpmlint-1.0/rpmlint 2010-06-04 21:51:11.000000000 +0200 +++ new/rpmlint-1.1/rpmlint 2010-12-11 13:12:56.000000000 +0100 @@ -1,18 +1,381 @@ -#!/bin/sh +#!/usr/bin/python -ttOu +# -*- coding: utf-8 -*- ############################################################################# # File : rpmlint # Package : rpmlint # Author : Frederic Lepied # Created on : Mon Sep 27 19:20:18 1999 -# Version : $Id: rpmlint 1790 2010-06-04 19:51:11Z scop $ +# Version : $Id: rpmlint 1821 2010-12-08 16:57:09Z scop $ # Purpose : main entry point: process options, load the checks and run # the checks. ############################################################################# -PYTHONPATH=${PYTHONPATH=.} +import getopt +import glob +import imp +import locale +import os +import re +import stat +import sys +import tempfile -PYTHONPATH=${PYTHONPATH}:/usr/share/rpmlint +# 1 instead of 0 here because we want the script dir to be looked up first, +# e.g. for in-place from tarball or SCM checkout +sys.path.insert(1, '/usr/share/rpmlint') -exec python -tt -u -O /usr/share/rpmlint/rpmlint.py "$@" +# Do not import anything that initializes its global variables from +# Config at load time here (or anything that imports such a thing), +# that results in those variables initialized before config files are +# loaded which is too early - settings from config files won't take +# place for those variables. + +from Filter import badnessScore, badnessThreshold, printAllReasons, \ + printDescriptions, printInfo, printed_messages +import AbstractCheck +import Config +import Pkg + + +_default_user_conf = '%s/rpmlint' % \ + (os.environ.get('XDG_CONFIG_HOME') or '~/.config') + +# Print usage information +def usage(name): + print ('''usage: %s [<options>] <rpm files|installed packages|specfiles|dirs> + options: +\t[-i|--info] +\t[-I <messageid,messageid,...>] +\t[-c|--check <check>] +\t[-a|--all] +\t[-C|--checkdir <checkdir>] +\t[-h|--help] +\t[-v|--verbose] +\t[-E|--extractdir <dir>] +\t[-V|--version] +\t[-n|--noexception] +\t[-f|--file <user config file to use instead of %s] +\t[-o|--option <key value>]''' \ + % (name, _default_user_conf)) + +# Print version information +def printVersion(): + print ('rpmlint version %s Copyright (C) 1999-2007 Frederic Lepied, Mandriva' % Config.__version__) + +def loadCheck(name): + '''Load a (check) module by its name, unless it is already loaded.''' + # Avoid loading more than once (initialization costs) + loaded = sys.modules.get(name) + if loaded: + return loaded + (fobj, pathname, description) = imp.find_module(name) + try: + imp.load_module(name, fobj, pathname, description) + finally: + fobj.close() + +############################################################################# +# main program +############################################################################# +def main(): + + locale.setlocale(locale.LC_COLLATE, '') + + # Add check dirs to the front of load path + sys.path[0:0] = Config.checkDirs() + + # Load all checks + for c in Config.allChecks(): + loadCheck(c) + + packages_checked = 0 + specfiles_checked = 0 + do_spec_check = 'SpecCheck' in Config.allChecks() + if do_spec_check: + # See comments in "top level import section" for why this isn't + # imported earlier. + import SpecCheck + + try: + # Loop over all file names given in arguments + dirs = [] + for arg in args: + pkgs = [] + isfile = False + try: + if arg == "-": + arg = "(standard input)" + # Short-circuit stdin spec file check + if do_spec_check: + stdin = sys.stdin.readlines() + if not stdin: + continue + pkg = Pkg.FakePkg(arg) + check = SpecCheck.SpecCheck() + check.verbose = verbose + check.check_spec(pkg, None, spec_lines=stdin) + pkg.cleanup() + specfiles_checked += 1 + continue + + try: + st = os.stat(arg) + isfile = True + if stat.S_ISREG(st[stat.ST_MODE]): + if arg.endswith(".spec"): + if do_spec_check: + # Short-circuit spec file checks + pkg = Pkg.FakePkg(arg) + check = SpecCheck.SpecCheck() + check.verbose = verbose + check.check_spec(pkg, arg) + pkg.cleanup() + specfiles_checked += 1 + elif "/" in arg or arg.endswith(".rpm") or \ + arg.endswith(".spm"): + pkgs.append(Pkg.Pkg(arg, extract_dir)) + else: + raise OSError + + elif stat.S_ISDIR(st[stat.ST_MODE]): + dirs.append(arg) + continue + else: + raise OSError + except OSError: + ipkgs = Pkg.getInstalledPkgs(arg) + if not ipkgs: + Pkg.warn( + '(none): E: no installed packages by name %s' % arg) + else: + ipkgs.sort(key = lambda x: locale.strxfrm( + x.header.sprintf("%{NAME}.%{ARCH}"))) + pkgs.extend(ipkgs) + except KeyboardInterrupt: + if isfile: + arg = os.path.abspath(arg) + Pkg.warn( + '(none): E: interrupted, exiting while reading %s' % arg) + sys.exit(2) + except Exception, e: + if isfile: + arg = os.path.abspath(arg) + Pkg.warn('(none): E: error while reading %s: %s' % (arg, e)) + pkgs = [] + continue + + for pkg in pkgs: + runChecks(pkg) + packages_checked += 1 + + for dname in dirs: + try: + for path, dirs, files in os.walk(dname): + for fname in files: + fname = os.path.abspath(os.path.join(path, fname)) + try: + if fname.endswith('.rpm') or \ + fname.endswith('.spm'): + pkg = Pkg.Pkg(fname, extract_dir) + runChecks(pkg) + packages_checked += 1 + + elif do_spec_check and fname.endswith('.spec'): + pkg = Pkg.FakePkg(fname) + check = SpecCheck.SpecCheck() + check.verbose = verbose + check.check_spec(pkg, fname) + pkg.cleanup() + specfiles_checked += 1 + + except KeyboardInterrupt: + Pkg.warn('(none): E: interrupted, exiting while ' + + 'reading %s' % fname) + sys.exit(2) + except Exception, e: + Pkg.warn( + '(none): E: while reading %s: %s' % (fname, e)) + continue + except Exception, e: + Pkg.warn( + '(none): E: error while reading dir %s: %s' % (dname, e)) + continue + + if printAllReasons(): + Pkg.warn('(none): E: badness %d exceeds threshold %d, aborting.' % + (badnessScore(), badnessThreshold())) + sys.exit(66) + + finally: + print "%d packages and %d specfiles checked; %d errors, %d warnings." \ + % (packages_checked, specfiles_checked, + printed_messages["E"], printed_messages["W"]) + + if printed_messages["E"] > 0: + sys.exit(64) + sys.exit(0) + +def runChecks(pkg): + + try: + if verbose: + printInfo(pkg, 'checking') + + for name in Config.allChecks(): + check = AbstractCheck.AbstractCheck.known_checks.get(name) + if check: + check.verbose = verbose + check.check(pkg) + else: + Pkg.warn('(none): W: unknown check %s, skipping' % name) + finally: + pkg.cleanup() + +############################################################################# +# +############################################################################# + +sys.argv[0] = os.path.basename(sys.argv[0]) + +# parse options +try: + (opt, args) = getopt.getopt(sys.argv[1:], + 'iI:c:C:hVvanE:f:o:', + ['info', + 'check=', + 'checkdir=', + 'help', + 'version', + 'verbose', + 'all', + 'noexception', + 'extractdir=', + 'file=', + 'option=', + ]) +except getopt.GetoptError, e: + Pkg.warn("%s: %s" % (sys.argv[0], e)) + usage(sys.argv[0]) + sys.exit(1) + +# process options +checkdir = '/usr/share/rpmlint' +checks = [] +verbose = False +extract_dir = None +conf_file = _default_user_conf +if not os.path.exists(os.path.expanduser(conf_file)): + # deprecated backwards compatibility with < 0.88 + conf_file = '~/.rpmlintrc' +info_error = None + +# load global config files +configs = glob.glob('/etc/rpmlint/*config') +configs.sort() + +# Was rpmlint invoked as a prefixed variant? +m = re.match(r"(?P<prefix>[\w-]+)-rpmlint(\.py)?", sys.argv[0]) +if m: + # Okay, we're a prefixed variant. Look for the variant config. + # If we find it, use it. If not, fallback to the default. + prefix = m.group('prefix') + if os.path.isfile('/usr/share/rpmlint/config.%s' % prefix): + configs.insert(0, '/usr/share/rpmlint/config.%s' % prefix) + else: + configs.insert(0, '/usr/share/rpmlint/config') +else: + configs.insert(0, '/usr/share/rpmlint/config') + +for f in configs: + try: + execfile(f) + except IOError: + pass + except Exception, E: + Pkg.warn('(none): W: error loading %s, skipping: %s' % (f, E)) +# pychecker fix +del f + +config_overrides = {} + +# process command line options +for o in opt: + if o[0] in ('-c', '--check'): + checks.append(o[1]) + elif o[0] in('-i', '--info'): + Config.info = True + elif o[0] == '-I': + info_error = o[1] + elif o[0] in ('-h', '--help'): + usage(sys.argv[0]) + sys.exit(0) + elif o[0] in ('-C', '--checkdir'): + Config.addCheckDir(o[1]) + elif o[0] in ('-v', '--verbose'): + verbose = True + elif o[0] in ('-V', '--version'): + printVersion() + sys.exit(0) + elif o[0] in ('-E', '--extractdir'): + extract_dir = o[1] + Config.setOption('ExtractDir', extract_dir) + elif o[0] in ('-n', '--noexception'): + Config.no_exception = True + elif o[0] in ('-a', '--all'): + if '*' not in args: + args.append('*') + elif o[0] in ('-f', '--file'): + conf_file = o[1] + elif o[0] in ('-o', '--option'): + kv = o[1].split(None, 1) + if len(kv) == 1: + config_overrides[kv[0]] = None + else: + config_overrides[kv[0]] = eval(kv[1]) + +# load user config file +try: + execfile(os.path.expanduser(conf_file)) +except IOError: + pass +except Exception,E: + Pkg.warn('(none): W: error loading %s, skipping: %s' % (conf_file, E)) + +# apply config overrides +for key, value in config_overrides.items(): + Config.setOption(key, value) + +if not extract_dir: + extract_dir = Config.getOption('ExtractDir', tempfile.gettempdir()) + +if info_error: + Config.info = True + sys.path[0:0] = Config.checkDirs() + for c in checks: + Config.addCheck(c) + for c in Config.allChecks(): + loadCheck(c) + for e in info_error.split(','): + print "%s:" % e + printDescriptions(e) + sys.exit(0) + +# if no argument print usage +if not args: + usage(sys.argv[0]) + sys.exit(1) + +if __name__ == '__main__': + if checks: + Config.resetChecks() + for check in checks: + Config.addCheck(check) + main() # rpmlint ends here + +# Local variables: +# indent-tabs-mode: nil +# py-indent-offset: 4 +# End: +# ex: ts=4 sw=4 et diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/rpmlint.1 new/rpmlint-1.1/rpmlint.1 --- old/rpmlint-1.0/rpmlint.1 2010-10-04 20:43:07.000000000 +0200 +++ new/rpmlint-1.1/rpmlint.1 2010-12-07 00:21:40.000000000 +0100 @@ -1,4 +1,4 @@ -.TH RPMLINT "1" "January 2009" "rpmlint" "User Commands" +.TH RPMLINT "1" "December 2010" "rpmlint" "User Commands" .SH NAME rpmlint \- check common problems in rpm packages .SH SYNOPSIS @@ -36,7 +36,10 @@ .TP \fB\-C\fR, \fB\-\-checkdir\fR=\fIdir\fR Insert \fIdir\fR to the front of the list of paths to load checks -(and other Python modules) from. +from, unless it is already in the list. The default list of check +dirs typically contains only /usr/share/rpmlint. Directories in the +check dirs list are also inserted to the front of the list of paths to +load Python modules from when the check process begins. .TP \fB\-h\fR, \fB\-\-help\fR Display summary of command line options and exit. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/rpmlint.py new/rpmlint-1.1/rpmlint.py --- old/rpmlint-1.0/rpmlint.py 2010-07-12 18:13:41.000000000 +0200 +++ new/rpmlint-1.1/rpmlint.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,372 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################# -# File : rpmlint.py -# Package : rpmlint -# Author : Frederic Lepied -# Created on : Mon Sep 27 19:20:18 1999 -# Version : $Id: rpmlint.py 1799 2010-07-12 16:13:41Z scop $ -# Purpose : main entry point: process options, load the checks and run -# the checks. -############################################################################# - -import getopt -import glob -import imp -import locale -import os -import re -import stat -import sys -import tempfile - -# Do not import anything that initializes its global variables from -# Config at load time here (or anything that imports such a thing), -# that results in those variables initialized before config files are -# loaded which is too early - settings from config files won't take -# place for those variables. - -from Filter import badnessScore, badnessThreshold, printAllReasons, \ - printDescriptions, printInfo, printed_messages -import AbstractCheck -import Config -import Pkg - - -_default_user_conf = '%s/rpmlint' % \ - (os.environ.get('XDG_CONFIG_HOME') or '~/.config') - -# Print usage information -def usage(name): - print ('''usage: %s [<options>] <rpm files|installed packages|specfiles|dirs> - options: -\t[-i|--info] -\t[-I <messageid,messageid,...>] -\t[-c|--check <check>] -\t[-a|--all] -\t[-C|--checkdir <checkdir>] -\t[-h|--help] -\t[-v|--verbose] -\t[-E|--extractdir <dir>] -\t[-V|--version] -\t[-n|--noexception] -\t[-f|--file <user config file to use instead of %s] -\t[-o|--option <key value>]''' \ - % (name, _default_user_conf)) - -# Print version information -def printVersion(): - print ('rpmlint version %s Copyright (C) 1999-2007 Frederic Lepied, Mandriva' % Config.__version__) - -def loadCheck(name): - '''Load a (check) module by its name, unless it is already loaded.''' - # Avoid loading more than once (initialization costs) - loaded = sys.modules.get(name) - if loaded: - return loaded - (fobj, pathname, description) = imp.find_module(name) - try: - imp.load_module(name, fobj, pathname, description) - finally: - fobj.close() - -############################################################################# -# main program -############################################################################# -def main(): - - locale.setlocale(locale.LC_COLLATE, '') - - # Add check dirs to the front of load path - sys.path[0:0] = Config.checkDirs() - - # Load all checks - for c in Config.allChecks(): - loadCheck(c) - - packages_checked = 0 - specfiles_checked = 0 - do_spec_check = 'SpecCheck' in Config.allChecks() - if do_spec_check: - # See comments in "top level import section" for why this isn't - # imported earlier. - import SpecCheck - - try: - # Loop over all file names given in arguments - dirs = [] - for arg in args: - pkgs = [] - isfile = False - try: - if arg == "-": - arg = "(standard input)" - # Short-circuit stdin spec file check - if do_spec_check: - stdin = sys.stdin.readlines() - if not stdin: - continue - pkg = Pkg.FakePkg(arg) - check = SpecCheck.SpecCheck() - check.verbose = verbose - check.check_spec(pkg, None, spec_lines=stdin) - pkg.cleanup() - specfiles_checked += 1 - continue - - try: - st = os.stat(arg) - isfile = True - if stat.S_ISREG(st[stat.ST_MODE]): - if not arg.endswith(".spec"): - pkgs.append(Pkg.Pkg(arg, extract_dir)) - elif do_spec_check: - # Short-circuit spec file checks - pkg = Pkg.FakePkg(arg) - check = SpecCheck.SpecCheck() - check.verbose = verbose - check.check_spec(pkg, arg) - pkg.cleanup() - specfiles_checked += 1 - - elif stat.S_ISDIR(st[stat.ST_MODE]): - dirs.append(arg) - continue - else: - raise OSError - except OSError: - ipkgs = Pkg.getInstalledPkgs(arg) - if not ipkgs: - Pkg.warn( - '(none): E: no installed packages by name %s' % arg) - else: - ipkgs.sort(key = lambda x: locale.strxfrm( - x.header.sprintf("%{NAME}.%{ARCH}"))) - pkgs.extend(ipkgs) - except KeyboardInterrupt: - if isfile: - arg = os.path.abspath(arg) - Pkg.warn( - '(none): E: interrupted, exiting while reading %s' % arg) - sys.exit(2) - except Exception, e: - if isfile: - arg = os.path.abspath(arg) - Pkg.warn('(none): E: error while reading %s: %s' % (arg, e)) - pkgs = [] - continue - - for pkg in pkgs: - runChecks(pkg) - packages_checked += 1 - - for dname in dirs: - try: - for path, dirs, files in os.walk(dname): - for fname in files: - fname = os.path.abspath(os.path.join(path, fname)) - try: - if fname.endswith('.rpm') or \ - fname.endswith('.spm'): - pkg = Pkg.Pkg(fname, extract_dir) - runChecks(pkg) - packages_checked += 1 - - elif do_spec_check and fname.endswith('.spec'): - pkg = Pkg.FakePkg(fname) - check = SpecCheck.SpecCheck() - check.verbose = verbose - check.check_spec(pkg, fname) - pkg.cleanup() - specfiles_checked += 1 - - except KeyboardInterrupt: - Pkg.warn('(none): E: interrupted, exiting while ' + - 'reading %s' % fname) - sys.exit(2) - except Exception, e: - Pkg.warn( - '(none): E: while reading %s: %s' % (fname, e)) - continue - except Exception, e: - Pkg.warn( - '(none): E: error while reading dir %s: %s' % (dname, e)) - continue - - if printAllReasons(): - Pkg.warn('(none): E: badness %d exceeds threshold %d, aborting.' % - (badnessScore(), badnessThreshold())) - sys.exit(66) - - finally: - print "%d packages and %d specfiles checked; %d errors, %d warnings." \ - % (packages_checked, specfiles_checked, - printed_messages["E"], printed_messages["W"]) - - if printed_messages["E"] > 0: - sys.exit(64) - sys.exit(0) - -def runChecks(pkg): - - try: - if verbose: - printInfo(pkg, 'checking') - - for name in Config.allChecks(): - check = AbstractCheck.AbstractCheck.known_checks.get(name) - if check: - check.verbose = verbose - check.check(pkg) - else: - Pkg.warn('(none): W: unknown check %s, skipping' % name) - finally: - pkg.cleanup() - -############################################################################# -# -############################################################################# - -sys.argv[0] = os.path.basename(sys.argv[0]) - -# parse options -try: - (opt, args) = getopt.getopt(sys.argv[1:], - 'iI:c:C:hVvanE:f:o:', - ['info', - 'check=', - 'checkdir=', - 'help', - 'version', - 'verbose', - 'all', - 'noexception', - 'extractdir=', - 'file=', - 'option=', - ]) -except getopt.GetoptError, e: - Pkg.warn("%s: %s" % (sys.argv[0], e)) - usage(sys.argv[0]) - sys.exit(1) - -# process options -checkdir = '/usr/share/rpmlint' -checks = [] -verbose = False -extract_dir = None -conf_file = _default_user_conf -if not os.path.exists(os.path.expanduser(conf_file)): - # deprecated backwards compatibility with < 0.88 - conf_file = '~/.rpmlintrc' -info_error = None - -# load global config files -configs = glob.glob('/etc/rpmlint/*config') -configs.sort() - -# Was rpmlint invoked as a prefixed variant? -m = re.match(r"(?P<prefix>[\w-]+)-rpmlint(\.py)?", sys.argv[0]) -if m: - # Okay, we're a prefixed variant. Look for the variant config. - # If we find it, use it. If not, fallback to the default. - prefix = m.group('prefix') - if os.path.isfile('/usr/share/rpmlint/config.%s' % prefix): - configs.insert(0, '/usr/share/rpmlint/config.%s' % prefix) - else: - configs.insert(0, '/usr/share/rpmlint/config') -else: - configs.insert(0, '/usr/share/rpmlint/config') - -for f in configs: - try: - execfile(f) - except IOError: - pass - except Exception, E: - Pkg.warn('(none): W: error loading %s, skipping: %s' % (f, E)) -# pychecker fix -del f - -config_overrides = {} - -# process command line options -for o in opt: - if o[0] in ('-c', '--check'): - checks.append(o[1]) - elif o[0] in('-i', '--info'): - Config.info = True - elif o[0] == '-I': - info_error = o[1] - elif o[0] in ('-h', '--help'): - usage(sys.argv[0]) - sys.exit(0) - elif o[0] in ('-C', '--checkdir'): - Config.addCheckDir(o[1]) - elif o[0] in ('-v', '--verbose'): - verbose = True - elif o[0] in ('-V', '--version'): - printVersion() - sys.exit(0) - elif o[0] in ('-E', '--extractdir'): - extract_dir = o[1] - Config.setOption('ExtractDir', extract_dir) - elif o[0] in ('-n', '--noexception'): - Config.no_exception = True - elif o[0] in ('-a', '--all'): - if '*' not in args: - args.append('*') - elif o[0] in ('-f', '--file'): - conf_file = o[1] - elif o[0] in ('-o', '--option'): - kv = o[1].split(None, 1) - if len(kv) == 1: - config_overrides[kv[0]] = None - else: - config_overrides[kv[0]] = eval(kv[1]) - -# load user config file -try: - execfile(os.path.expanduser(conf_file)) -except IOError: - pass -except Exception,E: - Pkg.warn('(none): W: error loading %s, skipping: %s' % (conf_file, E)) - -# apply config overrides -for key, value in config_overrides.items(): - Config.setOption(key, value) - -if not extract_dir: - extract_dir = Config.getOption('ExtractDir', tempfile.gettempdir()) - -if info_error: - Config.info = True - sys.path[0:0] = Config.checkDirs() - for c in checks: - Config.addCheck(c) - for c in Config.allChecks(): - loadCheck(c) - for e in info_error.split(','): - print "%s:" % e - printDescriptions(e) - sys.exit(0) - -# if no argument print usage -if not args: - usage(sys.argv[0]) - sys.exit(1) - -if __name__ == '__main__': - if checks: - Config.resetChecks() - for check in checks: - Config.addCheck(check) - main() - -# rpmlint.py ends here - -# Local variables: -# indent-tabs-mode: nil -# py-indent-offset: 4 -# End: -# ex: ts=4 sw=4 et diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rpmlint-1.0/test.sh new/rpmlint-1.1/test.sh --- old/rpmlint-1.0/test.sh 2010-01-25 22:02:09.000000000 +0100 +++ new/rpmlint-1.1/test.sh 2010-12-06 23:58:56.000000000 +0100 @@ -12,6 +12,6 @@ done echo "Check that rpmlint executes with no unexpected errors" -python ./rpmlint.py -C $(pwd) test/*.rpm test/*.spec >/dev/null +python ./rpmlint -C $(pwd) test/*.rpm test/*.spec >/dev/null rc=$? test $rc -eq 0 -o $rc -eq 64 ++++++ rpmlint-add-details.diff ++++++
From c7aa88a93128892705322c564e849ca2a6a74b5b Mon Sep 17 00:00:00 2001 From: scop <scop@9bc8b190-ac0f-0410-8968-dc7d1f502856> Date: Thu, 10 Mar 2011 17:29:42 +0000 Subject: [PATCH] Don't overwrite already existing details (Ludwig Nussel).
This allows the distro config to provide alternative descriptions and distro specific explanations without having to patch checks. git-svn-id: http://rpmlint.zarb.org/svn/trunk@1845 9bc8b190-ac0f-0410-8968-dc7d1f502856 --- Filter.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) Index: rpmlint-1.1/Filter.py =================================================================== --- rpmlint-1.1.orig/Filter.py +++ rpmlint-1.1/Filter.py @@ -115,7 +115,8 @@ _details = {} def addDetails(*details): for idx in range(len(details)/2): - _details[details[idx*2]] = details[idx*2+1] + if not details[idx*2] in _details: + _details[details[idx*2]] = details[idx*2+1] def badnessScore(): global _badness_score ++++++ rpmlint-pkg-quoting.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- Pkg.py.orig +++ Pkg.py -@@ -492,7 +492,7 @@ class Pkg: +@@ -496,7 +496,7 @@ class Pkg: dir = self.dirname) # TODO: better shell escaping or sequence based command invocation command_str = \ ++++++ script-interpreter-only-for-exec-scripts.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,12 +2,12 @@ =================================================================== --- FilesCheck.py.orig +++ FilesCheck.py -@@ -1225,7 +1225,7 @@ class FilesCheck(AbstractCheck.AbstractC - interpreter = None - if res: - interpreter = res.group(1) -- if not interpreter_regex.search(interpreter): -+ if mode & 0111 != 0 and not interpreter_regex.search(interpreter): - printError(pkg, 'wrong-script-interpreter', - f, interpreter) - elif not nonexec_file and not \ +@@ -1238,7 +1238,7 @@ class FilesCheck(AbstractCheck.AbstractC + elif interpreter or mode & 0111 != 0 or \ + script_regex.search(f): + if interpreter: +- if not interpreter_regex.search(interpreter): ++ if mode & 0111 != 0 and not interpreter_regex.search(interpreter): + printError(pkg, 'wrong-script-interpreter', + f, interpreter) + elif not nonexec_file and not \ ++++++ selfconflicts-provide.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- TagsCheck.py +Index: TagsCheck.py +=================================================================== +--- TagsCheck.py.orig +++ TagsCheck.py -@@ -801,6 +801,7 @@ +@@ -815,6 +815,7 @@ class TagsCheck(AbstractCheck.AbstractCh obs_names = [x[0] for x in pkg.obsoletes()] prov_names = [x[0].split(':/')[0] for x in pkg.provides()] @@ -8,7 +10,7 @@ for o in (x for x in obs_names if x not in prov_names): printWarning(pkg, 'obsolete-not-provided', o) -@@ -812,6 +813,8 @@ +@@ -826,6 +827,8 @@ class TagsCheck(AbstractCheck.AbstractCh # https://bugzilla.redhat.com/460872 useless_provides = [] for p in prov_names: @@ -17,7 +19,7 @@ if prov_names.count(p) != 1 and p not in useless_provides: useless_provides.append(p) for p in useless_provides: -@@ -952,6 +955,10 @@ +@@ -966,6 +969,10 @@ the Release tag.''', '''There is no Name tag in your package. You have to specify a name using the Name tag.''', ++++++ sourced-dirs.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,8 +2,8 @@ =================================================================== --- FilesCheck.py.orig +++ FilesCheck.py -@@ -685,7 +685,7 @@ manifest_perl_regex = re.compile('^/usr/ - shebang_regex = re.compile('^#!\s*(\S*)') +@@ -686,7 +686,7 @@ manifest_perl_regex = re.compile('^/usr/ + shebang_regex = re.compile('^#!\s*(\S+)') interpreter_regex = re.compile('^/(usr/)?(s?bin|games|libexec(/.+)?|(lib(64)?|share)/.+)/[^/]+$') script_regex = re.compile('^/((usr/)?s?bin|etc/(rc\.d/init\.d|X11/xinit\.d|cron\.(hourly|daily|monthly|weekly)))/') -sourced_script_regex = re.compile('^/etc/(bash_completion\.d|profile\.d)/') ++++++ stricter-interpreter-check.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,13 +2,13 @@ =================================================================== --- FilesCheck.py.orig +++ FilesCheck.py -@@ -1248,7 +1248,8 @@ class FilesCheck(AbstractCheck.AbstractC - f.endswith('.la')): - printError(pkg, 'script-without-shebang', f) +@@ -1261,7 +1261,8 @@ class FilesCheck(AbstractCheck.AbstractC + f.endswith('.la')): + printError(pkg, 'script-without-shebang', f) -- if mode & 0111 == 0 and not is_doc: -+ if mode & 0111 == 0 and not is_doc and \ -+ interpreter and interpreter.startswith("/"): - printError(pkg, 'non-executable-script', f, - oct(perm), interpreter) - if line.endswith('\r\n') or line.endswith('\r'): +- if mode & 0111 == 0 and not is_doc: ++ if mode & 0111 == 0 and not is_doc and \ ++ interpreter and interpreter.startswith("/"): + printError(pkg, 'non-executable-script', f, + oct(perm), interpreter) + if '\r' in chunk: ++++++ suse-binarieschecks.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,16 @@ ---- BinariesCheck.py +Index: BinariesCheck.py +=================================================================== +--- BinariesCheck.py.orig +++ BinariesCheck.py -@@ -17,6 +17,7 @@ +@@ -10,6 +10,7 @@ + + import re + import stat ++import os + + import rpm + +@@ -17,6 +18,7 @@ from Filter import addDetails, printErro import AbstractCheck import Config import Pkg @@ -8,7 +18,7 @@ DEFAULT_SYSTEM_LIB_PATHS = ( -@@ -37,6 +38,9 @@ +@@ -37,6 +39,9 @@ class BinaryInfo: unused_regex = re.compile('^\s+(\S+)') exit_call_regex = re.compile('\s+FUNC\s+.*?\s+(_?exit(?:@\S+)?)(?:\s|$)') fork_call_regex = re.compile('\s+FUNC\s+.*?\s+(fork(?:@\S+)?)(?:\s|$)') @@ -18,7 +28,7 @@ def __init__(self, pkg, path, file, is_ar, is_shlib): self.readelf_error = False -@@ -50,7 +54,10 @@ +@@ -50,7 +55,10 @@ class BinaryInfo: self.stack = False self.exec_stack = False self.exit_calls = [] @@ -29,7 +39,7 @@ self.tail = '' is_debug = path.endswith('.debug') -@@ -93,6 +100,11 @@ +@@ -93,6 +101,11 @@ class BinaryInfo: self.exec_stack = True continue @@ -41,7 +51,7 @@ if is_shlib: r = BinaryInfo.exit_call_regex.search(l) if r: -@@ -103,6 +115,14 @@ +@@ -103,6 +116,14 @@ class BinaryInfo: fork_called = True continue @@ -56,7 +66,17 @@ if self.non_pic: self.non_pic = 'TEXTREL' in res[1] -@@ -270,6 +290,17 @@ +@@ -263,13 +284,26 @@ class BinariesCheck(AbstractCheck.Abstra + continue + + # stripped ? +- if 'not stripped' in pkgfile.magic: ++ if 'not stripped' in pkgfile.magic and \ ++ (os.environ.get('BUILD_DIR', '') == '' or ++ os.environ.get('BUILD_DEBUG', '') != ''): + printWarning(pkg, 'unstripped-binary-or-object', fname) + + # inspect binary file is_shlib = so_regex.search(fname) bin_info = BinaryInfo(pkg, pkgfile.path, fname, is_ar, is_shlib) @@ -67,25 +87,25 @@ + elif not bin_info.symtab: + printError(pkg, 'static-library-without-symtab', fname) + elif not bin_info.debuginfo and \ -+ (os.environ.get('BUILD_IS_RUNNING', None) == None or \ -+ os.environ.get('BUILD_DEBUG_FLAGS','').find('-g') != -1): ++ (os.environ.get('BUILD_DIR', '') == '' or \ ++ os.environ.get('BUILD_DEBUG','') != ''): + printWarning(pkg, 'static-library-without-debuginfo', fname) + if is_shlib: has_lib = True -@@ -319,6 +350,10 @@ +@@ -319,6 +353,10 @@ class BinariesCheck(AbstractCheck.Abstra for ec in bin_info.exit_calls: printWarning(pkg, 'shared-lib-calls-exit', fname, ec) -+ # gethostbyname ? ++ # gethostbyname ? + if bin_info.calls_gethostbyname: -+ printError(pkg, 'binary-or-shlib-calls-gethostbyname', fname) ++ printInfo(pkg, 'binary-or-shlib-calls-gethostbyname', fname) + # rpath ? if bin_info.rpath: for p in bin_info.rpath: -@@ -504,6 +539,14 @@ +@@ -504,6 +542,14 @@ with the intended shared libraries only. 'ldd-failed', '''Executing ldd on this file failed, all checks could not be run.''', @@ -100,7 +120,7 @@ 'executable-stack', '''The binary declares the stack as executable. Executable stack is usually an error as it is only needed if the code contains GCC trampolines or similar -@@ -516,6 +559,10 @@ +@@ -516,6 +562,10 @@ don\'t define a proper .note.GNU-stack s make the stack executable. Usual suspects include use of a non-GNU linker or an old GNU linker version.''', @@ -111,3 +131,16 @@ 'shared-lib-calls-exit', '''This library package calls exit() or _exit(), probably in a non-fork() context. Doing so from a library is strongly discouraged - when a library +@@ -533,6 +583,12 @@ form, make sure that rpmbuild does not s + that use prelink, make sure that prelink does not strip it either, usually by + placing a blacklist file in /etc/prelink.conf.d. For more information, see + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=256900#49''', ++ ++'unstripped-binary-or-object', ++'''stripping debug info from binaries happens automatically according to global ++project settings. So there's normally no need to manually strip binaries. ++Left over unstripped binaries could therefore indicate a bug in the automatic ++stripping process.''', + ) + + # BinariesCheck.py ends here ++++++ suse-bzip-bigger-than-100k.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- SourceCheck.py +Index: SourceCheck.py +=================================================================== +--- SourceCheck.py.orig +++ SourceCheck.py -@@ -17,7 +17,7 @@ +@@ -17,7 +17,7 @@ import Config DEFAULT_VALID_SRC_PERMS = (0644, 0755) @@ -9,7 +11,7 @@ compress_ext = Config.getOption("CompressExtension", "bz2") valid_src_perms = Config.getOption("ValidSrcPerms", DEFAULT_VALID_SRC_PERMS) -@@ -41,7 +41,7 @@ +@@ -41,7 +41,7 @@ class SourceCheck(AbstractCheck.Abstract else: spec_file = fname elif source_regex.search(fname) and compress_ext and \ @@ -18,7 +20,7 @@ printWarning(pkg, 'source-or-patch-not-compressed', compress_ext, fname) perm = pkgfile.mode & 07777 -@@ -58,8 +58,10 @@ +@@ -58,8 +58,10 @@ all your RPM information.''', 'source-or-patch-not-compressed', '''A source archive or file in your package is not compressed using the %s ++++++ suse-changelog.patch ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- rpmlint-1.0/TagsCheck.py.orig 2010-12-19 15:51:54.000000000 +0100 -+++ rpmlint-1.0/TagsCheck.py 2010-12-19 15:56:43.000000000 +0100 -@@ -1008,8 +1008,8 @@ Development/''', +Index: TagsCheck.py +=================================================================== +--- TagsCheck.py.orig ++++ TagsCheck.py +@@ -1022,8 +1022,8 @@ Development/''', "%s".''' % '", "'.join(VALID_GROUPS), 'no-changelogname-tag', @@ -10,4 +12,4 @@ +spec file and prepare your changes file using e.g. the 'osc vc' command.''', 'no-version-in-last-changelog', - '''The last changelog entry doesn't contain a version. Please insert the + '''The latest changelog entry doesn't contain a version. Please insert the ++++++ suse-check-optional-dependencies.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- FilesCheck.py.orig +++ FilesCheck.py -@@ -928,6 +928,16 @@ class FilesCheck(AbstractCheck.AbstractC +@@ -944,6 +944,16 @@ class FilesCheck(AbstractCheck.AbstractC if res.group(1) != pkg.name: printError(pkg, 'incoherent-logrotate-file', f) @@ -19,7 +19,7 @@ if link != '': ext = compr_regex.search(link) if ext: -@@ -1725,6 +1735,24 @@ consequences), or other compiler flags w +@@ -1739,6 +1749,24 @@ consequences), or other compiler flags w extraction not working as expected. Verify that the binaries are not unexpectedly stripped and that the intended compiler flags are used.''', ++++++ suse-checks.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- Config.py +Index: Config.py +=================================================================== +--- Config.py.orig +++ Config.py -@@ -17,14 +17,13 @@ +@@ -17,14 +17,13 @@ try: except ImportError: __version__ = 'devel' ++++++ suse-file-var-run.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- FilesCheck.py.orig +++ FilesCheck.py -@@ -885,7 +885,7 @@ class FilesCheck(AbstractCheck.AbstractC +@@ -901,7 +901,7 @@ class FilesCheck(AbstractCheck.AbstractC is_kernel_package: printError(pkg, "kernel-modules-not-in-kernel-packages", f) @@ -11,7 +11,7 @@ printError(pkg, 'dir-or-file-in-tmp', f) elif f.startswith('/mnt/'): printError(pkg, 'dir-or-file-in-mnt', f) -@@ -895,6 +895,8 @@ class FilesCheck(AbstractCheck.AbstractC +@@ -911,6 +911,8 @@ class FilesCheck(AbstractCheck.AbstractC printError(pkg, 'dir-or-file-in-usr-local', f) elif f.startswith('/var/local/'): printError(pkg, 'dir-or-file-in-var-local', f) @@ -20,7 +20,7 @@ elif sub_bin_regex.search(f): printError(pkg, 'subdir-in-bin', f) elif f.startswith('/home/'): -@@ -1465,6 +1467,12 @@ for packages to install files in this di +@@ -1478,6 +1480,12 @@ for packages to install files in this di '''A file in the package is located in /var/local. It's not permitted for packages to install files in this directory.''', ++++++ suse-no-run-ldconfig.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- SpecCheck.py +Index: SpecCheck.py +=================================================================== +--- SpecCheck.py.orig +++ SpecCheck.py -@@ -394,6 +394,10 @@ +@@ -403,6 +403,10 @@ class SpecCheck(AbstractCheck.AbstractCh printWarning(pkg, 'comparison-operator-in-deptoken', conf) @@ -11,7 +13,7 @@ if current_section == 'changelog': for match in AbstractCheck.macro_regex.findall(line): res = re.match('%+', match) -@@ -681,6 +685,14 @@ +@@ -715,6 +719,14 @@ may break short circuit builds.''', '''Make check or other automated regression test should be run in %check, as they can be disabled with a rpm macro for short circuiting purposes.''', ++++++ suse-pkg-config-check.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- TagsCheck.py.orig +++ TagsCheck.py -@@ -414,6 +414,7 @@ lib_devel_number_regex = re.compile('^li +@@ -416,6 +416,7 @@ lib_devel_number_regex = re.compile('^li invalid_url_regex = re.compile(Config.getOption('InvalidURL'), re.IGNORECASE) lib_package_regex = re.compile('(?:^(?:compat-)?lib.*?(\.so.*)?|libs?[\d-]*)$', re.IGNORECASE) leading_space_regex = re.compile('^\s+') @@ -10,7 +10,7 @@ license_regex = re.compile('\(([^)]+)\)|\s(?:and|or)\s') invalid_version_regex = re.compile('([0-9](?:rc|alpha|beta|pre).*)', re.IGNORECASE) # () are here for grouping purpose in the regexp -@@ -623,10 +624,12 @@ class TagsCheck(AbstractCheck.AbstractCh +@@ -627,10 +628,12 @@ class TagsCheck(AbstractCheck.AbstractCh base = is_devel.group(1) dep = None has_so = False @@ -24,7 +24,7 @@ if has_so: base_or_libs = base + '/' + base + '-libs/lib' + base # try to match *%_isa as well (e.g. "(x86-64)", "(x86-32)") -@@ -663,6 +666,15 @@ class TagsCheck(AbstractCheck.AbstractCh +@@ -667,6 +670,15 @@ class TagsCheck(AbstractCheck.AbstractCh if prov not in (x[0] for x in pkg.provides()): printWarning(pkg, 'no-provides', prov) @@ -40,7 +40,7 @@ # List of words to ignore in spell check ignored_words = set() for pf in pkg.files(): -@@ -1082,6 +1094,11 @@ instead or require a file in bin or /etc +@@ -1104,6 +1116,11 @@ instead or require a file in bin or /etc 'no-url-tag', '''The URL tag is missing. Please add a http or ftp link to the project location.''', ++++++ suse-rclink-check.diff ++++++ --- InitScriptCheck.py +++ InitScriptCheck.py @@ -51,7 +51,7 @@ return initscript_list = [] - + rclinks = set() # check chkconfig call in %post and %preun postin = pkg[rpm.RPMTAG_POSTIN] or pkg[rpm.RPMTAG_POSTINPROG] @@ -60,6 +60,9 @@ for fname, pkgfile in pkg.files().items(): + if stat.S_ISLNK(pkgfile.mode) and fname.startswith("/usr/sbin/rc"): + rclinks.add(fname.partition('/rc')[2]) + if not fname.startswith('/etc/init.d/') and \ not fname.startswith('/etc/rc.d/init.d/'): continue @@ -199,6 +202,12 @@ if not subsys_regex_found: printError(pkg, 'subsys-not-used', fname) + for script in initscript_list: + if script.startswith("rc") or script.startswith("boot."): + continue + if not script in rclinks: + printWarning(pkg, 'suse-missing-rclink', script) + goodnames = (pkg.name.lower(), pkg.name.lower() + 'd') if len(initscript_list) == 1 and initscript_list[0] not in goodnames: printWarning(pkg, 'incoherent-init-script-name', initscript_list[0], @@ -229,6 +238,10 @@ '''The package contains an init script but doesn't contain a %postun with a call to %insserv_cleanup-postun''', +'suse-missing-rclink', +'''The package contains an init script with the given name but does not +have contain the SUSE policy symlink /usr/sbin/rcFOO -> /etc/init.d/FOO''', + 'preun-without-chkconfig', '''The package contains an init script but doesn't call chkconfig in its %preun script.''', ++++++ suse-shlib-devel-dependency.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- TagsCheck.py.orig +++ TagsCheck.py -@@ -631,10 +631,10 @@ class TagsCheck(AbstractCheck.AbstractCh +@@ -635,10 +635,10 @@ class TagsCheck(AbstractCheck.AbstractCh if pkg_config_regex.match(fname) and fname.endswith('.pc'): has_pc = True if has_so: ++++++ suse-url-check.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- TagsCheck.py +Index: TagsCheck.py +=================================================================== +--- TagsCheck.py.orig +++ TagsCheck.py -@@ -762,7 +762,7 @@ +@@ -776,7 +776,7 @@ class TagsCheck(AbstractCheck.AbstractCh if not valid_license: self._unexpanded_macros(pkg, 'License', rpm_license) @@ -9,7 +11,7 @@ if hasattr(rpm, 'RPMTAG_%s' % tag.upper()): url = pkg[getattr(rpm, 'RPMTAG_%s' % tag.upper())] self._unexpanded_macros(pkg, tag, url, is_url = True) -@@ -1070,7 +1070,7 @@ +@@ -1092,7 +1092,7 @@ once.''', '''This rpm requires a specific release of another package.''', 'no-url-tag', ++++++ suse-version.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -23,7 +23,7 @@ res = prereq_regex.search(line) if res: printError(pkg, 'prereq-use', res.group(2)) -@@ -731,6 +738,15 @@ set which may result in security issues +@@ -756,6 +763,15 @@ set which may result in security issues depending on the system where the package is built. Add default attributes using %defattr before it in the %files section, or use per line %attr's.''', ++++++ suse-whitelist-opensuse.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- TagsCheck.py +Index: TagsCheck.py +=================================================================== +--- TagsCheck.py.orig +++ TagsCheck.py -@@ -868,7 +868,7 @@ +@@ -881,7 +881,7 @@ class TagsCheck(AbstractCheck.AbstractCh spell_check(pkg, utf8summary, 'Summary(%s)', lang, ignored_words) if '\n' in summary: printError(pkg, 'summary-on-multiple-lines', lang) ++++++ sysv5-init-checks.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,15 +1,17 @@ --- InitScriptCheck.py +++ InitScriptCheck.py -@@ -30,6 +30,8 @@ - use_deflevels = Config.getOption('UseDefaultRunlevels', 1) +@@ -29,6 +29,10 @@ + use_deflevels = Config.getOption('UseDefaultRunlevels', True) lsb_tags_regex = re.compile('^# ([\w-]+):\s*(.*?)\s*$') lsb_cont_regex = re.compile('^#(?:\t| )(.*?)\s*$') +insserv_regex=re.compile('^\s*sbin/insserv', re.MULTILINE) -+preun_regex=re.compile('^\s*/etc/init.d/\S+ stop', re.MULTILINE) ++preun_regex=re.compile('^\s*%stop_on_removal\s+\S+', re.MULTILINE) ++restart_on_update_regex=re.compile('^\s*%restart_on_update \S+', re.MULTILINE) ++insserv_cleanup_regex=re.compile('^\s*%insserv_cleanup', re.MULTILINE) LSB_KEYWORDS = ('Provides', 'Required-Start', 'Required-Stop', 'Should-Start', 'Should-Stop', 'Default-Start', 'Default-Stop', -@@ -48,6 +50,13 @@ +@@ -47,6 +51,13 @@ return initscript_list = [] @@ -21,34 +23,41 @@ + postun = pkg[rpm.RPMTAG_POSTUN] or pkg[rpm.RPMTAG_POSTUNPROG] + for fname, pkgfile in pkg.files().items(): - if rc_regex.search(fname): - basename = os.path.basename(fname) -@@ -57,13 +66,17 @@ - - if dot_in_name_regex.match(basename): - printError(pkg, 'init-script-name-with-dot', fname) -- # check chkconfig call in %post and %preun -- postin = pkg[rpm.RPMTAG_POSTIN] or pkg[rpm.RPMTAG_POSTINPROG] - if not postin: -- printError(pkg, 'init-script-without-chkconfig-postin', fname) -+ printError(pkg, 'init-script-without-%stop_on_removal-postin', fname) -+ else: -+ if not preun_regex.search(preun): -+ printError(pkg, 'preun-without-%stop_on_removal-preun', f) -+ -+ if not postun: -+ printError(pkg, 'init-script-without-%insserv_cleanup-postun', f) - else: -- if not chkconfig_regex.search(postin): -- printError(pkg, 'postin-without-chkconfig', fname) -+ if not insserv_regex.search(postun): -+ printError(pkg, 'postun-without-%insserv_cleanup', f) - - preun = pkg[rpm.RPMTAG_PREUN] or pkg[rpm.RPMTAG_PREUNPROG] - if not preun: -@@ -193,10 +206,18 @@ - 'postin-without-chkconfig', - '''The package contains an init script but doesn't call chkconfig in its %post.''', + + if not fname.startswith('/etc/init.d/') and \ +@@ -60,18 +71,19 @@ + + if dot_in_name_regex.match(basename): + printError(pkg, 'init-script-name-with-dot', fname) +- # check chkconfig call in %post and %preun +- postin = pkg[rpm.RPMTAG_POSTIN] or pkg[rpm.RPMTAG_POSTINPROG] +- if not postin: +- printError(pkg, 'init-script-without-chkconfig-postin', fname) +- elif not chkconfig_regex.search(postin): +- printError(pkg, 'postin-without-chkconfig', fname) + +- preun = pkg[rpm.RPMTAG_PREUN] or pkg[rpm.RPMTAG_PREUNPROG] + if not preun: +- printError(pkg, 'init-script-without-chkconfig-preun', fname) +- elif not chkconfig_regex.search(preun): +- printError(pkg, 'preun-without-chkconfig', fname) ++ printError(pkg, 'init-script-without-%stop_on_removal-preun', fname) ++ elif not stop_on_removal_regex.search(postin): ++ printError(pkg, 'preun-without-%%stop_on_removal-preun', fname) ++ ++ if not postun: ++ printError(pkg, 'init-script-without-%restart_on_update-postun', fname) ++ else: ++ if not restart_on_update_regex.search(postun): ++ printError(pkg, 'postun-without-%restart_on_update', fname) ++ if not insserv_cleanup_regex.search(postun): ++ printError(pkg, 'postun-without-%insserv_cleanup', fname) + + status_found = False + reload_found = False +@@ -202,10 +214,18 @@ + '''The package contains an init script but doesn't call chkconfig in its + %post script.''', -'init-script-without-chkconfig-preun', +'init-script-without-%stop_on_removal-preun', @@ -64,9 +73,9 @@ +with a call to %insserv_cleanup-postun''', + 'preun-without-chkconfig', - '''The package contains an init script but doesn't call chkconfig in its %preun.''', - -@@ -254,6 +275,18 @@ + '''The package contains an init script but doesn't call chkconfig in its + %preun script.''', +@@ -264,6 +284,24 @@ 'init-script-non-executable', '''The init script should have at least the execution bit set for root in order for it to run at boot time.''', @@ -81,7 +90,13 @@ +'''The package doesn't have a %insserv_cleanup call in %postun''', + +'postun-without-%insserv_cleanup', -+'''The package doesn't have a %insserv_cleanup call in %postun''', ++'''The package has an init script that is inserted with insserv but ++doesn't have a %insserv_cleanup call in %postun''', ++ ++'init-script-without-%restart_on_update-postun', ++''' The package has an init script but is missing the %restart_on_update ++call in %postun to automatically restart the daemon. This is optional, ++but in most cases it is wanted. Please check.''' ) # InitScriptCheck.py ends here ++++++ usr-arch.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- BinariesCheck.py.orig +++ BinariesCheck.py -@@ -196,6 +196,7 @@ usr_lib_exception_regex = re.compile(Con +@@ -197,6 +197,7 @@ usr_lib_exception_regex = re.compile(Con srcname_regex = re.compile('(.*?)-[0-9]') invalid_dir_ref_regex = re.compile('/(home|tmp)(\W|$)') ocaml_mixed_regex = re.compile('^Caml1999X0\d\d$') @@ -10,7 +10,7 @@ def dir_base(path): res = path_regex.search(path) -@@ -268,7 +269,7 @@ class BinariesCheck(AbstractCheck.Abstra +@@ -269,7 +270,7 @@ class BinariesCheck(AbstractCheck.Abstra # arch dependent packages only from here on # in /usr/share ? ++++++ xdg-paths-update.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -1,6 +1,8 @@ ---- MenuXDGCheck.py +Index: MenuXDGCheck.py +=================================================================== +--- MenuXDGCheck.py.orig +++ MenuXDGCheck.py -@@ -18,7 +18,7 @@ +@@ -18,7 +18,7 @@ class MenuXDGCheck(AbstractCheck.Abstrac # $ echo $XDG_DATA_DIRS/applications # /var/lib/menu-xdg:/usr/share AbstractCheck.AbstractFilesCheck.__init__( ++++++ yast-provides.diff ++++++ --- /var/tmp/diff_new_pack.zJvCTr/_old 2011-04-21 12:10:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zJvCTr/_new 2011-04-21 12:10:51.000000000 +0200 @@ -2,7 +2,7 @@ =================================================================== --- TagsCheck.py.orig +++ TagsCheck.py -@@ -795,7 +795,7 @@ class TagsCheck(AbstractCheck.AbstractCh +@@ -809,7 +809,7 @@ class TagsCheck(AbstractCheck.AbstractCh printWarning(pkg, 'no-url-tag') obs_names = [x[0] for x in pkg.obsoletes()] ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org
participants (1)
-
root@hilbert.suse.de