From feeb3548f4e00fb60481f9105c68e4f2322ab92a Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 11 Sep 2017 14:42:52 +0100 Subject: [PATCH] ostree/summary: Generate an ostree-metadata ref when updating summary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the new way of publishing repository metadata, rather than as additional-metadata in the summary file. The use of an ostree-metadata ref means that the metadata from multiple upstream collections is not conflated when doing P2P mirroring of many repositories. The new ref is only generated if the repository has a collection ID set. The old summary file continues to be generated for backwards compatibility (and because it continues to be the canonical ref → checksum map for the repository). The new code is only used if configured with --enable-experimental-api. Includes unit tests. Signed-off-by: Philip Withnall Closes: #1158 Approved by: cgwalters --- man/ostree-summary.xml | 11 +++- src/ostree/ot-builtin-summary.c | 91 +++++++++++++++++++++++++++++++++ tests/test-summary-update.sh | 19 +++++++ 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/man/ostree-summary.xml b/man/ostree-summary.xml index dd72a6ea..815d2b5a 100644 --- a/man/ostree-summary.xml +++ b/man/ostree-summary.xml @@ -83,7 +83,16 @@ Boston, MA 02111-1307, USA. your organisation or repository using a dot prefix. The values must be in GVariant text format. For example, exampleos.end-of-life "@t 1445385600". - + + + + + diff --git a/src/ostree/ot-builtin-summary.c b/src/ostree/ot-builtin-summary.c index 9d04753d..abd1f86c 100644 --- a/src/ostree/ot-builtin-summary.c +++ b/src/ostree/ot-builtin-summary.c @@ -106,6 +106,97 @@ ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError return FALSE; } +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + const char *collection_id = ostree_repo_get_collection_id (repo); +#else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ + const char *collection_id = NULL; +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + + /* Write out a new metadata commit for the repository. */ + if (collection_id != NULL) + { +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + OstreeCollectionRef collection_ref = { (gchar *) collection_id, (gchar *) OSTREE_REPO_METADATA_REF }; + g_autofree char *old_ostree_metadata_checksum = NULL; + g_autofree gchar *new_ostree_metadata_checksum = NULL; + g_autoptr(OstreeMutableTree) mtree = NULL; + g_autoptr(OstreeRepoFile) repo_file = NULL; + g_autoptr(GVariantDict) new_summary_commit_dict = NULL; + g_autoptr(GVariant) new_summary_commit = NULL; + + if (!ostree_repo_resolve_rev (repo, OSTREE_REPO_METADATA_REF, + TRUE, &old_ostree_metadata_checksum, error)) + return FALSE; + + /* Add bindings to the metadata. */ + new_summary_commit_dict = g_variant_dict_new (additional_metadata); + g_variant_dict_insert (new_summary_commit_dict, OSTREE_COMMIT_META_KEY_COLLECTION_BINDING, + "s", collection_ref.collection_id); + g_variant_dict_insert_value (new_summary_commit_dict, OSTREE_COMMIT_META_KEY_REF_BINDING, + g_variant_new_strv ((const gchar * const *) &collection_ref.ref_name, 1)); + new_summary_commit = g_variant_dict_end (new_summary_commit_dict); + + if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) + return FALSE; + + /* Set up an empty mtree. */ + mtree = ostree_mutable_tree_new (); + + glnx_unref_object GFileInfo *fi = g_file_info_new (); + g_file_info_set_attribute_uint32 (fi, "unix::uid", 0); + g_file_info_set_attribute_uint32 (fi, "unix::gid", 0); + g_file_info_set_attribute_uint32 (fi, "unix::mode", (0755 | S_IFDIR)); + + g_autofree guchar *csum_raw = NULL; + g_autofree char *csum = NULL; + + g_autoptr(GVariant) dirmeta = ostree_create_directory_metadata (fi, NULL /* xattrs */); + + if (!ostree_repo_write_metadata (repo, OSTREE_OBJECT_TYPE_DIR_META, NULL, + dirmeta, &csum_raw, cancellable, error)) + return FALSE; + + csum = ostree_checksum_from_bytes (csum_raw); + ostree_mutable_tree_set_metadata_checksum (mtree, csum); + + if (!ostree_repo_write_mtree (repo, mtree, (GFile **) &repo_file, NULL, error)) + return FALSE; + + if (!ostree_repo_write_commit (repo, old_ostree_metadata_checksum, + NULL /* subject */, NULL /* body */, + new_summary_commit, repo_file, &new_ostree_metadata_checksum, + NULL, error)) + return FALSE; + + if (opt_key_ids != NULL) + { + for (const char * const *iter = (const char * const *) opt_key_ids; + iter != NULL && *iter != NULL; iter++) + { + const char *key_id = *iter; + + if (!ostree_repo_sign_commit (repo, + new_ostree_metadata_checksum, + key_id, + opt_gpg_homedir, + cancellable, + error)) + return FALSE; + } + } + + ostree_repo_transaction_set_collection_ref (repo, &collection_ref, + new_ostree_metadata_checksum); + + if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error)) + return FALSE; +#else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ + g_assert_not_reached (); + return FALSE; +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + } + + /* Regenerate and sign the conventional summary file. */ if (!ostree_repo_regenerate_summary (repo, additional_metadata, cancellable, error)) return FALSE; diff --git a/tests/test-summary-update.sh b/tests/test-summary-update.sh index 457debbe..60228114 100755 --- a/tests/test-summary-update.sh +++ b/tests/test-summary-update.sh @@ -91,4 +91,23 @@ ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata=map='@a{sv} {}' ${CMD_PREFIX} ostree --repo=repo summary --view > summary assert_file_has_content summary "^map: {}$" +# Check the ostree-metadata ref has also been created with the same content and appropriate bindings. +${CMD_PREFIX} ostree --repo=repo refs --collections > refs +assert_file_has_content refs "^(org.example.Collection1, ostree-metadata)$" + +${CMD_PREFIX} ostree --repo=repo show ostree-metadata --raw > metadata +assert_file_has_content metadata "'map': <@a{sv} {}>" +assert_file_has_content metadata "'ostree.ref-binding': <\['ostree-metadata'\]>" +assert_file_has_content metadata "'ostree.collection-binding': <'org.example.Collection1'>" + +# There should be 5 commits in the ostree-metadata branch, since we’ve updated the summary 5 times. +${CMD_PREFIX} ostree --repo=repo log ostree-metadata | grep 'commit ' | wc -l > commit-count +assert_file_has_content commit-count "^5$" + +# The ostree-metadata commits should not contain any files +${CMD_PREFIX} ostree --repo=repo ls ostree-metadata > files +assert_file_has_content files " /$" +cat files | wc -l > files-count +assert_file_has_content files-count "^1$" + echo "ok 2 update summary with collections"