1#! /usr/bin/env python3
3""" Output html for packages in NEW """
4# Copyright (C) 2007, 2009 Joerg Jaspert <joerg@debian.org>
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20################################################################################
22# <elmo> I'm James Troup, long term source of all evil in Debian. you may
23# know me from such debian-devel-announce gems as "Serious
24# Problems With ...."
26################################################################################
28import os
29import sys
30import time
31import apt_pkg
32import dak.examine_package
34from daklib import policy
35from daklib.dbconn import *
36from daklib.config import Config
37from daklib.dakmultiprocessing import DakProcessPool, PROC_STATUS_SUCCESS, PROC_STATUS_EXCEPTION
38from multiprocessing import Manager
40# Globals
41Cnf = None
42Options = None
43manager = Manager()
44sources = manager.list()
45htmlfiles_to_process = manager.list()
46timeout_str = "Error or timeout while processing"
49################################################################################
50################################################################################
51################################################################################
53def html_header(name, missing):
54 if name.endswith('.changes'): 54 ↛ 55line 54 didn't jump to line 55, because the condition on line 54 was never true
55 name = ' '.join(name.split('_')[:2])
56 result = """<!DOCTYPE html>
57<html lang="en">
58 <head>
59 <meta charset="utf-8">
60 <title>%(name)s - Debian NEW package overview</title>
61 <link rel="stylesheet" href="/style.css">
62 <link rel="shortcut icon" href="https://www.debian.org/favicon.ico">
63 <script>
64 function toggle(id, initial, display) {
65 var o = document.getElementById(id);
66 toggleObj(o, initial, display);
67 }
68 function show(id, display) {
69 var o = document.getElementById(id);
70 o.style.display = 'table-row-group';
71 }
72 function toggleObj(o, initial, display) {
73 if(! o.style.display)
74 o.style.display = initial;
75 if(o.style.display == display) {
76 o.style.display = "none";
77 } else {
78 o.style.display = display;
79 }
80 }
81 </script>
82 </head>
83 <body id="NEW-details-page">
84 <div id="logo">
85 <a href="https://www.debian.org/">
86 <img src="https://www.debian.org/logos/openlogo-nd-50.png"
87 alt=""></a>
88 <a href="https://www.debian.org/">
89 <img src="https://www.debian.org/Pics/debian.png"
90 alt="Debian Project"></a>
91 </div>
92 <div id="titleblock">
93 <img src="https://www.debian.org/Pics/red-upperleft.png"
94 id="red-upperleft" alt="">
95 <img src="https://www.debian.org/Pics/red-lowerleft.png"
96 id="red-lowerleft" alt="">
97 <img src="https://www.debian.org/Pics/red-upperright.png"
98 id="red-upperright" alt="">
99 <img src="https://www.debian.org/Pics/red-lowerright.png"
100 id="red-lowerright" alt="">
101 <span class="title">
102 Debian NEW package overview for %(name)s
103 </span>
104 </div>
106 """ % {"name": name}
108 # we assume only one source (.dsc) per changes here
109 result += """
110 <div id="menu">
111 <p class="title">Navigation</p>
112 <p><a href="#changes" onclick="show('changes-body')">.changes</a></p>
113 <p><a href="#dsc" onclick="show('dsc-body')">.dsc</a></p>
114 <p><a href="#source-lintian" onclick="show('source-lintian-body')">source lintian</a></p>
116"""
117 for binarytype, packagename in [m for m in missing if m[0] in ('deb', 'udeb')]:
118 result += """
119 <p class="subtitle">%(pkg)s</p>
120 <p><a href="#binary-%(pkg)s-control" onclick="show('binary-%(pkg)s-control-body')">control file</a></p>
121 <p><a href="#binary-%(pkg)s-lintian" onclick="show('binary-%(pkg)s-lintian-body')">binary lintian</a></p>
122 <p><a href="#binary-%(pkg)s-contents" onclick="show('binary-%(pkg)s-contents-body')">.deb contents</a></p>
123 <p><a href="#binary-%(pkg)s-copyright" onclick="show('binary-%(pkg)s-copyright-body')">copyright</a></p>
124 <p><a href="#binary-%(pkg)s-file-listing" onclick="show('binary-%(pkg)s-file-listing-body')">file listing</a></p>
126""" % {"pkg": packagename}
127 result += " </div>"
128 return result
131def html_footer():
132 result = """ <p class="validate">Timestamp: %s (UTC)</p>
133""" % (time.strftime("%d.%m.%Y / %H:%M:%S", time.gmtime()))
134 result += "</body></html>"
135 return result
137################################################################################
140def do_pkg(upload_id):
141 cnf = Config()
143 session = DBConn().session()
144 upload = session.query(PolicyQueueUpload).filter_by(id=upload_id).one()
146 queue = upload.policy_queue
147 changes = upload.changes
149 origchanges = os.path.join(queue.path, changes.changesname)
150 print(origchanges)
152 htmlname = "{0}_{1}.html".format(changes.source, changes.version)
153 htmlfile = os.path.join(cnf['Show-New::HTMLPath'], htmlname)
155 # Have we already processed this?
156 if os.path.exists(htmlfile) and \ 156 ↛ 158line 156 didn't jump to line 158, because the condition on line 156 was never true
157 os.stat(htmlfile).st_mtime > time.mktime(changes.created.timetuple()):
158 with open(htmlfile, "r") as fd:
159 if fd.read() != timeout_str:
160 sources.append(htmlname)
161 return (PROC_STATUS_SUCCESS,
162 '%s already up-to-date' % htmlfile)
164 # Go, process it... Now!
165 htmlfiles_to_process.append(htmlfile)
166 sources.append(htmlname)
168 group = cnf.get('Dinstall::UnprivGroup') or None
170 with open(htmlfile, 'w') as outfile, \
171 policy.UploadCopy(upload, group=group) as upload_copy:
172 handler = policy.PolicyQueueUploadHandler(upload, session)
173 missing = [(o['type'], o['package']) for o in handler.missing_overrides()]
174 distribution = changes.distribution
176 outfile.write(html_header(changes.source, missing))
177 outfile.write(dak.examine_package.display_changes(distribution, origchanges))
179 if upload.source is not None and ('dsc', upload.source.source) in missing: 179 ↛ 182line 179 didn't jump to line 182, because the condition on line 179 was never false
180 fn = os.path.join(upload_copy.directory, upload.source.poolfile.basename)
181 outfile.write(dak.examine_package.check_dsc(distribution, fn, session))
182 for binary in upload.binaries:
183 if (binary.binarytype, binary.package) not in missing: 183 ↛ 184line 183 didn't jump to line 184, because the condition on line 183 was never true
184 continue
185 fn = os.path.join(upload_copy.directory, binary.poolfile.basename)
186 outfile.write(dak.examine_package.check_deb(distribution, fn, session))
188 outfile.write(html_footer())
190 session.close()
191 htmlfiles_to_process.remove(htmlfile)
192 return (PROC_STATUS_SUCCESS, '{0} already updated'.format(htmlfile))
194################################################################################
197def usage(exit_code=0):
198 print("""Usage: dak show-new [OPTION]... [CHANGES]...
199 -h, --help show this help and exit.
200 -p, --html-path [path] override output directory.
201 """)
202 sys.exit(exit_code)
204################################################################################
207def init(session):
208 global cnf, Options
210 cnf = Config()
212 Arguments = [('h', "help", "Show-New::Options::Help"),
213 ("p", "html-path", "Show-New::HTMLPath", "HasArg"),
214 ('q', 'queue', 'Show-New::Options::Queue', 'HasArg')]
216 for i in ["help"]:
217 key = "Show-New::Options::%s" % i
218 if key not in cnf: 218 ↛ 216line 218 didn't jump to line 216, because the condition on line 218 was never false
219 cnf[key] = ""
221 changesnames = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv)
222 Options = cnf.subtree("Show-New::Options")
224 if Options["help"]:
225 usage()
227 queue_names = Options.find('Queue', 'new').split(',')
228 uploads = session.query(PolicyQueueUpload) \
229 .join(PolicyQueueUpload.policy_queue).filter(PolicyQueue.queue_name.in_(queue_names)) \
230 .join(PolicyQueueUpload.changes).order_by(DBChange.source)
232 if len(changesnames) > 0: 232 ↛ 233line 232 didn't jump to line 233, because the condition on line 232 was never true
233 uploads = uploads.filter(DBChange.changesname.in_(changesnames))
235 return uploads
238def result_callback(r):
239 code, msg = r
240 if code == PROC_STATUS_EXCEPTION: 240 ↛ 241line 240 didn't jump to line 241, because the condition on line 240 was never true
241 print("Job raised exception: %s" % (msg))
242 elif code != PROC_STATUS_SUCCESS: 242 ↛ 243line 242 didn't jump to line 243, because the condition on line 242 was never true
243 print("Job failed: %s" % (msg))
246################################################################################
247################################################################################
249def main():
250 dak.examine_package.use_html = True
251 pool = DakProcessPool(processes=5)
253 session = DBConn().session()
254 upload_ids = [u.id for u in init(session)]
255 session.close()
257 for upload_id in upload_ids:
258 pool.apply_async(do_pkg, [upload_id], callback=result_callback)
259 pool.close()
261 pool.join()
263 for htmlfile in htmlfiles_to_process: 263 ↛ 264line 263 didn't jump to line 264, because the loop on line 263 never started
264 with open(htmlfile, "w") as fd:
265 fd.write(timeout_str)
267 if pool.overall_status() != PROC_STATUS_SUCCESS: 267 ↛ 268line 267 didn't jump to line 268, because the condition on line 267 was never true
268 raise Exception("Processing failed (code %s)" % (pool.overall_status()))
270 files = set(os.listdir(cnf["Show-New::HTMLPath"]))
271 to_delete = [x for x in files.difference(set(sources)) if x.endswith(".html")]
272 for f in to_delete:
273 os.remove(os.path.join(cnf["Show-New::HTMLPath"], f))
275################################################################################
278if __name__ == '__main__':
279 main()