#!/usr/bin/python
# Compare package versions between PPA and archive
#
# Copyright (C) 2009-2010, Canonical, Ltd.
# Author: Kees Cook <kees@ubuntu.com>

import sys, optparse, time
import lpl_common
import apt_pkg

apt_pkg.InitSystem();

parser = optparse.OptionParser()
parser.add_option("--ppa", help="The PPA to check from (default: ubuntu-security/ppa)", metavar="GROUP[/PPA]", action='store', default='ubuntu-security/ppa')
parser.add_option("-r","--release", help="Limit check to a specific set of comma-separate releases", metavar="SERIES", action='store', default=None)
parser.add_option("--retries", help="Retry failed sync at most RETRIES times", action='store', metavar="RETRIES", default=1, type="int")
parser.add_option("--lpnet", help="Use lpnet instead of edge for LP API", action='store_true')
parser.add_option("-d", "--destination", help="The archive to check against (default: Ubuntu Archive)", metavar="GROUP[/PPA]", action='store', default='ubuntu')
parser.add_option("--pocket", help="The destination pocket (default: Security)", metavar="POCKET", action='store', default='Security')
(opt, args) = parser.parse_args()

print "Loading Ubuntu Distribution ..."
lp = lpl_common.connect(use_edge=(not opt.lpnet))
ubuntu = lp.distributions['ubuntu']

dest_archive, dest_group, dest_ppa = lpl_common.get_archive(opt.destination, lp, verbose=True, distribution=ubuntu)

origin_archive, origin_group, origin_ppa = lpl_common.get_archive(opt.ppa, lp, verbose=True, distribution=ubuntu)

series = dict()
if opt.release:
    serieses = opt.release.split(',')
    for series_name in serieses:
        series.setdefault(series_name, ubuntu.getSeries(name_or_version=series_name))

if len(args) == 0:
    print "Loading package list ..."
    pkgs = origin_archive.getPublishedSources(status='Published', exact_match=True)
    for pkg in pkgs:
        pkg_name = pkg.source_package_name
        if pkg_name not in args:
            print "\t%s" % (pkg_name)
            args.append(pkg_name)

rc = 0
for pkg_name in args:
    wanted = []
    seen = dict()

    # Locate the package to copy
    print "Locating %s ..." % (pkg_name)
    sources = origin_archive.getPublishedSources(source_name=pkg_name,
                                                 status='Published',
                                                 exact_match=True)

    # Filter for the series we want
    for source_item in sources:
        series_name = source_item.distro_series.name
        if len(series) > 0 and not series_name in series:
            continue
        if not seen.has_key(series_name):
            seen[series_name] = []
        seen[series_name].append(source_item)

    # Identify most recent package version across all pockets
    for series_name in seen.keys():
        if len(seen[series_name]) > 1:
            seen[series_name] = sorted(seen[series_name], cmp=lambda x, y: apt_pkg.VersionCompare(x.source_package_version, y.source_package_version), reverse=True)
        wanted.append(seen[series_name][0])

    # Publish
    for source_item in wanted:
        published = dest_archive.getPublishedSources(source_name=source_item.source_package_name,
                                                     version=source_item.source_package_version,
                                                     distro_series=source_item.distro_series,
                                                     pocket=opt.pocket,
                                                     status='Published',
                                                     exact_match=True)
        count=0
        for published_item in published:
            count+=1
        pocket = ""
        if opt.pocket:
            pocket = "-%s" % (opt.pocket.lower())
        msg = "%s (%s%s/%s)" % (source_item.source_package_name, source_item.distro_series.name, pocket, source_item.source_package_version)
        if count==1:
            print "\tOK: %s" % (msg)
        else:
            print >>sys.stderr, "\tUnpublished: %s" % (msg)
            rc = 1

sys.exit(rc)
