#!/usr/bin/env python3

# Copyright 2021 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# pylint: disable=missing-function-docstring

"""Chrome OS kernel configuration tool

Script to merge all configs and run 'make oldconfig' on it to wade out bad
juju, then split the configs into distro-commmon and flavour-specific parts

See this page for more details:
http://dev.chromium.org/chromium-os/how-tos-and-troubleshooting/kernel-configuration
"""

import argparse
import difflib
import fnmatch
import glob
import logging
import os
import re
import shutil
import subprocess
import sys
import tempfile
from typing import Dict, List

MODES = ['oldconfig', 'olddefconfig', 'editconfig', 'genconfig', 'checkconfig']
TOOLCHAIN_PREFIXES = {
    'x86_64': 'x86_64-cros-linux-gnu',
    'armel': 'armv7a-cros-linux-gnueabihf',
    'arm64': 'aarch64-cros-linux-gnu',
}


def splitconfig(srcdir: str) -> Dict[str, str]:
    """Split and merge common configs

    Return dict of filename-to-contents.
    """
    allconfigs = {}

    # Parse config files.
    for config in os.listdir(srcdir):
        # Only config.*
        if not config.endswith('.config'):
            continue

        allconfigs[config] = set()

        for line in open(os.path.join(srcdir, config)):
            m = re.match(r'#*\s*CONFIG_(\w+)[\s=](.*)$', line)
            if not m:
                continue
            option, value = m.groups()
            allconfigs[config].add((option, value))

    # Split out common config options.
    common = None
    for config in allconfigs:
        if common is None:
            common = allconfigs[config].copy()
        else:
            common &= allconfigs[config]
    for config in allconfigs:
        allconfigs[config] -= common
    allconfigs['common.config'] = common

    ret = {}
    # Generate new splitconfigs.
    for config in allconfigs:
        if allconfigs[config] is None:
            continue
        contents = '#\n# Config options generated by splitconfig\n#\n'
        for option, value in sorted(list(allconfigs[config])):
            if value == 'is not set':
                contents += '# CONFIG_%s %s\n' % (option, value)
            else:
                contents += 'CONFIG_%s=%s\n' % (option, value)
        ret[config] = contents
    return ret


def die(msg: str = 'Aborting'):
    logging.error(msg)
    sys.exit(1)


def in_chroot() -> bool:
    return os.path.exists('/etc/cros_chroot_version')


def rerun_in_chroot():
    cmd = ['cros_sdk', '--working-dir', '.', '--',
           os.path.relpath(sys.argv[0])] + sys.argv[1:]
    logging.info('Re-running in chroot')
    logging.debug('Run: %s', cmd)
    sys.exit(subprocess.run(cmd, check=False).returncode)


def make_toolchain_args(arch: str) -> Dict[str, str]:
    ret = {
        'LD': 'ld.lld',
    }

    if in_chroot():
        prefix = TOOLCHAIN_PREFIXES[arch]
        ccompiler = prefix + '-clang'
        # CrOS build tooling wants us to use these, and avoid a default of
        # unprefixed 'gcc' or 'clang'. Supply defaults here, but also consider
        # environment varibles below.
        ret['HOSTCC'] = 'x86_64-pc-linux-gnu-clang'
        ret['HOSTCXX'] = 'x86_64-pc-linux-gnu-clang++'
    else:
        prefix = 'x86_64-linux-gnu'
        ccompiler = prefix + '-gcc'

    if not shutil.which(ccompiler):
        if in_chroot():
            die('%s not found. Try running "`sudo cros_setup_toolchains -t %s`"'
                % (ccompiler, prefix))
        else:
            die('%s not found. Try running inside chroot.' % ccompiler)

    # Propagate a few environment variables as make args.
    for key in ('HOSTCC', 'HOSTCXX'):
        val = os.getenv(key)
        if val:
            ret[key] = val

    ret.update({
        'CC': ccompiler,
        'CXX': prefix + '-g++',
        'CROSS_COMPILE': prefix + '-',
    })
    return ret


def getchar() -> str:
    # We don't want line-buffering, and shelling out to bash is much simpler
    # than messing with tty settings.
    return subprocess.check_output(
            ['bash', '-c', 'read -n 1 -s; echo "${REPLY}"']
            ).decode('utf-8').strip()


def editconfig_prompt(variant: str) -> bool:
    print('* %s: press <Enter> to edit, S to skip' % variant)
    return getchar() not in ('S', 's')


def filter_match(target: str, pattern: str) -> bool:
    return fnmatch.fnmatch(target, '*' + pattern + '*')


def is_editconfig_interactive(arch_flavour: str, prompt: bool,
                              pattern: str) -> bool:
    if filter_match(arch_flavour, pattern):
        if not prompt:
            return True
        return editconfig_prompt(arch_flavour)
    return False


def make_cmd(builddir: str, arch: str, target: str) -> List[str]:
    pairs = make_toolchain_args(arch)
    pairs['ARCH'] = 'arm' if arch == 'armel' else arch
    pairs['O'] = builddir

    make_args = [k + '=' + v for k, v in pairs.items()]

    return ['make', '-j'] + make_args + [target, 'savedefconfig']


def checkconfig(srcdir: str, outdir: str) -> int:
    error = 0
    for src_config in glob.glob(srcdir + '/chromeos/config/**/*.config',
                                recursive=True):
        relative = os.path.relpath(src_config, srcdir)
        out_config = os.path.join(outdir, relative)
        logging.debug('Compare %s to %s', src_config, out_config)
        before = open(src_config, 'r').readlines()
        after = open(out_config, 'r').readlines()

        if before == after:
            continue

        error = 1
        diff = difflib.context_diff(before, after, fromfile='a/' + relative,
                                    tofile='b/' + relative)
        sys.stdout.writelines(diff)
        logging.error('checkconfig failed for config %s', relative)

    if error:
        logging.error("""Consider running `%s olddefconfig` to normalize.

NOTE: chromeos/config changes should always be in a CL by themselves and never
squashed into the same patch as code changes. If code and config changes need
to land together, consider using Cq-Depend to make a circular dependency.""",
                      sys.argv[0])
    else:
        logging.info('All good!')
    return error


def build_one_arch(args, tmpdir: str, srcdir: str, family: str,
                   arch: str) -> List[subprocess.Popen]:
    procs = []
    config_base_dir = srcdir + '/chromeos/config/' + family
    config_arch_dir = config_base_dir + '/' + arch
    for flavourconfig in glob.glob(os.path.join(srcdir, config_arch_dir,
        '*.flavour.config')):
        flavour = os.path.basename(flavourconfig)
        builddir = os.path.join(tmpdir, 'build', family, arch, flavour)
        os.makedirs(builddir)

        # Merge base.config, common.config, <flavour>.flavour.config
        conf = '\n'.join(open(os.path.join(srcdir, f)).read() for f in [
                config_base_dir + '/base.config',
                config_arch_dir + '/common.config',
                config_arch_dir + '/' + flavour,
        ])
        open(os.path.join(builddir, '.config'), 'w').write(conf)

        interactive = False
        if args.mode == 'genconfig':
            mode = 'olddefconfig'
        elif args.mode == 'editconfig':
            interactive = is_editconfig_interactive(
                    family + '/' + arch + '/' + flavour,
                    not args.yes, args.filter)
            mode = 'menuconfig' if interactive else 'olddefconfig'
        elif args.mode == 'checkconfig':
            mode = 'olddefconfig'
        else:
            if args.mode == 'oldconfig':
                # 'oldconfig' may run into interactive prompts.
                interactive = True
            mode = args.mode

        cmd = make_cmd(builddir, arch, mode)
        if interactive:
            logging.info('Starting interactive cmd: %s', ' '.join(cmd))
            ret = subprocess.run(cmd, check=False, cwd=srcdir)
            if ret.returncode:
                die('cmd "%s" failed' % ' '.join(cmd))
        else:
            logging.info('Starting background cmd: %s', ' '.join(cmd))
            procs += [subprocess.Popen(cmd, cwd=srcdir,
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE)]
    return procs


def do_splitconfig(tmpdir: str, srcdir: str, outdir: str,
                   family: str, arches: List[str], save_configs: bool):
    family_cfg_dir = 'chromeos/config/' + family

    if save_configs:
        keep_dir = 'CONFIGS/' + family
        os.makedirs(keep_dir, exist_ok=True)

    for arch in arches:
        dest = os.path.join(tmpdir, family, arch)
        family_arch_dir = family_cfg_dir + '/' + arch
        os.makedirs(dest)
        for flavourconfig in glob.glob(os.path.join(srcdir, family_arch_dir,
                                       '*.flavour.config')):
            flavour = os.path.basename(flavourconfig)
            builddir = os.path.join(tmpdir, 'build', family, arch, flavour)
            shutil.copy(os.path.join(builddir, 'defconfig'),
                        os.path.join(dest, flavour))
            if save_configs:
                shutil.copy(os.path.join(builddir, '.config'),
                            os.path.join(keep_dir, arch + '-' + flavour))
                shutil.copy(os.path.join(builddir, 'defconfig'),
                            os.path.join(keep_dir, arch + '-' +
                                         flavour + '.def'))
        os.makedirs(os.path.join(outdir, family_arch_dir), exist_ok=True)
        # Find per-arch common items; flavour-unique options can be written out
        # immediately.
        for config, contents in splitconfig(dest).items():
            if config == 'common.config':
                open(os.path.join(tmpdir, family, arch + '.config'),
                     'w').write(contents)
            else:
                open(os.path.join(outdir, family_arch_dir, config),
                     'w').write(contents)

    # Find cross-arch common items; common ones go to base.config, and unique
    # ones to <arch>/common.config.
    for config, contents in splitconfig(tmpdir + '/' + family).items():
        if config == 'common.config':
            open(os.path.join(outdir, family_cfg_dir, 'base.config'),
                 'w').write(contents)
        else:
            assert config.endswith('.config')
            # Python3.9: arch = config.removesuffix('.config')
            arch = config[:-len('.config')]
            open(os.path.join(outdir, family_cfg_dir, arch, 'common.config'),
                 'w').write(contents)


# Arches relevant to this family.
def family_arches(family: str) -> List[str]:
    return [os.path.basename(p)
            for p in glob.glob('chromeos/config/' + family + '/*')
            if os.path.isdir(p)]


def doit(args, tmpdir: str) -> int:
    for d in (os.getcwd(),
              os.path.abspath(os.path.join(
                  os.path.dirname(sys.argv[0]), '..', '..'))):
        if (os.path.exists(os.path.join(d, 'MAINTAINERS')) and
            os.path.exists(os.path.join(d, 'Makefile'))):
            srcdir = d
            logging.info('Using top kernel dir: %s', srcdir)
            break
    else:
        die('This does not appear to be a kernel source directory.')

    if not in_chroot() and not args.force:
        rerun_in_chroot()
        assert False # Should not reach this.

    # Most commands write back to source directory.
    if args.mode == 'checkconfig':
        outdir = tmpdir
    else:
        outdir = srcdir

    save_configs = args.mode == 'genconfig'

    procs = []

    families = [os.path.basename(p)
                for p in glob.glob('chromeos/config/*')
                if os.path.isdir(p)]
    for family in families:
        for arch in family_arches(family):
            if not arch in TOOLCHAIN_PREFIXES:
                die('Unexpected arch: %s' % arch)
            procs += build_one_arch(args, tmpdir, srcdir, family, arch)

    for p in procs:
        ret = p.wait()
        if ret:
            assert p.stderr # Remind pytype we captured stderr.
            logging.error(p.stderr.read().decode('utf-8'))
            die('cmd "%s" failed' % ' '.join(p.args))

    logging.info('Generating splitconfigs')
    for family in families:
        do_splitconfig(tmpdir, srcdir, outdir,
                       family, family_arches(family), save_configs)

    if args.mode == 'checkconfig':
        return checkconfig(srcdir, outdir)

    return 0


def main() -> int:
    parser = argparse.ArgumentParser(
            description='Chrome OS kernel configuration script',
            epilog="""
               Note that Kbuild will evaluate some features depending on the
               toolchain, so we try to enter the SDK chroot. This can be
               overridden, with a potentially degraded experience.
               """)

    log_level_choices = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
    parser.add_argument(
        '--log_level', '-l',
        choices=log_level_choices,
        default='INFO'
    )
    parser.add_argument('--force', '-F', action='store_true',
                        help='Force allowing to run outside the chroot')
    parser.add_argument('--filter', '-f', default='',
                        help='Only attempt to edit configs which match filter')
    parser.add_argument('--yes', '-y', action='store_true',
                        help='Edit all configs which match unconditionally')
    parser.add_argument('mode', choices=MODES, help='sub-command/mode')

    args = parser.parse_args()
    logging.basicConfig(level=args.log_level,
                        format='%(levelname)s - %(message)s')

    with tempfile.TemporaryDirectory() as tmpdir:
        return doit(args, tmpdir)


sys.exit(main())
