/packages/python/python-pycairo/

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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from __future__ import print_function import os import sys import getopt import shutil import re import warnings import subprocess from optparse import OptionParser scripts_path = os.path.abspath(os.path.dirname(os.path.abspath(sys.argv[0]))) lib_path = scripts_path + '/lib' sys.path = sys.path + [lib_path] import scriptpath # Figure out where is the bitbake/lib/bb since we need bb.siggen and bb.process bitbakepath = scriptpath.add_bitbake_lib_path() if not bitbakepath: sys.stderr.write("Unable to find bitbake by searching parent directory of this script or PATH\n") sys.exit(1) import bb.siggen import bb.process # Match the stamp's filename # group(1): PE_PV (may no PE) # group(2): PR # group(3): TASK # group(4): HASH stamp_re = re.compile("(?P.*)-(?Pr\d+)\.(?Pdo_\w+)\.(?P[^\.]*)") sigdata_re = re.compile(".*\.sigdata\..*") def gen_dict(stamps): """ Generate the dict from the stamps dir. The output dict format is: {fake_f: {pn: PN, pv: PV, pr: PR, task: TASK, path: PATH}} Where: fake_f: pv + task + hash path: the path to the stamp file """ # The member of the sub dict (A "path" will be appended below) sub_mem = ("pv", "pr", "task") d = {} for dirpath, _, files in os.walk(stamps): for f in files: # The "bitbake -S" would generate ".sigdata", but no "_setscene". fake_f = re.sub('_setscene.', '.', f) fake_f = re.sub('.sigdata', '', fake_f) subdict = {} tmp = stamp_re.match(fake_f) if tmp: for i in sub_mem: subdict[i] = tmp.group(i) if len(subdict) != 0: pn = os.path.basename(dirpath) subdict['pn'] = pn # The path will be used by os.stat() and bb.siggen subdict['path'] = dirpath + "/" + f fake_f = tmp.group('pv') + tmp.group('task') + tmp.group('hash') d[fake_f] = subdict return d # Re-construct the dict def recon_dict(dict_in): """ The output dict format is: {pn_task: {pv: PV, pr: PR, path: PATH}} """ dict_out = {} for k in dict_in.keys(): subdict = {} # The key pn_task = "%s_%s" % (dict_in.get(k).get('pn'), dict_in.get(k).get('task')) # If more than one stamps are found, use the latest one. if pn_task in dict_out: full_path_pre = dict_out.get(pn_task).get('path') full_path_cur = dict_in.get(k).get('path') if os.stat(full_path_pre).st_mtime > os.stat(full_path_cur).st_mtime: continue subdict['pv'] = dict_in.get(k).get('pv') subdict['pr'] = dict_in.get(k).get('pr') subdict['path'] = dict_in.get(k).get('path') dict_out[pn_task] = subdict return dict_out def split_pntask(s): """ Split the pn_task in to (pn, task) and return it """ tmp = re.match("(.*)_(do_.*)", s) return (tmp.group(1), tmp.group(2)) def print_added(d_new = None, d_old = None): """ Print the newly added tasks """ added = {} for k in d_new.keys(): if k not in d_old: # Add the new one to added dict, and remove it from # d_new, so the remaining ones are the changed ones added[k] = d_new.get(k) del(d_new[k]) if not added: return 0 # Format the output, the dict format is: # {pn: task1, task2 ...} added_format = {} counter = 0 for k in added.keys(): pn, task = split_pntask(k) if pn in added_format: # Append the value added_format[pn] = "%s %s" % (added_format.get(pn), task) else: added_format[pn] = task counter += 1 print("=== Newly added tasks: (%s tasks)" % counter) for k in added_format.keys(): print(" %s: %s" % (k, added_format.get(k))) return counter def print_vrchanged(d_new = None, d_old = None, vr = None): """ Print the pv or pr changed tasks. The arg "vr" is "pv" or "pr" """ pvchanged = {} counter = 0 for k in d_new.keys(): if d_new.get(k).get(vr) != d_old.get(k).get(vr): counter += 1 pn, task = split_pntask(k) if pn not in pvchanged: # Format the output, we only print pn (no task) since # all the tasks would be changed when pn or pr changed, # the dict format is: # {pn: pv/pr_old -> pv/pr_new} pvchanged[pn] = "%s -> %s" % (d_old.get(k).get(vr), d_new.get(k).get(vr)) del(d_new[k]) if not pvchanged: return 0 print("\n=== %s changed: (%s tasks)" % (vr.upper(), counter)) for k in pvchanged.keys(): print(" %s: %s" % (k, pvchanged.get(k))) return counter def print_depchanged(d_new = None, d_old = None, verbose = False): """ Print the dependency changes """ depchanged = {} counter = 0 for k in d_new.keys(): counter += 1 pn, task = split_pntask(k) if (verbose): full_path_old = d_old.get(k).get("path") full_path_new = d_new.get(k).get("path") # No counter since it is not ready here if sigdata_re.match(full_path_old) and sigdata_re.match(full_path_new): output = bb.siggen.compare_sigfiles(full_path_old, full_path_new) if output: print("\n=== The verbose changes of %s.%s:" % (pn, task)) print('\n'.join(output)) else: # Format the output, the format is: # {pn: task1, task2, ...} if pn in depchanged: depchanged[pn] = "%s %s" % (depchanged.get(pn), task) else: depchanged[pn] = task if len(depchanged) > 0: print("\n=== Dependencies changed: (%s tasks)" % counter) for k in depchanged.keys(): print(" %s: %s" % (k, depchanged[k])) return counter def main(): """ Print what will be done between the current and last builds: 1) Run "STAMPS_DIR= bitbake -S recipe" to re-generate the stamps 2) Figure out what are newly added and changed, can't figure out what are removed since we can't know the previous stamps clearly, for example, if there are several builds, we can't know which stamps the last build has used exactly. 3) Use bb.siggen.compare_sigfiles to diff the old and new stamps """ parser = OptionParser( version = "1.0", usage = """%prog [options] [package ...] print what will be done between the current and last builds, for example: $ bitbake core-image-sato # Edit the recipes $ bitbake-whatchanged core-image-sato The changes will be printed" Note: The amount of tasks is not accurate when the task i