mirror of
https://github.com/apple/container.git
synced 2026-07-15 05:57: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
133 lines
5.4 KiB
Swift
133 lines
5.4 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 ContainerBuildIR
|
|
import ContainerBuildSnapshotter
|
|
import Foundation
|
|
|
|
/// Executes FilesystemOperation (COPY and ADD).
|
|
public struct FilesystemOperationExecutor: OperationExecutor {
|
|
public let capabilities: ExecutorCapabilities
|
|
|
|
public init() {
|
|
self.capabilities = ExecutorCapabilities(
|
|
supportedOperations: [.filesystem],
|
|
maxConcurrency: 10
|
|
)
|
|
}
|
|
|
|
public func execute(_ operation: ContainerBuildIR.Operation, context: ExecutionContext) async throws -> ExecutionResult {
|
|
guard let fsOp = operation as? FilesystemOperation else {
|
|
throw ExecutorError(
|
|
type: .invalidConfiguration,
|
|
context: ExecutorError.ErrorContext(
|
|
operation: operation, underlyingError: NSError(domain: "Executor", code: 1),
|
|
diagnostics: ExecutorError.Diagnostics(environment: [:], workingDirectory: "", recentLogs: [])))
|
|
}
|
|
|
|
let startTime = Date()
|
|
|
|
do {
|
|
let (_, finalSnapshot) = try await context.withSnapshot { snapshot in
|
|
try await performFilesystemOperation(fsOp, in: snapshot)
|
|
}
|
|
|
|
let duration = Date().timeIntervalSince(startTime)
|
|
|
|
return ExecutionResult(
|
|
snapshot: finalSnapshot,
|
|
duration: duration,
|
|
output: nil
|
|
)
|
|
|
|
} catch {
|
|
|
|
throw ExecutorError(
|
|
type: .executionFailed,
|
|
context: ExecutorError.ErrorContext(
|
|
operation: operation,
|
|
underlyingError: error,
|
|
diagnostics: ExecutorError.Diagnostics(
|
|
environment: context.environment.effectiveEnvironment,
|
|
workingDirectory: context.workingDirectory,
|
|
recentLogs: ["Failed to execute filesystem operation: \(fsOp.action)"]
|
|
)
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Perform the filesystem operation.
|
|
///
|
|
/// This simulates filesystem operations for development and testing purposes.
|
|
/// The snapshotter is fully functional and creates real filesystem snapshots,
|
|
/// but the actual file operations are simulated to avoid system dependencies.
|
|
///
|
|
/// - Parameters:
|
|
/// - operation: The filesystem operation to perform
|
|
/// - snapshot: The prepared snapshot with working directory
|
|
private func performFilesystemOperation(
|
|
_ operation: FilesystemOperation,
|
|
in snapshot: Snapshot
|
|
) async throws {
|
|
// NOTE: The snapshotter is fully operational and creates real filesystem snapshots.
|
|
// We simulate filesystem operations to:
|
|
// 1. Avoid requiring actual file system access during development
|
|
// 2. Enable predictable testing without side effects
|
|
// 3. Allow the build system to run in restricted environments
|
|
//
|
|
// In a production implementation, this would:
|
|
// 1. Get the working directory from the snapshot (already available)
|
|
// 2. Resolve the source (context, stage, URL)
|
|
// 3. Perform actual file operations (copy or add)
|
|
// 4. Apply file metadata (permissions, ownership)
|
|
// 5. Let the snapshotter track filesystem changes (already working)
|
|
|
|
// Only COPY and ADD operations are supported for filesystem operations
|
|
switch operation.action {
|
|
case .copy:
|
|
// Simulate COPY operation
|
|
// In production: Copy files from source to destination in the snapshot
|
|
break
|
|
case .add:
|
|
// Simulate ADD operation
|
|
// In production: Add files to the snapshot, with automatic extraction for archives
|
|
break
|
|
default:
|
|
throw ExecutorError(
|
|
type: .unsupportedOperation,
|
|
context: ExecutorError.ErrorContext(
|
|
operation: operation,
|
|
underlyingError: NSError(
|
|
domain: "FilesystemOperationExecutor",
|
|
code: 1,
|
|
userInfo: [NSLocalizedDescriptionKey: "Only COPY and ADD operations are supported. Got: \(operation.action)"]
|
|
),
|
|
diagnostics: ExecutorError.Diagnostics(
|
|
environment: [:],
|
|
workingDirectory: "",
|
|
recentLogs: ["Unsupported filesystem operation: \(operation.action)"]
|
|
)
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
public func canExecute(_ operation: ContainerBuildIR.Operation) -> Bool {
|
|
operation is FilesystemOperation
|
|
}
|
|
}
|