mirror of
https://github.com/apple/container.git
synced 2026-07-14 21:47:01 +00:00
d2f48982c1
This PR defines the snapshotter protocol
```swift
///Mount a snapshot and all its previous layers
func prepare(_ snapshot: Snapshot) async throws -> Snapshot
/// Commit a snapshot, making it permanent.
func commit(_ snapshot: Snapshot) async throws -> Snapshot
/// Remove a snapshot from snapshot store
func remove(_ snapshot: Snapshot) async throws
```
It updates executors to work with this new protocol
114 lines
4.0 KiB
Swift
114 lines
4.0 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
// Copyright © 2025 Apple Inc. and the container project authors. All rights reserved.
|
|
//
|
|
// 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 ContainerBuildCache
|
|
import ContainerBuildExecutor
|
|
import ContainerBuildIR
|
|
import ContainerBuildReporting
|
|
import ContainerBuildSnapshotter
|
|
import Foundation
|
|
|
|
public actor DummySnapshotter: Snapshotter {
|
|
public init() {}
|
|
|
|
public func prepare(_ snapshot: Snapshot) async throws -> Snapshot {
|
|
if let mount = snapshot.state.mountpoint {
|
|
var isDir: ObjCBool = false
|
|
if !FileManager.default.fileExists(atPath: mount.path, isDirectory: &isDir) {
|
|
try FileManager.default.createDirectory(at: mount, withIntermediateDirectories: true)
|
|
}
|
|
}
|
|
return snapshot
|
|
}
|
|
|
|
public func commit(_ snapshot: Snapshot) async throws -> Snapshot {
|
|
// Produce a minimal committed snapshot; layer fields are optional
|
|
Snapshot(
|
|
id: snapshot.id,
|
|
digest: snapshot.digest,
|
|
size: snapshot.size,
|
|
parent: snapshot.parent,
|
|
createdAt: snapshot.createdAt,
|
|
state: .committed()
|
|
)
|
|
}
|
|
|
|
public func remove(_ snapshot: Snapshot) async throws {
|
|
if let mount = snapshot.state.mountpoint {
|
|
try? FileManager.default.removeItem(at: mount)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A simple demonstration of the build execution system.
|
|
public struct Demo {
|
|
public static func runDemo() async throws {
|
|
// Set up the build environment first
|
|
let snapshotter = DummySnapshotter()
|
|
let cache = NoOpBuildCache()
|
|
let reporter = Reporter()
|
|
|
|
// Create a build graph with parallel operations, passing the reporter
|
|
let graph = try IRExample.createParallelBuild(reporter: reporter)
|
|
let config = Scheduler.Configuration(
|
|
maxConcurrency: ProcessInfo.processInfo.activeProcessorCount,
|
|
failFast: true,
|
|
enableProgressReporting: true
|
|
)
|
|
let executor = Scheduler(
|
|
snapshotter: snapshotter,
|
|
cache: cache,
|
|
reporter: reporter,
|
|
configuration: config
|
|
)
|
|
|
|
// Create progress consumer
|
|
let consumer = PlainProgressConsumer(
|
|
configuration: .init()
|
|
)
|
|
|
|
// Start progress monitoring task
|
|
let progressTask = Task {
|
|
try await consumer.consume(reporter: reporter)
|
|
}
|
|
|
|
// Register completion handler to wait for progress task
|
|
executor.onCompletion {
|
|
try? await progressTask.value
|
|
}
|
|
|
|
// Execute the build - this will wait for progress to complete before returning
|
|
_ = try await executor.execute(graph)
|
|
|
|
// Get build statistics
|
|
let stats = consumer.getStatistics()
|
|
|
|
// Print build summary based on statistics
|
|
if let duration = stats.duration {
|
|
if stats.success == true {
|
|
print("\nBuild completed successfully in \(String(format: "%.2f", duration))s")
|
|
// print(" Total operations: \(stats.totalOperations)")
|
|
// print(" Cache hits: \(stats.cacheHits)")
|
|
// print(" Executed: \(stats.executedOperations)")
|
|
} else {
|
|
print("\nBuild failed after \(String(format: "%.2f", duration))s")
|
|
// print(" Failed operations: \(stats.failedOperations)")
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|