Skip to content

Commit

Permalink
Use find to delete files recursively (#4732)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
agners authored Nov 27, 2023
1 parent cb03d03 commit 3d5bd2a
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ WORKDIR /usr/src
RUN \
set -x \
&& apk add --no-cache \
coreutils \
findutils \
eudev \
eudev-libs \
git \
Expand Down
20 changes: 13 additions & 7 deletions supervisor/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down

0 comments on commit 3d5bd2a

Please sign in to comment.