ostree/summary: Generate an ostree-metadata ref when updating summary
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 <withnall@endlessm.com> Closes: #1158 Approved by: cgwalters
This commit is contained in:
parent
16aa4d728a
commit
feeb3548f4
|
|
@ -83,7 +83,16 @@ Boston, MA 02111-1307, USA.
|
||||||
your organisation or repository using a dot prefix. The values
|
your organisation or repository using a dot prefix. The values
|
||||||
must be in GVariant text format. For example,
|
must be in GVariant text format. For example,
|
||||||
<command>exampleos.end-of-life "@t 1445385600"</command>.
|
<command>exampleos.end-of-life "@t 1445385600"</command>.
|
||||||
</para></listitem>
|
</para>
|
||||||
|
|
||||||
|
<!-- FIXME: Uncomment this when collection ID support becomes non-experimental.
|
||||||
|
<para>If the repository has a collection ID configured, the
|
||||||
|
<filename>ostree-metadata</filename> branch for that collection ID
|
||||||
|
will also be updated with a new commit containing the given metadata,
|
||||||
|
which will be signed if the summary file is signed.</para>
|
||||||
|
-->
|
||||||
|
|
||||||
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,97 @@ ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError
|
||||||
return FALSE;
|
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))
|
if (!ostree_repo_regenerate_summary (repo, additional_metadata, cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,4 +91,23 @@ ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata=map='@a{sv} {}'
|
||||||
${CMD_PREFIX} ostree --repo=repo summary --view > summary
|
${CMD_PREFIX} ostree --repo=repo summary --view > summary
|
||||||
assert_file_has_content summary "^map: {}$"
|
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"
|
echo "ok 2 update summary with collections"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue