gitbay/MRs/MRCreateViewModel.swift

v1.9.0
gitbay-ios/gitbay/MRs/MRCreateViewModel.swift history · blame · raw

61 lines · 1958 bytes

 1import Foundation
 2import Observation
 3
 4/// `mr create <repo> --source <b> --target <b> --title <t> --file -`.
 5///
 6/// Branch names are typed, not picked: no command lists branches yet
 7/// (krz/gitbay#45). The target prefills with the default branch from
 8/// `repo show`.
 9@Observable
10@MainActor
11final class MRCreateViewModel {
12
13    private(set) var working = false
14    private(set) var errorMessage: String?
15    private(set) var defaultBranch: String?
16    var draft = false
17    var format: String?
18
19    private let client: GitbayClient
20    let repoPath: String
21
22    init(client: GitbayClient, repoPath: String) {
23        self.client = client
24        self.repoPath = repoPath
25    }
26
27    func loadDefaultBranch() async {
28        guard defaultBranch == nil else { return }
29        defaultBranch = (try? await client.read(
30            ["repo", "show", repoPath], as: RepoDetail.self
31        ))?.defaultBranch
32    }
33
34    nonisolated private struct Created: Decodable, Sendable {
35        let number: Int64
36    }
37
38    func create(source: String, target: String, title: String, body: String) async -> Int64? {
39        working = true
40        errorMessage = nil
41        defer { working = false }
42        do {
43            var argv = ["mr", "create", repoPath,
44                        "--source", source, "--target", target, "--title", title]
45            var stdin: String?
46            if !body.isEmpty {
47                argv.append(contentsOf: ["--file", "-"])
48                stdin = body
49            }
50            if let format { argv.append(contentsOf: ["--format", format]) }
51            if draft { argv.append("--draft") }
52            let created = try await client.run(argv, stdin: stdin, as: Created.self)
53            return created?.number
54        } catch let error as GitbayError {
55            errorMessage = error.userFacingMessage
56        } catch {
57            errorMessage = GitbayError.transport(error).userFacingMessage
58        }
59        return nil
60    }
61}