mirror of
https://github.com/apple/container.git
synced 2026-07-12 12:37:02 +00:00
Update container copy to use FilePath (#1580)
- Replace `URL` with `FilePath` in `container copy` (#1557). In addition, make `copyIn`/`copyOut` API to use `String` for path as we need to preserve the trailing slash to the `LinuxContainer.copy`---i.e., this trailing slash is used in `LinuxContainer.copy` to determine copy behavior.
This commit is contained in:
@@ -113,6 +113,7 @@ let package = Package(
|
||||
"ContainerRuntimeClient",
|
||||
"ContainerRuntimeLinuxClient",
|
||||
"ContainerVersion",
|
||||
.product(name: "SystemPackage", package: "swift-system"),
|
||||
"ContainerXPC",
|
||||
"TerminalProgress",
|
||||
"Yams",
|
||||
|
||||
@@ -20,6 +20,7 @@ import ContainerResource
|
||||
import Containerization
|
||||
import ContainerizationError
|
||||
import Foundation
|
||||
import SystemPackage
|
||||
|
||||
extension Application {
|
||||
public struct ContainerCopy: AsyncLoggableCommand {
|
||||
@@ -63,40 +64,42 @@ extension Application {
|
||||
|
||||
switch (srcRef, dstRef) {
|
||||
case (.container(let id, let path), .local(let localPath)):
|
||||
let srcURL = URL(fileURLWithPath: path)
|
||||
let destURL = URL(fileURLWithPath: localPath).standardizedFileURL
|
||||
let srcPath = FilePath(path)
|
||||
let destPath = FilePath((localPath as NSString).standardizingPath)
|
||||
var isDirectory: ObjCBool = false
|
||||
let exists = FileManager.default.fileExists(atPath: destURL.path, isDirectory: &isDirectory)
|
||||
let exists = FileManager.default.fileExists(atPath: destPath.string, isDirectory: &isDirectory)
|
||||
|
||||
if exists && isDirectory.boolValue {
|
||||
let finalDest = destURL.appendingPathComponent(srcURL.lastPathComponent)
|
||||
try await client.copyOut(id: id, source: srcURL, destination: finalDest)
|
||||
guard let lastComponent = srcPath.lastComponent else {
|
||||
throw ContainerizationError(.invalidArgument, message: "source path has no last component: \(path)")
|
||||
}
|
||||
let finalDest = destPath.appending(lastComponent)
|
||||
try await client.copyOut(id: id, source: path, destination: finalDest.string)
|
||||
} else if localPath.hasSuffix("/") {
|
||||
try await client.copyOut(id: id, source: srcURL, destination: destURL)
|
||||
try await client.copyOut(id: id, source: path, destination: destPath.string)
|
||||
var resultIsDir: ObjCBool = false
|
||||
if FileManager.default.fileExists(atPath: destURL.path, isDirectory: &resultIsDir),
|
||||
if FileManager.default.fileExists(atPath: destPath.string, isDirectory: &resultIsDir),
|
||||
!resultIsDir.boolValue
|
||||
{
|
||||
try? FileManager.default.removeItem(at: destURL)
|
||||
try? FileManager.default.removeItem(atPath: destPath.string)
|
||||
throw ContainerizationError(
|
||||
.invalidArgument,
|
||||
message: "destination is not a directory: \(localPath)")
|
||||
}
|
||||
} else {
|
||||
try await client.copyOut(id: id, source: srcURL, destination: destURL)
|
||||
try await client.copyOut(id: id, source: path, destination: destPath.string)
|
||||
}
|
||||
case (.local(let localPath), .container(let id, let path)):
|
||||
let srcURL = URL(fileURLWithPath: localPath).standardizedFileURL
|
||||
let srcPath = FilePath((localPath as NSString).standardizingPath)
|
||||
var isDirectory: ObjCBool = false
|
||||
guard FileManager.default.fileExists(atPath: srcURL.path, isDirectory: &isDirectory) else {
|
||||
guard FileManager.default.fileExists(atPath: srcPath.string, isDirectory: &isDirectory) else {
|
||||
throw ContainerizationError(.notFound, message: "source path does not exist: \(localPath)")
|
||||
}
|
||||
if localPath.hasSuffix("/") && !isDirectory.boolValue {
|
||||
throw ContainerizationError(.invalidArgument, message: "source path is not a directory: \(localPath)")
|
||||
}
|
||||
|
||||
let destURL = URL(fileURLWithPath: path)
|
||||
try await client.copyIn(id: id, source: srcURL, destination: destURL, createParents: true)
|
||||
try await client.copyIn(id: id, source: srcPath.string, destination: path, createParents: true)
|
||||
case (.container, .container):
|
||||
throw ContainerizationError(.invalidArgument, message: "copying between containers is not supported")
|
||||
case (.local, .local):
|
||||
|
||||
@@ -312,15 +312,11 @@ public struct ContainerClient: Sendable {
|
||||
}
|
||||
|
||||
/// Copy a file or directory from the host into the container.
|
||||
public func copyIn(id: String, source: URL, destination: URL, mode: UInt32 = 0o644, createParents: Bool = true) async throws {
|
||||
public func copyIn(id: String, source: String, destination: String, mode: UInt32 = 0o644, createParents: Bool = true) async throws {
|
||||
let request = XPCMessage(route: .containerCopyIn)
|
||||
let destinationPath =
|
||||
destination.hasDirectoryPath && !destination.path.hasSuffix("/")
|
||||
? "\(destination.path)/"
|
||||
: destination.path
|
||||
request.set(key: .id, value: id)
|
||||
request.set(key: .sourcePath, value: source.path)
|
||||
request.set(key: .destinationPath, value: destinationPath)
|
||||
request.set(key: .sourcePath, value: source)
|
||||
request.set(key: .destinationPath, value: destination)
|
||||
request.set(key: .fileMode, value: UInt64(mode))
|
||||
request.set(key: .createParents, value: createParents)
|
||||
|
||||
@@ -336,11 +332,11 @@ public struct ContainerClient: Sendable {
|
||||
}
|
||||
|
||||
/// Copy a file or directory from the container to the host.
|
||||
public func copyOut(id: String, source: URL, destination: URL, createParents: Bool = true) async throws {
|
||||
public func copyOut(id: String, source: String, destination: String, createParents: Bool = true) async throws {
|
||||
let request = XPCMessage(route: .containerCopyOut)
|
||||
request.set(key: .id, value: id)
|
||||
request.set(key: .sourcePath, value: source.path)
|
||||
request.set(key: .destinationPath, value: destination.path)
|
||||
request.set(key: .sourcePath, value: source)
|
||||
request.set(key: .destinationPath, value: destination)
|
||||
request.set(key: .createParents, value: createParents)
|
||||
|
||||
do {
|
||||
|
||||
Reference in New Issue
Block a user