-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgraph.py
More file actions
87 lines (67 loc) · 2.29 KB
/
Copy pathgraph.py
File metadata and controls
87 lines (67 loc) · 2.29 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
import os
from argparse import ArgumentParser
from pathlib import Path
from downstream.updater import Updater
def transitive_deps(graph: dict[str, set[str]], name: str) -> set[str]:
result: set[str] = set()
for dep in graph.get(name, set()):
result.add(dep)
result |= transitive_deps(graph, dep)
return result
def indirect_deps(graph: dict[str, set[str]], name: str) -> set[str]:
result: set[str] = set()
for dep in graph.get(name, set()):
result |= transitive_deps(graph, dep)
return result
def attrs_str(**kwargs: str) -> str:
if not kwargs:
return ""
return " [" + " ".join(f"{k}=<{v}>" for k, v in kwargs.items()) + "]"
class Args:
downstream: Path
prune: bool
external: bool
def main() -> None:
parser = ArgumentParser()
parser.add_argument("downstream", type=Path)
parser.add_argument(
"-p",
"--prune",
action="store_true",
help="omit edges already implied transitively",
)
parser.add_argument(
"-e",
"--external",
action="store_true",
help="also graph dependencies not listed in repos.toml",
)
args = parser.parse_args(namespace=Args())
os.chdir(args.downstream)
updater = Updater()
graph = updater.dep_graph(external=args.external)
external = {
dep
for deps in graph.values()
for dep in deps
if dep not in updater.subrepos_by_name
}
print("digraph G {")
print(" rankdir=LR;")
for subrepo in sorted(updater.subrepos, key=lambda r: r.name):
indirect = indirect_deps(graph, subrepo.name) if args.prune else set()
label = f'{subrepo.name}<BR/><FONT POINT-SIZE="8">{subrepo.rev}</FONT>'
attrs = {"label": label}
if subrepo.critical:
attrs["style"] = "filled"
attrs["color"] = "pink"
print(f' "{subrepo.name}"{attrs_str(**attrs)};')
for dep in sorted(graph[subrepo.name]):
comment = "// " if dep in indirect else ""
print(f' {comment}"{dep}" -> "{subrepo.name}";')
for name in sorted(external):
attrs = {"label": name, "style": "dashed", "color": "gray", "fontcolor": "gray"}
print(f' "{name}"{attrs_str(**attrs)};')
print("}")
if __name__ == "__main__":
main()