]> git.pld-linux.org Git - projects/pld-ftp-admin.git/blob - bin/pfa-lintpkg
- add -o outfile support
[projects/pld-ftp-admin.git] / bin / pfa-lintpkg
1 #!/usr/bin/env python
2 # vi: encoding=utf-8 ts=8 sts=4 sw=4 et
3
4 import sys, os, re
5 import getopt
6 import subprocess
7 sys.path.insert(0, os.environ['HOME']+'/pld-ftp-admin/modules')
8 import ftptree
9 from common import checkdir
10 import ftpio
11
12 try:
13     opts, args = getopt.getopt(sys.argv[1:], 'qso:', [ "quiet" ])
14 except getopt.GetoptError:
15     print >>sys.stderr, "ERR: options error"
16     print >>sys.stderr, "rpmlint.py tree package1 [package2...]"
17     sys.exit(1)
18
19 quiet = False
20 show = False
21 outstream = sys.stdout
22 for o, a in opts:
23     if o == "-q" or o == "--quiet":
24         quiet = True
25     if o == "-s":
26         show = True
27     if o == "-o":
28         outstream = open(a, 'w')
29
30 if len(args) < 1:
31     print >>sys.stderr, "ERR: missing tree name"
32     print >>sys.stderr, "rpmlint.py tree package1 [package2...]"
33     sys.exit(1)
34
35 treename = args[0]
36 packages = args[1:]
37
38 checkdir(treename)
39
40 ftpio.connect('rpmlint')
41
42 if not ftpio.lock(treename, True):
43     print >>sys.stderr, "ERR: %s tree already locked" % treename
44     sys.exit(1)
45
46 files = []
47 try:
48     if len(packages) < 1:
49         loadall = True
50     else:
51         loadall = False
52
53     # if no files specified, grab whole tree contents
54     tree = ftptree.FtpTree(treename, loadall = loadall)
55     tree.do_checkbuild = False
56     if loadall:
57         # this is hack, should be a param, not access private .loadedpkgs element
58         tree.mark4moving(tree.loadedpkgs)
59     else:
60         tree.mark4moving(packages)
61     files = tree.rpmfiles(debugfiles = False, sourcefiles = False)
62
63 except (ftptree.SomeError, KeyboardInterrupt), e:
64     # In case of problems we need to unlock the tree before exiting
65     ftpio.unlock(treename)
66     sys.exit(1)
67
68 ftpio.unlock(treename)
69
70 class LintPkg:
71     def __init__(self, cachedir):
72         self.outstream = sys.stdout
73
74         # for rpmlint stats
75         self.packages = self.specfiles = self.errors = self.warnings = 0
76         # 1 packages and 0 specfiles checked; 0 errors, 0 warnings.
77         self.lintre = re.compile('(?P<packages>\d+) packages and (?P<specfiles>\d+) specfiles checked; (?P<errors>\d+) errors, (?P<warnings>\d+) warnings.')
78
79         self._rpmlint = '/usr/bin/rpmlint'
80
81         self.cachedir = os.path.expanduser(cachedir)
82         if not os.path.isdir(self.cachedir):
83             os.makedirs(self.cachedir)
84
85     def cachefile(self, file):
86         (dirname, filename) = os.path.split(file)
87         return os.path.join(self.cachedir, filename+'.txt')
88
89     def get_stats(self, file):
90         cachefile = self.cachefile(file)
91         if not os.path.exists(cachefile):
92             return None
93
94         # show last line (that contains status)
95         l = (open(cachefile, 'r').readlines())[-1]
96         m = self.lintre.match(l)
97         if not m:
98             return None
99
100         return {
101             'packages': int(m.group('packages')),
102             'specfiles': int(m.group('specfiles')),
103             'errors': int(m.group('errors')),
104             'warnings': int(m.group('warnings')),
105         }
106
107     """
108     update stats from cachefile
109     """
110     def update_stats(self, file):
111         m = self.get_stats(file)
112         if not m:
113             return False
114         self.packages += m['packages']
115         self.specfiles += m['specfiles']
116         self.errors += m['errors']
117         self.warnings += m['warnings']
118         return True
119
120     def print_stats(self, file = None):
121         if file:
122             (dirname, filename) = os.path.split(file)
123             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),
124         else:
125             print >>self.outstream, "\r\033[0K%d packages and %d specfiles checked; %d errors, %d warnings." % (self.packages, self.specfiles, self.errors, self.warnings)
126         sys.stdout.flush()
127
128     def cat(self, file):
129         print >>self.outstream, "".join(open(file, 'r').readlines())
130
131     def show_results(self, file):
132         m = self.get_stats(file)
133         if not m:
134             return False
135
136         cachefile = self.cachefile(file)
137         if not os.path.exists(cachefile):
138             print >>self.outsteram, "MISSING: report: %s" % file
139
140         if m['errors'] > 0 or m['warnings'] > 0:
141             (dirname, filename) = os.path.split(file)
142             print >>self.outstream, "rpmlint: %s" % filename
143             self.cat(cachefile)
144
145     def rpmlint(self, file):
146         cachefile = self.cachefile(file)
147
148         rc = None
149         if not os.path.exists(cachefile) or os.stat(file).st_mtime > os.stat(cachefile).st_mtime:
150             cmd = [self._rpmlint, file]
151             outfd = open(cachefile, 'w')
152             try:
153                 rc = subprocess.call(cmd, stdin = subprocess.PIPE, stdout = outfd, stderr = outfd, close_fds = True)
154             except KeyboardInterrupt:
155                 os.unlink(cachefile)
156                 raise
157             outfd.close()
158         if not self.update_stats(file):
159             # update failed, dump cache and remove it
160             self.cat(cachefile)
161             os.unlink(cachefile)
162             rc = 1
163         return rc == 0
164
165 try:
166     lock = 'rpmlint:'+treename
167     if not ftpio.lock(lock, True):
168         print >>sys.stderr, "ERR: %s tree already locked for rpmlint" % treename
169         sys.exit(1)
170
171     if not quiet:
172         print >>outstream, "rpmlint of %d files from %d packages" % (len(files), len(tree.loadedpkgs))
173     lint = LintPkg("~/tmp/rpmlint")
174     lint.outstream = outstream
175     for file in files:
176         lint.rpmlint(file)
177         if not quiet:
178             lint.print_stats(file)
179         if show:
180             lint.show_results(file)
181
182     if not quiet:
183         lint.print_stats()
184
185     ftpio.unlock(lock)
186 except (Exception, KeyboardInterrupt):
187     ftpio.unlock(lock)
188     raise
This page took 0.044452 seconds and 4 git commands to generate.