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
5 changes: 2 additions & 3 deletions Sources/ContainerCommands/BuildCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ extension Application {

@Option(
name: .shortAndLong,
help:
"Amount of builder container memory (1MiByte granularity), with optional K, M, G, T, or P suffix"
help: "Amount of builder container memory (1MiByte granularity), with optional K, M, G, T, or P suffix"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove the P suffix for simplicity?

)
var memory: String = "2048MB"

Expand All @@ -95,7 +94,7 @@ extension Application {

@Option(
name: .long,
help: "Add the platform to the build (takes precedence over --os and --arch)",
help: "Add the platform to the build (format: os/arch[/variant], takes precedence over --os and --arch)",
transform: { val in val.split(separator: ",").map { String($0) } }
)
var platform: [[String]] = [[]]
Expand Down
2 changes: 1 addition & 1 deletion Sources/ContainerCommands/Image/ImageCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ extension Application {
commandName: "image",
abstract: "Manage images",
subcommands: [
ImageDelete.self,
ImageInspect.self,
ImageList.self,
ImageLoad.self,
ImagePrune.self,
ImagePull.self,
ImagePush.self,
ImageRemove.self,
ImageSave.self,
ImageTag.self,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ extension Application {
@Flag(name: .shortAndLong, help: "Remove all images")
var all: Bool = false

@Argument
var images: [String] = []

@OptionGroup
var global: Flags.Global

@Argument
var images: [String] = []
}

public struct RemoveImageImplementation {
struct DeleteImageImplementation {
static func validate(options: RemoveImageOptions) throws {
if options.images.count == 0 && !options.all {
throw ContainerizationError(.invalidArgument, message: "no image specified and --all not supplied")
Expand Down Expand Up @@ -81,9 +81,7 @@ extension Application {
}
}

public struct ImageRemove: AsyncParsableCommand {
public init() {}

public struct ImageDelete: AsyncParsableCommand {
@OptionGroup
var options: RemoveImageOptions

Expand All @@ -92,12 +90,14 @@ extension Application {
abstract: "Remove one or more images",
aliases: ["rm"])

public init() {}

public func validate() throws {
try RemoveImageImplementation.validate(options: options)
try DeleteImageImplementation.validate(options: options)
}

public mutating func run() async throws {
try await RemoveImageImplementation.removeImage(options: options)
try await DeleteImageImplementation.removeImage(options: options)
}
}
}
3 changes: 2 additions & 1 deletion Sources/ContainerCommands/Image/ImageInspect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import SwiftProtobuf

extension Application {
public struct ImageInspect: AsyncParsableCommand {
public init() {}
public static let configuration = CommandConfiguration(
commandName: "inspect",
abstract: "Display information about one or more images")
Expand All @@ -33,6 +32,8 @@ extension Application {
@Argument(help: "Images to inspect")
var images: [String]

public init() {}

public func run() async throws {
var printable = [any Codable]()
let result = try await ClientImage.get(names: images)
Expand Down
9 changes: 5 additions & 4 deletions Sources/ContainerCommands/Image/ImageList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ import SwiftProtobuf

extension Application {
public struct ListImageOptions: ParsableArguments {
public init() {}
@Option(name: .long, help: "Format of the output")
var format: ListFormat = .table

@Flag(name: .shortAndLong, help: "Only output the image name")
var quiet = false

@Flag(name: .shortAndLong, help: "Verbose output")
var verbose = false

@Option(name: .long, help: "Format of the output")
var format: ListFormat = .table

@OptionGroup
var global: Flags.Global

public init() {}
}

struct ListImageImplementation {
Expand Down
8 changes: 4 additions & 4 deletions Sources/ContainerCommands/Image/ImageLoad.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ extension Application {
abstract: "Load images from an OCI compatible tar archive"
)

@OptionGroup
var global: Flags.Global

@Option(
name: .shortAndLong, help: "Path to the tar archive to load images from", completion: .file(),
name: .shortAndLong, help: "Path to the image tar archive", completion: .file(),
transform: { str in
URL(fileURLWithPath: str, relativeTo: .currentDirectory()).absoluteURL.path(percentEncoded: false)
})
var input: String

@OptionGroup
var global: Flags.Global

public func run() async throws {
guard FileManager.default.fileExists(atPath: input) else {
print("File does not exist \(input)")
Expand Down
12 changes: 6 additions & 6 deletions Sources/ContainerCommands/Image/ImagePull.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,20 @@ extension Application {
var progressFlags: Flags.Progress

@Option(
help: "Platform string in the form 'os/arch/variant'. Example 'linux/arm64/v8', 'linux/amd64'. This takes precedence over --os and --arch"
name: .shortAndLong,
help: "Limit the pull to the specified architecture"
)
var platform: String?
var arch: String?

@Option(
help: "Set OS if image can target multiple operating systems"
help: "Limit the pull to the specified OS"
)
var os: String?

@Option(
name: [.customLong("arch"), .customShort("a")],
help: "Set arch if image can target multiple architectures"
help: "Limit the pull to the specified platform (format: os/arch[/variant], takes precedence over --os and --arch)"
)
var arch: String?
var platform: String?

@Argument var reference: String

Expand Down
27 changes: 22 additions & 5 deletions Sources/ContainerCommands/Image/ImagePush.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,46 @@ import TerminalProgress

extension Application {
public struct ImagePush: AsyncParsableCommand {
public init() {}
public static let configuration = CommandConfiguration(
commandName: "push",
abstract: "Push an image"
)

@OptionGroup
var global: Flags.Global

@OptionGroup
var registry: Flags.Registry

@OptionGroup
var progressFlags: Flags.Progress

@Option(help: "Platform string in the form 'os/arch/variant'. Example 'linux/arm64/v8', 'linux/amd64'") var platform: String?
@Option(
name: [.customLong("arch"), .customShort("a")],
help: "Limit the push to the specified architecture"
)
var arch: String?

@Option(
help: "Limit the push to the specified OS"
)
var os: String?

@Option(help: "Limit the push to the specified platform (format: os/arch[/variant], takes precedence over --os and --arch)")
var platform: String?

@OptionGroup
var global: Flags.Global

@Argument var reference: String

public init() {}

public func run() async throws {
var p: Platform?
if let platform {
p = try Platform(from: platform)
} else if let arch {
p = try Platform(from: "\(os ?? "linux")/\(arch)")
} else if let os {
p = try Platform(from: "\(os)/\(arch ?? Arch.hostArchitecture().rawValue)")
}

let scheme = try RequestScheme(registry.scheme)
Expand Down
26 changes: 13 additions & 13 deletions Sources/ContainerCommands/Image/ImageSave.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,32 @@ extension Application {
abstract: "Save an image as an OCI compatible tar archive"
)

@OptionGroup
var global: Flags.Global

@Option(
help: "Platform string in the form 'os/arch/variant'. Example 'linux/arm64/v8', 'linux/amd64'. This takes precedence over --os and --arch"
name: [.customLong("arch"), .customShort("a")],
help: "Architecture for the saved image"
)
var platform: String?
var arch: String?

@Option(
help: "Set OS if image can target multiple operating systems"
help: "OS for the saved image"
)
var os: String?

@Option(
name: [.customLong("arch"), .customShort("a")],
help: "Set arch if image can target multiple architectures"
)
var arch: String?

@Option(
name: .shortAndLong, help: "Path to save the image tar archive", completion: .file(),
name: .shortAndLong, help: "Pathname for the saved image", completion: .file(),
transform: { str in
URL(fileURLWithPath: str, relativeTo: .currentDirectory()).absoluteURL.path(percentEncoded: false)
})
var output: String

@Option(
help: "Platform for the saved image (format: os/arch[/variant], takes precedence over --os and --arch)"
)
var platform: String?

@OptionGroup
var global: Flags.Global

@Argument var references: [String]

public func run() async throws {
Expand Down
8 changes: 4 additions & 4 deletions Sources/ContainerCommands/Image/ImageTag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ extension Application {
public init() {}
public static let configuration = CommandConfiguration(
commandName: "tag",
abstract: "Tag an image")
abstract: "Create a new reference for an existing image")

@Argument(help: "SOURCE_IMAGE[:TAG]")
@Argument(help: "the existing image reference (format: image-name[:tag])")
Copy link
Contributor

@dkovba dkovba Sep 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capitalize the help string.

var source: String

@Argument(help: "TARGET_IMAGE[:TAG]")
@Argument(help: "the new image reference")
Copy link
Contributor

@dkovba dkovba Sep 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capitalize the help string.

var target: String

@OptionGroup
Expand All @@ -37,7 +37,7 @@ extension Application {
let existing = try await ClientImage.get(reference: source)
let targetReference = try ClientImage.normalizeReference(target)
try await existing.tag(new: targetReference)
print("Image \(source) tagged as \(target)")
print(target)
}
}
}