summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authordann frazier <dannf@debian.org>2006-08-17 00:30:54 +0000
committerdann frazier <dannf@debian.org>2006-08-17 00:30:54 +0000
commit83af1b5d5c8f7e018a003469f86f711158deb252 (patch)
tree1f0a82c943f1f2d1b8ac70f1c56631591208ac23 /scripts
parent8a0c0175a017301b997cfa0a8fc67b2f0888cf4c (diff)
while i'm reorganizing, might as well move the scripts & dsa-texts
out of the active issues directory ok - should be done for now - let me know if you'd prefer a different organization git-svn-id: svn+ssh://svn.debian.org/svn/kernel-sec@551 e094ebfe-e918-0410-adfb-c712417f3574
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/deb822.py182
-rwxr-xr-xscripts/html-report160
-rwxr-xr-xscripts/sync-pkg-list32
-rwxr-xr-xscripts/ubuntu-todo2
-rwxr-xr-xscripts/verify-report.pl70
5 files changed, 446 insertions, 0 deletions
diff --git a/scripts/deb822.py b/scripts/deb822.py
new file mode 100755
index 00000000..a6432cc5
--- /dev/null
+++ b/scripts/deb822.py
@@ -0,0 +1,182 @@
+#!/usr/bin/python
+
+## Version: 0.20051107
+
+import re, string
+
+class deb822:
+ def __init__(self, fp):
+ self.map = {}
+ self.keys = []
+ single = re.compile("^(?P<key>\S+):\s+(?P<data>\S.*)$")
+ multi = re.compile("^(?P<key>\S+):\s*$")
+ multidata = re.compile("^\s(?P<data>.*)$")
+ ws = re.compile("^\s*$")
+
+ curkey = None
+ content = ""
+ for line in fp.readlines():
+ if ws.match(line):
+ if curkey:
+ self.map[curkey] = content[:-1]
+ curkey = None
+ content = ""
+ continue
+
+ m = single.match(line)
+ if m:
+ if curkey:
+ self.map[curkey] = content[:-1]
+ curkey = m.group('key')
+ self.keys.append(curkey)
+ self.map[curkey] = m.group('data')
+ curkey = None
+ content = ""
+ continue
+
+ m = multi.match(line)
+ if m:
+ if curkey:
+ self.map[curkey] = content[:-1]
+ curkey = m.group('key')
+ self.keys.append(curkey)
+ content = "\n"
+ continue
+
+ m = multidata.match(line)
+ if m:
+ content = content + line
+ continue
+
+ if curkey:
+ self.map[curkey] = content[:-1]
+
+ def dump(self, fd):
+ for key in self.keys:
+ fd.write(key + ": " + self.map[key] + "\n")
+
+ def isSingleLine(self, s):
+ if s.count("\n"):
+ return False
+ else:
+ return True
+
+ def isMultiLine(self, s):
+ return not self.isSingleLine(s)
+
+ def _mergeFields(self, s1, s2):
+ if not s2:
+ return s1
+ if not s1:
+ return s2
+
+ if self.isSingleLine(s1) and self.isSingleLine(s2):
+ ## some fields are delimited by a single space, others
+ ## a comma followed by a space. this heuristic assumes
+ ## that there are multiple items in one of the string fields
+ ## so that we can pick up on the delimiter being used
+ delim = ' '
+ if (s1 + s2).count(', '):
+ delim = ', '
+
+ L = (s1 + delim + s2).split(delim)
+ L.sort()
+
+ prev = merged = L[0]
+
+ for item in L[1:]:
+ ## skip duplicate entries
+ if item == prev:
+ continue
+ merged = merged + delim + item
+ prev = item
+ return merged
+
+ if self.isMultiLine(s1) and self.isMultiLine(s2):
+ for item in s2.splitlines(True):
+ if item not in s1.splitlines(True):
+ s1 = s1 + "\n" + item
+ return s1
+
+ raise ValueError
+
+ def mergeFields(self, key, d1, d2 = None):
+ ## this method can work in two ways - abstract that away
+ if d2 == None:
+ x1 = self
+ x2 = d1
+ else:
+ x1 = d1
+ x2 = d2
+
+ ## we only have to do work if both objects contain our key
+ ## otherwise, we just take the one that does, or raise an
+ ## exception if neither does
+ if key in x1.keys and key in x1.keys:
+ merged = self._mergeFields(x1.map[key], x2.map[key])
+ elif key in x1.keys:
+ merged = x1[key]
+ elif key in x2.keys:
+ merged = x2[key]
+ else:
+ raise KeyError
+
+ ## back to the two different ways - if this method was called
+ ## upon an object, update that object in place.
+ ## return nothing in this case, to make the author notice a
+ ## problem if she assumes the object itself will not be modified
+ if d2 == None:
+ self.map[key] = merged
+ return None
+
+ return merged
+
+ def hasField(self, key):
+ if key in self.keys:
+ return True
+ return False
+
+ def addField(self, key, value):
+ if key in self.keys:
+ ## key is already there
+ raise KeyError
+ else:
+ self.keys.append(key)
+ self.map[key] = value
+
+## methods that changes and dsc files have in common
+class _dscchanges(deb822):
+ """A base class; not intended for direct use"""
+
+## Specialty class for dealing with .dsc files
+class dsc(_dscchanges):
+ def files(self):
+ fileList = []
+
+ for fileEntry in self.map["Files"].splitlines():
+ file = {}
+ if fileEntry:
+ fields = fileEntry.split()
+ file["md5sum"] = fields[0]
+ file["size"] = fields[1]
+ file["name"] = fields[2]
+ fileList.append(file)
+
+ return fileList
+
+class changes(_dscchanges):
+ def files(self):
+ fileList = []
+
+ for fileEntry in self.map["Files"].splitlines():
+ file = {}
+ if fileEntry:
+ fields = fileEntry.split()
+ file["md5sum"] = fields[0]
+ file["size"] = fields[1]
+ file["section"] = fields[2]
+ file["priority"] = fields[3]
+ file["name"] = fields[4]
+ fileList.append(file)
+
+ return fileList
diff --git a/scripts/html-report b/scripts/html-report
new file mode 100755
index 00000000..38ca25e5
--- /dev/null
+++ b/scripts/html-report
@@ -0,0 +1,160 @@
+#!/usr/bin/python2.4
+
+import os, os.path, sys
+import deb822, re
+
+TrackerDir = ".."
+
+## get an unsorted list of tracked issues
+def trackedIssues(dir):
+ ignores = [ re.compile('~$'),
+ re.compile('^#.*#$'),
+ re.compile('^00'),
+ re.compile('\.patch$')]
+
+ validpaths = []
+ for f in os.listdir(dir):
+ nogood = False
+ for i in ignores:
+ if i.search(f):
+ nogood = True
+ break
+ if nogood:
+ continue
+ else:
+ validpaths.append(f)
+
+ issues = []
+ for f in validpaths:
+ path = os.path.join(dir, f)
+ if os.path.isfile(path):
+ issues.append(f)
+ return issues
+
+def trackedVersions(dir):
+ pkglist = os.path.join(dir, '00pkglist')
+ f = open(pkglist, 'r')
+ return f.read().split('\n')[:-1]
+
+def issueStatus(issue, version):
+ path = os.path.join(TrackerDir, issue)
+ i = deb822.deb822(open(path, 'r'))
+ if i.hasField(version):
+ return i.map[version]
+ else:
+ return None
+
+def statusMatrix(issues, versions):
+ Di = {}
+ for i in issues:
+ Dv = {}
+ for v in versions:
+ Dv[v] = issueStatus(i, v)
+ Di[i] = Dv
+ return Di
+
+## remaining functions create the HTML
+def htmlHeader():
+ sys.stdout.write('<html>\n')
+ sys.stdout.write('<head>\n')
+ sys.stdout.write(' <title>Debian Kernel Patch Tracker Status</title>\n')
+ sys.stdout.write('</head>\n')
+ sys.stdout.write('<body>\n')
+ sys.stdout.write('<h1><center>Debian Kernel Patch Tracker Status</center></h1>')
+ key = '''
+ <table border=1>
+ <tr>
+ <td>Key</td>
+ </tr>
+ <tr>
+ <td bgcolor="green">Fixed or N/A - version is listed if specified</td>
+ </tr>
+ <tr>
+ <td bgcolor="lightgreen">Pending - version is listed if specified</td>
+ </tr>
+ <tr>
+ <td bgcolor="yellow">Needed</td>
+ </tr>
+ <tr>
+ <td bgcolor="orange">Ignored for a reason</td>
+ </tr>
+ </table>'''
+ sys.stdout.write(key)
+ sys.stdout.write('<BR>\n')
+
+
+def htmlFooter():
+ sys.stdout.write(' </body>\n')
+ sys.stdout.write('</html>\n')
+
+def tableHeader(columns):
+ ## populateTable() will assume columns should be filled out
+ ## in sort() order, so make sure our column names match
+ columns.sort()
+ sys.stdout.write("<table border=1>\n")
+ sys.stdout.write(" <tr>\n")
+ sys.stdout.write(" <td> </td>\n")
+ for c in columns:
+ sys.stdout.write(" <td>"+c+"</td>\n")
+ sys.stdout.write(" </tr>\n")
+
+def tableFooter():
+ sys.stdout.write("</table>\n")
+
+## Parse a status string, and return an html table entry
+def statusCell(status):
+ if not status:
+ return '<td color="grey">Unknown</td>'
+
+ statusRe = re.compile("(?P<status>\S+)(\s*\((?P<ver>.*)\))?(\s*\[(?P<name>.*)\])?$")
+
+ m = statusRe.match(status)
+ if m:
+ d = m.groupdict()
+ ver = name = ""
+ if d.has_key('ver') and d['ver']:
+ ver = d['ver']
+ if d.has_key('name') and d['name']:
+ name = d['name']
+
+ if d['status'] == 'N/A':
+ return '<td bgcolor="green">N/A</td>'
+ elif d['status'] == "released":
+ return '<td bgcolor="green">' + ver + '</td>'
+ elif d['status'] == "pending":
+ return '<td bgcolor="lightgreen">' + ver + '</td>'
+ elif d['status'] == "needed":
+ return '<td bgcolor="yellow">' + ver + '</td>'
+ elif d['status'] == "ignored":
+ return '<td bgcolor="orange">' + ver + '</td>'
+ else:
+ return '<td bgcolor="grey">Unknown</td>'
+
+def populateTable(matrix):
+ issues = matrix.keys()
+ issues.sort()
+
+ for i in issues:
+ versions = matrix[i].keys()
+ versions.sort()
+ sys.stdout.write(' <tr>\n')
+ sys.stdout.write(' <td>' + i + '</td>\n')
+ for v in versions:
+ cell = statusCell(matrix[i][v].strip())
+ if cell:
+ sys.stdout.write(cell)
+ else:
+ sys.stderr.write("Error in field: " + i + ", " + v + "\n")
+ sys.stdout.write(' </tr>\n')
+
+if __name__ == '__main__':
+ ## Doing this in a separate stage means some unnecessary duplicate
+ ## opens & closes... but oh well - our data set isn't very large
+ issues = trackedIssues(TrackerDir)
+ versions = trackedVersions(TrackerDir)
+
+ htmlHeader()
+ tableHeader(versions)
+ populateTable(statusMatrix(issues, versions))
+ tableFooter()
+ htmlFooter()
diff --git a/scripts/sync-pkg-list b/scripts/sync-pkg-list
new file mode 100755
index 00000000..7702f6e9
--- /dev/null
+++ b/scripts/sync-pkg-list
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+
+import sys
+import deb822
+from optparse import OptionParser
+
+if __name__ == '__main__':
+ parser = OptionParser()
+ parser.add_option("-p", "--pkglist", dest="pkglist",
+ help="File containing list of packages being tracked",
+ metavar="PACKAGELIST")
+ (options, args) = parser.parse_args()
+
+ if not options.pkglist:
+ sys.stderr.write("A package list must be specified, see --help")
+ sys.exit(1)
+
+ f = open(options.pkglist, 'r')
+ pkglist = f.read().split()
+ f.close()
+
+ for file in args:
+ f = open(file, 'r')
+ d = deb822.deb822(f)
+ f.close
+ for pkg in pkglist:
+ if not d.hasField(pkg):
+ d.addField(pkg, "")
+ f = open(file, 'w')
+ d.dump(f)
+ f.close()
+
diff --git a/scripts/ubuntu-todo b/scripts/ubuntu-todo
new file mode 100755
index 00000000..a8f5c439
--- /dev/null
+++ b/scripts/ubuntu-todo
@@ -0,0 +1,2 @@
+#!/bin/sh -e
+egrep '(hoary|breezy|dapper|edgy).*(needed|pending)' *
diff --git a/scripts/verify-report.pl b/scripts/verify-report.pl
new file mode 100755
index 00000000..b810b9c7
--- /dev/null
+++ b/scripts/verify-report.pl
@@ -0,0 +1,70 @@
+#!/usr/bin/perl -w
+# Analyse patch-tracker entries
+# Problems reported to stderr
+# Suggested entrie printed to stdout
+# Must be run in directory with patch-tracker entries
+#
+# (C) 2006 Horms <horms@verge.net.au>
+# Released under the terms of the GNU GPL v2
+
+use strict;
+
+my $BOILERPLATE = "00boilerplate";
+
+sub readfile {
+ my ($file) = (@_);
+ my $l = [];
+ my $h = {};
+ my $key = undef;
+
+ open BP, "<$file" or die "Could not open \"$file\" for reading\n";
+ while (<BP>) {
+ if (m/(^[a-zA-Z0-9.-]+:)(.*)/ and $1 ne "http:") {
+ $key = $1;
+ push @$l , $1;
+ $h->{"$1"} = $2 . "\n";
+ }
+ elsif (defined $key) {
+ $h->{"$key"} .= $_;
+ }
+ else {
+ print STDERR "Leading crap: $_";
+ }
+ }
+ close BP;
+
+ return ($l, $h);
+}
+
+{
+ my $bp_l;
+ my $bp_h;
+ my $l;
+ my $h;
+
+ ($bp_l, $bp_h) = readfile($BOILERPLATE);
+
+ foreach my $f (@ARGV) {
+ ($l, $h) = readfile($f);
+ my $log_p = (scalar @ARGV > 1) ? "$f: " : "";
+ for my $i (@$bp_l) {
+ if (defined $h->{"$i"}) {
+ print $i . $h->{"$i"};
+ delete $h->{"$i"};
+ }
+ else {
+ print STDERR $log_p . "Missing Field: \"$i\"\n";
+ print $i . " XXX\n";
+ }
+ }
+ for my $i (keys %$h) {
+ print STDERR $log_p . "Extra Feild: \"$i\"\n";
+ if (defined $h->{"$i"}) {
+ print $i . $h->{"$i"};
+ }
+ else {
+ print $i . " XXX\n";
+ }
+ }
+ }
+}

© 2014-2024 Faster IT GmbH | imprint | privacy policy