lib/checkout: For "process whiteouts" mode, replace directories too
I'm playing around with some ostree ⇔ OCI/Docker bits, and ran into this while importing an OCI image that built from the Fedora base image where `/home` is a regular directory, and I added a layer that did the ostree bits of moving it to `/var` and leaving a symlink. OCI/Docker supports this. Now since "process whiteouts" is really the "enable OCI/Docker" mode, let's only replace dirs if that's enabled. This leaves the `UNION_FILES` targeted for its original use case which is unioning components/packages. (Although that use case itself is now a bit superceded by `UNION_IDENTICAL`, but eh). Closes: #1294 Approved by: jlebon
This commit is contained in:
parent
9166605e5a
commit
b8251d26bd
|
|
@ -228,8 +228,24 @@ create_file_copy_from_input_at (OstreeRepo *repo,
|
||||||
return glnx_throw_errno_prefix (error, "symlinkat");
|
return glnx_throw_errno_prefix (error, "symlinkat");
|
||||||
case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES:
|
case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES:
|
||||||
{
|
{
|
||||||
/* Unioning? Let's unlink and try again */
|
/* For unioning, we further bifurcate a bit; for the "process whiteouts"
|
||||||
(void) unlinkat (destination_dfd, destination_name, 0);
|
* mode which is really "Docker/OCI", we need to match their semantics
|
||||||
|
* and handle replacing a directory with a symlink. See also equivalent
|
||||||
|
* bits for regular files in checkout_file_hardlink().
|
||||||
|
*/
|
||||||
|
if (options->process_whiteouts)
|
||||||
|
{
|
||||||
|
if (!glnx_shutil_rm_rf_at (destination_dfd, destination_name, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (unlinkat (destination_dfd, destination_name, 0) < 0)
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (errno != ENOENT))
|
||||||
|
return glnx_throw_errno_prefix (error, "unlinkat(%s)", destination_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (symlinkat (target, destination_dfd, destination_name) < 0)
|
if (symlinkat (target, destination_dfd, destination_name) < 0)
|
||||||
return glnx_throw_errno_prefix (error, "symlinkat");
|
return glnx_throw_errno_prefix (error, "symlinkat");
|
||||||
}
|
}
|
||||||
|
|
@ -309,7 +325,17 @@ create_file_copy_from_input_at (OstreeRepo *repo,
|
||||||
/* Handled above */
|
/* Handled above */
|
||||||
break;
|
break;
|
||||||
case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES:
|
case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES:
|
||||||
replace_mode = GLNX_LINK_TMPFILE_REPLACE;
|
/* Special case OCI/Docker - see similar code in checkout_file_hardlink()
|
||||||
|
* and above for symlinks.
|
||||||
|
*/
|
||||||
|
if (options->process_whiteouts)
|
||||||
|
{
|
||||||
|
if (!glnx_shutil_rm_rf_at (destination_dfd, destination_name, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
/* Inherit the NOREPLACE default...we deleted whatever's there */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
replace_mode = GLNX_LINK_TMPFILE_REPLACE;
|
||||||
break;
|
break;
|
||||||
case OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES:
|
case OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES:
|
||||||
replace_mode = GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST;
|
replace_mode = GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST;
|
||||||
|
|
@ -467,7 +493,15 @@ checkout_file_hardlink (OstreeRepo *self,
|
||||||
/* Make a link with a temp name */
|
/* Make a link with a temp name */
|
||||||
if (!hardlink_add_tmp_name (self, srcfd, loose_path, tmpname, cancellable, error))
|
if (!hardlink_add_tmp_name (self, srcfd, loose_path, tmpname, cancellable, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
/* Rename it into place */
|
/* For OCI/Docker mode, we need to handle replacing a directory with a regular
|
||||||
|
* file. See also the equivalent code for symlinks above.
|
||||||
|
*/
|
||||||
|
if (options->process_whiteouts)
|
||||||
|
{
|
||||||
|
if (!glnx_shutil_rm_rf_at (destination_dfd, destination_name, NULL, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* Rename it into place - for non-OCI this will overwrite files but not directories */
|
||||||
if (!glnx_renameat (self->tmp_dir_fd, tmpname, destination_dfd, destination_name, error))
|
if (!glnx_renameat (self->tmp_dir_fd, tmpname, destination_dfd, destination_name, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
ret_result = HARDLINK_RESULT_LINKED;
|
ret_result = HARDLINK_RESULT_LINKED;
|
||||||
|
|
|
||||||
|
|
@ -848,7 +848,7 @@ typedef enum {
|
||||||
/**
|
/**
|
||||||
* OstreeRepoCheckoutOverwriteMode:
|
* OstreeRepoCheckoutOverwriteMode:
|
||||||
* @OSTREE_REPO_CHECKOUT_OVERWRITE_NONE: No special options
|
* @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_UNION_FILES: When layering checkouts, unlink() and replace existing files, but do not modify existing directories (unless whiteouts are enabled, then directories are replaced)
|
||||||
* @OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES: Only add new files/directories
|
* @OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES: Only add new files/directories
|
||||||
* @OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL: Like UNION_FILES, but error if files are not identical (requires hardlink checkouts)
|
* @OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL: Like UNION_FILES, but error if files are not identical (requires hardlink checkouts)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -879,6 +879,20 @@ if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper; then
|
||||||
assert_has_file overlay-co/anewdir/blah
|
assert_has_file overlay-co/anewdir/blah
|
||||||
assert_has_file overlay-co/anewfile
|
assert_has_file overlay-co/anewfile
|
||||||
|
|
||||||
|
# And test replacing a directory wholesale with a symlink as well as a regular file
|
||||||
|
mkdir overlay
|
||||||
|
echo baz to file > overlay/baz
|
||||||
|
ln -s anewfile overlay/anewdir
|
||||||
|
$OSTREE --repo=repo commit ${COMMIT_ARGS} -b overlay-dir-convert --tree=dir=overlay
|
||||||
|
rm overlay -rf
|
||||||
|
|
||||||
|
rm overlay-co -rf
|
||||||
|
for branch in test2 overlay-dir-convert; do
|
||||||
|
$OSTREE --repo=repo checkout --union --whiteouts ${branch} overlay-co
|
||||||
|
done
|
||||||
|
assert_has_file overlay-co/baz
|
||||||
|
test -L overlay-co/anewdir
|
||||||
|
|
||||||
echo "ok whiteouts enabled"
|
echo "ok whiteouts enabled"
|
||||||
|
|
||||||
# Now double check whiteouts are not processed without --whiteouts
|
# Now double check whiteouts are not processed without --whiteouts
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue