Factor out resolution responsibilities

This commit is contained in:
2025-07-11 20:40:23 +10:00
parent 08a05a44eb
commit 1ba8e14ef4
5 changed files with 59 additions and 83 deletions

View File

@@ -6,31 +6,27 @@
import Foundation
public class ApkPackageGraph {
public var pkgIndex: ApkIndex
private var _nodes = [ApkPackageGraphNode]()
public var nodes: [ApkPackageGraphNode] { self._nodes }
public var shallowIsolates: [ApkPackageGraphNode] { self._nodes.filter(\.isShallow) }
public var deepIsolates: [ApkPackageGraphNode] { self._nodes.filter(\.isDeep) }
public init(index: ApkIndex) {
self.pkgIndex = index
}
public init() {}
public func buildGraphNode() {
public func buildGraphNode(index pkgIndex: ApkIndex, providers: ApkIndexProviderCache) {
for (packageID, package) in pkgIndex.packages.enumerated() {
let children: [ApkPackageGraphNode.ChildRef] = package.dependencies.compactMap { dependency in
guard let providerID = pkgIndex.resolveIndex(requirement: dependency.requirement) else {
guard let providerID = providers.resolve(index: pkgIndex, requirement: dependency.requirement) else {
return nil
}
return .init(constraint: .dependency, packageID: providerID, versionSpec: dependency.requirement.versionSpec)
} + package.installIf.compactMap { installIf in
guard let prvID = pkgIndex.resolveIndex(requirement: installIf.requirement) else {
} /* + package.installIf.compactMap { installIf in
guard let prvID = providers.resolve(index: pkgIndex, requirement: installIf.requirement) else {
return nil
}
return .init(constraint: .installIf, packageID: prvID, versionSpec: installIf.requirement.versionSpec)
}
} */
self._nodes.append(.init(self,
id: packageID,
children: children

View File

@@ -10,23 +10,10 @@ public class ApkPackageGraphNode {
public var parentIDs = [ApkIndex.Index]()
public var children: [ChildRef]
private weak var _graph: ApkPackageGraph?
public var package: ApkIndexPackage {
self._graph!.pkgIndex.packages[self.packageID]
}
public var parents: [ApkIndexPackage] {
self.parentIDs.map { index in self._graph!.pkgIndex.packages[index] }
}
public var childPackages: [ApkIndexPackage] {
self.children.map { child in self._graph!.pkgIndex.packages[child.packageID] }
}
@inlinable public var isShallow: Bool { self.parentIDs.isEmpty }
@inlinable public var isDeep: Bool { self.children.isEmpty }
internal init(_ graph: ApkPackageGraph, id: Int, children: [ChildRef]) {
self._graph = graph
self.packageID = id
self.children = children
}
@@ -54,31 +41,8 @@ extension ApkPackageGraphNode {
}
}
extension ApkPackageGraphNode: CustomStringConvertible {
public var description: String {
let package = self.package
var result = " \(package.nameDescription):\n"
if !self.parentIDs.isEmpty {
result += " parents:\n"
for parent in self.parents {
result += " \(parent.nameDescription)\n"
}
}
if !self.children.isEmpty {
result += " children:\n"
for child in self.children {
let childPackage = self._graph!.pkgIndex.packages[child.packageID]
result += " "
switch child.constraint {
case .dependency: result += "dep="
case .installIf: result += "installIf="
}
result += childPackage.nameDescription
result += ", "
result += child.versionSpec.description
result += "\n"
}
}
return result
extension ApkIndex {
public func at(node: ApkPackageGraphNode) -> ApkIndexPackage {
self.packages[node.packageID]
}
}

View File

@@ -8,12 +8,6 @@ import Foundation
public struct ApkIndex: Sendable {
public let packages: [ApkIndexPackage]
public typealias Index = Array<ApkIndexPackage>.Index
lazy var providers: [(ApkIndexProvides, Index)] = {
self.packages.enumerated().flatMap { index, pkg in
[ (.specific(name: pkg.name, version: pkg.version), index) ] + pkg.provides.map { ($0, index) }
}
}()
}
public extension ApkIndex {
@@ -28,24 +22,8 @@ public extension ApkIndex {
$0.name == name
}
}
mutating func resolve(requirement: ApkVersionRequirement) -> ApkIndexPackage? {
self.providers.filter { prv in prv.0.satisfies(requirement) }
.map { self.packages[$1] }.max()
}
mutating func resolveIndex(requirement: ApkVersionRequirement) -> Index? {
self.providers.filter { prv in prv.0.satisfies(requirement) }
.max { self.packages[$0.1] < self.packages[$1.1] }?.1
}
}
extension ApkIndexPackage: Comparable {
public static func < (lhs: Self, rhs: Self) -> Bool {
// Prefer highest declared provider priority
lhs.providerPriority ?? 0 < rhs.providerPriority ?? 0
}
}
public extension ApkIndex {
static func merge<S: Sequence>(_ tables: S) -> Self where S.Element == Self {

View File

@@ -0,0 +1,37 @@
/*
* darwin-apk © 2025 Gay Pizza Specifications
* SPDX-License-Identifier: Apache-2.0
*/
import Foundation
public struct ApkIndexProviderCache {
private var _providers = [(ApkIndexProvides, ApkIndex.Index)]()
//private var _installIfCache = [(ApkIndexInstallIf, Set<ApkIndex.Index>)]()
public init(index pkgIndex: ApkIndex) {
for (index, pkg) in pkgIndex.packages.enumerated() {
self._providers.append((.specific(name: pkg.name, version: pkg.version), index))
for provision in pkg.provides {
self._providers.append((provision, index))
}
//for installIf in pkg.installIf {
// self._installIfCache.append((installIf, index))
//}
}
}
}
extension ApkIndexProviderCache {
func resolve(index pkgIndex: ApkIndex, requirement: ApkVersionRequirement) -> ApkIndex.Index? {
self._providers.filter { prv in prv.0.satisfies(requirement) }
.max { pkgIndex.packages[$0.1] < pkgIndex.packages[$1.1] }?.1
}
}
extension ApkIndexPackage: Comparable {
public static func < (lhs: Self, rhs: Self) -> Bool {
// Prefer highest declared provider priority
lhs.providerPriority ?? 0 < rhs.providerPriority ?? 0
}
}