summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2012-08-27 21:44:35 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-09-07 12:10:45 +0100
commite58eb8cbb0f9ecd4afa23ffb64c8467b24d93c5c (patch)
tree6be029b25e2b74e9338a6932d88168317c7bdb7b /bitbake
parentd5226c96d3c64bcfa8922327594663352703a8a8 (diff)
downloadpoky-e58eb8cbb0f9ecd4afa23ffb64c8467b24d93c5c.tar.gz
bitbake: bitbake-diffsigs: allow specifying task & follow deps recursively
Add the ability to compare the two most recent runs of a specified task, and follow dependent hash changes recursively. This enables you to trace back and find exactly why a task was re-run after the fact. Note that this relies on the metadata providing a function, hooked in as bb.siggen.find_siginfo, which allows searching in the appropriate places to find signature data files. (Bitbake rev: cc70181659c07e04c205e17832846acf1ff31d28) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rwxr-xr-xbitbake/bin/bitbake-diffsigs97
-rw-r--r--bitbake/lib/bb/siggen.py17
2 files changed, 102 insertions, 12 deletions
diff --git a/bitbake/bin/bitbake-diffsigs b/bitbake/bin/bitbake-diffsigs
index 146cab8119..62f682748b 100755
--- a/bitbake/bin/bitbake-diffsigs
+++ b/bitbake/bin/bitbake-diffsigs
@@ -1,15 +1,102 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2
3# bitbake-diffsigs
4# BitBake task signature data comparison utility
5#
6# Copyright (C) 2012 Intel Corporation
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License version 2 as
10# published by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc.,
19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
2import os 21import os
3import sys 22import sys
4import warnings 23import warnings
24import fnmatch
25import optparse
26import logging
27
5sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib')) 28sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
6 29
30import bb.tinfoil
7import bb.siggen 31import bb.siggen
8 32
9if len(sys.argv) > 2: 33logger = logging.getLogger('BitBake')
10 output = bb.siggen.compare_sigfiles(sys.argv[1], sys.argv[2]) 34
35def find_compare_task(bbhandler, pn, taskname):
36 """ Find the most recent signature files for the specified PN/task and compare them """
37
38 if not hasattr(bb.siggen, 'find_siginfo'):
39 logger.error('Metadata does not support finding signature data files')
40 sys.exit(1)
41
42 filedates = bb.siggen.find_siginfo(pn, taskname, None, bbhandler.config_data)
43 latestfiles = sorted(filedates.keys(), key=lambda f: filedates[f])[-2:]
44 if not latestfiles:
45 logger.error('No sigdata files found matching %s %s' % (pn, taskname))
46 sys.exit(1)
47 elif len(latestfiles) < 2:
48 logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (pn, taskname))
49 sys.exit(1)
50 else:
51 # Define recursion callback
52 def recursecb(key, hash1, hash2):
53 hashes = [hash1, hash2]
54 hashfiles = bb.siggen.find_siginfo(key, None, hashes, bbhandler.config_data)
55
56 recout = []
57 if len(hashfiles) == 2:
58 out2 = bb.siggen.compare_sigfiles(hashfiles[hash1], hashfiles[hash2], recursecb)
59 recout.extend(list(' ' + l for l in out2))
60 else:
61 recout.append("Unable to find matching sigdata for %s with hashes %s or %s" % (key, hash1, hash2))
62
63 return recout
64
65 # Recurse into signature comparison
66 output = bb.siggen.compare_sigfiles(latestfiles[0], latestfiles[1], recursecb)
67 if output:
68 print '\n'.join(output)
69 sys.exit(0)
70
71
72
73parser = optparse.OptionParser(
74 usage = """
75 %prog -t recipename taskname
76 %prog sigdatafile1 sigdatafile2
77 %prog sigdatafile1""")
78
79parser.add_option("-t", "--task",
80 help = "find the signature data files for last two runs of the specified task and compare them",
81 action="store_true", dest="taskmode")
82
83options, args = parser.parse_args(sys.argv)
84
85if len(args) == 1:
86 parser.print_help()
11else: 87else:
12 output = bb.siggen.dump_sigfile(sys.argv[1]) 88 tinfoil = bb.tinfoil.Tinfoil()
89 if options.taskmode:
90 if len(args) < 3:
91 logger.error("Please specify a recipe and task name")
92 sys.exit(1)
93 tinfoil.prepare(config_only = True)
94 find_compare_task(tinfoil, args[1], args[2])
95 else:
96 if len(args) == 2:
97 output = bb.siggen.dump_sigfile(sys.argv[1])
98 else:
99 output = bb.siggen.compare_sigfiles(sys.argv[1], sys.argv[2])
13 100
14if output: 101 if output:
15 print '\n'.join(output) 102 print '\n'.join(output)
diff --git a/bitbake/lib/bb/siggen.py b/bitbake/lib/bb/siggen.py
index 8d1501b8ae..8fe59b9057 100644
--- a/bitbake/lib/bb/siggen.py
+++ b/bitbake/lib/bb/siggen.py
@@ -301,7 +301,7 @@ def clean_basepaths(a):
301 b[clean_basepath(x)] = a[x] 301 b[clean_basepath(x)] = a[x]
302 return b 302 return b
303 303
304def compare_sigfiles(a, b): 304def compare_sigfiles(a, b, recursecb = None):
305 output = [] 305 output = []
306 306
307 p1 = pickle.Unpickler(open(a, "rb")) 307 p1 = pickle.Unpickler(open(a, "rb"))
@@ -369,8 +369,8 @@ def compare_sigfiles(a, b):
369 369
370 370
371 if 'runtaskhashes' in a_data and 'runtaskhashes' in b_data: 371 if 'runtaskhashes' in a_data and 'runtaskhashes' in b_data:
372 a = clean_basepaths(a_data['runtaskhashes']) 372 a = a_data['runtaskhashes']
373 b = clean_basepaths(b_data['runtaskhashes']) 373 b = b_data['runtaskhashes']
374 changed, added, removed = dict_diff(a, b) 374 changed, added, removed = dict_diff(a, b)
375 if added: 375 if added:
376 for dep in added: 376 for dep in added:
@@ -381,7 +381,7 @@ def compare_sigfiles(a, b):
381 #output.append("Dependency on task %s was replaced by %s with same hash" % (dep, bdep)) 381 #output.append("Dependency on task %s was replaced by %s with same hash" % (dep, bdep))
382 bdep_found = True 382 bdep_found = True
383 if not bdep_found: 383 if not bdep_found:
384 output.append("Dependency on task %s was added with hash %s" % (dep, a[dep])) 384 output.append("Dependency on task %s was added with hash %s" % (clean_basepath(dep), a[dep]))
385 if removed: 385 if removed:
386 for dep in removed: 386 for dep in removed:
387 adep_found = False 387 adep_found = False
@@ -391,11 +391,14 @@ def compare_sigfiles(a, b):
391 #output.append("Dependency on task %s was replaced by %s with same hash" % (adep, dep)) 391 #output.append("Dependency on task %s was replaced by %s with same hash" % (adep, dep))
392 adep_found = True 392 adep_found = True
393 if not adep_found: 393 if not adep_found:
394 output.append("Dependency on task %s was removed with hash %s" % (dep, b[dep])) 394 output.append("Dependency on task %s was removed with hash %s" % (clean_basepath(dep), b[dep]))
395 if changed: 395 if changed:
396 for dep in changed: 396 for dep in changed:
397 output.append("Hash for dependent task %s changed from %s to %s" % (dep, a[dep], b[dep])) 397 output.append("Hash for dependent task %s changed from %s to %s" % (clean_basepath(dep), a[dep], b[dep]))
398 398 if callable(recursecb):
399 recout = recursecb(dep, a[dep], b[dep])
400 if recout:
401 output.extend(recout)
399 402
400 a_taint = a_data.get('taint', None) 403 a_taint = a_data.get('taint', None)
401 b_taint = b_data.get('taint', None) 404 b_taint = b_data.get('taint', None)