73 lines
3.1 KiB
Swift
73 lines
3.1 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
// Copyright © 2026 Apple Inc. and the container project authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import ContainerPersistence
|
|
import ContainerResource
|
|
import ContainerizationOCI
|
|
import Foundation
|
|
|
|
extension ClientImage {
|
|
/// Resolves, from the content store, the index descriptor and per-variant
|
|
/// manifest content needed to build an ``ImageResource``.
|
|
///
|
|
/// Manifests without a platform, or whose config/manifest cannot be
|
|
/// fetched, are skipped.
|
|
public func toImageResource(containerSystemConfig: ContainerSystemConfig) async throws -> ImageResource {
|
|
var variants: [ImageResource.Variant] = []
|
|
var earliest: Date?
|
|
|
|
for desc in try await self.index().manifests {
|
|
guard let platform = desc.platform else {
|
|
continue
|
|
}
|
|
let config: ContainerizationOCI.Image
|
|
let manifest: ContainerizationOCI.Manifest
|
|
do {
|
|
config = try await self.config(for: platform)
|
|
manifest = try await self.manifest(for: platform)
|
|
} catch {
|
|
continue
|
|
}
|
|
let size =
|
|
desc.size + manifest.config.size
|
|
+ manifest.layers.reduce(0) { $0 + $1.size }
|
|
|
|
variants.append(.init(platform: platform, digest: desc.digest, size: size, config: config))
|
|
|
|
// Use the earliest variant's creation timestamp as the image's date.
|
|
if let date = config.created.flatMap(Self.parseCreated) {
|
|
earliest = min(earliest ?? date, date)
|
|
}
|
|
}
|
|
|
|
let created = earliest ?? Date(timeIntervalSince1970: 0)
|
|
let displayName = try Self.denormalizeReference(self.description.reference, containerSystemConfig: containerSystemConfig)
|
|
let configuration = ImageResource.ImageConfiguration(description: self.description, creationDate: created)
|
|
return ImageResource(configuration: configuration, variants: variants, displayReference: displayName)
|
|
}
|
|
|
|
private static func parseCreated(_ value: String) -> Date? {
|
|
let withFractional = ISO8601DateFormatter()
|
|
withFractional.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
|
if let date = withFractional.date(from: value) {
|
|
return date
|
|
}
|
|
let formatter = ISO8601DateFormatter()
|
|
formatter.formatOptions = [.withInternetDateTime]
|
|
return formatter.date(from: value)
|
|
}
|
|
}
|