From 45ef34ec64a05bd9a70c4839adc85a8f6cb9fd6b Mon Sep 17 00:00:00 2001 From: a dinosaur Date: Sat, 5 Jul 2025 19:22:44 +1000 Subject: [PATCH] Improve indexing error messages --- Sources/apk/Index/ApkIndex.swift | 25 +++++++++++++++++++++--- Sources/apk/Index/ApkIndexPackage.swift | 26 ++++++++++++------------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Sources/apk/Index/ApkIndex.swift b/Sources/apk/Index/ApkIndex.swift index 2bbf63c..f7e9a19 100644 --- a/Sources/apk/Index/ApkIndex.swift +++ b/Sources/apk/Index/ApkIndex.swift @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +import Foundation + public struct ApkIndex: Sendable { public let packages: [ApkIndexPackage] } @@ -32,9 +34,13 @@ public extension ApkIndex { } extension ApkIndex { - init(raw: ApkRawIndex) throws { - self.packages = try raw.packages.map { - try ApkIndexPackage(raw: $0) + init(raw: ApkRawIndex) throws(ApkIndexError) { + self.packages = try raw.packages.map { records throws(ApkIndexError) in + do { + return try ApkIndexPackage(raw: records) + } catch { + throw .parseError(records.lookup("P") ?? "UNKNOWN", error) + } } } } @@ -44,3 +50,16 @@ extension ApkIndex: CustomStringConvertible { self.packages.map(String.init).joined(separator: "\n") } } + +public enum ApkIndexError: Error { + case parseError(String, any Error) +} + +extension ApkIndexError: LocalizedError { + public var errorDescription: String? { + switch self { + case .parseError(let packageName, let cause): + return "Failed to parse index for \"\(packageName)\": \(cause.localizedDescription)" + } + } +} diff --git a/Sources/apk/Index/ApkIndexPackage.swift b/Sources/apk/Index/ApkIndexPackage.swift index 3033aa6..fa383d6 100644 --- a/Sources/apk/Index/ApkIndexPackage.swift +++ b/Sources/apk/Index/ApkIndexPackage.swift @@ -74,32 +74,32 @@ extension ApkIndexPackage { do { dependencies = try record.value.split(separator: " ") .map { .init(requirement: try .init(extract: $0)) } - } catch { throw .badValue(key: record.key) } + } catch { throw .badValue(key: record.key, cause: error.localizedDescription) } case "C": guard let digest = ApkIndexDigest(decode: record.value) else { - throw .badValue(key: record.key) + throw .badValue(key: record.key, cause: "Invalid SHA digest") } indexChecksum = digest case "S": guard let value = UInt64(record.value, radix: 10) else { - throw .badValue(key: record.key) + throw .badValue(key: record.key, cause: "Invalid size value") } packageSize = value case "I": guard let value = UInt64(record.value, radix: 10) else { - throw .badValue(key: record.key) + throw .badValue(key: record.key, cause: "Invalid installed size value") } installedSize = value case "p": do { provides = try record.value.split(separator: " ") .map { .init(requirement: try .init(extract: $0)) } - } catch { throw .badValue(key: record.key) } + } catch { throw .badValue(key: record.key, cause: error.localizedDescription) } case "i": do { installIf = try record.value.split(separator: " ") .map { .init(requirement: try .init(extract: $0)) } - } catch { throw .badValue(key: record.key) } + } catch { throw .badValue(key: record.key, cause: error.localizedDescription) } case "o": origin = record.value case "m": @@ -107,7 +107,7 @@ extension ApkIndexPackage { case "t": guard let timet = UInt64(record.value, radix: 10), let timetInterval = TimeInterval(exactly: timet) else { - throw .badValue(key: record.key) + throw .badValue(key: record.key, cause: "Invalid build time value") } buildTime = Date(timeIntervalSince1970: timetInterval) case "c": @@ -115,7 +115,7 @@ extension ApkIndexPackage { case "k": guard let value = UInt64(record.value, radix: 10), (0..