diff --git a/source/dub/dependencyresolver.d b/source/dub/dependencyresolver.d index e77fd0f..edfbc4e 100644 --- a/source/dub/dependencyresolver.d +++ b/source/dub/dependencyresolver.d @@ -10,8 +10,8 @@ import dub.dependency; import dub.internal.vibecompat.core.log; -import std.algorithm : all, canFind, sort; -import std.array : appender; +import std.algorithm : all, canFind, filter, sort; +import std.array : appender, array; import std.conv : to; import std.exception : enforce; import std.string : format, indexOf, lastIndexOf; @@ -66,7 +66,7 @@ size_t[string] package_indices; CONFIG[][] all_configs; bool[TreeNode] visited; - void findConfigsRec(TreeNode parent) + void findConfigsRec(TreeNode parent, bool parent_unique) { if (parent in visited) return; visited[parent] = true; @@ -87,13 +87,17 @@ configs = getSpecificConfigs(ch) ~ configs; + // eliminate configurations from which we know that they can't satisfy + // the uniquely defined root dependencies (==version or ~branch style dependencies) + if (parent_unique) configs = configs.filter!(c => matches(ch.configs, c)).array; + all_configs[pidx] = configs; foreach (v; configs) - findConfigsRec(TreeNode(ch.pack, v)); + findConfigsRec(TreeNode(ch.pack, v), parent_unique && configs.length == 1); } } - findConfigsRec(root); + findConfigsRec(root, true); // prepend an invalid configuration to denote an unchosen dependency // this is used to properly support optional dependencies (when