#!/usr/bin/env python3

# bitbake-diffsigs / bitbake-dumpsig
# BitBake task signature data dump and comparison utility
#
# Copyright (C) 2012-2013, 2017 Intel Corporation
#
# SPDX-License-Identifier: GPL-2.0-only
#

import os
import sys
import warnings

warnings.simplefilter("default")
import argparse
import logging
import pickle

sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))

import bb.tinfoil
import bb.siggen
import bb.msg

myname = os.path.basename(sys.argv[0])
logger = bb.msg.logger_create(myname)

is_dump = myname == 'bitbake-dumpsig'


def find_siginfo(tinfoil, pn, taskname, sigs=None):
    result = None
    tinfoil.set_event_mask(['bb.event.FindSigInfoResult',
                            'logging.LogRecord',
                            'bb.command.CommandCompleted',
                            'bb.command.CommandFailed'])
    ret = tinfoil.run_command('findSigInfo', pn, taskname, sigs)
    if ret:
        while True:
            event = tinfoil.wait_event(1)
            if event:
                if isinstance(event, bb.command.CommandCompleted):
                    break
                elif isinstance(event, bb.command.CommandFailed):
                    logger.error(str(event))
                    sys.exit(2)
                elif isinstance(event, bb.event.FindSigInfoResult):
                    result = event.result
                elif isinstance(event, logging.LogRecord):
                    logger.handle(event)
    else:
        logger.error('No result returned from findSigInfo command')
        sys.exit(2)
    return result


def find_siginfo_task(bbhandler, pn, taskname, sig1=None, sig2=None):
    """ Find the most recent signature files for the specified PN/task """

    if not taskname.startswith('do_'):
        taskname = 'do_%s' % taskname

    if sig1 and sig2:
        sigfiles = find_siginfo(bbhandler, pn, taskname, [sig1, sig2])
        if not sigfiles:
            logger.error('No sigdata files found matching %s %s matching either %s or %s' % (pn, taskname, sig1, sig2))
            sys.exit(1)
        elif sig1 not in sigfiles:
            logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig1))
            sys.exit(1)
        elif sig2 not in sigfiles:
            logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig2))
            sys.exit(1)
    else:
        sigfiles = find_siginfo(bbhandler, pn, taskname)
        latestsigs = sorted(sigfiles.keys(), key=lambda h: sigfiles[h]['time'])[-2:]
        if not latestsigs:
            logger.error('No sigdata files found matching %s %s' % (pn, taskname))
            sys.exit(1)
        sig1 = latestsigs[0]
        sig2 = latestsigs[1]

    latestfiles = [sigfiles[sig1]['path'], sigfiles[sig2]['path']]

    return latestfiles


# Define recursion callback
def recursecb(key, hash1, hash2):
    hashes = [hash1, hash2]
    hashfiles = find_siginfo(tinfoil, key, None, hashes)

    recout = []
    if not hashfiles:
        recout.append("Unable to find matching sigdata for %s with hashes %s or %s" % (key, hash1, hash2))
    elif hash1 not in hashfiles:
        recout.append("Unable to find matching sigdata for %s with hash %s" % (key, hash1))
    elif hash2 not in hashfiles:
        recout.append("Unable to find matching sigdata for %s with hash %s" % (key, hash2))
    else:
        out2 = bb.siggen.compare_sigfiles(hashfiles[hash1]['path'], hashfiles[hash2]['path'], recursecb, color=color)
        for change in out2:
            for line in change.splitlines():
                recout.append('    ' + line)

    return recout


parser = argparse.ArgumentParser(
    description=("Dumps" if is_dump else "Compares") + " siginfo/sigdata files written out by BitBake")

parser.add_argument('-D', '--debug',
                    help='Enable debug output',
                    action='store_true')

if is_dump:
    parser.add_argument("-t", "--task",
                        help="find the signature data file for the last run of the specified task",
                        action="store", dest="taskargs", nargs=2, metavar=('recipename', 'taskname'))

    parser.add_argument("sigdatafile1",
                        help="Signature file to dump. Not used when using -t/--task.",
                        action="store", nargs='?', metavar="sigdatafile")
else:
    parser.add_argument('-c', '--color',
                        help='Colorize the output (where %(metavar)s is %(choices)s)',
                        choices=['auto', 'always', 'never'], default='auto', metavar='color')

    parser.add_argument('-d', '--dump',
                        help='Dump the last signature data instead of comparing (equivalent to using bitbake-dumpsig)',
                        action='store_true')

    parser.add_argument("-t", "--task",
                        help="find the signature data files for the last two runs of the specified task and compare them",
                        action="store", dest="taskargs", nargs=2, metavar=('recipename', 'taskname'))

    parser.add_argument("-s", "--signature",
                        help="With -t/--task, specify the signatures to look for instead of taking the last two",
                        action="store", dest="sigargs", nargs=2, metavar=('fromsig', 'tosig'))

    parser.add_argument("sigdatafile1",
                        help="First signature file to compare (or signature file to dump, if second not specified). Not used when using -t/--task.",
                        action="store", nargs='?')

    parser.add_argument("sigdatafile2",
                        help="Second signature file to compare",
                        action="store", nargs='?')

options = parser.parse_args()
if is_dump:
    options.color = 'never'
    options.dump = True
    options.sigdatafile2 = None
    options.sigargs = None

if options.debug:
    logger.setLevel(logging.DEBUG)

color = (options.color == 'always' or (options.color == 'auto' and sys.stdout.isatty()))

if options.taskargs:
    with bb.tinfoil.Tinfoil() as tinfoil:
        tinfoil.prepare(config_only=True)
        if not options.dump and options.sigargs:
            files = find_siginfo_task(tinfoil, options.taskargs[0], options.taskargs[1], options.sigargs[0],
                                      options.sigargs[1])
        else:
            files = find_siginfo_task(tinfoil, options.taskargs[0], options.taskargs[1])

        if options.dump:
            logger.debug("Signature file: %s" % files[-1])
            output = bb.siggen.dump_sigfile(files[-1])
        else:
            if len(files) < 2:
                logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (
                    options.taskargs[0], options.taskargs[1]))
                sys.exit(1)

            # Recurse into signature comparison
            logger.debug("Signature file (previous): %s" % files[-2])
            logger.debug("Signature file (latest): %s" % files[-1])
            output = bb.siggen.compare_sigfiles(files[-2], files[-1], recursecb, color=color)
else:
    if options.sigargs:
        logger.error('-s/--signature can only be used together with -t/--task')
        sys.exit(1)
    try:
        if not options.dump and options.sigdatafile1 and options.sigdatafile2:
            with bb.tinfoil.Tinfoil() as tinfoil:
                tinfoil.prepare(config_only=True)
                output = bb.siggen.compare_sigfiles(options.sigdatafile1, options.sigdatafile2, recursecb, color=color)
        elif options.sigdatafile1:
            output = bb.siggen.dump_sigfile(options.sigdatafile1)
        else:
            logger.error('Must specify signature file(s) or -t/--task')
            parser.print_help()
            sys.exit(1)
    except IOError as e:
        logger.error(str(e))
        sys.exit(1)
    except (pickle.UnpicklingError, EOFError):
        logger.error('Invalid signature data - ensure you are specifying sigdata/siginfo files')
        sys.exit(1)

if output:
    print('\n'.join(output))
