import ftpio
try:
- opts, args = getopt.getopt(sys.argv[1:], 'q', [ "quiet" ])
+ opts, args = getopt.getopt(sys.argv[1:], 'qsdo:', [ "quiet" ])
except getopt.GetoptError:
print >>sys.stderr, "ERR: options error"
print >>sys.stderr, "rpmlint.py tree package1 [package2...]"
sys.exit(1)
quiet = False
+show = False
+debugfiles = False
+outstream = sys.stdout
for o, a in opts:
if o == "-q" or o == "--quiet":
quiet = True
+ if o == "-s":
+ show = True
+ if o == "-d":
+ debugfiles = True
+ if o == "-o":
+ outstream = open(a, 'w')
if len(args) < 1:
print >>sys.stderr, "ERR: missing tree name"
# if no files specified, grab whole tree contents
tree = ftptree.FtpTree(treename, loadall = loadall)
+ tree.do_checkbuild = False
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)
+ files = tree.rpmfiles(debugfiles = debugfiles, sourcefiles = False)
except (ftptree.SomeError, KeyboardInterrupt), e:
# In case of problems we need to unlock the tree before exiting
class LintPkg:
def __init__(self, cachedir):
+ self.outstream = sys.stdout
+
# for rpmlint stats
self.packages = self.specfiles = self.errors = self.warnings = 0
# 1 packages and 0 specfiles checked; 0 errors, 0 warnings.
self._rpmlint = '/usr/bin/rpmlint'
+ # mtime, which invalidates all caches
+ self.mtime = None
+ rpmlintrc = os.path.expanduser("~/.config/rpmlint")
+ if os.path.exists(rpmlintrc):
+ self.mtime = os.stat(rpmlintrc).st_mtime
+
self.cachedir = os.path.expanduser(cachedir)
if not os.path.isdir(self.cachedir):
os.makedirs(self.cachedir)
(dirname, filename) = os.path.split(file)
return os.path.join(self.cachedir, filename+'.txt')
- """
- update stats from cachefile
- """
- def update_stats(self, file):
+ def get_stats(self, file):
cachefile = self.cachefile(file)
+ if not os.path.exists(cachefile):
+ return None
# show last line (that contains status)
l = (open(cachefile, 'r').readlines())[-1]
m = self.lintre.match(l)
if not m:
- return False
+ return None
- 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 {
+ 'packages': int(m.group('packages')),
+ 'specfiles': int(m.group('specfiles')),
+ 'errors': int(m.group('errors')),
+ 'warnings': int(m.group('warnings')),
+ }
+
+ """
+ update stats from cachefile
+ """
+ def update_stats(self, file):
+ m = self.get_stats(file)
+ if not m:
+ return False
+ self.packages += m['packages']
+ self.specfiles += m['specfiles']
+ self.errors += m['errors']
+ self.warnings += m['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),
+ print >>self.outstream, "\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)
+ print >>self.outstream, "\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 cat(self, file):
+ print >>self.outstream, "".join(open(file, 'r').readlines())
+
+ def show_results(self, file):
+ m = self.get_stats(file)
+ if not m:
+ return False
+
+ cachefile = self.cachefile(file)
+ if not os.path.exists(cachefile):
+ print >>self.outsteram, "MISSING: report: %s" % file
+
+ if m['errors'] > 0 or m['warnings'] > 0:
+ (dirname, filename) = os.path.split(file)
+ print >>self.outstream, "rpmlint: %s" % filename
+ self.cat(cachefile)
+
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:
+ if not os.path.exists(cachefile) \
+ or os.stat(file).st_mtime > os.stat(cachefile).st_mtime \
+ or (self.mtime and self.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)
+ env = {'TZ': 'GMT'}
+ rc = subprocess.call(cmd, stdin = subprocess.PIPE, stdout = outfd, stderr = outfd, env = env, close_fds = True)
except KeyboardInterrupt:
os.unlink(cachefile)
raise
outfd.close()
if not self.update_stats(file):
+ # update failed, dump cache and remove it
+ self.cat(cachefile)
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)
+try:
+ lock = 'rpmlint:'+treename
+ if not ftpio.lock(lock, True):
+ print >>sys.stderr, "ERR: %s tree already locked for rpmlint" % treename
+ sys.exit(1)
+
+ if not quiet:
+ print >>outstream, "rpmlint of %d files from %d packages" % (len(files), len(tree.loadedpkgs))
+ lint = LintPkg("~/tmp/rpmlint")
+ lint.outstream = outstream
+ for file in files:
+ lint.rpmlint(file)
+ if not quiet:
+ lint.print_stats(file)
+ if show:
+ lint.show_results(file)
+
if not quiet:
- lint.print_stats(file)
+ lint.print_stats()
-if not quiet:
- lint.print_stats()
+ ftpio.unlock(lock)
+except (Exception, KeyboardInterrupt):
+ ftpio.unlock(lock)
+ raise