]> git.decadent.org.uk Git - dak.git/blob - dak/control_suite.py
Fix all the whitespace / tab breakage, so its now all the same
[dak.git] / dak / control_suite.py
1 #!/usr/bin/env python
2
3 # Manipulate suite tags
4 # Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006  James Troup <james@nocrew.org>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 #######################################################################################
21
22 # 8to6Guy: "Wow, Bob, You look rough!"
23 # BTAF: "Mbblpmn..."
24 # BTAF <.oO>: "You moron! This is what you get for staying up all night drinking vodka and salad dressing!"
25 # BTAF <.oO>: "This coffee I.V. drip is barely even keeping me awake! I need something with more kick! But what?"
26 # BTAF: "OMIGOD! I OVERDOSED ON HEROIN"
27 # CoWorker#n: "Give him air!!"
28 # CoWorker#n+1: "We need a syringe full of adrenaline!"
29 # CoWorker#n+2: "Stab him in the heart!"
30 # BTAF: "*YES!*"
31 # CoWorker#n+3: "Bob's been overdosing quite a bit lately..."
32 # CoWorker#n+4: "Third time this week."
33
34 # -- http://www.angryflower.com/8to6.gif
35
36 #######################################################################################
37
38 # Adds or removes packages from a suite.  Takes the list of files
39 # either from stdin or as a command line argument.  Special action
40 # "set", will reset the suite (!) and add all packages from scratch.
41
42 #######################################################################################
43
44 import pg, sys
45 import apt_pkg
46 import daklib.database
47 import daklib.logging
48 import daklib.utils
49
50 #######################################################################################
51
52 Cnf = None
53 projectB = None
54 Logger = None
55
56 ################################################################################
57
58 def usage (exit_code=0):
59     print """Usage: dak control-suite [OPTIONS] [FILE]
60 Display or alter the contents of a suite using FILE(s), or stdin.
61
62   -a, --add=SUITE            add to SUITE
63   -h, --help                 show this help and exit
64   -l, --list=SUITE           list the contents of SUITE
65   -r, --remove=SUITE         remove from SUITE
66   -s, --set=SUITE            set SUITE"""
67
68     sys.exit(exit_code)
69
70 #######################################################################################
71
72 def get_id (package, version, architecture):
73     if architecture == "source":
74         q = projectB.query("SELECT id FROM source WHERE source = '%s' AND version = '%s'" % (package, version))
75     else:
76         q = projectB.query("SELECT b.id FROM binaries b, architecture a WHERE b.package = '%s' AND b.version = '%s' AND (a.arch_string = '%s' OR a.arch_string = 'all') AND b.architecture = a.id" % (package, version, architecture))
77
78     ql = q.getresult()
79     if not ql:
80         daklib.utils.warn("Couldn't find '%s_%s_%s'." % (package, version, architecture))
81         return None
82     if len(ql) > 1:
83         daklib.utils.warn("Found more than one match for '%s_%s_%s'." % (package, version, architecture))
84         return None
85     id = ql[0][0]
86     return id
87
88 #######################################################################################
89
90 def set_suite (file, suite_id):
91     lines = file.readlines()
92
93     projectB.query("BEGIN WORK")
94
95     # Build up a dictionary of what is currently in the suite
96     current = {}
97     q = projectB.query("SELECT b.package, b.version, a.arch_string, ba.id FROM binaries b, bin_associations ba, architecture a WHERE ba.suite = %s AND ba.bin = b.id AND b.architecture = a.id" % (suite_id))
98     ql = q.getresult()
99     for i in ql:
100         key = " ".join(i[:3])
101         current[key] = i[3]
102     q = projectB.query("SELECT s.source, s.version, sa.id FROM source s, src_associations sa WHERE sa.suite = %s AND sa.source = s.id" % (suite_id))
103     ql = q.getresult()
104     for i in ql:
105         key = " ".join(i[:2]) + " source"
106         current[key] = i[2]
107
108     # Build up a dictionary of what should be in the suite
109     desired = {}
110     for line in lines:
111         split_line = line.strip().split()
112         if len(split_line) != 3:
113             daklib.utils.warn("'%s' does not break into 'package version architecture'." % (line[:-1]))
114             continue
115         key = " ".join(split_line)
116         desired[key] = ""
117
118     # Check to see which packages need removed and remove them
119     for key in current.keys():
120         if not desired.has_key(key):
121             (package, version, architecture) = key.split()
122             id = current[key]
123             if architecture == "source":
124                 q = projectB.query("DELETE FROM src_associations WHERE id = %s" % (id))
125             else:
126                 q = projectB.query("DELETE FROM bin_associations WHERE id = %s" % (id))
127             Logger.log(["removed",key,id])
128
129     # Check to see which packages need added and add them
130     for key in desired.keys():
131         if not current.has_key(key):
132             (package, version, architecture) = key.split()
133             id = get_id (package, version, architecture)
134             if not id:
135                 continue
136             if architecture == "source":
137                 q = projectB.query("INSERT INTO src_associations (suite, source) VALUES (%s, %s)" % (suite_id, id))
138             else:
139                 q = projectB.query("INSERT INTO bin_associations (suite, bin) VALUES (%s, %s)" % (suite_id, id))
140             Logger.log(["added",key,id])
141
142     projectB.query("COMMIT WORK")
143
144 #######################################################################################
145
146 def process_file (file, suite, action):
147
148     suite_id = daklib.database.get_suite_id(suite)
149
150     if action == "set":
151         set_suite (file, suite_id)
152         return
153
154     lines = file.readlines()
155
156     projectB.query("BEGIN WORK")
157
158     for line in lines:
159         split_line = line.strip().split()
160         if len(split_line) != 3:
161             daklib.utils.warn("'%s' does not break into 'package version architecture'." % (line[:-1]))
162             continue
163
164         (package, version, architecture) = split_line
165
166         id = get_id(package, version, architecture)
167         if not id:
168             continue
169
170         if architecture == "source":
171             # Find the existing assoications ID, if any
172             q = projectB.query("SELECT id FROM src_associations WHERE suite = %s and source = %s" % (suite_id, id))
173             ql = q.getresult()
174             if not ql:
175                 assoication_id = None
176             else:
177                 assoication_id = ql[0][0]
178             # Take action
179             if action == "add":
180                 if assoication_id:
181                     daklib.utils.warn("'%s_%s_%s' already exists in suite %s." % (package, version, architecture, suite))
182                     continue
183                 else:
184                     q = projectB.query("INSERT INTO src_associations (suite, source) VALUES (%s, %s)" % (suite_id, id))
185             elif action == "remove":
186                 if assoication_id == None:
187                     daklib.utils.warn("'%s_%s_%s' doesn't exist in suite %s." % (package, version, architecture, suite))
188                     continue
189                 else:
190                     q = projectB.query("DELETE FROM src_associations WHERE id = %s" % (assoication_id))
191         else:
192             # Find the existing assoications ID, if any
193             q = projectB.query("SELECT id FROM bin_associations WHERE suite = %s and bin = %s" % (suite_id, id))
194             ql = q.getresult()
195             if not ql:
196                 assoication_id = None
197             else:
198                 assoication_id = ql[0][0]
199             # Take action
200             if action == "add":
201                 if assoication_id:
202                     daklib.utils.warn("'%s_%s_%s' already exists in suite %s." % (package, version, architecture, suite))
203                     continue
204                 else:
205                     q = projectB.query("INSERT INTO bin_associations (suite, bin) VALUES (%s, %s)" % (suite_id, id))
206             elif action == "remove":
207                 if assoication_id == None:
208                     daklib.utils.warn("'%s_%s_%s' doesn't exist in suite %s." % (package, version, architecture, suite))
209                     continue
210                 else:
211                     q = projectB.query("DELETE FROM bin_associations WHERE id = %s" % (assoication_id))
212
213     projectB.query("COMMIT WORK")
214
215 #######################################################################################
216
217 def get_list (suite):
218     suite_id = daklib.database.get_suite_id(suite)
219     # List binaries
220     q = projectB.query("SELECT b.package, b.version, a.arch_string FROM binaries b, bin_associations ba, architecture a WHERE ba.suite = %s AND ba.bin = b.id AND b.architecture = a.id" % (suite_id))
221     ql = q.getresult()
222     for i in ql:
223         print " ".join(i)
224
225     # List source
226     q = projectB.query("SELECT s.source, s.version FROM source s, src_associations sa WHERE sa.suite = %s AND sa.source = s.id" % (suite_id))
227     ql = q.getresult()
228     for i in ql:
229         print " ".join(i) + " source"
230
231 #######################################################################################
232
233 def main ():
234     global Cnf, projectB, Logger
235
236     Cnf = daklib.utils.get_conf()
237
238     Arguments = [('a',"add","Control-Suite::Options::Add", "HasArg"),
239                  ('h',"help","Control-Suite::Options::Help"),
240                  ('l',"list","Control-Suite::Options::List","HasArg"),
241                  ('r',"remove", "Control-Suite::Options::Remove", "HasArg"),
242                  ('s',"set", "Control-Suite::Options::Set", "HasArg")]
243
244     for i in ["add", "help", "list", "remove", "set", "version" ]:
245         if not Cnf.has_key("Control-Suite::Options::%s" % (i)):
246             Cnf["Control-Suite::Options::%s" % (i)] = ""
247
248     file_list = apt_pkg.ParseCommandLine(Cnf,Arguments,sys.argv)
249     Options = Cnf.SubTree("Control-Suite::Options")
250
251     if Options["Help"]:
252         usage()
253
254     projectB = pg.connect(Cnf["DB::Name"], Cnf["DB::Host"],int(Cnf["DB::Port"]))
255
256     daklib.database.init(Cnf, projectB)
257
258     action = None
259
260     for i in ("add", "list", "remove", "set"):
261         if Cnf["Control-Suite::Options::%s" % (i)] != "":
262             suite = Cnf["Control-Suite::Options::%s" % (i)]
263             if daklib.database.get_suite_id(suite) == -1:
264                 daklib.utils.fubar("Unknown suite '%s'." %(suite))
265             else:
266                 if action:
267                     daklib.utils.fubar("Can only perform one action at a time.")
268                 action = i
269
270     # Need an action...
271     if action == None:
272         daklib.utils.fubar("No action specified.")
273
274     # Safety/Sanity check
275     if action == "set" and suite not in ["testing", "etch-m68k"]:
276         daklib.utils.fubar("Will not reset a suite other than testing.")
277
278     if action == "list":
279         get_list(suite)
280     else:
281         Logger = daklib.logging.Logger(Cnf, "control-suite")
282         if file_list:
283             for file in file_list:
284                 process_file(daklib.utils.open_file(file), suite, action)
285         else:
286             process_file(sys.stdin, suite, action)
287         Logger.close()
288
289 #######################################################################################
290
291 if __name__ == '__main__':
292     main()