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:
parent
04e0c4e01a
commit
246f02fd47
@ -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++" {
|
||||
|
@ -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::*;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user