diff --git a/man/ostree-commit.xml b/man/ostree-commit.xml index 2c821fc1..b0c5b335 100644 --- a/man/ostree-commit.xml +++ b/man/ostree-commit.xml @@ -106,6 +106,15 @@ Boston, MA 02111-1307, USA. + + ="REV" + + + Start from the content in a commit. This differs from --tree=ref=REV in that no commit modifiers are applied. This is usually what you want when + creating a derived commit. This is also used for --selinux-policy-from-base. + + + ="KEY=VALUE" diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 606af2be..72fa2841 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -58,6 +58,7 @@ static gboolean opt_selinux_policy_from_base; static gboolean opt_canonical_permissions; static gboolean opt_consume; static gboolean opt_devino_canonical; +static char *opt_base; static char **opt_trees; static gint opt_owner_uid = -1; static gint opt_owner_gid = -1; @@ -101,6 +102,7 @@ static GOptionEntry options[] = { { "orphan", 0, 0, G_OPTION_ARG_NONE, &opt_orphan, "Create a commit without writing a ref", NULL }, { "no-bindings", 0, 0, G_OPTION_ARG_NONE, &opt_no_bindings, "Do not write any ref bindings", NULL }, { "bind-ref", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_bind_refs, "Add a ref to ref binding commit metadata", "BRANCH" }, + { "base", 0, 0, G_OPTION_ARG_STRING, &opt_base, "Start from the given commit as a base (no modifiers apply)" }, { "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" }, @@ -600,7 +602,32 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio if (opt_link_checkout_speedup && !ostree_repo_scan_hardlinks (repo, cancellable, error)) goto out; - mtree = ostree_mutable_tree_new (); + if (opt_base) + { + g_autofree char *base_commit = NULL; + g_autoptr(GFile) root = NULL; + if (!ostree_repo_read_commit (repo, opt_base, &root, &base_commit, cancellable, error)) + goto out; + OstreeRepoFile *rootf = (OstreeRepoFile*) root; + + mtree = ostree_mutable_tree_new_from_checksum (repo, + ostree_repo_file_tree_get_contents_checksum (rootf), + ostree_repo_file_tree_get_metadata_checksum (rootf)); + + if (opt_selinux_policy_from_base) + { + g_assert (modifier); + if (!ostree_repo_commit_modifier_set_sepolicy_from_commit (modifier, repo, base_commit, cancellable, error)) + goto out; + /* Don't try to handle it twice */ + opt_selinux_policy_from_base = FALSE; + } + } + else + { + mtree = ostree_mutable_tree_new (); + } + /* Convert implicit . or explicit path via argv into * --tree=dir= so that we only have one primary code path below. diff --git a/tests/archive-test.sh b/tests/archive-test.sh index 42b232bf..1e63a35b 100644 --- a/tests/archive-test.sh +++ b/tests/archive-test.sh @@ -68,3 +68,11 @@ echo "ok cat-file" cd ${test_tmpdir} $OSTREE fsck echo "ok fsck" + +mkdir -p test-overlays +date > test-overlays/overlaid-file +$OSTREE commit ${COMMIT_ARGS} -b test-base --base test2 --owner-uid 42 --owner-gid 42 test-overlays/ +$OSTREE ls -R test-base > ls.txt +assert_streq "$(wc -l < ls.txt)" 14 +assert_streq "$(grep '42.*42' ls.txt | wc -l)" 2 +echo "ok commit overlay base" diff --git a/tests/test-archivez.sh b/tests/test-archivez.sh index 0dccd737..c27ce03f 100755 --- a/tests/test-archivez.sh +++ b/tests/test-archivez.sh @@ -23,7 +23,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -echo '1..12' +echo '1..13' setup_test_repository "archive"