Commit 3078d39ae2

3078d39ae26f4c077bb9186ce0ec692263d589ef

parent: b0ba9d0cc4

Unsigned

cmc <hello@cleberg.net> · 2026-04-14 01:32 UTC

fix: more sonarqube quality fixes

Layout: unified · split

Hutch.xcodeproj/project.pbxproj +8 −8
@@ -515,7 +515,7 @@
515515 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
516516 CODE_SIGN_ENTITLEMENTS = Hutch/Hutch.entitlements;
517517 CODE_SIGN_STYLE = Automatic;
518 CURRENT_PROJECT_VERSION = 72;
518 CURRENT_PROJECT_VERSION = 73;
519519 DEVELOPMENT_TEAM = ZCNAX3VL9D;
520520 ENABLE_PREVIEWS = YES;
521521 GENERATE_INFOPLIST_FILE = YES;
@@ -532,7 +532,7 @@
532532 "$(inherited)",
533533 "@executable_path/Frameworks",
534534 );
535 MARKETING_VERSION = 3.1.4;
535 MARKETING_VERSION = 3.1.5;
536536 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch;
537537 PRODUCT_NAME = "$(TARGET_NAME)";
538538 STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -552,7 +552,7 @@
552552 ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
553553 CODE_SIGN_ENTITLEMENTS = Hutch/Hutch.entitlements;
554554 CODE_SIGN_STYLE = Automatic;
555 CURRENT_PROJECT_VERSION = 72;
555 CURRENT_PROJECT_VERSION = 73;
556556 DEVELOPMENT_TEAM = ZCNAX3VL9D;
557557 ENABLE_PREVIEWS = YES;
558558 GENERATE_INFOPLIST_FILE = YES;
@@ -569,7 +569,7 @@
569569 "$(inherited)",
570570 "@executable_path/Frameworks",
571571 );
572 MARKETING_VERSION = 3.1.4;
572 MARKETING_VERSION = 3.1.5;
573573 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch;
574574 PRODUCT_NAME = "$(TARGET_NAME)";
575575 STRING_CATALOG_GENERATE_SYMBOLS = YES;
@@ -632,7 +632,7 @@
632632 APPLICATION_EXTENSION_API_ONLY = YES;
633633 CODE_SIGN_ENTITLEMENTS = HutchWidgetExtension/HutchWidgetExtension.entitlements;
634634 CODE_SIGN_STYLE = Automatic;
635 CURRENT_PROJECT_VERSION = 72;
635 CURRENT_PROJECT_VERSION = 73;
636636 DEVELOPMENT_TEAM = ZCNAX3VL9D;
637637 GENERATE_INFOPLIST_FILE = NO;
638638 INFOPLIST_FILE = HutchWidgetExtension/Info.plist;
@@ -642,7 +642,7 @@
642642 "@executable_path/Frameworks",
643643 "@executable_path/../../Frameworks",
644644 );
645 MARKETING_VERSION = 3.1.4;
645 MARKETING_VERSION = 3.1.5;
646646 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension;
647647 PRODUCT_NAME = "$(TARGET_NAME)";
648648 SKIP_INSTALL = YES;
@@ -661,7 +661,7 @@
661661 APPLICATION_EXTENSION_API_ONLY = YES;
662662 CODE_SIGN_ENTITLEMENTS = HutchWidgetExtension/HutchWidgetExtension.entitlements;
663663 CODE_SIGN_STYLE = Automatic;
664 CURRENT_PROJECT_VERSION = 72;
664 CURRENT_PROJECT_VERSION = 73;
665665 DEVELOPMENT_TEAM = ZCNAX3VL9D;
666666 GENERATE_INFOPLIST_FILE = NO;
667667 INFOPLIST_FILE = HutchWidgetExtension/Info.plist;
@@ -671,7 +671,7 @@
671671 "@executable_path/Frameworks",
672672 "@executable_path/../../Frameworks",
673673 );
674 MARKETING_VERSION = 3.1.4;
674 MARKETING_VERSION = 3.1.5;
675675 PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension;
676676 PRODUCT_NAME = "$(TARGET_NAME)";
677677 SKIP_INSTALL = YES;
Hutch/Networking/SRHTClient.swift +13 −12
@@ -23,13 +23,13 @@ final class SRHTClient: Sendable {
2323
2424 /// The personal access token used for `Authorization: Bearer` headers.
2525 /// Loaded from Keychain on init; can be refreshed via ``reloadToken()``.
26 private let _token: OSAllocatedUnfairLock<String?>
26 private let tokenLock: OSAllocatedUnfairLock<String?>
2727
2828 /// In-memory response cache for stale-while-revalidate pattern.
2929 let responseCache = ResponseCache()
3030
3131 var hasToken: Bool {
32 _token.withLock { $0 != nil }
32 tokenLock.withLock { $0 != nil }
3333 }
3434
3535 init(session: URLSession = .shared, token: String? = nil) {
@@ -37,12 +37,12 @@ final class SRHTClient: Sendable {
3737 self.decoder = JSONDecoder()
3838 self.decoder.dateDecodingStrategy = .srhtFlexible
3939 self.encoder = JSONEncoder()
40 self._token = OSAllocatedUnfairLock(initialState: token)
40 self.tokenLock = OSAllocatedUnfairLock(initialState: token)
4141 }
4242
4343 /// Update the stored token (e.g. after the user saves a new one in Keychain).
4444 func setToken(_ token: String?) {
45 _token.withLock { $0 = token }
45 tokenLock.withLock { $0 = token }
4646 }
4747
4848 /// Execute a GraphQL query or mutation against a SourceHut service.
@@ -59,7 +59,7 @@ final class SRHTClient: Sendable {
5959 variables: [String: any Sendable]? = nil,
6060 responseType _: T.Type
6161 ) async throws -> T {
62 guard let token = _token.withLock({ $0 }), !token.isEmpty else {
62 guard let token = tokenLock.withLock({ $0 }), !token.isEmpty else {
6363 throw SRHTError.unauthorized
6464 }
6565
@@ -173,7 +173,7 @@ final class SRHTClient: Sendable {
173173 file: MultipartUploadFile,
174174 responseType _: T.Type
175175 ) async throws -> T {
176 guard let token = _token.withLock({ $0 }), !token.isEmpty else {
176 guard let token = tokenLock.withLock({ $0 }), !token.isEmpty else {
177177 throw SRHTError.unauthorized
178178 }
179179
@@ -307,7 +307,7 @@ final class SRHTClient: Sendable {
307307 files: [MultipartUploadFile],
308308 responseType _: T.Type
309309 ) async throws -> T {
310 guard let token = _token.withLock({ $0 }), !token.isEmpty else {
310 guard let token = tokenLock.withLock({ $0 }), !token.isEmpty else {
311311 throw SRHTError.unauthorized
312312 }
313313
@@ -417,7 +417,7 @@ final class SRHTClient: Sendable {
417417 service: service,
418418 query: query,
419419 variables: variables,
420 responseType: responseType,
420 responseType: T.self,
421421 cacheKey: cacheKey
422422 )
423423 }
@@ -430,7 +430,7 @@ final class SRHTClient: Sendable {
430430 responseType _: T.Type,
431431 cacheKey: String
432432 ) async throws -> T {
433 guard let token = _token.withLock({ $0 }), !token.isEmpty else {
433 guard let token = tokenLock.withLock({ $0 }), !token.isEmpty else {
434434 throw SRHTError.unauthorized
435435 }
436436
@@ -527,7 +527,7 @@ final class SRHTClient: Sendable {
527527 /// Fetch the contents of a URL as plain text, using the same authorization header.
528528 /// Used for build logs and other non-GraphQL resources.
529529 func fetchText(url: URL) async throws -> String {
530 guard let token = _token.withLock({ $0 }), !token.isEmpty else {
530 guard let token = tokenLock.withLock({ $0 }), !token.isEmpty else {
531531 throw SRHTError.unauthorized
532532 }
533533 guard Self.isTrustedAuthenticatedTextURL(url) else {
@@ -593,12 +593,13 @@ final class SRHTClient: Sendable {
593593 resultKeyPath: String
594594 ) async throws -> [T] {
595595 var all: [T] = []
596 for try await element in paginated(
596 let pages: SRHTPaginatedSequence<T> = paginated(
597597 service: service,
598598 query: query,
599599 variables: variables,
600600 resultKeyPath: resultKeyPath
601 ) {
601 )
602 for try await element in pages {
602603 all.append(element)
603604 }
604605 return all
Hutch/Views/Builds/BuildListViewModel.swift +3 −2
@@ -182,12 +182,13 @@ final class BuildListViewModel {
182182 /// Fetch the first page of jobs. Shows cached data instantly if available,
183183 /// then refreshes from the network in the background.
184184 func loadJobs() async {
185 // Show cached data immediately on first load
185 // Show cached data immediately on first load (may populate `jobs` from cache).
186186 if jobs.isEmpty {
187187 loadFromCache()
188188 }
189189
190 if jobs.isEmpty {
190 let treatAsInitialLoad = jobs.isEmpty
191 if treatAsInitialLoad {
191192 isLoading = true
192193 } else {
193194 isRefreshing = true
Hutch/Views/Pastes/PasteListView.swift +4 −4
@@ -276,14 +276,14 @@ private struct CreatePasteSheet: View {
276276 NavigationStack {
277277 Form {
278278 Section("Files") {
279 ForEach($files) { $file in
279 ForEach($files) { fileBinding in
280280 VStack(alignment: .leading, spacing: 8) {
281 TextField("Filename (optional)", text: $file.filename)
281 TextField("Filename (optional)", text: fileBinding.filename)
282282 .autocorrectionDisabled()
283283 .textInputAutocapitalization(.never)
284284
285285 ZStack(alignment: .topLeading) {
286 if file.contents.isEmpty {
286 if fileBinding.wrappedValue.contents.isEmpty {
287287 Text("Paste contents")
288288 .foregroundStyle(.tertiary)
289289 .padding(.top, 8)
@@ -291,7 +291,7 @@ private struct CreatePasteSheet: View {
291291 .allowsHitTesting(false)
292292 }
293293
294 TextEditor(text: $file.contents)
294 TextEditor(text: fileBinding.contents)
295295 .font(.system(.body, design: .monospaced))
296296 .frame(minHeight: 180)
297297 }
Hutch/Views/Repositories/CommitDetailViewModel.swift +6 −3
@@ -7,8 +7,11 @@ private struct CommitResponse: Decodable, Sendable {
77}
88
99private struct CommitRepository: Decodable, Sendable {
10 // swiftlint:disable:next identifier_name
11 let revparse_single: CommitDetail
10 let revparseSingle: CommitDetail
11
12 enum CodingKeys: String, CodingKey {
13 case revparseSingle = "revparse_single"
14 }
1215}
1316
1417// MARK: - View Model
@@ -66,7 +69,7 @@ final class CommitDetailViewModel {
6669
6770 do {
6871 let result = try await executeWithRetry()
69 commit = result.repository?.revparse_single
72 commit = result.repository?.revparseSingle
7073 } catch {
7174 self.error = error.userFacingMessage
7275 }
Hutch/Views/Repositories/FileTreeViewModel.swift +6 −2
@@ -7,7 +7,11 @@ private struct RevparseResponse: Decodable, Sendable {
77}
88
99private struct RevparseRepository: Decodable, Sendable {
10 let revparse_single: RevparseCommit?
10 let revparseSingle: RevparseCommit?
11
12 enum CodingKeys: String, CodingKey {
13 case revparseSingle = "revparse_single"
14 }
1115}
1216
1317private struct RevparseCommit: Decodable, Sendable {
@@ -277,7 +281,7 @@ final class FileTreeViewModel {
277281 }
278282 throw error
279283 }
280 if let tree = result.repository?.revparse_single?.tree,
284 if let tree = result.repository?.revparseSingle?.tree,
281285 let rootId = tree.id {
282286 navStack = [FileNavEntry(name: "root", treeId: rootId)]
283287 var allEntries = tree.entries?.results ?? []