2 # vi: encoding=utf-8 ts=8 sts=4 sw=4 et
7 sys.path.insert(0, os.environ['HOME']+'/pld-ftp-admin/modules')
9 from common import checkdir
13 opts, args = getopt.getopt(sys.argv[1:], 'qsdo:', [ "quiet" ])
14 except getopt.GetoptError:
15 print >>sys.stderr, "ERR: options error"
16 print >>sys.stderr, "rpmlint.py tree package1 [package2...]"
22 outstream = sys.stdout
24 if o == "-q" or o == "--quiet":
31 outstream = open(a, 'w')
34 print >>sys.stderr, "ERR: missing tree name"
35 print >>sys.stderr, "rpmlint.py tree package1 [package2...]"
43 ftpio.connect('rpmlint')
45 if not ftpio.lock(treename, True):
46 print >>sys.stderr, "ERR: %s tree already locked" % treename
56 # if no files specified, grab whole tree contents
57 tree = ftptree.FtpTree(treename, loadall = loadall)
58 tree.do_checkbuild = False
60 # this is hack, should be a param, not access private .loadedpkgs element
61 tree.mark4moving(tree.loadedpkgs)
63 tree.mark4moving(packages)
64 files = tree.rpmfiles(debugfiles = debugfiles, sourcefiles = False)
66 except (ftptree.SomeError, KeyboardInterrupt), e:
67 # In case of problems we need to unlock the tree before exiting
68 ftpio.unlock(treename)
71 ftpio.unlock(treename)
74 def __init__(self, cachedir):
75 self.outstream = sys.stdout
78 self.packages = self.specfiles = self.errors = self.warnings = 0
79 # 1 packages and 0 specfiles checked; 0 errors, 0 warnings.
80 self.lintre = re.compile('(?P<packages>\d+) packages and (?P<specfiles>\d+) specfiles checked; (?P<errors>\d+) errors, (?P<warnings>\d+) warnings.')
82 self._rpmlint = '/usr/bin/rpmlint'
84 self.cachedir = os.path.expanduser(cachedir)
85 if not os.path.isdir(self.cachedir):
86 os.makedirs(self.cachedir)
88 def cachefile(self, file):
89 (dirname, filename) = os.path.split(file)
90 return os.path.join(self.cachedir, filename+'.txt')
92 def get_stats(self, file):
93 cachefile = self.cachefile(file)
94 if not os.path.exists(cachefile):
97 # show last line (that contains status)
98 l = (open(cachefile, 'r').readlines())[-1]
99 m = self.lintre.match(l)
104 'packages': int(m.group('packages')),
105 'specfiles': int(m.group('specfiles')),
106 'errors': int(m.group('errors')),
107 'warnings': int(m.group('warnings')),
111 update stats from cachefile
113 def update_stats(self, file):
114 m = self.get_stats(file)
117 self.packages += m['packages']
118 self.specfiles += m['specfiles']
119 self.errors += m['errors']
120 self.warnings += m['warnings']
123 def print_stats(self, file = None):
125 (dirname, filename) = os.path.split(file)
126 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),
128 print >>self.outstream, "\r\033[0K%d packages and %d specfiles checked; %d errors, %d warnings." % (self.packages, self.specfiles, self.errors, self.warnings)
132 print >>self.outstream, "".join(open(file, 'r').readlines())
134 def show_results(self, file):
135 m = self.get_stats(file)
139 cachefile = self.cachefile(file)
140 if not os.path.exists(cachefile):
141 print >>self.outsteram, "MISSING: report: %s" % file
143 if m['errors'] > 0 or m['warnings'] > 0:
144 (dirname, filename) = os.path.split(file)
145 print >>self.outstream, "rpmlint: %s" % filename
148 def rpmlint(self, file):
149 cachefile = self.cachefile(file)
152 if not os.path.exists(cachefile) or os.stat(file).st_mtime > os.stat(cachefile).st_mtime:
153 cmd = [self._rpmlint, file]
154 outfd = open(cachefile, 'w')
157 rc = subprocess.call(cmd, stdin = subprocess.PIPE, stdout = outfd, stderr = outfd, env = env, close_fds = True)
158 except KeyboardInterrupt:
162 if not self.update_stats(file):
163 # update failed, dump cache and remove it
170 lock = 'rpmlint:'+treename
171 if not ftpio.lock(lock, True):
172 print >>sys.stderr, "ERR: %s tree already locked for rpmlint" % treename
176 print >>outstream, "rpmlint of %d files from %d packages" % (len(files), len(tree.loadedpkgs))
177 lint = LintPkg("~/tmp/rpmlint")
178 lint.outstream = outstream
182 lint.print_stats(file)
184 lint.show_results(file)
190 except (Exception, KeyboardInterrupt):