MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / write_image_layout

Function write_image_layout

atomic-repository/src/oci.rs:177–262  ·  view source on GitHub ↗

Write a complete OCI image layout under `out` (created if needed): `out/oci-layout`, `out/index.json`, and `out/blobs/sha256/<...>` blobs. `layers` are ordered base→top. Returns the manifest digest (`"sha256:..."`). The image config records the layers' uncompressed `diff_id`s; the manifest records the gzipped layer digests; `config.annotations` are passed through to the manifest.

(
    out: &Path,
    layers: &[OciLayer],
    config: &OciImageConfig,
)

Source from the content-addressed store, hash-verified

175/// records the gzipped layer digests; `config.annotations` are passed through to
176/// the manifest.
177pub fn write_image_layout(
178 out: &Path,
179 layers: &[OciLayer],
180 config: &OciImageConfig,
181) -> std::io::Result<String> {
182 let blobs = out.join("blobs").join("sha256");
183 std::fs::create_dir_all(&blobs)?;
184
185 // Image config blob. diff_ids are the UNCOMPRESSED layer digests.
186 let diff_ids: Vec<String> = layers.iter().map(|l| l.diff_id.clone()).collect();
187 let history: Vec<serde_json::Value> = layers
188 .iter()
189 .map(|_| serde_json::json!({ "created_by": "atomic sandbox" }))
190 .collect();
191 let config_json = serde_json::json!({
192 "architecture": config.architecture,
193 "os": config.os,
194 "config": {
195 "Env": config.env,
196 "Entrypoint": config.entrypoint,
197 },
198 "rootfs": {
199 "type": "layers",
200 "diff_ids": diff_ids,
201 },
202 "history": history,
203 });
204 let config_bytes = json_to_vec(&config_json)?;
205 let config_hex = sha256_hex(&config_bytes);
206 std::fs::write(blobs.join(&config_hex), &config_bytes)?;
207 let config_digest = format!("sha256:{config_hex}");
208
209 // Layer blobs (the gzipped bytes), keyed by their gzipped digest.
210 for layer in layers {
211 std::fs::write(blobs.join(digest_hex(&layer.digest)), &layer.tar_gz)?;
212 }
213
214 // Manifest blob. Layer digests here are the GZIPPED digests.
215 let manifest_layers: Vec<serde_json::Value> = layers
216 .iter()
217 .map(|l| {
218 serde_json::json!({
219 "mediaType": MEDIA_TYPE_LAYER,
220 "digest": l.digest,
221 "size": l.size,
222 })
223 })
224 .collect();
225 let manifest_json = serde_json::json!({
226 "schemaVersion": 2,
227 "mediaType": MEDIA_TYPE_MANIFEST,
228 "config": {
229 "mediaType": MEDIA_TYPE_CONFIG,
230 "digest": config_digest,
231 "size": config_bytes.len(),
232 },
233 "layers": manifest_layers,
234 "annotations": config.annotations,

Callers 3

stageMethod · 0.85
sealMethod · 0.85

Calls 6

json_to_vecFunction · 0.85
sha256_hexFunction · 0.85
writeFunction · 0.85
digest_hexFunction · 0.85
iterMethod · 0.45
cloneMethod · 0.45