summaryrefslogtreecommitdiff
path: root/classes/task-metadata-track.bbclass
blob: d3622aef68e4f79d1f5cd0ef229a41c75a124632 (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
# Copyright (C) 2009 Chris Larson <clarson@kergoth.com>
# Released under the MIT license (see COPYING.MIT for the terms)
#
# This class uses events to capture the state of the datastore when the task
# starts, and after it completes.  It diffs those captured states, and emits
# messages showing which variables changed, and what their values were changed
# to.
#
# It provides a mechanism to blacklist variables you expect to change, both
# globally and on a per-task basis.
#
# Known instances of tasks changing metadata:
#
# PSTAGE_PKGMANAGER changes by calls to pstage_set_pkgmanager in:
#   do_clean, do_setscene, do_package_stage
#
# Subpackage metadata, read by the pkgdata functions in base.bbclass, in:
#   do_package, do_package_stage, do_package_write_*


TASK_METADATA_BLACKLIST = "\
    __RUNQUEUE_DO_NOT_USE_EXTERNALLY \
"

#TASK_METADATA_BLACKLIST_do_clean = "\
#    PSTAGE_PKGMANAGER \
#"


def dict_diff(olddict, newdict):
    diff = {}
    for key in set(olddict).union(set(newdict)):
        old = olddict.get(key)
        new = newdict.get(key)
        if old != new:
            diff[key] = (old, new)

    return diff

def dict_for_data(data):
    newdict = {}
    for key in data.keys():
        newdict[key] = data.getVar(key, False)
    return newdict

def task_metadata_track_start(task, data):
    originaldata = dict_for_data(data)
    data.setVar("__originaldata_%s" % task, originaldata)

def task_metadata_track_stop(task, data):
    from bb import note

    pf = data.getVar("PF", True)
    def emit(msg):
        note("%s: %s" % (pf, msg))

    originaldata = data.getVar("__originaldata_%s" % task, False)
    newdata = dict_for_data(data)
    blacklist = data.getVar("TASK_METADATA_BLACKLIST", True).split() + \
                (data.getVar("TASK_METADATA_BLACKLIST_%s" % task, True) or "").split()

    diff = dict_diff(originaldata, newdata)
    diff_clean = [key for key in diff \
                  if not key in blacklist and \
                  not key.startswith("__originaldata_")]

    if diff_clean:
        emit("Variables changed by %s:" % task)
        for key in diff_clean:
            (old, new) = diff[key]
            emit("  %s:" % key)
            emit("    '%s' -> '%s'" % (old, new))

python __task_metadata_track_eh () {
    from bb.build import TaskStarted, TaskSucceeded

    if isinstance(e, TaskStarted):
        if e.data is None:
            from bb import fatal
            fatal("e.data is none for %s" % e)
        task_metadata_track_start(e.task, e.data)
    elif isinstance(e, TaskSucceeded):
        task_metadata_track_stop(e.task, e.data)
}
addhandler __task_metadata_track_eh

addtask py_listtasks
do_py_listtasks[nostamp] = "1"
do_py_listtasks[recrdeptask] = "do_py_listtasks"
python do_py_listtasks() {
	import sys
	for e in d.keys():
		if d.getVarFlag(e, "task") and \
		   d.getVarFlag(e, "python"):
			sys.stdout.write("%s\n" % e)
}