#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-only
#

import sys, os, subprocess, re, shutil

allowed = (
    # type is supported by dash
    'if type systemctl >/dev/null 2>/dev/null; then',
    'if type systemd-tmpfiles >/dev/null 2>/dev/null; then',
    'type update-rc.d >/dev/null 2>/dev/null; then',
    'command -v',
    # HOSTNAME is set locally
    'buildhistory_single_commit "$CMDLINE" "$HOSTNAME"',
    # False-positive, match is a grep not shell expression
    'grep "^$groupname:[^:]*:[^:]*:\\([^,]*,\\)*$username\\(,[^,]*\\)*"',
    # TODO verify dash's '. script args' behaviour
    '. $target_sdk_dir/${oe_init_build_env_path} $target_sdk_dir >> $LOGFILE'
    )

def is_allowed(s):
    for w in allowed:
        if w in s:
            return True
    return False

SCRIPT_LINENO_RE = re.compile(r' line (\d+) ')
BASHISM_WARNING = re.compile(r'^(possible bashism in.*)$', re.MULTILINE)

def process(filename, function, lineno, script):
    import tempfile

    if not script.startswith("#!"):
        script = "#! /bin/sh\n" + script

    fn = tempfile.NamedTemporaryFile(mode="w+t")
    fn.write(script)
    fn.flush()

    try:
        subprocess.check_output(("checkbashisms.pl", fn.name), universal_newlines=True, stderr=subprocess.STDOUT)
        # No bashisms, so just return
        return
    except subprocess.CalledProcessError as e:
        # TODO check exit code is 1

        # Replace the temporary filename with the function and split it
        output = e.output.replace(fn.name, function)
        if not output or not output.startswith('possible bashism'):
            # Probably starts with or contains only warnings. Dump verbatim
            # with one space indention. Can't do the splitting and allowed
            # checking below.
            return '\n'.join([filename,
                              ' Unexpected output from checkbashisms.pl'] +
                             [' ' + x for x in output.splitlines()])

        # We know that the first line matches and that therefore the first
        # list entry will be empty - skip it.
        output = BASHISM_WARNING.split(output)[1:]
        # Turn the output into a single string like this:
        # /.../foobar.bb
        #  possible bashism in updatercd_postrm line 2 (type):
        #   if ${@use_updatercd(d)} && type update-rc.d >/dev/null 2>/dev/null; then
        #  ...
        #   ...
        result = []
        # Check the results against the allowed list
        for message, source in zip(output[0::2], output[1::2]):
            if not is_whitelisted(source):
                if lineno is not None:
                    message = SCRIPT_LINENO_RE.sub(lambda m: ' line %d ' % (int(m.group(1)) + int(lineno) - 1),
                                                   message)
                result.append(' ' + message.strip())
                result.extend(['  %s' % x for x in source.splitlines()])
        if result:
            result.insert(0, filename)
            return '\n'.join(result)
        else:
            return None

def get_tinfoil():
    scripts_path = os.path.dirname(os.path.realpath(__file__))
    lib_path = scripts_path + '/lib'
    sys.path = sys.path + [lib_path]
    import scriptpath
    scriptpath.add_bitbake_lib_path()
    import bb.tinfoil
    tinfoil = bb.tinfoil.Tinfoil()
    tinfoil.prepare()
    # tinfoil.logger.setLevel(logging.WARNING)
    return tinfoil

if __name__=='__main__':
    import argparse, shutil

    parser = argparse.ArgumentParser(description='Bashim detector for shell fragments in recipes.')
    parser.add_argument("recipes", metavar="RECIPE", nargs="*", help="recipes to check (if not specified, all will be checked)")
    parser.add_argument("--verbose", default=False, action="store_true")
    args = parser.parse_args()

    if shutil.which("checkbashisms.pl") is None:
        print("Cannot find checkbashisms.pl on $PATH, get it from https://salsa.debian.org/debian/devscripts/raw/master/scripts/checkbashisms.pl")
        sys.exit(1)

    # The order of defining the worker function,
    # initializing the pool and connecting to the
    # bitbake server is crucial, don't change it.
    def func(item):
        (filename, key, lineno), script = item
        if args.verbose:
            print("Scanning %s:%s" % (filename, key))
        return process(filename, key, lineno, script)

    import multiprocessing
    pool = multiprocessing.Pool()

    tinfoil = get_tinfoil()

    # This is only the default configuration and should iterate over
    # recipecaches to handle multiconfig environments
    pkg_pn = tinfoil.cooker.recipecaches[""].pkg_pn

    if args.recipes:
        initial_pns = args.recipes
    else:
        initial_pns = sorted(pkg_pn)

    pns = set()
    scripts = {}
    print("Generating scripts...")
    for pn in initial_pns:
        for fn in pkg_pn[pn]:
            # There's no point checking multiple BBCLASSEXTENDed variants of the same recipe
            # (at least in general - there is some risk that the variants contain different scripts)
            realfn, _, _ = bb.cache.virtualfn2realfn(fn)
            if realfn not in pns:
                pns.add(realfn)
                data = tinfoil.parse_recipe_file(realfn)
                for key in data.keys():
                    if data.getVarFlag(key, "func") and not data.getVarFlag(key, "python"):
                        script = data.getVar(key, False)
                        if script:
                            filename = data.getVarFlag(key, "filename")
                            lineno = data.getVarFlag(key, "lineno")
                            # There's no point in checking a function multiple
                            # times just because different recipes include it.
                            # We identify unique scripts by file, name, and (just in case)
                            # line number.
                            attributes = (filename or realfn, key, lineno)
                            scripts.setdefault(attributes, script)


    print("Scanning scripts...\n")
    for result in pool.imap(func, scripts.items()):
        if result:
            print(result)
    tinfoil.shutdown()
