From 7e1975e3a3d627e316b99a87580808499d9cb9c3 Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Wed, 6 Apr 2016 11:29:40 +0200 Subject: [PATCH] Handle SPDX style license exceptions --- TagsCheck.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) Index: rpmlint-1.5/TagsCheck.py =================================================================== --- rpmlint-1.5.orig/TagsCheck.py +++ rpmlint-1.5/TagsCheck.py @@ -139,6 +139,34 @@ DEFAULT_VALID_LICENSES = ( 'Shareware', ) +DEFAULT_VALID_LICENSE_EXCEPTIONS = ( + '389-exception', + 'Autoconf-exception-2.0', + 'Autoconf-exception-3.0', + 'Bison-exception-2.2', + 'CLISP-exception-2.0', + 'Classpath-exception-2.0', + 'DigiRule-FOSS-exception', + 'FLTK-exception', + 'Fawkes-Runtime-exception', + 'Font-exception-2.0', + 'GCC-exception-2.0', + 'GCC-exception-3.1', + 'LZMA-exception', + 'Libtool-exception', + 'Nokia-Qt-exception-1.1', + 'OCCT-exception-1.0', + 'Qwt-exception-1.0', + 'WxWindows-exception-3.1', + 'eCos-exception-2.0', + 'freertos-exception-2.0', + 'gnu-javamail-exception', + 'i2p-gpl-java-exception', + 'mif-exception', + 'openvpn-openssl-exception', + 'u-boot-exception-2.0', +) + BAD_WORDS = { 'alot': 'a lot', 'accesnt': 'accent', @@ -403,6 +431,7 @@ VALID_GROUPS = Config.getOption('ValidGr if VALID_GROUPS is None: # get defaults from rpm package only if it's not set VALID_GROUPS = Pkg.get_default_valid_rpmgroups() VALID_LICENSES = Config.getOption('ValidLicenses', DEFAULT_VALID_LICENSES) +VALID_LICENSE_EXCEPTIONS = Config.getOption('ValidLicenseExceptions', DEFAULT_VALID_LICENSE_EXCEPTIONS) INVALID_REQUIRES = map(re.compile, Config.getOption('InvalidRequires', DEFAULT_INVALID_REQUIRES)) packager_regex = re.compile(Config.getOption('Packager')) changelog_version_regex = re.compile('[^>]([^ >]+)\s*$') @@ -416,6 +445,7 @@ invalid_url_regex = re.compile(Config.ge lib_package_regex = re.compile('(?:^(?:compat-)?lib.*?(\.so.*)?|libs?[\d-]*)$', re.IGNORECASE) leading_space_regex = re.compile('^\s+') license_regex = re.compile('\(([^)]+)\)|\s(?:and|or)\s') +license_exception_regex = re.compile('(\S+)\sWITH\s(\S+)') invalid_version_regex = re.compile('([0-9](?:rc|alpha|beta|pre).*)', re.IGNORECASE) # () are here for grouping purpose in the regexp forbidden_words_regex = re.compile('(' + Config.getOption('ForbiddenWords') + ')', re.IGNORECASE) @@ -761,6 +791,10 @@ class TagsCheck(AbstractCheck.AbstractCh # printWarning(pkg, 'package-provides-itself') # break + def split_license_exception(license): + x, y = license_exception_regex.split(license)[1:3] + return x.strip(), y.strip() + def split_license(license): return (x.strip() for x in (l for l in license_regex.split(license) if l)) @@ -769,16 +803,26 @@ class TagsCheck(AbstractCheck.AbstractCh if not rpm_license: printError(pkg, 'no-license') else: - valid_license = True + invalid_license_part = None if rpm_license not in VALID_LICENSES: - for l1 in split_license(rpm_license): + license_string = rpm_license + + l1, lexception = split_license_exception(rpm_license) + # SPDX allows " WITH " + if lexception: + license_string = l1 + if lexception not in VALID_LICENSE_EXCEPTIONS: + printWarning(pkg, 'invalid-license-exception', lexception) + invalid_license_part = rpm_license + + for l1 in split_license(license_string): if l1 in VALID_LICENSES: continue for l2 in split_license(l1): if l2 not in VALID_LICENSES: - printWarning(pkg, 'invalid-license', l2) - valid_license = False - if not valid_license: + invalid_license_part = l2 + if invalid_license_part: + printWarning(pkg, 'invalid-license', invalid_license_part) self._unexpanded_macros(pkg, 'License', rpm_license) for tag in ('URL', 'BugURL'): @@ -1044,6 +1088,11 @@ your specfile.''', '''The value of the License tag was not recognized. Known values are: "%s".''' % '", "'.join(VALID_LICENSES), +'invalid-license-exception', +'''The ' WITH ' license exception of the License tag was not recognized. +Known values are: +"%s".''' % '", "'.join(VALID_LICENSE_EXCEPTIONS), + 'obsolete-not-provided', '''If a package is obsoleted by a compatible replacement, the obsoleted package should also be provided in order to not cause unnecessary dependency breakage.