diff --git a/apps/macos/Sources/Clawdis/ClawdisConfigFile.swift b/apps/macos/Sources/Clawdis/ClawdisConfigFile.swift index a65abad5a..63d2ee302 100644 --- a/apps/macos/Sources/Clawdis/ClawdisConfigFile.swift +++ b/apps/macos/Sources/Clawdis/ClawdisConfigFile.swift @@ -2,16 +2,27 @@ import Foundation enum ClawdisConfigFile { private static let logger = Logger(subsystem: "com.steipete.clawdis", category: "config") + private static let configPathEnv = "CLAWDIS_CONFIG_PATH" + private static let stateDirEnv = "CLAWDIS_STATE_DIR" static func url() -> URL { - FileManager.default.homeDirectoryForCurrentUser - .appendingPathComponent(".clawdis") + if let override = self.envPath(self.configPathEnv) { + return URL(fileURLWithPath: override) + } + return self.stateDirURL() .appendingPathComponent("clawdis.json") } + static func stateDirURL() -> URL { + if let override = self.envPath(self.stateDirEnv) { + return URL(fileURLWithPath: override, isDirectory: true) + } + return FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent(".clawdis", isDirectory: true) + } + static func defaultWorkspaceURL() -> URL { - FileManager.default.homeDirectoryForCurrentUser - .appendingPathComponent(".clawdis") + self.stateDirURL() .appendingPathComponent("workspace", isDirectory: true) } @@ -96,4 +107,12 @@ enum ClawdisConfigFile { self.saveDict(root) self.logger.debug("agent workspace updated set=\(!trimmed.isEmpty)") } + + private static func envPath(_ key: String) -> String? { + guard let value = ProcessInfo.processInfo.environment[key]?.trimmingCharacters(in: .whitespacesAndNewlines), + !value.isEmpty else { + return nil + } + return value + } } diff --git a/apps/macos/Sources/Clawdis/SettingsRootView.swift b/apps/macos/Sources/Clawdis/SettingsRootView.swift index a7f88c0de..f53ae9d31 100644 --- a/apps/macos/Sources/Clawdis/SettingsRootView.swift +++ b/apps/macos/Sources/Clawdis/SettingsRootView.swift @@ -105,8 +105,8 @@ struct SettingsRootView: View { } private var nixManagedBanner: some View { - let configPath = ProcessInfo.processInfo.environment["CLAWDIS_CONFIG_PATH"] ?? "~/.clawdis/clawdis.json" - let stateDir = ProcessInfo.processInfo.environment["CLAWDIS_STATE_DIR"] ?? "~/.clawdis" + let configPath = ClawdisConfigFile.url().path + let stateDir = ClawdisConfigFile.stateDirURL().path return VStack(alignment: .leading, spacing: 6) { HStack(spacing: 8) { diff --git a/apps/macos/Tests/ClawdisIPCTests/ClawdisConfigFileTests.swift b/apps/macos/Tests/ClawdisIPCTests/ClawdisConfigFileTests.swift new file mode 100644 index 000000000..ea366e8d6 --- /dev/null +++ b/apps/macos/Tests/ClawdisIPCTests/ClawdisConfigFileTests.swift @@ -0,0 +1,49 @@ +import Foundation +import Testing +@testable import Clawdis + +@Suite +struct ClawdisConfigFileTests { + @Test + func configPathRespectsEnvOverride() { + let override = FileManager.default.temporaryDirectory + .appendingPathComponent("clawdis-config-\(UUID().uuidString)") + .appendingPathComponent("clawdis.json") + .path + + self.withEnv("CLAWDIS_CONFIG_PATH", value: override) { + #expect(ClawdisConfigFile.url().path == override) + } + } + + @Test + func stateDirOverrideSetsConfigPath() { + let dir = FileManager.default.temporaryDirectory + .appendingPathComponent("clawdis-state-\(UUID().uuidString)", isDirectory: true) + .path + + self.withEnv("CLAWDIS_CONFIG_PATH", value: nil) { + self.withEnv("CLAWDIS_STATE_DIR", value: dir) { + #expect(ClawdisConfigFile.stateDirURL().path == dir) + #expect(ClawdisConfigFile.url().path == "\(dir)/clawdis.json") + } + } + } + + private func withEnv(_ key: String, value: String?, _ body: () -> Void) { + let previous = ProcessInfo.processInfo.environment[key] + if let value { + setenv(key, value, 1) + } else { + unsetenv(key) + } + defer { + if let previous { + setenv(key, previous, 1) + } else { + unsetenv(key) + } + } + body() + } +} diff --git a/apps/macos/Tests/ClawdisIPCTests/DeviceModelCatalogTests.swift b/apps/macos/Tests/ClawdisIPCTests/DeviceModelCatalogTests.swift index 4b50fc0b0..aad69b2c4 100644 --- a/apps/macos/Tests/ClawdisIPCTests/DeviceModelCatalogTests.swift +++ b/apps/macos/Tests/ClawdisIPCTests/DeviceModelCatalogTests.swift @@ -30,4 +30,10 @@ struct DeviceModelCatalogTests { #expect(DeviceModelCatalog.symbol(deviceFamily: "Android", modelIdentifier: "", friendlyName: nil) == "android") #expect(DeviceModelCatalog.symbol(deviceFamily: "Linux", modelIdentifier: "", friendlyName: nil) == "cpu") } + + @Test + func presentationUsesBundledModelMappings() { + let presentation = DeviceModelCatalog.presentation(deviceFamily: "iPhone", modelIdentifier: "iPhone1,1") + #expect(presentation?.title == "iPhone") + } }