1include "library";
2
3def onlyDeps:
4  { Name: .Name, Deps: .Deps | map(.Name) }
5;
6
7def mergeDepsForSameModule:
8  group_by(.Name) | map({Name: .[0].Name, Deps: map(.Deps) | flatten | unique | sort})
9;
10
11def toMergeMap:
12  map({key: .Name, value: .Deps}) | from_entries
13;
14
15def moduleGraphNoVariants:
16  map(onlyDeps) | mergeDepsForSameModule | toMergeMap
17;
18
19def removeSelfEdges:
20  to_entries |
21  map(.key as $key | {key: .key, value: .value | [.[] | select(. != $key)]}) |
22  from_entries
23;
24
25def nextDepths($m):
26  . as $old |
27  to_entries |
28  map({
29      key: .key,
30      value: (
31          .key as $key |
32          $m[.key] // [] |
33          map($old[.]) |
34          if any(. == -1) then -1 else (max // -1) + 1 end
35      )
36  }) |
37  from_entries
38;
39
40def maxDepths($m):
41  map({key: ., value: -1}) | from_entries |
42  {Prev: [], Next: .} |
43  until (.Prev == .Next; {Prev: .Next, Next: .Next | nextDepths($m)}) |
44  .Next
45;
46
47def variantlessDistancesFromLeaves($root):
48  (moduleGraphNoVariants | removeSelfEdges) as $m |
49  [$root] |
50  transitiveDeps($m) |
51  maxDepths($m)
52;
53
54variantlessDistancesFromLeaves($arg)