diff --git a/rust/src/daemon.rs b/rust/src/daemon.rs index 30d3e90f31..19e481cedf 100644 --- a/rust/src/daemon.rs +++ b/rust/src/daemon.rs @@ -42,22 +42,6 @@ pub(crate) fn daemon_sanitycheck_environment( Ok(()) } -/// Get a currently unique (for this host) identifier for the -/// deployment; TODO - adding the deployment timestamp would make it -/// persistently unique, needs API in libostree. -pub(crate) fn deployment_generate_id( - mut deployment: Pin<&mut crate::FFIOstreeDeployment>, -) -> String { - let deployment = deployment.gobj_wrap(); - // unwrap safety: These can't actually return NULL - format!( - "{}-{}.{}", - deployment.osname().unwrap(), - deployment.csum().unwrap(), - deployment.deployserial() - ) -} - /// Insert values from `v` into the target `dict` with key `k`. fn vdict_insert_strv<'a>(dict: &glib::VariantDict, k: &str, v: impl IntoIterator) { // TODO: drive this into variant_utils in ostree-rs-ext so we don't need @@ -150,7 +134,7 @@ pub(crate) fn deployment_populate_variant( let deployment = &deployment.gobj_wrap(); let dict = dict.gobj_wrap(); - let id = deployment_generate_id(deployment.gobj_rewrap()); + let id = crate::deployment_generate_id_impl(deployment); // First, basic values from ostree dict.insert("id", &id); diff --git a/rust/src/deployment_utils.rs b/rust/src/deployment_utils.rs new file mode 100644 index 0000000000..d7192476fc --- /dev/null +++ b/rust/src/deployment_utils.rs @@ -0,0 +1,98 @@ +//! Helper logic for handling deployments. + +// SPDX-License-Identifier: Apache-2.0 OR MIT + +use crate::cxxrsutil::*; +use anyhow::{anyhow, format_err, Result}; +use ostree_ext::glib::translate::*; +use ostree_ext::ostree; +use std::pin::Pin; + +/// Get a currently unique (for this host) identifier for the deployment. +// TODO - adding the deployment timestamp would make it +// persistently unique, needs API in libostree. +pub fn deployment_generate_id(mut deployment: Pin<&mut crate::FFIOstreeDeployment>) -> String { + let deployment = deployment.gobj_wrap(); + deployment_generate_id_impl(&deployment) +} + +pub(crate) fn deployment_generate_id_impl(deployment: &ostree::Deployment) -> String { + // SAFETY: the results of these are not-nullable in the C API. + format!( + "{}-{}.{}", + deployment.osname().unwrap(), + deployment.csum().unwrap(), + deployment.deployserial() + ) +} + +pub fn deployment_for_id( + mut ffi_sysroot: Pin<&mut crate::ffi::OstreeSysroot>, + deploy_id: &str, +) -> CxxResult<*mut crate::FFIOstreeDeployment> { + let sysroot = &ffi_sysroot.gobj_wrap(); + + let deployment = deployment_for_id_impl(sysroot, deploy_id)?; + + let depl_ptr: *mut ostree::ffi::OstreeDeployment = deployment.to_glib_full(); + Ok(depl_ptr as *mut _) +} + +fn deployment_for_id_impl( + sysroot: &ostree::Sysroot, + deploy_id: &str, +) -> Result { + if deploy_id.is_empty() { + return Err(anyhow!("empty deployment ID")); + } + + for depl_entry in sysroot.deployments() { + let id = deployment_generate_id_impl(&depl_entry); + if deploy_id == id { + return Ok(depl_entry); + } + } + + Err(anyhow!("Deployment with id '{}' not found", deploy_id)) +} + +pub fn deployment_checksum_for_id( + mut ffi_sysroot: Pin<&mut crate::ffi::OstreeSysroot>, + deploy_id: &str, +) -> CxxResult { + let sysroot = &ffi_sysroot.gobj_wrap(); + + let deployment = deployment_for_id_impl(&sysroot, deploy_id)?; + // SAFETY: result is not-nullable in the C API. + let csum = deployment.csum().unwrap(); + Ok(csum.to_string()) +} + +pub fn deployment_get_base( + mut ffi_sysroot: Pin<&mut crate::ffi::OstreeSysroot>, + opt_deploy_id: &str, + opt_os_name: &str, +) -> CxxResult<*mut crate::FFIOstreeDeployment> { + let sysroot = &ffi_sysroot.gobj_wrap(); + let deploy_id = opt_string(opt_deploy_id); + let os_name = opt_string(opt_os_name); + + let deployment = deployment_get_base_impl(&sysroot, deploy_id, os_name)?; + + let depl_ptr: *mut ostree::ffi::OstreeDeployment = deployment.to_glib_full(); + Ok(depl_ptr as *mut _) +} + +fn deployment_get_base_impl( + sysroot: &ostree::Sysroot, + deploy_id: Option<&str>, + os_name: Option<&str>, +) -> Result { + match deploy_id { + Some(id) => deployment_for_id_impl(sysroot, id), + None => sysroot.merge_deployment(os_name).ok_or_else(|| { + let name = os_name.unwrap_or_default(); + format_err!("No deployments found for os '{}'", name) + }), + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 4ebe888f77..ff4ef81a29 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -225,6 +225,24 @@ pub mod ffi { fn directory_size(dfd: i32, mut cancellable: Pin<&mut GCancellable>) -> Result; } + // deployment_utils.rs + extern "Rust" { + fn deployment_for_id( + sysroot: Pin<&mut OstreeSysroot>, + deploy_id: &str, + ) -> Result<*mut OstreeDeployment>; + fn deployment_checksum_for_id( + sysroot: Pin<&mut OstreeSysroot>, + deploy_id: &str, + ) -> Result; + fn deployment_get_base( + sysroot: Pin<&mut OstreeSysroot>, + opt_deploy_id: &str, + opt_os_name: &str, + ) -> Result<*mut OstreeDeployment>; + + } + // A grab-bag of metadata from the deployment's ostree commit // around layering/derivation #[derive(Debug, Default)] @@ -718,9 +736,11 @@ mod core; use crate::core::*; mod capstdext; mod daemon; +pub(crate) use daemon::*; +mod deployment_utils; +pub(crate) use deployment_utils::*; mod dirdiff; pub mod failpoint_bridge; -pub(crate) use daemon::*; use failpoint_bridge::*; mod extensions; pub(crate) use extensions::*; diff --git a/src/daemon/rpmostreed-deployment-utils.cxx b/src/daemon/rpmostreed-deployment-utils.cxx index cff6f3a256..c7ab46457e 100644 --- a/src/daemon/rpmostreed-deployment-utils.cxx +++ b/src/daemon/rpmostreed-deployment-utils.cxx @@ -33,25 +33,6 @@ #include "rpmostreed-errors.h" #include "rpmostreed-utils.h" -gboolean -rpmostreed_deployment_get_for_id (OstreeSysroot *sysroot, const gchar *deploy_id, - OstreeDeployment **out_deployment, GError **error) -{ - g_autoptr (GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot); - for (guint i = 0; i < deployments->len; i++) - { - auto deployment = static_cast (deployments->pdata[i]); - auto id = rpmostreecxx::deployment_generate_id (*deployment); - if (g_strcmp0 (deploy_id, id.c_str ()) == 0) - { - *out_deployment = (OstreeDeployment *)g_object_ref (deployment); - return TRUE; - } - } - - return glnx_throw (error, "Deployment with id '%s' not found", deploy_id); -} - /* rpmostreed_deployment_get_for_index: * * sysroot: A #OstreeSysroot instance diff --git a/src/daemon/rpmostreed-deployment-utils.h b/src/daemon/rpmostreed-deployment-utils.h index 3d2fa63fad..bc9a40f2b3 100644 --- a/src/daemon/rpmostreed-deployment-utils.h +++ b/src/daemon/rpmostreed-deployment-utils.h @@ -27,9 +27,6 @@ G_BEGIN_DECLS char *rpmostreed_deployment_generate_id (OstreeDeployment *deployment); -gboolean rpmostreed_deployment_get_for_id (OstreeSysroot *sysroot, const gchar *deploy_id, - OstreeDeployment **out_deployment, GError **error); - OstreeDeployment *rpmostreed_deployment_get_for_index (OstreeSysroot *sysroot, const gchar *index, GError **error); diff --git a/src/daemon/rpmostreed-os.cxx b/src/daemon/rpmostreed-os.cxx index fdb27e3a2b..abd324da39 100644 --- a/src/daemon/rpmostreed-os.cxx +++ b/src/daemon/rpmostreed-os.cxx @@ -339,28 +339,23 @@ get_deployments_rpm_diff (const char *arg_deployid0, const char *arg_deployid1, { g_autoptr (GCancellable) cancellable = NULL; RpmostreedSysroot *global_sysroot; - glnx_unref_object OstreeDeployment *deployment0 = NULL; - glnx_unref_object OstreeDeployment *deployment1 = NULL; OstreeSysroot *ot_sysroot = NULL; OstreeRepo *ot_repo = NULL; g_autoptr (GVariant) value = NULL; - const gchar *ref0; - const gchar *ref1; global_sysroot = rpmostreed_sysroot_get (); ot_sysroot = rpmostreed_sysroot_get_root (global_sysroot); ot_repo = rpmostreed_sysroot_get_repo (global_sysroot); - if (!rpmostreed_deployment_get_for_id (ot_sysroot, arg_deployid0, &deployment0, error)) - return FALSE; - ref0 = ostree_deployment_get_csum (deployment0); + rust::Str deploy_id0 (arg_deployid0 ?: ""); + auto ref0 = ROSCXX_TRY_VAL (deployment_checksum_for_id (*ot_sysroot, deploy_id0), error); - if (!rpmostreed_deployment_get_for_id (ot_sysroot, arg_deployid1, &deployment1, error)) - return FALSE; - ref1 = ostree_deployment_get_csum (deployment1); + rust::Str deploy_id1 (arg_deployid1 ?: ""); + auto ref1 = ROSCXX_TRY_VAL (deployment_checksum_for_id (*ot_sysroot, deploy_id1), error); - if (!rpm_ostree_db_diff_variant (ot_repo, ref0, ref1, FALSE, &value, cancellable, error)) + if (!rpm_ostree_db_diff_variant (ot_repo, ref0.c_str (), ref1.c_str (), FALSE, &value, + cancellable, error)) return FALSE; *out_value = util::move_nullify (value); @@ -406,17 +401,9 @@ get_cached_update_rpm_diff (const gchar *name, const char *arg_deployid, GVarian ot_sysroot = rpmostreed_sysroot_get_root (global_sysroot); ot_repo = rpmostreed_sysroot_get_repo (global_sysroot); - if (arg_deployid == NULL || arg_deployid[0] == '\0') - { - base_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name); - if (base_deployment == NULL) - return glnx_throw (error, "No deployments found for os %s", name); - } - else - { - if (!rpmostreed_deployment_get_for_id (ot_sysroot, arg_deployid, &base_deployment, error)) - return FALSE; - } + rust::Str os_name (name ?: ""); + rust::Str deploy_id (arg_deployid ?: ""); + base_deployment = ROSCXX_TRY_VAL (deployment_get_base (*ot_sysroot, deploy_id, os_name), error); origin = rpmostree_origin_parse_deployment (base_deployment, error); if (!origin)