From 710f0970c51037799b5bb51dc1ed7d07aa38c695 Mon Sep 17 00:00:00 2001 From: a dinosaur Date: Sun, 6 Jul 2025 18:32:15 +1000 Subject: [PATCH] Add requirement-based resolution to index --- Sources/apk/Index/ApkIndex.swift | 13 ++++++ .../apk/Version/ApkVersionRequirement.swift | 4 +- .../apk/Version/ApkVersionSpecification.swift | 45 +++++++++++++++++++ Tests/darwin-apk-tests/ApkVersionTests.swift | 13 ++++++ 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/Sources/apk/Index/ApkIndex.swift b/Sources/apk/Index/ApkIndex.swift index f7e9a19..d3ad40f 100644 --- a/Sources/apk/Index/ApkIndex.swift +++ b/Sources/apk/Index/ApkIndex.swift @@ -7,6 +7,7 @@ import Foundation public struct ApkIndex: Sendable { public let packages: [ApkIndexPackage] + public typealias Index = Array.Index } public extension ApkIndex { @@ -21,6 +22,18 @@ public extension ApkIndex { $0.name == name } } + + func resolve(requirement: ApkVersionRequirement) -> ApkIndexPackage? { + self.packages.first { + $0.name == requirement.name && requirement.versionSpec.satisfied(by: $0.version) + } + } + + func resolveIndex(requirement: ApkVersionRequirement) -> Index? { + self.packages.firstIndex { + $0.name == requirement.name && requirement.versionSpec.satisfied(by: $0.version) + } + } } public extension ApkIndex { diff --git a/Sources/apk/Version/ApkVersionRequirement.swift b/Sources/apk/Version/ApkVersionRequirement.swift index aaab99b..bc411f7 100644 --- a/Sources/apk/Version/ApkVersionRequirement.swift +++ b/Sources/apk/Version/ApkVersionRequirement.swift @@ -5,7 +5,7 @@ import Foundation -internal struct ApkVersionRequirement: Sendable, Hashable { +public struct ApkVersionRequirement: Sendable, Hashable { let name: String let versionSpec: ApkVersionSpecification @@ -49,7 +49,7 @@ internal struct ApkVersionRequirement: Sendable, Hashable { } extension ApkVersionRequirement: CustomStringConvertible { - var description: String { + public var description: String { switch self.versionSpec { case .any(let invert): "\(invert ? "!" : "")\(self.name)" diff --git a/Sources/apk/Version/ApkVersionSpecification.swift b/Sources/apk/Version/ApkVersionSpecification.swift index eae3b55..bac67cd 100644 --- a/Sources/apk/Version/ApkVersionSpecification.swift +++ b/Sources/apk/Version/ApkVersionSpecification.swift @@ -30,6 +30,51 @@ internal extension ApkVersionSpecification { return false } } + + func satisfied(by version: String) -> Bool { + switch self { + case .any: + //return true + return ApkVersionCompare.validate(version) + case .constraint(_ , let op, let requiredVersion): + switch ApkVersionCompare.compare(version, requiredVersion, mode: op.isFuzzy ? .fuzzy : .normal) { + case .equal: return op.isEqual + case .greater: return op.isGreater + case .less: return op.isLess + default: return false + } + } + } +} + +internal extension ApkVersionSpecification.Operator { + @inlinable var isFuzzy: Bool { + switch self { + case .fuzzyEquals, .lessFuzzy, .greaterFuzzy: return true + default: return false + } + } + + @inlinable var isEqual: Bool { + switch self { + case .equals, .fuzzyEquals, .greaterEqual, .lessEqual, .greaterFuzzy, .lessFuzzy: true + default: false + } + } + + @inlinable var isGreater: Bool { + switch self { + case .greater, .greaterEqual, .greaterFuzzy: true + default: false + } + } + + @inlinable var isLess: Bool { + switch self { + case .less, .lessEqual, .lessFuzzy: true + default: false + } + } } extension ApkVersionSpecification.Operator: CustomStringConvertible { diff --git a/Tests/darwin-apk-tests/ApkVersionTests.swift b/Tests/darwin-apk-tests/ApkVersionTests.swift index ae82a82..b11876a 100644 --- a/Tests/darwin-apk-tests/ApkVersionTests.swift +++ b/Tests/darwin-apk-tests/ApkVersionTests.swift @@ -57,3 +57,16 @@ import Testing #expect(!ApkVersionCompare.validate(invalid), "Should be invalid: \(invalid)") } } + +@Test func testVersionComparion() { + func test(_ spec: ApkVersionSpecification, _ version: String) -> Bool { spec.satisfied(by: version) } + #expect(test(.any(), "15.6-r0")) + #expect(test(.constraint(op: .equals, version: "15.6"), "15.6")) + #expect(test(.constraint(op: .fuzzyEquals, version: "15.6"), "15.6b")) + #expect(test(.constraint(op: .greaterEqual, version: "15.6"), "15.6")) + #expect(test(.constraint(op: .lessEqual, version: "15.6"), "15.6")) + #expect(!test(.constraint(op: .greater, version: "15.6"), "15.6")) + #expect(!test(.constraint(op: .less, version: "15.6"), "15.6")) + #expect(test(.constraint(op: .less, version: "15.6"), "14.7.6")) + #expect(test(.constraint(op: .greaterEqual, version: "13.7.6"), "15.6")) +}