Skip to content

Commit 8d896f9

Browse files
Fix developer dir selection in Swiftly toolchain installation (#1897)
1 parent a4c6c70 commit 8d896f9

File tree

3 files changed

+92
-51
lines changed

3 files changed

+92
-51
lines changed

src/commands/installSwiftlyToolchain.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -156,47 +156,53 @@ export async function promptToInstallSwiftlyToolchain(
156156
toolchain: toolchain,
157157
}));
158158

159-
const selected = await vscode.window.showQuickPick(quickPickItems, {
159+
const selectedToolchain = await vscode.window.showQuickPick(quickPickItems, {
160160
title: "Install Swift Toolchain via Swiftly",
161161
placeHolder: "Pick a Swift toolchain to install",
162162
canPickMany: false,
163163
});
164-
if (!selected) {
164+
if (!selectedToolchain) {
165165
return;
166166
}
167167

168-
const target = await askWhereToSetToolchain();
169-
if (!target) {
168+
const xcodes = await SwiftToolchain.findXcodeInstalls();
169+
const selectedDeveloperDir = await showDeveloperDirQuickPick(xcodes);
170+
if (!selectedDeveloperDir) {
170171
return;
171172
}
172173

173-
const xcodes = await SwiftToolchain.findXcodeInstalls();
174-
const developerDir = await showDeveloperDirQuickPick(xcodes);
175-
if (!developerDir) {
174+
const target = await askWhereToSetToolchain();
175+
if (!target) {
176176
return;
177177
}
178178

179179
// Install the toolchain via Swiftly
180-
if (!(await installSwiftlyToolchainWithProgress(selected.toolchain.version.name, ctx.logger))) {
180+
if (
181+
!(await installSwiftlyToolchainWithProgress(
182+
selectedToolchain.toolchain.version.name,
183+
ctx.logger
184+
))
185+
) {
181186
return;
182187
}
188+
183189
// Tell Swiftly to use the newly installed toolchain
184-
if (target === vscode.ConfigurationTarget.Workspace) {
185-
await Promise.all(
186-
vscode.workspace.workspaceFolders?.map(folder =>
187-
Swiftly.use(selected.toolchain.version.name, folder.uri.fsPath)
188-
) ?? []
189-
);
190-
return;
191-
}
192190
await setToolchainPath(
193191
{
194192
category: "swiftly",
195193
async onDidSelect() {
196-
await Swiftly.use(selected.toolchain.version.name);
194+
if (target === vscode.ConfigurationTarget.Workspace) {
195+
await Promise.all(
196+
vscode.workspace.workspaceFolders?.map(folder =>
197+
Swiftly.use(selectedToolchain.toolchain.version.name, folder.uri.fsPath)
198+
) ?? []
199+
);
200+
return;
201+
}
202+
await Swiftly.use(selectedToolchain.toolchain.version.name);
197203
},
198204
},
199-
developerDir,
205+
selectedDeveloperDir.developerDir,
200206
target
201207
);
202208
}

src/ui/ToolchainSelection.ts

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import configuration from "../configuration";
2020
import { SwiftLogger } from "../logging/SwiftLogger";
2121
import { Swiftly } from "../toolchain/swiftly";
2222
import { SwiftToolchain } from "../toolchain/toolchain";
23+
import { isEmptyObject } from "../utilities/utilities";
2324
import { showReloadExtensionNotification } from "./ReloadExtension";
2425

2526
/**
@@ -406,50 +407,48 @@ export async function showToolchainSelectionQuickPick(
406407
if (selectedToolchain?.type === "toolchain") {
407408
// Select an Xcode to build with
408409
let developerDir: string | undefined = undefined;
409-
if (process.platform === "darwin") {
410-
let selectedXcodePath: string | undefined = undefined;
411-
if (selectedToolchain.category === "xcode") {
412-
selectedXcodePath = selectedToolchain.xcodePath;
413-
} else if (xcodePaths.length === 1) {
414-
selectedXcodePath = xcodePaths[0];
415-
} else if (xcodePaths.length > 1) {
416-
selectedXcodePath = await showDeveloperDirQuickPick(xcodePaths);
417-
if (!selectedXcodePath) {
418-
return;
419-
}
420-
}
421-
// Find the actual DEVELOPER_DIR based on the selected Xcode app
422-
if (selectedXcodePath) {
423-
developerDir = await SwiftToolchain.getXcodeDeveloperDir({
424-
...process.env,
425-
DEVELOPER_DIR: selectedXcodePath,
426-
});
410+
if (selectedToolchain.category === "xcode") {
411+
developerDir = await SwiftToolchain.getXcodeDeveloperDir({
412+
...process.env,
413+
DEVELOPER_DIR: selectedToolchain.xcodePath,
414+
});
415+
} else {
416+
const selectedDeveloperDir = await showDeveloperDirQuickPick(xcodePaths);
417+
if (!selectedDeveloperDir) {
418+
return;
427419
}
420+
developerDir = selectedDeveloperDir.developerDir;
428421
}
429422
// Update the toolchain configuration
430423
await setToolchainPath(selectedToolchain, developerDir);
431424
return;
432425
}
433426
}
434427

435-
/**
436-
* Prompt the user to choose a value for the DEVELOPER_DIR environment variable.
437-
*
438-
* @param xcodePaths An array of paths to available Xcode installations on the system
439-
* @returns The selected DEVELOPER_DIR or undefined if the user cancelled selection
440-
*/
441-
export async function showDeveloperDirQuickPick(xcodePaths: string[]): Promise<string | undefined> {
442-
const selected = await vscode.window.showQuickPick<vscode.QuickPickItem>(
428+
async function showXcodeQuickPick(
429+
xcodePaths: string[]
430+
): Promise<{ type: "selected"; xcodePath: string | undefined } | undefined> {
431+
if (process.platform !== "darwin" || xcodePaths.length === 0) {
432+
return { type: "selected", xcodePath: undefined };
433+
}
434+
if (xcodePaths.length === 1) {
435+
return { type: "selected", xcodePath: xcodePaths[1] };
436+
}
437+
type XcodeQuickPickItem = vscode.QuickPickItem & { inUse: boolean; xcodePath: string };
438+
const selected = await vscode.window.showQuickPick<XcodeQuickPickItem>(
443439
SwiftToolchain.getXcodeDeveloperDir(configuration.swiftEnvironmentVariables).then(
444440
existingDeveloperDir => {
445441
return xcodePaths
446442
.map(xcodePath => {
447-
const result: vscode.QuickPickItem = {
443+
const result: XcodeQuickPickItem = {
448444
label: path.basename(xcodePath, ".app"),
449445
detail: xcodePath,
446+
inUse: false,
447+
xcodePath,
450448
};
451449
if (existingDeveloperDir.startsWith(xcodePath)) {
452450
result.description = "$(check) in use";
451+
result.inUse = true;
453452
}
454453
return result;
455454
})
@@ -472,7 +471,35 @@ export async function showDeveloperDirQuickPick(xcodePaths: string[]): Promise<s
472471
canPickMany: false,
473472
}
474473
);
475-
return selected?.detail;
474+
if (!selected) {
475+
return undefined;
476+
}
477+
return { type: "selected", xcodePath: selected.xcodePath };
478+
}
479+
480+
/**
481+
* Prompt the user to choose a value for the DEVELOPER_DIR environment variable.
482+
*
483+
* @param xcodePaths An array of paths to available Xcode installations on the system
484+
* @returns The selected DEVELOPER_DIR or undefined if the user cancelled selection
485+
*/
486+
export async function showDeveloperDirQuickPick(
487+
xcodePaths: string[]
488+
): Promise<{ developerDir: string | undefined } | undefined> {
489+
const selectedXcode = await showXcodeQuickPick(xcodePaths);
490+
if (!selectedXcode) {
491+
return undefined;
492+
}
493+
if (!selectedXcode.xcodePath) {
494+
return { developerDir: undefined };
495+
}
496+
// Find the actual DEVELOPER_DIR based on the selected Xcode app
497+
return {
498+
developerDir: await SwiftToolchain.getXcodeDeveloperDir({
499+
...process.env,
500+
DEVELOPER_DIR: selectedXcode.xcodePath,
501+
}),
502+
};
476503
}
477504

478505
/**
@@ -554,13 +581,13 @@ export async function setToolchainPath(
554581
const toolchainPath = toolchain.category !== "swiftly" ? toolchain.swiftFolderPath : undefined;
555582
const swiftConfiguration = vscode.workspace.getConfiguration("swift");
556583
await swiftConfiguration.update("path", toolchainPath, target);
557-
const swiftEnv = configuration.swiftEnvironmentVariables;
584+
const swiftEnvironmentVariables = {
585+
...configuration.swiftEnvironmentVariables,
586+
DEVELOPER_DIR: developerDir,
587+
};
558588
await swiftConfiguration.update(
559589
"swiftEnvironmentVariables",
560-
{
561-
...swiftEnv,
562-
DEVELOPER_DIR: developerDir,
563-
},
590+
isEmptyObject(swiftEnvironmentVariables) ? undefined : swiftEnvironmentVariables,
564591
target
565592
);
566593
await checkAndRemoveWorkspaceSetting(target);

src/utilities/utilities.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ export const IS_RUNNING_UNDER_DOCKER = IS_RUNNING_UNDER_ACT || IS_RUNNING_UNDER_
5050
*/
5151
export const IS_RUNNING_UNDER_TEST = process.env.RUNNING_UNDER_VSCODE_TEST_CLI === "1";
5252

53+
/** Determines whether the provided object has any properties set to non-null values. */
54+
export function isEmptyObject(obj: { [key: string]: unknown }): boolean {
55+
const properties = Object.getOwnPropertyNames(obj).filter(
56+
property => obj[property] !== undefined && obj[property] !== null
57+
);
58+
return properties.length === 0;
59+
}
60+
5361
/**
5462
* Get required environment variable for Swift product
5563
*

0 commit comments

Comments
 (0)