mirror of
https://github.com/apple/container.git
synced 2026-09-12 10:45:42 +00:00
Lowercase error messages (#440)
For consistency, all error messages are lowercased.
This commit is contained in:
@@ -59,7 +59,7 @@ public struct Image: Sendable {
|
||||
/// Returns the underlying OCI index for the image.
|
||||
public func index() async throws -> Index {
|
||||
guard let content: Content = try await contentStore.get(digest: digest) else {
|
||||
throw ContainerizationError(.notFound, message: "Content with digest \(digest)")
|
||||
throw ContainerizationError(.notFound, message: "content with digest \(digest)")
|
||||
}
|
||||
return try content.decode()
|
||||
}
|
||||
@@ -71,10 +71,10 @@ public struct Image: Sendable {
|
||||
desc.platform == platform
|
||||
}
|
||||
guard let desc else {
|
||||
throw ContainerizationError(.unsupported, message: "Platform \(platform.description)")
|
||||
throw ContainerizationError(.unsupported, message: "platform \(platform.description)")
|
||||
}
|
||||
guard let content: Content = try await contentStore.get(digest: desc.digest) else {
|
||||
throw ContainerizationError(.notFound, message: "Content with digest \(digest)")
|
||||
throw ContainerizationError(.notFound, message: "content with digest \(digest)")
|
||||
}
|
||||
return try content.decode()
|
||||
}
|
||||
@@ -95,7 +95,7 @@ public struct Image: Sendable {
|
||||
let manifest = try await self.manifest(for: platform)
|
||||
let desc = manifest.config
|
||||
guard let content: Content = try await contentStore.get(digest: desc.digest) else {
|
||||
throw ContainerizationError(.notFound, message: "Content with digest \(digest)")
|
||||
throw ContainerizationError(.notFound, message: "content with digest \(digest)")
|
||||
}
|
||||
return try content.decode()
|
||||
}
|
||||
@@ -120,10 +120,10 @@ public struct Image: Sendable {
|
||||
/// Returns a reference to the content blob for the image. The specified digest must be referenced by the image in one of its layers.
|
||||
public func getContent(digest: String) async throws -> Content {
|
||||
guard try await self.referencedDigests().contains(digest.trimmingDigestPrefix) else {
|
||||
throw ContainerizationError(.internalError, message: "Image \(self.reference) does not reference digest \(digest)")
|
||||
throw ContainerizationError(.internalError, message: "image \(self.reference) does not reference digest \(digest)")
|
||||
}
|
||||
guard let content: Content = try await contentStore.get(digest: digest) else {
|
||||
throw ContainerizationError(.notFound, message: "Content with digest \(digest)")
|
||||
throw ContainerizationError(.notFound, message: "content with digest \(digest)")
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ extension ImageStore {
|
||||
for chunk in layerGroup.chunks(ofCount: 8) {
|
||||
for desc in chunk {
|
||||
guard let content = try await self.contentStore.get(digest: desc.digest) else {
|
||||
throw ContainerizationError(.notFound, message: "Content with digest \(desc.digest)")
|
||||
throw ContainerizationError(.notFound, message: "content with digest \(desc.digest)")
|
||||
}
|
||||
group.addTask {
|
||||
let readStream = try ReadStream(url: content.path)
|
||||
@@ -104,7 +104,7 @@ extension ImageStore {
|
||||
|
||||
private func createIndex(from index: Descriptor, matching: (Platform) -> Bool) async throws -> Data {
|
||||
guard let content = try await self.contentStore.get(digest: index.digest) else {
|
||||
throw ContainerizationError(.notFound, message: "Content with digest \(index.digest)")
|
||||
throw ContainerizationError(.notFound, message: "content with digest \(index.digest)")
|
||||
}
|
||||
var idx: Index = try content.decode()
|
||||
let manifests = idx.manifests
|
||||
@@ -156,7 +156,7 @@ extension ImageStore {
|
||||
for desc in descs {
|
||||
let mediaType = desc.mediaType
|
||||
guard let content = try await self.contentStore.get(digest: desc.digest) else {
|
||||
throw ContainerizationError(.notFound, message: "Content with digest \(desc.digest)")
|
||||
throw ContainerizationError(.notFound, message: "content with digest \(desc.digest)")
|
||||
}
|
||||
switch mediaType {
|
||||
case MediaTypes.index, MediaTypes.dockerManifestList:
|
||||
|
||||
@@ -75,7 +75,7 @@ extension ImageStore {
|
||||
// the Index.
|
||||
let supportedPlatforms = index.manifests.compactMap { $0.platform }
|
||||
guard supportedPlatforms.allSatisfy(matcher) else {
|
||||
throw ContainerizationError(.unsupported, message: "Image \(root.digest) does not support required platforms")
|
||||
throw ContainerizationError(.unsupported, message: "image \(root.digest) does not support required platforms")
|
||||
}
|
||||
let writer = try ContentWriter(for: self.ingestDir)
|
||||
let result = try writer.create(from: index)
|
||||
@@ -95,7 +95,7 @@ extension ImageStore {
|
||||
}
|
||||
return try await self.client.fetch(name: name, descriptor: descriptor)
|
||||
} catch {
|
||||
throw ContainerizationError(.internalError, message: "Cannot fetch content with digest \(descriptor.digest)", cause: error)
|
||||
throw ContainerizationError(.internalError, message: "cannot fetch content with digest \(descriptor.digest)", cause: error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ extension ImageStore {
|
||||
let tempFile = ingestDir.appendingPathComponent(id)
|
||||
let (_, digest) = try await client.fetchBlob(name: name, descriptor: descriptor, into: tempFile, progress: progress)
|
||||
guard digest.digestString == descriptor.digest else {
|
||||
throw ContainerizationError(.internalError, message: "Digest mismatch expected \(descriptor.digest), got \(digest.digestString)")
|
||||
throw ContainerizationError(.internalError, message: "digest mismatch expected \(descriptor.digest), got \(digest.digestString)")
|
||||
}
|
||||
do {
|
||||
try fm.moveItem(at: tempFile, to: ingestDir.appendingPathComponent(digest.encoded))
|
||||
@@ -194,7 +194,7 @@ extension ImageStore {
|
||||
])
|
||||
}
|
||||
guard result.digest.digestString == descriptor.digest else {
|
||||
throw ContainerizationError(.internalError, message: "Digest mismatch expected \(descriptor.digest), got \(result.digest.digestString)")
|
||||
throw ContainerizationError(.internalError, message: "digest mismatch expected \(descriptor.digest), got \(result.digest.digestString)")
|
||||
}
|
||||
return data
|
||||
}
|
||||
@@ -209,7 +209,7 @@ extension ImageStore {
|
||||
throw ContainerizationError(
|
||||
.internalError,
|
||||
message:
|
||||
"Descriptor \(root.mediaType) with digest \(root.digest) does not list any supported platform or supports more than one platform. Supported platforms = \(supportedPlatforms)"
|
||||
"descriptor \(root.mediaType) with digest \(root.digest) does not list any supported platform or supports more than one platform. Supported platforms = \(supportedPlatforms)"
|
||||
)
|
||||
}
|
||||
let platform = supportedPlatforms.first!
|
||||
@@ -223,7 +223,7 @@ extension ImageStore {
|
||||
])
|
||||
return index
|
||||
default:
|
||||
throw ContainerizationError(.internalError, message: "Failed to create index for descriptor \(root.digest), media type \(root.mediaType)")
|
||||
throw ContainerizationError(.internalError, message: "failed to create index for descriptor \(root.digest), media type \(root.mediaType)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ extension ImageStore {
|
||||
let image = try await self.get(reference: reference)
|
||||
let allowedMediaTypes = [MediaTypes.dockerManifestList, MediaTypes.index]
|
||||
guard allowedMediaTypes.contains(image.mediaType) else {
|
||||
throw ContainerizationError(.internalError, message: "Cannot save image \(image.reference) with Index media type \(image.mediaType)")
|
||||
throw ContainerizationError(.internalError, message: "cannot save image \(image.reference) with Index media type \(image.mediaType)")
|
||||
}
|
||||
toSave.append(image)
|
||||
}
|
||||
@@ -54,7 +54,7 @@ extension ImageStore {
|
||||
let ref = try Reference.parse(image.reference)
|
||||
let name = ref.path
|
||||
guard let tag = ref.tag ?? ref.digest else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid tag/digest for image reference \(image.reference)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid tag/digest for image reference \(image.reference)")
|
||||
}
|
||||
let operation = ExportOperation(name: name, tag: tag, contentStore: self.contentStore, client: client, progress: nil)
|
||||
var descriptor = try await operation.export(index: image.descriptor, platforms: matcher)
|
||||
@@ -99,7 +99,7 @@ extension ImageStore {
|
||||
return images
|
||||
}
|
||||
guard importedImages.count > 0 else {
|
||||
throw ContainerizationError(.internalError, message: "Failed to import image")
|
||||
throw ContainerizationError(.internalError, message: "failed to import image")
|
||||
}
|
||||
return importedImages
|
||||
} catch {
|
||||
|
||||
@@ -43,7 +43,7 @@ extension ImageStore {
|
||||
let data = try Data(contentsOf: statePath)
|
||||
return try JSONDecoder().decode(State.self, from: data)
|
||||
} catch {
|
||||
throw ContainerizationError(.internalError, message: "Failed to load image state \(error.localizedDescription)")
|
||||
throw ContainerizationError(.internalError, message: "failed to load image state \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ extension ImageStore {
|
||||
do {
|
||||
_ = try Reference.parse(new)
|
||||
} catch {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid reference \(new). Error: \(error)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid reference \(new). Error: \(error)")
|
||||
}
|
||||
let newDescription = Image.Description(reference: new, descriptor: descriptor)
|
||||
return try await self.create(description: newDescription)
|
||||
@@ -242,7 +242,7 @@ extension ImageStore {
|
||||
let ref = try Reference.parse(reference)
|
||||
let name = ref.path
|
||||
guard let tag = ref.tag ?? ref.digest else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid tag/digest for image reference \(reference)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid tag/digest for image reference \(reference)")
|
||||
}
|
||||
|
||||
let rootDescriptor = try await client.resolve(name: name, tag: tag)
|
||||
@@ -282,12 +282,12 @@ extension ImageStore {
|
||||
let img = try await self.get(reference: reference)
|
||||
let allowedMediaTypes = [MediaTypes.dockerManifestList, MediaTypes.index]
|
||||
guard allowedMediaTypes.contains(img.mediaType) else {
|
||||
throw ContainerizationError(.internalError, message: "Cannot push image \(reference) with Index media type \(img.mediaType)")
|
||||
throw ContainerizationError(.internalError, message: "cannot push image \(reference) with Index media type \(img.mediaType)")
|
||||
}
|
||||
let ref = try Reference.parse(reference)
|
||||
let name = ref.path
|
||||
guard let tag = ref.tag ?? ref.digest else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid tag/digest for image reference \(reference)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid tag/digest for image reference \(reference)")
|
||||
}
|
||||
let client = try RegistryClient(reference: reference, insecure: insecure, auth: auth)
|
||||
let operation = ExportOperation(name: name, tag: tag, contentStore: self.contentStore, client: client, progress: progress)
|
||||
|
||||
@@ -72,7 +72,7 @@ public struct EXT4Unpacker: Unpacker {
|
||||
progress: ProgressHandler? = nil
|
||||
) async throws -> Mount {
|
||||
#if !os(macOS)
|
||||
throw ContainerizationError(.unsupported, message: "Cannot unpack an image on current platform")
|
||||
throw ContainerizationError(.unsupported, message: "cannot unpack an image on current platform")
|
||||
#else
|
||||
let cleanedPath = try prepareUnpackPath(path: path)
|
||||
let manifest = try await image.manifest(for: platform)
|
||||
@@ -95,7 +95,7 @@ public struct EXT4Unpacker: Unpacker {
|
||||
case MediaTypes.imageLayerGzip, MediaTypes.dockerImageLayerGzip:
|
||||
compression = .gzip
|
||||
default:
|
||||
throw ContainerizationError(.unsupported, message: "Media type \(layer.mediaType) not supported.")
|
||||
throw ContainerizationError(.unsupported, message: "media type \(layer.mediaType) not supported.")
|
||||
}
|
||||
try filesystem.unpack(
|
||||
source: content.path,
|
||||
|
||||
@@ -391,7 +391,7 @@ extension LinuxProcess {
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
self.logger?.error("Timeout waiting for IO to complete for process \(id): \(error)")
|
||||
self.logger?.error("timeout waiting for IO to complete for process \(id): \(error)")
|
||||
}
|
||||
self.state.withLock {
|
||||
$0.ioTracker = nil
|
||||
|
||||
@@ -41,39 +41,39 @@ public enum ArchiveError: Error, CustomStringConvertible {
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .unableToCreateArchive:
|
||||
return "Unable to create an archive."
|
||||
return "unable to create an archive."
|
||||
case .noUnderlyingArchive:
|
||||
return "No underlying archive was provided."
|
||||
return "no underlying archive was provided."
|
||||
case .noArchiveInCallback:
|
||||
return "No archive was provided in the callback."
|
||||
return "no archive was provided in the callback."
|
||||
case .noDelegateConfigured:
|
||||
return "No delegate was configured."
|
||||
return "no delegate was configured."
|
||||
case .delegateFreedBeforeCallback:
|
||||
return "The delegate was freed before the callback was invoked."
|
||||
return "the delegate was freed before the callback was invoked."
|
||||
case .unableToSetFormat(let code, let name):
|
||||
return "Unable to set the archive format \(name), code \(code)"
|
||||
return "unable to set the archive format \(name), code \(code)"
|
||||
case .unableToAddFilter(let code, let name):
|
||||
return "Unable to set the archive filter \(name), code \(code)"
|
||||
return "unable to set the archive filter \(name), code \(code)"
|
||||
case .unableToWriteEntryHeader(let code):
|
||||
return "Unable to write the entry header to the archive. Error code \(code)"
|
||||
return "unable to write the entry header to the archive. Error code \(code)"
|
||||
case .unableToWriteData(let code):
|
||||
return "Unable to write data to the archive. Error code \(code)"
|
||||
return "unable to write data to the archive. Error code \(code)"
|
||||
case .unableToCloseArchive(let code):
|
||||
return "Unable to close the archive. Error code \(code)"
|
||||
return "unable to close the archive. Error code \(code)"
|
||||
case .unableToOpenArchive(let code):
|
||||
return "Unable to open the archive. Error code \(code)"
|
||||
return "unable to open the archive. Error code \(code)"
|
||||
case .unableToSetOption(_):
|
||||
return "Unable to set an option on the archive."
|
||||
return "unable to set an option on the archive."
|
||||
case .failedToSetLocale(let locales):
|
||||
return "Failed to set locale to \(locales)"
|
||||
return "failed to set locale to \(locales)"
|
||||
case .failedToGetProperty(let path, let propertyName):
|
||||
return "Failed to read property \(propertyName) from file at path \(path)"
|
||||
return "failed to read property \(propertyName) from file at path \(path)"
|
||||
case .failedToDetectFilter:
|
||||
return "Failed to detect filter from archive."
|
||||
return "failed to detect filter from archive."
|
||||
case .failedToDetectFormat:
|
||||
return "Failed to detect format from archive."
|
||||
return "failed to detect format from archive."
|
||||
case .failedToExtractArchive(let reason):
|
||||
return "Failed to extract archive: \(reason)"
|
||||
return "failed to extract archive: \(reason)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ extension ArchiveReader {
|
||||
}
|
||||
}
|
||||
guard foundEntry else {
|
||||
throw ArchiveError.failedToExtractArchive("No entries found in archive")
|
||||
throw ArchiveError.failedToExtractArchive("no entries found in archive")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,12 @@ extension EXT4 {
|
||||
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .notFound(let p): return "No such file or directory: \(p)"
|
||||
case .notAFile(let p): return "Not a regular file: \(p)"
|
||||
case .isDirectory(let p): return "Is a directory: \(p)"
|
||||
case .notADirectory(let p): return "Not a directory: \(p)"
|
||||
case .symlinkLoop(let p): return "Symlink loop while resolving: \(p)"
|
||||
case .invalidPath(let p): return "Invalid path: \(p)"
|
||||
case .notFound(let p): return "no such file or directory: \(p)"
|
||||
case .notAFile(let p): return "not a regular file: \(p)"
|
||||
case .isDirectory(let p): return "is a directory: \(p)"
|
||||
case .notADirectory(let p): return "not a directory: \(p)"
|
||||
case .symlinkLoop(let p): return "symlink loop while resolving: \(p)"
|
||||
case .invalidPath(let p): return "invalid path: \(p)"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ extension EXT4.EXT4Reader {
|
||||
/// Validate that a physical block address is within device bounds
|
||||
private func validateBlockAddress(_ block: UInt32) throws {
|
||||
guard UInt64(block) < totalBlocks else {
|
||||
throw EXT4.PathIOError.invalidPath("Block address \(block) exceeds device bounds (\(totalBlocks) blocks)")
|
||||
throw EXT4.PathIOError.invalidPath("block address \(block) exceeds device bounds (\(totalBlocks) blocks)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ extension EXT4.EXT4Reader {
|
||||
if bytesWritten > 0 {
|
||||
return bytesWritten
|
||||
}
|
||||
throw EXT4.PathIOError.invalidPath("Failed to seek to offset \(absoluteByteOffset): \(error)")
|
||||
throw EXT4.PathIOError.invalidPath("failed to seek to offset \(absoluteByteOffset): \(error)")
|
||||
}
|
||||
|
||||
while remaining > 0 && bytesWritten < desiredBytes {
|
||||
@@ -345,7 +345,7 @@ extension EXT4.EXT4Reader {
|
||||
// Read symlink target
|
||||
let linkBytes = try readFileFromInode(inodeNum: child.1)
|
||||
guard let linkTarget = String(data: linkBytes, encoding: .utf8), !linkTarget.isEmpty else {
|
||||
throw EXT4.PathIOError.invalidPath("Empty symlink target")
|
||||
throw EXT4.PathIOError.invalidPath("empty symlink target")
|
||||
}
|
||||
|
||||
// Parse symlink target into components
|
||||
@@ -517,7 +517,7 @@ extension EXT4.EXT4Reader {
|
||||
// Return partial data that was successfully read
|
||||
return out
|
||||
}
|
||||
throw EXT4.PathIOError.invalidPath("Failed to seek to offset \(absByteOffset): \(error)")
|
||||
throw EXT4.PathIOError.invalidPath("failed to seek to offset \(absByteOffset): \(error)")
|
||||
}
|
||||
|
||||
var left = ovlLen
|
||||
|
||||
@@ -106,7 +106,7 @@ extension ContainerizationError {
|
||||
|
||||
let match = values[rawValue]
|
||||
guard let match else {
|
||||
fatalError("invalid Code Value \(rawValue)")
|
||||
fatalError("invalid code value \(rawValue)")
|
||||
}
|
||||
self.value = match
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ package final class LocalOCILayoutClient: ContentClient {
|
||||
throw ContainerizationError(
|
||||
.internalError,
|
||||
message:
|
||||
"File \(filePath) exists but contains different content. Expected digest: \(expectedDigest.digestString), existing digest: \(existingDigest.digestString)"
|
||||
"file \(filePath) exists but contains different content. expected digest: \(expectedDigest.digestString), existing digest: \(existingDigest.digestString)"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -55,19 +55,19 @@ extension RegistryClient {
|
||||
}
|
||||
|
||||
guard let digest = response.headers.first(name: "Docker-Content-Digest") else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing required header Docker-Content-Digest")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing required header Docker-Content-Digest")
|
||||
}
|
||||
|
||||
guard let type = response.headers.first(name: "Content-Type") else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing required header Content-Type")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing required header Content-Type")
|
||||
}
|
||||
|
||||
guard let sizeStr = response.headers.first(name: "Content-Length") else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing required header Content-Length")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing required header Content-Length")
|
||||
}
|
||||
|
||||
guard let size = Int64(sizeStr) else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Cannot convert \(sizeStr) to Int64")
|
||||
throw ContainerizationError(.invalidArgument, message: "cannot convert \(sizeStr) to Int64")
|
||||
}
|
||||
|
||||
return Descriptor(mediaType: type, digest: digest, size: size)
|
||||
@@ -92,7 +92,7 @@ extension RegistryClient {
|
||||
|
||||
let mediaType = descriptor.mediaType
|
||||
if mediaType.isEmpty {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing media type for descriptor \(descriptor.digest)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing media type for descriptor \(descriptor.digest)")
|
||||
}
|
||||
|
||||
let headers = [
|
||||
@@ -120,7 +120,7 @@ extension RegistryClient {
|
||||
|
||||
let mediaType = descriptor.mediaType
|
||||
if mediaType.isEmpty {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing media type for descriptor \(descriptor.digest)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing media type for descriptor \(descriptor.digest)")
|
||||
}
|
||||
|
||||
let headers = [
|
||||
@@ -142,7 +142,7 @@ extension RegistryClient {
|
||||
|
||||
let mediaType = descriptor.mediaType
|
||||
if mediaType.isEmpty {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing media type for descriptor \(descriptor.digest)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing media type for descriptor \(descriptor.digest)")
|
||||
}
|
||||
|
||||
let headers = [
|
||||
@@ -158,7 +158,7 @@ extension RegistryClient {
|
||||
|
||||
// How many bytes to expect
|
||||
guard let expectedBytes = response.headers.first(name: "Content-Length").flatMap(Int64.init) else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing required header Content-Length")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing required header Content-Length")
|
||||
}
|
||||
|
||||
try await closure(expectedBytes, response.body)
|
||||
@@ -186,7 +186,7 @@ extension RegistryClient {
|
||||
guard written == readBytes else {
|
||||
throw ContainerizationError(
|
||||
.internalError,
|
||||
message: "Could not write \(readBytes) bytes to file \(file)"
|
||||
message: "could not write \(readBytes) bytes to file \(file)"
|
||||
)
|
||||
}
|
||||
hasher.update(data: buf.readableBytesView)
|
||||
@@ -212,7 +212,7 @@ extension RegistryClient {
|
||||
var hasher = SHA256()
|
||||
var received: Int64 = 0
|
||||
guard FileManager.default.createFile(atPath: file.path, contents: nil) else {
|
||||
throw ContainerizationError(.internalError, message: "Cannot create file at path \(file.path)")
|
||||
throw ContainerizationError(.internalError, message: "cannot create file at path \(file.path)")
|
||||
}
|
||||
try await self.fetchBlob(name: name, descriptor: descriptor) { (size, body) in
|
||||
let fd = try FileHandle(forWritingTo: file)
|
||||
|
||||
@@ -50,7 +50,7 @@ extension RegistryClient {
|
||||
|
||||
let mediaType = descriptor.mediaType
|
||||
if mediaType.isEmpty {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing media type for descriptor \(descriptor.digest)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing media type for descriptor \(descriptor.digest)")
|
||||
}
|
||||
|
||||
var isManifest = false
|
||||
@@ -88,7 +88,7 @@ extension RegistryClient {
|
||||
}
|
||||
|
||||
if exists {
|
||||
throw ContainerizationError(.exists, message: "Content already exists \(descriptor.digest)")
|
||||
throw ContainerizationError(.exists, message: "content already exists \(descriptor.digest)")
|
||||
}
|
||||
} else if response.status != .notFound {
|
||||
let url = components.url?.absoluteString ?? "unknown"
|
||||
@@ -111,7 +111,7 @@ extension RegistryClient {
|
||||
case .ok, .accepted, .noContent:
|
||||
break
|
||||
case .created:
|
||||
throw ContainerizationError(.exists, message: "Content already exists \(descriptor.digest)")
|
||||
throw ContainerizationError(.exists, message: "content already exists \(descriptor.digest)")
|
||||
default:
|
||||
let url = components.url?.absoluteString ?? "unknown"
|
||||
let reason = await ErrorResponse.fromResponseBody(response.body)?.jsonString
|
||||
@@ -120,11 +120,11 @@ extension RegistryClient {
|
||||
|
||||
// Get the location to upload the blob.
|
||||
guard let location = response.headers.first(name: "Location") else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing required header Location")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing required header Location")
|
||||
}
|
||||
|
||||
guard let urlComponents = URLComponents(string: location) else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid url \(location)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid url \(location)")
|
||||
}
|
||||
var queryItems = urlComponents.queryItems ?? []
|
||||
queryItems.append(URLQueryItem(name: "digest", value: descriptor.digest))
|
||||
@@ -156,7 +156,7 @@ extension RegistryClient {
|
||||
|
||||
guard descriptor.digest == response.headers.first(name: "Docker-Content-Digest") else {
|
||||
let required = response.headers.first(name: "Docker-Content-Digest") ?? ""
|
||||
throw ContainerizationError(.internalError, message: "Digest mismatch \(descriptor.digest) != \(required)")
|
||||
throw ContainerizationError(.internalError, message: "digest mismatch \(descriptor.digest) != \(required)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ extension RegistryClient {
|
||||
/// See https://docs.docker.com/registry/spec/auth/token/
|
||||
internal func fetchToken(request: TokenRequest) async throws -> TokenResponse {
|
||||
guard var components = URLComponents(string: request.realm) else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Cannot create URL from \(request.realm)")
|
||||
throw ContainerizationError(.invalidArgument, message: "cannot create URL from \(request.realm)")
|
||||
}
|
||||
components.queryItems = [
|
||||
URLQueryItem(name: "client_id", value: request.clientId),
|
||||
@@ -161,13 +161,13 @@ extension RegistryClient {
|
||||
let parsedHeaders = Self.parseWWWAuthenticateHeaders(headers: authenticateHeaders)
|
||||
let bearerChallenge = parsedHeaders.first { $0.type == "Bearer" }
|
||||
guard let bearerChallenge else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing Bearer challenge in \(TokenRequest.authenticateHeaderName) header")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing Bearer challenge in \(TokenRequest.authenticateHeaderName) header")
|
||||
}
|
||||
guard let realm = bearerChallenge.realm else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Cannot parse realm from \(TokenRequest.authenticateHeaderName) header")
|
||||
throw ContainerizationError(.invalidArgument, message: "cannot parse realm from \(TokenRequest.authenticateHeaderName) header")
|
||||
}
|
||||
guard let service = bearerChallenge.service else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Cannot parse service from \(TokenRequest.authenticateHeaderName) header")
|
||||
throw ContainerizationError(.invalidArgument, message: "cannot parse service from \(TokenRequest.authenticateHeaderName) header")
|
||||
}
|
||||
let scope = bearerChallenge.scope
|
||||
let tokenRequest = TokenRequest(realm: realm, service: service, clientId: self.clientID, scope: scope, authentication: self.authentication)
|
||||
|
||||
@@ -70,15 +70,15 @@ public final class RegistryClient: ContentClient {
|
||||
) throws {
|
||||
let ref = try Reference.parse(reference)
|
||||
guard let domain = ref.resolvedDomain else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid domain for image reference \(reference)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid domain for image reference \(reference)")
|
||||
}
|
||||
let scheme = insecure ? "http" : "https"
|
||||
let _url = "\(scheme)://\(domain)"
|
||||
guard let url = URL(string: _url) else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Cannot convert \(_url) to URL")
|
||||
throw ContainerizationError(.invalidArgument, message: "cannot convert \(_url) to URL")
|
||||
}
|
||||
guard let host = url.host else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid host \(domain)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid host \(domain)")
|
||||
}
|
||||
let port = url.port
|
||||
self.init(
|
||||
@@ -142,7 +142,7 @@ public final class RegistryClient: ContentClient {
|
||||
closure: (HTTPClientResponse) async throws -> T
|
||||
) async throws -> T {
|
||||
guard let path = components.url?.absoluteString else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid url \(components.path)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid url \(components.path)")
|
||||
}
|
||||
|
||||
var request = HTTPClientRequest(url: path)
|
||||
@@ -187,7 +187,7 @@ public final class RegistryClient: ContentClient {
|
||||
do {
|
||||
let _currentToken = try await fetchToken(request: tokenRequest)
|
||||
guard let token = _currentToken.getToken() else {
|
||||
throw ContainerizationError(.internalError, message: "Failed to fetch Bearer token")
|
||||
throw ContainerizationError(.internalError, message: "failed to fetch Bearer token")
|
||||
}
|
||||
currentToken = _currentToken
|
||||
request.headers.replaceOrAdd(name: "Authorization", value: token)
|
||||
@@ -197,7 +197,7 @@ public final class RegistryClient: ContentClient {
|
||||
throw err
|
||||
}
|
||||
if status == .unauthorized || status == .forbidden {
|
||||
throw RegistryClient.Error.invalidStatus(url: path, _response.status, reason: "Access denied or wrong credentials")
|
||||
throw RegistryClient.Error.invalidStatus(url: path, _response.status, reason: "access denied or wrong credentials")
|
||||
}
|
||||
|
||||
throw err
|
||||
@@ -225,9 +225,9 @@ public final class RegistryClient: ContentClient {
|
||||
if err.errorCode == kDNSServiceErr_NoSuchRecord {
|
||||
let message: String
|
||||
if let proxyURL = self.proxyURL, let proxyHost = proxyURL.host {
|
||||
message = "Failed to resolve either repository hostname \(host()) or proxy hostname \(proxyHost)"
|
||||
message = "failed to resolve either repository hostname \(host()) or proxy hostname \(proxyHost)"
|
||||
} else {
|
||||
message = "Failed to resolve either repository hostname \(host())"
|
||||
message = "failed to resolve either repository hostname \(host())"
|
||||
}
|
||||
throw ContainerizationError(.internalError, message: message)
|
||||
}
|
||||
@@ -241,7 +241,7 @@ public final class RegistryClient: ContentClient {
|
||||
}
|
||||
}
|
||||
guard let response else {
|
||||
throw ContainerizationError(.internalError, message: "Invalid response")
|
||||
throw ContainerizationError(.internalError, message: "invalid response")
|
||||
}
|
||||
return try await closure(response)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class ContentWriter {
|
||||
let exists = FileManager.default.fileExists(atPath: base.path, isDirectory: &isDirectory)
|
||||
|
||||
guard exists && isDirectory.boolValue else {
|
||||
throw ContainerizationError(.internalError, message: "Cannot create ContentWriter for path \(base.absolutePath()). Not a directory")
|
||||
throw ContainerizationError(.internalError, message: "cannot create ContentWriter for path \(base.absolutePath()). Not a directory")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public final class LocalContent: Content {
|
||||
|
||||
public init(path: URL) throws {
|
||||
guard FileManager.default.fileExists(atPath: path.path) else {
|
||||
throw ContainerizationError(.notFound, message: "Content at path \(path.absolutePath())")
|
||||
throw ContainerizationError(.notFound, message: "content at path \(path.absolutePath())")
|
||||
}
|
||||
|
||||
self.file = try FileHandle(forReadingFrom: path)
|
||||
@@ -63,7 +63,7 @@ public final class LocalContent: Content {
|
||||
if let size = fileAttrs[FileAttributeKey.size] as? UInt64 {
|
||||
return size
|
||||
}
|
||||
throw ContainerizationError(.internalError, message: "Could not determine file size for \(path.absolutePath())")
|
||||
throw ContainerizationError(.internalError, message: "could not determine file size for \(path.absolutePath())")
|
||||
}
|
||||
|
||||
public func decode<T>() throws -> T where T: Decodable {
|
||||
|
||||
@@ -154,7 +154,7 @@ public actor LocalContentStore: ContentStore {
|
||||
@discardableResult
|
||||
public func completeIngestSession(_ id: String) async throws -> [String] {
|
||||
guard await activeIngestSessions.contains(id) else {
|
||||
throw ContainerizationError(.internalError, message: "Invalid session id \(id)")
|
||||
throw ContainerizationError(.internalError, message: "invalid session id \(id)")
|
||||
}
|
||||
await activeIngestSessions.remove(id)
|
||||
let temporaryPath = self._ingestPath.appendingPathComponent(id)
|
||||
|
||||
@@ -105,7 +105,7 @@ public struct Platform: Sendable, Equatable {
|
||||
public init(from platform: String) throws {
|
||||
let items = platform.split(separator: "/", maxSplits: 1)
|
||||
guard let osValue = items.first else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing OS in \(platform)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing OS in \(platform)")
|
||||
}
|
||||
switch osValue {
|
||||
case "linux":
|
||||
@@ -115,18 +115,18 @@ public struct Platform: Sendable, Equatable {
|
||||
case "windows":
|
||||
_rawOS = osValue.description
|
||||
default:
|
||||
throw ContainerizationError(.invalidArgument, message: "Unknown OS in \(osValue)")
|
||||
throw ContainerizationError(.invalidArgument, message: "unknown OS in \(osValue)")
|
||||
}
|
||||
guard items.count > 1 else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing architecture in \(platform)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing architecture in \(platform)")
|
||||
}
|
||||
|
||||
guard let archItems = items.last?.split(separator: "/", maxSplits: 1, omittingEmptySubsequences: false) else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing architecture in \(platform)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing architecture in \(platform)")
|
||||
}
|
||||
|
||||
guard let archName = archItems.first else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing architecture in \(platform)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing architecture in \(platform)")
|
||||
}
|
||||
|
||||
switch archName {
|
||||
@@ -144,7 +144,7 @@ public struct Platform: Sendable, Equatable {
|
||||
|
||||
if archItems.count == 2 {
|
||||
guard let archVariant = archItems.last else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing variant in \(platform)")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing variant in \(platform)")
|
||||
}
|
||||
|
||||
switch archName {
|
||||
@@ -153,40 +153,40 @@ public struct Platform: Sendable, Equatable {
|
||||
case "v5", "v6", "v7", "v8":
|
||||
variant = archVariant.description
|
||||
default:
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid variant \(archVariant)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid variant \(archVariant)")
|
||||
}
|
||||
case "armhf":
|
||||
switch archVariant {
|
||||
case "v7":
|
||||
variant = "v7"
|
||||
default:
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid variant \(archVariant)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid variant \(archVariant)")
|
||||
}
|
||||
case "armel":
|
||||
switch archVariant {
|
||||
case "v6":
|
||||
variant = "v6"
|
||||
default:
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid variant \(archVariant)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid variant \(archVariant)")
|
||||
}
|
||||
case "aarch64", "arm64":
|
||||
switch archVariant {
|
||||
case "v8", "8":
|
||||
variant = "v8"
|
||||
default:
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid variant \(archVariant)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid variant \(archVariant)")
|
||||
}
|
||||
case "x86_64", "x86-64", "amd64":
|
||||
switch archVariant {
|
||||
case "v1":
|
||||
variant = nil
|
||||
default:
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid variant \(archVariant)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid variant \(archVariant)")
|
||||
}
|
||||
case "i386", "386", "ppc64le", "riscv64":
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid variant \(archVariant)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid variant \(archVariant)")
|
||||
default:
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid variant \(archVariant)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid variant \(archVariant)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,11 +302,11 @@ extension Platform: Codable {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let architecture = try container.decodeIfPresent(String.self, forKey: .architecture)
|
||||
guard let architecture else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing architecture")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing architecture")
|
||||
}
|
||||
let os = try container.decodeIfPresent(String.self, forKey: .os)
|
||||
guard let os else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Missing OS")
|
||||
throw ContainerizationError(.invalidArgument, message: "missing OS")
|
||||
}
|
||||
let variant = try container.decodeIfPresent(String.self, forKey: .variant)
|
||||
self.init(arch: architecture, os: os, variant: variant)
|
||||
|
||||
@@ -105,12 +105,12 @@ public class Reference: CustomStringConvertible {
|
||||
|
||||
public static func parse(_ s: String) throws -> Reference {
|
||||
if s.count > referenceTotalLengthMax {
|
||||
throw ContainerizationError(.invalidArgument, message: "Reference length \(s.count) greater than \(referenceTotalLengthMax)")
|
||||
throw ContainerizationError(.invalidArgument, message: "reference length \(s.count) greater than \(referenceTotalLengthMax)")
|
||||
}
|
||||
|
||||
let identifierRegex = try Regex(Self.identifierPattern)
|
||||
guard try identifierRegex.wholeMatch(in: s) == nil else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Cannot specify 64 byte hex string as reference")
|
||||
throw ContainerizationError(.invalidArgument, message: "cannot specify 64 byte hex string as reference")
|
||||
}
|
||||
|
||||
let (domain, remainder) = try Self.parseDomain(from: s)
|
||||
@@ -118,17 +118,17 @@ public class Reference: CustomStringConvertible {
|
||||
if let domain {
|
||||
let domainRegex = try Regex(domainPattern)
|
||||
guard try domainRegex.wholeMatch(in: domain) != nil else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid domain \(domain) for reference \(s)")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid domain \(domain) for reference \(s)")
|
||||
}
|
||||
}
|
||||
let fields = try constructedRawReference.matches(regex: pathTagPattern)
|
||||
guard let path = fields["path"] else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Cannot parse path for reference \(s)")
|
||||
throw ContainerizationError(.invalidArgument, message: "cannot parse path for reference \(s)")
|
||||
}
|
||||
|
||||
let ref = try Reference(path: path, domain: domain)
|
||||
if ref.name.count > nameTotalLengthMax {
|
||||
throw ContainerizationError(.invalidArgument, message: "Repo length \(ref.name.count) greater than \(nameTotalLengthMax)")
|
||||
throw ContainerizationError(.invalidArgument, message: "repo length \(ref.name.count) greater than \(nameTotalLengthMax)")
|
||||
}
|
||||
|
||||
// Extract tag and digest
|
||||
@@ -165,7 +165,7 @@ public class Reference: CustomStringConvertible {
|
||||
|
||||
public static func withName(_ name: String) throws -> Reference {
|
||||
if name.count > nameTotalLengthMax {
|
||||
throw ContainerizationError(.invalidArgument, message: "Name length \(name.count) greater than \(nameTotalLengthMax)")
|
||||
throw ContainerizationError(.invalidArgument, message: "name length \(name.count) greater than \(nameTotalLengthMax)")
|
||||
}
|
||||
let fields = try name.matches(regex: Self.domainPattern)
|
||||
// Extract domain and path
|
||||
@@ -173,7 +173,7 @@ public class Reference: CustomStringConvertible {
|
||||
let path = fields["path"] ?? ""
|
||||
|
||||
if domain.isEmpty || path.isEmpty {
|
||||
throw ContainerizationError(.invalidArgument, message: "Image reference domain or path is empty")
|
||||
throw ContainerizationError(.invalidArgument, message: "image reference domain or path is empty")
|
||||
}
|
||||
|
||||
return try Reference(path: path, domain: domain)
|
||||
@@ -188,7 +188,7 @@ public class Reference: CustomStringConvertible {
|
||||
tag = fields["tag"] ?? ""
|
||||
|
||||
if tag.isEmpty {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid format for image reference. Missing tag")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid format for image reference. Missing tag")
|
||||
}
|
||||
return try Reference(path: self.path, domain: self.domain, tag: tag)
|
||||
}
|
||||
@@ -202,7 +202,7 @@ public class Reference: CustomStringConvertible {
|
||||
digest = fields["digest"] ?? ""
|
||||
|
||||
if digest.isEmpty {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid format for image reference. Missing digest")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid format for image reference. Missing digest")
|
||||
}
|
||||
return try Reference(path: self.path, domain: self.domain, digest: digest)
|
||||
}
|
||||
@@ -252,7 +252,7 @@ extension String {
|
||||
let regex = try NSRegularExpression(pattern: regex, options: [])
|
||||
let nsRange = NSRange(self.startIndex..<self.endIndex, in: self)
|
||||
guard let match = regex.firstMatch(in: self, options: [], range: nsRange), match.range == nsRange else {
|
||||
throw ContainerizationError(.invalidArgument, message: "Invalid format for image reference")
|
||||
throw ContainerizationError(.invalidArgument, message: "invalid format for image reference")
|
||||
}
|
||||
var results = [String: String]()
|
||||
for name in try regex.captureGroupNames() {
|
||||
|
||||
@@ -392,7 +392,7 @@ extension Socket {
|
||||
sysRead(handle.fileDescriptor, baseAddress, bufferSize)
|
||||
}
|
||||
if bytesRead < 0 {
|
||||
throw Socket.errnoToError(msg: "Error reading from connection")
|
||||
throw Socket.errnoToError(msg: "error reading from connection")
|
||||
} else if bytesRead == 0 {
|
||||
throw SocketError.closed
|
||||
}
|
||||
|
||||
@@ -57,13 +57,13 @@ public enum User {
|
||||
init(rawString: String) throws {
|
||||
let args = rawString.split(separator: ":", omittingEmptySubsequences: false)
|
||||
guard args.count == 7 else {
|
||||
throw Error.parseError("Cannot parse User from '\(rawString)'")
|
||||
throw Error.parseError("cannot parse User from '\(rawString)'")
|
||||
}
|
||||
guard let uid = UInt32(args[2]) else {
|
||||
throw Error.parseError("Cannot parse uid from '\(args[2])'")
|
||||
throw Error.parseError("cannot parse uid from '\(args[2])'")
|
||||
}
|
||||
guard let gid = UInt32(args[3]) else {
|
||||
throw Error.parseError("Cannot parse gid from '\(args[3])'")
|
||||
throw Error.parseError("cannot parse gid from '\(args[3])'")
|
||||
}
|
||||
self.name = String(args[0])
|
||||
self.password = String(args[1])
|
||||
@@ -86,10 +86,10 @@ public enum User {
|
||||
init(rawString: String) throws {
|
||||
let args = rawString.split(separator: ":", omittingEmptySubsequences: false)
|
||||
guard args.count == 4 else {
|
||||
throw Error.parseError("Cannot parse Group from '\(rawString)'")
|
||||
throw Error.parseError("cannot parse Group from '\(rawString)'")
|
||||
}
|
||||
guard let gid = UInt32(args[2]) else {
|
||||
throw Error.parseError("Cannot parse gid from '\(args[2])'")
|
||||
throw Error.parseError("cannot parse gid from '\(args[2])'")
|
||||
}
|
||||
self.name = String(args[0])
|
||||
self.password = String(args[1])
|
||||
|
||||
@@ -140,7 +140,7 @@ extension Application {
|
||||
return
|
||||
}
|
||||
guard !FileManager.default.fileExists(atPath: unpackPath) else {
|
||||
throw ContainerizationError(.exists, message: "Directory already exists at \(unpackPath)")
|
||||
throw ContainerizationError(.exists, message: "directory already exists at \(unpackPath)")
|
||||
}
|
||||
let unpackUrl = URL(filePath: unpackPath)
|
||||
try FileManager.default.createDirectory(at: unpackUrl, withIntermediateDirectories: true)
|
||||
@@ -266,7 +266,7 @@ extension Application {
|
||||
var authentication: Authentication?
|
||||
let ref = try Reference.parse(ref)
|
||||
guard let host = ref.resolvedDomain else {
|
||||
throw ContainerizationError(.invalidArgument, message: "No host specified in image reference")
|
||||
throw ContainerizationError(.invalidArgument, message: "no host specified in image reference")
|
||||
}
|
||||
authentication = Self.authenticationFromEnv(host: host)
|
||||
if let authentication {
|
||||
|
||||
@@ -56,7 +56,7 @@ extension Application {
|
||||
for rawBinary in kernels {
|
||||
let parts = rawBinary.split(separator: ":")
|
||||
guard parts.count == 2 else {
|
||||
throw "Invalid binary format: \(rawBinary)"
|
||||
throw "invalid binary format: \(rawBinary)"
|
||||
}
|
||||
let platform: SystemPlatform
|
||||
switch parts[1] {
|
||||
|
||||
@@ -91,7 +91,7 @@ struct OCIClientTests: ~Copyable {
|
||||
throw error!
|
||||
}
|
||||
#expect(status == .unauthorized)
|
||||
#expect(reason == "Access denied or wrong credentials")
|
||||
#expect(reason == "access denied or wrong credentials")
|
||||
}
|
||||
|
||||
@Test(.enabled(if: hasRegistryCredentials))
|
||||
|
||||
Reference in New Issue
Block a user