#!/usr/bin/python3
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright © 2020      Christian Kastner <ckk@debian.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see
# <http://www.gnu.org/licenses/>.
#
#######################################################################


import argparse
import os
import platform
import psutil
import sys


MACHINE_TO_DEB_ARCH = {
    'x86_64': 'amd64',
    'i386': 'i386'
}
DEB_ARCH_TO_QEMU = {
    'amd64': 'qemu-system-x86_64',
    'i386': 'qemu-system-i386',
}


MACHINE = platform.machine()
try:
    ARCH = MACHINE_TO_DEB_ARCH[MACHINE]
except KeyError as e:
    print(f"Unsupported machine type {MACHINE}", file=sys.stderr)
    sys.exit(1)
# Defaults
MEM = 2048
CPUS = psutil.cpu_count(logical=False)
DIST = 'unstable'
_DEFAULT_IMAGEDIR = os.path.join(os.path.expanduser('~'), '.cache', 'sbuild')
IMAGEDIR = os.environ.get('IMAGEDIR', _DEFAULT_IMAGEDIR)


def main():
    # init options
    parser = argparse.ArgumentParser(
        description="Build Debian packages using sbuild(1) and QEMU images",
        epilog="All other options are passed on through to sbuild(1). "
               "The image will be started in -snapshot mode, so no changes "
               "are saved, and multiple processes can use the same image "
               "concurrently.",
    )
    parser.add_argument(
        '--arch',
        action='store',
        default=ARCH,
        help="Architecture to use. Default is the host architecture. "
             "Currently supported architectures are: "
            f"{', '.join(DEB_ARCH_TO_QEMU.keys())}.",
    )
    parser.add_argument(
        '-d', '--dist',
        action='store',
        default=DIST,
        help=f"Distribution (for the .changes file). Default is '{DIST}'.",
    )
    parser.add_argument(
        '--image',
        action='store',
        help="VM image to use for building. If not specified, will look for "
             "an image with the name DIST-autopkgtest-ARCH.img. Will first "
             "look in the current directory, and if no such file exists "
             "there, then the directory $IMAGEDIR is tried. A suitable image "
             "can be created with qemu-sbuild-create(1).",
    )
    parser.add_argument(
        '--autopkgtest-debug',
        action='store_true',
        help="Enable debug output for the autopkgtest-virt-qemu(1) driver.",
    )
    parser.add_argument(
        '--ram',
        metavar='MiB',
        action='store',
        default=MEM,
        help=f"VM memory size in MB. Default: {MEM}",
    )
    parser.add_argument(
        '--cpus',
        metavar='CPUs',
        action='store',
        default=CPUS,
        help="VM CPU count. Default: Number of physical cores on the host.",
    )
    parser.add_argument(
        '--overlay-dir',
        action='store',
        help="Directory for the temporary image overlay instead of "
             "autopkgtest's default of /tmp (or $TMPDIR).",
    )
    parser.add_argument(
        '--noexec',
        action='store_true',
        help="Don't actually do anything. Just print the sbuild(1) command "
             "string that would be executed, and then exit.",
    )
    parsed_args, unparsed_args = parser.parse_known_args()

    if parsed_args.image:
        if os.path.exists(os.path.abspath(parsed_args.image)):
            image = parsed_args.image
        else:
            image = os.path.join(IMAGEDIR, parsed_args.image)
    else:
        guessed_name = f'{parsed_args.dist}-autopkgtest-{ARCH}.img'
        if os.path.exists(os.path.abspath(guessed_name)):
            images = os.path.abspath(guessed_name)
        else:
            image = os.path.join(
                IMAGEDIR,
                f'{parsed_args.dist}-autopkgtest-{ARCH}.img',
            )
    qemu = DEB_ARCH_TO_QEMU[ARCH]

    args = [
            'sbuild',
            '--arch',                           parsed_args.arch,
            '--dist',                           parsed_args.dist,
            '--purge-build=never',
            '--purge-deps=never',
            '--chroot-mode=autopkgtest',
            '--autopkgtest-virt-server=qemu',
            '--autopkgtest-virt-server-opt',    '--overlay-dir=/tmp',
            '--autopkgtest-virt-server-opt',    f'--qemu-command={qemu}',
            '--autopkgtest-virt-server-opt',    f'--ram-size={parsed_args.ram}',
            '--autopkgtest-virt-server-opt',    f'--cpus={parsed_args.cpus}',
            '--autopkgtest-virt-server-opt',    image,
            # Worarkound -- dose can hang stuff in a qemu VM
            '--bd-uninstallable-explainer',     'apt',
        ]
    if parsed_args.autopkgtest_debug:
        args += ['--autopkgtest-virt-server-opt', '--debug']
    if parsed_args.overlay_dir:
        d = parsed_args.overlay_dir
        args += ['--autopkgtest-virt-server-opt', f'--overlay_dir={d}']

    # Pass on the remaining arguments to sbuild
    args += unparsed_args

    print(' '.join(str(a) for a in args))
    if not parsed_args.noexec:
        os.execvp(args[0], args)


if __name__ == '__main__':
    main()
