From 3ddbd791b860404874396e70c221b7408d1da257 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Thu, 18 Jan 2018 13:16:47 +1100 Subject: sb: Add an orphan check to sb-check. The orphans check lets you see which configuration and build set files in the RSB are not referernced. You can audit the list and remove any configuration files not being used. Top level build set files are included so you need to becareful not to remove something that is valid and useful. To run: $ ./source-builder/sb-check --check-orphans --- source-builder/sb/check.py | 110 +++++++++++++++++++++++++++++++++++++++++++-- source-builder/sb/path.py | 8 ++++ 2 files changed, 115 insertions(+), 3 deletions(-) diff --git a/source-builder/sb/check.py b/source-builder/sb/check.py index 85a1fbe..183f4af 100644 --- a/source-builder/sb/check.py +++ b/source-builder/sb/check.py @@ -27,9 +27,11 @@ import os import error import execute +import fnmatch import log import options import path +import re import version def _check_none(_opts, macro, value, constraint): @@ -162,15 +164,117 @@ def check_exe(label, exe): return _check_exe(None, label, exe, None, True) +def check_orphans(opts): + + def _find_files(path, globs, excludes = []): + ff = [] + for root, dirs, files in os.walk(path, followlinks = True): + for f in files: + for g in globs: + if fnmatch.fnmatch(f, g) and f not in excludes: + ff += [os.path.join(root, f)] + return sorted(ff) + + def _clean(line): + line = line[0:-1] + b = line.find('#') + if b >= 0: + line = line[1:b] + return line.strip() + + def _find(name, opts): + ename = opts.defaults.expand(name) + if ':' in ename: + paths = path.dirname(ename).split(':') + name = path.basename(name) + else: + paths = opts.defaults.get_value('_configdir').split(':') + for p in paths: + n = path.join(opts.defaults.expand(p), name) + if path.exists(n): + return n + return None + + paths = opts.defaults.get_value('_configdir').split(':') + + cfgs = {} + for p in paths: + ep = opts.defaults.expand(p) + print('Scanning: %s (%s)' % (p, ep)) + for f in _find_files(ep, ['*.cfg', '*.bset']): + root, ext = path.splitext(f) + cfgs[f] = { 'src': None, 'ext': ext, 'refs': 0, 'errors':[] } + + wss = re.compile(r'\s+') + + for c in cfgs: + with open(c, 'r') as f: + cfgs[c]['src'] = f.readlines() + lc = 0 + for l in cfgs[c]['src']: + lc += 1 + l = _clean(l) + if len(l) == 0: + continue + if l[0] == '%': + ls = wss.split(l, 2) + if ls[0] == '%include': + name = _find(ls[1], opts) + if name is None: + cfgs[c]['errors'] += [lc] + elif name not in cfgs: + raise error.general('include: %s: not present' % (ls[1])) + else: + cfgs[name]['refs'] += 1 + elif cfgs[c]['ext'] == '.bset' and ':' not in l: + for ext in ['', '.cfg', '.bset']: + name = _find(l + ext, opts) + if name is not None: + if name not in cfgs: + raise error.general('include: %s: not present' % (ls[1])) + else: + cfgs[name]['refs'] += 1 + break + + topdir = opts.defaults.expand('%{_topdir}') + + orphans = [] + show = True + + for c in cfgs: + if cfgs[c]['refs'] == 0: + orphans += [c] + if len(cfgs[c]['errors']) != 0: + if show: + print('Warnings:') + show = False + print(' %s:' % (path.relpath(c))) + for l in cfgs[c]['errors']: + print(' %3d: %s' % (l, cfgs[c]['src'][l - 1][:-1])) + + show = True + + for o in sorted(orphans): + if show: + print('Orphans:') + show = False + print(' %s' % (path.relpath(o))) + def run(): import sys try: _opts = options.load(args = sys.argv) log.notice('RTEMS Source Builder - Check, %s' % (version.str())) - if host_setup(_opts): - print('Environment is ok') + + orphans = _opts.parse_args('--check-orphans', error = False, extra = False) + if orphans: + print('Checking for orphans...') + check_orphans(_opts) else: - print('Environment is not correctly set up') + if host_setup(_opts): + print('Environment is ok') + else: + print('Environment is not correctly set up') except error.general as gerr: print(gerr) sys.exit(1) diff --git a/source-builder/sb/path.py b/source-builder/sb/path.py index 3bf4e0c..679436c 100644 --- a/source-builder/sb/path.py +++ b/source-builder/sb/path.py @@ -92,6 +92,14 @@ def abspath(path): path = shell(path) return shell(os.path.abspath(host(path))) +def relpath(path, start = None): + path = shell(path) + if start is None: + path = os.path.relpath(host(path)) + else: + path = os.path.relpath(host(path), start) + return shell(path) + def splitext(path): path = shell(path) root, ext = os.path.splitext(host(path)) -- cgit v1.2.3