diff --git a/source/dub/project.d b/source/dub/project.d index 91fbf72..101e8fa 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -377,7 +377,6 @@ foreach (d; p.getAllDependencies()) parents[d.name] ~= p.name; - size_t createConfig(string pack, string config) { foreach (i, v; configs) if (v.pack == pack && v.config == config) @@ -401,12 +400,26 @@ void removeConfig(size_t i) { logDebug("Eliminating config %s for %s", configs[i].config, configs[i].pack); - configs = configs.remove(i); - edges = edges.filter!(e => e.from != i && e.to != i).array(); - foreach (ref e; edges) { - if (e.from > i) e.from--; - if (e.to > i) e.to--; - } + auto had_dep_to_pack = new bool[configs.length]; + auto still_has_dep_to_pack = new bool[configs.length]; + + edges = edges.filter!((e) { + if (e.to == i) { + had_dep_to_pack[e.from] = true; + return false; + } else if (configs[e.to].pack == configs[i].pack) { + still_has_dep_to_pack[e.from] = true; + } + if (e.from == i) return false; + return true; + }).array; + + configs[i] = Vertex.init; // mark config as removed + + // also remove any configs that cannot be satisfied anymore + foreach (j; 0 .. configs.length) + if (j != i && had_dep_to_pack[j] && !still_has_dep_to_pack[j]) + removeConfig(j); } bool isReachable(string pack, string conf) { @@ -482,26 +495,24 @@ do { // remove all configs that are not reachable by all parent packages changed = false; - for (size_t i = 0; i < configs.length; ) { + foreach (i, ref c; configs) { + if (c == Vertex.init) continue; // ignore deleted configurations if (!isReachableByAllParentPacks(i)) { - logDebug("NOT REACHABLE by (%s):", parents[configs[i].pack]); + logDebug("%s %s NOT REACHABLE by all of (%s):", c.pack, c.config, parents[c.pack]); removeConfig(i); changed = true; - } else i++; + } } // when all edges are cleaned up, pick one package and remove all but one config if (!changed) { foreach (p; getTopologicalPackageList()) { size_t cnt = 0; - for (size_t i = 0; i < configs.length; ) { - if (configs[i].pack == p.name) { - if (++cnt > 1) { - logDebug("NON-PRIMARY:"); - removeConfig(i); - } else i++; - } else i++; - } + foreach (i, ref c; configs) + if (c.pack == p.name && ++cnt > 1) { + logDebug("NON-PRIMARY: %s %s", c.pack, c.config); + removeConfig(i); + } if (cnt > 1) { changed = true; break; @@ -516,6 +527,7 @@ // return the resulting configuration set as an AA string[string] ret; foreach (c; configs) { + if (c == Vertex.init) continue; // ignore deleted configurations assert(ret.get(c.pack, c.config) == c.config, format("Conflicting configurations for %s found: %s vs. %s", c.pack, c.config, ret[c.pack])); logDebug("Using configuration '%s' for %s", c.config, c.pack); ret[c.pack] = c.config; diff --git a/test/issue1005-configuration-resolution.sh b/test/issue1005-configuration-resolution.sh new file mode 100755 index 0000000..3665a5e --- /dev/null +++ b/test/issue1005-configuration-resolution.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd ${CURR_DIR}/issue1005-configuration-resolution +${DUB} build --bare main || exit 1 diff --git a/test/issue1005-configuration-resolution/.no_build b/test/issue1005-configuration-resolution/.no_build new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue1005-configuration-resolution/.no_build diff --git a/test/issue1005-configuration-resolution/a/dub.sdl b/test/issue1005-configuration-resolution/a/dub.sdl new file mode 100644 index 0000000..d19952b --- /dev/null +++ b/test/issue1005-configuration-resolution/a/dub.sdl @@ -0,0 +1,10 @@ +name "a" +dependency "b" version="*" + +configuration "x" { + subConfiguration "b" "x" +} + +configuration "y" { + subConfiguration "b" "y" +} diff --git a/test/issue1005-configuration-resolution/b/dub.sdl b/test/issue1005-configuration-resolution/b/dub.sdl new file mode 100644 index 0000000..3cfa48b --- /dev/null +++ b/test/issue1005-configuration-resolution/b/dub.sdl @@ -0,0 +1,7 @@ +name "b" + +configuration "x" { +} + +configuration "y" { +} \ No newline at end of file diff --git a/test/issue1005-configuration-resolution/b/source/b.d b/test/issue1005-configuration-resolution/b/source/b.d new file mode 100644 index 0000000..2a9bb41 --- /dev/null +++ b/test/issue1005-configuration-resolution/b/source/b.d @@ -0,0 +1,3 @@ +module b; + +void foo() {} diff --git a/test/issue1005-configuration-resolution/c/dub.sdl b/test/issue1005-configuration-resolution/c/dub.sdl new file mode 100644 index 0000000..e46b148 --- /dev/null +++ b/test/issue1005-configuration-resolution/c/dub.sdl @@ -0,0 +1,2 @@ +name "c" +dependency "a" version="*" diff --git a/test/issue1005-configuration-resolution/main/dub.sdl b/test/issue1005-configuration-resolution/main/dub.sdl new file mode 100644 index 0000000..d492491 --- /dev/null +++ b/test/issue1005-configuration-resolution/main/dub.sdl @@ -0,0 +1,6 @@ +name "main" + +dependency "b" version="*" +dependency "c" version="*" + +subConfiguration "b" "y" diff --git a/test/issue1005-configuration-resolution/main/source/app.d b/test/issue1005-configuration-resolution/main/source/app.d new file mode 100644 index 0000000..0ec7361 --- /dev/null +++ b/test/issue1005-configuration-resolution/main/source/app.d @@ -0,0 +1,6 @@ +import b; + +void main() +{ + foo(); +}