]> git.decadent.org.uk Git - dak.git/blob - rhona
rhona clean ups.
[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.2 2000-11-24 04:04:23 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     # A nicer way to do this would be `SELECT bin FROM
37     # bin_associations EXCEPT SELECT id from binaries WHERE
38     # last_update IS NULL', but it seems postgresql can't handle that
39     # query as it hadn't return after I left it running for 20 minutes
40     # on auric.
41
42     linked_binaries = {};
43     q = projectB.query("SELECT bin FROM bin_associations");
44     ql = q.getresult();
45     for i in ql:
46         linked_binaries[i[0]] = "";
47     
48     all_binaries = {};
49     q = projectB.query("SELECT b.id, b.file FROM binaries b, files f WHERE f.last_used IS NULL AND f.id = b.file")
50     ql = q.getresult();
51     for i in ql:
52         all_binaries[i[0]] = i[1];
53
54     projectB.query("BEGIN WORK");
55     for id in all_binaries.keys():
56         if not linked_binaries.has_key(id):
57             date = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()-(4*(24*60*60))))
58             projectB.query("UPDATE files SET last_used = '%s' WHERE id = %s" % (date, all_binaries[id]))
59     projectB.query("COMMIT WORK");
60
61     # Check for any binaries which are marked for eventual deletion but are now used again.
62
63     all_marked_binaries = {};
64     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")
65     ql = q.getresult();
66     for i in ql:
67         all_marked_binaries[i[0]] = i[1];
68     projectB.query("BEGIN WORK");
69     for id in all_marked_binaries.keys():
70         if linked_binaries.has_key(id):
71             # Can't imagine why this would happen, so warn about it for now.
72             print "W: %s has released %s from the target list." % (id, all_marked_binaries[id]);
73             projectB.query("UPDATE files SET last_used = NULL WHERE id = %s" % (all_marked_binaries[id]));
74     projectB.query("COMMIT WORK");
75
76 def check_sources():
77     # A nicer way to do this would be using `EXCEPT', but see the
78     # commeint in process_binary.
79
80     linked_sources = {};
81     q = projectB.query("SELECT source FROM binaries WHERE source is not null");
82     ql = q.getresult();
83     for i in ql:
84         linked_sources[i[0]] = "";
85     
86     all_sources = {};
87     q = projectB.query("SELECT s.id, s.file FROM source s, files f WHERE f.last_used IS NULL AND f.id = s.file")
88     ql = q.getresult();
89     for i in ql:
90         all_sources[i[0]] = i[1];
91
92     projectB.query("BEGIN WORK");
93     for id in all_sources.keys():
94         if not linked_sources.has_key(id):
95             date = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()-(4*(24*60*60))))
96             projectB.query("UPDATE files SET last_used = '%s' WHERE id = %s" % (date, all_sources[id]))
97             # Delete all other files references by .dsc too if they're not used by anyone else
98             q = projectB.query("SELECT f.id FROM files f, dsc_files d WHERE d.source = %d AND d.file = f.id" % (id));
99             ql = q.getresult();
100             for i in ql:
101                 q_others = projectB.query("SELECT file FROM dsc_files d WHERE file = %s" % (i[0]));
102                 ql_others = q.getresult();
103                 if len(ql) == 1:
104                     projectB.query("UPDATE files SET last_used = '%s' WHERE id = %s" % (date, i[0]));
105     projectB.query("COMMIT WORK");
106
107     # Check for any sources which are marked for eventual deletion but are now used again.
108     all_marked_sources = {};
109     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");
110     ql = q.getresult();
111     for i in ql:
112         all_marked_sources[i[0]] = i[1];
113     projectB.query("BEGIN WORK");
114     for id in all_marked_sources.keys():
115         if linked_sources.has_key(id):
116             # Can't imagine why this would happen, so warn about it for now.
117             print "W: %s has released %s from the target list." % (id, all_marked_sources[id]);
118             projectB.query("UPDATE files SET last_used = NULL WHERE id = %s" % (all_marked_sources[id]));
119             # Unmark all other files references by .dsc too
120             q = projectB.query("SELECT file FROM dsc_files WHERE source = %d" % (id));
121             ql = q.getresult();
122             for i in ql:
123                     projectB.query("UPDATE files SET last_used = NULL WHERE id = %s" % (i[0]));
124     projectB.query("COMMIT WORK");
125
126     # Whee, check for any source files (i.e. non .dsc) which are
127     # marked for eventual deletion but are now used by a source
128     # package again.
129     all_marked_dsc_files = {}
130     q = projectB.query("SELECT s.id, s.file FROM source s, files f, dsc_files d WHERE f.last_used IS NOT NULL AND f.id = d.file AND d.source = s.id");
131     ql = q.getresult();
132     for i in ql:
133         all_marked_dsc_files[i[0]] = i[1];
134     projectB.query("BEGIN WORK");
135     for id in all_marked_dsc_files.keys():
136         if linked_sources.has_key(id):
137             # Can't imagine why this would happen, so warn about it for now.
138             print "W: %s has released %s from the target list." % (id, all_marked_sources[id]);
139             projectB.query("UPDATE files SET last_used = NULL WHERE id = %s" % (all_marked_sources[id]));
140             # Unmark all other files references by .dsc too
141             q = projectB.query("SELECT file FROM dsc_files WHERE source = %d" % (id));
142             ql = q.getresult();
143             for i in ql:
144                     projectB.query("UPDATE files SET last_used = NULL WHERE id = %s" % (i[0]));
145     projectB.query("COMMIT WORK");
146
147 def clean():
148     date = time.strftime("%Y-%m-%d %H:%M", time.localtime(time.time()-int(Cnf["Rhona::StayOfExecution"])));
149     q = projectB.query("SELECT l.path, f.filename FROM location l, files f WHERE f.last_used < '%s' AND l.id = f.location" % (date))
150     ql = q.getresult();
151     for i in ql:
152         filename = i[0] + i[1];
153         dest = Cnf["Rhona::Morgue"]+os.path.basename(filename);
154         if not os.path.exists(filename):
155             sys.stderr.write("E: can not find %s.\n" % (filename));
156             continue;
157         print "Cleaning %s to %s..." % (filename, dest)
158         #utils.move(filename, dest);
159         #projectB.query("DELETE FROM binaries WHERE id = %s" % (i[0]));
160         #FIXME: need to remove from "or source" + files + dsc_files.. etc.
161
162 def main():
163     global Cnf, projectB;
164     
165     projectB = pg.connect('projectb', 'localhost');
166
167     apt_pkg.init();
168     
169     Cnf = apt_pkg.newConfiguration();
170     apt_pkg.ReadConfigFileISC(Cnf,utils.which_conf_file());
171
172     print "Checking for orphaned binary packages..."
173     check_binaries();
174     print "Checking for orphaned source packages..."
175     check_sources();
176     print "Cleaning orphaned packages..."
177     clean();
178
179 if __name__ == '__main__':
180     main()
181