]> git.decadent.org.uk Git - dak.git/blobdiff - daklib/cruft.py
Add by-hash support
[dak.git] / daklib / cruft.py
index 79787e26cc81ab120cfc1af5f7504f0ef544ed0c..05666ceba2e34f84eec7d98af41cea5a1d76ecd7 100644 (file)
@@ -24,6 +24,7 @@ helper functions for cruft-report
 from daklib.dbconn import *
 
 from sqlalchemy import func
+from sqlalchemy.orm import object_session
 
 def newer_version(lowersuite_name, highersuite_name, session):
     '''
@@ -46,5 +47,185 @@ def newer_version(lowersuite_name, highersuite_name, session):
             with_parent(lowersuite).group_by(DBSource.source).scalar()
         if lowerversion is not None:
             list.append((source, higherversion, lowerversion))
+
+    list.sort()
     return list
 
+def get_package_names(suite):
+    '''
+    Returns a query that selects all distinct package names from suite ordered
+    by package name.
+    '''
+
+    session = object_session(suite)
+    return session.query(DBBinary.package).with_parent(suite). \
+        group_by(DBBinary.package).order_by(DBBinary.package)
+
+class NamedSource(object):
+    '''
+    A source package identified by its name with all of its versions in a
+    suite.
+    '''
+    def __init__(self, suite, source):
+        self.source = source
+        query = suite.sources.filter_by(source = source). \
+            order_by(DBSource.version)
+        self.versions = [src.version for src in query]
+
+    def __str__(self):
+        return "%s(%s)" % (self.source, ", ".join(self.versions))
+
+class DejavuBinary(object):
+    '''
+    A binary package identified by its name which gets built by multiple source
+    packages in a suite. The architecture is ignored which leads to the
+    following corner case, e.g.:
+
+    If a source package 'foo-mips' that builds a binary package 'foo' on mips
+    and another source package 'foo-mipsel' builds a binary package with the
+    same name 'foo' on mipsel then the binary package 'foo' will be reported as
+    built from multiple source packages.
+    '''
+
+    def __init__(self, suite, package):
+        self.package = package
+        session = object_session(suite)
+        # We need a subquery to make sure that both binary and source packages
+        # are in the right suite.
+        bin_query = suite.binaries.filter_by(package = package).subquery()
+        src_query = session.query(DBSource.source).with_parent(suite). \
+            join(bin_query).order_by(DBSource.source).group_by(DBSource.source)
+        self.sources = []
+        if src_query.count() > 1:
+            for source, in src_query:
+                self.sources.append(str(NamedSource(suite, source)))
+
+    def has_multiple_sources(self):
+        'Has the package been built by multiple sources?'
+        return len(self.sources) > 1
+
+    def __str__(self):
+        return "%s built by: %s" % (self.package, ", ".join(self.sources))
+
+def report_multiple_source(suite):
+    '''
+    Reports binary packages built from multiple source package with different
+    names.
+    '''
+
+    print "Built from multiple source packages"
+    print "-----------------------------------"
+    print
+    for package, in get_package_names(suite):
+        binary = DejavuBinary(suite, package)
+        if binary.has_multiple_sources():
+            print binary
+    print
+
+
+def query_without_source(suite_id, session):
+    """searches for arch: all packages from suite that do no longer
+    reference a source package in the same suite
+
+    subquery unique_binaries: selects all packages with only 1 version
+    in suite since 'dak rm' does not allow to specify version numbers"""
+
+    query = """
+    with unique_binaries as
+        (select package, max(version) as version, max(source) as source
+            from bin_associations_binaries
+        where architecture = 2 and suite = :suite_id
+            group by package having count(*) = 1)
+    select ub.package, ub.version
+        from unique_binaries ub
+        left join src_associations_src sas
+        on ub.source = sas.src and sas.suite = :suite_id
+        where sas.id is null
+        order by ub.package"""
+    return session.execute(query, {'suite_id': suite_id})
+
+
+def queryNBS(suite_id, session):
+    """This one is really complex. It searches arch != all packages that
+    are no longer built from current source packages in suite.
+
+    temp table unique_binaries: will be populated with packages that
+    have only one version in suite because 'dak rm' does not allow
+    specifying version numbers
+
+    temp table newest_binaries: will be populated with packages that are
+    built from current sources
+
+    subquery uptodate_arch: returns all architectures built from current
+    sources
+
+    subquery unique_binaries_uptodate_arch: returns all packages in
+    architectures from uptodate_arch
+
+    subquery unique_binaries_uptodate_arch_agg: same as
+    unique_binaries_uptodate_arch but with column architecture
+    aggregated to array
+
+    subquery uptodate_packages: similar to uptodate_arch but returns all
+    packages built from current sources
+
+    subquery outdated_packages: returns all packages with architectures
+    no longer built from current source
+    """
+
+    query = """
+create temp table unique_binaries (
+    package text not null,
+    architecture integer not null,
+    source integer not null);
+
+insert into unique_binaries
+    select bab.package, bab.architecture, max(bab.source)
+        from bin_associations_binaries bab
+        where bab.suite = :suite_id and bab.architecture > 2
+        group by package, architecture having count(*) = 1;
+
+create temp table newest_binaries (
+    package text not null,
+    architecture integer not null,
+    source text not null,
+    version debversion not null);
+
+insert into newest_binaries
+    select ub.package, ub.architecture, nsa.source, nsa.version
+        from unique_binaries ub
+        join newest_src_association nsa
+            on ub.source = nsa.src and nsa.suite = :suite_id;
+
+with uptodate_arch as
+    (select architecture, source, version
+        from newest_binaries
+        group by architecture, source, version),
+    unique_binaries_uptodate_arch as
+    (select ub.package, ub.architecture, ua.source, ua.version
+        from unique_binaries ub
+        join source s
+            on ub.source = s.id
+        join uptodate_arch ua
+            on ub.architecture = ua.architecture and s.source = ua.source),
+    unique_binaries_uptodate_arch_agg as
+    (select ubua.package,
+        array(select unnest(array_agg(a.arch_string)) order by 1) as arch_list,
+        ubua.source, ubua.version
+        from unique_binaries_uptodate_arch ubua
+        join architecture a
+            on ubua.architecture = a.id
+        group by ubua.source, ubua.version, ubua.package),
+    uptodate_packages as
+    (select package, source, version
+        from newest_binaries
+        group by package, source, version),
+    outdated_packages as
+    (select array(select unnest(array_agg(package)) order by 1) as pkg_list,
+        arch_list, source, version
+        from unique_binaries_uptodate_arch_agg
+        where package not in
+            (select package from uptodate_packages)
+        group by arch_list, source, version)
+    select * from outdated_packages order by source"""
+    return session.execute(query, {'suite_id': suite_id})