X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=dak%2Fexamine_package.py;h=5080d3482b3876e6f4de6297769a83f19aa6ccd6;hb=969f96350310474d777d4aa804e38ed96a41bd77;hp=48163156614f54e740c46ba39d9f390a98460e22;hpb=9e8be31466d5673f0391c8eb13a40969a371308d;p=dak.git
diff --git a/dak/examine_package.py b/dak/examine_package.py
old mode 100755
new mode 100644
index 48163156..5080d348
--- a/dak/examine_package.py
+++ b/dak/examine_package.py
@@ -34,7 +34,7 @@
import errno, os, pg, re, sys, md5
import apt_pkg, apt_inst
-import daklib.database, daklib.utils
+import daklib.database, daklib.utils, daklib.queue
################################################################################
@@ -54,24 +54,8 @@ re_version = re.compile('^(.*)\((.*)\)')
re_newlinespace = re.compile('\n')
re_spacestrip = re.compile('(\s)')
-################################################################################
-
-# Colour definitions
-
-# Main
-main_colour = "\033[36m"
-# Contrib
-contrib_colour = "\033[33m"
-# Non-Free
-nonfree_colour = "\033[31m"
-# Arch
-arch_colour = "\033[32m"
-# End
-end_colour = "\033[0m"
-# Bold
-bold_colour = "\033[1m"
-# Bad maintainer
-maintainer_colour = arch_colour
+html_escaping = {'"':'"', '&':'&', '<':'<', '>':'>'}
+re_html_escaping = re.compile('|'.join(map(re.escape, html_escaping.keys())))
################################################################################
@@ -84,6 +68,9 @@ daklib.database.init(Cnf, projectB)
printed_copyrights = {}
+# default is to not output html.
+use_html = 0
+
################################################################################
def usage (exit_code=0):
@@ -91,19 +78,76 @@ def usage (exit_code=0):
Check NEW package(s).
-h, --help show this help and exit
+ -H, --html-output output html page with inspection result
+ -f, --file-name filename for the html page
PACKAGE can be a .changes, .dsc, .deb or .udeb filename."""
sys.exit(exit_code)
+################################################################################
+# probably xml.sax.saxutils would work as well
+
+def html_escape(s):
+ return re_html_escaping.sub(lambda x: html_escaping.get(x.group(0)), s)
+
+def escape_if_needed(s):
+ if use_html:
+ return re_html_escaping.sub(html_escaping.get, s)
+ else:
+ return s
+
+def headline(s, level=2):
+ if use_html:
+ print "
%s" % (s) + else: + print s + +def print_formatted_text(s): + if use_html: + print "
%s" % (html_escape(s)) + else: + print s + ################################################################################ def get_depends_parts(depend) : v_match = re_version.match(depend) if v_match: - d_parts = { 'name' : v_match.group(1), 'version' : v_match.group(2) } + d_parts = { 'name' : v_match.group(1), 'version' : v_match.group(2) } else : - d_parts = { 'name' : depend , 'version' : '' } + d_parts = { 'name' : depend , 'version' : '' } return d_parts def get_or_list(depend) : @@ -123,19 +167,19 @@ def split_depends (d_str) : dep_list = get_comma_list(d_str) d = 0 while d < len(dep_list): - # put depends into their own list - depends_tree.append([dep_list[d]]) - d += 1 + # put depends into their own list + depends_tree.append([dep_list[d]]) + d += 1 d = 0 while d < len(depends_tree): - k = 0 - # split up Or'd depends into a multi-item list - depends_tree[d] = get_or_list(depends_tree[d][0]) - while k < len(depends_tree[d]): - # split depends into {package, version relation} - depends_tree[d][k] = get_depends_parts(depends_tree[d][k]) - k += 1 - d += 1 + k = 0 + # split up Or'd depends into a multi-item list + depends_tree[d] = get_or_list(depends_tree[d][0]) + while k < len(depends_tree[d]): + # split depends into {package, version relation} + depends_tree[d][k] = get_depends_parts(depends_tree[d][k]) + k += 1 + d += 1 return depends_tree def read_control (filename): @@ -147,49 +191,52 @@ def read_control (filename): deb_file = daklib.utils.open_file(filename) try: - extracts = apt_inst.debExtractControl(deb_file) - control = apt_pkg.ParseSection(extracts) + extracts = apt_inst.debExtractControl(deb_file) + control = apt_pkg.ParseSection(extracts) except: - print "can't parse control info" - control = '' + print_formatted_text("can't parse control info") + # TV-COMMENT: this will raise exceptions in two lines + control = '' deb_file.close() control_keys = control.keys() if control.has_key("Depends"): - depends_str = control.Find("Depends") - # create list of dependancy lists - depends = split_depends(depends_str) + depends_str = control.Find("Depends") + # create list of dependancy lists + depends = split_depends(depends_str) if control.has_key("Recommends"): - recommends_str = control.Find("Recommends") - recommends = split_depends(recommends_str) + recommends_str = control.Find("Recommends") + recommends = split_depends(recommends_str) if control.has_key("Section"): - section_str = control.Find("Section") - - c_match = re_contrib.search(section_str) - nf_match = re_nonfree.search(section_str) - if c_match : - # contrib colour - section = contrib_colour + section_str + end_colour - elif nf_match : - # non-free colour - section = nonfree_colour + section_str + end_colour - else : - # main - section = main_colour + section_str + end_colour + section_str = control.Find("Section") + + c_match = re_contrib.search(section_str) + nf_match = re_nonfree.search(section_str) + if c_match : + # contrib colour + section = colour_output(section_str, 'contrib') + elif nf_match : + # non-free colour + section = colour_output(section_str, 'nonfree') + else : + # main + section = colour_output(section_str, 'main') if control.has_key("Architecture"): - arch_str = control.Find("Architecture") - arch = arch_colour + arch_str + end_colour + arch_str = control.Find("Architecture") + arch = colour_output(arch_str, 'arch') if control.has_key("Maintainer"): - maintainer = control.Find("Maintainer") - localhost = re_localhost.search(maintainer) - if localhost: - #highlight bad email - maintainer = maintainer_colour + maintainer + end_colour + maintainer = control.Find("Maintainer") + localhost = re_localhost.search(maintainer) + if localhost: + #highlight bad email + maintainer = colour_output(maintainer, 'maintainer') + else: + maintainer = escape_if_needed(maintainer) return (control, control_keys, section, depends, recommends, arch, maintainer) @@ -198,26 +245,26 @@ def read_dsc (dsc_filename): dsc_file = daklib.utils.open_file(dsc_filename) try: - dsc = daklib.utils.parse_changes(dsc_filename) + dsc = daklib.utils.parse_changes(dsc_filename) except: - print "can't parse control info" + print_formatted_text("can't parse control info") dsc_file.close() - filecontents = strip_pgp_signature(dsc_filename) + filecontents = escape_if_needed(strip_pgp_signature(dsc_filename)) if dsc.has_key("build-depends"): - builddep = split_depends(dsc["build-depends"]) - builddepstr = create_depends_string(builddep) - filecontents = re_builddep.sub("Build-Depends: "+builddepstr, filecontents) + builddep = split_depends(dsc["build-depends"]) + builddepstr = create_depends_string(builddep) + filecontents = re_builddep.sub("Build-Depends: "+builddepstr, filecontents) if dsc.has_key("build-depends-indep"): - builddepindstr = create_depends_string(split_depends(dsc["build-depends-indep"])) - filecontents = re_builddepind.sub("Build-Depends-Indep: "+builddepindstr, filecontents) + builddepindstr = create_depends_string(split_depends(dsc["build-depends-indep"])) + filecontents = re_builddepind.sub("Build-Depends-Indep: "+builddepindstr, filecontents) if dsc.has_key("architecture") : - if (dsc["architecture"] != "any"): - newarch = arch_colour + dsc["architecture"] + end_colour - filecontents = re_arch.sub("Architecture: " + newarch, filecontents) + if (dsc["architecture"] != "any"): + newarch = colour_output(dsc["architecture"], 'arch') + filecontents = re_arch.sub("Architecture: " + newarch, filecontents) return filecontents @@ -227,67 +274,78 @@ def create_depends_string (depends_tree): result = "" comma_count = 1 for l in depends_tree: - if (comma_count >= 2): - result += ", " - or_count = 1 - for d in l: - if (or_count >= 2 ): - result += " | " - # doesn't do version lookup yet. - - q = projectB.query("SELECT DISTINCT(b.package), b.version, c.name, su.suite_name FROM binaries b, files fi, location l, component c, bin_associations ba, suite su WHERE b.package='%s' AND b.file = fi.id AND fi.location = l.id AND l.component = c.id AND ba.bin=b.id AND ba.suite = su.id AND su.suite_name='%s' ORDER BY b.version desc" % (d['name'], suite)) - ql = q.getresult() - if ql: - i = ql[0] - - if i[2] == "contrib": - result += contrib_colour + d['name'] - elif i[2] == "non-free": - result += nonfree_colour + d['name'] - else : - result += main_colour + d['name'] - - if d['version'] != '' : - result += " (%s)" % (d['version']) - result += end_colour - else: - result += bold_colour + d['name'] - if d['version'] != '' : - result += " (%s)" % (d['version']) - result += end_colour - or_count += 1 - comma_count += 1 + if (comma_count >= 2): + result += ", " + or_count = 1 + for d in l: + if (or_count >= 2 ): + result += " | " + # doesn't do version lookup yet. + + q = projectB.query("SELECT DISTINCT(b.package), b.version, c.name, su.suite_name FROM binaries b, files fi, location l, component c, bin_associations ba, suite su WHERE b.package='%s' AND b.file = fi.id AND fi.location = l.id AND l.component = c.id AND ba.bin=b.id AND ba.suite = su.id AND su.suite_name='%s' ORDER BY b.version desc" % (d['name'], suite)) + ql = q.getresult() + if ql: + i = ql[0] + + adepends = d['name'] + if d['version'] != '' : + adepends += " (%s)" % (d['version']) + + if i[2] == "contrib": + result += colour_output(adepends, "contrib") + elif i[2] == "non-free": + result += colour_output(adepends, "nonfree") + else : + result += colour_output(adepends, "main") + else: + adepends = d['name'] + if d['version'] != '' : + adepends += " (%s)" % (d['version']) + result += colour_output(adepends, "bold") + or_count += 1 + comma_count += 1 return result def output_deb_info(filename): (control, control_keys, section, depends, recommends, arch, maintainer) = read_control(filename) + to_print = "" if control == '': - print "no control info" + print_formatted_text("no control info") else: - for key in control_keys : - output = " " + key + ": " - if key == 'Depends': - output += create_depends_string(depends) - elif key == 'Recommends': - output += create_depends_string(recommends) - elif key == 'Section': - output += section - elif key == 'Architecture': - output += arch - elif key == 'Maintainer': - output += maintainer - elif key == 'Description': - desc = control.Find(key) - desc = re_newlinespace.sub('\n ', desc) - output += desc - else: - output += control.Find(key) - print output - -def do_command (command, filename): + for key in control_keys : + output = " " + key + ": " + if key == 'Depends': + output += create_depends_string(depends) + elif key == 'Recommends': + output += create_depends_string(recommends) + elif key == 'Section': + output += section + elif key == 'Architecture': + output += arch + elif key == 'Maintainer': + output += maintainer + elif key == 'Description': + desc = control.Find(key) + desc = re_newlinespace.sub('\n ', desc) + output += escape_if_needed(desc) + else: + output += escape_if_needed(control.Find(key)) + to_print += output + '\n' + print_escaped_text(to_print) + +def do_command (command, filename, escaped=0): o = os.popen("%s %s" % (command, filename)) - print o.read() + if escaped: + print_escaped_text(o.read()) + else: + print_formatted_text(o.read()) + +def do_lintian (filename): + if use_html: + do_command("lintian --show-overrides --color html", filename, 1) + else: + do_command("lintian --show-overrides --color always", filename, 1) def print_copyright (deb_filename): package = re_package.sub(r'\1', deb_filename) @@ -295,64 +353,62 @@ def print_copyright (deb_filename): copyright = o.read()[:-1] if copyright == "": - print "WARNING: No copyright found, please check package manually." + print_formatted_text("WARNING: No copyright found, please check package manually.") return doc_directory = re_doc_directory.sub(r'\1', copyright) if package != doc_directory: - print "WARNING: wrong doc directory (expected %s, got %s)." % (package, doc_directory) + print_formatted_text("WARNING: wrong doc directory (expected %s, got %s)." % (package, doc_directory)) return - o = os.popen("dpkg-deb --fsys-tarfile %s | tar xvOf - %s" % (deb_filename, copyright)) + o = os.popen("dpkg-deb --fsys-tarfile %s | tar xvOf - %s 2>/dev/null" % (deb_filename, copyright)) copyright = o.read() copyrightmd5 = md5.md5(copyright).hexdigest() if printed_copyrights.has_key(copyrightmd5) and printed_copyrights[copyrightmd5] != "%s (%s)" % (package, deb_filename): - print "NOTE: Copyright is the same as %s.\n" % \ - (printed_copyrights[copyrightmd5]) + print_formatted_text( "NOTE: Copyright is the same as %s.\n" % \ + (printed_copyrights[copyrightmd5])) else: - printed_copyrights[copyrightmd5] = "%s (%s)" % (package, deb_filename) + printed_copyrights[copyrightmd5] = "%s (%s)" % (package, deb_filename) - print copyright + print_formatted_text(copyright) def check_dsc (dsc_filename): - print "---- .dsc file for %s ----" % (dsc_filename) + headline(".dsc file for %s" % (dsc_filename)) (dsc) = read_dsc(dsc_filename) - print dsc - print "---- lintian check for %s ----" % (dsc_filename) - do_command ("lintian --show-overrides --color always", dsc_filename) + print_escaped_text(dsc) + headline("lintian check for %s" % (dsc_filename)) + do_lintian(dsc_filename) def check_deb (deb_filename): filename = os.path.basename(deb_filename) if filename.endswith(".udeb"): - is_a_udeb = 1 + is_a_udeb = 1 else: - is_a_udeb = 0 + is_a_udeb = 0 - print "---- control file for %s ----" % (filename) + headline("control file for %s" % (filename)) #do_command ("dpkg -I", deb_filename) output_deb_info(deb_filename) if is_a_udeb: - print "---- skipping lintian check for udeb ----" - print + headline("skipping lintian check for udeb") + print else: - print "---- lintian check for %s ----" % (filename) - do_command ("lintian --show-overrides --color always", deb_filename) - print "---- linda check for %s ----" % (filename) - do_command ("linda", deb_filename) + headline("lintian check for %s" % (filename)) + do_lintian(deb_filename) - print "---- contents of %s ----" % (filename) + headline("contents of %s" % (filename)) do_command ("dpkg -c", deb_filename) if is_a_udeb: - print "---- skipping copyright for udeb ----" + headline("skipping copyright for udeb") else: - print "---- copyright of %s ----" % (filename) + headline("copyright of %s" % (filename)) print_copyright(deb_filename) - print "---- file listing of %s ----" % (filename) + headline("file listing of %s" % (filename)) do_command ("ls -l", deb_filename) # Read a file, strip the signature and return the modified contents as @@ -379,14 +435,14 @@ def strip_pgp_signature (filename): if line.startswith("-----END PGP SIGNATURE"): inside_signature = 0 continue - contents += line + contents += line file.close() return contents # Display the .changes [without the signature] def display_changes (changes_filename): - print "---- .changes file for %s ----" % (changes_filename) - print strip_pgp_signature(changes_filename) + headline(".changes file for %s" % (changes_filename)) + print_formatted_text(strip_pgp_signature(changes_filename)) def check_changes (changes_filename): display_changes(changes_filename) @@ -394,8 +450,8 @@ def check_changes (changes_filename): changes = daklib.utils.parse_changes (changes_filename) files = daklib.utils.build_file_list(changes) for file in files.keys(): - if file.endswith(".deb") or file.endswith(".udeb"): - check_deb(file) + if file.endswith(".deb") or file.endswith(".udeb"): + check_deb(file) if file.endswith(".dsc"): check_dsc(file) # else: => byhand @@ -405,26 +461,28 @@ def main (): # Cnf = daklib.utils.get_conf() - Arguments = [('h',"help","Examine-Package::Options::Help")] - for i in [ "help" ]: - if not Cnf.has_key("Frenanda::Options::%s" % (i)): - Cnf["Examine-Package::Options::%s" % (i)] = "" + Arguments = [('h',"help","Examine-Package::Options::Help"), + ('H',"html-output","Examine-Package::Options::Html-Output"), + ] + for i in [ "Help", "Html-Output", "partial-html" ]: + if not Cnf.has_key("Examine-Package::Options::%s" % (i)): + Cnf["Examine-Package::Options::%s" % (i)] = "" args = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv) Options = Cnf.SubTree("Examine-Package::Options") if Options["Help"]: - usage() + usage() stdout_fd = sys.stdout for file in args: try: - # Pipe output for each argument through less - less_fd = os.popen("less -R -", 'w', 0) - # -R added to display raw control chars for colour - sys.stdout = less_fd - + if not Options["Html-Output"]: + # Pipe output for each argument through less + less_fd = os.popen("less -R -", 'w', 0) + # -R added to display raw control chars for colour + sys.stdout = less_fd try: if file.endswith(".changes"): check_changes(file) @@ -435,9 +493,10 @@ def main (): else: daklib.utils.fubar("Unrecognised file type: '%s'." % (file)) finally: - # Reset stdout here so future less invocations aren't FUBAR - less_fd.close() - sys.stdout = stdout_fd + if not Options["Html-Output"]: + # Reset stdout here so future less invocations aren't FUBAR + less_fd.close() + sys.stdout = stdout_fd except IOError, e: if errno.errorcode[e.errno] == 'EPIPE': daklib.utils.warn("[examine-package] Caught EPIPE; skipping.") @@ -452,4 +511,3 @@ def main (): if __name__ == '__main__': main() -