bin/commit: add --keep-metadata option

Clients of libostree such as rpm-ostree make extensive use of the
`ostree commit -b foo --tree=ref=foo` pattern in their tests, e.g. to
simulate an update.

What I'm trying to solve here is that it's often the case that we want
to keep metadata from the previous commit without having to be too
verbose (i.e. reading from the parent, then passing it as an argument).

The new `--keep-metadata` switch makes this really easy. I intend to use
this in the rpm-ostree testsuite to make sure we always carry over the
`source-title` metadata as well as during set up for tests that require
`rpmostree.rpmdb.pkglist` metadata.

I initially implemented this in a small wrapper script that uses the API
directly, though we make use of so many other `ostree commit` functions
that it'd require re-implementing a lot of it.

Closes: #1402
Approved by: cgwalters
This commit is contained in:
Jonathan Lebon 2018-01-09 20:29:22 +00:00 committed by Atomic Bot
parent 95e574d09b
commit 939791b4fa
3 changed files with 50 additions and 2 deletions

View File

@ -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

View File

@ -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));
}

View File

@ -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'