#!/usr/bin/env python3

# bitbake-diffsigs
# BitBake task signature data comparison utility
#
# Copyright (C) 2012-2013, 2017 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import os
import sys
import warnings
import fnmatch
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

logger = bb.msg.logger_create('bitbake-diffsigs')

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_compare_task(bbhandler, pn, taskname, sig1=None, sig2=None, color=False):
    """ Find the most recent signature files for the specified PN/task and compare them """

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

    if sig1 and sig2:
        sigfiles = find_siginfo(bbhandler, pn, taskname, [sig1, sig2])
        if len(sigfiles) == 0:
            logger.error('No sigdata files found matching %s %s matching either %s or %s' % (pn, taskname, sig1, sig2))
            sys.exit(1)
        elif not sig1 in sigfiles:
            logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig1))
            sys.exit(1)
        elif not sig2 in sigfiles:
            logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig2))
            sys.exit(1)
        latestfiles = [sigfiles[sig1], sigfiles[sig2]]
    else:
        filedates = find_siginfo(bbhandler, pn, taskname)
        latestfiles = sorted(filedates.keys(), key=lambda f: filedates[f])[-3:]
        if not latestfiles:
            logger.error('No sigdata files found matching %s %s' % (pn, taskname))
            sys.exit(1)
        elif len(latestfiles) < 2:
            logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (pn, taskname))
            sys.exit(1)

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

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

        return recout

    # Recurse into signature comparison
    logger.debug("Signature file (previous): %s" % latestfiles[-2])
    logger.debug("Signature file (latest): %s" % latestfiles[-1])
    output = bb.siggen.compare_sigfiles(latestfiles[-2], latestfiles[-1], recursecb, color=color)
    if output:
        print('\n'.join(output))
    sys.exit(0)



parser = argparse.ArgumentParser(
    description="Compares siginfo/sigdata files written out by BitBake")

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

parser.add_argument('--color',
        help='Colorize output (where %(metavar)s is %(choices)s)',
        choices=['auto', 'always', 'never'], default='auto', metavar='color')

parser.add_argument("-t", "--task",
        help="find the signature data files for 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 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 options.sigargs:
            find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1], options.sigargs[0], options.sigargs[1], color=color)
        else:
            find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1], color=color)
else:
    if options.sigargs:
        logger.error('-s/--signature can only be used together with -t/--task')
        sys.exit(1)
    try:
        if options.sigdatafile1 and options.sigdatafile2:
            output = bb.siggen.compare_sigfiles(options.sigdatafile1, options.sigdatafile2, 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))
