]> git.decadent.org.uk Git - dak.git/blobdiff - dak/generate_filelist.py
daklib/queue.py: Remove unneeded imports.
[dak.git] / dak / generate_filelist.py
index d0a64596eff5579ec51b42db2a357af0b2dbaf79..faf08bd7a8680e59802d4bdf8c12d4ec0a68a21b 100755 (executable)
@@ -5,6 +5,7 @@ Generate file lists for apt-ftparchive.
 
 @contact: Debian FTP Master <ftpmaster@debian.org>
 @copyright: 2009  Torsten Werner <twerner@debian.org>
+@copyright: 2011  Ansgar Burchardt <ansgar@debian.org>
 @license: GNU General Public License version 2 or later
 """
 
@@ -22,41 +23,29 @@ Generate file lists for apt-ftparchive.
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
+################################################################################
+
+# Ganneff> Please go and try to lock mhy now. After than try to lock NEW.
+# twerner> !lock mhy
+# dak> twerner: You suck, this is already locked by Ganneff
+# Ganneff> now try with NEW
+# twerner> !lock NEW
+# dak> twerner: also locked NEW
+# mhy> Ganneff: oy, stop using me for locks and highlighting me you tall muppet
+# Ganneff> hehe :)
+
+################################################################################
+
 from daklib.dbconn import *
 from daklib.config import Config
-from daklib import utils
-import apt_pkg, os, sys
-
-def fetch(query, args, session):
-    return [path + filename for (path, filename) in \
-        session.execute(query, args).fetchall()]
-
-def getSources(suite, component, session):
-    query = """
-        SELECT path, filename
-            FROM srcfiles_suite_component
-            WHERE suite = :suite AND component = :component
-            ORDER BY filename
-    """
-    args = { 'suite': suite.suite_id,
-             'component': component.component_id }
-    return fetch(query, args, session)
-
-def getBinaries(suite, component, architecture, type, session):
-    query = """
-        SELECT path, filename
-            FROM binfiles_suite_component_arch
-            WHERE suite = :suite AND component = :component AND type = :type AND
-                  (architecture = :architecture OR architecture = 2)
-            ORDER BY filename
-    """
-    args = { 'suite': suite.suite_id,
-             'component': component.component_id,
-             'architecture': architecture.arch_id,
-             'type': type }
-    return fetch(query, args, session)
-
-def listPath(suite, component, architecture = None, type = None):
+from daklib import utils, daklog
+from daklib.dakmultiprocessing import DakProcessPool, PROC_STATUS_SUCCESS, PROC_STATUS_SIGNALRAISED
+import apt_pkg, os, stat, sys
+
+from daklib.lists import getSources, getBinaries, getArchAll
+
+def listPath(suite, component, architecture = None, type = None,
+        incremental_mode = False):
     """returns full path to the list file"""
     suffixMap = { 'deb': "binary-",
                   'udeb': "debian-installer_binary-" }
@@ -67,78 +56,161 @@ def listPath(suite, component, architecture = None, type = None):
     filename = "%s_%s_%s.list" % \
         (suite.suite_name, component.component_name, suffix)
     pathname = os.path.join(Config()["Dir::Lists"], filename)
-    return utils.open_file(pathname, "w")
+    file = utils.open_file(pathname, "a")
+    timestamp = None
+    if incremental_mode:
+        timestamp = os.fstat(file.fileno())[stat.ST_MTIME]
+    else:
+        file.seek(0)
+        file.truncate()
+    return (file, timestamp)
+
+def writeSourceList(suite_id, component_id, incremental_mode):
+    session = DBConn().session()
+    suite = Suite.get(suite_id, session)
+    component = Component.get(component_id, session)
+    (file, timestamp) = listPath(suite, component,
+            incremental_mode = incremental_mode)
+
+    message = "sources list for %s %s" % (suite.suite_name, component.component_name)
+
+    for _, filename in getSources(suite, component, session, timestamp):
+        file.write(filename + '\n')
+    session.rollback()
+    file.close()
+    return (PROC_STATUS_SUCCESS, message)
+
+def writeAllList(suite_id, component_id, architecture_id, type, incremental_mode):
+    session = DBConn().session()
+    suite = Suite.get(suite_id, session)
+    component = Component.get(component_id, session)
+    architecture = Architecture.get(architecture_id, session)
+    (file, timestamp) = listPath(suite, component, architecture, type,
+            incremental_mode)
+
+    message = "all list for %s %s (arch=%s, type=%s)" % (suite.suite_name, component.component_name, architecture.arch_string, type)
 
-def writeSourceList(suite, component, session):
-    file = listPath(suite, component)
-    for filename in getSources(suite, component, session):
+    for _, filename in getArchAll(suite, component, architecture, type,
+            session, timestamp):
         file.write(filename + '\n')
+    session.rollback()
     file.close()
+    return (PROC_STATUS_SUCCESS, message)
 
-def writeBinaryList(suite, component, architecture, type, session):
-    file = listPath(suite, component, architecture, type)
-    for filename in getBinaries(suite, component, architecture, type, session):
+def writeBinaryList(suite_id, component_id, architecture_id, type, incremental_mode):
+    session = DBConn().session()
+    suite = Suite.get(suite_id, session)
+    component = Component.get(component_id, session)
+    architecture = Architecture.get(architecture_id, session)
+    (file, timestamp) = listPath(suite, component, architecture, type,
+            incremental_mode)
+
+    message = "binary list for %s %s (arch=%s, type=%s)" % (suite.suite_name, component.component_name, architecture.arch_string, type)
+
+    for _, filename in getBinaries(suite, component, architecture, type,
+            session, timestamp):
         file.write(filename + '\n')
+    session.rollback()
     file.close()
+    return (PROC_STATUS_SUCCESS, message)
 
 def usage():
     print """Usage: dak generate_filelist [OPTIONS]
 Create filename lists for apt-ftparchive.
 
-  -s, --suite=SUITE                    act on this suite
+  -s, --suite=SUITE            act on this suite
   -c, --component=COMPONENT    act on this component
-  -a, --architecture=ARCH        act on this architecture
-  -h, --help                                 show this help and exit
+  -a, --architecture=ARCH      act on this architecture
+  -h, --help                   show this help and exit
+  -i, --incremental            activate incremental mode
 
 ARCH, COMPONENT and SUITE can be comma (or space) separated list, e.g.
-    --suite=testing,unstable"""
+    --suite=testing,unstable
+
+Incremental mode appends only newer files to existing lists."""
     sys.exit()
 
 def main():
     cnf = Config()
+    Logger = daklog.Logger('generate-filelist')
     Arguments = [('h', "help",         "Filelist::Options::Help"),
                  ('s', "suite",        "Filelist::Options::Suite", "HasArg"),
                  ('c', "component",    "Filelist::Options::Component", "HasArg"),
-                 ('a', "architecture", "Filelist::Options::Architecture", "HasArg")]
-    query_suites = DBConn().session().query(Suite)
-    suites = [suite.suite_name for suite in query_suites.all()]
+                 ('a', "architecture", "Filelist::Options::Architecture", "HasArg"),
+                 ('i', "incremental",  "Filelist::Options::Incremental")]
+    session = DBConn().session()
+    query_suites = session.query(Suite)
+    suites = [suite.suite_name for suite in query_suites]
     if not cnf.has_key('Filelist::Options::Suite'):
-        cnf['Filelist::Options::Suite'] = ','.join(suites)
-    # we can ask the database for components if 'mixed' is gone
+        cnf['Filelist::Options::Suite'] = ','.join(suites).encode()
+    query_components = session.query(Component)
+    components = \
+        [component.component_name for component in query_components]
     if not cnf.has_key('Filelist::Options::Component'):
-        cnf['Filelist::Options::Component'] = 'main,contrib,non-free'
-    query_architectures = DBConn().session().query(Architecture)
+        cnf['Filelist::Options::Component'] = ','.join(components).encode()
+    query_architectures = session.query(Architecture)
     architectures = \
-        [architecture.arch_string for architecture in query_architectures.all()]
+        [architecture.arch_string for architecture in query_architectures]
     if not cnf.has_key('Filelist::Options::Architecture'):
-        cnf['Filelist::Options::Architecture'] = ','.join(architectures)
+        cnf['Filelist::Options::Architecture'] = ','.join(architectures).encode()
     cnf['Filelist::Options::Help'] = ''
-    apt_pkg.ParseCommandLine(cnf.Cnf, Arguments, sys.argv)
-    Options = cnf.SubTree("Filelist::Options")
+    cnf['Filelist::Options::Incremental'] = ''
+    apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv)
+    Options = cnf.subtree("Filelist::Options")
     if Options['Help']:
         usage()
-    session = DBConn().session()
-    suite_arch = session.query(SuiteArchitecture)
-    for suite_name in utils.split_args(Options['Suite']):
-        suite = query_suites.filter_by(suite_name = suite_name).one()
-        join = suite_arch.filter_by(suite_id = suite.suite_id)
-        for component_name in utils.split_args(Options['Component']):
-            component = session.query(Component).\
-                filter_by(component_name = component_name).one()
-            for architecture_name in utils.split_args(Options['Architecture']):
-                architecture = query_architectures.\
-                    filter_by(arch_string = architecture_name).one()
-                try:
-                    join.filter_by(arch_id = architecture.arch_id).one()
-                    if architecture_name == 'source':
-                        writeSourceList(suite, component, session)
-                    elif architecture_name != 'all':
-                        writeBinaryList(suite, component, architecture, 'deb', session)
-                        writeBinaryList(suite, component, architecture, 'udeb', session)
-                except:
+    pool = DakProcessPool()
+    query_suites = query_suites. \
+        filter(Suite.suite_name.in_(utils.split_args(Options['Suite'])))
+    query_components = query_components. \
+        filter(Component.component_name.in_(utils.split_args(Options['Component'])))
+    query_architectures = query_architectures. \
+        filter(Architecture.arch_string.in_(utils.split_args(Options['Architecture'])))
+
+    def parse_results(message):
+        # Split out into (code, msg)
+        code, msg = message
+        if code == PROC_STATUS_SUCCESS:
+            Logger.log([msg])
+        elif code == PROC_STATUS_SIGNALRAISED:
+            Logger.log(['E: Subprocess recieved signal ', msg])
+        else:
+            Logger.log(['E: ', msg])
+
+    for suite in query_suites:
+        suite_id = suite.suite_id
+        for component in query_components:
+            component_id = component.component_id
+            for architecture in query_architectures:
+                architecture_id = architecture.arch_id
+                if architecture not in suite.architectures:
                     pass
+                elif architecture.arch_string == 'source':
+                    pool.apply_async(writeSourceList,
+                        (suite_id, component_id, Options['Incremental']), callback=parse_results)
+                elif architecture.arch_string == 'all':
+                    pool.apply_async(writeAllList,
+                        (suite_id, component_id, architecture_id, 'deb',
+                            Options['Incremental']), callback=parse_results)
+                    pool.apply_async(writeAllList,
+                        (suite_id, component_id, architecture_id, 'udeb',
+                            Options['Incremental']), callback=parse_results)
+                else: # arch any
+                    pool.apply_async(writeBinaryList,
+                        (suite_id, component_id, architecture_id, 'deb',
+                            Options['Incremental']), callback=parse_results)
+                    pool.apply_async(writeBinaryList,
+                        (suite_id, component_id, architecture_id, 'udeb',
+                            Options['Incremental']), callback=parse_results)
+    pool.close()
+    pool.join()
+
     # this script doesn't change the database
-    session.rollback()
+    session.close()
+
+    Logger.close()
+
+    sys.exit(pool.overall_status())
 
 if __name__ == '__main__':
     main()