@@ -86,7 +86,7 @@ def _digest_into_blob_path(digest):
86
86
digest_path = digest .replace (":" , "/" , 1 )
87
87
return "blobs/{}" .format (digest_path )
88
88
89
- def _download (rctx , authn , identifier , output , resource , headers = {}, allow_fail = False ):
89
+ def _download (rctx , authn , identifier , output , resource , headers = {}, allow_fail = False , block = True ):
90
90
"Use the Bazel Downloader to fetch from the remote registry"
91
91
92
92
if resource != "blobs" and resource != "manifests" :
@@ -118,10 +118,13 @@ def _download(rctx, authn, identifier, output, resource, headers = {}, allow_fai
118
118
auth = {registry_url : auth },
119
119
allow_fail = allow_fail ,
120
120
)
121
+
122
+ # Use non-blocking download, and forward headers, on Bazel 7.1.0 and later.
121
123
if versions .is_at_least ("7.1.0" , versions .get ()):
122
- return rctx .download (headers = headers , ** kwargs )
123
- else :
124
- return rctx .download (** kwargs )
124
+ kwargs ["block" ] = block
125
+ kwargs ["headers" ] = headers
126
+
127
+ return rctx .download (** kwargs )
125
128
126
129
def _download_manifest (rctx , authn , identifier , output ):
127
130
bytes = None
@@ -156,7 +159,7 @@ def _download_manifest(rctx, authn, identifier, output):
156
159
157
160
def _create_downloader (rctx , authn ):
158
161
return struct (
159
- download_blob = lambda identifier , output : _download (rctx , authn , identifier , output , "blobs" ),
162
+ download_blob = lambda identifier , output , block : _download (rctx , authn , identifier , output , "blobs" , block = block ),
160
163
download_manifest = lambda identifier , output : _download_manifest (rctx , authn , identifier , output ),
161
164
)
162
165
@@ -226,7 +229,7 @@ def _oci_pull_impl(rctx):
226
229
rctx .template (_digest_into_blob_path (digest ), "manifest.json" )
227
230
228
231
config_output_path = _digest_into_blob_path (manifest ["config" ]["digest" ])
229
- downloader .download_blob (manifest ["config" ]["digest" ], config_output_path )
232
+ downloader .download_blob (manifest ["config" ]["digest" ], config_output_path , block = True )
230
233
231
234
# if the user provided a platform for the image, validate it matches the config as best effort.
232
235
if rctx .attr .platform :
@@ -236,8 +239,14 @@ def _oci_pull_impl(rctx):
236
239
237
240
# download all layers
238
241
# TODO: we should avoid eager-download of the layers ("shallow pull")
242
+ results = []
239
243
for layer in manifest ["layers" ]:
240
- downloader .download_blob (layer ["digest" ], _digest_into_blob_path (layer ["digest" ]))
244
+ results .append (downloader .download_blob (layer ["digest" ], _digest_into_blob_path (layer ["digest" ]), block = False ))
245
+
246
+ # wait for all downloads to complete, if download is asynchronous
247
+ for r in results :
248
+ if hasattr (r , "wait" ):
249
+ r .wait ()
241
250
242
251
rctx .file ("index.json" , util .build_manifest_json (
243
252
media_type = manifest ["mediaType" ],
@@ -311,7 +320,7 @@ def _oci_alias_impl(rctx):
311
320
elif manifest ["mediaType" ] in _SUPPORTED_MEDIA_TYPES ["manifest" ]:
312
321
# single arch image where the user specified the platform.
313
322
config_output_path = _digest_into_blob_path (manifest ["config" ]["digest" ])
314
- downloader .download_blob (manifest ["config" ]["digest" ], config_output_path )
323
+ downloader .download_blob (manifest ["config" ]["digest" ], config_output_path , block = True )
315
324
config_bytes = rctx .read (config_output_path )
316
325
config = json .decode (config_bytes )
317
326
if "os" in config and "architecture" in config :
0 commit comments