Move some small daemon layering lookup into Rust
Prep for more oxidation work. One notable improvement here is that about half of the callers of the mega function `rpmostree_deployment_get_layered_info` only wanted the base information, not the layered package lists for example - so we were passing 4 `NULL`s to ignore those. This Rust API returns a simple shared struct instead for those cases. I also changed things so that `base_commit` is always set, avoiding the callers needing to do that.
This commit is contained in:
parent
3041d648bb
commit
e02fff3d5a
@ -4,7 +4,7 @@
|
||||
|
||||
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
|
||||
use crate::cxxrsutil::*;
|
||||
use crate::{cxxrsutil::*, variant_utils};
|
||||
use std::pin::Pin;
|
||||
|
||||
/// Get a currently unique (for this host) identifier for the
|
||||
@ -74,3 +74,54 @@ pub(crate) fn deployment_populate_variant(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Load basic layering metadata about a deployment commit.
|
||||
pub(crate) fn deployment_layeredmeta_from_commit(
|
||||
mut deployment: Pin<&mut crate::FFIOstreeDeployment>,
|
||||
mut commit: Pin<&mut crate::FFIGVariant>,
|
||||
) -> CxxResult<crate::ffi::DeploymentLayeredMeta> {
|
||||
let deployment = deployment.gobj_wrap();
|
||||
let commit = &commit.gobj_wrap();
|
||||
let metadata = &variant_utils::variant_tuple_get(commit, 0).expect("commit metadata");
|
||||
let dict = &glib::VariantDict::new(Some(metadata));
|
||||
|
||||
// More recent versions have an explicit clientlayer attribute (which
|
||||
// realistically will always be TRUE). For older versions, we just
|
||||
// rely on the treespec being present. */
|
||||
let is_layered = variant_utils::variant_dict_lookup_bool(dict, "rpmostree.clientlayer")
|
||||
.unwrap_or_else(|| dict.contains("rpmostree.spec"));
|
||||
if !is_layered {
|
||||
Ok(crate::ffi::DeploymentLayeredMeta {
|
||||
is_layered,
|
||||
base_commit: deployment.get_csum().unwrap().into(),
|
||||
clientlayer_version: 0,
|
||||
})
|
||||
} else {
|
||||
let base_commit = ostree::commit_get_parent(commit)
|
||||
.expect("commit parent")
|
||||
.into();
|
||||
let clientlayer_version = dict
|
||||
.lookup_value("rpmostree.clientlayer_version", Some(&*variant_utils::TY_U))
|
||||
.map(|u| u.get().unwrap())
|
||||
.unwrap_or_default();
|
||||
Ok(crate::ffi::DeploymentLayeredMeta {
|
||||
is_layered,
|
||||
base_commit,
|
||||
clientlayer_version,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Load basic layering metadata about a deployment
|
||||
pub(crate) fn deployment_layeredmeta_load(
|
||||
mut repo: Pin<&mut crate::FFIOstreeRepo>,
|
||||
mut deployment: Pin<&mut crate::FFIOstreeDeployment>,
|
||||
) -> CxxResult<crate::ffi::DeploymentLayeredMeta> {
|
||||
let repo = repo.gobj_wrap();
|
||||
let deployment = deployment.gobj_wrap();
|
||||
let commit = &repo.load_variant(
|
||||
ostree::ObjectType::Commit,
|
||||
deployment.get_csum().unwrap().as_str(),
|
||||
)?;
|
||||
deployment_layeredmeta_from_commit(deployment.gobj_rewrap(), commit.gobj_rewrap())
|
||||
}
|
||||
|
@ -90,6 +90,15 @@ pub mod ffi {
|
||||
fn compose_postprocess_final(rootfs_dfd: i32) -> Result<()>;
|
||||
}
|
||||
|
||||
// A grab-bag of metadata from the deployment's ostree commit
|
||||
// around layering/derivation
|
||||
#[derive(Default)]
|
||||
struct DeploymentLayeredMeta {
|
||||
is_layered: bool,
|
||||
base_commit: String,
|
||||
clientlayer_version: u32,
|
||||
}
|
||||
|
||||
// daemon.rs
|
||||
extern "Rust" {
|
||||
fn deployment_generate_id(deployment: Pin<&mut OstreeDeployment>) -> String;
|
||||
@ -98,6 +107,14 @@ pub mod ffi {
|
||||
mut deployment: Pin<&mut OstreeDeployment>,
|
||||
mut dict: Pin<&mut GVariantDict>,
|
||||
) -> Result<()>;
|
||||
fn deployment_layeredmeta_from_commit(
|
||||
mut deployment: Pin<&mut OstreeDeployment>,
|
||||
mut commit: Pin<&mut GVariant>,
|
||||
) -> Result<DeploymentLayeredMeta>;
|
||||
fn deployment_layeredmeta_load(
|
||||
mut repo: Pin<&mut OstreeRepo>,
|
||||
mut deployment: Pin<&mut OstreeDeployment>,
|
||||
) -> Result<DeploymentLayeredMeta>;
|
||||
}
|
||||
|
||||
// initramfs.rs
|
||||
|
@ -12,6 +12,9 @@ lazy_static::lazy_static! {
|
||||
pub(crate) static ref TY_B: &'static glib::VariantTy = {
|
||||
glib::VariantTy::new("b").unwrap()
|
||||
};
|
||||
pub(crate) static ref TY_U: &'static glib::VariantTy = {
|
||||
glib::VariantTy::new("u").unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn new_variant_tuple<'a>(
|
||||
|
@ -618,21 +618,14 @@ try_load_base_rsack_from_pending (RpmOstreeSysrootUpgrader *self,
|
||||
if (is_live)
|
||||
return TRUE;
|
||||
|
||||
guint layer_version;
|
||||
g_autofree char *base_rev_owned = NULL;
|
||||
if (!rpmostree_deployment_get_layered_info (self->repo, self->origin_merge_deployment,
|
||||
NULL, &layer_version, &base_rev_owned, NULL,
|
||||
NULL, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
auto repo = ostree_sysroot_repo(self->sysroot);
|
||||
auto layeredmeta = rpmostreecxx::deployment_layeredmeta_load(*repo, *self->origin_merge_deployment);
|
||||
/* older client layers have a bug blocking us from using their base rpmdb:
|
||||
* https://github.com/projectatomic/rpm-ostree/pull/1560 */
|
||||
if (base_rev_owned && layer_version < 4)
|
||||
if (layeredmeta.is_layered && layeredmeta.clientlayer_version < 4)
|
||||
return TRUE;
|
||||
|
||||
const char *base_rev =
|
||||
base_rev_owned ?: ostree_deployment_get_csum (self->origin_merge_deployment);
|
||||
|
||||
const char *base_rev = layeredmeta.base_commit.c_str();
|
||||
/* it's no longer the base layer we're looking for (e.g. likely pulled a fresh one) */
|
||||
if (!g_str_equal (self->base_revision, base_rev))
|
||||
return TRUE;
|
||||
|
@ -2583,12 +2583,8 @@ finalize_deployment_transaction_execute (RpmostreedTransaction *transaction,
|
||||
if (!g_str_equal (ostree_deployment_get_osname (default_deployment), self->osname))
|
||||
return glnx_throw (error, "Staged deployment is not for osname '%s'", self->osname);
|
||||
|
||||
gboolean is_layered = FALSE;
|
||||
g_autofree char *base_checksum = NULL;
|
||||
if (!rpmostree_deployment_get_layered_info (repo, default_deployment, &is_layered, NULL,
|
||||
&base_checksum, NULL, NULL, NULL, error))
|
||||
return FALSE;
|
||||
const char *checksum = base_checksum ?: ostree_deployment_get_csum (default_deployment);
|
||||
auto layeredmeta = rpmostreecxx::deployment_layeredmeta_load(*repo, *default_deployment);
|
||||
const char *checksum = layeredmeta.base_commit.c_str();
|
||||
|
||||
auto expected_checksum =
|
||||
(char*)vardict_lookup_ptr (self->options, "checksum", "&s");
|
||||
|
@ -520,36 +520,19 @@ rpmostree_deployment_get_layered_info (OstreeRepo *repo,
|
||||
if (!ostree_repo_load_commit (repo, csum, &commit, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
auto layeredmeta = rpmostreecxx::deployment_layeredmeta_from_commit(*deployment, *commit);
|
||||
|
||||
g_autoptr(GVariant) metadata = g_variant_get_child_value (commit, 0);
|
||||
g_autoptr(GVariantDict) dict = g_variant_dict_new (metadata);
|
||||
|
||||
/* More recent versions have an explicit clientlayer attribute (which
|
||||
* realistically will always be TRUE). For older versions, we just
|
||||
* rely on the treespec being present. */
|
||||
gboolean is_layered = FALSE;
|
||||
if (!g_variant_dict_lookup (dict, "rpmostree.clientlayer", "b", &is_layered))
|
||||
is_layered = g_variant_dict_contains (dict, "rpmostree.spec");
|
||||
|
||||
guint clientlayer_version = 0;
|
||||
g_variant_dict_lookup (dict, "rpmostree.clientlayer_version", "u",
|
||||
&clientlayer_version);
|
||||
|
||||
/* only fetch base if we have to */
|
||||
g_autofree char *base_layer = NULL;
|
||||
if (is_layered && out_base_layer != NULL)
|
||||
{
|
||||
base_layer = ostree_commit_get_parent (commit);
|
||||
g_assert (base_layer);
|
||||
}
|
||||
|
||||
/* only fetch pkgs if we have to */
|
||||
g_auto(GStrv) layered_pkgs = NULL;
|
||||
g_autoptr(GVariant) removed_base_pkgs = NULL;
|
||||
g_autoptr(GVariant) replaced_base_pkgs = NULL;
|
||||
if (is_layered && (out_layered_pkgs != NULL || out_removed_base_pkgs != NULL))
|
||||
if (layeredmeta.is_layered && (out_layered_pkgs != NULL || out_removed_base_pkgs != NULL))
|
||||
{
|
||||
/* starting from v1, we no longer embed a treespec in client layers */
|
||||
if (clientlayer_version >= 1)
|
||||
if (layeredmeta.clientlayer_version >= 1)
|
||||
{
|
||||
g_assert (g_variant_dict_lookup (dict, "rpmostree.packages", "^as",
|
||||
&layered_pkgs));
|
||||
@ -572,7 +555,7 @@ rpmostree_deployment_get_layered_info (OstreeRepo *repo,
|
||||
&layered_pkgs));
|
||||
}
|
||||
|
||||
if (clientlayer_version >= 2)
|
||||
if (layeredmeta.clientlayer_version >= 2)
|
||||
{
|
||||
removed_base_pkgs =
|
||||
g_variant_dict_lookup_value (dict, "rpmostree.removed-base-packages",
|
||||
@ -589,11 +572,11 @@ rpmostree_deployment_get_layered_info (OstreeRepo *repo,
|
||||
/* canonicalize outputs to empty array */
|
||||
|
||||
if (out_is_layered != NULL)
|
||||
*out_is_layered = is_layered;
|
||||
*out_is_layered = layeredmeta.is_layered;
|
||||
if (out_layer_version != NULL)
|
||||
*out_layer_version = clientlayer_version;
|
||||
if (out_base_layer != NULL)
|
||||
*out_base_layer = util::move_nullify (base_layer);
|
||||
*out_layer_version = layeredmeta.clientlayer_version;
|
||||
if (out_base_layer != NULL && layeredmeta.is_layered)
|
||||
*out_base_layer = util::ruststr_dup_c_optempty(layeredmeta.base_commit);
|
||||
if (out_layered_pkgs != NULL)
|
||||
{
|
||||
if (!layered_pkgs)
|
||||
|
Loading…
Reference in New Issue
Block a user