detect cycles in pure nix

This commit is contained in:
DavHau 2021-11-01 13:25:33 +07:00
parent 2fd7782af4
commit 03ef2e4c7a
2 changed files with 70 additions and 5 deletions

View File

@ -58,10 +58,17 @@ let
nix eval --show-trace --impure --raw --expr "
builtins.toJSON (
(import ${dream2nixWithExternals} {}).translators.translators.${
lib.concatStringsSep "." translatorAttrPath
}.translate
(builtins.fromJSON (builtins.readFile '''$1'''))
let
dreamLock =
(import ${dream2nixWithExternals} {}).translators.translators.${
lib.concatStringsSep "." translatorAttrPath
}.translate
(builtins.fromJSON (builtins.readFile '''$1'''));
in
# don't use nix to detect cycles, this will be more efficient in python
dreamLock // {
generic = builtins.removeAttrs dreamLock.generic [ \"cyclicDependencies\" ];
}
)
" | jq > $outputFile
'';

View File

@ -3,6 +3,7 @@
# dream2nix
fetchers,
utils,
...
}:
let
@ -125,13 +126,70 @@ let
getDepByNameVer = name: version:
allDependencies."${name}"."${version}";
cyclicDependencies =
let
findCycles = node: prevNodes: cycles:
let
children = dependencyGraph."${node}";
cyclicChildren = lib.filter (child: prevNodes ? "${child}") children;
nonCyclicChildren = lib.filter (child: ! prevNodes ? "${child}") children;
cycles' =
cycles
++
(b.map (child: { from = node; to = child; }) cyclicChildren);
prevNodes' = prevNodes // { "${node}" = null; };
in
if nonCyclicChildren == [] then
cycles'
else
lib.flatten
(b.map
(child: findCycles child prevNodes' cycles')
nonCyclicChildren);
cyclesList = findCycles "${mainPackageName}#${mainPackageVersion}" {} [];
in
b.foldl'
(cycles: cycle:
let
fromNameVersion = utils.keyToNameVersion cycle.from;
fromName = fromNameVersion.name;
fromVersion = fromNameVersion.version;
toNameVersion = utils.keyToNameVersion cycle.to;
toName = toNameVersion.name;
toVersion = toNameVersion.version;
reverse = (cycles."${toName}"."${toVersion}" or []);
in
# if reverse edge already in cycles, do nothing
if b.elem cycle.from reverse then
cycles
else
lib.recursiveUpdate
cycles
{
"${fromName}"."${fromVersion}" =
let
existing = cycles."${fromName}"."${fromVersion}" or [];
in
if b.elem cycle.to existing then
existing
else
existing ++ [ cycle.to ];
})
{}
cyclesList;
in
{
sources = allSources;
generic =
{
inherit mainPackageName mainPackageVersion;
inherit
cyclicDependencies
mainPackageName
mainPackageVersion
;
buildSystem = buildSystemName;
sourcesCombinedHash = null;
translator = translatorName;