diff --git a/src/toolchain/toolchain.ts b/src/toolchain/toolchain.ts index c759ecece..7f78f6ff1 100644 --- a/src/toolchain/toolchain.ts +++ b/src/toolchain/toolchain.ts @@ -20,7 +20,7 @@ import * as vscode from "vscode"; import configuration from "../configuration"; import { SwiftOutputChannel } from "../ui/SwiftOutputChannel"; import { execFile, execSwift } from "../utilities/utilities"; -import { expandFilePathTilda, pathExists } from "../utilities/filesystem"; +import { expandFilePathTilde, pathExists } from "../utilities/filesystem"; import { Version } from "../utilities/version"; import { BuildFlags } from "./BuildFlags"; import { Sanitizer } from "./Sanitizer"; @@ -536,7 +536,7 @@ export class SwiftToolchain { } // swift may be a symbolic link const realSwift = await fs.realpath(swift); - const swiftPath = expandFilePathTilda(path.dirname(realSwift)); + const swiftPath = expandFilePathTilde(path.dirname(realSwift)); return await this.getSwiftEnvPath(swiftPath); } catch { throw Error("Failed to find swift executable"); diff --git a/src/utilities/filesystem.ts b/src/utilities/filesystem.ts index 8e63b57eb..b68fcaef6 100644 --- a/src/utilities/filesystem.ts +++ b/src/utilities/filesystem.ts @@ -58,9 +58,22 @@ export function isPathInsidePath(subpath: string, parent: string): boolean { * @param filepath File path * @returns full path */ -export function expandFilePathTilda(filepath: string): string { - if (process.platform !== "win32" && filepath[0] === "~" && process.env.HOME) { - return path.join(process.env.HOME, filepath.slice(1)); +export function expandFilePathTilde( + filepath: string, + directory: string | null = process.env.HOME ?? null, + platform: NodeJS.Platform = process.platform +): string { + // Guard no expanding on windows + if (platform === "win32") { + return filepath; } - return filepath; + // Guard tilde is present + if (filepath[0] !== "~") { + return filepath; + } + // Guard we know home directory + if (!directory) { + return filepath; + } + return path.join(directory, filepath.slice(1)); } diff --git a/test/integration-tests/utilities/filesystem.test.ts b/test/integration-tests/utilities/filesystem.test.ts index 220e826d6..067dea575 100644 --- a/test/integration-tests/utilities/filesystem.test.ts +++ b/test/integration-tests/utilities/filesystem.test.ts @@ -14,31 +14,9 @@ import * as assert from "assert"; import * as path from "path"; -import { - isPathInsidePath, - expandFilePathTilda, - fileExists, - pathExists, -} from "../../../src/utilities/filesystem"; +import { fileExists, pathExists } from "../../../src/utilities/filesystem"; suite("File System Utilities Test Suite", () => { - test("isPathInsidePath", () => { - assert(isPathInsidePath("/home/user/package", "/home/user/")); - assert(isPathInsidePath("/home/user/package/test", "/home/user/")); - assert(isPathInsidePath("/home/user/", "/home/user/")); - assert(isPathInsidePath("/home/user/.build", "/home/user/")); - assert(!isPathInsidePath("/home/user/package", "/home/user/package2")); - assert(!isPathInsidePath("/home/user/package/.build", "/home/user/package2/.build")); - assert(!isPathInsidePath("/home/user/package/", "/home/user/package/.build")); - }); - - test("expandFilePathTilda", () => { - const homeDir = process.env.HOME; - assert(expandFilePathTilda("~/Test"), `${homeDir}/Test`); - assert(expandFilePathTilda("/Users/John/Test"), `/Users/John/Test`); - assert(expandFilePathTilda("/Users/~/Test"), `/Users/~/Test`); - }); - test("fileExists", async () => { assert(await fileExists(__filename)); assert(!(await fileExists(__dirname))); diff --git a/test/unit-tests/utilities/filesystem.test.ts b/test/unit-tests/utilities/filesystem.test.ts new file mode 100644 index 000000000..477b1abf1 --- /dev/null +++ b/test/unit-tests/utilities/filesystem.test.ts @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the VS Code Swift open source project +// +// Copyright (c) 2024 the VS Code Swift project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of VS Code Swift project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import { isPathInsidePath, expandFilePathTilde } from "../../../src/utilities/filesystem"; +import { expect } from "chai"; + +suite("File System Utilities Unit Test Suite", () => { + test("isPathInsidePath", () => { + expect(isPathInsidePath("/home/user/package", "/home/user/")).to.be.true; + expect(isPathInsidePath("/home/user/package/test", "/home/user/")).to.be.true; + expect(isPathInsidePath("/home/user/", "/home/user/")).to.be.true; + expect(isPathInsidePath("/home/user/.build", "/home/user/")).to.be.true; + expect(isPathInsidePath("/home/user/package", "/home/user/package2")).to.be.false; + expect(isPathInsidePath("/home/user/package/.build", "/home/user/package2/.build")).to.be + .false; + expect(isPathInsidePath("/home/user/package/", "/home/user/package/.build")).to.be.false; + }); + + suite("expandFilePathTilde", () => { + test("expands tilde", () => { + expect(expandFilePathTilde("~/Test", "/Users/John", "darwin")).to.equal( + "/Users/John/Test" + ); + }); + + test("no tilde present", () => { + expect(expandFilePathTilde("/Users/John/Test", "/Users/John2", "darwin")).to.equal( + "/Users/John/Test" + ); + }); + + test("tilde not first character", () => { + expect(expandFilePathTilde("/Users/~/Test", "/Users/John", "darwin")).to.equal( + "/Users/~/Test" + ); + }); + + test("don't know the home directory", () => { + expect(expandFilePathTilde("~/Test", null, "darwin")).to.equal("~/Test"); + }); + + test("don't resolve tilde on Windows", () => { + expect(expandFilePathTilde("~/Test", "C:\\Users\\John", "win32")).to.equal("~/Test"); + }); + }); +});