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"