diff --git a/source/served/extension.d b/source/served/extension.d index 202bae61..c0854803 100644 --- a/source/served/extension.d +++ b/source/served/extension.d @@ -774,7 +774,54 @@ void delayedProjectActivation(WorkspaceD.Instance instance, string workspaceRoot scope (failure) instance.detach!DubComponent; - instance.get!DubComponent.validateConfiguration(); + auto dub = instance.get!DubComponent; + + dub.validateConfiguration(); + + if (dub.missingDependencies.length) + { + auto downloadNow = proj.config.d.forceDownloadDependencies; + + switch (downloadNow) + { + case DubUpgradeAction.ask: + default: + auto upgrade = translate!"d.dub.downloadMissingUpgrade"; + auto always = translate!"d.dub.downloadMissingAlways"; + auto never = translate!"d.dub.downloadMissingNever"; + auto res = rpc.window.requestMessage(MessageType.info, translate!"d.dub.downloadMissingMsg", [upgrade, always, never]); + if (res == always) + { + rpc.notifyMethod("coded/updateSetting", UpdateSettingParams("forceDownloadDependencies", JsonValue("always"), true)); + goto case DubUpgradeAction.always; + } + else if (res == never) + { + rpc.notifyMethod("coded/updateSetting", UpdateSettingParams("forceDownloadDependencies", JsonValue("never"), true)); + } + else if (res == upgrade) + { + goto case DubUpgradeAction.always; + } + break; + case DubUpgradeAction.always: + reportProgress(ProgressType.importUpgrades, 0, 1, workspaceUri); + scope (exit) + reportProgress(ProgressType.importUpgrades, 1, 1, workspaceUri); + dub.selectAndDownloadMissing(); // TODO: async this call + dub.validateConfiguration(); + break; + case DubUpgradeAction.never: + break; + } + } + + if (dub.missingDependencies.length) + { + error("Missing DUB dependencies, auto complete unavailable for packages: ", + dub.missingDependencies); + } + loadedDub = true; } } diff --git a/source/served/types.d b/source/served/types.d index 6e6ae8c0..27a5a3e8 100644 --- a/source/served/types.d +++ b/source/served/types.d @@ -61,6 +61,13 @@ enum ManyProjectsAction : string load = "load" } +enum DubUpgradeAction : string +{ + ask = "ask", + always = "always", + never = "never" +} + // alias to avoid name clashing alias UserConfiguration = Configuration; @serdeIgnoreUnexpectedKeys @@ -97,6 +104,7 @@ struct Configuration string dubCompiler; bool overrideDfmtEditorconfig = true; bool aggressiveUpdate = false; // differs from default code-d settings on purpose! + DubUpgradeAction forceDownloadDependencies = DubUpgradeAction.ask; bool argumentSnippets = false; bool scanAllFolders = true; string[] disabledRootGlobs; diff --git a/views/en.txt b/views/en.txt index a6a92805..e37e5065 100644 --- a/views/en.txt +++ b/views/en.txt @@ -162,6 +162,10 @@ d.dub.updateFail: Failed to update dub.json d.dub.override: Override without Backup d.dub.notRecipeFile: Dub format conversion only works with package recipes named dub.json, dub.sdl, package.json d.dub.convertFailed: The dub conversion command has failed +d.dub.downloadMissingMsg: Some DUB packages could not be found locally, should they be downloaded through `dub upgrade --missing-only`? +d.dub.downloadMissingUpgrade: Upgrade +d.dub.downloadMissingAlways: Always +d.dub.downloadMissingNever: Never d.coverage.statusText: {0}% Coverage d.coverage.tooltip: Coverage in this file generated from the according .lst file diff --git a/workspace-d/source/workspaced/com/dub.d b/workspace-d/source/workspaced/com/dub.d index b001be20..881f9540 100644 --- a/workspace-d/source/workspaced/com/dub.d +++ b/workspace-d/source/workspaced/com/dub.d @@ -124,11 +124,21 @@ class DubComponent : ComponentWrapper _dub.packageManager.getOrLoadPackage(NativePath(instance.cwd)); _dub.loadPackage(); _dub.project.validate(); + _dub.project.reinit(); + optionalifyRoot(); - selectAndDownloadMissing(); + if (!_compilerBinaryName.length) + _compilerBinaryName = config.get("dub", "defaultCompiler", _dub.defaultCompiler); + setCompiler(_compilerBinaryName); + + _settingsTemplate = cast() _dub.project.rootPackage.getBuildSettings(); + + _dubRunning = true; + } + private void optionalifyRoot() + { // mark all packages as optional so we don't crash - int missingPackages; auto optionalified = optionalifyPackages; foreach (ref pkg; _dub.project.getTopologicalPackageList()) { @@ -137,25 +147,14 @@ class DubComponent : ComponentWrapper .filter!(a => optionalified.canFind(a.name))) { auto d = _dub.project.getDependency(dep.name, true); - if (!d) - missingPackages++; - else + if (d) optionalifyRecipe(d); } } - - if (!_compilerBinaryName.length) - _compilerBinaryName = config.get("dub", "defaultCompiler", _dub.defaultCompiler); - setCompiler(_compilerBinaryName); - - _settingsTemplate = cast() _dub.project.rootPackage.getBuildSettings(); - - _dubRunning = true; } private string[] optionalifyPackages() { - bool[Package] visited; string[] optionalified; foreach (pkg; _dub.project.dependencies) optionalified ~= optionalifyRecipe(cast() pkg); @@ -320,6 +319,7 @@ class DubComponent : ComponentWrapper void upgrade(UpgradeOptions options) { _dub.upgrade(options); + optionalifyRoot(); } /// Equivalent of `upgrade(select | noSaveSelection)` @@ -331,8 +331,6 @@ class DubComponent : ComponentWrapper } /// Equivalent of `upgrade(select | upgrade)` - /// Updates internal dub.selections.json, does not save what has been changed. - /// Keeps existing selections, selects missing dependencies. void upgradeAndSelectAll() { upgrade(UpgradeOptions.select | UpgradeOptions.upgrade); @@ -381,6 +379,12 @@ class DubComponent : ComponentWrapper )); } + /// Lists missing dependencies + const(string[]) missingDependencies() @property const + { + return (cast() _dub.project).missingDependencies; + } + /// Lists all dependencies. This will go through all dependencies and contain the dependencies of dependencies. You need to create a tree structure from this yourself. /// Returns: `[{dependencies: string[string], ver: string, name: string}]` auto dependencies() @property const