#!/usr/bin/python

"""
Generates a list of packages which can be rebuild depending on the already
rebuild packages in our staging repositories
"""

import argparse
import tempfile

from pyalpm import Handle
import pyalpm

ARCH = "x86_64"
MIRROR_URL = "https://mirror.pkgbuild.com/{}/os/{}"

def register_dbs(handle, reponames):
    repos = []

    for reponame in reponames:
        repo = handle.register_syncdb(reponame, pyalpm.SIG_DATABASE_OPTIONAL)
        repo.servers = [MIRROR_URL.format(reponame, ARCH)]
        repo.update(False)
        repos.append(repo)

    return repos


def find_package_anywhere(handle, pkgname):
    for db in handle.get_syncdbs():
        pkg = db.get_pkg(pkgname)
        if pkg:
            return pkg

    return None


def can_rebuild(rebuild_packages, stable_handle, staging_handle):
    rebuild_packages_set = set(rebuild_packages)

    def is_all_rebuild(depends):
        for pkg in depends:
            if pkg not in rebuild_packages_set:
                continue

            if not find_package_anywhere(staging_handle, pkg):
                return False

        return True

    can_rebuild_list = []
    for pkgname in rebuild_packages:
        # Already rebuild
        pkg = find_package_anywhere(staging_handle, pkgname)
        if pkg is not None:
            continue

        pkg = find_package_anywhere(stable_handle, pkgname)
        # Can never happen
        if pkg is None:
            continue

        if is_all_rebuild(pkg.depends) and is_all_rebuild(pkg.makedepends) and is_all_rebuild(pkg.checkdepends):
            can_rebuild_list.append(pkgname)

    return can_rebuild_list


def compare_repos(rebuild_packages, staging_handle):
    missing = []
    for pkgname in rebuild_packages:
        if find_package_anywhere(staging_handle, pkgname) is None:
            missing.append(pkgname)

    return missing

def main(filename, verify, output_format):
    # Output of `genrebuild`.
    rebuild_packages = []
    packages = []

    with open(filename, 'r') as fp:
        rebuild_packages = fp.read().splitlines()

    with tempfile.TemporaryDirectory() as stable_tmpdir:
        with tempfile.TemporaryDirectory() as staging_tmpdir:
            stable_handle = Handle(".", stable_tmpdir)
            staging_handle = Handle(".", staging_tmpdir)

            register_dbs(stable_handle, ["core", "extra", "multilib"])
            register_dbs(staging_handle, ["core-staging", "extra-staging", "multilib-staging"])

            if verify:
                packages = compare_repos(rebuild_packages, staging_handle)
            else:
                packages = can_rebuild(rebuild_packages, stable_handle, staging_handle)

            if output_format == 'space':
                print(' '.join(packages))
            elif output_format == 'newline':
                print('\n'.join(packages))
            else:
                print('unsupported output format')

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
                        prog='canrebuild',
                        description='Returns packges which can be rebuild in the staging repositories')
    parser.add_argument('filename')
    parser.add_argument('--format', default='space', choices=['space', 'newline'])
    parser.add_argument('--verify', action=argparse.BooleanOptionalAction, help='compare staging versus stable packages')

    args = parser.parse_args()
    main(args.filename, args.verify, args.format)
