Validate SDK before overwriting (#192)

Running an invalid `sdk` subcommand like `xtool sdk list` (there's no
`list` subcommand) is interpreted as "install the sdk at path `./list`".
We previously unconditionally removed the existing SDK during
installation. By switching the order so that we validate the path first,
we avoid performing a potentially destructive action unless we have
clear intent.

See #186.

Before:

```bash
$ xtool sdk list
Removing existing SDK... # destructive!
Error: Could not read file or directory at path 'list'.
```

After:

```bash
$ xtool sdk list
Error: Could not read file or directory at path 'list'.
  See 'xtool help sdk' for usage.
```
This commit is contained in:
Kabir Oberai
2026-01-04 21:55:35 -05:00
committed by GitHub
Unverified
parent 22655f3e70
commit 7a5dfd2ccd
2 changed files with 8 additions and 4 deletions
+4 -1
View File
@@ -18,7 +18,10 @@ struct SDKBuilder {
init(path: String) throws {
var isDir: ObjCBool = false
guard FileManager.default.fileExists(atPath: path, isDirectory: &isDir) else {
throw Console.Error("Could not read file or directory at path '\(path)'")
throw Console.Error("""
Could not read file or directory at path '\(path)'.
See 'xtool help sdk' for usage.
""")
}
let url = URL(fileURLWithPath: path)
+4 -3
View File
@@ -243,14 +243,15 @@ struct InstallSDKOperation {
#if os(macOS)
print("Skipping SDK install; the iOS SDK ships with Xcode on macOS")
#else
// validate input before removing existing SDK
let input = try SDKBuilder.Input(path: path)
let arch = try ArchSelection.auto.sdkBuilderArch
if let sdk = try await DarwinSDK.current() {
print("Removing existing SDK...")
try sdk.remove()
}
let input = try SDKBuilder.Input(path: path)
let arch = try ArchSelection.auto.sdkBuilderArch
let tempDir = try TemporaryDirectory(name: "DarwinSDKBuild")
let builder = SDKBuilder(input: input, outputPath: tempDir.url.path, arch: arch)
let sdkPath = try await builder.buildSDK()