Fix detection of root package references during dependency resolution. See #334.
- References to and from sub packages of the root package are now also recognized as coming from the root package
 - Any dependency reference within a certain package "family"* (including path based ones) is now mapped to the same base package (circumventing the lookup of all possible matches)

* "family" == base package and all of its sub packages
1 parent 46811c2 commit d1bbdd6fa0bcb27db21130582dc0b723100ecb9e
@Sönke Ludwig Sönke Ludwig authored on 11 Jun 2014
Showing 2 changed files
View
9
source/dub/dependencyresolver.d
auto idx = indexOf(p, ":");
if (idx < 0) return p;
return p[0 .. idx];
}
 
auto root_base_pack = rootPackage(root.pack);
 
size_t[string] package_indices;
CONFIG[][] all_configs;
bool[TreeNode] visited;
if (auto pi = basepack in package_indices) {
pidx = *pi;
configs = all_configs[*pi];
} else {
if (basepack == root.pack) configs = [root.config];
if (basepack == root_base_pack) configs = [root.config];
else configs = getAllConfigs(basepack);
all_configs ~= configs;
package_indices[basepack] = pidx;
}
 
// get the current config/version of the current dependency
sizediff_t childidx = package_indices[basepack];
if (!all_configs[childidx].length) {
enforce(parentbase != root.pack, format("Root package %s contains reference to invalid package %s", parent.pack, ch.pack));
enforce(parentbase != root_base_pack, format("Root package %s contains reference to invalid package %s", parent.pack, ch.pack));
// choose another parent config to avoid the invalid child
if (parentidx > maxcpi) {
error = format("Package %s contains invalid dependency %s", parent.pack, ch.pack);
logDiagnostic("%s (ci=%s)", error, parentidx);
maxcpi = parentidx;
}
enforce(parent != root, "Invalid dependecy %s referenced by the root package.");
} else {
auto config = all_configs[childidx][config_indices[childidx]];
auto chnode = TreeNode(ch.pack, config);
if (!matches(ch.configs, config)) {
// if we are at the root level, we can safely skip the maxcpi computation and instead choose another childidx config
if (parent == root) {
if (parentbase == root_base_pack) {
error = format("No match for dependency %s %s of %s", ch.pack, ch.configs, parent.pack);
return childidx;
}
 
View
14
source/dub/dub.d
// this can hapen when the package description contains syntax errors
logDebug("Invalid package in dependency tree: %s %s", node.pack, node.config);
return null;
}
auto basepack = pack.basePackage;
 
foreach (dname, dspec; pack.dependencies) {
auto dbasename = getBasePackageName(dname);
 
// detect dependencies to the root package (or sub packages thereof)
if (dbasename == basepack.name) {
auto absdeppath = dspec.mapToPath(pack.path).path;
auto desireddeppath = dname == dbasename ? basepack.path : basepack.getSubPackage(getSubPackageName(dname)).path;
enforce(dspec.path.empty || absdeppath == desireddeppath,
format("Dependency from %s to root package references wrong path: %s vs. %s",
node.pack, absdeppath.toNativeString(), desireddeppath.toNativeString()));
ret ~= TreeNodes(dname, node.config);
continue;
}
 
if (dspec.optional && !m_dub.packageManager.getFirstPackage(dname))
continue;
if (m_options & UpgradeOptions.upgrade || !m_selectedVersions || !m_selectedVersions.hasSelectedVersion(dbasename))
ret ~= TreeNodes(dname, dspec.mapToPath(pack.path));