From 8f15cc627cc9f1d25634f4eb0675411935e249e5 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Tue, 23 Feb 2021 09:26:05 +0900 Subject: [PATCH] Imported Upstream version 1.7 --- AbstractCheck.py | 2 +- AppDataCheck.py | 14 ++-- BinariesCheck.py | 2 +- FilesCheck.py | 69 +++++++++--------- Filter.py | 16 +++-- INSTALL | 6 +- InitScriptCheck.py | 6 +- Makefile | 28 +++++--- MenuCheck.py | 4 +- Pkg.py | 203 +++++++++++++++++++++++++++++++++-------------------- PostCheck.py | 31 +++----- SCLCheck.py | 2 +- SourceCheck.py | 2 +- SpecCheck.py | 13 ++-- TagsCheck.py | 81 +++++++++++---------- ZipCheck.py | 3 +- config | 4 ++ rpmlint | 65 ++++++++--------- test.sh | 7 +- 19 files changed, 312 insertions(+), 246 deletions(-) diff --git a/AbstractCheck.py b/AbstractCheck.py index 64d279e..1c2bae0 100644 --- a/AbstractCheck.py +++ b/AbstractCheck.py @@ -57,7 +57,7 @@ class AbstractCheck: def check_binary(self, pkg): return - def check_spec(self, pkg, spec_file, spec_lines=[]): + def check_spec(self, pkg, spec_file): return def check_url(self, pkg, tag, url): diff --git a/AppDataCheck.py b/AppDataCheck.py index 03fc655..57c0fe9 100644 --- a/AppDataCheck.py +++ b/AppDataCheck.py @@ -9,8 +9,12 @@ from Filter import addDetails, printError from Pkg import getstatusoutput import AbstractCheck +import Config STANDARD_BIN_DIRS = ['/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/'] +DEFAULT_APPDATA_CHECKER = ('appstream-util', 'validate-relax') + +appdata_checker = Config.getOption("AppDataChecker", DEFAULT_APPDATA_CHECKER) class AppDataCheck(AbstractCheck.AbstractFilesCheck): @@ -25,21 +29,19 @@ class AppDataCheck(AbstractCheck.AbstractFilesCheck): root = pkg.dirName() f = root + filename try: - st = getstatusoutput(('appdata-validate', f), True) + st = getstatusoutput(appdata_checker + (f,)) except OSError: - # ignore the check if appdata-validate is not install + # ignore if the checker is not installed return if st[0]: - for line in st[1].splitlines(): - if 'problems detected' in line: - printError(pkg, 'invalid-appdata-file', filename) + printError(pkg, 'invalid-appdata-file', filename) check = AppDataCheck() addDetails( 'invalid-appdata-file', -'''appdata file is not valid, check with appdata-validate''', +'''appdata file is not valid, check with %s''' % (" ".join(appdata_checker)), ) # Local variables: diff --git a/BinariesCheck.py b/BinariesCheck.py index 4634eed..b80a3fa 100644 --- a/BinariesCheck.py +++ b/BinariesCheck.py @@ -278,7 +278,7 @@ class BinariesCheck(AbstractCheck.AbstractCheck): multi_pkg = False srpm = pkg[rpm.RPMTAG_SOURCERPM] if srpm: - res = srcname_regex.search(Pkg.b2s(srpm)) + res = srcname_regex.search(srpm) if res: multi_pkg = (pkg.name != res.group(1)) diff --git a/FilesCheck.py b/FilesCheck.py index 1ad548b..1e43bf3 100644 --- a/FilesCheck.py +++ b/FilesCheck.py @@ -17,7 +17,7 @@ import sys import rpm from Filter import addDetails, printError, printWarning -from Pkg import b2s, catcmd, getstatusoutput, is_utf8, is_utf8_str +from Pkg import b2s, catcmd, getstatusoutput, is_utf8, is_utf8_bytestr import AbstractCheck import Config @@ -194,7 +194,7 @@ buildconfig_rpath_regex = re.compile('(?:-rpath|Wl,-R)\\b') sofile_regex = re.compile('/lib(64)?/(.+/)?lib[^/]+\.so$') devel_regex = re.compile('(.*)-(debug(info)?|devel|headers|source|static)$') debuginfo_package_regex = re.compile('-debug(info)?$') -lib_regex = re.compile('lib(64)?/lib[^/]*\.so\..*') +lib_regex = re.compile('lib(64)?/lib[^/]*(\.so\..*|-[0-9.]+\.so)') ldconfig_regex = re.compile('^[^#]*ldconfig', re.MULTILINE) depmod_regex = re.compile('^[^#]*depmod', re.MULTILINE) install_info_regex = re.compile('^[^#]*install-info', re.MULTILINE) @@ -312,7 +312,7 @@ def peek(filename, pkg, length=1024): return (chunk, istext) # See Python sources for a full list of the values here. -# http://hg.python.org/cpython/file/tip/Lib/importlib/_bootstrap.py +# http://hg.python.org/cpython/file/tip/Lib/importlib/_bootstrap_external.py # http://hg.python.org/cpython/file/2.7/Python/import.c _python_magic_values = { '2.2': 60717, @@ -326,6 +326,7 @@ _python_magic_values = { '3.2': 3180, '3.3': 3230, '3.4': 3310, + '3.5': 3350, } @@ -394,17 +395,17 @@ class FilesCheck(AbstractCheck.AbstractCheck): def check(self, pkg): - files = pkg.files() - if use_utf8: - for filename in files: - if not is_utf8_str(filename): - printError(pkg, 'filename-not-utf8', filename) + for filename in pkg.header[rpm.RPMTAG_FILENAMES] or (): + if not is_utf8_bytestr(filename): + printError(pkg, 'filename-not-utf8', b2s(filename)) # Rest of the checks are for binary packages only if pkg.isSource(): return + files = pkg.files() + # Check if the package is a development package devel_pkg = devel_regex.search(pkg.name) @@ -421,7 +422,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): python_dep_error = False lib_file = False non_lib_file = None - log_file = None + log_files = [] logrotate_file = False debuginfo_srcs = False debuginfo_debugs = False @@ -512,13 +513,13 @@ class FilesCheck(AbstractCheck.AbstractCheck): mode_is_exec = mode & int("111", 8) if log_regex.search(f): - log_file = f + log_files.append(f) # Hardlink check - hardlink = hardlinks.get((rdev, inode)) - if hardlink and os.path.dirname(hardlink) != os.path.dirname(f): - printWarning(pkg, 'cross-directory-hard-link', f, hardlink) - hardlinks[(rdev, inode)] = f + for hardlink in hardlinks.get((rdev, inode), ()): + if os.path.dirname(hardlink) != os.path.dirname(f): + printWarning(pkg, 'cross-directory-hard-link', f, hardlink) + hardlinks.setdefault((rdev, inode), []).append(f) # normal file check if stat.S_ISREG(mode): @@ -526,24 +527,24 @@ class FilesCheck(AbstractCheck.AbstractCheck): # set[ug]id bit check if stat.S_ISGID & mode or stat.S_ISUID & mode: if stat.S_ISUID & mode: - printError(pkg, 'setuid-binary', f, user, oct(perm)) + printError(pkg, 'setuid-binary', f, user, "%o" % perm) if stat.S_ISGID & mode: if not (group == 'games' and (games_path_regex.search(f) or games_group_regex.search( pkg[rpm.RPMTAG_GROUP]))): printError(pkg, 'setgid-binary', f, group, - oct(perm)) + "%o" % perm) if mode & int("777", 8) != int("755", 8): printError(pkg, 'non-standard-executable-perm', f, - oct(perm)) + "%o" % perm) # Prefetch scriptlets, strip quotes from them (#169) - postin = b2s(pkg[rpm.RPMTAG_POSTIN]) or \ + postin = pkg[rpm.RPMTAG_POSTIN] or \ pkg.scriptprog(rpm.RPMTAG_POSTINPROG) if postin: postin = quotes_regex.sub('', postin) - postun = b2s(pkg[rpm.RPMTAG_POSTUN]) or \ + postun = pkg[rpm.RPMTAG_POSTUN] or \ pkg.scriptprog(rpm.RPMTAG_POSTUNPROG) if postun: postun = quotes_regex.sub('', postun) @@ -582,6 +583,8 @@ class FilesCheck(AbstractCheck.AbstractCheck): # check ldconfig call in %post and %postun if lib_regex.search(f): + if devel_pkg: + printError(pkg, 'non-devel-file-in-devel-package', f) if not postin: printError(pkg, 'library-without-ldconfig-postin', f) else: @@ -624,7 +627,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): elif not install_info_regex.search(postin): printError(pkg, 'postin-without-install-info', f) - preun = b2s(pkg[rpm.RPMTAG_PREUN]) or \ + preun = pkg[rpm.RPMTAG_PREUN] or \ pkg.scriptprog(rpm.RPMTAG_PREUNPROG) if not postun and not preun: printError(pkg, @@ -638,7 +641,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): if perl_temp_file_regex.search(f): printWarning(pkg, 'perl-temp-file', f) - is_buildconfig = buildconfigfile_regex.search(f) and True + is_buildconfig = istext and buildconfigfile_regex.search(f) # check rpaths in buildconfig files if is_buildconfig: @@ -650,7 +653,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): if res: if not mode_is_exec: printWarning(pkg, 'non-executable-in-bin', f, - oct(perm)) + "%o" % perm) else: exe = res.group(1) if "/" not in exe: @@ -668,13 +671,13 @@ class FilesCheck(AbstractCheck.AbstractCheck): ok_nonreadable = True break if not ok_nonreadable: - printError(pkg, 'non-readable', f, oct(perm)) + printError(pkg, 'non-readable', f, "%o" % perm) if size == 0 and not normal_zero_length_regex.search(f) and \ f not in ghost_files: printError(pkg, 'zero-length', f) if mode & stat.S_IWOTH: - printError(pkg, 'world-writable', f, oct(perm)) + printError(pkg, 'world-writable', f, "%o" % perm) if not perl_dep_error: res = perl_regex.search(f) @@ -748,7 +751,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): # normal executable check if mode & stat.S_IXUSR and perm != int("755", 8): printError(pkg, 'non-standard-executable-perm', - f, oct(perm)) + f, "%o" % perm) if mode_is_exec: if f in config_files: printError(pkg, 'executable-marked-as-config-file', f) @@ -818,7 +821,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): interpreter) if mode_is_exec: printError(pkg, 'executable-sourced-script', - f, oct(perm)) + f, "%o" % perm) # ...but executed ones should elif interpreter or mode_is_exec or script_regex.search(f): if interpreter: @@ -832,7 +835,7 @@ class FilesCheck(AbstractCheck.AbstractCheck): if not mode_is_exec and not is_doc: printError(pkg, 'non-executable-script', f, - oct(perm), interpreter) + "%o" % perm, interpreter) if b'\r' in chunk: printError( pkg, 'wrong-script-end-of-line-encoding', f) @@ -859,9 +862,9 @@ class FilesCheck(AbstractCheck.AbstractCheck): # normal dir check elif stat.S_ISDIR(mode): if mode & int("1002", 8) == 2: # world writable w/o sticky bit - printError(pkg, 'world-writable', f, oct(perm)) + printError(pkg, 'world-writable', f, "%o" % perm) if perm != int("755", 8): - printError(pkg, 'non-standard-dir-perm', f, oct(perm)) + printError(pkg, 'non-standard-dir-perm', f, "%o" % perm) if pkg.name not in filesys_packages and f in STANDARD_DIRS: printError(pkg, 'standard-dir-owned-by-package', f) if hidden_file_regex.search(f): @@ -975,8 +978,8 @@ class FilesCheck(AbstractCheck.AbstractCheck): if stat.S_IWGRP & mode or stat.S_IWOTH & mode: printError(pkg, 'non-owner-writeable-only-crontab-file', f) - if log_file and not logrotate_file: - printWarning(pkg, 'log-files-without-logrotate', log_file) + if len(log_files) and not logrotate_file: + printWarning(pkg, 'log-files-without-logrotate', sorted(log_files)) if lib_package and lib_file and non_lib_file: printError(pkg, 'outside-libdir-files', non_lib_file) @@ -1106,6 +1109,9 @@ that the file is an executable or that it has executable permissions.''', package. If you want to include source code in your package, be sure to create a development package.''', +'non-devel-file-in-devel-package', +'''A non-development file is located in a devel package.''', + 'non-standard-dir-perm', '''A standard directory should have permission set to 0755. If you get this message, it means that you have wrong directory permissions in some dirs @@ -1362,7 +1368,6 @@ for i in disallowed_dirs: for packages to install files in this directory.''' % i) - # FilesCheck.py ends here # Local variables: diff --git a/Filter.py b/Filter.py index eaa8384..5ce6219 100644 --- a/Filter.py +++ b/Filter.py @@ -7,6 +7,7 @@ # Purpose : filter the output of rpmlint to allow exceptions. ############################################################################# +from __future__ import print_function import locale import sys import textwrap @@ -27,10 +28,16 @@ if sys.stdout.isatty(): def __print(s): print(s) else: + __stdout = sys.stdout + if not __stdout.encoding: # Python < 3 only? + import codecs + if hasattr(__stdout, "buffer"): + __stdout = __stdout.buffer + __stdout = codecs.getwriter( + locale.getpreferredencoding())(__stdout, "replace") + def __print(s): - if isinstance(s, unicode): - s = s.encode(locale.getpreferredencoding(), "replace") - print(s) + print(s, file=__stdout) def printInfo(pkg, reason, *details): @@ -75,7 +82,8 @@ def _print(msgtype, pkg, reason, details): Testing.addOutput(s) else: if _rawout: - print >>_rawout, s.encode(locale.getpreferredencoding(), "replace") + print(s.encode(locale.getpreferredencoding(), "replace"), + file=_rawout) if not Config.isFiltered(s): printed_messages[msgtype] += 1 _badness_score += badness diff --git a/INSTALL b/INSTALL index c53ae86..34d5da0 100644 --- a/INSTALL +++ b/INSTALL @@ -1,6 +1,6 @@ You need the following utilities to run rpmlint: - o python 2.x (x >= 6) + o python 2.6 or newer o rpm 4.4.2.2 or newer and its python bindings o libmagic and its python bindings (optional) o readelf @@ -9,11 +9,11 @@ You need the following utilities to run rpmlint: o gzip, bzip2 and xz o groff and gtbl (optional) o enchant and its python bindings (optional) - o appdata-validate (optional) + o appstream-util, part of appstream-glib (optional) and the following programs to install it: - o python 2.x (x >= 6) + o python 2.6 or newer o rpm python bindings 4.4 or newer o sed o pytest (for running the test suite) diff --git a/InitScriptCheck.py b/InitScriptCheck.py index 5d851d4..0559405 100644 --- a/InitScriptCheck.py +++ b/InitScriptCheck.py @@ -59,14 +59,14 @@ class InitScriptCheck(AbstractCheck.AbstractCheck): printError(pkg, 'init-script-name-with-dot', fname) # check chkconfig call in %post and %preun - postin = Pkg.b2s(pkg[rpm.RPMTAG_POSTIN]) or \ + postin = pkg[rpm.RPMTAG_POSTIN] or \ pkg.scriptprog(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.b2s(pkg[rpm.RPMTAG_PREUN]) or \ + preun = pkg[rpm.RPMTAG_PREUN] or \ pkg.scriptprog(rpm.RPMTAG_PREUNPROG) if not preun: printError(pkg, 'init-script-without-chkconfig-preun', fname) @@ -84,7 +84,7 @@ class InitScriptCheck(AbstractCheck.AbstractCheck): # check common error in file content content = None try: - content = Pkg.readlines(pkgfile.path) + content = [x for x in Pkg.readlines(pkgfile.path)] except Exception: e = sys.exc_info()[1] printWarning(pkg, 'read-error', e) diff --git a/Makefile b/Makefile index e6e2a36..1efe7b4 100644 --- a/Makefile +++ b/Makefile @@ -17,29 +17,35 @@ FILES = rpmlint *.py INSTALL README README.devel COPYING tools/*.py \ GENERATED = ChangeLog __version__.py PACKAGE = rpmlint -PYTHON = python +PYTHON = /usr/bin/python # update this variable to create a new release -VERSION := 1.6 +VERSION := 1.7 # for the [A-Z]* part LC_ALL:=C export LC_ALL all: __version__.py __isocodes__.py - if [ "x${COMPILE_PYC}" = "x1" ] ; then \ - $(PYTHON) -m py_compile [A-Z]*.py __*__.py ; \ - fi - $(PYTHON) -O -m py_compile [A-Z]*.py __*__.py clean: - rm -f *~ *.pyc *.pyo $(GENERATED) + rm -rf *~ *.py[co] */*.py[co] __pycache__ */__pycache__ $(GENERATED) install: all mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(ETCDIR)/$(PACKAGE) $(DESTDIR)$(MANDIR)/man1 - -cp -p *.pyc $(DESTDIR)$(LIBDIR) - cp -p *.py *.pyo $(DESTDIR)$(LIBDIR) - cp -p rpmlint rpmdiff $(DESTDIR)$(BINDIR) + cp -p *.py $(DESTDIR)$(LIBDIR) + if [ "x${COMPILE_PYC}" = "x1" ] ; then \ + $(PYTHON) -m py_compile \ + $(DESTDIR)$(LIBDIR)/[A-Z]*.py \ + $(DESTDIR)$(LIBDIR)/__*__.py ; \ + fi + $(PYTHON) -O -m py_compile \ + $(DESTDIR)$(LIBDIR)/[A-Z]*.py \ + $(DESTDIR)$(LIBDIR)/__*__.py ; \ + for file in rpmlint rpmdiff ; do \ + sed -e "s,#!/usr/bin/python ,#!$(PYTHON) ," $$file > $(DESTDIR)$(BINDIR)/$$file ; \ + chmod +x $(DESTDIR)$(BINDIR)/$$file ; \ + done cp -p config $(DESTDIR)$(ETCDIR)/$(PACKAGE) compdir=`pkg-config --variable=completionsdir bash-completion 2>/dev/null` ; \ if [ "x$$compdir" = "x" ] ; then \ @@ -48,7 +54,7 @@ install: all else \ mkdir -p $(DESTDIR)$$compdir ; \ cp -p rpmlint.bash-completion $(DESTDIR)$$compdir/rpmlint ; \ - ln -s rpmlint $(DESTDIR)$$compdir/rpmdiff ; \ + ln -sf rpmlint $(DESTDIR)$$compdir/rpmdiff ; \ fi cp -p rpmdiff.1 rpmlint.1 $(DESTDIR)$(MANDIR)/man1 diff --git a/MenuCheck.py b/MenuCheck.py index c137ab9..7751133 100644 --- a/MenuCheck.py +++ b/MenuCheck.py @@ -198,14 +198,14 @@ class MenuCheck(AbstractCheck.AbstractCheck): printError(pkg, 'menu-in-wrong-dir', fname) if menus: - postin = Pkg.b2s(pkg[rpm.RPMTAG_POSTIN]) or \ + postin = pkg[rpm.RPMTAG_POSTIN] or \ pkg.scriptprog(rpm.RPMTAG_POSTINPROG) if not postin: printError(pkg, 'menu-without-postin') elif not update_menus_regex.search(postin): printError(pkg, 'postin-without-update-menus') - postun = Pkg.b2s(pkg[rpm.RPMTAG_POSTUN]) or \ + postun = pkg[rpm.RPMTAG_POSTUN] or \ pkg.scriptprog(rpm.RPMTAG_POSTUNPROG) if not postun: printError(pkg, 'menu-without-postun') diff --git a/Pkg.py b/Pkg.py index e97d7ef..7439a3f 100644 --- a/Pkg.py +++ b/Pkg.py @@ -13,7 +13,6 @@ import re import subprocess import sys import tempfile -import unicodedata try: from urlparse import urljoin except: @@ -37,6 +36,7 @@ if sys.version_info[0] > 2: # Blows up with Python < 3 without the exec() hack exec('def warn(s): print (s, file=sys.stderr)') long = int + unicode = str def b2s(b): if b is None: @@ -62,6 +62,17 @@ PREREQ_FLAG = (rpm.RPMSENSE_PREREQ or 64) | \ rpm.RPMSENSE_SCRIPT_PREUN | \ rpm.RPMSENSE_SCRIPT_POSTUN +SCRIPT_TAGS = [ + (rpm.RPMTAG_PREIN, rpm.RPMTAG_PREINPROG, '%pre'), + (rpm.RPMTAG_POSTIN, rpm.RPMTAG_POSTINPROG, '%post'), + (rpm.RPMTAG_PREUN, rpm.RPMTAG_PREUNPROG, '%preun'), + (rpm.RPMTAG_POSTUN, rpm.RPMTAG_POSTUNPROG, '%postun'), + (rpm.RPMTAG_TRIGGERSCRIPTS, rpm.RPMTAG_TRIGGERSCRIPTPROG, '%trigger'), + (rpm.RPMTAG_PRETRANS, rpm.RPMTAG_PRETRANSPROG, '%pretrans'), + (rpm.RPMTAG_POSTTRANS, rpm.RPMTAG_POSTTRANSPROG, '%posttrans'), + (rpm.RPMTAG_VERIFYSCRIPT, rpm.RPMTAG_VERIFYSCRIPTPROG, '%verifyscript'), + ] + var_regex = re.compile('^(.*)\${?(\w+)}?(.*)$') @@ -91,7 +102,7 @@ def substitute_shell_vars(val, script): return val -def getstatusoutput(cmd, stdoutonly=False, shell=False): +def getstatusoutput(cmd, stdoutonly=False, shell=False, raw=False): '''A version of commands.getstatusoutput() which can take cmd as a sequence, thus making it potentially more secure.''' if stdoutonly: @@ -102,12 +113,15 @@ def getstatusoutput(cmd, stdoutonly=False, shell=False): stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) proc.stdin.close() - text = b2s(proc.stdout.read()) + with proc.stdout: + text = proc.stdout.read() sts = proc.wait() + if not raw: + text = b2s(text) + if text.endswith('\n'): + text = text[:-1] if sts is None: sts = 0 - if text.endswith('\n'): - text = text[:-1] return sts, text bz2_regex = re.compile('\.t?bz2?$') @@ -125,59 +139,38 @@ def catcmd(fname): def is_utf8(fname): - (sts, text) = getstatusoutput(catcmd(fname).split() + [fname]) - return not sts and is_utf8_str(text) - -REPLACEMENT_CHAR = unicodedata.lookup('REPLACEMENT CHARACTER') + (sts, output) = getstatusoutput(catcmd(fname).split() + [fname], raw=True) + return not sts and is_utf8_bytestr(output) -def is_utf8_str(s): - if hasattr(s, 'decode'): - # byte string - try: - s.decode('UTF-8') - except: - return False - return True - # unicode string - return REPLACEMENT_CHAR not in s +def is_utf8_bytestr(s): + try: + s.decode('UTF-8') + except: + return False + return True -# TODO: PY3 -def to_utf8(string): +def to_unicode(string): if string is None: - return '' + return unicode('') elif isinstance(string, unicode): return string - try: - x = unicode(string, 'ascii') - return string - except UnicodeError: - encodings = ['utf-8', 'iso-8859-1', 'iso-8859-15', 'iso-8859-2'] - for enc in encodings: - try: - x = unicode(string, enc) - except UnicodeError: - pass - else: - if x.encode(enc) == string: - return x.encode('utf-8') - newstring = '' - for char in string: - if ord(char) > 127: - newstring = newstring + '?' + for enc in ('utf-8', 'iso-8859-1', 'iso-8859-15', 'iso-8859-2'): + try: + x = unicode(string, enc) + except UnicodeError: + pass else: - newstring = newstring + char - return newstring + if x.encode(enc) == string: + return x + return unicode(string, "ascii", errors="replace") def readlines(path): - fobj = open(path, 'rb') - try: + with open(path, 'rb') as fobj: for line in fobj: yield b2s(line) - finally: - fobj.close() def mktemp(): @@ -204,20 +197,13 @@ def get_default_valid_rpmgroups(filename=None): the rpm package (if installed) if no filename is given""" groups = [] if not filename: - try: - p = InstalledPkg('rpm') - except: - pass - else: + with InstalledPkg("rpm") as p: groupsfiles = [x for x in p.files() if x.endswith('/GROUPS')] if groupsfiles: filename = groupsfiles[0] if filename and os.path.exists(filename): - fobj = open(filename) - try: + with open(filename) as fobj: groups = fobj.read().strip().splitlines() - finally: - fobj.close() if 'Development/Debug' not in groups: groups.append('Development/Debug') if 'Unspecified' not in groups: # auto-added by rpm >= 4.6.0 @@ -450,7 +436,19 @@ def parse_deps(line): # classes representing package -class Pkg: +class AbstractPkg: + + def cleanup(self): + pass + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.cleanup() + + +class Pkg(AbstractPkg): _magic_from_compressed_re = re.compile('\([^)]+\s+compressed\s+data\\b') @@ -483,7 +481,7 @@ class Pkg: os.close(fd) self.is_source = not self.header[rpm.RPMTAG_SOURCERPM] - self.name = b2s(self.header[rpm.RPMTAG_NAME]) + self.name = self[rpm.RPMTAG_NAME] if self.isNoSource(): self.arch = 'nosrc' elif self.isSource(): @@ -509,9 +507,14 @@ class Pkg: if val == []: return None else: - if key in (rpm.RPMTAG_VERSION, rpm.RPMTAG_RELEASE, rpm.RPMTAG_ARCH, - rpm.RPMTAG_GROUP, rpm.RPMTAG_BUILDHOST, - rpm.RPMTAG_LICENSE): + # Note that text tags we want to try decoding for real in TagsCheck + # such as summary, description and changelog are not here. + if key in (rpm.RPMTAG_NAME, rpm.RPMTAG_VERSION, rpm.RPMTAG_RELEASE, + rpm.RPMTAG_ARCH, rpm.RPMTAG_GROUP, rpm.RPMTAG_BUILDHOST, + rpm.RPMTAG_LICENSE, rpm.RPMTAG_HEADERI18NTABLE, + rpm.RPMTAG_PACKAGER, rpm.RPMTAG_SOURCERPM) \ + or key in (x[0] for x in SCRIPT_TAGS) \ + or key in (x[1] for x in SCRIPT_TAGS): val = b2s(val) return val @@ -573,7 +576,7 @@ class Pkg: # LANGUAGE trumps other env vars per GNU gettext docs, see also #166 orig = os.environ.get('LANGUAGE') os.environ['LANGUAGE'] = lang - ret = b2s(self[tag]) + ret = self[tag] if orig is not None: os.environ['LANGUAGE'] = orig return ret @@ -666,8 +669,8 @@ class Pkg: self.dirName() or '/', pkgfile.name.lstrip('/'))) pkgfile.flags = flags[idx] pkgfile.mode = modes[idx] - pkgfile.user = users[idx] - pkgfile.group = groups[idx] + pkgfile.user = b2s(users[idx]) + pkgfile.group = b2s(groups[idx]) pkgfile.linkto = links[idx] and safe_normpath(links[idx]) pkgfile.size = sizes[idx] pkgfile.md5 = md5s[idx] @@ -676,7 +679,7 @@ class Pkg: pkgfile.inode = inodes[idx] pkgfile.requires = parse_deps(requires[idx]) pkgfile.provides = parse_deps(provides[idx]) - pkgfile.lang = langs[idx] + pkgfile.lang = b2s(langs[idx]) pkgfile.magic = magics[idx] if not pkgfile.magic and _magic: pkgfile.magic = _magic.file(pkgfile.path) @@ -750,6 +753,30 @@ class Pkg: self._gatherDepInfo() return self._provides + def recommends(self): + """Get package Recommends as list of + (name, flags, (epoch, version, release)) tuples.""" + self._gatherDepInfo() + return self._recommends + + def suggests(self): + """Get package Suggests as list of + (name, flags, (epoch, version, release)) tuples.""" + self._gatherDepInfo() + return self._suggests + + def enhances(self): + """Get package Enhances as list of + (name, flags, (epoch, version, release)) tuples.""" + self._gatherDepInfo() + return self._enhances + + def supplements(self): + """Get package Supplements as list of + (name, flags, (epoch, version, release)) tuples.""" + self._gatherDepInfo() + return self._supplements + # internal function to gather dependency info used by the above ones def _gather_aux(self, header, list, nametag, flagstag, versiontag, prereq=None): @@ -773,6 +800,10 @@ class Pkg: self._provides = [] self._conflicts = [] self._obsoletes = [] + self._recommends = [] + self._suggests = [] + self._enhances = [] + self._supplements = [] self._gather_aux(self.header, self._requires, rpm.RPMTAG_REQUIRENAME, @@ -791,6 +822,26 @@ class Pkg: rpm.RPMTAG_OBSOLETENAME, rpm.RPMTAG_OBSOLETEFLAGS, rpm.RPMTAG_OBSOLETEVERSION) + if hasattr(rpm, "RPMTAG_RECOMMENDNAME"): # rpm >= 4.12 + self._gather_aux(self.header, self._recommends, + rpm.RPMTAG_RECOMMENDNAME, + rpm.RPMTAG_RECOMMENDFLAGS, + rpm.RPMTAG_RECOMMENDVERSION) + if hasattr(rpm, "RPMTAG_SUGGESTNAME"): # rpm >= 4.12 + self._gather_aux(self.header, self._suggests, + rpm.RPMTAG_SUGGESTNAME, + rpm.RPMTAG_SUGGESTFLAGS, + rpm.RPMTAG_SUGGESTVERSION) + if hasattr(rpm, "RPMTAG_ENHANCENAME"): # rpm >= 4.12 + self._gather_aux(self.header, self._enhances, + rpm.RPMTAG_ENHANCENAME, + rpm.RPMTAG_ENHANCEFLAGS, + rpm.RPMTAG_ENHANCEVERSION) + if hasattr(rpm, "RPMTAG_SUPPLEMENTNAME"): # rpm >= 4.12 + self._gather_aux(self.header, self._supplements, + rpm.RPMTAG_SUPPLEMENTNAME, + rpm.RPMTAG_SUPPLEMENTFLAGS, + rpm.RPMTAG_SUPPLEMENTVERSION) def scriptprog(self, which): """Get the specified script interpreter as a string. @@ -798,11 +849,11 @@ class Pkg: interpreter arguments, if any.""" prog = self[which] if prog is None: - prog = b'' + prog = "" elif isinstance(prog, (list, tuple)): # http://rpm.org/ticket/847#comment:2 - prog = b' '.join(prog) - return b2s(prog) + prog = "".join(prog) + return prog def getInstalledPkgs(name): @@ -831,7 +882,7 @@ class InstalledPkg(Pkg): if not mi: raise KeyError(name) try: - hdr = mi.next() + hdr = next(mi) except StopIteration: raise KeyError(name) @@ -851,15 +902,12 @@ class InstalledPkg(Pkg): # Class to provide an API to a "fake" package, eg. for specfile-only checks -class FakePkg: +class FakePkg(AbstractPkg): def __init__(self, name): self.name = name self.arch = None self.current_linenum = None - def cleanup(self): - pass - # Class for files in packages class PkgFile(object): @@ -895,13 +943,12 @@ class PkgFile(object): if __name__ == '__main__': for p in sys.argv[1:]: - pkg = Pkg(sys.argv[1], tempfile.gettempdir()) - print ('Requires: %s' % pkg.requires()) - print ('Prereq: %s' % pkg.prereq()) - print ('Conflicts: %s' % pkg.conflicts()) - print ('Provides: %s' % pkg.provides()) - print ('Obsoletes: %s' % pkg.obsoletes()) - pkg.cleanup() + with Pkg(p, tempfile.gettempdir()) as pkg: + print('Requires: %s' % pkg.requires()) + print('Prereq: %s' % pkg.prereq()) + print('Conflicts: %s' % pkg.conflicts()) + print('Provides: %s' % pkg.provides()) + print('Obsoletes: %s' % pkg.obsoletes()) # Pkg.py ends here diff --git a/PostCheck.py b/PostCheck.py index a87964a..71337fa 100644 --- a/PostCheck.py +++ b/PostCheck.py @@ -61,17 +61,6 @@ for p in prereq_assoc: # pychecker fix del p -script_tags = [ - (rpm.RPMTAG_PREIN, rpm.RPMTAG_PREINPROG, '%pre'), - (rpm.RPMTAG_POSTIN, rpm.RPMTAG_POSTINPROG, '%post'), - (rpm.RPMTAG_PREUN, rpm.RPMTAG_PREUNPROG, '%preun'), - (rpm.RPMTAG_POSTUN, rpm.RPMTAG_POSTUNPROG, '%postun'), - (rpm.RPMTAG_TRIGGERSCRIPTS, rpm.RPMTAG_TRIGGERSCRIPTPROG, '%trigger'), - (rpm.RPMTAG_PRETRANS, rpm.RPMTAG_PRETRANSPROG, '%pretrans'), - (rpm.RPMTAG_POSTTRANS, rpm.RPMTAG_POSTTRANSPROG, '%posttrans'), - (rpm.RPMTAG_VERIFYSCRIPT, rpm.RPMTAG_VERIFYSCRIPTPROG, '%verifyscript'), - ] - def incorrect_shell_script(prog, shellscript): return check_syntax_script(prog, '-n', shellscript) @@ -105,7 +94,7 @@ class PostCheck(AbstractCheck.AbstractCheck): prereq = [x[0] for x in pkg.prereq()] files = pkg.files() - for tag in script_tags: + for tag in Pkg.SCRIPT_TAGS: script = pkg[tag[0]] if not isinstance(script, list): @@ -123,15 +112,15 @@ class PostCheck(AbstractCheck.AbstractCheck): if ghost_files: postin = pkg[rpm.RPMTAG_POSTIN] prein = pkg[rpm.RPMTAG_PREIN] - if not postin and not prein: - printWarning(pkg, 'ghost-files-without-postin') - else: - for f in ghost_files: - if (not postin or f not in postin) and \ - (not prein or f not in prein) and \ - f not in pkg.missingOkFiles(): - printWarning(pkg, - 'postin-without-ghost-file-creation', f) + for f in ghost_files: + if f in pkg.missingOkFiles(): + continue + if not postin and not prein: + printWarning(pkg, 'ghost-files-without-postin') + if (not postin or f not in postin) and \ + (not prein or f not in prein): + printWarning(pkg, + 'postin-without-ghost-file-creation', f) def check_aux(self, pkg, files, prog, script, tag, prereq): if script: diff --git a/SCLCheck.py b/SCLCheck.py index a9f099d..d0f783c 100644 --- a/SCLCheck.py +++ b/SCLCheck.py @@ -67,7 +67,7 @@ class SCLCheck(AbstractCheck.AbstractCheck): self._spec_file = pkgfile.path self.check_spec(pkg, self._spec_file) - def check_spec(self, pkg, spec_file, spec_lines=[]): + def check_spec(self, pkg, spec_file): '''SCL spec file checks''' spec = '\n'.join(Pkg.readlines(spec_file)) if global_scl_definition.search(spec): diff --git a/SourceCheck.py b/SourceCheck.py index 83c5d17..fcf796c 100644 --- a/SourceCheck.py +++ b/SourceCheck.py @@ -41,7 +41,7 @@ class SourceCheck(AbstractCheck.AbstractCheck): compress_ext, fname) perm = pkgfile.mode & int("7777", 8) if perm not in valid_src_perms: - printWarning(pkg, 'strange-permission', fname, oct(perm)) + printWarning(pkg, 'strange-permission', fname, "%o" % perm) check = SourceCheck() diff --git a/SpecCheck.py b/SpecCheck.py index 2b24b43..b69bead 100644 --- a/SpecCheck.py +++ b/SpecCheck.py @@ -8,6 +8,7 @@ ############################################################################# import re +import sys import unicodedata try: from urlparse import urlparse @@ -96,6 +97,7 @@ conflicts_regex = re.compile('^(?:Build)?Conflicts:\s*(.*)', re.IGNORECASE) compop_regex = re.compile('[<>=]') +setup_regex = re.compile(r'%setup\b') # intentionally no whitespace before! setup_q_regex = re.compile(' -[A-Za-z]*q') setup_t_regex = re.compile(' -[A-Za-z]*T') setup_ab_regex = re.compile(' -[A-Za-z]*[ab]') @@ -154,11 +156,9 @@ class SpecCheck(AbstractCheck.AbstractCheck): # check content of spec file self.check_spec(pkg, self._spec_file) - def check_spec(self, pkg, spec_file, spec_lines=[]): + def check_spec(self, pkg, spec_file): self._spec_file = spec_file spec_only = isinstance(pkg, Pkg.FakePkg) - if not spec_lines: - spec_lines = Pkg.readlines(spec_file) patches = {} applied_patches = [] applied_patches_ifarch = [] @@ -198,12 +198,13 @@ class SpecCheck(AbstractCheck.AbstractCheck): nbsp = chr(0xA0) if is_utf8: nbsp = UNICODE_NBSP + do_unicode = is_utf8 and sys.version_info[0] <= 2 - for line in spec_lines: + for line in Pkg.readlines(spec_file): pkg.current_linenum += 1 - if is_utf8: + if do_unicode: line = unicode(line, "utf-8", "replace") char = line.find(nbsp) @@ -259,7 +260,7 @@ class SpecCheck(AbstractCheck.AbstractCheck): if if_regex.search(line): if_depth = if_depth + 1 - if line.startswith('%setup'): + if setup_regex.match(line): if not setup_q_regex.search(line): # Don't warn if there's a -T without -a or -b if setup_t_regex.search(line): diff --git a/TagsCheck.py b/TagsCheck.py index fa38a07..b08b0d5 100644 --- a/TagsCheck.py +++ b/TagsCheck.py @@ -466,9 +466,10 @@ def spell_check(pkg, str, fmt, lang, ignored): if checker: # squeeze whitespace to ease leading context check checker.set_text(re.sub(r'\s+', ' ', str)) - uppername = pkg.name.upper() if use_utf8: - uppername = Pkg.to_utf8(uppername).decode('utf-8') + uppername = Pkg.to_unicode(pkg.header[rpm.RPMTAG_NAME]).upper() + else: + uppername = pkg.name.upper() upperparts = uppername.split('-') if lang.startswith('en'): ups = [x + "'S" for x in upperparts] @@ -538,16 +539,18 @@ class TagsCheck(AbstractCheck.AbstractCheck): def _unexpanded_macros(self, pkg, tagname, value, is_url=False): if not value: return - # str(value) because value might be a list - for match in AbstractCheck.macro_regex.findall(str(value)): - # Do not warn about %XX URL escapes - if is_url and re.match('^%[0-9A-F][0-9A-F]$', match, re.I): - continue - printWarning(pkg, 'unexpanded-macro', tagname, match) + if not isinstance(value, (list, tuple)): + value = [value] + for val in value: + for match in AbstractCheck.macro_regex.findall(val): + # Do not warn about %XX URL escapes + if is_url and re.match('^%[0-9A-F][0-9A-F]$', match, re.I): + continue + printWarning(pkg, 'unexpanded-macro', tagname, match) def check(self, pkg): - packager = Pkg.b2s(pkg[rpm.RPMTAG_PACKAGER]) + packager = pkg[rpm.RPMTAG_PACKAGER] if packager: self._unexpanded_macros(pkg, 'Packager', packager) if Config.getOption('Packager') and \ @@ -684,23 +687,22 @@ class TagsCheck(AbstractCheck.AbstractCheck): ignored_words.update((x[0] for x in pkg.obsoletes())) langs = pkg[rpm.RPMTAG_HEADERI18NTABLE] - if langs: - langs = [Pkg.b2s(x) for x in langs] - summary = Pkg.b2s(pkg[rpm.RPMTAG_SUMMARY]) + summary = pkg[rpm.RPMTAG_SUMMARY] if summary: if not langs: - self._unexpanded_macros(pkg, 'Summary', summary) + self._unexpanded_macros(pkg, 'Summary', Pkg.b2s(summary)) else: for lang in langs: self.check_summary(pkg, lang, ignored_words) else: printError(pkg, 'no-summary-tag') - description = Pkg.b2s(pkg[rpm.RPMTAG_DESCRIPTION]) + description = pkg[rpm.RPMTAG_DESCRIPTION] if description: if not langs: - self._unexpanded_macros(pkg, '%description', description) + self._unexpanded_macros(pkg, '%description', + Pkg.b2s(description)) else: for lang in langs: self.check_description(pkg, lang, ignored_words) @@ -726,14 +728,13 @@ class TagsCheck(AbstractCheck.AbstractCheck): if not changelog: printError(pkg, 'no-changelogname-tag') else: - changelog = [Pkg.b2s(x) for x in changelog] - clt = [Pkg.b2s(x) for x in pkg[rpm.RPMTAG_CHANGELOGTEXT]] + clt = pkg[rpm.RPMTAG_CHANGELOGTEXT] if use_version_in_changelog: - ret = changelog_version_regex.search(changelog[0]) + ret = changelog_version_regex.search(Pkg.b2s(changelog[0])) if not ret and clt: # we also allow the version specified as the first # thing on the first line of the text - ret = changelog_text_version_regex.search(clt[0]) + ret = changelog_text_version_regex.search(Pkg.b2s(clt[0])) if not ret: printWarning(pkg, 'no-version-in-last-changelog') elif version and release: @@ -754,10 +755,13 @@ class TagsCheck(AbstractCheck.AbstractCheck): printWarning(pkg, 'incoherent-version-in-changelog', ret.group(1), expected) - if clt: - changelog = changelog + clt - if use_utf8 and not Pkg.is_utf8_str(' '.join(changelog)): - printError(pkg, 'tag-not-utf8', '%changelog') + if use_utf8: + if clt: + changelog = changelog + clt + for s in changelog: + if not Pkg.is_utf8_bytestr(s): + printError(pkg, 'tag-not-utf8', '%changelog') + break clt = pkg[rpm.RPMTAG_CHANGELOGTIME][0] if clt: @@ -873,12 +877,16 @@ class TagsCheck(AbstractCheck.AbstractCheck): def check_description(self, pkg, lang, ignored_words): description = pkg.langtag(rpm.RPMTAG_DESCRIPTION, lang) - self._unexpanded_macros(pkg, '%%description -l %s' % lang, description) - utf8desc = description if use_utf8: - utf8desc = Pkg.to_utf8(description).decode('utf-8') - spell_check(pkg, utf8desc, '%%description -l %s', lang, ignored_words) - for l in utf8desc.splitlines(): + if not Pkg.is_utf8_bytestr(description): + printError(pkg, 'tag-not-utf8', '%description', lang) + description = Pkg.to_unicode(description) + else: + description = Pkg.b2s(description) + self._unexpanded_macros(pkg, '%%description -l %s' % lang, description) + spell_check(pkg, description, '%%description -l %s', lang, + ignored_words) + for l in description.splitlines(): if len(l) > max_line_len: printError(pkg, 'description-line-too-long', lang, l) res = forbidden_words_regex.search(l) @@ -888,23 +896,24 @@ class TagsCheck(AbstractCheck.AbstractCheck): res = tag_regex.search(l) if res: printWarning(pkg, 'tag-in-description', lang, res.group(1)) - if use_utf8 and not Pkg.is_utf8_str(description): - printError(pkg, 'tag-not-utf8', '%description', lang) def check_summary(self, pkg, lang, ignored_words): summary = pkg.langtag(rpm.RPMTAG_SUMMARY, lang) - self._unexpanded_macros(pkg, 'Summary(%s)' % lang, summary) - utf8summary = summary if use_utf8: - utf8summary = Pkg.to_utf8(summary).decode('utf-8') - spell_check(pkg, utf8summary, 'Summary(%s)', lang, ignored_words) + if not Pkg.is_utf8_bytestr(summary): + printError(pkg, 'tag-not-utf8', 'Summary', lang) + summary = Pkg.to_unicode(summary) + else: + summary = Pkg.b2s(summary) + self._unexpanded_macros(pkg, 'Summary(%s)' % lang, summary) + spell_check(pkg, summary, 'Summary(%s)', lang, ignored_words) if '\n' in summary: printError(pkg, 'summary-on-multiple-lines', lang) if summary[0] != summary[0].upper(): printWarning(pkg, 'summary-not-capitalized', lang, summary) if summary[-1] == '.': printWarning(pkg, 'summary-ended-with-dot', lang, summary) - if len(utf8summary) > max_line_len: + if len(summary) > max_line_len: printError(pkg, 'summary-too-long', lang, summary) if leading_space_regex.search(summary): printError(pkg, 'summary-has-leading-spaces', lang, summary) @@ -919,8 +928,6 @@ class TagsCheck(AbstractCheck.AbstractCheck): if res: printWarning(pkg, 'name-repeated-in-summary', lang, res.group(1)) - if use_utf8 and not Pkg.is_utf8_str(summary): - printError(pkg, 'tag-not-utf8', 'Summary', lang) # Create an object to enable the auto registration of the test diff --git a/ZipCheck.py b/ZipCheck.py index 097fc45..8a7b975 100644 --- a/ZipCheck.py +++ b/ZipCheck.py @@ -16,6 +16,7 @@ import zipfile from Filter import addDetails, printError, printWarning import AbstractCheck import Config +import Pkg zip_regex = re.compile('\.(zip|[ewj]ar)$') @@ -53,7 +54,7 @@ class ZipCheck(AbstractCheck.AbstractCheck): # additional jar checks if jar_regex.search(fname): try: - mf = z.read('META-INF/MANIFEST.MF') + mf = Pkg.b2s(z.read('META-INF/MANIFEST.MF')) if classpath_regex.search(mf): printWarning(pkg, 'class-path-in-manifest', fname) diff --git a/config b/config index f66f7a3..f1319a3 100644 --- a/config +++ b/config @@ -212,6 +212,10 @@ from Config import * # Type: string, default: 'mac' #SetOption("ManWarningCategory", 'mac') +# Command and arguments to validate appdata files. +# Type: tuple of strings, default: see DEFAULT_APPDATA_CHECKER in AppDataCheck +#setOption("AppDataChecker", ('appstream-util', 'validate-relax')) + # Output filters. # --------------- diff --git a/rpmlint b/rpmlint index aa37c3a..acbda29 100755 --- a/rpmlint +++ b/rpmlint @@ -108,8 +108,8 @@ def main(): stdin = sys.stdin.readlines() if not stdin: continue - pkg = Pkg.FakePkg(arg) - runSpecChecks(pkg, arg) + with Pkg.FakePkg(arg) as pkg: + runSpecChecks(pkg, arg) specfiles_checked += 1 continue @@ -119,8 +119,8 @@ def main(): if stat.S_ISREG(st[stat.ST_MODE]): if arg.endswith(".spec"): # Short-circuit spec file checks - pkg = Pkg.FakePkg(arg) - runSpecChecks(pkg, arg) + with Pkg.FakePkg(arg) as pkg: + runSpecChecks(pkg, arg) specfiles_checked += 1 elif "/" in arg or arg.endswith(".rpm") or \ arg.endswith(".spm"): @@ -157,7 +157,8 @@ def main(): continue for pkg in pkgs: - runChecks(pkg) + with pkg: + runChecks(pkg) packages_checked += 1 for dname in dirs: @@ -168,13 +169,13 @@ def main(): try: if fname.endswith('.rpm') or \ fname.endswith('.spm'): - pkg = Pkg.Pkg(fname, extract_dir) - runChecks(pkg) + with Pkg.Pkg(fname, extract_dir) as pkg: + runChecks(pkg) packages_checked += 1 elif fname.endswith('.spec'): - pkg = Pkg.FakePkg(fname) - runSpecChecks(pkg, fname) + with Pkg.FakePkg(fname) as pkg: + runSpecChecks(pkg, fname) specfiles_checked += 1 except KeyboardInterrupt: @@ -209,36 +210,30 @@ def main(): 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() + 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) def runSpecChecks(pkg, fname): - 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_spec(pkg, fname) - else: - Pkg.warn('(none): W: unknown check %s, skipping' % name) - finally: - pkg.cleanup() + if verbose: + printInfo(pkg, 'checking') + + for name in Config.allChecks(): + check = AbstractCheck.AbstractCheck.known_checks.get(name) + if check: + check.verbose = verbose + check.check_spec(pkg, fname) + else: + Pkg.warn('(none): W: unknown check %s, skipping' % name) ############################################################################# # diff --git a/test.sh b/test.sh index 1e071c5..1e18b97 100755 --- a/test.sh +++ b/test.sh @@ -2,6 +2,7 @@ export PYTHONPATH=$(pwd)/tools:$(pwd) export TESTPATH="$(pwd)/test/" +: ${PYTHON:=python} ${PYTEST:=py.test} echo echo "Please ignore the possibly occurring output like this:" @@ -9,7 +10,7 @@ echo " .../Patch*.patch: No such file or directory" echo for i in $TESTPATH/test.*.py; do - python $i + $PYTHON $i RET=$? if [ $RET -ne 0 ]; then exit $RET @@ -17,9 +18,9 @@ for i in $TESTPATH/test.*.py; do done echo "Check that rpmlint executes with no unexpected errors" -python ./rpmlint -C $(pwd) test/*/*.rpm test/spec/*.spec >/dev/null +$PYTHON ./rpmlint -C $(pwd) test/*/*.rpm test/spec/*.spec >/dev/null rc=$? test $rc -eq 0 -o $rc -eq 64 # SCLCheck tests -py.test -v +$PYTEST -v -- 2.7.4