mirror of
https://github.com/GayPizzaSpecifications/darwin-apk.git
synced 2025-08-03 13:31:32 +00:00
fix package graph
This commit is contained in:
@ -24,33 +24,27 @@ public class ApkPackageGraph {
|
|||||||
for (idx, package) in self.pkgIndex.packages.enumerated() {
|
for (idx, package) in self.pkgIndex.packages.enumerated() {
|
||||||
provides[package.name] = idx
|
provides[package.name] = idx
|
||||||
for provision in package.provides {
|
for provision in package.provides {
|
||||||
provides[provision.name] = idx
|
if !provides.keys.contains(provision.name) {
|
||||||
|
provides[provision.name] = idx
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (id, package) in pkgIndex.packages.enumerated() {
|
for (id, package) in pkgIndex.packages.enumerated() {
|
||||||
|
let children: [ApkIndexRequirementRef] = package.dependencies.filter { dependency in dependency.requirement.versionSpec != .conflict }.compactMap { dependency in
|
||||||
|
guard let id = provides[dependency.requirement.name] else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return .init(self, id: id, constraint: .dep(version: dependency.requirement.versionSpec))
|
||||||
|
}
|
||||||
self._nodes.append(.init(self,
|
self._nodes.append(.init(self,
|
||||||
id: id,
|
id: id,
|
||||||
children: package.dependencies.compactMap { dependency in
|
children: children
|
||||||
guard let id = provides[dependency.requirement.name] else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return .init(self, id: id, constraint: .dep(version: dependency.requirement.versionSpec))
|
|
||||||
} + package.provides.compactMap { provision in
|
|
||||||
guard let id = provides[provision.name] else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return .init(self, id: id, constraint: .provision)
|
|
||||||
} + package.installIf.compactMap { installIf in
|
|
||||||
guard let id = provides[installIf.requirement.name] else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return .init(self, id: id, constraint: .installIf(version: installIf.requirement.versionSpec ))
|
|
||||||
}
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
var reverseDependencies = [ApkIndexRequirementRef: [ApkIndexRequirementRef]]()
|
var reverseDependencies = [ApkIndexRequirementRef: [ApkIndexRequirementRef]]()
|
||||||
|
|
||||||
for (index, node) in self._nodes.enumerated() {
|
for (index, node) in self._nodes.enumerated() {
|
||||||
for child in node.children {
|
for child in node.children {
|
||||||
reverseDependencies[child, default: []].append(
|
reverseDependencies[child, default: []].append(
|
||||||
@ -60,6 +54,7 @@ public class ApkPackageGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (ref, parents) in reverseDependencies {
|
for (ref, parents) in reverseDependencies {
|
||||||
|
let package = self._nodes[ref.packageID].package
|
||||||
self._nodes[ref.packageID].parents = parents
|
self._nodes[ref.packageID].parents = parents
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,30 +62,31 @@ public class ApkPackageGraph {
|
|||||||
|
|
||||||
extension ApkPackageGraph {
|
extension ApkPackageGraph {
|
||||||
func findDependencyCycle(node: ApkPackageGraphNode) -> (ApkPackageGraphNode, ApkPackageGraphNode)? {
|
func findDependencyCycle(node: ApkPackageGraphNode) -> (ApkPackageGraphNode, ApkPackageGraphNode)? {
|
||||||
var resolving = Set<ApkPackageGraphNode>()
|
var resolving = Set<Int>()
|
||||||
var visited = Set<ApkPackageGraphNode>()
|
var visited = Set<Int>()
|
||||||
return self.findDependencyCycle(node: node, &resolving, &visited)
|
return self.findDependencyCycle(node: node, &resolving, &visited)
|
||||||
}
|
}
|
||||||
|
|
||||||
func findDependencyCycle(
|
func findDependencyCycle(
|
||||||
node: ApkPackageGraphNode,
|
node: ApkPackageGraphNode,
|
||||||
_ resolving: inout Set<ApkPackageGraphNode>,
|
_ resolving: inout Set<Int>,
|
||||||
_ visited: inout Set<ApkPackageGraphNode>
|
_ visited: inout Set<Int>
|
||||||
) -> (ApkPackageGraphNode, ApkPackageGraphNode)? {
|
) -> (ApkPackageGraphNode, ApkPackageGraphNode)? {
|
||||||
for dependency in node.children {
|
for dependency in node.children {
|
||||||
let depNode = self._nodes[dependency.packageID]
|
let depNode = self._nodes[dependency.packageID]
|
||||||
if resolving.contains(depNode) {
|
if resolving.contains(depNode.packageID) {
|
||||||
|
print("VIA \(resolving.map({ self._nodes[$0].package.name } )) CYCLE \(node.package.name) \(depNode.package.name)")
|
||||||
return (node, depNode)
|
return (node, depNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !visited.contains(depNode) {
|
if !visited.contains(depNode.packageID) {
|
||||||
resolving.insert(depNode)
|
resolving.insert(depNode.packageID)
|
||||||
if let cycle = findDependencyCycle(node: depNode, &resolving, &visited) {
|
if let cycle = findDependencyCycle(node: depNode, &resolving, &visited) {
|
||||||
return cycle
|
return cycle
|
||||||
}
|
}
|
||||||
|
|
||||||
resolving.remove(depNode)
|
resolving.remove(depNode.packageID)
|
||||||
visited.insert(depNode)
|
visited.insert(depNode.packageID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,12 +117,13 @@ extension ApkPackageGraph {
|
|||||||
working[$0] = .init()
|
working[$0] = .init()
|
||||||
}
|
}
|
||||||
|
|
||||||
while true {
|
while !working.isEmpty {
|
||||||
// Set of all nodes now with satisfied dependencies
|
// Set of all nodes now with satisfied dependencies
|
||||||
var set = working
|
var set = working
|
||||||
.filter { _, children in children.isEmpty }
|
.filter { _, children in children.isEmpty }
|
||||||
.map(\.key)
|
.map(\.key)
|
||||||
|
|
||||||
|
print("set \(set.count) working \(working.count)")
|
||||||
// If nothing was satisfied in this loop, check for cycles
|
// If nothing was satisfied in this loop, check for cycles
|
||||||
// If no cycles exist and the working set is empty, resolve is complete
|
// If no cycles exist and the working set is empty, resolve is complete
|
||||||
if set.isEmpty {
|
if set.isEmpty {
|
||||||
@ -137,18 +134,21 @@ extension ApkPackageGraph {
|
|||||||
let cycles = working.keys.compactMap { node in
|
let cycles = working.keys.compactMap { node in
|
||||||
self.findDependencyCycle(node: node)
|
self.findDependencyCycle(node: node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error if cycle breaking is turned off
|
// Error if cycle breaking is turned off
|
||||||
if !breakCycles {
|
if !breakCycles {
|
||||||
throw .cyclicDependency(cycles: cycles.map { node, dependency in
|
throw .cyclicDependency(cycles: cycles.map { node, dependency in
|
||||||
"\(node) -> \(dependency)"
|
"\(node) -> \(dependency)"
|
||||||
}.joined(separator: "\n"))
|
}.joined(separator: "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bread cycles by setting the new resolution set to dependencies that cycled
|
// Break cycles by setting the new resolution set to dependencies that cycled
|
||||||
set = cycles.map(\.1)
|
set = cycles.flatMap { [$0.0, $0.1] }
|
||||||
|
set = Array(Set(set))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print(set.map({ $0.package.name + " " + String($0.packageID) }))
|
||||||
|
|
||||||
// Add installation set to list of installation sets
|
// Add installation set to list of installation sets
|
||||||
results.append(set)
|
results.append(set)
|
||||||
|
|
||||||
@ -158,10 +158,12 @@ extension ApkPackageGraph {
|
|||||||
}.reduce(into: [ApkPackageGraphNode: Set<ApkPackageGraphNode>]()) { d, node in
|
}.reduce(into: [ApkPackageGraphNode: Set<ApkPackageGraphNode>]()) { d, node in
|
||||||
d[node.key] = node.value.subtracting(set)
|
d[node.key] = node.value.subtracting(set)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (what, deps) in working {
|
||||||
|
print("\(what.packageID) \(what.package.name): \(deps.map { $0.package.name + " " + String($0.packageID) })")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print(working)
|
|
||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@ struct ApkIndexRequirementRef {
|
|||||||
func satisfied(by other: ApkVersionRequirement) -> Bool {
|
func satisfied(by other: ApkVersionRequirement) -> Bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalize() -> ApkIndexRequirementRef {
|
||||||
|
.init(self._graph!, id: self.packageID, constraint: .dep(version: .any))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ApkIndexRequirementRef: Equatable, Hashable {
|
extension ApkIndexRequirementRef: Equatable, Hashable {
|
||||||
|
@ -32,7 +32,7 @@ struct DpkGraphCommand: AsyncParsableCommand {
|
|||||||
#else
|
#else
|
||||||
do {
|
do {
|
||||||
let sorted = try graph.parallelOrderSort()
|
let sorted = try graph.parallelOrderSort()
|
||||||
print(sorted)
|
print(sorted.count)
|
||||||
} catch {
|
} catch {
|
||||||
fatalError(error.localizedDescription)
|
fatalError(error.localizedDescription)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user