Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions Sources/ContainerCommands/Image/ImageLoad.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import ContainerAPIClient
import Containerization
import ContainerizationError
import Foundation
import SystemPackage
import TerminalProgress

extension Application {
Expand All @@ -32,9 +33,13 @@ extension Application {
@Option(
name: .shortAndLong, help: "Path to the image tar archive", completion: .file(),
transform: { str in
URL(fileURLWithPath: str, relativeTo: .currentDirectory()).absoluteURL.path(percentEncoded: false)
let path = FilePath(str)
Comment thread
saehejkang marked this conversation as resolved.
guard path.isRelative else { return path.lexicallyNormalized() }
return FilePath(FileManager.default.currentDirectoryPath)
.pushing(path)
.lexicallyNormalized()
})
var input: String?
var input: FilePath?

@Flag(name: .shortAndLong, help: "Load images even if the archive contains invalid files")
public var force = false
Expand All @@ -49,7 +54,14 @@ extension Application {
}

// Read from stdin; otherwise read from the input file
if input == nil {
let resolvedPath: FilePath
if let input {
guard FileManager.default.fileExists(atPath: input.string) else {
log.error("file does not exist", metadata: ["path": "\(input)"])
Application.exit(withError: ArgumentParser.ExitCode(1))
}
resolvedPath = input
} else {
guard FileManager.default.createFile(atPath: tempFile.path(), contents: nil) else {
throw ContainerizationError(.internalError, message: "unable to create temporary file")
}
Expand All @@ -65,11 +77,7 @@ extension Application {
fileHandle.write(chunk)
}
try fileHandle.close()
} else {
guard FileManager.default.fileExists(atPath: input!) else {
print("File does not exist \(input!)")
Application.exit(withError: ArgumentParser.ExitCode(1))
}
resolvedPath = FilePath(tempFile.path())
}

let progressConfig = try ProgressConfig(
Expand All @@ -85,7 +93,7 @@ extension Application {

progress.set(description: "Loading tar archive")
let result = try await ClientImage.load(
from: input ?? tempFile.path(),
from: resolvedPath.string,
force: force)
if !result.rejectedMembers.isEmpty {
log.warning("archive contains invalid members", metadata: ["paths": "\(result.rejectedMembers)"])
Expand Down
9 changes: 9 additions & 0 deletions Tests/CLITests/Subcommands/Images/TestCLIImagesCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -599,4 +599,13 @@ class TestCLIImagesCommand: CLITest {
#expect(status != 0, "Expected non-zero exit for missing image")
#expect(error.contains("image not found"))
}

@Test func testImageLoadMissingFileErrorToStderr() throws {
let missingPath = "/path/that/does/not/exist-\(UUID().uuidString)"
let (_, stdout, stderr, status) = try run(arguments: ["image", "load", "-i", missingPath])

#expect(status != 0, "Expected non-zero exit for missing file")
#expect(stdout.isEmpty, "Expected stdout to be empty, got: \(stdout)")
#expect(stderr.contains("file does not exist") && stderr.contains(missingPath), "Expected stderr to contain error message, got: \(stderr)")
}
}