Skip to content

Commit 8f9ae3f

Browse files
authored
ContainerRegistry: Remove return-type overloaded client functions (#145)
Motivation ---------- Return type overloads can be puzzling for new readers because the same function call returns a different type depending on where it is called. In some cases a type annotation is needed at the call site, but when the overloaded function is the final call in another function the compiler can infer the type, so the reader needs to know to check the type of the enclosing function. In addition, in a future pull request we will need access to the underlying data returned by the HTTP client, in order to verify digests and create `ContentDescriptor` objects. This refactoring starts to prepare for that and makes the code easier to understand. Modifications ------------- * Remove return-type overloaded version of `executeRequestThrowing()` * Remove return-type overloaded version of `getBlob()` Result ------ Refactoring. No functional change. Test Plan --------- Existing tests continue to pass.
1 parent 792ca55 commit 8f9ae3f

File tree

5 files changed

+28
-67
lines changed

5 files changed

+28
-67
lines changed

Sources/ContainerRegistry/Blobs.swift

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,28 +76,6 @@ public extension RegistryClient {
7676
.data
7777
}
7878

79-
/// Fetches a blob and tries to decode it as a JSON object.
80-
///
81-
/// - Parameters:
82-
/// - repository: Name of the repository containing the blob.
83-
/// - digest: Digest of the blob.
84-
/// - Returns: The decoded object.
85-
/// - Throws: If the blob download fails or the blob cannot be decoded.
86-
///
87-
/// Some JSON objects, such as ImageConfiguration, are stored
88-
/// in the registry as plain blobs with MIME type "application/octet-stream".
89-
/// This function attempts to decode the received data without reference
90-
/// to the MIME type.
91-
func getBlob<Response: Decodable>(repository: ImageReference.Repository, digest: ImageReference.Digest) async throws
92-
-> Response
93-
{
94-
try await executeRequestThrowing(
95-
.get(repository, path: "blobs/\(digest)", accepting: ["application/octet-stream"]),
96-
decodingErrors: [.notFound]
97-
)
98-
.data
99-
}
100-
10179
/// Uploads a blob to the registry.
10280
///
10381
/// This function uploads a blob of unstructured data to the registry.

Sources/ContainerRegistry/Manifests.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ public extension RegistryClient {
1717
repository: ImageReference.Repository,
1818
reference: any ImageReference.Reference,
1919
manifest: ImageManifest
20-
) async throws
21-
-> String
22-
{
20+
) async throws -> String {
2321
// See https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-manifests
2422
let httpResponse = try await executeRequestThrowing(
2523
// All blob uploads have Content-Type: application/octet-stream on the wire, even if mediatype is different
@@ -44,11 +42,12 @@ public extension RegistryClient {
4442
.absoluteString
4543
}
4644

47-
func getManifest(repository: ImageReference.Repository, reference: any ImageReference.Reference) async throws
48-
-> ImageManifest
49-
{
45+
func getManifest(
46+
repository: ImageReference.Repository,
47+
reference: any ImageReference.Reference
48+
) async throws -> ImageManifest {
5049
// See https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pulling-manifests
51-
try await executeRequestThrowing(
50+
let (data, _) = try await executeRequestThrowing(
5251
.get(
5352
repository,
5453
path: "manifests/\(reference)",
@@ -59,14 +58,15 @@ public extension RegistryClient {
5958
),
6059
decodingErrors: [.notFound]
6160
)
62-
.data
61+
return try decoder.decode(ImageManifest.self, from: data)
6362
}
6463

65-
func getIndex(repository: ImageReference.Repository, reference: any ImageReference.Reference) async throws
66-
-> ImageIndex
67-
{
64+
func getIndex(
65+
repository: ImageReference.Repository,
66+
reference: any ImageReference.Reference
67+
) async throws -> ImageIndex {
6868
// See https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pulling-manifests
69-
try await executeRequestThrowing(
69+
let (data, _) = try await executeRequestThrowing(
7070
.get(
7171
repository,
7272
path: "manifests/\(reference)",
@@ -77,6 +77,6 @@ public extension RegistryClient {
7777
),
7878
decodingErrors: [.notFound]
7979
)
80-
.data
80+
return try decoder.decode(ImageIndex.self, from: data)
8181
}
8282
}

Sources/ContainerRegistry/RegistryClient+ImageConfiguration.swift

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ extension RegistryClient {
2121
/// - Throws: If the blob cannot be decoded as an `ImageConfiguration`.
2222
///
2323
/// Image configuration records are stored as blobs in the registry. This function retrieves the requested blob and tries to decode it as a configuration record.
24-
public func getImageConfiguration(forImage image: ImageReference, digest: ImageReference.Digest) async throws
25-
-> ImageConfiguration
26-
{
27-
try await getBlob(repository: image.repository, digest: digest)
24+
public func getImageConfiguration(
25+
forImage image: ImageReference,
26+
digest: ImageReference.Digest
27+
) async throws -> ImageConfiguration {
28+
let data = try await getBlob(repository: image.repository, digest: digest)
29+
return try decoder.decode(ImageConfiguration.self, from: data)
2830
}
2931

3032
/// Upload an image configuration record to the registry.
@@ -35,9 +37,10 @@ extension RegistryClient {
3537
/// - Throws: If the blob upload fails.
3638
///
3739
/// Image configuration records are stored as blobs in the registry. This function encodes the provided configuration record and stores it as a blob in the registry.
38-
public func putImageConfiguration(forImage image: ImageReference, configuration: ImageConfiguration) async throws
39-
-> ContentDescriptor
40-
{
40+
public func putImageConfiguration(
41+
forImage image: ImageReference,
42+
configuration: ImageConfiguration
43+
) async throws -> ContentDescriptor {
4144
try await putBlob(
4245
repository: image.repository,
4346
mediaType: "application/vnd.oci.image.config.v1+json",

Sources/ContainerRegistry/RegistryClient.swift

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -308,27 +308,6 @@ extension RegistryClient {
308308
}
309309
}
310310

311-
/// Execute an HTTP request with no request body, decoding the JSON response
312-
/// - Parameters:
313-
/// - request: The HTTP request to execute.
314-
/// - success: The HTTP status code expected if the request is successful.
315-
/// - errors: Expected error codes for which the registry sends structured error messages.
316-
/// - Returns: An asynchronously-delivered tuple that contains the raw response body as a Data instance, and a HTTPURLResponse.
317-
/// - Throws: If the server response is unexpected or indicates that an error occurred.
318-
func executeRequestThrowing<Response: Decodable>(
319-
_ request: RegistryOperation,
320-
expectingStatus success: HTTPResponse.Status = .ok,
321-
decodingErrors errors: [HTTPResponse.Status]
322-
) async throws -> (data: Response, response: HTTPResponse) {
323-
let (data, httpResponse) = try await executeRequestThrowing(
324-
request,
325-
expectingStatus: success,
326-
decodingErrors: errors
327-
)
328-
let decoded = try decoder.decode(Response.self, from: data)
329-
return (decoded, httpResponse)
330-
}
331-
332311
/// Execute an HTTP request uploading a request body.
333312
/// - Parameters:
334313
/// - operation: The Registry operation to execute.
@@ -337,9 +316,6 @@ extension RegistryClient {
337316
/// - errors: Expected error codes for which the registry sends structured error messages.
338317
/// - Returns: An asynchronously-delivered tuple that contains the raw response body as a Data instance, and a HTTPURLResponse.
339318
/// - Throws: If the server response is unexpected or indicates that an error occurred.
340-
///
341-
/// A plain Data version of this function is required because Data is Encodable and encodes to base64.
342-
/// Accidentally encoding data blobs will cause digests to fail and runtimes to be unable to run the images.
343319
func executeRequestThrowing(
344320
_ operation: RegistryOperation,
345321
uploading payload: Data,

Sources/ContainerRegistry/Tags.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
public extension RegistryClient {
1616
func getTags(repository: ImageReference.Repository) async throws -> Tags {
1717
// See https://github.com/opencontainers/distribution-spec/blob/main/spec.md#listing-tags
18-
try await executeRequestThrowing(.get(repository, path: "tags/list"), decodingErrors: [.notFound]).data
18+
let (data, _) = try await executeRequestThrowing(
19+
.get(repository, path: "tags/list"),
20+
decodingErrors: [.notFound]
21+
)
22+
return try decoder.decode(Tags.self, from: data)
1923
}
2024
}

0 commit comments

Comments
 (0)