diff --git a/src/toolchain/BuildFlags.ts b/src/toolchain/BuildFlags.ts index dcb5d162c..dcb258518 100644 --- a/src/toolchain/BuildFlags.ts +++ b/src/toolchain/BuildFlags.ts @@ -128,6 +128,44 @@ export class BuildFlags { } } + /** + * Extract scratch-path or build-path value from an array of arguments + * @param args Array of command-line arguments to search + * @returns The path value if found, otherwise undefined + */ + private static extractScratchPath(args: string[]): string | undefined { + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if ((arg === "--scratch-path" || arg === "--build-path") && i + 1 < args.length) { + const path = args[i + 1]; + if (path === "") { + throw new Error(`Invalid ${arg}: path cannot be empty`); + } + if (path.startsWith("--")) { + throw new Error( + `Invalid ${arg}: expected a path but got another flag '${path}'` + ); + } + return path; + } + if (arg.startsWith("--scratch-path=")) { + const path = arg.substring("--scratch-path=".length); + if (path === "") { + throw new Error("Invalid --scratch-path: path cannot be empty"); + } + return path; + } + if (arg.startsWith("--build-path=")) { + const path = arg.substring("--build-path=".length); + if (path === "") { + throw new Error("Invalid --build-path: path cannot be empty"); + } + return path; + } + } + return undefined; + } + /** * Get build path from configuration if exists or return a fallback .build directory in given workspace * @param filesystem path to workspace that will be used as a fallback loacation with .build directory @@ -139,7 +177,12 @@ export class BuildFlags { ): string { const nodePath = platform === "posix" ? path.posix : platform === "win32" ? path.win32 : path; - const buildPath = configuration.buildPath.length > 0 ? configuration.buildPath : ".build"; + + const buildPath = + BuildFlags.extractScratchPath(configuration.buildArguments) ?? + BuildFlags.extractScratchPath(configuration.packageArguments) ?? + (configuration.buildPath.length > 0 ? configuration.buildPath : ".build"); + if (!nodePath.isAbsolute(buildPath) && absolute) { return nodePath.join(workspacePath, buildPath); } else { diff --git a/test/unit-tests/toolchain/BuildFlags.test.ts b/test/unit-tests/toolchain/BuildFlags.test.ts index d8c2d29c6..26626a373 100644 --- a/test/unit-tests/toolchain/BuildFlags.test.ts +++ b/test/unit-tests/toolchain/BuildFlags.test.ts @@ -203,6 +203,14 @@ suite("BuildFlags Test Suite", () => { suite("buildDirectoryFromWorkspacePath", () => { const buildPathConfig = mockGlobalValue(configuration, "buildPath"); + const buildArgsConfig = mockGlobalValue(configuration, "buildArguments"); + const packageArgsConfig = mockGlobalValue(configuration, "packageArguments"); + + beforeEach(() => { + buildPathConfig.setValue(""); + buildArgsConfig.setValue([]); + packageArgsConfig.setValue([]); + }); test("no configuration provided", () => { buildPathConfig.setValue(""); @@ -239,6 +247,107 @@ suite("BuildFlags Test Suite", () => { BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", true) ).to.equalPath("/some/full/workspace/test/path/some/relative/test/path"); }); + + test("--scratch-path in buildArguments with separate value", () => { + buildArgsConfig.setValue(["--scratch-path", "/custom/scratch/path"]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("/custom/scratch/path"); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", true) + ).to.equalPath("/custom/scratch/path"); + }); + + test("--scratch-path in buildArguments with equals format", () => { + buildArgsConfig.setValue(["--scratch-path=/custom/scratch/path"]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("/custom/scratch/path"); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", true) + ).to.equalPath("/custom/scratch/path"); + }); + + test("--scratch-path with relative path in buildArguments", () => { + buildArgsConfig.setValue(["--scratch-path", "custom/build"]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("custom/build"); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", true) + ).to.equalPath("/some/full/workspace/test/path/custom/build"); + }); + + test("--build-path in buildArguments (legacy support)", () => { + buildArgsConfig.setValue(["--build-path", "/legacy/build/path"]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("/legacy/build/path"); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", true) + ).to.equalPath("/legacy/build/path"); + }); + + test("--scratch-path in packageArguments", () => { + packageArgsConfig.setValue(["--scratch-path", "/package/scratch/path"]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("/package/scratch/path"); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", true) + ).to.equalPath("/package/scratch/path"); + }); + + test("buildArguments takes precedence over packageArguments", () => { + buildArgsConfig.setValue(["--scratch-path", "/build/args/path"]); + packageArgsConfig.setValue(["--scratch-path", "/package/args/path"]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("/build/args/path"); + }); + + test("buildArguments takes precedence over buildPath config", () => { + buildPathConfig.setValue("/config/path"); + buildArgsConfig.setValue(["--scratch-path", "/build/args/path"]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("/build/args/path"); + }); + + test("packageArguments takes precedence over buildPath config", () => { + buildPathConfig.setValue("/config/path"); + packageArgsConfig.setValue(["--scratch-path", "/package/args/path"]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("/package/args/path"); + }); + + test("--scratch-path among other arguments", () => { + buildArgsConfig.setValue([ + "--verbose", + "--scratch-path", + "/custom/path", + "--configuration", + "release", + ]); + + expect( + BuildFlags.buildDirectoryFromWorkspacePath("/some/full/workspace/test/path", false) + ).to.equalPath("/custom/path"); + }); }); suite("withAdditionalFlags", () => {