diff --git a/source/dub/commandline.d b/source/dub/commandline.d index e289bf2..7acf6d5 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -615,11 +615,14 @@ // TODO: only upgrade(select) if necessary, only upgrade(upgrade) every now and then // retrieve missing packages - logDiagnostic("Checking for missing dependencies."); - if (m_single) dub.upgrade(UpgradeOptions.select | UpgradeOptions.noSaveSelections); - else { - dub.upgrade(UpgradeOptions.select); + dub.project.reinit(); + if (!dub.project.hasAllDependencies) { + logDiagnostic("Checking for missing dependencies."); + if (m_single) dub.upgrade(UpgradeOptions.select | UpgradeOptions.noSaveSelections); + else dub.upgrade(UpgradeOptions.select); + } + if (!m_single) { logDiagnostic("Checking for upgrades."); dub.upgrade(UpgradeOptions.upgrade|UpgradeOptions.printUpgradesOnly|UpgradeOptions.useCachedResult); } diff --git a/source/dub/project.d b/source/dub/project.d index 06c2725..a71b4f3 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -50,6 +50,7 @@ Package[] m_dependencies; Package[][Package] m_dependees; SelectedVersions m_selections; + bool m_hasAllDependencies; } /** Loads a project. @@ -113,6 +114,14 @@ /// Package manager instance used by the project. @property inout(PackageManager) packageManager() inout { return m_packageManager; } + /** Determines if all dependencies necessary to build have been collected. + + If this function returns `false`, it may be necessary to add more entries + to `selections`, or to use `Dub.upgrade` to automatically select all + missing dependencies. + */ + bool hasAllDependencies() const { return m_hasAllDependencies; } + /** Allows iteration of the dependency tree in topological order */ int delegate(int delegate(ref Package)) getTopologicalPackageList(bool children_first = false, Package root_package = null, string[string] configs = null) @@ -262,6 +271,7 @@ void reinit() { m_dependencies = null; + m_hasAllDependencies = true; m_packageManager.refresh(false); void collectDependenciesRec(Package pack, int depth = 0) @@ -274,6 +284,10 @@ Dependency vspec = dep.spec; Package p; + // non-optional and optional-default dependencies (if no selections file exists) + // need to be satisfied + bool is_desired = !vspec.optional || (vspec.default_ && m_selections.bare); + auto basename = getBasePackageName(dep.name); auto subname = getSubPackageName(dep.name); if (dep.name == m_rootPackage.basePackage.name) { @@ -284,6 +298,7 @@ try p = m_packageManager.getSubPackage(m_rootPackage.basePackage, subname, false); catch (Exception e) { logDiagnostic("%sError getting sub package %s: %s", indent, dep.name, e.msg); + if (is_desired) m_hasAllDependencies = false; continue; } } else if (m_selections.hasSelectedVersion(basename)) { @@ -322,6 +337,7 @@ if (!p) { logDiagnostic("%sMissing dependency %s %s of %s", indent, dep.name, vspec, pack.name); + if (is_desired) m_hasAllDependencies = false; continue; }