2000-10-11 14:03:08 +08:00
|
|
|
#############################################################################
|
2005-11-28 05:49:15 +08:00
|
|
|
# File : SpecCheck.py
|
|
|
|
# Package : rpmlint
|
|
|
|
# Author : Frederic Lepied
|
|
|
|
# Created on : Thu Oct 7 17:06:14 1999
|
|
|
|
# Version : $Id$
|
|
|
|
# Purpose : check the spec file of a source rpm.
|
2000-10-11 14:03:08 +08:00
|
|
|
#############################################################################
|
|
|
|
|
|
|
|
from Filter import *
|
|
|
|
import AbstractCheck
|
2007-05-14 04:27:30 +08:00
|
|
|
import Pkg
|
2000-10-11 14:03:08 +08:00
|
|
|
import re
|
|
|
|
import sys
|
2002-06-01 21:17:28 +08:00
|
|
|
import string
|
2003-05-08 16:03:35 +08:00
|
|
|
import Config
|
|
|
|
|
|
|
|
# Don't check for hardcoded library paths in biarch packages
|
2006-05-12 21:53:43 +08:00
|
|
|
DEFAULT_BIARCH_PACKAGES = '^(gcc|glibc)'
|
2003-05-08 16:03:35 +08:00
|
|
|
|
|
|
|
# Don't check for hardcoded library paths in packages which can have
|
|
|
|
# their noarch files in /usr/lib/<package>/*, or packages that can't
|
|
|
|
# be installed on biarch systems
|
2007-03-11 07:05:21 +08:00
|
|
|
DEFAULT_HARDCODED_LIB_PATH_EXCEPTIONS = '/lib/(modules|cpp|perl5|rpm|hotplug|firmware)($|[\s/,])'
|
2006-05-12 21:53:43 +08:00
|
|
|
|
2007-05-13 03:52:58 +08:00
|
|
|
patch_regex = re.compile("^Patch(\d*)\s*:\s*([^\s]+)", re.IGNORECASE)
|
|
|
|
# TODO: http://rpmlint.zarb.org/cgi-bin/trac.cgi/ticket/59
|
|
|
|
applied_patch_regex = re.compile("^%patch.*-P\s+(\d+)|^%patch(\d*)\s")
|
2006-05-12 21:53:43 +08:00
|
|
|
source_dir_regex = re.compile("^[^#]*(\$RPM_SOURCE_DIR|%{?_sourcedir}?)")
|
|
|
|
obsolete_tags_regex = re.compile("^(Copyright|Serial)\s*:\s*([^\s]+)")
|
|
|
|
buildroot_regex = re.compile('Buildroot\s*:\s*([^\s]+)', re.IGNORECASE)
|
|
|
|
prefix_regex = re.compile('^Prefix\s*:\s*([^\s]+)', re.IGNORECASE)
|
|
|
|
packager_regex = re.compile('^Packager\s*:\s*([^\s]+)', re.IGNORECASE)
|
2008-03-25 04:45:35 +08:00
|
|
|
noarch_regex = re.compile('^BuildArch(?:itectures)?\s*:\s*\\bnoarch\\b', re.IGNORECASE)
|
2006-07-13 04:33:22 +08:00
|
|
|
make_check_regexp = re.compile('(^|\s|%{?__)make}?\s+(check|test)')
|
2006-05-13 17:49:35 +08:00
|
|
|
rm_regex = re.compile('(^|\s)((.*/)?rm|%{?__rm}?) ')
|
2006-09-09 18:57:13 +08:00
|
|
|
rpm_buildroot_regex = re.compile('(\\\*)\${?RPM_BUILD_ROOT}?|(%+){?buildroot}?')
|
2006-05-12 21:53:43 +08:00
|
|
|
configure_start_regex = re.compile('\./configure')
|
|
|
|
configure_libdir_spec_regex = re.compile('ln |\./configure[^#]*--libdir=([^\s]+)[^#]*')
|
|
|
|
lib_package_regex = re.compile('^%package.*\Wlib')
|
|
|
|
mklibname_regex = re.compile('%mklibname')
|
2008-04-30 02:48:27 +08:00
|
|
|
ifarch_regex = re.compile('%ifn?arch\s+')
|
2006-05-12 21:53:43 +08:00
|
|
|
if_regex = re.compile('%if\s+')
|
2008-04-30 02:48:27 +08:00
|
|
|
endif_regex = re.compile('%endif\\b')
|
2006-05-12 21:53:43 +08:00
|
|
|
biarch_package_regex = re.compile(DEFAULT_BIARCH_PACKAGES)
|
|
|
|
hardcoded_lib_path_exceptions_regex = re.compile(Config.getOption('HardcodedLibPathExceptions', DEFAULT_HARDCODED_LIB_PATH_EXCEPTIONS))
|
2006-12-04 06:43:16 +08:00
|
|
|
prereq_regex = re.compile('^PreReq(\(.*\))?:\s*(.+?)\s*$', re.IGNORECASE)
|
2006-05-12 21:53:43 +08:00
|
|
|
buildprereq_regex = re.compile('^BuildPreReq:\s*(.+?)\s*$', re.IGNORECASE)
|
|
|
|
use_utf8 = Config.getOption('UseUTF8', Config.USEUTF8_DEFAULT)
|
2006-06-06 02:57:33 +08:00
|
|
|
macro_regex = re.compile('(%+)[{(]?(\w+)')
|
2008-03-25 04:45:35 +08:00
|
|
|
libdir_regex = re.compile('%{?_lib(?:dir)?\}?\\b')
|
2008-04-30 02:45:03 +08:00
|
|
|
comment_or_empty_regex = re.compile('^\s*(#|$)')
|
|
|
|
defattr_regex = re.compile('^\s*%defattr\\b')
|
|
|
|
attr_regex = re.compile('^\s*%attr\\b')
|
2003-05-08 16:03:35 +08:00
|
|
|
|
2002-06-01 21:17:28 +08:00
|
|
|
# Only check for /lib, /usr/lib, /usr/X11R6/lib
|
|
|
|
# TODO: better handling of X libraries and modules.
|
2006-05-12 21:53:43 +08:00
|
|
|
hardcoded_library_paths = '(/lib|/usr/lib|/usr/X11R6/lib/(?!([^/]+/)+)[^/]*\\.([oa]|la|so[0-9.]*))'
|
|
|
|
hardcoded_library_path_regex = re.compile('^[^#]*((^|\s+|\.\./\.\.|\${?RPM_BUILD_ROOT}?|%{?buildroot}?|%{?_prefix}?)' + hardcoded_library_paths + '(?=[\s;/])([^\s,;]*))')
|
2000-10-11 14:03:08 +08:00
|
|
|
|
2006-12-04 06:43:16 +08:00
|
|
|
# Requires(pre,post) is broken in some rpm versions, see
|
|
|
|
# https://bugzilla.redhat.com/118780 and bugs linked to that one.
|
|
|
|
scriptlet_requires_regex = re.compile('^(PreReq|Requires)\([^\)]*,', re.IGNORECASE)
|
2006-02-02 23:16:30 +08:00
|
|
|
|
2006-06-16 04:44:26 +08:00
|
|
|
depscript_override_regex = re.compile('(^|\s)%(define|global)\s+__find_(requires|provides)\s')
|
|
|
|
depgen_disable_regex = re.compile('(^|\s)%(define|global)\s+_use_internal_dependency_generator\s+0')
|
|
|
|
|
2006-06-23 00:04:13 +08:00
|
|
|
indent_spaces_regex = re.compile(' {3}.*\S')
|
|
|
|
indent_tabs_regex = re.compile('\t.*\S')
|
|
|
|
|
2006-09-04 02:32:13 +08:00
|
|
|
provides_regex = re.compile('^Provides(?:\([^\)]+\))?:\s*(.*)', re.IGNORECASE)
|
|
|
|
obsoletes_regex = re.compile('^Obsoletes:\s*(.*)', re.IGNORECASE)
|
|
|
|
|
2007-02-06 05:26:31 +08:00
|
|
|
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]')
|
|
|
|
|
2006-09-04 02:32:13 +08:00
|
|
|
def deptokens(line):
|
|
|
|
'''Parse provides/requires/conflicts/obsoletes line to dep token list.'''
|
|
|
|
prco = []
|
|
|
|
tmp = ''
|
|
|
|
wantmore = 0
|
2008-07-31 00:49:48 +08:00
|
|
|
toks = re.split('[\s,]+', line.strip())
|
|
|
|
|
|
|
|
# Drop line continuation backslash in multiline macro definition, eg.
|
|
|
|
# [...] \
|
|
|
|
# Obsoletes: foo-%1 <= 1.0.0 \
|
|
|
|
# [...] \
|
|
|
|
# (yes, this is an ugly hack and we probably have other problems with
|
|
|
|
# multiline macro definitions elsewhere...)
|
|
|
|
if toks[-1] == '\\':
|
|
|
|
del toks[-1]
|
|
|
|
|
|
|
|
for tok in toks:
|
2007-06-01 04:06:59 +08:00
|
|
|
if len(tok) == 0:
|
|
|
|
continue
|
2006-09-04 02:32:13 +08:00
|
|
|
if len(tmp) == 0:
|
|
|
|
tmp = tok
|
|
|
|
elif wantmore:
|
|
|
|
tmp += ' ' + tok
|
|
|
|
wantmore = 0
|
|
|
|
elif tok[0] in ('=', '<', '>'):
|
|
|
|
tmp += ' ' + tok
|
|
|
|
wantmore = 1
|
|
|
|
else:
|
|
|
|
prco.append(tmp)
|
|
|
|
wantmore = 0
|
|
|
|
tmp = tok
|
|
|
|
if len(tmp) != 0:
|
|
|
|
prco.append(tmp)
|
|
|
|
return prco
|
|
|
|
|
|
|
|
def versioned(toks):
|
|
|
|
'''Return versioned dependency tokens from the given list.'''
|
|
|
|
res = []
|
|
|
|
for tok in toks:
|
|
|
|
if tok.find('=') > 0 or tok.find('<') > 0 or tok.find('>') > 0:
|
|
|
|
res.append(tok)
|
|
|
|
return res
|
|
|
|
|
|
|
|
def unversioned(toks):
|
|
|
|
'''Return unversioned dependency tokens from the given list.'''
|
|
|
|
res = []
|
|
|
|
for tok in toks:
|
|
|
|
if tok.find(' ') < 0:
|
|
|
|
res.append(tok)
|
|
|
|
return res
|
|
|
|
|
2006-09-09 18:57:13 +08:00
|
|
|
def contains_buildroot(line):
|
|
|
|
'''Check if the given line contains use of rpm buildroot.'''
|
|
|
|
res = rpm_buildroot_regex.search(line)
|
|
|
|
if res and \
|
|
|
|
(not res.group(1) or len(res.group(1)) % 2 == 0) and \
|
|
|
|
(not res.group(2) or len(res.group(2)) % 2 != 0):
|
|
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
2000-10-11 14:03:08 +08:00
|
|
|
class SpecCheck(AbstractCheck.AbstractCheck):
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-10-11 14:03:08 +08:00
|
|
|
def __init__(self):
|
2005-11-28 05:49:15 +08:00
|
|
|
AbstractCheck.AbstractCheck.__init__(self, "SpecCheck")
|
2007-05-15 06:02:01 +08:00
|
|
|
self._spec_file = None
|
2000-10-11 14:03:08 +08:00
|
|
|
|
2001-11-15 00:34:02 +08:00
|
|
|
def check(self, pkg):
|
2000-10-11 14:03:08 +08:00
|
|
|
if not pkg.isSource():
|
|
|
|
return
|
|
|
|
|
2008-02-27 01:24:44 +08:00
|
|
|
wrong_spec = False
|
2000-10-11 14:03:08 +08:00
|
|
|
# lookup spec file
|
2006-05-12 21:53:43 +08:00
|
|
|
files = pkg.files()
|
2005-11-28 05:49:15 +08:00
|
|
|
for f in files.keys():
|
2006-07-07 00:21:39 +08:00
|
|
|
if f.endswith('.spec'):
|
2008-08-22 03:41:01 +08:00
|
|
|
self._spec_file = pkg.dirName() + "/" + f
|
2008-02-27 01:24:44 +08:00
|
|
|
if f == pkg.name + ".spec":
|
|
|
|
wrong_spec = False
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
wrong_spec = True
|
2007-05-15 06:02:01 +08:00
|
|
|
if not self._spec_file:
|
2000-10-11 14:03:08 +08:00
|
|
|
printError(pkg, "no-spec-file")
|
|
|
|
else:
|
2008-02-27 01:24:44 +08:00
|
|
|
if wrong_spec:
|
|
|
|
printError(pkg, "invalid-spec-name")
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2000-10-11 14:03:08 +08:00
|
|
|
# check content of spec file
|
2008-07-31 00:36:13 +08:00
|
|
|
self.check_spec(pkg, self._spec_file)
|
2007-05-15 06:02:01 +08:00
|
|
|
|
2008-07-31 00:36:13 +08:00
|
|
|
def check_spec(self, pkg, spec_file):
|
|
|
|
self._spec_file = spec_file
|
|
|
|
spec_lines = Pkg.readlines(spec_file)
|
2007-05-15 06:02:01 +08:00
|
|
|
patches = {}
|
|
|
|
applied_patches = []
|
|
|
|
applied_patches_ifarch = []
|
|
|
|
source_dir = None
|
|
|
|
buildroot = 0
|
2008-03-25 04:45:35 +08:00
|
|
|
noarch = 0
|
2007-05-15 06:02:01 +08:00
|
|
|
configure = 0
|
|
|
|
configure_cmdline = ""
|
|
|
|
mklibname = 0
|
|
|
|
lib = 0
|
|
|
|
if_depth = 0
|
|
|
|
ifarch_depth = -1
|
|
|
|
current_section = 'package'
|
|
|
|
buildroot_clean={'clean':0 , 'install':0}
|
|
|
|
depscript_override = 0
|
|
|
|
depgen_disabled = 0
|
|
|
|
indent_spaces = 0
|
|
|
|
indent_tabs = 0
|
2008-04-30 02:45:03 +08:00
|
|
|
files_has_defattr = 0
|
2007-05-15 06:02:01 +08:00
|
|
|
section = {}
|
|
|
|
for sec in ['description', 'prep', 'build', 'install', 'clean',
|
|
|
|
'files', 'changelog', 'package', 'check']:
|
|
|
|
section[sec] = {
|
|
|
|
'count': 0,
|
|
|
|
're': re.compile('^%' + sec + '(?:\s|$)'),
|
|
|
|
}
|
|
|
|
|
2008-07-31 00:42:38 +08:00
|
|
|
is_utf8 = 0
|
|
|
|
if self._spec_file and use_utf8:
|
|
|
|
if Pkg.is_utf8(self._spec_file):
|
|
|
|
is_utf8 = 1
|
|
|
|
else:
|
2007-05-15 06:02:01 +08:00
|
|
|
printError(pkg, "non-utf8-spec-file", self._spec_file)
|
|
|
|
|
|
|
|
# gather info from spec lines
|
|
|
|
|
|
|
|
pkg.current_linenum = 0
|
2008-08-04 23:45:03 +08:00
|
|
|
|
|
|
|
nbsp = chr(0xA0)
|
|
|
|
if is_utf8:
|
|
|
|
nbsp = unichr(0xA0)
|
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
for line in spec_lines:
|
2008-07-31 00:42:38 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
pkg.current_linenum += 1
|
2008-07-31 00:42:38 +08:00
|
|
|
|
|
|
|
if is_utf8:
|
|
|
|
line = unicode(line, "utf-8", "replace")
|
|
|
|
|
|
|
|
if line.find(nbsp) != -1:
|
|
|
|
printWarning(pkg, "non-break-space", "line %s" % pkg.current_linenum)
|
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
section_marker = 0
|
|
|
|
for i in section.keys():
|
|
|
|
if section[i]['re'].search(line):
|
|
|
|
current_section = i
|
|
|
|
section_marker = 1
|
|
|
|
section[i]['count'] = section[i]['count'] + 1
|
|
|
|
|
|
|
|
if section_marker:
|
2008-04-30 02:45:03 +08:00
|
|
|
if current_section == 'files':
|
|
|
|
files_has_defattr = 0
|
2007-05-15 06:02:01 +08:00
|
|
|
continue
|
|
|
|
|
|
|
|
if current_section in ('prep', 'build'):
|
|
|
|
if contains_buildroot(line):
|
|
|
|
printWarning(pkg, 'rpm-buildroot-usage', '%' + current_section, line[:-1].strip())
|
|
|
|
|
|
|
|
if make_check_regexp.search(line) and current_section not in ('check', 'changelog', 'package', 'description'):
|
|
|
|
printWarning(pkg, 'make-check-outside-check-section', line[:-1])
|
|
|
|
|
|
|
|
if current_section in buildroot_clean.keys():
|
|
|
|
if contains_buildroot(line) and rm_regex.search(line):
|
|
|
|
buildroot_clean[current_section] = 1
|
|
|
|
|
|
|
|
if ifarch_regex.search(line):
|
|
|
|
if_depth = if_depth + 1
|
|
|
|
ifarch_depth = if_depth
|
|
|
|
|
|
|
|
if if_regex.search(line):
|
|
|
|
if_depth = if_depth + 1
|
|
|
|
|
|
|
|
if line.startswith('%setup'):
|
|
|
|
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):
|
|
|
|
if setup_ab_regex.search(line):
|
2007-02-06 05:26:31 +08:00
|
|
|
printWarning(pkg, 'setup-not-quiet')
|
2007-05-15 06:02:01 +08:00
|
|
|
else:
|
|
|
|
printWarning(pkg, 'setup-not-quiet')
|
|
|
|
|
|
|
|
if endif_regex.search(line):
|
|
|
|
if ifarch_depth == if_depth:
|
|
|
|
ifarch_depth = -1
|
|
|
|
if_depth = if_depth - 1
|
|
|
|
|
|
|
|
res=patch_regex.search(line)
|
|
|
|
if res:
|
|
|
|
pnum = int(res.group(1) or 0)
|
|
|
|
patches[pnum] = res.group(2)
|
|
|
|
else:
|
|
|
|
res = applied_patch_regex.search(line)
|
2000-10-11 14:03:08 +08:00
|
|
|
if res:
|
2007-05-15 06:02:01 +08:00
|
|
|
pnum = int(res.group(1) or res.group(2) or 0)
|
|
|
|
applied_patches.append(pnum)
|
|
|
|
if ifarch_depth > 0:
|
|
|
|
applied_patches_ifarch.append(pnum)
|
|
|
|
elif not source_dir:
|
|
|
|
res = source_dir_regex.search(line)
|
2000-10-11 14:03:08 +08:00
|
|
|
if res:
|
2007-05-15 06:02:01 +08:00
|
|
|
source_dir = 1
|
|
|
|
printError(pkg, "use-of-RPM_SOURCE_DIR")
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
res=obsolete_tags_regex.search(line)
|
|
|
|
if res:
|
|
|
|
printWarning(pkg, "obsolete-tag", res.group(1))
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
if configure:
|
|
|
|
if configure_cmdline[-1] == "\\":
|
|
|
|
configure_cmdline=configure_cmdline[:-1] + string.strip(line)
|
|
|
|
else:
|
|
|
|
configure = 0
|
|
|
|
res = configure_libdir_spec_regex.search(configure_cmdline)
|
|
|
|
if not res:
|
2008-02-23 22:15:59 +08:00
|
|
|
printWarning(pkg, "configure-without-libdir-spec")
|
2007-05-15 06:02:01 +08:00
|
|
|
elif res.group(1):
|
|
|
|
res = re.match(hardcoded_library_paths, res.group(1))
|
|
|
|
if res:
|
|
|
|
printError(pkg, "hardcoded-library-path", res.group(1), "in configure options")
|
|
|
|
|
|
|
|
if current_section != 'changelog' and configure_start_regex.search(line):
|
|
|
|
configure = 1
|
|
|
|
configure_cmdline = string.strip(line)
|
|
|
|
|
|
|
|
res = hardcoded_library_path_regex.search(line)
|
|
|
|
if current_section != 'changelog' and res and not (biarch_package_regex.match(pkg.name) or hardcoded_lib_path_exceptions_regex.search(string.lstrip(res.group(1)))):
|
|
|
|
printError(pkg, "hardcoded-library-path", "in", string.lstrip(res.group(1)))
|
|
|
|
|
|
|
|
res = buildroot_regex.search(line)
|
|
|
|
if res:
|
|
|
|
buildroot=1
|
|
|
|
if res.group(1).startswith('/'):
|
|
|
|
printWarning(pkg, 'hardcoded-path-in-buildroot-tag', res.group(1))
|
|
|
|
|
|
|
|
res = packager_regex.search(line)
|
|
|
|
if res:
|
|
|
|
printWarning(pkg, 'hardcoded-packager-tag', res.group(1))
|
|
|
|
res=prefix_regex.search(line)
|
|
|
|
if res:
|
|
|
|
if res.group(1) == '%{_prefix}' or res.group(1) == '%_prefix':
|
|
|
|
printWarning(pkg, 'redundant-prefix-tag')
|
|
|
|
else:
|
|
|
|
printWarning(pkg, 'hardcoded-prefix-tag', res.group(1))
|
2005-02-11 16:39:04 +08:00
|
|
|
|
2008-03-25 04:45:35 +08:00
|
|
|
res = noarch_regex.search(line)
|
|
|
|
if res:
|
|
|
|
noarch = 1
|
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
if mklibname_regex.search(line):
|
|
|
|
mklibname = 1
|
2003-01-17 06:28:57 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
if lib_package_regex.search(line):
|
|
|
|
lib = 1
|
2005-08-10 14:10:39 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
res = prereq_regex.search(line)
|
|
|
|
if res:
|
2008-06-15 08:36:08 +08:00
|
|
|
printError(pkg, 'prereq-use', res.group(2))
|
2006-02-13 00:31:00 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
res = buildprereq_regex.search(line)
|
|
|
|
if res:
|
2008-06-15 08:36:08 +08:00
|
|
|
printError(pkg, 'buildprereq-use', res.group(1))
|
2005-11-28 05:49:15 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
if scriptlet_requires_regex.search(line) and current_section == 'package':
|
|
|
|
printError(pkg, 'broken-syntax-in-scriptlet-requires', string.strip(line))
|
2006-02-02 23:16:30 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
if current_section == 'changelog':
|
|
|
|
res = macro_regex.search(line)
|
|
|
|
if res and len(res.group(1)) % 2:
|
|
|
|
printWarning(pkg, 'macro-in-%changelog', res.group(2))
|
|
|
|
else:
|
|
|
|
if not depscript_override:
|
|
|
|
depscript_override = depscript_override_regex.search(line)
|
|
|
|
if not depgen_disabled:
|
|
|
|
depgen_disabled = depgen_disable_regex.search(line)
|
2006-06-06 02:57:33 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
res = provides_regex.search(line)
|
|
|
|
if res:
|
|
|
|
for prov in unversioned(deptokens(res.group(1))):
|
|
|
|
printWarning(pkg, 'unversioned-explicit-provides', prov)
|
2006-09-04 02:32:13 +08:00
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
res = obsoletes_regex.search(line)
|
|
|
|
if res:
|
|
|
|
for obs in unversioned(deptokens(res.group(1))):
|
|
|
|
printWarning(pkg, 'unversioned-explicit-obsoletes', obs)
|
|
|
|
|
2008-04-30 02:45:03 +08:00
|
|
|
if current_section == 'files':
|
|
|
|
if not comment_or_empty_regex.search(line) and not \
|
|
|
|
(ifarch_regex.search(line) or if_regex.search(line) or
|
|
|
|
endif_regex.search(line)):
|
|
|
|
if defattr_regex.search(line):
|
2008-06-29 09:20:35 +08:00
|
|
|
files_has_defattr = 1;
|
2008-04-30 02:45:03 +08:00
|
|
|
elif not (files_has_defattr or attr_regex.search(line)):
|
2008-06-29 09:20:35 +08:00
|
|
|
printError(pkg, 'files-attr-not-set')
|
2008-04-30 02:45:03 +08:00
|
|
|
|
2008-03-25 04:45:35 +08:00
|
|
|
# TODO: check scriptlets for these too
|
|
|
|
if current_section == 'files' and noarch:
|
|
|
|
res = libdir_regex.search(line)
|
|
|
|
if res:
|
|
|
|
printWarning(pkg, 'libdir-macro-in-noarch-package', line.rstrip())
|
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
if not indent_tabs and indent_tabs_regex.search(line):
|
|
|
|
indent_tabs = pkg.current_linenum
|
|
|
|
if not indent_spaces and indent_spaces_regex.search(line):
|
|
|
|
indent_spaces = pkg.current_linenum
|
|
|
|
|
2007-06-07 06:11:02 +08:00
|
|
|
# No useful line number info beyond this point.
|
|
|
|
pkg.current_linenum = None
|
|
|
|
|
2007-05-15 06:02:01 +08:00
|
|
|
for sect in buildroot_clean:
|
|
|
|
if not buildroot_clean[sect]:
|
|
|
|
printError(pkg, 'no-cleaning-of-buildroot', '%' + sect)
|
|
|
|
|
|
|
|
if not buildroot:
|
|
|
|
printError(pkg, 'no-buildroot-tag')
|
|
|
|
|
|
|
|
for sec in ('prep', 'build', 'install', 'clean'):
|
|
|
|
if not section[sec]['count']:
|
|
|
|
printWarning(pkg, 'no-%%%s-section' % sec)
|
|
|
|
for sec in ('changelog',):
|
|
|
|
# prep, build, install, clean, check prevented by rpmbuild
|
|
|
|
if section[sec]['count'] > 1:
|
|
|
|
printWarning(pkg, 'more-than-one-%%%s-section' % sec)
|
|
|
|
|
|
|
|
if lib and not mklibname:
|
|
|
|
printError(pkg, 'lib-package-without-%mklibname')
|
|
|
|
|
|
|
|
if depscript_override and not depgen_disabled:
|
|
|
|
printWarning(pkg, 'depscript-without-disabling-depgen')
|
|
|
|
|
|
|
|
if indent_spaces and indent_tabs:
|
|
|
|
printWarning(pkg, 'mixed-use-of-spaces-and-tabs',
|
|
|
|
'(spaces: line %d, tab: line %d)' %
|
|
|
|
(indent_spaces, indent_tabs))
|
|
|
|
|
|
|
|
# process gathered info
|
|
|
|
for p in patches.keys():
|
|
|
|
if p in applied_patches_ifarch:
|
|
|
|
printWarning(pkg, "%ifarch-applied-patch", "Patch%d:" % p, patches[p])
|
|
|
|
if p not in applied_patches:
|
|
|
|
printWarning(pkg, "patch-not-applied", "Patch%d:" % p, patches[p])
|
2000-10-11 14:03:08 +08:00
|
|
|
|
|
|
|
# Create an object to enable the auto registration of the test
|
2006-05-12 21:53:43 +08:00
|
|
|
check = SpecCheck()
|
2000-10-11 14:03:08 +08:00
|
|
|
|
2001-06-20 19:33:02 +08:00
|
|
|
# Add information about checks
|
|
|
|
if Config.info:
|
|
|
|
addDetails(
|
2001-07-04 05:13:22 +08:00
|
|
|
'no-spec-file',
|
2001-07-16 01:01:17 +08:00
|
|
|
'''No spec file was specified in your RPM building. Please specify a valid
|
|
|
|
SPEC file to build a valid RPM package.''',
|
2001-07-04 05:13:22 +08:00
|
|
|
|
|
|
|
'invalid-spec-name',
|
2005-11-23 00:36:30 +08:00
|
|
|
'''Your spec filename must end with '.spec'. If it's not the case, rename your
|
2001-07-16 01:01:17 +08:00
|
|
|
file and rebuild your package.''',
|
2001-07-04 05:13:22 +08:00
|
|
|
|
2006-01-15 17:59:04 +08:00
|
|
|
'non-utf8-spec-file',
|
|
|
|
'''The character encoding of the spec file is not UTF-8. Convert it for
|
|
|
|
example using iconv(1).''',
|
|
|
|
|
2001-07-04 05:13:22 +08:00
|
|
|
'use-of-RPM_SOURCE_DIR',
|
2005-11-23 00:36:30 +08:00
|
|
|
'''You use $RPM_SOURCE_DIR or %{_sourcedir} in your spec file. If you have to
|
|
|
|
use a directory for building, use $RPM_BUILD_ROOT instead.''',
|
2001-07-04 05:13:22 +08:00
|
|
|
|
|
|
|
'patch-not-applied',
|
2001-07-16 01:01:17 +08:00
|
|
|
'''A patch is included in your package but was not applied. Refer to the patches
|
|
|
|
documentation to see what's wrong.''',
|
2001-07-04 05:13:22 +08:00
|
|
|
|
2001-06-20 19:33:02 +08:00
|
|
|
'obsolete-tag',
|
|
|
|
'''The following tags are obsolete: Copyright and Serial. They must
|
|
|
|
be replaced by License and Epoch respectively.''',
|
2001-07-16 01:01:17 +08:00
|
|
|
|
2001-11-14 13:11:24 +08:00
|
|
|
'no-buildroot-tag',
|
2005-11-23 00:36:30 +08:00
|
|
|
'''The BuildRoot tag isn't used in your spec. It must be used in order to
|
|
|
|
allow building the package as non root on some systems.''',
|
2001-11-14 13:11:24 +08:00
|
|
|
|
|
|
|
'hardcoded-path-in-buildroot-tag',
|
|
|
|
'''A path is hardcoded in your Buildroot tag. It should be replaced
|
|
|
|
by something like %{_tmppath}/%name-root.''',
|
|
|
|
|
2005-02-11 16:39:04 +08:00
|
|
|
'hardcoded-packager-tag',
|
2005-11-23 00:36:30 +08:00
|
|
|
'''The Packager tag is hardcoded in your spec file. It should be removed, so
|
|
|
|
as to use rebuilder's own defaults.''',
|
2005-02-11 16:39:04 +08:00
|
|
|
|
|
|
|
'hardcoded-prefix-tag',
|
2005-11-23 00:36:30 +08:00
|
|
|
'''The Prefix tag is hardcoded in your spec file. It should be removed, so as
|
|
|
|
to allow package relocation.''',
|
2005-02-11 16:39:04 +08:00
|
|
|
|
|
|
|
'redundant-prefix-tag',
|
2005-11-23 00:36:30 +08:00
|
|
|
'''The Prefix tag is uselessly defined as %{_prefix} in your spec file. It
|
|
|
|
should be removed, as it is redundant with rpm defaults.''',
|
2005-02-11 16:39:04 +08:00
|
|
|
|
2002-06-01 22:18:31 +08:00
|
|
|
'hardcoded-library-path',
|
2002-06-01 21:17:28 +08:00
|
|
|
'''A library path is hardcoded to one of the following paths: /lib,
|
|
|
|
/usr/lib. It should be replaced by something like /%{_lib} or %{_libdir}.''',
|
|
|
|
|
2002-06-01 22:18:31 +08:00
|
|
|
'configure-without-libdir-spec',
|
2005-11-23 00:36:30 +08:00
|
|
|
'''A configure script is run without specifying the libdir. configure
|
2008-02-23 22:15:59 +08:00
|
|
|
options must be augmented with something like --libdir=%{_libdir} whenever
|
|
|
|
the script supports it.''',
|
2002-06-01 22:18:31 +08:00
|
|
|
|
2006-06-29 17:47:57 +08:00
|
|
|
'no-%prep-section',
|
|
|
|
'''The spec file does not contain a %prep section. Even if some packages don't
|
|
|
|
directly need it, section markers may be overridden in rpm's configuration
|
|
|
|
to provide additional "under the hood" functionality. Add the section, even
|
|
|
|
if empty.''',
|
|
|
|
|
|
|
|
'no-%build-section',
|
|
|
|
'''The spec file does not contain a %build section. Even if some packages
|
|
|
|
don't directly need it, section markers may be overridden in rpm's
|
|
|
|
configuration to provide additional "under the hood" functionality, such as
|
|
|
|
injection of automatic -debuginfo subpackages. Add the section, even if
|
|
|
|
empty.''',
|
|
|
|
|
|
|
|
'no-%install-section',
|
|
|
|
'''The spec file does not contain an %install section. Even if some packages
|
|
|
|
don't directly need it, section markers may be overridden in rpm's
|
|
|
|
configuration to provide additional "under the hood" functionality. Add the
|
|
|
|
section, even if empty.''',
|
|
|
|
|
2002-01-26 05:55:59 +08:00
|
|
|
'no-%clean-section',
|
|
|
|
'''The spec file doesn't contain a %clean section to remove the files installed
|
|
|
|
by the %install section.''',
|
|
|
|
|
2006-12-11 06:39:23 +08:00
|
|
|
'more-than-one-%changelog-section',
|
|
|
|
'''The spec file unnecessarily contains more than one %changelog section;
|
|
|
|
remove the extra ones.''',
|
|
|
|
|
2003-01-17 06:28:57 +08:00
|
|
|
'lib-package-without-%mklibname',
|
|
|
|
'''The package name must be built using %mklibname to allow lib64 and lib32
|
|
|
|
coexistence.''',
|
|
|
|
|
2003-05-08 16:41:05 +08:00
|
|
|
'%ifarch-applied-patch',
|
|
|
|
'''A patch is applied inside an %ifarch block. Patches must be applied
|
|
|
|
on all architectures and may contain necessary configure and/or code
|
2005-08-10 14:10:39 +08:00
|
|
|
patch to be effective only on a given arch.''',
|
|
|
|
|
|
|
|
'prereq-use',
|
2006-02-13 00:31:00 +08:00
|
|
|
'''The use of PreReq is deprecated. In the majority of cases, a plain Requires
|
|
|
|
is enough and the right thing to do. Sometimes Requires(pre), Requires(post),
|
|
|
|
Requires(preun) and/or Requires(postun) can also be used instead of PreReq.''',
|
|
|
|
|
|
|
|
'buildprereq-use',
|
|
|
|
'''The use of BuildPreReq is deprecated, build dependencies are always required
|
|
|
|
before a package can be built. Use plain BuildRequires instead.''',
|
2003-05-08 16:41:05 +08:00
|
|
|
|
2006-02-02 23:16:30 +08:00
|
|
|
'broken-syntax-in-scriptlet-requires',
|
2006-12-04 06:43:16 +08:00
|
|
|
'''Comma separated context marked dependencies are silently broken in some
|
|
|
|
versions of rpm. One way to work around it is to split them into several ones,
|
|
|
|
eg. replace "Requires(post,preun): foo" with "Requires(post): foo" and
|
|
|
|
"Requires(preun): foo".''',
|
2006-02-02 23:16:30 +08:00
|
|
|
|
2006-05-13 00:28:02 +08:00
|
|
|
'setup-not-quiet',
|
2007-02-06 05:26:31 +08:00
|
|
|
'''Use the -q option to the %setup macro to avoid useless build output from
|
|
|
|
unpacking the sources.''',
|
2006-05-13 00:28:02 +08:00
|
|
|
|
2006-05-13 17:16:20 +08:00
|
|
|
'no-cleaning-of-buildroot',
|
2006-05-13 17:35:12 +08:00
|
|
|
'''You should clean $RPM_BUILD_ROOT in the %clean section and just after the
|
|
|
|
beginning of %install section. Use "rm -Rf $RPM_BUILD_ROOT".''',
|
2006-05-13 17:16:20 +08:00
|
|
|
|
2006-05-13 17:20:36 +08:00
|
|
|
'rpm-buildroot-usage',
|
|
|
|
'''$RPM_BUILD_ROOT should not be touched during %build or %prep stage, as it
|
|
|
|
will break short circuiting.''',
|
|
|
|
|
2006-05-13 17:29:23 +08:00
|
|
|
'make-check-outside-check-section',
|
2006-05-13 17:35:12 +08:00
|
|
|
'''Make check or other automated regression test should be run in %check, as
|
2006-06-06 02:57:33 +08:00
|
|
|
they can be disabled with a rpm macro for short circuiting purposes.''',
|
|
|
|
|
|
|
|
'macro-in-%changelog',
|
|
|
|
'''Macros are expanded in %changelog too, which can in unfortunate cases lead
|
|
|
|
to the package not building at all, or other subtle unexpected conditions that
|
|
|
|
affect the build. Even when that doesn\'t happen, the expansion results in
|
|
|
|
possibly "rewriting history" on subsequent package revisions and generally
|
|
|
|
odd entries eg. in source rpms, which is rarely wanted. Avoid use of macros
|
|
|
|
in %changelog altogether, or use two '%'s to escape them, like '%%foo'.''',
|
2006-06-16 04:44:26 +08:00
|
|
|
|
|
|
|
'depscript-without-disabling-depgen',
|
|
|
|
'''In some common rpm configurations/versions, defining __find_provides and/or
|
|
|
|
__find_requires has no effect if rpm's internal dependency generator has not
|
|
|
|
been disabled for the build. %define _use_internal_dependency_generator to 0
|
|
|
|
to disable it in the specfile, or don't define __find_provides/requires.''',
|
2006-06-23 00:04:13 +08:00
|
|
|
|
|
|
|
'mixed-use-of-spaces-and-tabs',
|
|
|
|
'''The specfile mixes use of spaces and tabs for indentation, which is a
|
|
|
|
cosmetic annoyance. Use either spaces or tabs for indentation, not both.''',
|
2006-09-04 02:32:13 +08:00
|
|
|
|
|
|
|
'unversioned-explicit-provides',
|
|
|
|
'''The specfile contains an unversioned Provides: token, which will match all
|
|
|
|
older, equal, and newer versions of the provided thing. This may cause
|
|
|
|
update problems and will make versioned dependencies, obsoletions and conflicts
|
|
|
|
on the provided thing useless -- make the Provides versioned if possible.''',
|
|
|
|
|
|
|
|
'unversioned-explicit-obsoletes',
|
|
|
|
'''The specfile contains an unversioned Obsoletes: token, which will match all
|
|
|
|
older, equal and newer versions of the obsoleted thing. This may cause update
|
|
|
|
problems, restrict future package/provides naming, and may match something it
|
|
|
|
was originally not inteded to match -- make the Obsoletes versioned if
|
|
|
|
possible.''',
|
2008-03-22 07:51:05 +08:00
|
|
|
|
2008-03-25 04:45:35 +08:00
|
|
|
'libdir-macro-in-noarch-package',
|
|
|
|
'''The %{_libdir} or %{_lib} macro was found in a noarch package in a section
|
|
|
|
that gets included in binary packages. This is most likely an error because
|
|
|
|
these macros are expanded on the build host and their values vary between
|
|
|
|
architectures, probably resulting in a package that does not work properly
|
|
|
|
on all architectures at runtime. Investigate whether the package is really
|
|
|
|
architecture independent or if some other dir/macro should be instead.''',
|
|
|
|
|
2008-03-22 07:51:05 +08:00
|
|
|
'non-break-space',
|
2008-03-25 05:13:24 +08:00
|
|
|
'''The spec file contains a non-break space, which looks like a regular space
|
|
|
|
in some editors but can lead to obscure errors. It should be replaced by a
|
|
|
|
regular space.''',
|
2008-04-30 02:45:03 +08:00
|
|
|
|
|
|
|
'files-attr-not-set',
|
|
|
|
'''A file or a directory entry in a %files section does not have attributes
|
|
|
|
set which may result in security issues in the resulting binary package
|
|
|
|
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.''',
|
2001-06-20 19:33:02 +08:00
|
|
|
)
|
|
|
|
|
2000-10-11 14:03:08 +08:00
|
|
|
# SpecCheck.py ends here
|
2006-04-01 16:09:17 +08:00
|
|
|
|
|
|
|
# Local variables:
|
|
|
|
# indent-tabs-mode: nil
|
|
|
|
# py-indent-offset: 4
|
|
|
|
# End:
|
|
|
|
# ex: ts=4 sw=4 et
|