checkout: Always replace existing content in overlay mode

The combination of the "honor whiteout" and "union" flags
are intended to basically be "merge trees like overlayfs does".
But we were missing this case in order to support e.g. replacing
a symlink with a directory.
This commit is contained in:
Colin Walters 2024-03-13 12:50:28 -04:00
parent 223a1af4b5
commit bb6dfd3ab0
2 changed files with 28 additions and 0 deletions

View File

@ -1062,6 +1062,22 @@ checkout_tree_at_recurse (OstreeRepo *self, OstreeRepoCheckoutAtOptions *options
if (!glnx_shutil_rm_rf_at (destination_parent_fd, destination_name, cancellable, error))
return FALSE;
}
else if (options->process_whiteouts
&& options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
{
/* In this mode, we're flattening in a manner similar to overlayfs, so ensure
* any non-directory content there is gone. /
*/
struct stat stbuf;
if (!glnx_fstatat_allow_noent (destination_parent_fd, destination_name, &stbuf,
AT_SYMLINK_NOFOLLOW, error))
return FALSE;
if (errno == 0 && !S_ISDIR (stbuf.st_mode))
{
if (!glnx_shutil_rm_rf_at (destination_parent_fd, destination_name, cancellable, error))
return FALSE;
}
}
/* Create initially with mode 0700, then chown/chmod only when we're
* done. This avoids anyone else being able to operate on partially

View File

@ -1159,6 +1159,18 @@ if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper && touch overlay/baz/an
assert_has_file overlay-co/baz
test -L overlay-co/anewdir
rm overlay-co overlay -rf
mkdir -p overlay/somelink overlay/yet/ovlnewdir
echo ovlnewf > overlay/yet/ovlnewdir/ovlnewf
$OSTREE --repo=repo commit ${COMMIT_ARGS} -b overlay-symlink-convert --tree=dir=overlay
for branch in test2 overlay-symlink-convert; do
$OSTREE --repo=repo checkout --union --whiteouts ${branch} overlay-co
done
test -d overlay-co/somelink || fatal "should replace symlink with dir"
assert_has_dir overlay-co/yet/another
assert_has_dir overlay-co/yet/ovlnewdir
assert_file_has_content overlay-co/yet/ovlnewdir/ovlnewf ovlnewf
rm overlay-co overlay -rf
echo "ok whiteouts enabled"
# Now double check whiteouts are not processed without --whiteouts