commit: 2d5809fd23c620f7889441202eeb5950959eb3e8
Author: Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Wed Jun 25 04:50:26 2025 +0000
Commit: Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Sat Jun 28 02:30:15 2025 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=2d5809fd
phase-functions.sh: improve empty directory culling in __dyn_clean()
Presently, the __dyn_clean() function contains a pipeline that is
intended to recursively delete empty directories, with the exception of
those whose pathnames are equal to - or subsumed by - the path specified
by the 'WORKDIR' variable. This pipeline suffers from various defects,
which are described and addressed herewith.
The value of the 'PORTAGE_BUILDDIR' variable could be treated by the
find(1) utility as an option or primary. Address this issue by using the
find0() function, which takes advantage of the -files0-from option that
is supported as of findutils-4.9.0.
Pathnames containing <newline> are handled neither correctly nor safely.
Address this issue by specifying the -print0 primary to find(1), thereby
producing a stream of null-terminated pathnames.
The value of the 'WORKDIR' variable is injected into the argument
following the -regex primary, resulting in it being treated as a
sub-pattern of a regular expression in the GNU Emacs dialect. Address
this issue by eschewing the primary and, instead, using bash to safely
exclude any pathnames that are equal to - or subsumed by - 'WORKDIR'.
The sort(1) utility is used to reverse the list of pathnames, with the
intent of ensuring that directory removal is performed in a depth-first
fashion. Not only is this fairly expensive but it also requires for the
input stream to be a list of <newline>-terminated pathnames. Address
this issue by forgoing the use of sort(1) and, instead, specifying the
-depth primary to find(1).
The rmdir(1) utility is invoked in such a way that STDERR is muted. It
appears to be a sloppy attempt at covering up the fact that rmdir(1)
won't be able to remove any non-empty directories. Address this issue by
refraining from muting STDERR and, instead, specifying the -empty
primary to find(1).
The rmdir(1) utility is invoked in such a way that its operands could be
mistaken for options. Address this issue by specifying the "--" operand,
so as to signify end-of-options.
See-also: d887c7fd33b5f136ff62d423d7a11980fb9faca1
See-also: a0210b3c49ea346b1e999f92a7ed89802e8d6849
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>
bin/phase-functions.sh | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/bin/phase-functions.sh b/bin/phase-functions.sh
index abe7162560..de86b00cc4 100644
--- a/bin/phase-functions.sh
+++ b/bin/phase-functions.sh
@@ -321,7 +321,10 @@ __dyn_clean() {
fi
if [[ -f "${PORTAGE_BUILDDIR}/.unpacked" ]]; then
- find "${PORTAGE_BUILDDIR}" -type d ! -regex "^${WORKDIR}" |
sort -r | tr "\n" "\0" | ${XARGS} -0 rmdir &>/dev/null
+ printf '%s\0' "${PORTAGE_BUILDDIR}" \
+ | find0 -depth -type d -empty -print0 \
+ | while read -rd ''; do [[ ${REPLY} != "${WORKDIR}"?(/*) ]] &&
printf '%s\0' "${REPLY}"; done \
+ | ${XARGS} -0 rmdir --
fi
# Do not bind this to doebuild defined DISTDIR; don't trust doebuild,
and if mistakes are made it'll