3 """Configure dak parameters in the database"""
4 # Copyright (C) 2009 Mark Hymers <mhy@debian.org>
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.
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.
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
20 ################################################################################
29 from daklib import utils
30 from daklib.dbconn import *
31 from sqlalchemy.orm.exc import NoResultFound
33 ################################################################################
38 ################################################################################
40 print >> sys.stderr, msg
42 def die(msg, exit_code=1):
43 print >> sys.stderr, msg
46 def die_arglen(args, args_needed, msg):
47 if len(args) < args_needed:
50 def usage(exit_code=0):
51 """Perform administrative work on the dak database."""
53 print """Usage: dak admin COMMAND
54 Perform administrative work on the dak database.
56 -h, --help show this help and exit.
57 -n, --dry-run don't do anything, just show what would have been done
58 (only applies to add or rm operations).
60 Commands can use a long or abbreviated form:
64 c db-shell show db config in a usable form for psql
65 c NAME show option NAME as set in configuration table
68 k list-all list all keyrings
69 k list-binary list all keyrings with a NULL source acl
70 k list-source list all keyrings with a non NULL source acl
71 k add-buildd NAME ARCH... add buildd keyring with upload permission
72 for the given architectures
75 a list show a list of architectures
76 a rm ARCH remove an architecture (will only work if
77 no longer linked to any suites)
78 a add ARCH DESCRIPTION [SUITELIST]
79 add architecture ARCH with DESCRIPTION.
80 If SUITELIST is given, add to each of the
81 suites at the same time
84 component list show a list of components
85 component rm COMPONENT remove a component (will only work if
87 component add NAME DESCRIPTION ORDERING
88 add component NAME with DESCRIPTION.
92 s list [--print-archive]
94 s show SUITE show config details for a suite
95 s add SUITE VERSION [ label=LABEL ] [ description=DESCRIPTION ]
96 [ origin=ORIGIN ] [ codename=CODENAME ]
97 [ signingkey=SIGNINGKEY ] [ archive=ARCHIVE ]
98 add suite SUITE, version VERSION.
99 label, description, origin, codename
100 and signingkey are optional.
102 s add-all-arches SUITE VERSION... as "s add" but adds suite-architecture
103 relationships for all architectures
105 suite-architecture / s-a:
106 s-a list show the architectures for all suites
107 s-a list-suite ARCH show the suites an ARCH is in
108 s-a list-arch SUITE show the architectures in a SUITE
109 s-a add SUITE ARCH add ARCH to suite
110 s-a rm SUITE ARCH remove ARCH from suite (will only work if
111 no packages remain for the arch in the suite)
113 suite-component / s-c:
114 s-c list show the architectures for all suites
115 s-c list-suite COMPONENT
116 show the suites a COMPONENT is in
117 s-c list-component SUITE
118 show the components in a SUITE
119 s-c add SUITE COMPONENT
120 add COMPONENT to suite
121 s-c rm SUITE COMPONENT remove component from suite (will only work if
122 no packages remain for the component in the suite)
125 archive list list all archives
126 archive add NAME ROOT DESCRIPTION [primary-mirror=MIRROR] [tainted=1]
127 add archive NAME with path ROOT,
128 primary mirror MIRROR.
129 archive rm NAME remove archive NAME (will only work if there are
130 no files and no suites in the archive)
131 archive rename OLD NEW rename archive OLD to NEW
134 v-c list show version checks for all suites
135 v-c list-suite SUITE show version checks for suite SUITE
136 v-c add SUITE CHECK REFERENCE add a version check for suite SUITE
137 v-c rm SUITE CHECK REFERENCE remove a version check
139 CHECK is one of Enhances, MustBeNewerThan, MustBeOlderThan
140 REFERENCE is another suite name
143 change-component SUITE COMPONENT source SOURCE...
144 change-component SUITE COMPONENT binary BINARY...
145 Move source or binary packages to a different component by copying
146 associated files and changing the overrides.
148 forget-signature FILE: forget that we saw FILE
152 ################################################################################
154 def __architecture_list(d, args):
155 q = d.session().query(Architecture).order_by(Architecture.arch_string)
157 # HACK: We should get rid of source from the arch table
158 if j.arch_string == 'source': continue
162 def __architecture_add(d, args):
163 die_arglen(args, 4, "E: adding an architecture requires a name and a description")
164 print "Adding architecture %s" % args[2]
165 suites = [str(x) for x in args[4:]]
167 print "Adding to suites %s" % ", ".join(suites)
172 a.arch_string = str(args[2]).lower()
173 a.description = str(args[3])
176 su = get_suite(sn, s)
180 warn("W: Cannot find suite %s" % su)
182 except IntegrityError as e:
183 die("E: Integrity error adding architecture %s (it probably already exists)" % args[2])
184 except SQLAlchemyError as e:
185 die("E: Error adding architecture %s (%s)" % (args[2], e))
186 print "Architecture %s added" % (args[2])
188 def __architecture_rm(d, args):
189 die_arglen(args, 3, "E: removing an architecture requires at least a name")
190 print "Removing architecture %s" % args[2]
194 a = get_architecture(args[2].lower(), s)
196 die("E: Cannot find architecture %s" % args[2])
199 except IntegrityError as e:
200 die("E: Integrity error removing architecture %s (suite-arch entries probably still exist)" % args[2])
201 except SQLAlchemyError as e:
202 die("E: Error removing architecture %s (%s)" % (args[2], e))
203 print "Architecture %s removed" % args[2]
205 def architecture(command):
206 args = [str(x) for x in command]
207 Cnf = utils.get_conf()
210 die_arglen(args, 2, "E: architecture needs at least a command")
212 mode = args[1].lower()
214 __architecture_list(d, args)
216 __architecture_add(d, args)
218 __architecture_rm(d, args)
220 die("E: architecture command unknown")
222 dispatch['architecture'] = architecture
223 dispatch['a'] = architecture
225 ################################################################################
227 def component_list():
228 session = DBConn().session()
229 for component in session.query(Component).order_by(Component.component_name):
230 print "{0} ordering={1}".format(component.component_name, component.ordering)
232 def component_add(args):
233 (name, description, ordering) = args[0:3]
237 description=description,
241 for option in args[3:]:
242 (key, value) = option.split('=')
243 attributes[key] = value
245 session = DBConn().session()
247 component = Component()
248 for key, value in attributes.iteritems():
249 setattr(component, key, value)
251 session.add(component)
259 def component_rm(name):
260 session = DBConn().session()
261 component = get_component(name, session)
262 session.delete(component)
270 def component_rename(oldname, newname):
271 session = DBConn().session()
272 component = get_component(oldname, session)
273 component.component_name = newname
281 def component(command):
285 elif mode == 'rename':
286 component_rename(command[2], command[3])
288 component_add(command[2:])
290 component_rm(command[2])
292 die("E: component command unknown")
294 dispatch['component'] = component
296 ################################################################################
298 def __suite_list(d, args):
300 for j in s.query(Suite).join(Suite.archive).order_by(Archive.archive_name, Suite.suite_name).all():
301 if len(args) > 2 and args[2] == "--print-archive":
302 print "{0} {1}".format(j.archive.archive_name, j.suite_name)
304 print "{0}".format(j.suite_name)
306 def __suite_show(d, args):
308 die("E: showing an suite entry requires a suite")
311 su = get_suite(args[2].lower())
313 die("E: can't find suite entry for %s" % (args[2].lower()))
317 def __suite_add(d, args, addallarches=False):
318 die_arglen(args, 4, "E: adding a suite requires at least a name and a version")
319 suite_name = args[2].lower()
323 def get_field(field):
325 if varval.startswith(field + '='):
326 return varval.split('=')[1]
329 print "Adding suite %s" % suite_name
334 suite.suite_name = suite_name
335 suite.overridecodename = suite_name
336 suite.version = version
337 suite.label = get_field('label')
338 suite.description = get_field('description')
339 suite.origin = get_field('origin')
340 suite.codename = get_field('codename')
341 signingkey = get_field('signingkey')
342 if signingkey is not None:
343 suite.signingkeys = [signingkey.upper()]
344 archive_name = get_field('archive')
345 if archive_name is not None:
346 suite.archive = get_archive(archive_name, s)
348 suite.archive = s.query(Archive).filter(~Archive.archive_name.in_(['build-queues', 'new', 'policy'])).one()
349 suite.srcformats = s.query(SrcFormat).all()
352 except IntegrityError as e:
353 die("E: Integrity error adding suite %s (it probably already exists)" % suite_name)
354 except SQLAlchemyError as e:
355 die("E: Error adding suite %s (%s)" % (suite_name, e))
356 print "Suite %s added" % (suite_name)
360 q = s.query(Architecture).order_by(Architecture.arch_string)
362 suite.architectures.append(arch)
363 arches.append(arch.arch_string)
365 print "Architectures %s added to %s" % (','.join(arches), suite_name)
369 def __suite_rm(d, args):
370 die_arglen(args, 3, "E: removing a suite requires at least a name")
372 print "Removing suite {0}".format(name)
376 su = get_suite(name.lower())
378 die("E: Cannot find suite {0}".format(name))
381 except IntegrityError as e:
382 die("E: Integrity error removing suite {0} (suite-arch entries probably still exist)".format(name))
383 except SQLAlchemyError as e:
384 die("E: Error removing suite {0} ({1})".format(name, e))
385 print "Suite {0} removed".format(name)
388 args = [str(x) for x in command]
389 Cnf = utils.get_conf()
392 die_arglen(args, 2, "E: suite needs at least a command")
394 mode = args[1].lower()
397 __suite_list(d, args)
399 __suite_show(d, args)
403 __suite_add(d, args, False)
404 elif mode == 'add-all-arches':
405 __suite_add(d, args, True)
407 die("E: suite command unknown")
409 dispatch['suite'] = suite
410 dispatch['s'] = suite
412 ################################################################################
414 def __suite_architecture_list(d, args):
416 for j in s.query(Suite).order_by(Suite.suite_name):
417 architectures = j.get_architectures(skipsrc = True, skipall = True)
418 print j.suite_name + ': ' + \
419 ', '.join([a.arch_string for a in architectures])
421 def __suite_architecture_listarch(d, args):
422 die_arglen(args, 3, "E: suite-architecture list-arch requires a suite")
423 suite = get_suite(args[2].lower(), d.session())
425 die('E: suite %s is invalid' % args[2].lower())
426 a = suite.get_architectures(skipsrc = True, skipall = True)
431 def __suite_architecture_listsuite(d, args):
432 die_arglen(args, 3, "E: suite-architecture list-suite requires an arch")
433 architecture = get_architecture(args[2].lower(), d.session())
434 if architecture is None:
435 die("E: architecture %s is invalid" % args[2].lower())
436 for j in architecture.suites:
440 def __suite_architecture_add(d, args):
442 die("E: adding a suite-architecture entry requires a suite and arch")
446 suite = get_suite(args[2].lower(), s)
447 if suite is None: die("E: Can't find suite %s" % args[2].lower())
449 for arch_name in args[3:]:
450 arch = get_architecture(arch_name.lower(), s)
451 if arch is None: die("E: Can't find architecture %s" % args[3].lower())
454 suite.architectures.append(arch)
456 except IntegrityError as e:
457 die("E: Can't add suite-architecture entry (%s, %s) - probably already exists" % (args[2].lower(), arch_name))
458 except SQLAlchemyError as e:
459 die("E: Can't add suite-architecture entry (%s, %s) - %s" % (args[2].lower(), arch_name, e))
461 print "Added suite-architecture entry for %s, %s" % (args[2].lower(), arch_name)
468 def __suite_architecture_rm(d, args):
470 die("E: removing an suite-architecture entry requires a suite and arch")
475 suite_name = args[2].lower()
476 suite = get_suite(suite_name, s)
478 die('E: no such suite %s' % suite_name)
479 arch_string = args[3].lower()
480 architecture = get_architecture(arch_string, s)
481 if architecture not in suite.architectures:
482 die("E: architecture %s not found in suite %s" % (arch_string, suite_name))
483 suite.architectures.remove(architecture)
485 except IntegrityError as e:
486 die("E: Can't remove suite-architecture entry (%s, %s) - it's probably referenced" % (args[2].lower(), args[3].lower()))
487 except SQLAlchemyError as e:
488 die("E: Can't remove suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
490 print "Removed suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower())
493 def suite_architecture(command):
494 args = [str(x) for x in command]
495 Cnf = utils.get_conf()
498 die_arglen(args, 2, "E: suite-architecture needs at least a command")
500 mode = args[1].lower()
503 __suite_architecture_list(d, args)
504 elif mode == 'list-arch':
505 __suite_architecture_listarch(d, args)
506 elif mode == 'list-suite':
507 __suite_architecture_listsuite(d, args)
509 __suite_architecture_add(d, args)
511 __suite_architecture_rm(d, args)
513 die("E: suite-architecture command unknown")
515 dispatch['suite-architecture'] = suite_architecture
516 dispatch['s-a'] = suite_architecture
518 ################################################################################
520 def __suite_component_list(d, args):
522 for j in s.query(Suite).order_by(Suite.suite_name):
523 components = j.components
524 print j.suite_name + ': ' + \
525 ', '.join([c.component_name for c in components])
528 def __suite_component_listcomponent(d, args):
529 die_arglen(args, 3, "E: suite-component list-component requires a suite")
530 suite = get_suite(args[2].lower(), d.session())
532 die('E: suite %s is invalid' % args[2].lower())
533 for c in suite.components:
534 print c.component_name
537 def __suite_component_listsuite(d, args):
538 die_arglen(args, 3, "E: suite-component list-suite requires an component")
539 component = get_component(args[2].lower(), d.session())
540 if component is None:
541 die("E: component %s is invalid" % args[2].lower())
542 for s in component.suites:
546 def __suite_component_add(d, args):
548 die("E: adding a suite-component entry requires a suite and component")
552 suite = get_suite(args[2].lower(), s)
553 if suite is None: die("E: Can't find suite %s" % args[2].lower())
555 for component_name in args[3:]:
556 component = get_component(component_name.lower(), s)
557 if component is None: die("E: Can't find component %s" % args[3].lower())
560 suite.components.append(component)
562 except IntegrityError as e:
563 die("E: Can't add suite-component entry (%s, %s) - probably already exists" % (args[2].lower(), component_name))
564 except SQLAlchemyError as e:
565 die("E: Can't add suite-component entry (%s, %s) - %s" % (args[2].lower(), component_name, e))
567 print "Added suite-component entry for %s, %s" % (args[2].lower(), component_name)
573 def __suite_component_rm(d, args):
575 die("E: removing an suite-component entry requires a suite and component")
580 suite_name = args[2].lower()
581 suite = get_suite(suite_name, s)
583 die('E: no such suite %s' % suite_name)
584 component_string = args[3].lower()
585 component = get_component(arch_string, s)
586 if component not in suite.components:
587 die("E: component %s not found in suite %s" % (component_string, suite_name))
588 suite.components.remove(component)
590 except IntegrityError as e:
591 die("E: Can't remove suite-component entry (%s, %s) - it's probably referenced" % (args[2].lower(), args[3].lower()))
592 except SQLAlchemyError as e:
593 die("E: Can't remove suite-component entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
595 print "Removed suite-component entry for %s, %s" % (args[2].lower(), args[3].lower())
598 def suite_component(command):
599 args = [str(x) for x in command]
600 Cnf = utils.get_conf()
603 die_arglen(args, 2, "E: suite-component needs at least a command")
605 mode = args[1].lower()
608 __suite_component_list(d, args)
609 elif mode == 'list-component':
610 __suite_component_listcomponent(d, args)
611 elif mode == 'list-suite':
612 __suite_component_listsuite(d, args)
614 __suite_component_add(d, args)
616 # __suite_architecture_rm(d, args)
618 die("E: suite-component command unknown")
620 dispatch['suite-component'] = suite_component
621 dispatch['s-c'] = suite_component
623 ################################################################################
626 session = DBConn().session()
627 for archive in session.query(Archive).order_by(Archive.archive_name):
628 print "{0} path={1} description={2} tainted={3}".format(archive.archive_name, archive.path, archive.description, archive.tainted)
630 def archive_add(args):
631 (name, path, description) = args[0:3]
636 description=description,
639 for option in args[3:]:
640 (key, value) = option.split('=')
641 attributes[key] = value
643 session = DBConn().session()
646 for key, value in attributes.iteritems():
647 setattr(archive, key, value)
657 def archive_rm(name):
658 session = DBConn().session()
659 archive = get_archive(name, session)
660 session.delete(archive)
668 def archive_rename(oldname, newname):
669 session = DBConn().session()
670 archive = get_archive(oldname, session)
671 archive.archive_name = newname
679 def archive(command):
683 elif mode == 'rename':
684 archive_rename(command[2], command[3])
686 archive_add(command[2:])
688 archive_rm(command[2])
690 die("E: archive command unknown")
692 dispatch['archive'] = archive
694 ################################################################################
696 def __version_check_list(d):
697 session = d.session()
698 for s in session.query(Suite).order_by(Suite.suite_name):
699 __version_check_list_suite(d, s.suite_name)
701 def __version_check_list_suite(d, suite_name):
702 vcs = get_version_checks(suite_name)
704 print "%s %s %s" % (suite_name, vc.check, vc.reference.suite_name)
706 def __version_check_add(d, suite_name, check, reference_name):
707 suite = get_suite(suite_name)
709 die("E: Could not find suite %s." % (suite_name))
710 reference = get_suite(reference_name)
712 die("E: Could not find reference suite %s." % (reference_name))
714 session = d.session()
718 vc.reference = reference
722 def __version_check_rm(d, suite_name, check, reference_name):
723 suite = get_suite(suite_name)
725 die("E: Could not find suite %s." % (suite_name))
726 reference = get_suite(reference_name)
728 die("E: Could not find reference suite %s." % (reference_name))
730 session = d.session()
732 vc = session.query(VersionCheck).filter_by(suite=suite, check=check, reference=reference).one()
735 except NoResultFound:
736 print "W: version-check not found."
738 def version_check(command):
739 args = [str(x) for x in command]
740 Cnf = utils.get_conf()
743 die_arglen(args, 2, "E: version-check needs at least a command")
744 mode = args[1].lower()
747 __version_check_list(d)
748 elif mode == 'list-suite':
750 die("E: version-check list-suite needs a single parameter")
751 __version_check_list_suite(d, args[2])
754 die("E: version-check add needs three parameters")
755 __version_check_add(d, args[2], args[3], args[4])
758 die("E: version-check rm needs three parameters")
759 __version_check_rm(d, args[2], args[3], args[4])
761 die("E: version-check command unknown")
763 dispatch['version-check'] = version_check
764 dispatch['v-c'] = version_check
766 ################################################################################
768 def show_config(command):
769 args = [str(x) for x in command]
770 cnf = utils.get_conf()
772 die_arglen(args, 2, "E: config needs at least a command")
774 mode = args[1].lower()
778 if cnf.has_key("DB::Service"):
780 connstr = "postgresql://service=%s" % cnf["DB::Service"]
781 elif cnf.has_key("DB::Host"):
783 connstr = "postgres://%s" % cnf["DB::Host"]
784 if cnf.has_key("DB::Port") and cnf["DB::Port"] != "-1":
785 connstr += ":%s" % cnf["DB::Port"]
786 connstr += "/%s" % cnf["DB::Name"]
789 connstr = "postgres:///%s" % cnf["DB::Name"]
790 if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
791 connstr += "?port=%s" % cnf["DB::Port"]
793 elif mode == 'db-shell':
795 if cnf.has_key("DB::Service"):
796 e.append('PGSERVICE')
797 print "PGSERVICE=%s" % cnf["DB::Service"]
798 if cnf.has_key("DB::Name"):
799 e.append('PGDATABASE')
800 print "PGDATABASE=%s" % cnf["DB::Name"]
801 if cnf.has_key("DB::Host"):
802 print "PGHOST=%s" % cnf["DB::Host"]
804 if cnf.has_key("DB::Port") and cnf["DB::Port"] != "-1":
805 print "PGPORT=%s" % cnf["DB::Port"]
807 print "export " + " ".join(e)
809 print cnf.get(args[2])
811 session = DBConn().session()
813 o = session.query(DBConfig).filter_by(name = mode).one()
815 except NoResultFound:
816 print "W: option '%s' not set" % mode
818 dispatch['config'] = show_config
819 dispatch['c'] = show_config
821 ################################################################################
823 def show_keyring(command):
824 args = [str(x) for x in command]
825 cnf = utils.get_conf()
827 die_arglen(args, 2, "E: keyring needs at least a command")
829 mode = args[1].lower()
833 q = d.session().query(Keyring).filter(Keyring.active == True)
835 if mode == 'list-all':
837 elif mode == 'list-binary':
838 q = q.join(Keyring.acl).filter(ACL.allow_source == False)
839 elif mode == 'list-source':
840 q = q.join(Keyring.acl).filter(ACL.allow_source == True)
842 die("E: keyring command unknown")
847 def keyring_add_buildd(command):
849 arch_names = command[3:]
851 session = DBConn().session()
852 arches = session.query(Architecture).filter(Architecture.arch_string.in_(arch_names))
855 acl.name = 'buildd-{0}'.format('+'.join(arch_names))
856 acl.architectures.update(arches)
858 acl.allow_binary = True
859 acl.allow_binary_only = True
860 acl.allow_hijack = True
864 k.keyring_name = name
871 def keyring(command):
872 if command[1].startswith('list-'):
873 show_keyring(command)
874 elif command[1] == 'add-buildd':
875 keyring_add_buildd(command)
877 die("E: keyring command unknown")
879 dispatch['keyring'] = keyring
880 dispatch['k'] = keyring
882 ################################################################################
884 def change_component_source(transaction, suite, component, source_names):
885 session = transaction.session
887 overrides = session.query(Override).filter(Override.package.in_(source_names)).filter_by(suite=suite).join(OverrideType).filter_by(overridetype='dsc')
888 for override in overrides:
889 print "Changing override for {0}".format(override.package)
890 override.component = component
893 sources = session.query(DBSource).filter(DBSource.source.in_(source_names)).filter(DBSource.suites.contains(suite))
894 for source in sources:
895 print "Copying {0}={1}".format(source.source, source.version)
896 transaction.copy_source(source, suite, component)
898 def change_component_binary(transaction, suite, component, binary_names):
899 session = transaction.session
901 overrides = session.query(Override).filter(Override.package.in_(binary_names)).filter_by(suite=suite).join(OverrideType).filter(OverrideType.overridetype.in_(['deb', 'udeb']))
902 for override in overrides:
903 print "Changing override for {0}".format(override.package)
904 override.component = component
907 binaries = session.query(DBBinary).filter(DBBinary.package.in_(binary_names)).filter(DBBinary.suites.contains(suite))
908 for binary in binaries:
909 print "Copying {0}={1} [{2}]".format(binary.package, binary.version, binary.architecture.arch_string)
910 transaction.copy_binary(binary, suite, component)
913 def change_component(args):
914 with daklib.archive.ArchiveTransaction() as transaction:
915 session = transaction.session
917 suite = session.query(Suite).filter_by(suite_name=args[1]).one()
918 component = session.query(Component).filter_by(component_name=args[2]).one()
920 if args[3] == 'source':
921 change_component_source(transaction, suite, component, args[4:])
922 elif args[3] == 'binary':
923 change_component_binary(transaction, suite, component, args[4:])
925 raise Exception("Can only move source or binary, not {0}".format(args[3]))
929 dispatch['change-component'] = change_component
931 ################################################################################
933 def forget_signature(args):
935 with open(filename, 'r') as fh:
938 session = DBConn().session()
939 keyrings = [ k.keyring_name for k in session.query(Keyring).filter_by(active=True).order_by(Keyring.priority) ]
940 signed_file = daklib.gpg.SignedFile(data, keyrings)
941 history = SignatureHistory.from_signed_file(signed_file).query(session)
942 if history is not None:
943 session.delete(history)
946 print "Signature was not known to dak."
949 dispatch['forget-signature'] = forget_signature
951 ################################################################################
954 """Perform administrative work on the dak database"""
956 Cnf = utils.get_conf()
957 arguments = [('h', "help", "Admin::Options::Help"),
958 ('n', "dry-run", "Admin::Options::Dry-Run")]
959 for i in [ "help", "dry-run" ]:
960 if not Cnf.has_key("Admin::Options::%s" % (i)):
961 Cnf["Admin::Options::%s" % (i)] = ""
963 arguments = apt_pkg.parse_commandline(Cnf, arguments, sys.argv)
965 options = Cnf.subtree("Admin::Options")
966 if options["Help"] or len(arguments) < 1:
968 if options["Dry-Run"]:
971 subcommand = str(arguments[0])
973 if subcommand in dispatch.keys():
974 dispatch[subcommand](arguments)
976 die("E: Unknown command")
978 ################################################################################
980 if __name__ == '__main__':