]> git.decadent.org.uk Git - dak.git/blob - dak/dakdb/update2.py
show-new: Use dakmultiprocessing
[dak.git] / dak / dakdb / update2.py
1 #!/usr/bin/env python
2 # coding=utf8
3
4 """
5 debversion
6
7 @contact: Debian FTP Master <ftpmaster@debian.org>
8 @copyright: 2008  Michael Casadevall <mcasadevall@debian.org>
9 @copyright: 2008  Roger Leigh <rleigh@debian.org>
10 @license: GNU General Public License version 2 or later
11 """
12
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 2 of the License, or
16 # (at your option) any later version.
17
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 # GNU General Public License for more details.
22
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
27 ################################################################################
28
29 import psycopg2
30 import time
31 from daklib.dak_exceptions import DBUpdateError
32
33 ################################################################################
34
35 def do_update(self):
36     print "Note: to be able to enable the the PL/Perl (plperl) procedural language, we do"
37     print "need postgresql-plperl-$postgres-version installed. Make sure that this is the"
38     print "case before you continue. Interrupt if it isn't, sleeping 5 seconds now."
39     print "(We need to be database superuser for this to work!)"
40     time.sleep (5)
41
42     try:
43         c = self.db.cursor()
44
45         print "Enabling PL/Perl language"
46         c.execute("CREATE LANGUAGE plperl;")
47         c.execute("CREATE LANGUAGE plpgsql;")
48
49         print "Adding debversion type to database."
50
51 # Not present in all databases, maybe PL/Perl version-dependent?
52 #        c.execute("SET SESSION plperl.use_strict TO 't';")
53
54         c.execute("CREATE DOMAIN debversion AS TEXT;")
55         c.execute("COMMENT ON DOMAIN debversion IS 'Debian package version number';")
56
57         c.execute("""ALTER DOMAIN debversion
58                      ADD CONSTRAINT debversion_syntax
59                      CHECK (VALUE !~ '[^-+:.0-9a-zA-Z~]');""")
60
61         # From Dpkg::Version::parseversion
62         c.execute("""CREATE OR REPLACE FUNCTION debversion_split (debversion)
63   RETURNS text[] AS $$
64     my $ver = shift;
65     my %verhash;
66     if ($ver =~ /:/)
67     {
68         $ver =~ /^(\d+):(.+)/ or die "bad version number '$ver'";
69         $verhash{epoch} = $1;
70         $ver = $2;
71     }
72     else
73     {
74         $verhash{epoch} = 0;
75     }
76     if ($ver =~ /(.+)-(.*)$/)
77     {
78         $verhash{version} = $1;
79         $verhash{revision} = $2;
80     }
81     else
82     {
83         $verhash{version} = $ver;
84         $verhash{revision} = 0;
85     }
86
87     return [$verhash{'epoch'}, $verhash{'version'}, $verhash{'revision'}];
88 $$
89   LANGUAGE plperl
90   IMMUTABLE STRICT;""")
91         c.execute("""COMMENT ON FUNCTION debversion_split (debversion)
92                    IS 'Split debian version into epoch, upstream version and revision';""")
93
94         c.execute("""CREATE OR REPLACE FUNCTION debversion_epoch (version debversion)
95   RETURNS text AS $$
96 DECLARE
97   split text[];
98 BEGIN
99   split := debversion_split(version);
100   RETURN split[1];
101 END;
102 $$
103   LANGUAGE plpgsql
104   IMMUTABLE STRICT;
105 COMMENT ON FUNCTION debversion_epoch (debversion)
106   IS 'Get debian version epoch';
107
108 CREATE OR REPLACE FUNCTION debversion_version (version debversion)
109   RETURNS text AS $$
110 DECLARE
111   split text[];
112 BEGIN
113   split := debversion_split(version);
114   RETURN split[2];
115 END;
116 $$
117   LANGUAGE plpgsql
118   IMMUTABLE STRICT;""")
119         c.execute("""COMMENT ON FUNCTION debversion_version (debversion)
120                    IS 'Get debian version upstream version';""")
121
122         c.execute("""CREATE OR REPLACE FUNCTION debversion_revision (version debversion)
123   RETURNS text AS $$
124 DECLARE
125   split text[];
126 BEGIN
127   split := debversion_split(version);
128   RETURN split[3];
129 END;
130 $$
131   LANGUAGE plpgsql
132   IMMUTABLE STRICT;""")
133         c.execute("""COMMENT ON FUNCTION debversion_revision (debversion)
134                    IS 'Get debian version revision';""")
135
136 # From Dpkg::Version::parseversion
137         c.execute("""CREATE OR REPLACE FUNCTION debversion_compare_single (version1 text, version2 text)
138   RETURNS integer AS $$
139      sub order{
140           my ($x) = @_;
141           ##define order(x) ((x) == '~' ? -1 \
142           #           : cisdigit((x)) ? 0 \
143           #           : !(x) ? 0 \
144           #           : cisalpha((x)) ? (x) \
145           #           : (x) + 256)
146           # This comparison is out of dpkg's order to avoid
147           # comparing things to undef and triggering warnings.
148           if (not defined $x or not length $x) {
149                return 0;
150           }
151           elsif ($x eq '~') {
152                return -1;
153           }
154           elsif ($x =~ /^\d$/) {
155                return 0;
156           }
157           elsif ($x =~ /^[A-Z]$/i) {
158                return ord($x);
159           }
160           else {
161                return ord($x) + 256;
162           }
163      }
164
165      sub next_elem(\@){
166           my $a = shift;
167           return @{$a} ? shift @{$a} : undef;
168      }
169      my ($val, $ref) = @_;
170      $val = "" if not defined $val;
171      $ref = "" if not defined $ref;
172      my @val = split //,$val;
173      my @ref = split //,$ref;
174      my $vc = next_elem @val;
175      my $rc = next_elem @ref;
176      while (defined $vc or defined $rc) {
177           my $first_diff = 0;
178           while ((defined $vc and $vc !~ /^\d$/) or
179                  (defined $rc and $rc !~ /^\d$/)) {
180                my $vo = order($vc); my $ro = order($rc);
181                # Unlike dpkg's verrevcmp, we only return 1 or -1 here.
182                return (($vo - $ro > 0) ? 1 : -1) if $vo != $ro;
183                $vc = next_elem @val; $rc = next_elem @ref;
184           }
185           while (defined $vc and $vc eq '0') {
186                $vc = next_elem @val;
187           }
188           while (defined $rc and $rc eq '0') {
189                $rc = next_elem @ref;
190           }
191           while (defined $vc and $vc =~ /^\d$/ and
192                  defined $rc and $rc =~ /^\d$/) {
193                $first_diff = ord($vc) - ord($rc) if !$first_diff;
194                $vc = next_elem @val; $rc = next_elem @ref;
195           }
196           return 1 if defined $vc and $vc =~ /^\d$/;
197           return -1 if defined $rc and $rc =~ /^\d$/;
198           return (($first_diff  > 0) ? 1 : -1) if $first_diff;
199      }
200      return 0;
201 $$
202   LANGUAGE plperl
203   IMMUTABLE STRICT;""")
204         c.execute("""COMMENT ON FUNCTION debversion_compare_single (text, text)
205                    IS 'Compare upstream or revision parts of Debian versions';""")
206
207 # Logic only derived from Dpkg::Version::parseversion
208         c.execute("""CREATE OR REPLACE FUNCTION debversion_compare (version1 debversion, version2 debversion)
209   RETURNS integer AS $$
210 DECLARE
211   split1 text[];
212   split2 text[];
213   result integer;
214 BEGIN
215   result := 0;
216   split1 := debversion_split(version1);
217   split2 := debversion_split(version2);
218
219   -- RAISE NOTICE 'Version 1: %', version1;
220   -- RAISE NOTICE 'Version 2: %', version2;
221   -- RAISE NOTICE 'Split 1: %', split1;
222   -- RAISE NOTICE 'Split 2: %', split2;
223
224   IF split1[1] > split2[1] THEN
225     result := 1;
226   ELSIF split1[1] < split2[1] THEN
227     result := -1;
228   ELSE
229     result := debversion_compare_single(split1[2], split2[2]);
230     IF result = 0 THEN
231       result := debversion_compare_single(split1[3], split2[3]);
232     END IF;
233   END IF;
234
235   RETURN result;
236 END;
237 $$
238   LANGUAGE plpgsql
239   IMMUTABLE STRICT;""")
240         c.execute("""COMMENT ON FUNCTION debversion_compare (debversion, debversion)
241   IS 'Compare Debian versions';""")
242
243         c.execute("""CREATE OR REPLACE FUNCTION debversion_eq (version1 debversion, version2 debversion)
244   RETURNS boolean AS $$
245 DECLARE
246   comp integer;
247   result boolean;
248 BEGIN
249   comp := debversion_compare(version1, version2);
250   result := comp = 0;
251   RETURN result;
252 END;
253 $$
254   LANGUAGE plpgsql
255   IMMUTABLE STRICT;""")
256         c.execute("""COMMENT ON FUNCTION debversion_eq (debversion, debversion)
257   IS 'debversion equal';""")
258
259         c.execute("""CREATE OR REPLACE FUNCTION debversion_ne (version1 debversion, version2 debversion)
260   RETURNS boolean AS $$
261 DECLARE
262   comp integer;
263   result boolean;
264 BEGIN
265   comp := debversion_compare(version1, version2);
266   result := comp <> 0;
267   RETURN result;
268 END;
269 $$
270   LANGUAGE plpgsql
271   IMMUTABLE STRICT;""")
272         c.execute("""COMMENT ON FUNCTION debversion_ne (debversion, debversion)
273   IS 'debversion not equal';""")
274
275         c.execute("""CREATE OR REPLACE FUNCTION debversion_lt (version1 debversion, version2 debversion)
276   RETURNS boolean AS $$
277 DECLARE
278   comp integer;
279   result boolean;
280 BEGIN
281   comp := debversion_compare(version1, version2);
282   result := comp < 0;
283   RETURN result;
284 END;
285 $$
286   LANGUAGE plpgsql
287   IMMUTABLE STRICT;""")
288         c.execute("""COMMENT ON FUNCTION debversion_lt (debversion, debversion)
289                    IS 'debversion less-than';""")
290
291         c.execute("""CREATE OR REPLACE FUNCTION debversion_gt (version1 debversion, version2 debversion) RETURNS boolean AS $$
292 DECLARE
293   comp integer;
294   result boolean;
295 BEGIN
296   comp := debversion_compare(version1, version2);
297   result := comp > 0;
298   RETURN result;
299 END;
300 $$
301   LANGUAGE plpgsql
302   IMMUTABLE STRICT;""")
303         c.execute("""COMMENT ON FUNCTION debversion_gt (debversion, debversion)
304                    IS 'debversion greater-than';""")
305
306         c.execute("""CREATE OR REPLACE FUNCTION debversion_le (version1 debversion, version2 debversion)
307   RETURNS boolean AS $$
308 DECLARE
309   comp integer;
310   result boolean;
311 BEGIN
312   comp := debversion_compare(version1, version2);
313   result := comp <= 0;
314   RETURN result;
315 END;
316 $$
317   LANGUAGE plpgsql
318   IMMUTABLE STRICT;""")
319         c.execute("""COMMENT ON FUNCTION debversion_le (debversion, debversion)
320                    IS 'debversion less-than-or-equal';""")
321
322         c.execute("""CREATE OR REPLACE FUNCTION debversion_ge (version1 debversion, version2 debversion)
323   RETURNS boolean AS $$
324 DECLARE
325   comp integer;
326   result boolean;
327 BEGIN
328   comp := debversion_compare(version1, version2);
329   result := comp >= 0;
330   RETURN result;
331 END;
332 $$
333   LANGUAGE plpgsql
334   IMMUTABLE STRICT;""")
335         c.execute("""COMMENT ON FUNCTION debversion_ge (debversion, debversion)
336                    IS 'debversion greater-than-or-equal';""")
337
338         c.execute("""CREATE OPERATOR = (
339                    PROCEDURE = debversion_eq,
340                    LEFTARG = debversion,
341                    RIGHTARG = debversion,
342                    COMMUTATOR = =,
343                    NEGATOR = !=);""")
344         c.execute("""COMMENT ON OPERATOR = (debversion, debversion)
345                    IS 'debversion equal';""")
346
347         c.execute("""CREATE OPERATOR != (
348                    PROCEDURE = debversion_eq,
349                    LEFTARG = debversion,
350                    RIGHTARG = debversion,
351                    COMMUTATOR = !=,
352                    NEGATOR = =);""")
353         c.execute("""COMMENT ON OPERATOR != (debversion, debversion)
354                    IS 'debversion not equal';""")
355
356         c.execute("""CREATE OPERATOR < (
357                    PROCEDURE = debversion_lt,
358                    LEFTARG = debversion,
359                    RIGHTARG = debversion,
360                    COMMUTATOR = >,
361                    NEGATOR = >=);""")
362         c.execute("""COMMENT ON OPERATOR < (debversion, debversion)
363                    IS 'debversion less-than';""")
364
365         c.execute("""CREATE OPERATOR > (
366                    PROCEDURE = debversion_gt,
367                    LEFTARG = debversion,
368                    RIGHTARG = debversion,
369                    COMMUTATOR = <,
370                    NEGATOR = >=);""")
371         c.execute("""COMMENT ON OPERATOR > (debversion, debversion)
372                    IS 'debversion greater-than';""")
373
374         c.execute("""CREATE OPERATOR <= (
375                    PROCEDURE = debversion_le,
376                    LEFTARG = debversion,
377                    RIGHTARG = debversion,
378                    COMMUTATOR = >=,
379                    NEGATOR = >);""")
380         c.execute("""COMMENT ON OPERATOR <= (debversion, debversion)
381                    IS 'debversion less-than-or-equal';""")
382
383         c.execute("""CREATE OPERATOR >= (
384                    PROCEDURE = debversion_ge,
385                    LEFTARG = debversion,
386                    RIGHTARG = debversion,
387                    COMMUTATOR = <=,
388                    NEGATOR = <);""")
389         c.execute("""COMMENT ON OPERATOR >= (debversion, debversion)
390                    IS 'debversion greater-than-or-equal';""")
391
392         c.execute("ALTER TABLE source ALTER COLUMN version TYPE debversion;")
393         c.execute("ALTER TABLE binaries ALTER COLUMN version TYPE debversion;")
394
395         c.execute("UPDATE config SET value = '2' WHERE name = 'db_revision'")
396
397         self.db.commit()
398
399     except psycopg2.ProgrammingError, msg:
400         self.db.rollback()
401         raise DBUpdateError, "Unable to appy debversion updates, rollback issued. Error message : %s" % (str(msg))