merge with org.openembedded.dev
[openembedded.git] / classes / task-metadata-track.bbclass
1 # Copyright (C) 2009 Chris Larson <clarson@kergoth.com>
2 # Released under the MIT license (see COPYING.MIT for the terms)
3 #
4 # This class uses events to capture the state of the datastore when the task
5 # starts, and after it completes.  It diffs those captured states, and emits
6 # messages showing which variables changed, and what their values were changed
7 # to.
8 #
9 # It provides a mechanism to blacklist variables you expect to change, both
10 # globally and on a per-task basis.
11 #
12 # Known instances of tasks changing metadata:
13 #
14 # PSTAGE_PKGMANAGER changes by calls to pstage_set_pkgmanager in:
15 #   do_clean, do_setscene, do_package_stage
16 #
17 # Subpackage metadata, read by the pkgdata functions in base.bbclass, in:
18 #   do_package, do_package_stage, do_package_write_*
19
20
21 TASK_METADATA_BLACKLIST = "\
22     __RUNQUEUE_DO_NOT_USE_EXTERNALLY \
23 "
24
25 #TASK_METADATA_BLACKLIST_do_clean = "\
26 #    PSTAGE_PKGMANAGER \
27 #"
28
29
30 def dict_diff(olddict, newdict):
31     diff = {}
32     for key in set(olddict).union(set(newdict)):
33         old = olddict.get(key)
34         new = newdict.get(key)
35         if old != new:
36             diff[key] = (old, new)
37
38     return diff
39
40 def dict_for_data(data):
41     newdict = {}
42     for key in data.keys():
43         newdict[key] = data.getVar(key, False)
44     return newdict
45
46 def task_metadata_track_start(task, data):
47     originaldata = dict_for_data(data)
48     data.setVar("__originaldata_%s" % task, originaldata)
49
50 def task_metadata_track_stop(task, data):
51     from bb import note
52
53     pf = data.getVar("PF", True)
54     def emit(msg):
55         note("%s: %s" % (pf, msg))
56
57     originaldata = data.getVar("__originaldata_%s" % task, False)
58     newdata = dict_for_data(data)
59     blacklist = data.getVar("TASK_METADATA_BLACKLIST", True).split() + \
60                 (data.getVar("TASK_METADATA_BLACKLIST_%s" % task, True) or "").split()
61
62     diff = dict_diff(originaldata, newdata)
63     diff_clean = [key for key in diff \
64                   if not key in blacklist and \
65                   not key.startswith("__originaldata_")]
66
67     if diff_clean:
68         emit("Variables changed by %s:" % task)
69         for key in diff_clean:
70             (old, new) = diff[key]
71             emit("  %s:" % key)
72             emit("    '%s' -> '%s'" % (old, new))
73
74 python __task_metadata_track_eh () {
75     from bb.build import TaskStarted, TaskSucceeded
76
77     if isinstance(e, TaskStarted):
78         if e.data is None:
79             from bb import fatal
80             fatal("e.data is none for %s" % e)
81         task_metadata_track_start(e.task, e.data)
82     elif isinstance(e, TaskSucceeded):
83         task_metadata_track_stop(e.task, e.data)
84 }
85 addhandler __task_metadata_track_eh
86
87 addtask py_listtasks
88 do_py_listtasks[nostamp] = "1"
89 do_py_listtasks[recrdeptask] = "do_py_listtasks"
90 python do_py_listtasks() {
91         import sys
92         for e in d.keys():
93                 if d.getVarFlag(e, "task") and \
94                    d.getVarFlag(e, "python"):
95                         sys.stdout.write("%s\n" % e)
96 }