#!/usr/bin/env python # vi: encoding=utf-8 ts=8 sts=4 sw=4 et import sys, os, re import getopt import subprocess sys.path.insert(0, os.environ['HOME']+'/pld-ftp-admin/modules') import ftptree from common import checkdir import ftpio try: opts, args = getopt.getopt(sys.argv[1:], 'q', [ "quiet" ]) except getopt.GetoptError: print >>sys.stderr, "ERR: options error" print >>sys.stderr, "rpmlint.py tree package1 [package2...]" sys.exit(1) quiet = False for o, a in opts: if o == "-q" or o == "--quiet": quiet = True if len(args) < 1: print >>sys.stderr, "ERR: missing tree name" print >>sys.stderr, "rpmlint.py tree package1 [package2...]" sys.exit(1) treename = args[0] packages = args[1:] checkdir(treename) ftpio.connect('rpmlint') if not ftpio.lock(treename, True): print >>sys.stderr, "ERR: %s tree already locked" % treename sys.exit(1) files = [] try: if len(packages) < 1: loadall = True else: loadall = False # if no files specified, grab whole tree contents tree = ftptree.FtpTree(treename, loadall = loadall) if loadall: # this is hack, should be a param, not access private .loadedpkgs element tree.mark4moving(tree.loadedpkgs) else: tree.mark4moving(packages) files = tree.rpmfiles(debugfiles = False, sourcefiles = False) except (ftptree.SomeError, KeyboardInterrupt), e: # In case of problems we need to unlock the tree before exiting ftpio.unlock(treename) sys.exit(1) ftpio.unlock(treename) class LintPkg: def __init__(self, cachedir): # for rpmlint stats self.packages = self.specfiles = self.errors = self.warnings = 0 # 1 packages and 0 specfiles checked; 0 errors, 0 warnings. self.lintre = re.compile('(?P\d+) packages and (?P\d+) specfiles checked; (?P\d+) errors, (?P\d+) warnings.') self._rpmlint = '/usr/bin/rpmlint' self.cachedir = os.path.expanduser(cachedir) if not os.path.isdir(self.cachedir): os.makedirs(self.cachedir) def cachefile(self, file): (dirname, filename) = os.path.split(file) return os.path.join(self.cachedir, filename+'.txt') """ update stats from cachefile """ def update_stats(self, file): cachefile = self.cachefile(file) # show last line (that contains status) l = (open(cachefile, 'r').readlines())[-1] m = self.lintre.match(l) if not m: return False self.packages += int(m.group('packages')) self.specfiles += int(m.group('specfiles')) self.errors += int(m.group('errors')) self.warnings += int(m.group('warnings')) return True def print_stats(self, file = None): if file: (dirname, filename) = os.path.split(file) print "\r\033[0K%d packages and %d specfiles checked; %d errors, %d warnings. [%s]" % (self.packages, self.specfiles, self.errors, self.warnings, filename), else: print "\r\033[0K%d packages and %d specfiles checked; %d errors, %d warnings." % (self.packages, self.specfiles, self.errors, self.warnings) sys.stdout.flush() def rpmlint(self, file): cachefile = self.cachefile(file) rc = None if not os.path.exists(cachefile) or os.stat(file).st_mtime > os.stat(cachefile).st_mtime: cmd = [self._rpmlint, file] outfd = open(cachefile, 'w') try: rc = subprocess.call(cmd, stdin = subprocess.PIPE, stdout = outfd, stderr = outfd, close_fds = True) except KeyboardInterrupt: os.unlink(cachefile) raise outfd.close() if not self.update_stats(file): os.unlink(cachefile) rc = 1 return rc == 0 if not quiet: print "rpmlint of %d files from %d packages" % (len(files), len(tree.loadedpkgs)) lint = LintPkg("~/tmp/rpmlint") for file in files: lint.rpmlint(file) if not quiet: lint.print_stats(file) if not quiet: lint.print_stats()