Skip to content

Commit 33b13a2

Browse files
committed
ContainerRegistry: Do not expand the unqualified 'scratch' image name
1 parent d47538c commit 33b13a2

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

Sources/ContainerRegistry/ImageReference.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,18 @@ public struct ImageReference: Sendable, Equatable, CustomStringConvertible, Cust
7878
public init(fromString reference: String, defaultRegistry: String = "localhost:5000") throws {
7979
let (registry, remainder) = try splitReference(reference)
8080
let (repository, reference) = try parseName(remainder)
81+
82+
// As a special case, do not expand the reference for the unqualified 'scratch' image as it is handled locally.
83+
if registry == nil && repository.value == "scratch" {
84+
self.registry = ""
85+
self.repository = repository
86+
self.reference = reference
87+
return
88+
}
89+
8190
self.registry = registry ?? defaultRegistry
8291
if self.registry == "docker.io" {
83-
self.registry = "index.docker.io" // Special case for docker client, there is no network-level redirect
92+
self.registry = "index.docker.io" // Special case for Docker Hub, there is no network-level redirect
8493
}
8594
// As a special case, official images can be referred to by a single name, such as `swift` or `swift:slim`.
8695
// moby/moby assumes that these names refer to images in `library`: `library/swift` or `library/swift:slim`.
@@ -111,7 +120,11 @@ public struct ImageReference: Sendable, Equatable, CustomStringConvertible, Cust
111120

112121
/// Printable description of an ImageReference in a form which can be understood by a runtime
113122
public var description: String {
114-
"\(registry)/\(repository)\(reference.separator)\(reference)"
123+
if registry == "" {
124+
"\(repository)\(reference.separator)\(reference)"
125+
} else {
126+
"\(registry)/\(repository)\(reference.separator)\(reference)"
127+
}
115128
}
116129

117130
/// Printable description of an ImageReference in a form suitable for debugging.

Tests/ContainerRegistryTests/ImageReferenceTests.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,36 @@ struct ReferenceTests {
273273
)
274274
)
275275
}
276+
277+
@Test
278+
func testScratchReferences() throws {
279+
// The unqualified "scratch" image is handled locally so should not be expanded.
280+
#expect(
281+
try! ImageReference(fromString: "scratch", defaultRegistry: "localhost:5000")
282+
== ImageReference(
283+
registry: "",
284+
repository: ImageReference.Repository("scratch"),
285+
reference: ImageReference.Tag("latest")
286+
)
287+
)
288+
}
289+
290+
@Test
291+
func testReferenceDescription() throws {
292+
#expect(
293+
"\(try! ImageReference(fromString: "swift", defaultRegistry: "localhost:5000"))"
294+
== "localhost:5000/swift:latest"
295+
)
296+
297+
#expect(
298+
"\(try! ImageReference(fromString: "library/swift:slim", defaultRegistry: "docker.io"))"
299+
== "index.docker.io/library/swift:slim"
300+
)
301+
302+
#expect(
303+
"\(try! ImageReference(fromString: "scratch", defaultRegistry: "localhost:5000"))" == "scratch:latest"
304+
)
305+
}
276306
}
277307

278308
struct DigestTests {

0 commit comments

Comments
 (0)