#!/usr/bin/env python3 # Copyright (c) 2018 Pino Toscano # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. import queue import sys import yaml class SimpleGraph(object): def __init__(self): # node -> children mapping self.nodes = {} def _findRoots(self): ret = [] for k in self.nodes.keys(): if not self._findInValues(k, self.nodes): ret.append(k) return ret def _findInValues(self, k, d): for v in d.values(): if k in v: return True return False def addNode(self, node, parents): for p in parents: if p not in self.nodes: self.nodes[p] = [] self.nodes[p].append(node) if node not in self.nodes: self.nodes[node] = [] # insert the item def bfs(self): ''' Simply Breadth-first search. Returns a list of steps, with each step a list of all the nodes for it. ''' ret = [] nodesCopy = self.nodes roots = self._findRoots() q = queue.Queue() STEPDEL = '--------' visited = set() for r in roots: q.put(r) visited.add(r) ret.append([]) q.put(STEPDEL) while not q.empty(): n = q.get() if n == STEPDEL: if not q.empty(): ret.append([]) q.put(STEPDEL) else: children = nodesCopy.pop(n, []) for c in children: if c in visited: continue elif self._findInValues(c, nodesCopy): # child of another node too, so let that other node # handle this child continue q.put(c) visited.add(c) ret[-1].append(n) return ret if __name__ == '__main__': if len(sys.argv) != 3: sys.stderr.write("Usage: %s DEPSFILE MODYAML\n" % sys.argv[0]) sys.exit(1) g = SimpleGraph() with open(sys.argv[1]) as f: for l in f: if not l.strip() or l.startswith('#'): continue pieces = [x.strip() for x in l.split(' ')] if not pieces or not pieces[0].endswith(':'): sys.stderr.write("Invalid line '%s', skipped\n" % l) continue node = pieces[0][:-1] parents = pieces[1:] g.addNode(node, parents) with open(sys.argv[2]) as f: ydoc = yaml.safe_load(f) steps = g.bfs() stepsIndexes = {} for i, step in enumerate(steps, 1): for x in step: stepsIndexes[x] = i rpmComps = ydoc['data']['components']['rpms'] for k, v in rpmComps.items(): step = stepsIndexes[k] try: actualStep = int(v['buildorder']) if step != actualStep: print("%s has buildorder %d but must be %d" % (k, actualStep, step)) except KeyError: print("%s has no buildorder, set it to %d" % (k, step))