diff --git a/bash/ostree b/bash/ostree index 0ba135e7..a6eb56de 100644 --- a/bash/ostree +++ b/bash/ostree @@ -783,6 +783,7 @@ _ostree_commit() { local options_with_args=" --add-detached-metadata-string --add-metadata-string + --keep-metadata --bind-ref --body -m --body-file -F diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 842d07d1..5e5cddd1 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -45,6 +45,7 @@ static char *opt_skiplist_file; static char **opt_metadata_strings; static char **opt_metadata_variants; static char **opt_detached_metadata_strings; +static char **opt_metadata_keep; static gboolean opt_link_checkout_speedup; static gboolean opt_skip_if_unchanged; static gboolean opt_tar_autocreate_parents; @@ -96,6 +97,7 @@ static GOptionEntry options[] = { { "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_trees, "Overlay the given argument as a tree", "dir=PATH or tar=TARFILE or ref=COMMIT" }, { "add-metadata-string", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_metadata_strings, "Add a key/value pair to metadata", "KEY=VALUE" }, { "add-metadata", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_metadata_variants, "Add a key/value pair to metadata, where the KEY is a string, an VALUE is g_variant_parse() formatted", "KEY=VALUE" }, + { "keep-metadata", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_metadata_keep, "Keep metadata KEY and its associated VALUE from parent", "KEY" }, { "add-detached-metadata-string", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_detached_metadata_strings, "Add a key/value pair to detached metadata", "KEY=VALUE" }, { "owner-uid", 0, 0, G_OPTION_ARG_INT, &opt_owner_uid, "Set file ownership user id", "UID" }, { "owner-gid", 0, 0, G_OPTION_ARG_INT, &opt_owner_gid, "Set file ownership group id", "GID" }, @@ -498,7 +500,15 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio } } - if (opt_metadata_strings || opt_metadata_variants) + if (!parent && opt_metadata_keep) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Either --branch or --parent must be specified when using " + "--keep-metadata"); + goto out; + } + + if (opt_metadata_strings || opt_metadata_variants || opt_metadata_keep) { g_autoptr(GVariantBuilder) builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); @@ -511,6 +521,31 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio !parse_keyvalue_strings (builder, opt_metadata_variants, TRUE, error)) goto out; + if (opt_metadata_keep) + { + g_assert (parent); + + g_autoptr(GVariant) parent_commit = NULL; + if (!ostree_repo_load_commit (repo, parent, &parent_commit, NULL, error)) + goto out; + + g_auto(GVariantDict) dict; + g_variant_dict_init (&dict, g_variant_get_child_value (parent_commit, 0)); + for (char **keyp = opt_metadata_keep; keyp && *keyp; keyp++) + { + const char *key = *keyp; + g_autoptr(GVariant) val = g_variant_dict_lookup_value (&dict, key, NULL); + if (!val) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Missing metadata key '%s' from commit '%s'", key, parent); + goto out; + } + + g_variant_builder_add (builder, "{sv}", key, val); + } + } + metadata = g_variant_ref_sink (g_variant_builder_end (builder)); } diff --git a/tests/basic-test.sh b/tests/basic-test.sh index c4eb9cad..9c8771e5 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -19,7 +19,7 @@ set -euo pipefail -echo "1..$((78 + ${extra_basic_tests:-0}))" +echo "1..$((79 + ${extra_basic_tests:-0}))" CHECKOUT_U_ARG="" CHECKOUT_H_ARGS="-H" @@ -779,6 +779,18 @@ $OSTREE show --print-detached-metadata-key=SIGNATURE test2 > test2-meta assert_file_has_content test2-meta "HANCOCK" echo "ok metadata commit with strings" +$OSTREE commit ${COMMIT_ARGS} -b test2 --tree=ref=test2 \ + --add-detached-metadata-string=SIGNATURE=HANCOCK \ + --keep-metadata=KITTENS --keep-metadata=SOMENUM +if $OSTREE show --print-metadata-key=FOO test2; then + assert_not_reached "FOO was kept without explicit --keep-metadata?" +fi +$OSTREE show --print-metadata-key=KITTENS test2 > test2-meta +assert_file_has_content test2-meta "CUTE" +$OSTREE show -B --print-metadata-key=SOMENUM test2 > test2-meta +assert_file_has_content test2-meta "uint64 42" +echo "ok keep metadata from parent" + cd ${test_tmpdir} $OSTREE show --print-metadata-key=ostree.ref-binding test2 > test2-ref-binding assert_file_has_content test2-ref-binding 'test2'