forked from alisw/alibuild
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaliDeps
executable file
·117 lines (105 loc) · 4.03 KB
/
aliDeps
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/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, str)), 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, buildRequires, transitiveRed, disable):
dot = {}
keys = [ "requires" ]
if buildRequires:
keys.append("build_requires")
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"]
if name in disable:
debug("Ignoring %s, disabled explicitly" % name)
continue
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 k in keys:
for d in recipe.get(k, []):
d = d.split(":")[0]
d in disable or dot[name].append(d)
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 if s in dot
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 list(dot.items()):
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("--build-requires", "-b", dest="buildRequires", 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")
parser.add_argument("--disable", dest="disable", default="",
help="List of packages to ignore")
args = parser.parse_args()
args.disable = args.disable.split(",")
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)
deps(recipesDir=args.distDir,
topPackage=args.topPackage,
outFile=args.outFile,
buildRequires=args.buildRequires,
transitiveRed=args.neat,
disable=args.disable) or sys.exit(1)
if __name__ == "__main__":
main()