#!/usr/bin/python
# Checks the kernel ABI versions to make sure there are no mismatches
# between -security and -updates.
#
# Copyright (C) 2009-2010 Canonical, Ltd.
# Author: Kees Cook <kees@ubuntu.com>

import lpl_common
import sys

lp = lpl_common.connect()
ubuntu = lp.distributions['ubuntu']
archive = ubuntu.main_archive

def get_version(src, series, pocket):
    pubs = archive.getPublishedSources(exact_match=True,
                                   source_name=src,
                                   status="Published",
                                   pocket=pocket,
                                   distro_series=series)
    count = 0
    for pub in pubs:
        count += 1
    if count > 1:
        raise ValueError, count
    if count == 1:
        return pubs[0].source_package_version
    return None

def package_abi(version):
    return int(version.split('-').pop().split('.',1)[0])

def meta_abi(version, offset=-2):
    return int(version.split('.').pop(offset))

def pocket_abis_match(release, suffix, srcs, metas):

    series = ubuntu.getSeries(name_or_version=release)

    pkg = dict()
    meta = dict()
    for pocket in ['Updates', 'Security']:
        for src in srcs:
            pkg.setdefault(src,dict())
            pkg[src].setdefault(pocket,dict())
            #print 'fetching %s in %s %s ...' % (src, release, pocket)
            pkg[src][pocket]['name'] = src
            pkg[src][pocket]['version'] = get_version(src, series, pocket)

        # Add metas
        for src in metas:
            meta.setdefault(src,dict())
            meta[src].setdefault(pocket,dict())
            meta[src][pocket]['name'] = src
            meta[src][pocket]['version'] = get_version(src, series, pocket)
            if not meta[src][pocket]['version']:
                print >>sys.stderr, '%s missing in %s %s' % (src, release, pocket)
                sys.exit(1)

    ok = True
    for src in srcs:
        for pocket in ['Updates', 'Security']:
            if not pkg[src][pocket]['version']:
                raise ValueError, 'missing %s in %s %s' % (src, release, pocket)

            abi  = package_abi(pkg[src][pocket]['version'])

            for name in sorted(meta.keys()):
                mabi = meta_abi(meta[name][pocket]['version'])

                # Hack for different format and out of sync ABI on dapper
                if (release == 'dapper'):
                    mabi = meta_abi(meta[name][pocket]['version'],-1)
                    mabi -= 1

                if abi != mabi:
                    ok = False
                    print >>sys.stderr, "FAIL: ABI mismatch in %s %s: %d != %d (%s %s vs %s %s)" % (release, pocket, mabi, abi, meta[name][pocket]['name'], meta[name][pocket]['version'], pkg[src][pocket]['name'], pkg[src][pocket]['version'])
#                else:
#                    print "ok: ABI matches in %s %s: %d == %d (%s %s vs %s %s)" % (release, pocket, mabi, abi, pkg['meta'][pocket]['name'], pkg['meta'][pocket]['version'], src, pkg[src][pocket]['version'])


ok = True
if not pocket_abis_match('dapper','-2.6.15',['linux-source-2.6.15','linux-restricted-modules-2.6.15','linux-backports-modules-2.6.15'],['linux-meta']): ok = False
if not pocket_abis_match('hardy','-2.6.24',['linux','linux-restricted-modules-2.6.24','linux-backports-modules-2.6.24','linux-ubuntu-modules-2.6.24'],['linux-meta']): ok = False

if not pocket_abis_match('intrepid','-2.6.27',['linux','linux-restricted-modules','linux-backports-modules-2.6.27'],['linux-meta']): ok = False

if not pocket_abis_match('jaunty','-2.6.28',['linux','linux-restricted-modules','linux-backports-modules-2.6.28'],['linux-meta']): ok = False

if not pocket_abis_match('karmic','-2.6.31',['linux','linux-backports-modules-2.6.31'],['linux-meta','linux-ports-meta']): ok = False
if not pocket_abis_match('karmic','-2.6.31',['linux-ec2'],['linux-meta-ec2']): ok = False
if not pocket_abis_match('karmic','-2.6.31',['linux-fsl-imx51'],['linux-meta-fsl-imx51']): ok = False
if not pocket_abis_match('karmic','-2.6.31',['linux-mvl-dove'],['linux-meta-mvl-dove']): ok = False

if ok:
    sys.exit(0)
else:
    sys.exit(1)
