apply-live: Move client-side finish to Rust

Now that we have an RPM diff+printing binding, we can
move the client side postprocessing for `apply-live`
to Rust.
This commit is contained in:
Colin Walters 2021-02-12 22:57:21 +00:00 committed by OpenShift Merge Robot
parent 04e0c4e01a
commit 246f02fd47
3 changed files with 51 additions and 44 deletions

View File

@ -199,6 +199,7 @@ pub mod ffi {
) -> Result<bool>;
// FIXME/cxx make this Option<&str>
fn transaction_apply_live(sysroot: Pin<&mut OstreeSysroot>, target: &str) -> Result<()>;
fn applylive_client_finish() -> Result<()>;
}
// passwd.rs
@ -271,7 +272,13 @@ pub mod ffi {
fn n_removed(&self) -> i32;
fn n_added(&self) -> i32;
fn n_modified(&self) -> i32;
fn rpmdb_diff(
repo: Pin<&mut OstreeRepo>,
src: &CxxString,
dest: &CxxString,
) -> Result<UniquePtr<RPMDiff>>;
fn print(&self);
}
unsafe extern "C++" {

View File

@ -340,6 +340,12 @@ fn rerun_tmpfiles() -> Result<()> {
Ok(())
}
fn require_booted_deployment(sysroot: &ostree::Sysroot) -> Result<ostree::Deployment> {
sysroot
.get_booted_deployment()
.ok_or_else(|| anyhow!("Not booted into an OSTree system"))
}
/// Implementation of `rpm-ostree ex apply-live`.
pub(crate) fn transaction_apply_live(
mut sysroot: Pin<&mut crate::ffi::OstreeSysroot>,
@ -353,11 +359,7 @@ pub(crate) fn transaction_apply_live(
};
let repo = &sysroot.repo().expect("repo");
let booted = if let Some(b) = sysroot.get_booted_deployment() {
b
} else {
return Err(anyhow!("Not booted into an OSTree system").into());
};
let booted = require_booted_deployment(sysroot)?;
let osname = booted.get_osname().expect("osname");
let booted_commit = booted.get_csum().expect("csum");
let booted_commit = booted_commit.as_str();
@ -482,6 +484,42 @@ pub(crate) fn transaction_apply_live(
Ok(())
}
pub(crate) fn applylive_client_finish() -> CxxResult<()> {
let cancellable = gio::NONE_CANCELLABLE;
let sysroot = &ostree::Sysroot::new_default();
sysroot.load(cancellable)?;
let repo = &sysroot.get_repo(cancellable)?;
let booted = &require_booted_deployment(sysroot)?;
let booted_commit = booted.get_csum().expect("csum");
let booted_commit = booted_commit.as_str();
let live_state = get_live_state(booted)?
.ok_or_else(|| anyhow!("Failed to find expected apply-live state"))?;
// It might happen that the live target commit was GC'd somehow; we're not writing
// an explicit ref for it. In that case skip the diff.
if !repo.has_object(
ostree::ObjectType::Commit,
live_state.commit.as_str(),
cancellable,
)? {
return Ok(());
}
let pkgdiff = {
cxx::let_cxx_string!(from = booted_commit);
cxx::let_cxx_string!(to = live_state.commit.as_str());
let repo = repo.gobj_rewrap();
crate::ffi::rpmdb_diff(repo, &from, &to).map_err(anyhow::Error::msg)?
};
pkgdiff.print();
crate::ffi::output_message(
"Successfully updated running filesystem tree; some services may need to be restarted.",
);
Ok(())
}
#[cfg(test)]
mod test {
use super::*;

View File

@ -112,45 +112,7 @@ rpmostree_ex_builtin_apply_live (int argc,
error))
return FALSE;
/* TODO - we compute all this client side right now for multiple reasons.
* - The diff printing code all lives on the client right now
* - We don't bind `rpmostree_output_message()` into Rust yet
* - We've historically accessed RPM diffs client side
*/
g_autoptr(OstreeSysroot) sysroot = ostree_sysroot_new_default ();
if (!ostree_sysroot_load (sysroot, cancellable, error))
return FALSE;
g_autoptr(OstreeRepo) repo = NULL;
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
return FALSE;
OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
g_assert (booted_deployment);
const char *booted_commit = ostree_deployment_get_csum (booted_deployment);
auto live_state = rpmostreecxx::get_live_apply_state(*sysroot, *booted_deployment);
g_assert (live_state.commit.length() > 0);
gboolean have_target = FALSE;
if (!ostree_repo_has_object (repo, OSTREE_OBJECT_TYPE_COMMIT, live_state.commit.c_str(), &have_target, NULL, error))
return FALSE;
/* It might happen that the live target commit was GC'd somehow; we're not writing
* an explicit ref for it. In that case skip the diff.
*/
if (have_target)
{
g_autoptr(GPtrArray) removed = NULL;
g_autoptr(GPtrArray) added = NULL;
g_autoptr(GPtrArray) modified_old = NULL;
g_autoptr(GPtrArray) modified_new = NULL;
if (!rpm_ostree_db_diff (repo, booted_commit, live_state.commit.c_str(),
&removed, &added, &modified_old, &modified_new,
cancellable, error))
return FALSE;
rpmostree_diff_print_formatted (RPMOSTREE_DIFF_PRINT_FORMAT_FULL_MULTILINE, NULL, 0,
removed, added, modified_old, modified_new);
}
g_print ("Successfully updated running filesystem tree; some services may need to be restarted.\n");
rpmostreecxx::applylive_client_finish();
return TRUE;
}