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