a native ios client for gitbay

client ios swift

https://gitbay.org

gitbay/Repos/RepoModels.swift

ui-smoke
gitbay-ios/gitbay/Repos/RepoModels.swift history · blame · raw

152 lines · 4651 bytes

  1import Foundation
  2
  3/// One row of `repo list`.
  4nonisolated struct RepoSummary: Decodable, Sendable, Hashable, Identifiable {
  5    let path: String
  6    let visibility: String
  7    let description: String?
  8    let archived: Bool?
  9    /// Present on `repo search` rows, absent on `repo list`.
 10    let topics: [String]?
 11
 12    var id: String { path }
 13    var isArchived: Bool { archived ?? false }
 14    var isPrivate: Bool { visibility == "private" }
 15
 16    /// "krz/gitbay"  ("krz", "gitbay")
 17    var owner: String { String(path.split(separator: "/").first ?? "") }
 18    var name: String { String(path.split(separator: "/").last ?? "") }
 19}
 20
 21/// `repo show <owner/name>`.
 22nonisolated struct RepoDetail: Decodable, Sendable, Hashable {
 23    let path: String
 24    let description: String?
 25    let website: String?
 26    let visibility: String
 27    let defaultBranch: String
 28    let protectedBranches: [String]?
 29    let archived: Bool?
 30    let topics: [String]?
 31
 32    enum CodingKeys: String, CodingKey {
 33        case path, description, website, visibility, archived, topics
 34        case defaultBranch = "default_branch"
 35        case protectedBranches = "protected_branches"
 36    }
 37
 38    var isArchived: Bool { archived ?? false }
 39}
 40
 41/// `repo refs <owner/name>`  the branches and tags the server knows.
 42nonisolated struct RepoRefs: Decodable, Sendable, Hashable {
 43    let branches: [RepoRef]
 44    let tags: [RepoRef]
 45}
 46
 47nonisolated struct RepoRef: Decodable, Sendable, Hashable, Identifiable {
 48    let name: String
 49    let sha: String
 50    var id: String { name }
 51}
 52
 53/// `repo tree`  one directory listing.
 54nonisolated struct TreeListing: Decodable, Sendable, Hashable {
 55    let path: String
 56    let ref: String
 57    let dir: String
 58    let entries: [TreeEntry]
 59}
 60
 61/// One entry of a tree. The sha is the git object id  content at a sha
 62/// never changes, which is what makes caching on it sound.
 63nonisolated struct TreeEntry: Decodable, Sendable, Hashable, Identifiable {
 64    let name: String
 65    let type: String // blob | tree
 66    let mode: String
 67    let sha: String
 68    let size: Int64?
 69
 70    var id: String { sha + name }
 71    var isDirectory: Bool { type == "tree" }
 72    var isSymlink: Bool { mode == "120000" }
 73}
 74
 75/// `repo cat`  one file. Exactly one of `content`/`base64` is set.
 76nonisolated struct FileContent: Decodable, Sendable, Hashable {
 77    let path: String
 78    let ref: String
 79    let file: String
 80    let size: Int
 81    let binary: Bool
 82    let truncated: Bool?
 83    let content: String?
 84    let base64: String?
 85
 86    var isTruncated: Bool { truncated ?? false }
 87
 88    var data: Data? {
 89        if let content { return Data(content.utf8) }
 90        if let base64 { return Data(base64Encoded: base64) }
 91        return nil
 92    }
 93}
 94
 95/// `repo log`  one commit, with its signature verdict.
 96nonisolated struct Commit: Decodable, Sendable, Hashable, Identifiable {
 97    let sha: String
 98    let subject: String
 99    let authorName: String
100    let authorEmail: String
101    let committerEmail: String?
102    let date: Date
103    let signature: Signature
104
105    enum CodingKeys: String, CodingKey {
106        case sha, subject, date, signature
107        case authorName = "author_name"
108        case authorEmail = "author_email"
109        case committerEmail = "committer_email"
110    }
111
112    var id: String { sha }
113    var shortSHA: String { String(sha.prefix(10)) }
114
115    nonisolated struct Signature: Decodable, Sendable, Hashable {
116        let state: SignatureState
117        let signer: String?
118        let keyFingerprint: String?
119
120        enum CodingKeys: String, CodingKey {
121            case state, signer
122            case keyFingerprint = "key_fingerprint"
123        }
124    }
125}
126
127/// The server's verdict on a commit signature; `internal/sig/verify.go`.
128/// Unknown future states decode as `.unrecognized` rather than failing the
129/// whole log.
130nonisolated enum SignatureState: Sendable, Hashable, Decodable {
131    case verified
132    case signedUnknownKey
133    case signedEmailMismatch
134    case signedKeyExpired
135    case signedKeyRevoked
136    case badSignature
137    case unsigned
138    case unrecognized(String)
139
140    init(from decoder: any Decoder) throws {
141        switch try decoder.singleValueContainer().decode(String.self) {
142        case "verified": self = .verified
143        case "signed_unknown_key": self = .signedUnknownKey
144        case "signed_email_mismatch": self = .signedEmailMismatch
145        case "signed_key_expired": self = .signedKeyExpired
146        case "signed_key_revoked": self = .signedKeyRevoked
147        case "bad_signature": self = .badSignature
148        case "unsigned": self = .unsigned
149        case let other: self = .unrecognized(other)
150        }
151    }
152}