diff --git a/source/dub/dependency.d b/source/dub/dependency.d index 833ab40..4692d73 100644 --- a/source/dub/dependency.d +++ b/source/dub/dependency.d @@ -591,7 +591,67 @@ Package r_master = new Package(R_json); auto graph = new DependencyGraph(r_master); assert(graph.missing().length == 1); - foreach (sp; r_master.subPackages) graph.insert(sp); + // Subpackages need to be explicitly added. + graph.insert(r_master.subPackages[0]); assert(graph.missing().length == 0); } + + unittest { + /* + R -> S:sub + */ + auto R_json = parseJsonString(` + { + "name": "R", + "dependencies": { + "S:sub": "~master" + }, + "version": "~master" + } + `); + auto S_w_sub_json = parseJsonString(` + { + "name": "S", + "version": "~master", + "subPackages": [ + { + "name": "sub" + } + ] + } + `); + auto S_wout_sub_json = parseJsonString(` + { + "name": "S", + "version": "~master" + } + `); + auto sub_json = parseJsonString(` + { + "name": "sub", + "version": "~master" + } + `); + + Package r_master = new Package(R_json); + auto graph = new DependencyGraph(r_master); + assert(graph.missing().length == 1); + Package s_master = new Package(S_w_sub_json); + graph.insert(s_master); + assert(graph.missing().length == 1); + graph.insert(s_master.subPackages[0]); + assert(graph.missing().length == 0); + + graph = new DependencyGraph(r_master); + assert(graph.missing().length == 1); + s_master = new Package(S_wout_sub_json); + graph.insert(s_master); + assert(graph.missing().length == 1); + + graph = new DependencyGraph(r_master); + assert(graph.missing().length == 1); + s_master = new Package(sub_json); + graph.insert(s_master); + assert(graph.missing().length == 1); + } } \ No newline at end of file diff --git a/source/dub/package_.d b/source/dub/package_.d index 779609f..6f7b3a2 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -46,7 +46,7 @@ PackageInfo m_info; Package m_parentPackage; Package[] m_subPackages; - Path[string] m_exportedPackages; + Path[] m_exportedPackages; } static bool isPackageAt(Path path) @@ -171,11 +171,7 @@ throw new Exception("'subPackages' found in '" ~ name ~ "'. This is only supported in the main package file for '" ~ m_parentPackage.name ~ "'."); } if ("packageDefinition" in sub) { - auto path = Path(sub.packageDefinition.get!string); - enforce("name" in sub, "A subpackage is missing a name in package '" ~ name ~ "'"); - auto sub_name = sub.name.get!string; - enforce(sub_name !in m_exportedPackages, "Subpackage '" ~ sub_name ~ "' defined more than once in '" ~ name ~ "'"); - m_exportedPackages[sub_name] = path; + m_exportedPackages ~= Path(sub.packageDefinition.get!string); } else { m_subPackages ~= new Package(sub, root, this); @@ -200,7 +196,7 @@ @property inout(Package) basePackage() inout { return m_parentPackage ? m_parentPackage.basePackage : this; } @property inout(Package) parentPackage() inout { return m_parentPackage; } @property inout(Package)[] subPackages() inout { return m_subPackages; } - @property inout(Path[string]) exportedPackages() inout { return m_exportedPackages; } + @property inout(Path[]) exportedPackages() inout { return m_exportedPackages; } @property string[] configurations() const { diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index 4a00d1e..0dae1b0 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -599,20 +599,17 @@ // Additionally to the internally defined subpackages, whose metadata // is loaded with the main package.json, load all externally defined // packages after the package is available with all the data. - foreach ( sub_name, sub_path; pack.exportedPackages ) { + foreach ( sub_path; pack.exportedPackages ) { auto path = pack.path ~ sub_path; if ( !existsFile(path) ) { - logError("Package %s defined sub-package %s, definition file is missing: ", sub_name, path.toNativeString()); + logError("Package %s declared a sub-package, definition file is missing: %s", pack.name, path.toNativeString()); continue; } // Add the subpackage. try { - auto sub_pack = new Package(path, pack); - // Checking the raw name here, instead of the "parent:sub" style. - enforce(sub_pack.info.name == sub_name, "Name of package '" ~ sub_name ~ "' differs in definition in '" ~ path.toNativeString() ~ "'."); - dst_repos ~= sub_pack; + dst_repos ~= new Package(path, pack); } catch( Exception e ){ - logError("Package '%s': Failed to load sub-package '%s' in %s, error: %s", pack.name, sub_name, path.toNativeString(), e.msg); + logError("Package '%s': Failed to load sub-package in %s, error: %s", pack.name, path.toNativeString(), e.msg); logDiagnostic("Full error: %s", e.toString().sanitize()); } } diff --git a/source/dub/project.d b/source/dub/project.d index 99dab94..0094a5f 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -632,10 +632,10 @@ logDiagnostic("Fetching package %s (%d suppliers registered)", pkg, packageSuppliers.length); auto ppath = pkg.getSubPackagePath(); auto basepkg = pkg.getBasePackage(); - foreach (ps; packageSuppliers) { + foreach (supplier; packageSuppliers) { try { // Get main package. - auto sp = new Package(ps.getPackageDescription(basepkg, reqDep.dependency, false)); + auto sp = new Package(supplier.getPackageDescription(basepkg, reqDep.dependency, false)); // Fetch subpackage, if one was requested. foreach (spn; ppath[1 .. $]) { try { @@ -651,18 +651,15 @@ // external package is inferred as having no additional dependencies. // When the package is then fetched the state is re-evaluated and // possible new dependencies will be resolved. - if (spn in sp.exportedPackages) { - string hacked_info = "{\"name\": \"" ~ spn ~ "\"}"; - auto info = parseJson(hacked_info); - sp = new Package(info, Path(), sp); - } - else throw e; + string hacked_info = "{\"name\": \"" ~ spn ~ "\"}"; + auto info = parseJson(hacked_info); + sp = new Package(info, Path(), sp); } } p = sp; break; } catch (Exception e) { - logDiagnostic("No metadata for %s: %s", ps.description, e.msg); + logDiagnostic("No metadata for %s: %s", supplier.description, e.msg); } } enforce(p !is null, "Could not find package candidate for "~pkg~" "~reqDep.dependency.toString());