commit: 5ee2d40e97c2aa21a3d322f486fe6783a150bbda
Author: Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Tue Sep 16 12:53:53 2025 +0000
Commit: Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue Sep 16 15:40:42 2025 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=5ee2d40e
phase-helpers.sh: install default docs where DOCS is undeclared, not unset
EAPI 6 introduced the einstalldocs() function. A recent commit altered
the behaviour of the function in such a way that, if the 'DOCS' variable
is found to be unset, a default set of documentation files shall be
installed. The prior behaviour was to do so in the event that the
variable is undeclared.
It transpires that there is a disagreement between the implementation
and the specification. Below is an excerpt of the pseudocode presented
by PMS, with some redactions made for the purpose of legibility.
7: else if the DOCS variable is unset then
8: for all d matching the filename expansion of README* ChangeLog AUTHORS ...
9: if file d exists and has a size greater than zero then
10: call dodoc with d as argument
11: end if
12: end for
13: end if
Note the use of the term, unset. In bash, it is quite possible to
declare a variable that remains in an unset state.
# ( DOCS=(); test -v DOCS || echo unset )
unset
# ( f() { local -a DOCS; test -v DOCS || echo unset; }; f )
unset
Effectively, PMS is in the wrong. By focusing unduly on the
specification, I inadvertently introduced a regression whereby, if
'DOCS' is set as an empty array, the function proceeds to install the
default documentation.
Address this issue by restoring the prior behaviour of checking whether
'DOCS' is undeclared. Further, perform the test by taking advantage of
the ${param@A} form of expansion, rather than parse the output of the
declare builtin as the prior implementation did. Not only does this
approach avoid an unnecessary subshell but it addresses an adjacent bug.
Imagine that 'DOCS' is declared as a function-local array that is empty.
src_install() {
# This declares a local array that is unset and empty
local -a DOCS
# Imagine that einstalldocs() continues to parse declare -p.
# Here, it will proceed to install the default documentation.
einstalldocs
}
This long-standing bug was caused by testing in the fashion of
[[ $(declare -p DOCS) != *=* ]], which falsely assumes that the
<equals-sign> character is present for a declared variable.
# ( DOCS=(); declare -p DOCS; )
declare -a DOCS=()
# ( f() { local -a DOCS; declare -p DOCS; }; f ) # no <equals-sign>
declare -a DOCS
Fixes: 7ff579ccb92b2f2512933a41e9a0a204b0601201
Closes: https://bugs.gentoo.org/962934
Link: https://projects.gentoo.org/pms/6/pms.html#x1-145003r4
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>
bin/phase-helpers.sh | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh
index 47c6f8167c..aa9f6af8be 100644
--- a/bin/phase-helpers.sh
+++ b/bin/phase-helpers.sh
@@ -962,7 +962,11 @@ if ___eapi_has_einstalldocs; then
einstalldocs() (
local f
- if [[ ! -v DOCS ]]; then
+ # The implementation deviates from PMS, which purports to be
+ # concerned with whether the "DOCS variable is unset". In fact,
+ # the implementation checks whether the variable is undeclared.
+ # However, it is PMS that is in the wrong. See bug #962934.
+ if [[ ! ${DOCS@A} ]]; then
for f in README* ChangeLog AUTHORS NEWS TODO CHANGES \
THANKS BUGS FAQ CREDITS CHANGELOG
do