diff --git a/src/mio.py b/src/mio.py index 1f239d10f2773f7488a2a0bce8bb75aec25e746b..f749cced0556c61139cf0f82fcc1f015d4c3e28d 100755 --- a/src/mio.py +++ b/src/mio.py @@ -8,6 +8,7 @@ import mio.transform import mio.parser import mio.repository import mio.node +import mio.analyze import argparse import os import os.path @@ -182,6 +183,10 @@ if __name__ == '__main__': action="append", nargs='*', default=None, metavar="TARGET", help="print dependency tree for TARGET") + optParser.add_argument("--dependency-check", + action="append", nargs='*', default=None, + metavar="TARGET", + help="check dependencies for TARGET") optParser.add_argument("-v","--verbose", action="count", dest="verbose", default=0, @@ -310,6 +315,14 @@ if __name__ == '__main__': pass pass + if options.dependency_check != None: + # Flatten list + targets = [i for l in options.dependency_check for i in l ] + if len(targets) == 0: + tree = parse('hostinfo.xml') + targets = [ h.name[0] for h in tree._group_] + mio.analyze.dependency_check(rules, options, targets) + if options.dependency_tree != None: def dump_tree(name, indent=0): def command_or_script(cos, prefix=''): @@ -317,7 +330,6 @@ if __name__ == '__main__': print("%s [%s command] %s" % ( (' '*indent, prefix, cos.command[0]))) pass - pass if cos.script[0] != None: print("%s [%s script] %s" % ( (' '*indent, prefix, cos.script[0]))) @@ -327,6 +339,7 @@ if __name__ == '__main__': tree = rules.get(name) for p in tree._pre_: command_or_script(p, 'pre') + pass if not options.noyum: for r in tree._rpm_: print("%s[r] %s" % (' '*(indent+1), r.name[0])) diff --git a/src/mio/analyze.py b/src/mio/analyze.py new file mode 100644 index 0000000000000000000000000000000000000000..d8b314dfb2819abab5de54d3eedf8f5946525371 --- /dev/null +++ b/src/mio/analyze.py @@ -0,0 +1,74 @@ +import os +import mio.util +from mio.node import * + +def get_dependencies(rules, name, path, dependencies=None, exclude=[]): + result = dependencies or dict() + if group_node(name) in exclude: + # Exclude this group + return result + def add_dependency(dest, kind, source=''): + if not dest in result: + result[dest] = dict() + pass + if not (kind,source) in result[dest]: + result[dest][(kind,source)] = set() + pass + result[dest][(kind,source)].add(path) + pass + + tree = rules.get(name) + for s in tree._symlink_: + if symlink_node(s.name[0], s) in exclude: + # Exclude symlink + continue + if s.delete[0] == 'yes': + add_dependency(s.name[0], 'delete') + pass + else: + add_dependency(s.name[0], 'symlink', s.value[0]) + pass + pass + for f in tree._file_: + if file_node(f.name[0], f) in exclude: + # Exclude file + continue + if f.delete[0] == 'yes': + add_dependency(f.name[0], 'delete') + pass + elif f.source[0] == '': + add_dependency(f.name[0], 'chmod') + pass + else: + src = os.path.normpath('%s/%s' % (f.files[0:], + f.source[0] or f.name[0])) + add_dependency(f.name[0], 'file', src) + pass + pass + for d in tree._dependency_: + result = get_dependencies(rules=rules, + name=d.name[0], + path=path + (d.name[0],), + dependencies=result, + exclude=mio.util.exclusion_closure( + exclude, d)) + pass + return result + +def dependency_check(rules, options, targets): + errors = 0 + for t in targets: + dep = get_dependencies(rules, t, (t,)) + for dk in [ k for k in sorted(dep) if len(dep[k]) > 1 ]: + errors += 1 + print(t) + print(' %s' % dk) + for sk in sorted(dep[dk]): + print(' %s' % str(sk)) + for p in sorted(dep[dk][sk]): + print(' %s' % str(p)) + pass + pass + if errors: + raise Exception('Dependency check failed') + pass diff --git a/src/mio/util.py b/src/mio/util.py index 72202189ebb247c4f0e51398e55eef3cba0489cb..1a09fe712c5f98a026cdb94ad3115e95400ba3bc 100755 --- a/src/mio/util.py +++ b/src/mio/util.py @@ -3,6 +3,7 @@ import os import pwd import re from mio.log import log, NORMAL, VERBOSE +from mio.node import * try: # Python 2 @@ -119,3 +120,23 @@ def owner(decl): def group(decl): return decl.group[0:] +def exclusion_closure(exclude, target): + if not target._exclude_: + return exclude + else: + result = list(exclude) # Create exclusion closure + for e in target._exclude_: + for (key, value) in e._attribute.items(): + if key == 'dependency': + result.append(group_node(value)) + elif key == 'file': + result.append(file_node(value)) + elif key == 'dir': + result.append(dir_node(value)) + elif key == 'rpm': + result.append(rpm_node(value)) + elif key == 'symlink': + result.append(symlink_node(value)) + else: + raise BadExclude(e, key) + return result