mirror of
https://github.com/GayPizzaSpecifications/darwin-apk.git
synced 2025-08-03 13:31:32 +00:00
97 lines
3.1 KiB
Swift
97 lines
3.1 KiB
Swift
/*
|
|
* darwin-apk © 2024 Gay Pizza Specifications
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import Foundation
|
|
|
|
public struct ApkIndexUpdater {
|
|
public var repositories: [ApkIndexRepository]
|
|
|
|
public init() {
|
|
self.repositories = []
|
|
}
|
|
|
|
public func update() {
|
|
let downloader = ApkIndexDownloader()
|
|
for repo in self.repositories {
|
|
let localIndex = URL(filePath: repo.localName)
|
|
#if false
|
|
let shouldDownload = true
|
|
#else
|
|
let shouldDownload = !FileManager.default.fileExists(atPath: localIndex.path())
|
|
#endif
|
|
if shouldDownload {
|
|
print("Fetching index for \"\(repo.name)\"")
|
|
downloader.downloadFile(remote: repo.url, destination: localIndex)
|
|
}
|
|
}
|
|
|
|
let graph: ApkPackageGraph
|
|
do {
|
|
let tables = try self.repositories.map { try readIndex(URL(filePath: $0.localName)) }
|
|
graph = ApkPackageGraph(index: ApkIndex.merge(tables))
|
|
graph.buildGraphNode()
|
|
|
|
try graph.pkgIndex.description.write(to: URL(filePath: "packages.txt"), atomically: false, encoding: .utf8)
|
|
} catch {
|
|
fatalError(error.localizedDescription)
|
|
}
|
|
|
|
if var out = TextFileWriter(URL(filePath: "shallowIsolates.txt")) {
|
|
for node in graph.shallowIsolates { print(node, to: &out) }
|
|
}
|
|
if var out = TextFileWriter(URL(filePath: "deepIsolates.txt")) {
|
|
for node in graph.deepIsolates { print(node, to: &out) }
|
|
}
|
|
}
|
|
|
|
private func readIndex(_ indexURL: URL) throws -> ApkIndex {
|
|
let tarSignature: [TarReader.Entry]
|
|
let tarRecords: [TarReader.Entry]
|
|
|
|
print("Archive: \(indexURL.lastPathComponent)")
|
|
|
|
let durFormat = Duration.UnitsFormatStyle(
|
|
allowedUnits: [ .seconds, .milliseconds ],
|
|
width: .condensedAbbreviated,
|
|
fractionalPart: .show(length: 3))
|
|
let gzipStart = ContinuousClock.now
|
|
|
|
var tars = [Data]()
|
|
do {
|
|
var file = try FileInputStream(indexURL)
|
|
//var file = try MemoryInputStream(buffer: try Data(contentsOf: indexURL))
|
|
var gzip = GZipReader()
|
|
tars.append(try gzip.read(inStream: file))
|
|
tars.append(try gzip.read(inStream: file))
|
|
} catch {
|
|
fatalError(error.localizedDescription)
|
|
}
|
|
|
|
print("Gzip time: \((ContinuousClock.now - gzipStart).formatted(durFormat))")
|
|
let untarStart = ContinuousClock.now
|
|
|
|
let signatureStream = MemoryInputStream(buffer: tars[0])
|
|
tarSignature = try TarReader.read(signatureStream)
|
|
let recordsStream = MemoryInputStream(buffer: tars[1])
|
|
tarRecords = try TarReader.read(recordsStream)
|
|
|
|
guard case .file(let signatureName, _) = tarSignature.first
|
|
else { fatalError("Missing signature") }
|
|
guard let apkIndexFile = tarRecords.firstFile(name: "APKINDEX")
|
|
else { fatalError("APKINDEX missing") }
|
|
guard let description = tarRecords.firstFile(name: "DESCRIPTION")
|
|
else { fatalError("DESCRIPTION missing") }
|
|
|
|
print("TAR time: \((ContinuousClock.now - untarStart).formatted(durFormat))")
|
|
let indexStart = ContinuousClock.now
|
|
defer {
|
|
print("Index time: \((ContinuousClock.now - indexStart).formatted(durFormat))")
|
|
}
|
|
|
|
return try ApkIndex(raw:
|
|
try ApkRawIndex(lines: MemoryInputStream(buffer: apkIndexFile).lines))
|
|
}
|
|
}
|