]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update20.py
Start the known_changes table
[dak.git] / dak / dakdb / update20.py
1 #!/usr/bin/env python
2 # coding=utf8
3
4 """
5 Adding table to get rid of queue/done checks
6
7 @contact: Debian FTP Master <ftpmaster@debian.org>
8 @copyright: 2009  Joerg Jaspert <joerg@debian.org>
9 @license: GNU General Public License version 2 or later
10 """
11
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
16
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
26 ################################################################################
27
28
29 ################################################################################
30
31 import psycopg2
32 import time
33 import os
34 import datetime
35 from daklib.dak_exceptions import DBUpdateError, InvalidDscError, ChangesUnicodeError
36 from daklib.config import Config
37 from daklib.utils import parse_changes, warn, gpgv_get_status_output, process_gpgv_output
38
39 ################################################################################
40
41 def check_signature (sig_filename, data_filename=""):
42     keyrings = [
43         "/home/joerg/keyring/keyrings/debian-keyring.gpg",
44         "/home/joerg/keyring/keyrings/debian-keyring.pgp",
45         "/home/joerg/keyring/keyrings/debian-maintainers.gpg",
46         "/home/joerg/keyring/keyrings/debian-role-keys.gpg",
47         "/home/joerg/keyring/keyrings/emeritus-keyring.pgp",
48         "/home/joerg/keyring/keyrings/emeritus-keyring.gpg",
49         "/home/joerg/keyring/keyrings/removed-keys.gpg",
50         "/home/joerg/keyring/keyrings/removed-keys.pgp"
51         ]
52
53     keyringargs = " ".join(["--keyring %s" % x for x in keyrings ])
54
55     # Build the command line
56     status_read, status_write = os.pipe()
57     cmd = "gpgv --status-fd %s %s %s" % (status_write, keyringargs, sig_filename)
58
59     # Invoke gpgv on the file
60     (output, status, exit_status) = gpgv_get_status_output(cmd, status_read, status_write)
61
62     # Process the status-fd output
63     (keywords, internal_error) = process_gpgv_output(status)
64
65     # If we failed to parse the status-fd output, let's just whine and bail now
66     if internal_error:
67         warn("Couldn't parse signature")
68         return (None, rejects)
69
70     # usually one would check for bad things here. We, however, do not care.
71
72     # Next check gpgv exited with a zero return code
73     if exit_status:
74         warn("Couldn't parse signature")
75         return (None, rejects)
76
77     # Sanity check the good stuff we expect
78     if not keywords.has_key("VALIDSIG"):
79         warn("Couldn't parse signature")
80     else:
81         args = keywords["VALIDSIG"]
82         if len(args) < 1:
83             warn("Couldn't parse signature")
84         else:
85             fingerprint = args[0]
86
87     return (fingerprint, [])
88
89 ################################################################################
90
91 def do_update(self):
92     print "Adding known_changes table"
93
94     try:
95         c = self.db.cursor()
96         c.execute("""
97                     CREATE TABLE known_changes (
98                     id SERIAL PRIMARY KEY,
99                     changesname TEXT NOT NULL,
100                     seen TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(),
101                     source TEXT NOT NULL,
102                     binaries TEXT NOT NULL,
103                     architecture TEXT NOT NULL,
104                     version TEXT NOT NULL,
105                     distribution TEXT NOT NULL,
106                     urgency TEXT NOT NULL,
107                     maintainer TEXT NOT NULL,
108                     changedby TEXT NOT NULL,
109                     date TEXT NOT NULL,
110                     UNIQUE (changesname)
111             )
112         """)
113         c.execute("CREATE INDEX changesname_ind ON known_changes(changesname)")
114         c.execute("CREATE INDEX changestimestamp_ind ON known_changes(seen)")
115         c.execute("CREATE INDEX changessource_ind ON known_changes(source)")
116         c.execute("CREATE INDEX changesdistribution_ind ON known_changes(distribution)")
117         c.execute("CREATE INDEX changesurgency_ind ON known_changes(urgency)")
118
119         print "Done. Now looking for old changes files"
120         count = 0
121         failure = 0
122         cnf = Config()
123         for directory in [ "Accepted", "Byhand", "Done", "New", "ProposedUpdates", "OldProposedUpdates" ]:
124             checkdir = cnf["Dir::Queue::%s" % (directory) ]
125             if os.path.exists(checkdir):
126                 print "Looking into %s" % (checkdir)
127                 for dirpath, dirnames, filenames in os.walk(checkdir, topdown=False):
128                     if not filenames:
129                         # Empty directory (or only subdirectories), next
130                         continue
131                     for changesfile in filenames:
132                         if not changesfile.endswith(".changes"):
133                             # Only interested in changes files.
134                             continue
135                         try:
136                             count += 1
137                             print "Directory %s, file %7d, failures %3d. (%s)" % (dirpath[-10:], count, failure, changesfile)
138                             changes = parse_changes(os.path.join(dirpath, changesfile), signing_rules=-1)
139                             (changes["fingerprint"], _) = check_signature(os.path.join(dirpath, changesfile))
140                         except InvalidDscError, line:
141                             warn("syntax error in .dsc file '%s', line %s." % (f, line))
142                             failure += 1
143                         except ChangesUnicodeError:
144                             warn("found invalid changes file, not properly utf-8 encoded")
145                             failure += 1
146
147                         filetime = datetime.datetime.fromtimestamp(os.path.getctime(os.path.join(dirpath, changesfile)))
148                         c.execute("INSERT INTO known_changes(changesname, seen, source, binaries, architecture, version, distribution, urgency, maintainer, changedby, date) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" , [changesfile, filetime, changes["source"], changes["binary"], changes["architecture"], changes["version"], changes["distribution"], changes["urgency"], changes["maintainer"], changes["changed-by"], changes["date"]])
149
150         c.execute("UPDATE config SET value = '20' WHERE name = 'db_revision'")
151         self.db.commit()
152
153     except psycopg2.ProgrammingError, msg:
154         self.db.rollback()
155         raise DBUpdateError, "Unable to apply source format update 15, rollback issued. Error message : %s" % (str(msg))