diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index ae8abe81ae..aa74c839b8 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -268,6 +268,7 @@ OstreeLzmaDecompressorClass ostree-mutable-tree OstreeMutableTree ostree_mutable_tree_new +ostree_mutable_tree_new_from_commit ostree_mutable_tree_new_from_checksum ostree_mutable_tree_check_error ostree_mutable_tree_set_metadata_checksum diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 35d5395678..6b6b5c6c98 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -25,6 +25,7 @@ LIBOSTREE_2021.5 { global: ostree_sepolicy_new_from_commit; + ostree_mutable_tree_new_from_commit; } LIBOSTREE_2021.4; /* Stub section for the stable release *after* this development one; don't diff --git a/src/libostree/ostree-mutable-tree.c b/src/libostree/ostree-mutable-tree.c index 8509d1566d..bba3cf9153 100644 --- a/src/libostree/ostree-mutable-tree.c +++ b/src/libostree/ostree-mutable-tree.c @@ -681,3 +681,39 @@ ostree_mutable_tree_new_from_checksum (OstreeRepo *repo, out->metadata_checksum = g_strdup (metadata_checksum); return out; } + +/** + * ostree_mutable_tree_new_from_commit: + * @repo: The repo which contains the objects refered by the checksums. + * @rev: ref or SHA-256 checksum + * + * Creates a new OstreeMutableTree with the contents taken from the given commit. + * The data will be loaded from the repo lazily as needed. + * + * Returns: (transfer full): A new tree + * Since: 2021.5 + */ +OstreeMutableTree * +ostree_mutable_tree_new_from_commit (OstreeRepo *repo, + const char *rev, + GError **error) +{ + g_autofree char *commit = NULL; + if (!ostree_repo_resolve_rev (repo, rev, FALSE, &commit, error)) + return NULL; + g_autoptr(GVariant) commit_v = NULL; + if (!ostree_repo_load_commit (repo, commit, &commit_v, NULL, error)) + return NULL; + + g_autoptr(GVariant) contents_checksum_v = NULL; + g_autoptr(GVariant) metadata_checksum_v = NULL; + char contents_checksum[OSTREE_SHA256_STRING_LEN + 1]; + char metadata_checksum[OSTREE_SHA256_STRING_LEN + 1]; + g_variant_get_child (commit_v, 6, "@ay", &contents_checksum_v); + ostree_checksum_inplace_from_bytes (g_variant_get_data (contents_checksum_v), + contents_checksum); + g_variant_get_child (commit_v, 7, "@ay", &metadata_checksum_v); + ostree_checksum_inplace_from_bytes (g_variant_get_data (metadata_checksum_v), + metadata_checksum); + return ostree_mutable_tree_new_from_checksum (repo, contents_checksum, metadata_checksum); +} diff --git a/src/libostree/ostree-mutable-tree.h b/src/libostree/ostree-mutable-tree.h index 753f96e7f0..9bf368025f 100644 --- a/src/libostree/ostree-mutable-tree.h +++ b/src/libostree/ostree-mutable-tree.h @@ -52,6 +52,12 @@ GType ostree_mutable_tree_get_type (void) G_GNUC_CONST; _OSTREE_PUBLIC OstreeMutableTree *ostree_mutable_tree_new (void); +_OSTREE_PUBLIC +OstreeMutableTree * +ostree_mutable_tree_new_from_commit (OstreeRepo *repo, + const char *rev, + GError **error); + _OSTREE_PUBLIC OstreeMutableTree * ostree_mutable_tree_new_from_checksum (OstreeRepo *repo, const char *contents_checksum, diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index b993678e7e..a306c114bc 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -638,20 +638,14 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio if (opt_base) { - g_autofree char *base_commit = NULL; - g_autoptr(GFile) base_root = NULL; - if (!ostree_repo_read_commit (repo, opt_base, &base_root, &base_commit, cancellable, error)) + mtree = ostree_mutable_tree_new_from_commit (repo, opt_base, error); + if (!mtree) goto out; - OstreeRepoFile *rootf = (OstreeRepoFile*) base_root; - - mtree = ostree_mutable_tree_new_from_checksum (repo, - ostree_repo_file_tree_get_contents_checksum (rootf), - ostree_repo_file_tree_get_metadata_checksum (rootf)); if (opt_selinux_policy_from_base) { g_assert (modifier); - if (!ostree_repo_commit_modifier_set_sepolicy_from_commit (modifier, repo, base_commit, cancellable, error)) + if (!ostree_repo_commit_modifier_set_sepolicy_from_commit (modifier, repo, opt_base, cancellable, error)) goto out; /* Don't try to handle it twice */ opt_selinux_policy_from_base = FALSE;