# Yocto Project layer check tool
#
# Copyright (C) 2017 Intel Corporation
#
# SPDX-License-Identifier: MIT
#

import os
import re
import subprocess
from enum import Enum

import bb.tinfoil

class LayerType(Enum):
    BSP = 0
    DISTRO = 1
    SOFTWARE = 2
    ERROR_NO_LAYER_CONF = 98
    ERROR_BSP_DISTRO = 99

def _get_configurations(path):
    configs = []

    for f in os.listdir(path):
        file_path = os.path.join(path, f)
        if os.path.isfile(file_path) and f.endswith('.conf'):
            configs.append(f[:-5]) # strip .conf
    return configs

def _get_layer_collections(layer_path, lconf=None, data=None):
    import bb.parse
    import bb.data

    if lconf is None:
        lconf = os.path.join(layer_path, 'conf', 'layer.conf')

    if data is None:
        ldata = bb.data.init()
        bb.parse.init_parser(ldata)
    else:
        ldata = data.createCopy()

    ldata.setVar('LAYERDIR', layer_path)
    try:
        ldata = bb.parse.handle(lconf, ldata, include=True)
    except:
        raise RuntimeError("Parsing of layer.conf from layer: %s failed" % layer_path)
    ldata.expandVarref('LAYERDIR')

    collections = (ldata.getVar('BBFILE_COLLECTIONS') or '').split()
    if not collections:
        name = os.path.basename(layer_path)
        collections = [name]

    collections = {c: {} for c in collections}
    for name in collections:
        priority = ldata.getVar('BBFILE_PRIORITY_%s' % name)
        pattern = ldata.getVar('BBFILE_PATTERN_%s' % name)
        depends = ldata.getVar('LAYERDEPENDS_%s' % name)
        compat = ldata.getVar('LAYERSERIES_COMPAT_%s' % name)
        try:
            depDict = bb.utils.explode_dep_versions2(depends or "")
        except bb.utils.VersionStringException as vse:
            bb.fatal('Error parsing LAYERDEPENDS_%s: %s' % (name, str(vse)))

        collections[name]['priority'] = priority
        collections[name]['pattern'] = pattern
        collections[name]['depends'] = ' '.join(depDict.keys())
        collections[name]['compat'] = compat

    return collections

def _detect_layer(layer_path):
    """
        Scans layer directory to detect what type of layer
        is BSP, Distro or Software.

        Returns a dictionary with layer name, type and path.
    """

    layer = {}
    layer_name = os.path.basename(layer_path)

    layer['name'] = layer_name
    layer['path'] = layer_path
    layer['conf'] = {}

    if not os.path.isfile(os.path.join(layer_path, 'conf', 'layer.conf')):
        layer['type'] = LayerType.ERROR_NO_LAYER_CONF
        return layer

    machine_conf = os.path.join(layer_path, 'conf', 'machine')
    distro_conf = os.path.join(layer_path, 'conf', 'distro')

    is_bsp = False
    is_distro = False

    if os.path.isdir(machine_conf):
        machines = _get_configurations(machine_conf)
        if machines:
            is_bsp = True

    if os.path.isdir(distro_conf):
        distros = _get_configurations(distro_conf)
        if distros:
            is_distro = True

    if is_bsp and is_distro:
        layer['type'] = LayerType.ERROR_BSP_DISTRO
    elif is_bsp:
        layer['type'] = LayerType.BSP
        layer['conf']['machines'] = machines
    elif is_distro:
        layer['type'] = LayerType.DISTRO
        layer['conf']['distros'] = distros
    else:
        layer['type'] = LayerType.SOFTWARE

    layer['collections'] = _get_layer_collections(layer['path'])

    return layer

def detect_layers(layer_directories, no_auto):
    layers = []

    for directory in layer_directories:
        directory = os.path.realpath(directory)
        if directory[-1] == '/':
            directory = directory[0:-1]

        if no_auto:
            conf_dir = os.path.join(directory, 'conf')
            if os.path.isdir(conf_dir):
                layer = _detect_layer(directory)
                if layer:
                    layers.append(layer)
        else:
            for root, dirs, files in os.walk(directory):
                dir_name = os.path.basename(root)
                conf_dir = os.path.join(root, 'conf')
                if os.path.isdir(conf_dir):
                    layer = _detect_layer(root)
                    if layer:
                        layers.append(layer)

    return layers

def _find_layer_depends(depend, layers):
    for layer in layers:
        if 'collections' not in layer:
            continue

        for collection in layer['collections']:
            if depend == collection:
                return layer
    return None

def add_layer_dependencies(bblayersconf, layer, layers, logger):
    def recurse_dependencies(depends, layer, layers, logger, ret = []):
        logger.debug('Processing dependencies %s for layer %s.' % \
                    (depends, layer['name']))

        for depend in depends.split():
            # core (oe-core) is suppose to be provided
            if depend == 'core':
                continue

            layer_depend = _find_layer_depends(depend, layers)
            if not layer_depend:
                logger.error('Layer %s depends on %s and isn\'t found.' % \
                        (layer['name'], depend))
                ret = None
                continue

            # We keep processing, even if ret is None, this allows us to report
            # multiple errors at once
            if ret is not None and layer_depend not in ret:
                ret.append(layer_depend)
            else:
                # we might have processed this dependency already, in which case
                # we should not do it again (avoid recursive loop)
                continue

            # Recursively process...
            if 'collections' not in layer_depend:
                continue

            for collection in layer_depend['collections']:
                collect_deps = layer_depend['collections'][collection]['depends']
                if not collect_deps:
                    continue
                ret = recurse_dependencies(collect_deps, layer_depend, layers, logger, ret)

        return ret

    layer_depends = []
    for collection in layer['collections']:
        depends = layer['collections'][collection]['depends']
        if not depends:
            continue

        layer_depends = recurse_dependencies(depends, layer, layers, logger, layer_depends)

    # Note: [] (empty) is allowed, None is not!
    if layer_depends is None:
        return False
    else:
        add_layers(bblayersconf, layer_depends, logger)

    return True

def add_layers(bblayersconf, layers, logger):
    # Don't add a layer that is already present.
    added = set()
    output = check_command('Getting existing layers failed.', 'bitbake-layers show-layers').decode('utf-8')
    for layer, path, pri in re.findall(r'^(\S+) +([^\n]*?) +(\d+)$', output, re.MULTILINE):
        added.add(path)

    with open(bblayersconf, 'a+') as f:
        for layer in layers:
            logger.info('Adding layer %s' % layer['name'])
            name = layer['name']
            path = layer['path']
            if path in added:
                logger.info('%s is already in %s' % (name, bblayersconf))
            else:
                added.add(path)
                f.write("\nBBLAYERS += \"%s\"\n" % path)
    return True

def check_command(error_msg, cmd, cwd=None):
    '''
    Run a command under a shell, capture stdout and stderr in a single stream,
    throw an error when command returns non-zero exit code. Returns the output.
    '''

    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=cwd)
    output, _ = p.communicate()
    if p.returncode:
        msg = "%s\nCommand: %s\nOutput:\n%s" % (error_msg, cmd, output.decode('utf-8'))
        raise RuntimeError(msg)
    return output

def get_signatures(builddir, failsafe=False, machine=None):
    import re

    # some recipes needs to be excluded like meta-world-pkgdata
    # because a layer can add recipes to a world build so signature
    # will be change
    exclude_recipes = ('meta-world-pkgdata',)

    sigs = {}
    tune2tasks = {}

    cmd = 'BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE BB_SIGNATURE_HANDLER" BB_SIGNATURE_HANDLER="OEBasicHash" '
    if machine:
        cmd += 'MACHINE=%s ' % machine
    cmd += 'bitbake '
    if failsafe:
        cmd += '-k '
    cmd += '-S none world'
    sigs_file = os.path.join(builddir, 'locked-sigs.inc')
    if os.path.exists(sigs_file):
        os.unlink(sigs_file)
    try:
        check_command('Generating signatures failed. This might be due to some parse error and/or general layer incompatibilities.',
                      cmd, builddir)
    except RuntimeError as ex:
        if failsafe and os.path.exists(sigs_file):
            # Ignore the error here. Most likely some recipes active
            # in a world build lack some dependencies. There is a
            # separate test_machine_world_build which exposes the
            # failure.
            pass
        else:
            raise

    sig_regex = re.compile("^(?P<task>.*:.*):(?P<hash>.*) .$")
    tune_regex = re.compile("(^|\s)SIGGEN_LOCKEDSIGS_t-(?P<tune>\S*)\s*=\s*")
    current_tune = None
    with open(sigs_file, 'r') as f:
        for line in f.readlines():
            line = line.strip()
            t = tune_regex.search(line)
            if t:
                current_tune = t.group('tune')
            s = sig_regex.match(line)
            if s:
                exclude = False
                for er in exclude_recipes:
                    (recipe, task) = s.group('task').split(':')
                    if er == recipe:
                        exclude = True
                        break
                if exclude:
                    continue

                sigs[s.group('task')] = s.group('hash')
                tune2tasks.setdefault(current_tune, []).append(s.group('task'))

    if not sigs:
        raise RuntimeError('Can\'t load signatures from %s' % sigs_file)

    return (sigs, tune2tasks)

def get_depgraph(targets=['world'], failsafe=False):
    '''
    Returns the dependency graph for the given target(s).
    The dependency graph is taken directly from DepTreeEvent.
    '''
    depgraph = None
    with bb.tinfoil.Tinfoil() as tinfoil:
        tinfoil.prepare(config_only=False)
        tinfoil.set_event_mask(['bb.event.NoProvider', 'bb.event.DepTreeGenerated', 'bb.command.CommandCompleted'])
        if not tinfoil.run_command('generateDepTreeEvent', targets, 'do_build'):
            raise RuntimeError('starting generateDepTreeEvent failed')
        while True:
            event = tinfoil.wait_event(timeout=1000)
            if event:
                if isinstance(event, bb.command.CommandFailed):
                    raise RuntimeError('Generating dependency information failed: %s' % event.error)
                elif isinstance(event, bb.command.CommandCompleted):
                    break
                elif isinstance(event, bb.event.NoProvider):
                    if failsafe:
                        # The event is informational, we will get information about the
                        # remaining dependencies eventually and thus can ignore this
                        # here like we do in get_signatures(), if desired.
                        continue
                    if event._reasons:
                        raise RuntimeError('Nothing provides %s: %s' % (event._item, event._reasons))
                    else:
                        raise RuntimeError('Nothing provides %s.' % (event._item))
                elif isinstance(event, bb.event.DepTreeGenerated):
                    depgraph = event._depgraph

    if depgraph is None:
        raise RuntimeError('Could not retrieve the depgraph.')
    return depgraph

def compare_signatures(old_sigs, curr_sigs):
    '''
    Compares the result of two get_signatures() calls. Returns None if no
    problems found, otherwise a string that can be used as additional
    explanation in self.fail().
    '''
    # task -> (old signature, new signature)
    sig_diff = {}
    for task in old_sigs:
        if task in curr_sigs and \
           old_sigs[task] != curr_sigs[task]:
            sig_diff[task] = (old_sigs[task], curr_sigs[task])

    if not sig_diff:
        return None

    # Beware, depgraph uses task=<pn>.<taskname> whereas get_signatures()
    # uses <pn>:<taskname>. Need to convert sometimes. The output follows
    # the convention from get_signatures() because that seems closer to
    # normal bitbake output.
    def sig2graph(task):
        pn, taskname = task.rsplit(':', 1)
        return pn + '.' + taskname
    def graph2sig(task):
        pn, taskname = task.rsplit('.', 1)
        return pn + ':' + taskname
    depgraph = get_depgraph(failsafe=True)
    depends = depgraph['tdepends']

    # If a task A has a changed signature, but none of its
    # dependencies, then we need to report it because it is
    # the one which introduces a change. Any task depending on
    # A (directly or indirectly) will also have a changed
    # signature, but we don't need to report it. It might have
    # its own changes, which will become apparent once the
    # issues that we do report are fixed and the test gets run
    # again.
    sig_diff_filtered = []
    for task, (old_sig, new_sig) in sig_diff.items():
        deps_tainted = False
        for dep in depends.get(sig2graph(task), ()):
            if graph2sig(dep) in sig_diff:
                deps_tainted = True
                break
        if not deps_tainted:
            sig_diff_filtered.append((task, old_sig, new_sig))

    msg = []
    msg.append('%d signatures changed, initial differences (first hash before, second after):' %
               len(sig_diff))
    for diff in sorted(sig_diff_filtered):
        recipe, taskname = diff[0].rsplit(':', 1)
        cmd = 'bitbake-diffsigs --task %s %s --signature %s %s' % \
              (recipe, taskname, diff[1], diff[2])
        msg.append('   %s: %s -> %s' % diff)
        msg.append('      %s' % cmd)
        try:
            output = check_command('Determining signature difference failed.',
                                   cmd).decode('utf-8')
        except RuntimeError as error:
            output = str(error)
        if output:
            msg.extend(['      ' + line for line in output.splitlines()])
            msg.append('')
    return '\n'.join(msg)
