forked from alisw/alibuild
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaliDeps
More file actions
executable file
·100 lines (89 loc) · 3.4 KB
/
aliDeps
File metadata and controls
executable file
·100 lines (89 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python
from argparse import ArgumentParser
from glob import glob
from tempfile import NamedTemporaryFile
import logging, sys, yaml
from logging import debug, error, info
from os import remove
from subprocess import Popen, PIPE, STDOUT
def format(s, **kwds):
return s % kwds
def execute(command):
popen = Popen(command, shell=(isinstance(command, basestring)), stdout=PIPE, stderr=STDOUT)
linesIterator = iter(popen.stdout.readline, "")
for line in linesIterator:
debug(line.strip("\n")) # yield line
output = popen.communicate()[0]
debug(output)
exitCode = popen.returncode
return exitCode
def deps(recipesDir, topPackage, outFile, transitiveRed):
dot = {}
for p in glob("%s/*.sh" % recipesDir):
debug(format("Reading file %(filename)s", filename=p))
try:
recipe = yaml.safe_load(open(p).read().split("---")[0])
name = recipe["package"]
except Exception as e:
error(format("Error reading recipe %(filename)s: %(type)s: %(msg)s",
filename=p, type=type(e).__name__, msg=str(e)))
sys.exit(1)
dot[name] = dot.get(name, [])
for d in recipe.get("requires", []):
dot[name].append(d.split(":")[0])
selected = None
if topPackage != "all":
if not topPackage in dot:
error(format("Package %(topPackage)s does not exist", topPackage=topPackage))
return False
selected = [ topPackage ]
olen = 0
while len(selected) != olen:
olen = len(selected)
selected += [ d for s in selected for d in dot[s] if not d in selected ]
selected.sort()
with NamedTemporaryFile(delete=False) as fp:
fp.write("digraph {\n")
for p,deps in dot.iteritems():
if selected and not p in selected: continue
fp.write(" \"%s\";\n" % p)
for d in deps:
fp.write(" \"%s\" -> \"%s\";\n" % (p,d))
fp.write("}\n")
try:
if transitiveRed:
execute(format("tred %(dotFile)s > %(dotFile)s.0 && mv %(dotFile)s.0 %(dotFile)s",
dotFile=fp.name))
execute(["dot", fp.name, "-Tpdf", "-o", outFile])
except Exception as e:
error(format("Error generating dependencies with dot: %(type)s: %(msg)s",
type=type(e).__name__, msg=str(e)))
else:
info(format("Dependencies graph generated: %(outFile)s", outFile=outFile))
remove(fp.name)
return True
def main():
parser = ArgumentParser()
parser.add_argument("topPackage")
parser.add_argument("--dist", dest="distDir", default="alidist",
help="Recipes directory")
parser.add_argument("--output-file", "-o", dest="outFile", default="dist.pdf",
help="Output file (PDF format)")
parser.add_argument("--debug", "-d", dest="debug", action="store_true", default=False,
help="Debug output")
parser.add_argument("--neat", "-n", dest="neat", action="store_true", default=False,
help="Neat graph with transitive reduction")
args = parser.parse_args()
logger = logging.getLogger()
loggerHandler = logging.StreamHandler()
logger.addHandler(loggerHandler)
loggerHandler.setFormatter(logging.Formatter('%(levelname)-5s: %(message)s'))
if args.debug: logger.setLevel(logging.DEBUG)
else: logger.setLevel(logging.INFO)
if not deps(recipesDir=args.distDir,
topPackage=args.topPackage,
outFile=args.outFile,
transitiveRed=args.neat):
sys.exit(1)
if __name__ == "__main__":
main()