aboutsummaryrefslogtreecommitdiff
path: root/Hutch/Views/Repositories/RepositorySettingsViewModel.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-03-18 20:23:58 -0500
committerChristian Cleberg <[email protected]>2026-03-18 20:23:58 -0500
commitc41cd437acde4e4f4c0781cebd4d5f4bf9517bb9 (patch)
tree28bf13b89e36774720d015a26a8979b567ad0be9 /Hutch/Views/Repositories/RepositorySettingsViewModel.swift
parent1745311950fd68ad81957b3ba64f8566cd86ce19 (diff)
parent4dd920558a1c7174c0e9a5b872325df36e363516 (diff)
downloadhutch-c41cd437acde4e4f4c0781cebd4d5f4bf9517bb9.tar.gz
hutch-c41cd437acde4e4f4c0781cebd4d5f4bf9517bb9.tar.bz2
hutch-c41cd437acde4e4f4c0781cebd4d5f4bf9517bb9.zip
v1.2: Merge branch 'dev'
Diffstat (limited to 'Hutch/Views/Repositories/RepositorySettingsViewModel.swift')
-rw-r--r--Hutch/Views/Repositories/RepositorySettingsViewModel.swift74
1 files changed, 62 insertions, 12 deletions
diff --git a/Hutch/Views/Repositories/RepositorySettingsViewModel.swift b/Hutch/Views/Repositories/RepositorySettingsViewModel.swift
index d6f3300..71d6ab6 100644
--- a/Hutch/Views/Repositories/RepositorySettingsViewModel.swift
+++ b/Hutch/Views/Repositories/RepositorySettingsViewModel.swift
@@ -6,12 +6,20 @@ private struct UpdateRepoResponse: Decodable, Sendable {
let updateRepository: UpdatedRepo
}
+private struct UpdateRepoInfoResponse: Decodable, Sendable {
+ let updateRepository: UpdatedRepoInfo
+}
+
private struct UpdatedRepo: Decodable, Sendable {
- let id: Int
- let rid: String
+ let id: Int?
+ let rid: String?
let name: String
let description: String?
- let visibility: Visibility
+ let visibility: Visibility?
+}
+
+private struct UpdatedRepoInfo: Decodable, Sendable {
+ let id: Int
}
private struct ACLResponse: Decodable, Sendable {
@@ -71,6 +79,7 @@ final class RepositorySettingsViewModel {
var editedDescription: String
var editedVisibility: Visibility
var editedHead: String
+ private let originalEditedHead: String
var isSavingInfo = false
// MARK: - Rename fields
@@ -116,11 +125,14 @@ final class RepositorySettingsViewModel {
self.branches = branches
// Extract branch name from HEAD reference
+ let initialEditedHead: String
if let head = repository.head?.name {
- self.editedHead = head.replacingOccurrences(of: "refs/heads/", with: "")
+ initialEditedHead = head.replacingOccurrences(of: "refs/heads/", with: "")
} else {
- self.editedHead = "main"
+ initialEditedHead = "main"
}
+ self.editedHead = initialEditedHead
+ self.originalEditedHead = initialEditedHead
}
// MARK: - Update Repository Info
@@ -133,22 +145,32 @@ final class RepositorySettingsViewModel {
}
"""
+ private static let updateRepoInfoMutation = """
+ mutation updateRepository($id: Int!, $input: RepoInput!) {
+ updateRepository(id: $id, input: $input) {
+ id
+ }
+ }
+ """
+
func saveInfo() async {
isSavingInfo = true
defer { isSavingInfo = false }
error = nil
do {
- let input: [String: any Sendable] = [
+ var input: [String: any Sendable] = [
"description": editedDescription,
- "visibility": editedVisibility.rawValue,
- "HEAD": editedHead
+ "visibility": editedVisibility.rawValue
]
+ if let headReference = selectedHeadReferenceForSave() {
+ input["HEAD"] = headReference
+ }
_ = try await client.execute(
service: service,
- query: Self.updateRepoMutation,
+ query: Self.updateRepoInfoMutation,
variables: ["id": repositoryId, "input": input],
- responseType: UpdateRepoResponse.self
+ responseType: UpdateRepoInfoResponse.self
)
} catch {
self.error = error.localizedDescription
@@ -238,8 +260,9 @@ final class RepositorySettingsViewModel {
}
func addACL() async {
- let entity = newACLEntity.trimmingCharacters(in: .whitespacesAndNewlines)
- guard !entity.isEmpty else { return }
+ let rawEntity = newACLEntity.trimmingCharacters(in: .whitespacesAndNewlines)
+ guard !rawEntity.isEmpty else { return }
+ let entity = Self.gitCanonicalEntity(from: rawEntity)
isAddingACL = true
defer { isAddingACL = false }
error = nil
@@ -267,6 +290,33 @@ final class RepositorySettingsViewModel {
}
}
+ static func gitCanonicalEntity(from input: String) -> String {
+ let trimmed = input.trimmingCharacters(in: .whitespacesAndNewlines)
+ guard !trimmed.isEmpty else { return trimmed }
+ let username = trimmed.hasPrefix("~") ? String(trimmed.dropFirst()) : trimmed
+ return "~\(username)"
+ }
+
+ static func gitHeadReference(from input: String) -> String {
+ let trimmed = input.trimmingCharacters(in: .whitespacesAndNewlines)
+ guard !trimmed.isEmpty else { return trimmed }
+ if trimmed.hasPrefix("refs/") {
+ return trimmed
+ }
+ return "refs/heads/\(trimmed)"
+ }
+
+ func selectedHeadReferenceForSave() -> String? {
+ let normalizedEditedHead = editedHead.trimmingCharacters(in: .whitespacesAndNewlines)
+ guard normalizedEditedHead != originalEditedHead else {
+ return nil
+ }
+
+ return branches.first {
+ $0.name.replacingOccurrences(of: "refs/heads/", with: "") == normalizedEditedHead
+ }?.name
+ }
+
func deleteACL(_ entry: ACLEntry) async {
isDeletingACL = true
defer { isDeletingACL = false }