From 0e7e0f96fb42a0838250cfc7f09522e3bcd6eb63 Mon Sep 17 00:00:00 2001 From: monsterlag <64719697+monsterlag@users.noreply.github.com> Date: Thu, 22 Oct 2026 08:15:46 -0400 Subject: [PATCH] Resolve a relative install --path against the current directory Path(_:) returns nil for relative paths, so `xcodes install 14.0 --path Xcode.xip` silently ignored the archive and looked the version up online instead. --- Sources/xcodes/App.swift | 7 ++++++- Tests/xcodesTests/XipPathTests.swift | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 Tests/xcodesTests/XipPathTests.swift diff --git a/Sources/xcodes/App.swift b/Sources/xcodes/App.swift index 36ee7e5e..d2f4fb23 100644 --- a/Sources/xcodes/App.swift +++ b/Sources/xcodes/App.swift @@ -22,6 +22,11 @@ func getDirectory(possibleDirectory: String?, default: Path = Path.root.join("Ap return directory } +/// Resolves the `--path` argument of `install`, treating relative paths as relative to the current directory. +func xipPath(from pathString: String?) -> Path? { + pathString.map { Path($0) ?? Path.cwd/$0 } +} + struct GlobalDirectoryOption: ParsableArguments { @Option(help: "The directory where your Xcodes are installed. Defaults to /Applications.", completion: .directory) @@ -277,7 +282,7 @@ struct Xcodes: AsyncParsableCommand { installation = .latest } else if latestPrerelease { installation = .latestPrerelease - } else if let pathString = pathString, let path = Path(pathString) { + } else if let path = xipPath(from: pathString) { installation = .path(versionString, path) } else { installation = .version(versionString) diff --git a/Tests/xcodesTests/XipPathTests.swift b/Tests/xcodesTests/XipPathTests.swift new file mode 100644 index 00000000..4ef7fc19 --- /dev/null +++ b/Tests/xcodesTests/XipPathTests.swift @@ -0,0 +1,18 @@ +import XCTest +import Path +@testable import xcodes + +final class XipPathTests: XCTestCase { + func test_xipPath_nilWhenNoPathIsGiven() { + XCTAssertNil(xipPath(from: nil)) + } + + func test_xipPath_keepsAbsolutePath() { + XCTAssertEqual(xipPath(from: "/tmp/Xcode-14.0.0.xip"), Path.root/"tmp/Xcode-14.0.0.xip") + } + + func test_xipPath_resolvesRelativePathAgainstCurrentDirectory() { + XCTAssertEqual(xipPath(from: "Xcode-14.0.0.xip"), Path.cwd/"Xcode-14.0.0.xip") + XCTAssertEqual(xipPath(from: "Downloads/Xcode-14.0.0.xip"), Path.cwd/"Downloads/Xcode-14.0.0.xip") + } +}