diff --git a/Plugins/ContainerImageBuilder/runner.swift b/Plugins/ContainerImageBuilder/runner.swift index c1e328c..d4cc152 100644 --- a/Plugins/ContainerImageBuilder/runner.swift +++ b/Plugins/ContainerImageBuilder/runner.swift @@ -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. diff --git a/Sources/ContainerRegistry/AuthHandler.swift b/Sources/ContainerRegistry/AuthHandler.swift index 245a725..e5730fe 100644 --- a/Sources/ContainerRegistry/AuthHandler.swift +++ b/Sources/ContainerRegistry/AuthHandler.swift @@ -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) @@ -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, diff --git a/Sources/ContainerRegistry/HTTPClient.swift b/Sources/ContainerRegistry/HTTPClient.swift index d34f8d5..c9bee70 100644 --- a/Sources/ContainerRegistry/HTTPClient.swift +++ b/Sources/ContainerRegistry/HTTPClient.swift @@ -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) diff --git a/Sources/ContainerRegistry/ImageReference.swift b/Sources/ContainerRegistry/ImageReference.swift index 63e02d9..0f88c64 100644 --- a/Sources/ContainerRegistry/ImageReference.swift +++ b/Sources/ContainerRegistry/ImageReference.swift @@ -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) } @@ -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)" } @@ -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. @@ -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 } @@ -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 @@ -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)" } @@ -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) @@ -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 @@ -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)" } diff --git a/Sources/ContainerRegistry/RegistryClient.swift b/Sources/ContainerRegistry/RegistryClient.swift index d117d49..74d56c9 100644 --- a/Sources/ContainerRegistry/RegistryClient.swift +++ b/Sources/ContainerRegistry/RegistryClient.swift @@ -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) diff --git a/Sources/ContainerRegistry/Schema.swift b/Sources/ContainerRegistry/Schema.swift index cbeeab7..caca06d 100644 --- a/Sources/ContainerRegistry/Schema.swift +++ b/Sources/ContainerRegistry/Schema.swift @@ -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 @@ -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 diff --git a/Sources/ContainerRegistry/ScratchImage.swift b/Sources/ContainerRegistry/ScratchImage.swift index a67c05e..0431819 100644 --- a/Sources/ContainerRegistry/ScratchImage.swift +++ b/Sources/ContainerRegistry/ScratchImage.swift @@ -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() diff --git a/Sources/Tar/tar.swift b/Sources/Tar/tar.swift index 4dcf459..62a17b1 100644 --- a/Sources/Tar/tar.swift +++ b/Sources/Tar/tar.swift @@ -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,