]> git.decadent.org.uk Git - dak.git/blob - dak/admin.py
change to not using autocommit by default
[dak.git] / dak / admin.py
1 #!/usr/bin/env python
2
3 """Configure dak parameters in the database"""
4 # Copyright (C) 2009  Mark Hymers <mhy@debian.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 import sys
23
24 import apt_pkg
25
26 from daklib import utils
27 from daklib.dbconn import *
28 from daklib.config import Config
29
30 ################################################################################
31
32 dispatch = {}
33 dryrun = False
34
35 ################################################################################
36 def warn(msg):
37     print >> sys.stderr, msg
38
39 def die(msg, exit_code=1):
40     print >> sys.stderr, msg
41     sys.exit(exit_code)
42
43 def die_arglen(args, args_needed, msg):
44     if len(args) < args_needed:
45         die(msg)
46
47 def usage(exit_code=0):
48     """Perform administrative work on the dak database."""
49
50     print """Usage: dak admin COMMAND
51 Perform administrative work on the dak database.
52
53   -h, --help          show this help and exit.
54   -n, --dry-run       don't do anything, just show what would have been done
55                       (only applies to add or rm operations).
56
57   Commands can use a long or abbreviated form:
58
59   architecture / a:
60      a list                 show a list of architectures
61      a rm ARCH              remove an architecture (will only work if
62                             no longer linked to any suites)
63      a add ARCH DESCRIPTION [SUITELIST]
64                             add architecture ARCH with DESCRIPTION.
65                             If SUITELIST is given, add to each of the
66                             suites at the same time
67
68   suite-architecture / s-a:
69      s-a list-suite ARCH    show the suites an ARCH is in
70      s-a list-arch SUITE    show the architectures in a SUITE
71      s-a add SUITE ARCH     add ARCH to suite
72      s-a rm SUITE ARCH      remove ARCH from suite (will only work if
73                             no packages remain for the arch in the suite)
74 """
75     sys.exit(exit_code)
76
77 ################################################################################
78
79 def __architecture_list(d, args):
80     q = d.session().query(Architecture).order_by('arch_string')
81     for j in q.all():
82         # HACK: We should get rid of source from the arch table
83         if j.arch_string == 'source': continue
84         print j.arch_string
85     sys.exit(0)
86
87 def __architecture_add(d, args):
88     die_arglen(args, 3, "E: adding an architecture requires a name and a description")
89     print "Adding architecture %s" % args[2]
90     suites = [str(x) for x in args[4:]]
91     print suites
92     if not dryrun:
93         try:
94             s = d.session()
95             a = Architecture()
96             a.arch_string = str(args[2]).lower()
97             a.description = str(args[3])
98             s.add(a)
99             for sn in suites:
100                 su = get_suite(sn ,s)
101                 if su is not None:
102                     archsu = SuiteArchitecture()
103                     archsu.arch_id = a.arch_id
104                     archsu.suite_id = su.suite_id
105                     s.add(archsu)
106                 else:
107                     warn("W: Cannot find suite %s" % su)
108             s.commit()
109         except IntegrityError, e:
110             die("E: Integrity error adding architecture %s (it probably already exists)" % args[2])
111         except SQLAlchemyError, e:
112             die("E: Error adding architecture %s (%s)" % (args[2], e))
113     print "Architecture %s added" % (args[2])
114
115 def __architecture_rm(d, args):
116     die_arglen(args, 3, "E: removing an architecture requires at least a name")
117     print "Removing architecture %s" % args[2]
118     if not dryrun:
119         try:
120             s = d.session()
121             a = get_architecture(args[2].lower(), s)
122             if a is None:
123                 die("E: Cannot find architecture %s" % args[2])
124             s.delete(a)
125             s.commit()
126         except IntegrityError, e:
127             die("E: Integrity error removing architecture %s (suite-arch entries probably still exist)" % args[2])
128         except SQLAlchemyError, e:
129             die("E: Error removing architecture %s (%s)" % (args[2], e))
130     print "Architecture %s removed" % args[2]
131
132 def architecture(command):
133     args = [str(x) for x in command]
134     Cnf = utils.get_conf()
135     d = DBConn()
136
137     die_arglen(args, 2, "E: architecture needs at least a command")
138
139     mode = args[1].lower()
140     if mode == 'list':
141         __architecture_list(d, args)
142     elif mode == 'add':
143         __architecture_add(d, args)
144     elif mode == 'rm':
145         __architecture_rm(d, args)
146     else:
147         die("E: architecture command unknown")
148
149 dispatch['architecture'] = architecture
150 dispatch['a'] = architecture
151
152 ################################################################################
153
154 def __suite_architecture_listarch(d, args):
155     die_arglen(args, 3, "E: suite-architecture list-arch requires a suite")
156     a = get_suite_architectures(args[2].lower())
157     for j in a:
158         # HACK: We should get rid of source from the arch table
159         if j.arch_string != 'source':
160             print j.arch_string
161
162
163 def __suite_architecture_listsuite(d, args):
164     die_arglen(args, 3, "E: suite-architecture list-suite requires an arch")
165     for j in get_architecture_suites(args[2].lower()):
166         print j.suite_name
167
168
169 def __suite_architecture_add(d, args):
170     if len(args) < 3:
171         die("E: adding a suite-architecture entry requires a suite and arch")
172
173     s = d.session()
174
175     suite = get_suite(args[2].lower(), s)
176     if suite is None: die("E: Can't find suite %s" % args[2].lower())
177
178     arch = get_architecture(args[3].lower(), s)
179     if arch is None: die("E: Can't find architecture %s" % args[3].lower())
180
181     if not dryrun:
182         try:
183             sa = SuiteArchitecture()
184             sa.arch_id = arch.arch_id
185             sa.suite_id = suite.suite_id
186             s.add(sa)
187             s.commit()
188         except IntegrityError, e:
189             die("E: Can't add suite-architecture entry (%s, %s) - probably already exists" % (args[2].lower(), args[3].lower()))
190         except SQLAlchemyError, e:
191             die("E: Can't add suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
192
193     print "Added suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower())
194
195
196 def __suite_architecture_rm(d, args):
197     if len(args) < 3:
198         die("E: removing an suite-architecture entry requires a suite and arch")
199
200     s = d.session()
201     if not dryrun:
202         try:
203             sa = get_suite_architecture(args[2].lower(), args[3].lower(), s)
204             if sa is None:
205                 die("E: can't find suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower()))
206             s.delete(sa)
207             s.commit()
208         except IntegrityError, e:
209             die("E: Can't remove suite-architecture entry (%s, %s) - it's probably referenced" % (args[2].lower(), args[3].lower()))
210         except SQLAlchemyError, e:
211             die("E: Can't remove suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
212
213     print "Removed suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower()) 
214
215
216 def suite_architecture(command):
217     args = [str(x) for x in command]
218     Cnf = utils.get_conf()
219     d = DBConn()
220
221     die_arglen(args, 2, "E: suite-architecture needs at least a command")
222
223     mode = args[1].lower()
224
225     if mode == 'list-arch':
226         __suite_architecture_listarch(d, args)
227     elif mode == 'list-suite':
228         __suite_architecture_listsuite(d, args)
229     elif mode == 'add':
230         __suite_architecture_add(d, args)
231     elif mode == 'rm':
232         __suite_architecture_rm(d, args)
233     else:
234         die("E: suite-architecture command unknown")
235
236 dispatch['suite-architecture'] = suite_architecture
237 dispatch['s-a'] = suite_architecture
238
239 ################################################################################
240
241 def main():
242     """Perform administrative work on the dak database"""
243     global dryrun
244     Cnf = utils.get_conf()
245     arguments = [('h', "help", "Admin::Options::Help"),
246                  ('n', "dry-run", "Admin::Options::Dry-Run")]
247     for i in [ "help", "dry-run" ]:
248         if not Cnf.has_key("Admin::Options::%s" % (i)):
249             Cnf["Admin::Options::%s" % (i)] = ""
250
251     arguments = apt_pkg.ParseCommandLine(Cnf, arguments, sys.argv)
252
253     options = Cnf.SubTree("Admin::Options")
254     if options["Help"] or len(arguments) < 1:
255         usage()
256     if options["Dry-Run"]:
257         dryrun = True
258
259     subcommand = str(arguments[0])
260
261     if subcommand in dispatch.keys():
262         dispatch[subcommand](arguments)
263     else:
264         die("E: Unknown command")
265
266 ################################################################################
267
268 if __name__ == '__main__':
269     main()