Commit 48eb4d9dbf
48eb4d9dbf5408636b96f05510ffc13be8e84fdc
parent: fe4dc49efe
Verified · cmc
cmc <hello@cleberg.net> · 2026-09-17 15:03 UTC
Add KeycaskError with exit codes
Layout: unified · split
Sources/KeycaskCore/KeycaskCore.swift
deleted
−3
| @@ -1,3 +0,0 @@ |
| 1 | | public enum KeycaskCore { |
| 2 | | public static let name = "keycask" |
| 3 | | } |
Sources/KeycaskCore/KeycaskError.swift
added
+38
| @@ -0,0 +1,38 @@ |
| 1 | public enum KeycaskError: Error, Equatable, Sendable { |
| 2 | case notFound(String) |
| 3 | case ambiguous(name: String, candidates: [String]) |
| 4 | case cannotDecrypt |
| 5 | case corrupt(String) |
| 6 | case vaultExists(String) |
| 7 | case noVault(String) |
| 8 | case duplicateID(String) |
| 9 | case io(String) |
| 10 | case usage(String) |
| 11 | case failure(String) |
| 12 | |
| 13 | public var exitCode: Int32 { |
| 14 | switch self { |
| 15 | case .failure, .io, .corrupt, .vaultExists, .duplicateID: 1 |
| 16 | case .usage: 2 |
| 17 | case .notFound, .noVault: 3 |
| 18 | case .cannotDecrypt: 4 |
| 19 | case .ambiguous: 5 |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | public var message: String { |
| 24 | switch self { |
| 25 | case .notFound(let what): "\(what): not found" |
| 26 | case .ambiguous(let name, let candidates): |
| 27 | (["\(name): ambiguous, use an id:"] + candidates).joined(separator: "\n") |
| 28 | case .cannotDecrypt: "cannot decrypt: wrong passphrase or damaged vault" |
| 29 | case .corrupt(let why): "vault is corrupt: \(why)" |
| 30 | case .vaultExists(let path): "vault \(path) already exists" |
| 31 | case .noVault(let path): "vault \(path) not found (run `keycask init`)" |
| 32 | case .duplicateID(let id): "duplicate id \(id)" |
| 33 | case .io(let why): why |
| 34 | case .usage(let why): why |
| 35 | case .failure(let why): why |
| 36 | } |
| 37 | } |
| 38 | } |
Sources/keycask/main.swift
+1 −1
| @@ -1,3 +1,3 @@ |
| 1 | 1 | import KeycaskCore |
| 2 | 2 | |
| 3 | | print(KeycaskCore.name) |
| 3 | print("keycask") |
Tests/KeycaskCoreTests/KeycaskErrorTests.swift
added
+28
| @@ -0,0 +1,28 @@ |
| 1 | import Testing |
| 2 | |
| 3 | @testable import KeycaskCore |
| 4 | |
| 5 | @Suite struct KeycaskErrorTests { |
| 6 | @Test func exitCodesFollowTheSpec() { |
| 7 | #expect(KeycaskError.failure("x").exitCode == 1) |
| 8 | #expect(KeycaskError.io("x").exitCode == 1) |
| 9 | #expect(KeycaskError.corrupt("x").exitCode == 1) |
| 10 | #expect(KeycaskError.vaultExists("x").exitCode == 1) |
| 11 | #expect(KeycaskError.duplicateID("abcd2345").exitCode == 1) |
| 12 | #expect(KeycaskError.usage("x").exitCode == 2) |
| 13 | #expect(KeycaskError.notFound("x").exitCode == 3) |
| 14 | #expect(KeycaskError.noVault("/p").exitCode == 3) |
| 15 | #expect(KeycaskError.cannotDecrypt.exitCode == 4) |
| 16 | #expect(KeycaskError.ambiguous(name: "gh", candidates: []).exitCode == 5) |
| 17 | } |
| 18 | |
| 19 | @Test func messagesNameTheSubject() { |
| 20 | #expect(KeycaskError.notFound("gh").message == "gh: not found") |
| 21 | #expect(KeycaskError.noVault("/v").message == "vault /v not found (run `keycask init`)") |
| 22 | #expect(KeycaskError.vaultExists("/v").message == "vault /v already exists") |
| 23 | #expect( |
| 24 | KeycaskError.cannotDecrypt.message |
| 25 | == "cannot decrypt: wrong passphrase or damaged vault") |
| 26 | #expect(KeycaskError.corrupt("bad json").message == "vault is corrupt: bad json") |
| 27 | } |
| 28 | } |
Tests/KeycaskCoreTests/SmokeTests.swift
deleted
−7
| @@ -1,7 +0,0 @@ |
| 1 | | import Testing |
| 2 | | |
| 3 | | @testable import KeycaskCore |
| 4 | | |
| 5 | | @Test func packageBuilds() { |
| 6 | | #expect(KeycaskCore.name == "keycask") |
| 7 | | } |