]> git.decadent.org.uk Git - dak.git/blob - rhona
Initial revision
[dak.git] / rhona
1 #!/usr/bin/env python
2
3 # rhona, cleans up unassociated binary (and source) packages
4 # Copyright (C) 2000  James Troup <james@nocrew.org>
5 # $Id: rhona,v 1.1.1.1 2000-11-24 00:20:10 troup Exp $
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21 # 07:05|<elmo> well.. *shrug*.. no, probably not.. but to fix it,
22 #      |       we're going to have to implement reference counting
23 #      |       through dependencies.. do we really want to go down
24 #      |       that road?
25 #
26 # 07:05|<Culus> elmo: Augh! <brain jumps out of skull>
27
28 import pg, string, os, sys, time
29 import apt_pkg
30 import utils
31
32 projectB = None
33 Cnf = None
34
35 def check_binaries():
36
37     # A nicer way to do this would be `SELECT bin FROM
38     # bin_associations EXCEPT SELECT id from binaries WHERE
39     # last_update IS NULL', but it seems postgresql can't handle that
40     # query as it hadn't return after I left it running for 20 minutes
41     # on auric.
42
43     linked_binaries = {};
44     q = projectB.query("SELECT bin FROM bin_associations");
45     ql = q.getresult();
46     for i in ql:
47         linked_binaries[i[0]] = "";
48     
49     all_binaries = {};
50     q = projectB.query("SELECT b.id, b.file FROM binaries b, files f WHERE f.last_used IS NULL AND f.id = b.file")
51     ql = q.getresult();
52     for i in ql:
53         all_binaries[i[0]] = i[1];
54
55     projectB.query("BEGIN WORK");
56     for id in all_binaries.keys():
57         if not linked_binaries.has_key(id):
58             date = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()-(4*(24*60*60))))
59             projectB.query("UPDATE files SET last_used = '%s' WHERE id = %s" % (date, all_binaries[id]))
60     projectB.query("COMMIT WORK");
61
62     # Check for any binaries which are marked for eventual deletion but are now used again.
63
64     all_marked_binaries = {};
65     q = projectB.query("SELECT b.id, b.file FROM binaries b, files f WHERE f.last_used IS NOT NULL AND f.id = b.file")
66     ql = q.getresult();
67     for i in ql:
68         all_marked_binaries[i[0]] = i[1];
69     projectB.query("BEGIN WORK");
70     for id in all_marked_binaries.keys():
71         if linked_binaries.has_key(id):
72             # Can't imagine why this would happen, so warn about it for now.
73             print "W: %s has released %s from the target list." % (id, all_marked_binaries[id]);
74             projectB.query("UPDATE files SET last_used = NULL WHERE id = %s" % (all_marked_binaries[id]));
75     projectB.query("COMMIT WORK");
76
77 def check_sources():
78
79     # A nicer way to do this would be using `EXCEPT', but see the
80     # commeint in process_binary.
81
82     linked_sources = {};
83     q = projectB.query("SELECT source FROM binaries WHERE source is not null");
84     ql = q.getresult();
85     for i in ql:
86         linked_sources[i[0]] = "";
87     
88     all_sources = {};
89     q = projectB.query("SELECT s.id, s.file FROM source s, files f WHERE f.last_used IS NULL AND f.id = s.file")
90     ql = q.getresult();
91     for i in ql:
92         all_sources[i[0]] = i[1];
93
94     projectB.query("BEGIN WORK");
95     for id in all_sources.keys():
96         if not linked_sources.has_key(id):
97             date = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()-(4*(24*60*60))))
98             projectB.query("UPDATE files SET last_used = '%s' WHERE id = %s" % (date, all_sources[id]))
99             # Delete all other files references by .dsc too if they're not used by anyone else
100             q = projectB.query("SELECT f.id FROM files f, dsc_files d WHERE d.source = %d AND d.file = f.id" % (id));
101             ql = q.getresult();
102             for i in ql:
103                 q_others = projectB.query("SELECT id FROM dsc_files d WHERE file = %s" % (i[0]));
104                 ql_others = q.getresult();
105                 if len(ql) == 1:
106                     projectB.query("UPDATE files SET last_used = '%s' WHERE id = %s" % (date, i[0]));
107     projectB.query("COMMIT WORK");
108
109     # Check for any sources which are marked for eventual deletion but are now used again.
110     # Need to check versus dsc_files too!
111
112     all_marked_sources = {};
113     q = projectB.query("SELECT s.id, s.file FROM source s, files f WHERE f.last_used IS NOT NULL AND f.id = s.file");
114     ql = q.getresult();
115     for i in ql:
116         all_marked_sources[i[0]] = i[1];
117     projectB.query("BEGIN WORK");
118     for id in all_marked_sources.keys():
119         if linked_sources.has_key(id):
120             # Can't imagine why this would happen, so warn about it for now.
121             print "W: %s has released %s from the target list." % (id, all_marked_sources[id]);
122             projectB.query("UPDATE files SET last_used = NULL WHERE id = %s" % (all_marked_sources[id]));
123             # Unmark all other files references by .dsc too
124             q = projectB.query("SELECT id FROM dsc_files WHERE source = %d" % (id));
125             ql = q.getresult();
126             for i in ql:
127                     projectB.query("UPDATE files SET last_used = NULL WHERE id = %s" % (i[0]));
128     projectB.query("COMMIT WORK");
129
130 def clean():
131     date = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()-int(Cnf["Rhona::StayOfExecution"])));
132     q = projectB.query("SELECT l.path, f.filename FROM location l, files f WHERE f.last_used < '%s' AND l.id = f.location" % (date))
133     ql = q.getresult();
134     for i in ql:
135         filename = i[0] + i[1];
136         dest = Cnf["Rhona::Morgue"]+os.path.basename(filename);
137         if not os.path.exists(filename):
138             sys.stderr.write("E: can not find %s.\n" % (filename));
139             continue;
140         print "Cleaning %s to %s..." % (filename, dest)
141         #utils.move(filename, dest);
142         #projectB.query("DELETE FROM binaries WHERE id = %s" % (i[0]));
143         #FIXME: need to remove from "or source" + files + dsc_files.. etc.
144
145 def main():
146     global Cnf, projectB;
147     
148     projectB = pg.connect('projectb', 'localhost');
149
150     apt_pkg.init();
151     
152     Cnf = apt_pkg.newConfiguration();
153     apt_pkg.ReadConfigFileISC(Cnf,utils.which_conf_file());
154
155     print "Checking for orphaned binary packages..."
156     check_binaries();
157     print "Checking for orphaned source packages..."
158     check_sources();
159     print "Cleaning orphaned packages..."
160     clean();
161
162 if __name__ == '__main__':
163     main()
164