bootc icon indicating copy to clipboard operation
bootc copied to clipboard

copy-to-storage: Fails for non-ostree base image

Open cgwalters opened this issue 9 months ago • 1 comments

The bootc image copy-to-storage code currently requires the final-diffid from an ostree-container base.

Typed this up, but didn't test yet

diff --git a/ostree-ext/src/container/store.rs b/ostree-ext/src/container/store.rs
index 74500f36..bb6fee11 100644
--- a/ostree-ext/src/container/store.rs
+++ b/ostree-ext/src/container/store.rs
@@ -1401,13 +1401,7 @@ pub(crate) fn export_to_oci(
     let srcinfo = query_image(repo, imgref)?.ok_or_else(|| anyhow!("No such image"))?;
     let (commit_layer, component_layers, remaining_layers) =
         parse_manifest_layout(&srcinfo.manifest, &srcinfo.configuration)?;
-    let commit_layer = commit_layer.ok_or_else(|| anyhow!("Missing {DIFFID_LABEL}"))?;
-    let commit_chunk_ref = ref_for_layer(commit_layer)?;
-    let commit_chunk_rev = repo.require_rev(&commit_chunk_ref)?;
-    let mut chunking = chunking::Chunking::new(repo, &commit_chunk_rev)?;
-    for layer in component_layers {
-        chunking_from_layer_committed(repo, layer, &mut chunking)?;
-    }
+
     // Unfortunately today we can't guarantee we reserialize the same tar stream
     // or compression, so we'll need to generate a new copy of the manifest and config
     // with the layers reset.
@@ -1417,8 +1411,6 @@ pub(crate) fn export_to_oci(
     new_config.history_mut().clear();
     new_config.rootfs_mut().diff_ids_mut().clear();
 
-    let mut dest_oci = ocidir::OciDir::ensure(dest_oci)?;
-
     let opts = ExportOpts {
         skip_compression: opts.skip_compression,
         authfile: opts.authfile,
@@ -1427,19 +1419,36 @@ pub(crate) fn export_to_oci(
 
     let mut labels = HashMap::new();
 
-    // Given the object chunking information we recomputed from what
-    // we found on disk, re-serialize to layers (tarballs).
-    export_chunked(
-        repo,
-        &srcinfo.base_commit,
-        &mut dest_oci,
-        &mut new_manifest,
-        &mut new_config,
-        &mut labels,
-        chunking,
-        &opts,
-        "",
-    )?;
+    let mut dest_oci = ocidir::OciDir::ensure(dest_oci)?;
+
+    let commit_chunk_ref = commit_layer
+        .as_ref()
+        .map(|l| ref_for_layer(l))
+        .transpose()?;
+    let commit_chunk_rev = commit_chunk_ref
+        .as_ref()
+        .map(|r| repo.require_rev(&r))
+        .transpose()?;
+    if let Some(commit_chunk_rev) = commit_chunk_rev {
+        let mut chunking = chunking::Chunking::new(repo, &commit_chunk_rev)?;
+        for layer in component_layers {
+            chunking_from_layer_committed(repo, layer, &mut chunking)?;
+        }
+
+        // Given the object chunking information we recomputed from what
+        // we found on disk, re-serialize to layers (tarballs).
+        export_chunked(
+            repo,
+            &srcinfo.base_commit,
+            &mut dest_oci,
+            &mut new_manifest,
+            &mut new_config,
+            &mut labels,
+            chunking,
+            &opts,
+            "",
+        )?;
+    }
 
     // Now, handle the non-ostree layers; this is a simple conversion of
     //

cgwalters avatar Mar 24 '25 13:03 cgwalters

I tried /usr/libexec/bootc-base-imagectl rechunk on custom image, the chunked image does not have final-diffid issue when run bootc image copy-to-storage.

Does that mean custom image need rechunk? Thanks.

henrywang avatar May 20 '25 08:05 henrywang