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;
 				}