]> git.decadent.org.uk Git - dak.git/blobdiff - dak/admin.py
Merge remote-tracking branch 'jcristau/cs-set-log-suite'
[dak.git] / dak / admin.py
index e4d1034d0ac247ba2cda62018b3fb203c65eae07..0be5e6c0a74b9d73a73706c2859324b22dc662be 100755 (executable)
@@ -23,6 +23,9 @@ import sys
 
 import apt_pkg
 
+import daklib.archive
+import daklib.gpg
+
 from daklib import utils
 from daklib.dbconn import *
 from sqlalchemy.orm.exc import NoResultFound
@@ -98,6 +101,8 @@ Perform administrative work on the dak database.
 
      s add-all-arches SUITE VERSION... as "s add" but adds suite-architecture
                             relationships for all architectures
+     s add-build-queue SUITE BUILD-QUEUE BUILD-QUEUE-CODENAME BUILD-QUEUE-ARCHIVE
+                            add a build queue for an existing suite
 
   suite-architecture / s-a:
      s-a list               show the architectures for all suites
@@ -107,6 +112,17 @@ Perform administrative work on the dak database.
      s-a rm SUITE ARCH      remove ARCH from suite (will only work if
                             no packages remain for the arch in the suite)
 
+  suite-component / s-c:
+     s-c list               show the architectures for all suites
+     s-c list-suite COMPONENT
+                            show the suites a COMPONENT is in
+     s-c list-component SUITE
+                            show the components in a SUITE
+     s-c add SUITE COMPONENT
+                            add COMPONENT to suite
+     s-c rm SUITE COMPONENT remove component from suite (will only work if
+                            no packages remain for the component in the suite)
+
   archive:
      archive list           list all archives
      archive add NAME ROOT DESCRIPTION [primary-mirror=MIRROR] [tainted=1]
@@ -124,6 +140,14 @@ Perform administrative work on the dak database.
        where
          CHECK     is one of Enhances, MustBeNewerThan, MustBeOlderThan
         REFERENCE is another suite name
+
+  change-component:
+     change-component SUITE COMPONENT source SOURCE...
+     change-component SUITE COMPONENT binary BINARY...
+         Move source or binary packages to a different component by copying
+         associated files and changing the overrides.
+
+  forget-signature FILE:    forget that we saw FILE
 """
     sys.exit(exit_code)
 
@@ -298,6 +322,9 @@ def __suite_add(d, args, addallarches=False):
     version = args[3]
     rest = args[3:]
 
+    if len(version) == 0:
+        version = None
+
     def get_field(field):
         for varval in args:
             if varval.startswith(field + '='):
@@ -362,6 +389,60 @@ def __suite_rm(d, args):
             die("E: Error removing suite {0} ({1})".format(name, e))
     print "Suite {0} removed".format(name)
 
+def __suite_add_build_queue(d, args):
+    session = d.session()
+
+    die_arglen(args, 6, "E: Adding a build queue needs four parameters.")
+
+    suite_name = args[2]
+    build_queue_name = args[3]
+    build_queue_codename = args[4]
+    build_queue_archive_name = args[5]
+    try:
+        suite = session.query(Suite).filter_by(suite_name=suite_name).one()
+    except NoResultFound:
+        die("E: Unknown suite '{0}'".format(suite_name))
+    try:
+        build_queue_archive = session.query(Archive).filter_by(archive_name=build_queue_archive_name).one()
+    except NoResultFound:
+        die("E: Unknown archive '{0}'".format(build_queue_archive_name))
+
+    # Create suite
+    s = Suite()
+    s.suite_name = build_queue_name
+    s.origin = suite.origin
+    s.label = suite.label
+    s.description = "buildd {0} incoming".format(suite_name)
+    s.codename = build_queue_codename
+    s.notautomatic = suite.notautomatic
+    s.overridesuite = suite.overridesuite or suite.suite_name
+    s.butautomaticupgrades = suite.butautomaticupgrades
+    s.signingkeys = suite.signingkeys
+    s.include_long_description = False
+
+    # Do not accept direct uploads to the build queue
+    s.accept_source_uploads = False
+    s.accept_binary_uploads = False
+
+    s.archive = build_queue_archive
+    s.architectures.extend(suite.architectures)
+    s.components.extend(suite.components)
+    s.srcformats.extend(suite.srcformats)
+
+    session.add(s)
+    session.flush()
+
+    bq = BuildQueue()
+    bq.queue_name = build_queue_codename
+    bq.suite = s
+
+    session.add(bq)
+    session.flush()
+
+    suite.copy_queues.append(bq)
+
+    session.commit()
+
 def suite(command):
     args = [str(x) for x in command]
     Cnf = utils.get_conf()
@@ -381,6 +462,8 @@ def suite(command):
         __suite_add(d, args, False)
     elif mode == 'add-all-arches':
         __suite_add(d, args, True)
+    elif mode == 'add-build-queue':
+        __suite_add_build_queue(d, args)
     else:
         die("E: suite command unknown")
 
@@ -424,20 +507,24 @@ def __suite_architecture_add(d, args):
     suite = get_suite(args[2].lower(), s)
     if suite is None: die("E: Can't find suite %s" % args[2].lower())
 
-    arch = get_architecture(args[3].lower(), s)
-    if arch is None: die("E: Can't find architecture %s" % args[3].lower())
+    for arch_name in args[3:]:
+        arch = get_architecture(arch_name.lower(), s)
+        if arch is None: die("E: Can't find architecture %s" % args[3].lower())
 
-    if not dryrun:
         try:
             suite.architectures.append(arch)
-            s.commit()
+            s.flush()
         except IntegrityError as e:
-            die("E: Can't add suite-architecture entry (%s, %s) - probably already exists" % (args[2].lower(), args[3].lower()))
+            die("E: Can't add suite-architecture entry (%s, %s) - probably already exists" % (args[2].lower(), arch_name))
         except SQLAlchemyError as e:
-            die("E: Can't add suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
+            die("E: Can't add suite-architecture entry (%s, %s) - %s" % (args[2].lower(), arch_name, e))
+
+        print "Added suite-architecture entry for %s, %s" % (args[2].lower(), arch_name)
 
-    print "Added suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower())
+    if not dryrun:
+        s.commit()
 
+    s.close()
 
 def __suite_architecture_rm(d, args):
     if len(args) < 3:
@@ -491,6 +578,111 @@ dispatch['s-a'] = suite_architecture
 
 ################################################################################
 
+def __suite_component_list(d, args):
+    s = d.session()
+    for j in s.query(Suite).order_by(Suite.suite_name):
+        components = j.components
+        print j.suite_name + ': ' + \
+              ', '.join([c.component_name for c in components])
+
+
+def __suite_component_listcomponent(d, args):
+     die_arglen(args, 3, "E: suite-component list-component requires a suite")
+     suite = get_suite(args[2].lower(), d.session())
+     if suite is None:
+         die('E: suite %s is invalid' % args[2].lower())
+     for c in suite.components:
+         print c.component_name
+
+
+def __suite_component_listsuite(d, args):
+     die_arglen(args, 3, "E: suite-component list-suite requires an component")
+     component = get_component(args[2].lower(), d.session())
+     if component is None:
+         die("E: component %s is invalid" % args[2].lower())
+     for s in component.suites:
+         print s.suite_name
+
+
+def __suite_component_add(d, args):
+     if len(args) < 3:
+         die("E: adding a suite-component entry requires a suite and component")
+
+     s = d.session()
+
+     suite = get_suite(args[2].lower(), s)
+     if suite is None: die("E: Can't find suite %s" % args[2].lower())
+
+     for component_name in args[3:]:
+         component = get_component(component_name.lower(), s)
+         if component is None: die("E: Can't find component %s" % args[3].lower())
+
+         try:
+             suite.components.append(component)
+             s.flush()
+         except IntegrityError as e:
+             die("E: Can't add suite-component entry (%s, %s) - probably already exists" % (args[2].lower(), component_name))
+         except SQLAlchemyError as e:
+             die("E: Can't add suite-component entry (%s, %s) - %s" % (args[2].lower(), component_name, e))
+
+         print "Added suite-component entry for %s, %s" % (args[2].lower(), component_name)
+
+     if not dryrun:
+         s.commit()
+     s.close()
+
+def __suite_component_rm(d, args):
+     if len(args) < 3:
+         die("E: removing an suite-component entry requires a suite and component")
+
+     s = d.session()
+     if not dryrun:
+         try:
+             suite_name = args[2].lower()
+             suite = get_suite(suite_name, s)
+             if suite is None:
+                 die('E: no such suite %s' % suite_name)
+             component_string = args[3].lower()
+             component = get_component(arch_string, s)
+             if component not in suite.components:
+                 die("E: component %s not found in suite %s" % (component_string, suite_name))
+             suite.components.remove(component)
+             s.commit()
+         except IntegrityError as e:
+             die("E: Can't remove suite-component entry (%s, %s) - it's probably referenced" % (args[2].lower(), args[3].lower()))
+         except SQLAlchemyError as e:
+             die("E: Can't remove suite-component entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
+
+     print "Removed suite-component entry for %s, %s" % (args[2].lower(), args[3].lower())
+
+
+def suite_component(command):
+    args = [str(x) for x in command]
+    Cnf = utils.get_conf()
+    d = DBConn()
+
+    die_arglen(args, 2, "E: suite-component needs at least a command")
+
+    mode = args[1].lower()
+
+    if mode == 'list':
+        __suite_component_list(d, args)
+    elif mode == 'list-component':
+        __suite_component_listcomponent(d, args)
+    elif mode == 'list-suite':
+        __suite_component_listsuite(d, args)
+    elif mode == 'add':
+        __suite_component_add(d, args)
+    # elif mode == 'rm':
+    #     __suite_architecture_rm(d, args)
+    else:
+        die("E: suite-component command unknown")
+
+dispatch['suite-component'] = suite_component
+dispatch['s-c'] = suite_component
+
+################################################################################
+
 def archive_list():
     session = DBConn().session()
     for archive in session.query(Archive).order_by(Archive.archive_name):
@@ -750,6 +942,75 @@ dispatch['k'] = keyring
 
 ################################################################################
 
+def change_component_source(transaction, suite, component, source_names):
+    session = transaction.session
+
+    overrides = session.query(Override).filter(Override.package.in_(source_names)).filter_by(suite=suite).join(OverrideType).filter_by(overridetype='dsc')
+    for override in overrides:
+        print "Changing override for {0}".format(override.package)
+        override.component = component
+    session.flush()
+
+    sources = session.query(DBSource).filter(DBSource.source.in_(source_names)).filter(DBSource.suites.contains(suite))
+    for source in sources:
+        print "Copying {0}={1}".format(source.source, source.version)
+        transaction.copy_source(source, suite, component)
+
+def change_component_binary(transaction, suite, component, binary_names):
+    session = transaction.session
+
+    overrides = session.query(Override).filter(Override.package.in_(binary_names)).filter_by(suite=suite).join(OverrideType).filter(OverrideType.overridetype.in_(['deb', 'udeb']))
+    for override in overrides:
+        print "Changing override for {0}".format(override.package)
+        override.component = component
+    session.flush()
+
+    binaries = session.query(DBBinary).filter(DBBinary.package.in_(binary_names)).filter(DBBinary.suites.contains(suite))
+    for binary in binaries:
+        print "Copying {0}={1} [{2}]".format(binary.package, binary.version, binary.architecture.arch_string)
+        transaction.copy_binary(binary, suite, component)
+    pass
+
+def change_component(args):
+    with daklib.archive.ArchiveTransaction() as transaction:
+        session = transaction.session
+
+        suite = session.query(Suite).filter_by(suite_name=args[1]).one()
+        component = session.query(Component).filter_by(component_name=args[2]).one()
+
+        if args[3] == 'source':
+            change_component_source(transaction, suite, component, args[4:])
+        elif args[3] == 'binary':
+            change_component_binary(transaction, suite, component, args[4:])
+        else:
+            raise Exception("Can only move source or binary, not {0}".format(args[3]))
+
+        transaction.commit()
+
+dispatch['change-component'] = change_component
+
+################################################################################
+
+def forget_signature(args):
+    filename = args[1]
+    with open(filename, 'r') as fh:
+        data = fh.read()
+
+    session = DBConn().session()
+    keyrings = [ k.keyring_name for k in session.query(Keyring).filter_by(active=True).order_by(Keyring.priority) ]
+    signed_file = daklib.gpg.SignedFile(data, keyrings)
+    history = SignatureHistory.from_signed_file(signed_file).query(session)
+    if history is not None:
+        session.delete(history)
+        session.commit()
+    else:
+        print "Signature was not known to dak."
+    session.rollback()
+
+dispatch['forget-signature'] = forget_signature
+
+################################################################################
+
 def main():
     """Perform administrative work on the dak database"""
     global dryrun