A new user interface for you! Read more...

File verify-buildrequires.diff of Package rpmlint

--- SpecCheck.py
+++ SpecCheck.py
@@ -45,7 +45,8 @@
 biarch_package_regex = re.compile(DEFAULT_BIARCH_PACKAGES)
 hardcoded_lib_path_exceptions_regex = re.compile(Config.getOption('HardcodedLibPathExceptions', DEFAULT_HARDCODED_LIB_PATH_EXCEPTIONS))
 prereq_regex = re.compile('^PreReq(\(.*\))?:\s*(.+?)\s*$', re.IGNORECASE)
-buildprereq_regex = re.compile('^BuildPreReq:\s*(.+?)\s*$', re.IGNORECASE)
+buildprereq_regex = re.compile('^BuildPreReq\s*:\s*(.+)\s*$', re.IGNORECASE)
+buildrequires_regex = re.compile('^\s*BuildRequires\s*:\s*(.+)\s*$', re.IGNORECASE)
 use_utf8 = Config.getOption('UseUTF8', Config.USEUTF8_DEFAULT)
 macro_regex = re.compile('(%+)[{(]?(\w+)')
 libdir_regex = re.compile('%{?_lib(?:dir)?\}?\\b')
@@ -126,6 +127,25 @@
             res.append(tok)
     return res
 
+def find_reverse_requires():
+    reverse_requires = dict()
+    try:
+        f = file("/.builtinfo/rpmdeps", "r")
+    except:
+        return reverse_requires
+
+    for line in f:
+        if line.startswith('R:'):
+            package = "-".join(line.split(':')[1].split('-')[:-3])
+            deps = deptokens(line.split(':')[2])
+            for dep in deps:
+                name = dep.split(' ')[0]
+                if name.startswith('/') or name.find('(') != -1 or name == dep:
+                    continue
+                reverse_requires.setdefault(name, set()).add(package)
+
+    return reverse_requires
+
 def contains_buildroot(line):
     '''Check if the given line contains use of rpm buildroot.'''
     res = rpm_buildroot_regex.search(line)
@@ -188,6 +208,8 @@
         indent_tabs = 0
         files_has_defattr = 0
         section = {}
+        buildrequires = set()
+
         for sec in ['description', 'prep', 'build', 'install', 'clean',
                     'files', 'changelog', 'package', 'check']:
             section[sec] = {
@@ -348,6 +370,14 @@
                 if res:
                     printError(pkg, 'buildprereq-use', res.group(1))
 
+                res = buildrequires_regex.search(line)
+                if not if_depth and res:
+                    for r in deptokens(res.group(1)):
+                        name = r.split(' ')[0]
+                        if name in buildrequires:
+                            printWarning(pkg, 'duplicate-buildrequires', name)
+                        buildrequires.add(name)
+
                 if scriptlet_requires_regex.search(line):
                     printError(pkg, 'broken-syntax-in-scriptlet-requires', string.strip(line))
 
@@ -420,6 +450,24 @@
                          '(spaces: line %d, tab: line %d)' %
                          (indent_spaces, indent_tabs))
 
+        reverse_requires = find_reverse_requires()
+        for r in buildrequires:
+            if r in reverse_requires:
+                for rev in reverse_requires[r]:
+                    if rev in buildrequires:
+                        printWarning(pkg, 'unnecessary-buildrequires', r, 'already included by', rev)
+
+            if not r.endswith("-devel"):
+                develr = [ r + "-devel" ]
+                # libfoo-4_2 -> libfoo-devel
+                dr2 = re.sub(r'-?[0-9_]+$', '', r) + "-devel"
+                if dr2 != develr[0]:
+                    develr.append(dr2);
+                for dr in develr:
+                    if r in reverse_requires and dr in reverse_requires[r] \
+                            and not  dr in buildrequires:
+                        printWarning(pkg, "non-devel-buildrequires", r, "- did you mean", dr, "?")
+
         # process gathered info
         for p in patches.keys():
             if p in applied_patches_ifarch:
@@ -557,6 +605,17 @@
 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'.''',
 
+'unnecessary-buildrequires',
+''' The specfile contains a buildrequires entry that seems to be already
+requires by one of the other buildrequires. Please consider reducing your
+buildrequires definitions in case this is a real implicit dependency.''',
+
+'non-devel-buildrequires',
+'''The specfile contains a buildrequires entry that has a -devel package.
+Please carefully check if you want to buildrequire the -devel subpackage or if
+this is an unnecessary dependency that is already required by one of the other
+buildrequires.''',
+
 '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