Skip to content

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

@cgwalters

Description

@cgwalters

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
     //

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/experimental-featureRelating to an experimental featurebugSomething isn't workingtriagedThis issue appears to be valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions