Combine the patch basenames from all matched directories into a
list, and apply them in POSIX sorted order.  This allows patches in
more-specific directories to override patches of the same basename found
in less-specific directories. An empty patch (or /dev/null symlink)
negates a patch with the same basename found in a less-specific
directory.

This behavior is much more flexible and intuitive than the previous one,
while remaining backward-compatible to some extent.

NOTE: The implementation uses an associative array, which requires bash
version 4 or later.

X-Gentoo-bug: 608880
X-Gentoo-bug-url: https://bugs.gentoo.org/608880
---
 bin/phase-helpers.sh | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh
index 4b9b12b70..f8c2c34d4 100644
--- a/bin/phase-helpers.sh
+++ b/bin/phase-helpers.sh
@@ -1094,22 +1094,41 @@ if ___eapi_has_eapply_user; then
 
                local basedir=${PORTAGE_CONFIGROOT%/}/etc/portage/patches
 
-               local d applied
+               local applied d f
+               local -A _eapply_user_patches
                local prev_shopt=$(shopt -p nullglob)
                shopt -s nullglob
 
-               # possibilities:
+               # Patches from all matched directories are combined into a
+               # sorted (POSIX order) list of the patch basenames. Patches
+               # in more-specific directories override patches of the same
+               # basename found in less-specific directories. An empty patch
+               # (or /dev/null symlink) negates a patch with the same
+               # basename found in a less-specific directory.
+               #
+               # order of specificity:
                # 1. ${CATEGORY}/${P}-${PR} (note: -r0 desired to avoid applying
                #    ${P} twice)
                # 2. ${CATEGORY}/${P}
                # 3. ${CATEGORY}/${PN}
                # all of the above may be optionally followed by a slot
-               for d in 
"${basedir}"/${CATEGORY}/{${P}-${PR},${P},${PN}}{,:${SLOT%/*}}; do
-                       if [[ -n $(echo "${d}"/*.diff) || -n $(echo 
"${d}"/*.patch) ]]; then
-                               eapply "${d}"
+               for d in 
"${basedir}"/${CATEGORY}/{${P}-${PR},${P},${PN}}{:${SLOT%/*},}; do
+                       for f in "${d}"/*; do
+                               if [[ ( ${f} == *.diff || ${f} == *.patch ) &&
+                                       -z ${_eapply_user_patches[${f##*/}]} 
]]; then
+                                       _eapply_user_patches[${f##*/}]=${f}
+                               fi
+                       done
+               done
+
+               while read -r -d '' f; do
+                       f=${_eapply_user_patches[${f}]}
+                       if [[ -s ${f} ]]; then
+                               eapply "${f}"
                                applied=1
                        fi
-               done
+               done < <(printf -- "%s\0" "${!_eapply_user_patches[@]}" |
+                       LC_ALL=C sort -z)
 
                ${prev_shopt}
 
-- 
2.13.0


Reply via email to