Use find to delete files recursively (#4732)

* Use find to delete files recursively

Instead of using rm -rf use find to delete files recursively. This
has the added benefit that we do not need to rely on shell expansion.

In particular, shell expansion caused the --one-file-system flag to
not work as intended: The idea was that the content of a (left-over)
bind mounted directory would not get deleted. However, since shell
expansion passed the directory to rm, rm happily deleted also files in
that bind mounted directory.

* Pass arguments correctly

* Fix argument order and stderr output

* Improve error handling

Log with exception level if there is an OS level error. Decode the
stderr output correctly.

* Remove unnecessary newline
This commit is contained in:
Stefan Agner 2023-11-27 17:36:30 +01:00 committed by GitHub
parent cb03d039f4
commit 3d5bd2adef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 8 deletions

View File

@ -15,7 +15,7 @@ WORKDIR /usr/src
RUN \
set -x \
&& apk add --no-cache \
coreutils \
findutils \
eudev \
eudev-libs \
git \

View File

@ -105,30 +105,36 @@ async def remove_folder(
if any(item.match(exclude) for exclude in excludes):
moved_files.append(item.rename(temp_path / item.name))
del_folder = f"{folder}" + "/{,.[!.],..?}*" if content_only else f"{folder}"
find_args = []
if content_only:
find_args.extend(["-mindepth", "1"])
try:
proc = await asyncio.create_subprocess_exec(
"bash",
"-c",
f"rm -rf --one-file-system {del_folder}",
"/usr/bin/find",
folder,
"-xdev",
*find_args,
"-delete",
stdout=asyncio.subprocess.DEVNULL,
stderr=asyncio.subprocess.PIPE,
env=clean_env(),
)
_, error_msg = await proc.communicate()
except OSError as err:
error_msg = str(err)
_LOGGER.exception("Can't remove folder %s: %s", folder, err)
else:
if proc.returncode == 0:
return
_LOGGER.error(
"Can't remove folder %s: %s", folder, error_msg.decode("utf-8").strip()
)
finally:
if excludes:
for item in moved_files:
item.rename(folder / item.name)
temp.cleanup()
_LOGGER.error("Can't remove folder %s: %s", folder, error_msg)
def clean_env() -> dict[str, str]:
"""Return a clean env from system."""