Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions crates/ostree-ext/src/container/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,24 @@ fn cleanup_root(root: &Dir) -> Result<()> {
Ok(())
}

/// Copy `/usr` directory metadata to the root, matching the composefs-rs
/// approach since OCI images don't reliably include root dir metadata.
///
/// See:
/// - <https://github.com/coreos/fedora-coreos-tracker/issues/2238>
/// - <https://github.com/coreos/fedora-coreos-tracker/issues/2238#issuecomment-6082074286>
fn normalize_root_dirmeta(mt: &ostree::MutableTree) -> Result<()> {
let usr = mt.walk(&["usr"], 0).context("looking up /usr in mtree")?;

let usr_meta_checksum = usr.metadata_checksum();
if usr_meta_checksum.is_empty() {
anyhow::bail!("/usr has no metadata checksum in mtree");
}

mt.set_metadata_checksum(&usr_meta_checksum);
Ok(())
}

impl ImageImporter {
/// The metadata key used in ostree commit metadata to serialize
const CACHED_KEY_MANIFEST_DIGEST: &'static str = "ostree-ext.cached.manifest-digest";
Expand Down Expand Up @@ -1307,6 +1325,8 @@ impl ImageImporter {
)
.context("Writing merged filesystem to mtree")?;

normalize_root_dirmeta(&mt).context("normalizing root dir metadata on mtree")?;

let merged_root = repo
.write_mtree(&mt, cancellable)
.context("Writing mtree")?;
Expand Down
20 changes: 20 additions & 0 deletions crates/ostree-ext/tests/it/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ fn assert_err_contains<T>(r: Result<T>, s: impl AsRef<str>) {
}
}

/// Verify that a commit's root directory metadata matches `/usr`.
fn assert_root_dirmeta_matches_usr(repo: &ostree::Repo, commit: &str) {
let root = repo.read_commit(commit, gio::Cancellable::NONE).unwrap().0;
let root = root.downcast::<ostree::RepoFile>().unwrap();
root.ensure_resolved().unwrap();

let usr = root.resolve_relative_path("usr");
let usr = usr.downcast::<ostree::RepoFile>().unwrap();
usr.ensure_resolved().unwrap();

let root_meta_checksum = root.tree_get_metadata_checksum().unwrap();
let usr_meta_checksum = usr.tree_get_metadata_checksum().unwrap();
assert_eq!(
root_meta_checksum, usr_meta_checksum,
"root dir metadata checksum should match /usr"
);
}

static TEST_REGISTRY: LazyLock<String> =
LazyLock::new(|| match std::env::var_os("TEST_REGISTRY") {
Some(t) => t.to_str().unwrap().to_owned(),
Expand Down Expand Up @@ -707,6 +725,7 @@ async fn test_export_as_container_nonderived() -> Result<()> {
let reimported = fixture.must_import(&dest).await?;
let reimport_ls = fixture::ostree_ls(fixture.destrepo(), &reimported.merge_commit).unwrap();
similar_asserts::assert_eq!(initimport_ls, reimport_ls);
assert_root_dirmeta_matches_usr(fixture.destrepo(), &reimported.merge_commit);
Ok(())
}

Expand Down Expand Up @@ -1558,6 +1577,7 @@ async fn test_non_ostree() -> Result<()> {
similar_asserts::assert_eq!(&src_manifest, &dest_manifest);
}
assert_eq!(imp.manifest_digest, src_digest);
assert_root_dirmeta_matches_usr(fixture.destrepo(), &imp.merge_commit);
Ok(())
}

Expand Down
Loading