Skip to content

Commit 9b1e63f

Browse files
committed
composefs: Prep for new composefs-rs OCI APIs
Extract read_origin() helper from status.rs into state.rs for reuse in GC. Add local [patch] for composefs-rs development. Adapt export.rs to use OpenConfig struct from updated composefs-rs API. Assisted-by: OpenCode (Claude claude-opus-4-6)
1 parent 48124b0 commit 9b1e63f

5 files changed

Lines changed: 42 additions & 23 deletions

File tree

Cargo.lock

Lines changed: 12 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,6 @@ todo = "deny"
114114
needless_borrow = "allow"
115115
needless_borrows_for_generic_args = "allow"
116116

117+
[patch."https://github.com/composefs/composefs-rs"]
118+
cfsctl = { path = "/workspaces/composefs-rs/crates/cfsctl" }
119+

crates/lib/src/bootc_composefs/export.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ pub async fn export_repo_to_image(
5555
let oci_dir = OciDir::ensure(tmpdir.try_clone()?).context("Opening OCI")?;
5656

5757
// Use composefs_oci::open_config to get the config and layer map
58-
let (config, layer_map) =
59-
open_config(&*booted_cfs.repo, &config_digest, None).context("Opening config")?;
58+
let open = open_config(&*booted_cfs.repo, &config_digest, None).context("Opening config")?;
59+
let config = open.config;
60+
let layer_map = open.layer_refs;
6061

6162
// We can't guarantee that we'll get the same tar stream as the container image
6263
// So we create new config and manifest

crates/lib/src/bootc_composefs/state.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,27 @@ use crate::{
4444
utils::path_relative_to,
4545
};
4646

47+
/// Read and parse the `.origin` INI file for a deployment.
48+
///
49+
/// Returns `None` if the state directory or origin file doesn't exist
50+
/// (e.g. the deployment was partially deleted).
51+
#[context("Reading origin for deployment {deployment_id}")]
52+
pub(crate) fn read_origin(sysroot: &Dir, deployment_id: &str) -> Result<Option<tini::Ini>> {
53+
let depl_state_path = std::path::PathBuf::from(STATE_DIR_RELATIVE).join(deployment_id);
54+
55+
let Some(state_dir) = sysroot.open_dir_optional(&depl_state_path)? else {
56+
return Ok(None);
57+
};
58+
59+
let origin_filename = format!("{deployment_id}.origin");
60+
let Some(origin_contents) = state_dir.read_to_string_optional(&origin_filename)? else {
61+
return Ok(None);
62+
};
63+
64+
let ini = tini::Ini::from_string(&origin_contents).context("Failed to parse origin file")?;
65+
Ok(Some(ini))
66+
}
67+
4768
pub(crate) fn get_booted_bls(boot_dir: &Dir) -> Result<BLSConfig> {
4869
let cmdline = Cmdline::from_proc()?;
4970
let booted = cmdline

crates/lib/src/bootc_composefs/status.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
boot::BootType,
1212
repo::get_imgref,
1313
selinux::are_selinux_policies_compatible,
14-
state::get_composefs_usr_overlay_status,
14+
state::{get_composefs_usr_overlay_status, read_origin},
1515
utils::{compute_store_boot_digest_for_uki, get_uki_cmdline},
1616
},
1717
composefs_consts::{
@@ -699,11 +699,6 @@ async fn composefs_deployment_status_from(
699699
// This is our source of truth
700700
let bootloader_entry_verity = list_bootloader_entries(storage)?;
701701

702-
let state_dir = storage
703-
.physical_root
704-
.open_dir(STATE_DIR_RELATIVE)
705-
.with_context(|| format!("Opening {STATE_DIR_RELATIVE}"))?;
706-
707702
let host_spec = HostSpec {
708703
image: None,
709704
boot_order: BootOrder::Default,
@@ -732,15 +727,8 @@ async fn composefs_deployment_status_from(
732727
let mut extra_deployment_boot_entries: Vec<BootEntry> = Vec::new();
733728

734729
for verity_digest in bootloader_entry_verity {
735-
// read the origin file
736-
let config = state_dir
737-
.open_dir(&verity_digest)
738-
.with_context(|| format!("Failed to open {verity_digest}"))?
739-
.read_to_string(format!("{verity_digest}.origin"))
740-
.with_context(|| format!("Reading file {verity_digest}.origin"))?;
741-
742-
let ini = tini::Ini::from_string(&config)
743-
.with_context(|| format!("Failed to parse file {verity_digest}.origin as ini"))?;
730+
let ini = read_origin(&storage.physical_root, &verity_digest)?
731+
.ok_or_else(|| anyhow::anyhow!("No origin file for deployment {verity_digest}"))?;
744732

745733
let mut boot_entry =
746734
boot_entry_from_composefs_deployment(storage, ini, &verity_digest).await?;

0 commit comments

Comments
 (0)