virt/checkbuildorder.py

131 lines
4.1 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (c) 2018 Pino Toscano <ptoscano@redhat.com>
#
# 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))