summaryrefslogtreecommitdiff
path: root/Hutch/Views/Repositories/RepositoryDetailViewModel.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-20 12:51:22 -0500
committerChristian Cleberg <[email protected]>2026-04-20 12:51:22 -0500
commitd29fbef60abdffaee190b758530dde9212745ed2 (patch)
tree4615b6bc3ade3395188360e753ed7c757ee4eeb8 /Hutch/Views/Repositories/RepositoryDetailViewModel.swift
parent454c459394437f346a2d08d59a5504c0f6ec299f (diff)
downloadhutch-d29fbef60abdffaee190b758530dde9212745ed2.tar.gz
hutch-d29fbef60abdffaee190b758530dde9212745ed2.tar.bz2
hutch-d29fbef60abdffaee190b758530dde9212745ed2.zip
fix: ensure all branches and tags are accounted for and not cutoff due to pagination
Diffstat (limited to 'Hutch/Views/Repositories/RepositoryDetailViewModel.swift')
-rw-r--r--Hutch/Views/Repositories/RepositoryDetailViewModel.swift80
1 files changed, 69 insertions, 11 deletions
diff --git a/Hutch/Views/Repositories/RepositoryDetailViewModel.swift b/Hutch/Views/Repositories/RepositoryDetailViewModel.swift
index 8dec51b..9aff1a4 100644
--- a/Hutch/Views/Repositories/RepositoryDetailViewModel.swift
+++ b/Hutch/Views/Repositories/RepositoryDetailViewModel.swift
@@ -240,9 +240,9 @@ final class RepositoryDetailViewModel {
// MARK: - References
private static let refsQuery = """
- query refs($rid: ID!) {
+ query refs($rid: ID!, $cursor: Cursor) {
repository(rid: $rid) {
- references {
+ references(cursor: $cursor) {
results {
name
target
@@ -263,15 +263,15 @@ final class RepositoryDetailViewModel {
error = nil
do {
- let result = try await client.execute(
- service: service,
- query: Self.refsQuery,
- variables: ["rid": repository.rid],
- responseType: RefsResponse.self
- )
- let allRefs = result.repository?.references.results ?? []
- branches = allRefs.filter { $0.name.hasPrefix("refs/heads/") }.map { $0.toDetail() }
- tags = allRefs.filter { $0.name.hasPrefix("refs/tags/") }.map { $0.toDetail() }
+ let allRefs = try await fetchAllReferences()
+ branches = allRefs
+ .filter { $0.name.hasPrefix("refs/heads/") }
+ .map { $0.toDetail() }
+ .sorted(by: Self.sortBranches)
+ tags = allRefs
+ .filter { $0.name.hasPrefix("refs/tags/") }
+ .map { $0.toDetail() }
+ .sorted(by: Self.sortTags)
} catch {
if isEmptyRepositoryError(error) {
branches = []
@@ -284,6 +284,64 @@ final class RepositoryDetailViewModel {
isLoadingRefs = false
}
+ var defaultBranchReference: ReferenceDetail? {
+ if let headName = repository.head?.name,
+ let branch = branches.first(where: { $0.name == headName }) {
+ return branch
+ }
+ return branches.first
+ }
+
+ var latestTagReference: ReferenceDetail? {
+ tags.first
+ }
+
+ private func fetchAllReferences() async throws -> [ReferencePayload] {
+ var allRefs: [ReferencePayload] = []
+ var cursor: String?
+
+ repeat {
+ let page = try await fetchReferencePage(cursor: cursor)
+ allRefs.append(contentsOf: page.results)
+ cursor = page.cursor
+ } while cursor != nil
+
+ return allRefs
+ }
+
+ private func fetchReferencePage(cursor: String?) async throws -> RefsPage {
+ var variables: [String: any Sendable] = ["rid": repository.rid]
+ if let cursor {
+ variables["cursor"] = cursor
+ }
+
+ let result = try await client.execute(
+ service: service,
+ query: Self.refsQuery,
+ variables: variables,
+ responseType: RefsResponse.self
+ )
+
+ return result.repository?.references ?? RefsPage(results: [], cursor: nil)
+ }
+
+ nonisolated private static func sortBranches(_ lhs: ReferenceDetail, _ rhs: ReferenceDetail) -> Bool {
+ lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending
+ }
+
+ nonisolated private static func sortTags(_ lhs: ReferenceDetail, _ rhs: ReferenceDetail) -> Bool {
+ switch (lhs.date, rhs.date) {
+ case let (lhsDate?, rhsDate?) where lhsDate != rhsDate:
+ return lhsDate > rhsDate
+ case (.some, nil):
+ return true
+ case (nil, .some):
+ return false
+ default:
+ return lhs.name.localizedCaseInsensitiveCompare(rhs.name) == .orderedAscending
+ }
+ }
+
// MARK: - README
private static let readmeQuery = """