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
1 change: 1 addition & 0 deletions Plugins/ContainerImageBuilder/runner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import Foundation

/// Error code returned if the process terminates because of an uncaught signal.
public enum ExitCode: Error { case rawValue(Int32) }

/// Runs `command` with the given arguments and environment variables, capturing standard output and standard error.
Expand Down
10 changes: 10 additions & 0 deletions Sources/ContainerRegistry/AuthHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func parseChallenge(_ s: String) throws -> BearerChallenge {
return res
}

/// AuthChallenge represents an HTTP `WWW-Authenticate` challenge header.
public enum AuthChallenge: Equatable {
case none
case basic(String)
Expand Down Expand Up @@ -156,6 +157,15 @@ public struct AuthHandler {
return nil
}

/// Respond to an HTTP `WWW-Authenticate` challenge header sent by a container registry.
/// - Parameters:
/// - registry: The registry which issued the challenge.
/// - repository: The repository path within the registry for which permission is to be requested.
/// - actions: The repository actions for which permission is to be requested.
/// - scheme: The challenge header to which to respond.
/// - client: An HTTPClient instance to use when contacting the registry.
/// - Returns: An `Authorization` header appropriate to the challenge.
/// - Throws: If scheme is `Bearer` and an error occurs when contacting the OAuth server.
public func auth(
registry: URL,
repository: ImageReference.Repository,
Expand Down
4 changes: 3 additions & 1 deletion Sources/ContainerRegistry/HTTPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import FoundationNetworking
import HTTPTypes
import HTTPTypesFoundation

// HEAD does not include a response body so if an error is thrown, data will be nil
/// An error encountered while making an HTTP request
///
/// The response to a `HEAD` request does not include a body so if an error is thrown, `data` will be `nil`
public enum HTTPClientError: Error {
case unexpectedStatusCode(status: HTTPResponse.Status, response: HTTPResponse, data: Data?)
case unexpectedContentType(String)
Expand Down
37 changes: 37 additions & 0 deletions Sources/ContainerRegistry/ImageReference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public struct ImageReference: Sendable, Equatable, CustomStringConvertible, Cust
/// The tag or digest identifying the image.
public var reference: Reference

/// Error thrown when an `ImageReference` string cannot be parsed.
public enum ValidationError: Error {
case unexpected(String)
}
Expand Down Expand Up @@ -114,6 +115,11 @@ public struct ImageReference: Sendable, Equatable, CustomStringConvertible, Cust
self.reference = reference
}

/// Returns a Boolean value indicating whether two `ImageReference` values are equal.
/// - Parameters:
/// - lhs: First `ImageReference` to compare
/// - rhs: Second `ImageReference` to compare
/// - Returns: `True` if the `ImageReferences` are equal, otherwise `false`
public static func == (lhs: ImageReference, rhs: ImageReference) -> Bool {
"\(lhs)" == "\(rhs)"
}
Expand All @@ -138,12 +144,16 @@ extension ImageReference {
public struct Repository: Sendable, Equatable, CustomStringConvertible, CustomDebugStringConvertible {
var value: String

/// Error thrown when a `Repository` string cannot be parsed.
public enum ValidationError: Error, Equatable {
case emptyString
case containsUppercaseLetters(String)
case invalidReferenceFormat(String)
}

/// Creates an `ImageReference.Repository` instance from a string.
/// - Parameter rawValue: A repository string
/// - Throws: If `rawValue` cannot be parsed
public init(_ rawValue: String) throws {
// Reference handling in github.com/distribution reports empty and uppercase as specific errors.
// All other errors caused are reported as generic format errors.
Expand All @@ -164,6 +174,7 @@ extension ImageReference {
value = rawValue
}

/// Printable description of a Reference in a form which can be understood by a runtime
public var description: String {
value
}
Expand All @@ -185,12 +196,16 @@ extension ImageReference {
public struct Tag: Reference, Sendable, Equatable, CustomStringConvertible, CustomDebugStringConvertible {
var value: String

/// Error thrown when a `Tag` cannot be parsed.
public enum ValidationError: Error, Equatable {
case emptyString
case invalidReferenceFormat(String)
case tooLong(String)
}

/// Creates a `Tag` instance from a string.
/// - Parameter rawValue: A tag string
/// - Throws: If `rawValue` cannot be parsed
public init(_ rawValue: String) throws {
guard rawValue.count > 0 else {
throw ValidationError.emptyString
Expand All @@ -209,12 +224,19 @@ extension ImageReference {
value = rawValue
}

/// Returns a Boolean value indicating whether two `Tag` values are equal.
/// - Parameters:
/// - lhs: First `Tag` to compare
/// - rhs: Second `Tag` to compare
/// - Returns: `True` if the `Tag` are equal, otherwise `false`
public static func == (lhs: Tag, rhs: Tag) -> Bool {
lhs.value == rhs.value
}

/// Value which separates the `tag` from the registry and repository parts of a image reference with a human readable tag
public var separator: String = ":"

/// Printable description of a Tag in a form which can be understood by a runtime
public var description: String {
"\(value)"
}
Expand All @@ -227,10 +249,14 @@ extension ImageReference {

/// Digest identifies a specific blob by the hash of the blob's contents.
public struct Digest: Reference, Sendable, Equatable, CustomStringConvertible, CustomDebugStringConvertible {
/// Represents a digest algorithm
public enum Algorithm: String, Sendable {
case sha256 = "sha256"
case sha512 = "sha512"

/// Creates an `Algorithm` instance from a string.
/// - Parameter rawValue: An algorithm string
/// - Throws: If `rawValue` cannot be parsed
init(fromString rawValue: String) throws {
guard let algorithm = Algorithm(rawValue: rawValue) else {
throw RegistryClientError.invalidDigestAlgorithm(rawValue)
Expand All @@ -242,11 +268,15 @@ extension ImageReference {
var algorithm: Algorithm
var value: String

/// Error thrown when a `Digest` cannot be parsed.
public enum ValidationError: Error, Equatable {
case emptyString
case invalidReferenceFormat(String)
}

/// Creates a `Digest` instance from a string.
/// - Parameter rawValue: A digest string
/// - Throws: If `rawValue` cannot be parsed
public init(_ rawValue: String) throws {
guard rawValue.count > 0 else {
throw ValidationError.emptyString
Expand All @@ -271,12 +301,19 @@ extension ImageReference {
throw ValidationError.invalidReferenceFormat(rawValue)
}

/// Returns a Boolean value indicating whether two `Digest` values are equal.
/// - Parameters:
/// - lhs: First `Digest` to compare
/// - rhs: Second `Digest` to compare
/// - Returns: `True` if the `Digest` are equal, otherwise `false`
public static func == (lhs: Digest, rhs: Digest) -> Bool {
lhs.algorithm == rhs.algorithm && lhs.value == rhs.value
}

/// Value which separates the `digest` from the registry and repository parts of an image reference with a digest
public var separator: String = "@"

/// Printable description of a Digest in a form which can be understood by a runtime
public var description: String {
"\(algorithm):\(value)"
}
Expand Down
1 change: 1 addition & 0 deletions Sources/ContainerRegistry/RegistryClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import FoundationNetworking
import HTTPTypes
import Basics

/// An error encountered while communicating with a container registry.
public enum RegistryClientError: Error {
case registryParseError(String)
case invalidRegistryPath(String)
Expand Down
2 changes: 2 additions & 0 deletions Sources/ContainerRegistry/Schema.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ public struct ImageConfigurationRootFS: Codable, Hashable, Sendable {
self.diff_ids = diff_ids
}

/// Field name mapping
public enum CodingKeys: String, CodingKey {
case _type = "type"
case diff_ids
Expand Down Expand Up @@ -400,6 +401,7 @@ public struct Platform: Codable, Hashable, Sendable {
self.features = features
}

/// Field name mapping
public enum CodingKeys: String, CodingKey {
case architecture
case os
Expand Down
4 changes: 4 additions & 0 deletions Sources/ContainerRegistry/ScratchImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public struct ScratchImage {
var manifestDescriptor: ContentDescriptor
var index: ImageIndex

/// Construct a `ScratchImage` structure, representing a scratch container image with no contents.
/// - Parameters:
/// - architecture: The CPU architecture encoded in the scratch image layer. The scratch layer is empty, but this value should match any layers stacked on top of it.
/// - os: The operating system name encoded in the scratch image layer. The scratch layer is empty, but this value should match any layers stacked on top of it.
public init(architecture: String, os: String) {
self.encoder = containerJSONEncoder()

Expand Down
16 changes: 16 additions & 0 deletions Sources/Tar/tar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,22 @@ public struct TarHeader {
/// Filename prefix - prepended to name
var prefix: String = ""

/// Construct a Tar archive header block
/// - Parameters:
/// - name: File name
/// - mode: Access mode
/// - uid: File owner's user ID
/// - gid: File's group ID
/// - size: File size in octets
/// - mtime: Last modification time
/// - typeflag: Type of file represented by this header
/// - linkname: Reference to a previous file in the archive. Only valid when `typeflag` is `.LNKTYPE`. This is an internal link in the archive file, _not_ a symbolic link.
/// - uname: File owner's user name
/// - gname: File's group name
/// - devmajor: Device major number. Only valid when `typeflag` is `.BLKTYPE` or `.CHRTYPE`.
/// - devminor: Device minor number. Only valid when `typeflag` is `.BLKTYPE` or `.CHRTYPE`.
/// - prefix: Optional filename prefix, allowing file names longer than 100 octets to be stored.
/// - Throws: If the value of any field cannot be represented in a Tar header.
public init(
name: String,
mode: Int = 0o555,
Expand Down