diff options
author | Ruixin <peter.bao@mail.utoronto.ca> | 2017-08-31 15:44:35 +0000 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-09-01 15:42:50 +0000 |
commit | f07432d4cefcea7fb8c602b9ab78e83236127d8f (patch) | |
tree | 26e226ac0fa173deb7fae4fcff29586a204653ec | |
parent | 12114ce3828936ed170adaa71a4c6e948764b127 (diff) | |
download | ostree-f07432d4cefcea7fb8c602b9ab78e83236127d8f.tar.gz |
checkout: add an extra checkout_overwrite mode
This is for issue projectatomic/rpm-ostree#365,
an extra option of overwrite mode is added to the checkout command
so that when there is "non-directory" file already exist
during checkout, the error will be handled.
Some tests are added for regression
Closes: #1116
Approved by: cgwalters
-rw-r--r-- | bash/ostree | 1 | ||||
-rw-r--r-- | man/ostree-checkout.xml | 8 | ||||
-rw-r--r-- | src/libostree/ostree-repo-checkout.c | 3 | ||||
-rw-r--r-- | src/libostree/ostree-repo.h | 2 | ||||
-rw-r--r-- | src/ostree/ot-builtin-checkout.c | 18 | ||||
-rw-r--r-- | tests/basic-test.sh | 28 |
6 files changed, 57 insertions, 3 deletions
diff --git a/bash/ostree b/bash/ostree index f12d88b7..4ebe22c3 100644 --- a/bash/ostree +++ b/bash/ostree @@ -696,6 +696,7 @@ _ostree_checkout() { --require-hardlinks -H --union --union-add + --disjoint-union --user-mode -U --whiteouts " diff --git a/man/ostree-checkout.xml b/man/ostree-checkout.xml index c8585878..07d44b34 100644 --- a/man/ostree-checkout.xml +++ b/man/ostree-checkout.xml @@ -98,6 +98,14 @@ Boston, MA 02111-1307, USA. </varlistentry> <varlistentry> + <term><option>--disjoint-union</option></term> + + <listitem><para> + When layering checkouts, error out if a file would be replaced, but add new files and directories + </para></listitem> + </varlistentry> + + <varlistentry> <term><option>--allow-noent</option></term> <listitem><para> diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 3deaa297..4fbbee7d 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -654,7 +654,8 @@ checkout_tree_at_recurse (OstreeRepo *self, { if (errno == EEXIST && (options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES - || options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES)) + || options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES + || options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_DISJOINT_UNION_FILES)) did_exist = TRUE; else return glnx_throw_errno (error); diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index ab037020..58b1a1dc 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -832,11 +832,13 @@ typedef enum { * @OSTREE_REPO_CHECKOUT_OVERWRITE_NONE: No special options * @OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES: When layering checkouts, unlink() and replace existing files, but do not modify existing directories * @OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES: Only add new files/directories + * @OSTREE_REPO_CHECKOUT_OVERWRITE_DISJOINT_UNION_FILES: When layering checkouts, error out if a file would be replaced, but add new files and directories */ typedef enum { OSTREE_REPO_CHECKOUT_OVERWRITE_NONE = 0, OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES = 1, OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES = 2, /* Since: 2017.3 */ + OSTREE_REPO_CHECKOUT_OVERWRITE_DISJOINT_UNION_FILES = 3 /* Since: 2017.11 */ } OstreeRepoCheckoutOverwriteMode; _OSTREE_PUBLIC diff --git a/src/ostree/ot-builtin-checkout.c b/src/ostree/ot-builtin-checkout.c index a31d3685..a3494ae3 100644 --- a/src/ostree/ot-builtin-checkout.c +++ b/src/ostree/ot-builtin-checkout.c @@ -37,6 +37,7 @@ static gboolean opt_disable_cache; static char *opt_subpath; static gboolean opt_union; static gboolean opt_union_add; +static gboolean opt_disjoint_union; static gboolean opt_whiteouts; static gboolean opt_from_stdin; static char *opt_from_file; @@ -72,6 +73,7 @@ static GOptionEntry options[] = { { "subpath", 0, 0, G_OPTION_ARG_FILENAME, &opt_subpath, "Checkout sub-directory PATH", "PATH" }, { "union", 0, 0, G_OPTION_ARG_NONE, &opt_union, "Keep existing directories, overwrite existing files", NULL }, { "union-add", 0, 0, G_OPTION_ARG_NONE, &opt_union_add, "Keep existing files/directories, only add new", NULL }, + { "disjoint-union", 0, 0, G_OPTION_ARG_NONE, &opt_disjoint_union, "When layering checkouts, error out if a file would be replaced, but add new files and directories", NULL }, { "whiteouts", 0, 0, G_OPTION_ARG_NONE, &opt_whiteouts, "Process 'whiteout' (Docker style) entries", NULL }, { "allow-noent", 0, 0, G_OPTION_ARG_NONE, &opt_allow_noent, "Do nothing if specified path does not exist", NULL }, { "from-stdin", 0, 0, G_OPTION_ARG_NONE, &opt_from_stdin, "Process many checkouts from standard input", NULL }, @@ -99,7 +101,7 @@ process_one_checkout (OstreeRepo *repo, * convenient infrastructure for testing C APIs with data. */ if (opt_disable_cache || opt_whiteouts || opt_require_hardlinks || - opt_union_add || opt_force_copy || opt_bareuseronly_dirs) + opt_union_add || opt_force_copy || opt_bareuseronly_dirs || opt_disjoint_union) { OstreeRepoCheckoutAtOptions options = { 0, }; @@ -112,6 +114,18 @@ process_one_checkout (OstreeRepo *repo, "Cannot specify both --union and --union-add"); goto out; } + if (opt_union && opt_disjoint_union) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Cannot specify both --union and --disjoint-union"); + goto out; + } + if (opt_union_add && opt_disjoint_union) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Cannot specify both --union-add and --disjoint-union "); + goto out; + } if (opt_require_hardlinks && opt_force_copy) { glnx_throw (error, "Cannot specify both --require-hardlinks and --force-copy"); @@ -121,6 +135,8 @@ process_one_checkout (OstreeRepo *repo, options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES; else if (opt_union_add) options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES; + else if (opt_disjoint_union) + options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_DISJOINT_UNION_FILES; if (opt_whiteouts) options.process_whiteouts = TRUE; if (subpath) diff --git a/tests/basic-test.sh b/tests/basic-test.sh index de4bd445..6b43ca90 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -19,7 +19,7 @@ set -euo pipefail -echo "1..$((70 + ${extra_basic_tests:-0}))" +echo "1..$((72 + ${extra_basic_tests:-0}))" $CMD_PREFIX ostree --version > version.yaml python -c 'import yaml; yaml.safe_load(open("version.yaml"))' @@ -469,6 +469,32 @@ assert_file_has_content checkout-test-union-add/union-add-test 'existing file fo assert_file_has_content checkout-test-union-add/union-add-test2 'another file for union add testing' echo "ok checkout union add" +# Create some new files for testing +cd ${test_tmpdir} +mkdir disjoint-union-test +mkdir disjoint-union-test/test_one +chmod a+w disjoint-union-test/test_one +echo 'file for add dirs testing' > disjoint-union-test/test_one/test_file +$OSTREE commit ${COMMIT_ARGS} -b test-disjoint-union --tree=dir=disjoint-union-test +$OSTREE checkout --disjoint-union test-disjoint-union checkout-test-disjoint-union +echo "ok adding new directories and new file" +# Make a new file, and try the checkout again +echo 'second test file' > disjoint-union-test/test_one/test_second_file +$OSTREE commit ${COMMIT_ARGS} -b test-disjoint-union --tree=dir=disjoint-union-test +# Check out the latest commit, should fail due to presence of existing files +if $OSTREE checkout --disjoint-union test-disjoint-union checkout-test-disjoint-union 2> err.txt; then + assert_not_reached "checking out files unexpectedly succeeded!" +fi +assert_file_has_content err.txt 'File exists' +# Verify that Union mode still functions properly +rm checkout-test-disjoint-union/test_one/test_file +echo 'file for testing union mode alongwith disjoint-union mode' > checkout-test-disjoint-union/test_one/test_file +$OSTREE checkout --union test-disjoint-union checkout-test-disjoint-union +assert_has_file checkout-test-disjoint-union/test_one/test_second_file +# This shows the file with same name has been successfully overwriten +assert_file_has_content checkout-test-disjoint-union/test_one/test_file 'file for add dirs testing' +echo "ok checkout disjoint union" + cd ${test_tmpdir} rm files -rf && mkdir files mkdir files/worldwritable-dir |