aboutsummaryrefslogtreecommitdiffstats
path: root/bin/toaster-eventreplay
blob: 8fa4ab7116b63ee3c79bea20dfadfedb6103211f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python3
#
# Copyright (C) 2014        Alex Damian
#
# SPDX-License-Identifier: GPL-2.0-only
#
# This file re-uses code spread throughout other Bitbake source files.
# As such, all other copyrights belong to their own right holders.
#

"""
This command takes a filename as a single parameter. The filename is read
as a build eventlog, and the ToasterUI is used to process events in the file
and log data in the database
"""

import os
import sys
import json
import pickle
import codecs

from collections import namedtuple

# mangle syspath to allow easy import of modules
from os.path import join, dirname, abspath
sys.path.insert(0, join(dirname(dirname(abspath(__file__))), 'lib'))

import bb.cooker
from bb.ui import toasterui

class EventPlayer:
    """Emulate a connection to a bitbake server."""

    def __init__(self, eventfile, variables):
        self.eventfile = eventfile
        self.variables = variables
        self.eventmask = []

    def waitEvent(self, _timeout):
        """Read event from the file."""
        line = self.eventfile.readline().strip()
        if not line:
            return
        try:
            event_str = json.loads(line)['vars'].encode('utf-8')
            event = pickle.loads(codecs.decode(event_str, 'base64'))
            event_name = "%s.%s" % (event.__module__, event.__class__.__name__)
            if event_name not in self.eventmask:
                return
            return event
        except ValueError as err:
            print("Failed loading ", line)
            raise err

    def runCommand(self, command_line):
        """Emulate running a command on the server."""
        name = command_line[0]

        if name == "getVariable":
            var_name = command_line[1]
            variable = self.variables.get(var_name)
            if variable:
                return variable['v'], None
            return None, "Missing variable %s" % var_name

        elif name == "getAllKeysWithFlags":
            dump = {}
            flaglist = command_line[1]
            for key, val in self.variables.items():
                try:
                    if not key.startswith("__"):
                        dump[key] = {
                            'v': val['v'],
                            'history' : val['history'],
                        }
                        for flag in flaglist:
                            dump[key][flag] = val[flag]
                except Exception as err:
                    print(err)
            return (dump, None)

        elif name == 'setEventMask':
            self.eventmask = command_line[-1]
            return True, None

        else:
            raise Exception("Command %s not implemented" % command_line[0])

    def getEventHandle(self):
        """
        This method is called by toasterui.
        The return value is passed to self.runCommand but not used there.
        """
        pass

def main(argv):
    with open(argv[-1]) as eventfile:
        # load variables from the first line
        variables = json.loads(eventfile.readline().strip())['allvariables']

        params = namedtuple('ConfigParams', ['observe_only'])(True)
        player = EventPlayer(eventfile, variables)

        return toasterui.main(player, player, params)

# run toaster ui on our mock bitbake class
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: %s <event file>" % os.path.basename(sys.argv[0]))
        sys.exit(1)

    sys.exit(main(sys.argv))