On sob, 2017-03-11 at 16:03 +0100, Michał Górny wrote: > Move epatch and epatch_user (along with the descriptions for all their > variables) into a dedicated epatch.eclass. This function is very > complex, therefore it benefits from separate eclass and a dedicated > maintainer. Furthermore, it is mostly obsoleted by eapply* in EAPI 6. > > The new eclass is implicitly inherited by eutils to preserve > compatibility. However, the inherit will be removed in EAPI 7, > and the ebuilds should switch to inheriting epatch directly or using > eapply*. > > Thanks to Ulrich Müller for doing the necessary research. > --- > eclass/epatch.eclass | 458 > +++++++++++++++++++++++++++++++++++++++++++++++++++ > eclass/eutils.eclass | 440 +------------------------------------------------ > 2 files changed, 459 insertions(+), 439 deletions(-) > create mode 100644 eclass/epatch.eclass > > diff --git a/eclass/epatch.eclass b/eclass/epatch.eclass > new file mode 100644 > index 000000000000..fb0a10b53583 > --- /dev/null > +++ b/eclass/epatch.eclass > @@ -0,0 +1,458 @@ > +# Copyright 1999-2017 Gentoo Foundation > +# Distributed under the terms of the GNU General Public License v2 > + > +# @ECLASS: epatch.eclass > +# @MAINTAINER: > +# base-sys...@gentoo.org > +# @BLURB: easy patch application functions > +# @DESCRIPTION: > +# An eclass providing epatch and epatch_user functions to easily apply > +# patches to ebuilds. Mostly superseded by eapply* in EAPI 6. > + > +if [[ -z ${_EPATCH_ECLASS} ]]; then > + > +# @VARIABLE: EPATCH_SOURCE > +# @DESCRIPTION: > +# Default directory to search for patches. > +EPATCH_SOURCE="${WORKDIR}/patch" > +# @VARIABLE: EPATCH_SUFFIX > +# @DESCRIPTION: > +# Default extension for patches (do not prefix the period yourself). > +EPATCH_SUFFIX="patch.bz2" > +# @VARIABLE: EPATCH_OPTS > +# @DESCRIPTION: > +# Options to pass to patch. Meant for ebuild/package-specific tweaking > +# such as forcing the patch level (-p#) or fuzz (-F#) factor. Note that > +# for single patch tweaking, you can also pass flags directly to epatch. > +EPATCH_OPTS="" > +# @VARIABLE: EPATCH_COMMON_OPTS > +# @DESCRIPTION: > +# Common options to pass to `patch`. You probably should never need to > +# change these. If you do, please discuss it with base-system first to > +# be sure. > +# @CODE > +# -g0 - keep RCS, ClearCase, Perforce and SCCS happy #24571 > +# --no-backup-if-mismatch - do not leave .orig files behind > +# -E - automatically remove empty files > +# @CODE > +EPATCH_COMMON_OPTS="-g0 -E --no-backup-if-mismatch" > +# @VARIABLE: EPATCH_EXCLUDE > +# @DESCRIPTION: > +# List of patches not to apply. Note this is only file names, > +# and not the full path. Globs accepted. > +EPATCH_EXCLUDE="" > +# @VARIABLE: EPATCH_SINGLE_MSG > +# @DESCRIPTION: > +# Change the printed message for a single patch. > +EPATCH_SINGLE_MSG="" > +# @VARIABLE: EPATCH_MULTI_MSG > +# @DESCRIPTION: > +# Change the printed message for multiple patches. > +EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates) ..." > +# @VARIABLE: EPATCH_FORCE > +# @DESCRIPTION: > +# Only require patches to match EPATCH_SUFFIX rather than the extended > +# arch naming style. > +EPATCH_FORCE="no" > +# @VARIABLE: EPATCH_USER_EXCLUDE > +# @DEFAULT_UNSET > +# @DESCRIPTION: > +# List of patches not to apply. Note this is only file names, > +# and not the full path. Globs accepted. > + > +# @FUNCTION: epatch > +# @USAGE: [options] [patches] [dirs of patches] > +# @DESCRIPTION: > +# epatch is designed to greatly simplify the application of patches. It can > +# process patch files directly, or directories of patches. The patches may > be > +# compressed (bzip/gzip/etc...) or plain text. You generally need not > specify > +# the -p option as epatch will automatically attempt -p0 to -p4 until things > +# apply successfully. > +# > +# If you do not specify any patches/dirs, then epatch will default to the > +# directory specified by EPATCH_SOURCE. > +# > +# Any options specified that start with a dash will be passed down to patch > +# for this specific invocation. As soon as an arg w/out a dash is found, > then > +# arg processing stops. > +# > +# When processing directories, epatch will apply all patches that match: > +# @CODE > +# if ${EPATCH_FORCE} != "yes" > +# ??_${ARCH}_foo.${EPATCH_SUFFIX} > +# else > +# *.${EPATCH_SUFFIX} > +# @CODE > +# The leading ?? are typically numbers used to force consistent patch > ordering. > +# The arch field is used to apply patches only for the host architecture with > +# the special value of "all" means apply for everyone. Note that using > values > +# other than "all" is highly discouraged -- you should apply patches all the > +# time and let architecture details be detected at configure/compile time. > +# > +# If EPATCH_SUFFIX is empty, then no period before it is implied when > searching > +# for patches to apply. > +# > +# Refer to the other EPATCH_xxx variables for more customization of behavior. > +epatch() { > + _epatch_draw_line() { > + # create a line of same length as input string > + [[ -z $1 ]] && set "$(printf "%65s" '')" > + echo "${1//?/=}" > + } > + > + unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402 > + > + # First process options. We localize the EPATCH_OPTS setting > + # from above so that we can pass it on in the loop below with > + # any additional values the user has specified. > + local EPATCH_OPTS=( ${EPATCH_OPTS[*]} ) > + while [[ $# -gt 0 ]] ; do > + case $1 in > + -*) EPATCH_OPTS+=( "$1" ) ;; > + *) break ;; > + esac > + shift > + done > + > + # Let the rest of the code process one user arg at a time -- > + # each arg may expand into multiple patches, and each arg may > + # need to start off with the default global EPATCH_xxx values > + if [[ $# -gt 1 ]] ; then > + local m > + for m in "$@" ; do > + epatch "${m}" > + done > + return 0 > + fi > + > + local SINGLE_PATCH="no" > + # no args means process ${EPATCH_SOURCE} > + [[ $# -eq 0 ]] && set -- "${EPATCH_SOURCE}" > + > + if [[ -f $1 ]] ; then > + SINGLE_PATCH="yes" > + set -- "$1" > + # Use the suffix from the single patch (localize it); the code > + # below will find the suffix for us > + local EPATCH_SUFFIX=$1 > + > + elif [[ -d $1 ]] ; then > + # We have to force sorting to C so that the wildcard expansion > is consistent #471666. > + evar_push_set LC_COLLATE C > + # Some people like to make dirs of patches w/out suffixes (vim). > + set -- "$1"/*${EPATCH_SUFFIX:+."${EPATCH_SUFFIX}"} > + evar_pop > + > + elif [[ -f ${EPATCH_SOURCE}/$1 ]] ; then > + # Re-use EPATCH_SOURCE as a search dir > + epatch "${EPATCH_SOURCE}/$1" > + return $? > + > + else > + # sanity check ... if it isn't a dir or file, wtf man ? > + [[ $# -ne 0 ]] && EPATCH_SOURCE=$1 > + echo > + eerror "Cannot find \$EPATCH_SOURCE! Value for \$EPATCH_SOURCE > is:" > + eerror > + eerror " ${EPATCH_SOURCE}" > + eerror " ( ${EPATCH_SOURCE##*/} )" > + echo > + die "Cannot find \$EPATCH_SOURCE!" > + fi > + > + # Now that we know we're actually going to apply something, merge > + # all of the patch options back in to a single variable for below. > + EPATCH_OPTS="${EPATCH_COMMON_OPTS} ${EPATCH_OPTS[*]}" > + > + local PIPE_CMD > + case ${EPATCH_SUFFIX##*\.} in > + xz) PIPE_CMD="xz -dc" ;; > + lzma) PIPE_CMD="lzma -dc" ;; > + bz2) PIPE_CMD="bzip2 -dc" ;; > + gz|Z|z) PIPE_CMD="gzip -dc" ;; > + ZIP|zip) PIPE_CMD="unzip -p" ;; > + *) ;; > + esac > + > + [[ ${SINGLE_PATCH} == "no" ]] && einfo "${EPATCH_MULTI_MSG}" > + > + local x > + for x in "$@" ; do > + # If the patch dir given contains subdirs, or our EPATCH_SUFFIX > + # didn't match anything, ignore continue on > + [[ ! -f ${x} ]] && continue > + > + local patchname=${x##*/} > + > + # Apply single patches, or forced sets of patches, or > + # patches with ARCH dependant names. > + # ???_arch_foo.patch > + # Else, skip this input altogether > + local a=${patchname#*_} # strip the ???_ > + a=${a%%_*} # strip the _foo.patch > + if ! [[ ${SINGLE_PATCH} == "yes" || \ > + ${EPATCH_FORCE} == "yes" || \ > + ${a} == all || \ > + ${a} == ${ARCH} ]] > + then > + continue > + fi > + > + # Let people filter things dynamically > + if [[ -n ${EPATCH_EXCLUDE}${EPATCH_USER_EXCLUDE} ]] ; then > + # let people use globs in the exclude > + eshopts_push -o noglob > + > + local ex > + for ex in ${EPATCH_EXCLUDE} ; do > + if [[ ${patchname} == ${ex} ]] ; then > + einfo " Skipping ${patchname} due to > EPATCH_EXCLUDE ..." > + eshopts_pop > + continue 2 > + fi > + done > + > + for ex in ${EPATCH_USER_EXCLUDE} ; do > + if [[ ${patchname} == ${ex} ]] ; then > + einfo " Skipping ${patchname} due to > EPATCH_USER_EXCLUDE ..." > + eshopts_pop > + continue 2 > + fi > + done > + > + eshopts_pop > + fi > + > + if [[ ${SINGLE_PATCH} == "yes" ]] ; then > + if [[ -n ${EPATCH_SINGLE_MSG} ]] ; then > + einfo "${EPATCH_SINGLE_MSG}" > + else > + einfo "Applying ${patchname} ..." > + fi > + else > + einfo " ${patchname} ..." > + fi > + > + # Handle aliased patch command #404447 #461568 > + local patch="patch" > + eval $(alias patch 2>/dev/null | sed 's:^alias ::') > + > + # most of the time, there will only be one run per unique name, > + # but if there are more, make sure we get unique log filenames > + local STDERR_TARGET="${T}/${patchname}.out" > + if [[ -e ${STDERR_TARGET} ]] ; then > + STDERR_TARGET="${T}/${patchname}-$$.out" > + fi > + > + printf "***** %s *****\nPWD: %s\nPATCH TOOL: %s -> %s\nVERSION > INFO:\n%s\n\n" \ > + "${patchname}" \ > + "${PWD}" \ > + "${patch}" \ > + "$(type -P "${patch}")" \ > + "$(${patch} --version)" \ > + > "${STDERR_TARGET}" > + > + # Decompress the patch if need be > + local count=0 > + local PATCH_TARGET > + if [[ -n ${PIPE_CMD} ]] ; then > + PATCH_TARGET="${T}/$$.patch" > + echo "PIPE_COMMAND: ${PIPE_CMD} ${x} > > ${PATCH_TARGET}" >> "${STDERR_TARGET}" > + > + if ! (${PIPE_CMD} "${x}" > "${PATCH_TARGET}") >> > "${STDERR_TARGET}" 2>&1 ; then > + echo > + eerror "Could not extract patch!" > + #die "Could not extract patch!" > + count=5 > + break > + fi > + else > + PATCH_TARGET=${x} > + fi > + > + # Check for absolute paths in patches. If sandbox is disabled, > + # people could (accidently) patch files in the root filesystem. > + # Or trigger other unpleasantries #237667. So disallow -p0 on > + # such patches. > + local abs_paths=$(egrep -n '^[-+]{3} /' "${PATCH_TARGET}" | awk > '$2 != "/dev/null" { print }') > + if [[ -n ${abs_paths} ]] ; then > + count=1 > + printf "NOTE: skipping -p0 due to absolute paths in > patch:\n%s\n" "${abs_paths}" >> "${STDERR_TARGET}" > + fi > + # Similar reason, but with relative paths. > + local rel_paths=$(egrep -n '^[-+]{3} [^ ]*[.][.]/' > "${PATCH_TARGET}") > + if [[ -n ${rel_paths} ]] ; then > + echo > + eerror "Rejected Patch: ${patchname} !" > + eerror " ( ${PATCH_TARGET} )" > + eerror > + eerror "Your patch uses relative paths '../':" > + eerror "${rel_paths}" > + echo > + die "you need to fix the relative paths in patch" > + fi > + > + # Dynamically detect the correct -p# ... i'm lazy, so shoot me > :/ > + local patch_cmd > + while [[ ${count} -lt 5 ]] ; do > + patch_cmd="${patch} -p${count} ${EPATCH_OPTS}" > + > + # Generate some useful debug info ... > + ( > + _epatch_draw_line "***** ${patchname} *****" > + echo > + echo "PATCH COMMAND: ${patch_cmd} --dry-run -f < > '${PATCH_TARGET}'" > + echo > + _epatch_draw_line "***** ${patchname} *****" > + ${patch_cmd} --dry-run -f < "${PATCH_TARGET}" 2>&1 > + ret=$? > + echo > + echo "patch program exited with status ${ret}" > + exit ${ret} > + ) >> "${STDERR_TARGET}" > + > + if [ $? -eq 0 ] ; then > + ( > + _epatch_draw_line "***** ${patchname} *****" > + echo > + echo "ACTUALLY APPLYING ${patchname} ..." > + echo "PATCH COMMAND: ${patch_cmd} < > '${PATCH_TARGET}'" > + echo > + _epatch_draw_line "***** ${patchname} *****" > + ${patch_cmd} < "${PATCH_TARGET}" 2>&1 > + ret=$? > + echo > + echo "patch program exited with status ${ret}" > + exit ${ret} > + ) >> "${STDERR_TARGET}" > + > + if [ $? -ne 0 ] ; then > + echo > + eerror "A dry-run of patch command > succeeded, but actually" > + eerror "applying the patch failed!" > + #die "Real world sux compared to the > dreamworld!" > + count=5 > + fi > + break > + fi > + > + : $(( count++ )) > + done > + > + (( EPATCH_N_APPLIED_PATCHES++ )) > + > + # if we had to decompress the patch, delete the temp one > + if [[ -n ${PIPE_CMD} ]] ; then > + rm -f "${PATCH_TARGET}" > + fi > + > + if [[ ${count} -ge 5 ]] ; then > + echo > + eerror "Failed Patch: ${patchname} !" > + eerror " ( ${PATCH_TARGET} )" > + eerror > + eerror "Include in your bugreport the contents of:" > + eerror > + eerror " ${STDERR_TARGET}" > + echo > + die "Failed Patch: ${patchname}!" > + fi > + > + # if everything worked, delete the full debug patch log > + rm -f "${STDERR_TARGET}" > + > + # then log away the exact stuff for people to review later > + cat <<-EOF >> "${T}/epatch.log" > + PATCH: ${x} > + CMD: ${patch_cmd} > + PWD: ${PWD} > + > + EOF > + eend 0 > + done > + > + [[ ${SINGLE_PATCH} == "no" ]] && einfo "Done with patching" > + : # everything worked > +} > + > +case ${EAPI:-0} in > +0|1|2|3|4|5) > + > +# @VARIABLE: EPATCH_USER_SOURCE > +# @DESCRIPTION: > +# Location for user patches, see the epatch_user function. > +# Should be set by the user. Don't set this in ebuilds. > +: ${EPATCH_USER_SOURCE:=${PORTAGE_CONFIGROOT%/}/etc/portage/patches} > + > +# @FUNCTION: epatch_user > +# @USAGE: > +# @DESCRIPTION: > +# Applies user-provided patches to the source tree. The patches are > +# taken from /etc/portage/patches/<CATEGORY>/<P-PR|P|PN>[:SLOT]/, where the > first > +# of these three directories to exist will be the one to use, ignoring > +# any more general directories which might exist as well. They must end > +# in ".patch" to be applied. > +# > +# User patches are intended for quick testing of patches without ebuild > +# modifications, as well as for permanent customizations a user might > +# desire. Obviously, there can be no official support for arbitrarily > +# patched ebuilds. So whenever a build log in a bug report mentions that > +# user patches were applied, the user should be asked to reproduce the > +# problem without these. > +# > +# Not all ebuilds do call this function, so placing patches in the > +# stated directory might or might not work, depending on the package and > +# the eclasses it inherits and uses. It is safe to call the function > +# repeatedly, so it is always possible to add a call at the ebuild > +# level. The first call is the time when the patches will be > +# applied. > +# > +# Ideally, this function should be called after gentoo-specific patches > +# have been applied, so that their code can be modified as well, but > +# before calls to e.g. eautoreconf, as the user patches might affect > +# autotool input files as well. > +epatch_user() { > + [[ $# -ne 0 ]] && die "epatch_user takes no options" > + > + # Allow multiple calls to this function; ignore all but the first > + local applied="${T}/epatch_user.log" > + [[ -e ${applied} ]] && return 2 > + > + # don't clobber any EPATCH vars that the parent might want > + local EPATCH_SOURCE check > + for check in ${CATEGORY}/{${P}-${PR},${P},${PN}}{,:${SLOT%/*}}; do > + EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CTARGET}/${check} > + [[ -r ${EPATCH_SOURCE} ]] || > EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CHOST}/${check} > + [[ -r ${EPATCH_SOURCE} ]] || > EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${check} > + if [[ -d ${EPATCH_SOURCE} ]] ; then > + local > old_n_applied_patches=${EPATCH_N_APPLIED_PATCHES:-0} > + EPATCH_SOURCE=${EPATCH_SOURCE} \ > + EPATCH_SUFFIX="patch" \ > + EPATCH_FORCE="yes" \ > + EPATCH_MULTI_MSG="Applying user patches from > ${EPATCH_SOURCE} ..." \ > + epatch > + echo "${EPATCH_SOURCE}" > "${applied}" > + if [[ ${old_n_applied_patches} -lt > ${EPATCH_N_APPLIED_PATCHES} ]]; then > + has epatch_user_death_notice > ${EBUILD_DEATH_HOOKS} || \ > + EBUILD_DEATH_HOOKS+=" > epatch_user_death_notice" > + fi > + return 0 > + fi > + done > + echo "none" > "${applied}" > + return 1 > +} > + > +# @FUNCTION: epatch_user_death_notice > +# @INTERNAL > +# @DESCRIPTION: > +# Include an explicit notice in the die message itself that user patches were > +# applied to this build. > +epatch_user_death_notice() { > + ewarn "!!! User patches were applied to this build!" > +} > + > +esac > + > +_EPATCH_ECLASS=1 > +fi #_EPATCH_ECLASS > diff --git a/eclass/eutils.eclass b/eclass/eutils.eclass > index 79ec00042a3f..724a310b3000 100644 > --- a/eclass/eutils.eclass > +++ b/eclass/eutils.eclass > @@ -22,7 +22,7 @@ inherit multilib toolchain-funcs > # implicitly inherited (now split) eclasses > case ${EAPI:-0} in > 0|1|2|3|4|5|6) > - inherit estack > + inherit epatch estack > ;; > esac > > @@ -70,370 +70,6 @@ egit_clean() { > find "$@" -type d -name '.git*' -prune -print0 | xargs -0 rm -rf > } > > -# @VARIABLE: EPATCH_SOURCE > -# @DESCRIPTION: > -# Default directory to search for patches. > -EPATCH_SOURCE="${WORKDIR}/patch" > -# @VARIABLE: EPATCH_SUFFIX > -# @DESCRIPTION: > -# Default extension for patches (do not prefix the period yourself). > -EPATCH_SUFFIX="patch.bz2" > -# @VARIABLE: EPATCH_OPTS > -# @DESCRIPTION: > -# Options to pass to patch. Meant for ebuild/package-specific tweaking > -# such as forcing the patch level (-p#) or fuzz (-F#) factor. Note that > -# for single patch tweaking, you can also pass flags directly to epatch. > -EPATCH_OPTS="" > -# @VARIABLE: EPATCH_COMMON_OPTS > -# @DESCRIPTION: > -# Common options to pass to `patch`. You probably should never need to > -# change these. If you do, please discuss it with base-system first to > -# be sure. > -# @CODE > -# -g0 - keep RCS, ClearCase, Perforce and SCCS happy #24571 > -# --no-backup-if-mismatch - do not leave .orig files behind > -# -E - automatically remove empty files > -# @CODE > -EPATCH_COMMON_OPTS="-g0 -E --no-backup-if-mismatch" > -# @VARIABLE: EPATCH_EXCLUDE > -# @DESCRIPTION: > -# List of patches not to apply. Note this is only file names, > -# and not the full path. Globs accepted. > -EPATCH_EXCLUDE="" > -# @VARIABLE: EPATCH_SINGLE_MSG > -# @DESCRIPTION: > -# Change the printed message for a single patch. > -EPATCH_SINGLE_MSG="" > -# @VARIABLE: EPATCH_MULTI_MSG > -# @DESCRIPTION: > -# Change the printed message for multiple patches. > -EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates) ..." > -# @VARIABLE: EPATCH_FORCE > -# @DESCRIPTION: > -# Only require patches to match EPATCH_SUFFIX rather than the extended > -# arch naming style. > -EPATCH_FORCE="no" > -# @VARIABLE: EPATCH_USER_EXCLUDE > -# @DEFAULT_UNSET > -# @DESCRIPTION: > -# List of patches not to apply. Note this is only file names, > -# and not the full path. Globs accepted. > - > -# @FUNCTION: epatch > -# @USAGE: [options] [patches] [dirs of patches] > -# @DESCRIPTION: > -# epatch is designed to greatly simplify the application of patches. It can > -# process patch files directly, or directories of patches. The patches may > be > -# compressed (bzip/gzip/etc...) or plain text. You generally need not > specify > -# the -p option as epatch will automatically attempt -p0 to -p4 until things > -# apply successfully. > -# > -# If you do not specify any patches/dirs, then epatch will default to the > -# directory specified by EPATCH_SOURCE. > -# > -# Any options specified that start with a dash will be passed down to patch > -# for this specific invocation. As soon as an arg w/out a dash is found, > then > -# arg processing stops. > -# > -# When processing directories, epatch will apply all patches that match: > -# @CODE > -# if ${EPATCH_FORCE} != "yes" > -# ??_${ARCH}_foo.${EPATCH_SUFFIX} > -# else > -# *.${EPATCH_SUFFIX} > -# @CODE > -# The leading ?? are typically numbers used to force consistent patch > ordering. > -# The arch field is used to apply patches only for the host architecture with > -# the special value of "all" means apply for everyone. Note that using > values > -# other than "all" is highly discouraged -- you should apply patches all the > -# time and let architecture details be detected at configure/compile time. > -# > -# If EPATCH_SUFFIX is empty, then no period before it is implied when > searching > -# for patches to apply. > -# > -# Refer to the other EPATCH_xxx variables for more customization of behavior. > -epatch() { > - _epatch_draw_line() { > - # create a line of same length as input string > - [[ -z $1 ]] && set "$(printf "%65s" '')" > - echo "${1//?/=}" > - } > - > - unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402 > - > - # First process options. We localize the EPATCH_OPTS setting > - # from above so that we can pass it on in the loop below with > - # any additional values the user has specified. > - local EPATCH_OPTS=( ${EPATCH_OPTS[*]} ) > - while [[ $# -gt 0 ]] ; do > - case $1 in > - -*) EPATCH_OPTS+=( "$1" ) ;; > - *) break ;; > - esac > - shift > - done > - > - # Let the rest of the code process one user arg at a time -- > - # each arg may expand into multiple patches, and each arg may > - # need to start off with the default global EPATCH_xxx values > - if [[ $# -gt 1 ]] ; then > - local m > - for m in "$@" ; do > - epatch "${m}" > - done > - return 0 > - fi > - > - local SINGLE_PATCH="no" > - # no args means process ${EPATCH_SOURCE} > - [[ $# -eq 0 ]] && set -- "${EPATCH_SOURCE}" > - > - if [[ -f $1 ]] ; then > - SINGLE_PATCH="yes" > - set -- "$1" > - # Use the suffix from the single patch (localize it); the code > - # below will find the suffix for us > - local EPATCH_SUFFIX=$1 > - > - elif [[ -d $1 ]] ; then > - # We have to force sorting to C so that the wildcard expansion > is consistent #471666. > - evar_push_set LC_COLLATE C > - # Some people like to make dirs of patches w/out suffixes (vim). > - set -- "$1"/*${EPATCH_SUFFIX:+."${EPATCH_SUFFIX}"} > - evar_pop > - > - elif [[ -f ${EPATCH_SOURCE}/$1 ]] ; then > - # Re-use EPATCH_SOURCE as a search dir > - epatch "${EPATCH_SOURCE}/$1" > - return $? > - > - else > - # sanity check ... if it isn't a dir or file, wtf man ? > - [[ $# -ne 0 ]] && EPATCH_SOURCE=$1 > - echo > - eerror "Cannot find \$EPATCH_SOURCE! Value for \$EPATCH_SOURCE > is:" > - eerror > - eerror " ${EPATCH_SOURCE}" > - eerror " ( ${EPATCH_SOURCE##*/} )" > - echo > - die "Cannot find \$EPATCH_SOURCE!" > - fi > - > - # Now that we know we're actually going to apply something, merge > - # all of the patch options back in to a single variable for below. > - EPATCH_OPTS="${EPATCH_COMMON_OPTS} ${EPATCH_OPTS[*]}" > - > - local PIPE_CMD > - case ${EPATCH_SUFFIX##*\.} in > - xz) PIPE_CMD="xz -dc" ;; > - lzma) PIPE_CMD="lzma -dc" ;; > - bz2) PIPE_CMD="bzip2 -dc" ;; > - gz|Z|z) PIPE_CMD="gzip -dc" ;; > - ZIP|zip) PIPE_CMD="unzip -p" ;; > - *) ;; > - esac > - > - [[ ${SINGLE_PATCH} == "no" ]] && einfo "${EPATCH_MULTI_MSG}" > - > - local x > - for x in "$@" ; do > - # If the patch dir given contains subdirs, or our EPATCH_SUFFIX > - # didn't match anything, ignore continue on > - [[ ! -f ${x} ]] && continue > - > - local patchname=${x##*/} > - > - # Apply single patches, or forced sets of patches, or > - # patches with ARCH dependant names. > - # ???_arch_foo.patch > - # Else, skip this input altogether > - local a=${patchname#*_} # strip the ???_ > - a=${a%%_*} # strip the _foo.patch > - if ! [[ ${SINGLE_PATCH} == "yes" || \ > - ${EPATCH_FORCE} == "yes" || \ > - ${a} == all || \ > - ${a} == ${ARCH} ]] > - then > - continue > - fi > - > - # Let people filter things dynamically > - if [[ -n ${EPATCH_EXCLUDE}${EPATCH_USER_EXCLUDE} ]] ; then > - # let people use globs in the exclude > - eshopts_push -o noglob > - > - local ex > - for ex in ${EPATCH_EXCLUDE} ; do > - if [[ ${patchname} == ${ex} ]] ; then > - einfo " Skipping ${patchname} due to > EPATCH_EXCLUDE ..." > - eshopts_pop > - continue 2 > - fi > - done > - > - for ex in ${EPATCH_USER_EXCLUDE} ; do > - if [[ ${patchname} == ${ex} ]] ; then > - einfo " Skipping ${patchname} due to > EPATCH_USER_EXCLUDE ..." > - eshopts_pop > - continue 2 > - fi > - done > - > - eshopts_pop > - fi > - > - if [[ ${SINGLE_PATCH} == "yes" ]] ; then > - if [[ -n ${EPATCH_SINGLE_MSG} ]] ; then > - einfo "${EPATCH_SINGLE_MSG}" > - else > - einfo "Applying ${patchname} ..." > - fi > - else > - einfo " ${patchname} ..." > - fi > - > - # Handle aliased patch command #404447 #461568 > - local patch="patch" > - eval $(alias patch 2>/dev/null | sed 's:^alias ::') > - > - # most of the time, there will only be one run per unique name, > - # but if there are more, make sure we get unique log filenames > - local STDERR_TARGET="${T}/${patchname}.out" > - if [[ -e ${STDERR_TARGET} ]] ; then > - STDERR_TARGET="${T}/${patchname}-$$.out" > - fi > - > - printf "***** %s *****\nPWD: %s\nPATCH TOOL: %s -> %s\nVERSION > INFO:\n%s\n\n" \ > - "${patchname}" \ > - "${PWD}" \ > - "${patch}" \ > - "$(type -P "${patch}")" \ > - "$(${patch} --version)" \ > - > "${STDERR_TARGET}" > - > - # Decompress the patch if need be > - local count=0 > - local PATCH_TARGET > - if [[ -n ${PIPE_CMD} ]] ; then > - PATCH_TARGET="${T}/$$.patch" > - echo "PIPE_COMMAND: ${PIPE_CMD} ${x} > > ${PATCH_TARGET}" >> "${STDERR_TARGET}" > - > - if ! (${PIPE_CMD} "${x}" > "${PATCH_TARGET}") >> > "${STDERR_TARGET}" 2>&1 ; then > - echo > - eerror "Could not extract patch!" > - #die "Could not extract patch!" > - count=5 > - break > - fi > - else > - PATCH_TARGET=${x} > - fi > - > - # Check for absolute paths in patches. If sandbox is disabled, > - # people could (accidently) patch files in the root filesystem. > - # Or trigger other unpleasantries #237667. So disallow -p0 on > - # such patches. > - local abs_paths=$(egrep -n '^[-+]{3} /' "${PATCH_TARGET}" | awk > '$2 != "/dev/null" { print }') > - if [[ -n ${abs_paths} ]] ; then > - count=1 > - printf "NOTE: skipping -p0 due to absolute paths in > patch:\n%s\n" "${abs_paths}" >> "${STDERR_TARGET}" > - fi > - # Similar reason, but with relative paths. > - local rel_paths=$(egrep -n '^[-+]{3} [^ ]*[.][.]/' > "${PATCH_TARGET}") > - if [[ -n ${rel_paths} ]] ; then > - echo > - eerror "Rejected Patch: ${patchname} !" > - eerror " ( ${PATCH_TARGET} )" > - eerror > - eerror "Your patch uses relative paths '../':" > - eerror "${rel_paths}" > - echo > - die "you need to fix the relative paths in patch" > - fi > - > - # Dynamically detect the correct -p# ... i'm lazy, so shoot me > :/ > - local patch_cmd > - while [[ ${count} -lt 5 ]] ; do > - patch_cmd="${patch} -p${count} ${EPATCH_OPTS}" > - > - # Generate some useful debug info ... > - ( > - _epatch_draw_line "***** ${patchname} *****" > - echo > - echo "PATCH COMMAND: ${patch_cmd} --dry-run -f < > '${PATCH_TARGET}'" > - echo > - _epatch_draw_line "***** ${patchname} *****" > - ${patch_cmd} --dry-run -f < "${PATCH_TARGET}" 2>&1 > - ret=$? > - echo > - echo "patch program exited with status ${ret}" > - exit ${ret} > - ) >> "${STDERR_TARGET}" > - > - if [ $? -eq 0 ] ; then > - ( > - _epatch_draw_line "***** ${patchname} *****" > - echo > - echo "ACTUALLY APPLYING ${patchname} ..." > - echo "PATCH COMMAND: ${patch_cmd} < > '${PATCH_TARGET}'" > - echo > - _epatch_draw_line "***** ${patchname} *****" > - ${patch_cmd} < "${PATCH_TARGET}" 2>&1 > - ret=$? > - echo > - echo "patch program exited with status ${ret}" > - exit ${ret} > - ) >> "${STDERR_TARGET}" > - > - if [ $? -ne 0 ] ; then > - echo > - eerror "A dry-run of patch command > succeeded, but actually" > - eerror "applying the patch failed!" > - #die "Real world sux compared to the > dreamworld!" > - count=5 > - fi > - break > - fi > - > - : $(( count++ )) > - done > - > - (( EPATCH_N_APPLIED_PATCHES++ )) > - > - # if we had to decompress the patch, delete the temp one > - if [[ -n ${PIPE_CMD} ]] ; then > - rm -f "${PATCH_TARGET}" > - fi > - > - if [[ ${count} -ge 5 ]] ; then > - echo > - eerror "Failed Patch: ${patchname} !" > - eerror " ( ${PATCH_TARGET} )" > - eerror > - eerror "Include in your bugreport the contents of:" > - eerror > - eerror " ${STDERR_TARGET}" > - echo > - die "Failed Patch: ${patchname}!" > - fi > - > - # if everything worked, delete the full debug patch log > - rm -f "${STDERR_TARGET}" > - > - # then log away the exact stuff for people to review later > - cat <<-EOF >> "${T}/epatch.log" > - PATCH: ${x} > - CMD: ${patch_cmd} > - PWD: ${PWD} > - > - EOF > - eend 0 > - done > - > - [[ ${SINGLE_PATCH} == "no" ]] && einfo "Done with patching" > - : # everything worked > -} > - > # @FUNCTION: emktemp > # @USAGE: [temp dir] > # @DESCRIPTION: > @@ -1493,80 +1129,6 @@ esac > case ${EAPI:-0} in > 0|1|2|3|4|5) > > -# @VARIABLE: EPATCH_USER_SOURCE > -# @DESCRIPTION: > -# Location for user patches, see the epatch_user function. > -# Should be set by the user. Don't set this in ebuilds. > -: ${EPATCH_USER_SOURCE:=${PORTAGE_CONFIGROOT%/}/etc/portage/patches} > - > -# @FUNCTION: epatch_user > -# @USAGE: > -# @DESCRIPTION: > -# Applies user-provided patches to the source tree. The patches are > -# taken from /etc/portage/patches/<CATEGORY>/<P-PR|P|PN>[:SLOT]/, where the > first > -# of these three directories to exist will be the one to use, ignoring > -# any more general directories which might exist as well. They must end > -# in ".patch" to be applied. > -# > -# User patches are intended for quick testing of patches without ebuild > -# modifications, as well as for permanent customizations a user might > -# desire. Obviously, there can be no official support for arbitrarily > -# patched ebuilds. So whenever a build log in a bug report mentions that > -# user patches were applied, the user should be asked to reproduce the > -# problem without these. > -# > -# Not all ebuilds do call this function, so placing patches in the > -# stated directory might or might not work, depending on the package and > -# the eclasses it inherits and uses. It is safe to call the function > -# repeatedly, so it is always possible to add a call at the ebuild > -# level. The first call is the time when the patches will be > -# applied. > -# > -# Ideally, this function should be called after gentoo-specific patches > -# have been applied, so that their code can be modified as well, but > -# before calls to e.g. eautoreconf, as the user patches might affect > -# autotool input files as well. > -epatch_user() { > - [[ $# -ne 0 ]] && die "epatch_user takes no options" > - > - # Allow multiple calls to this function; ignore all but the first > - local applied="${T}/epatch_user.log" > - [[ -e ${applied} ]] && return 2 > - > - # don't clobber any EPATCH vars that the parent might want > - local EPATCH_SOURCE check > - for check in ${CATEGORY}/{${P}-${PR},${P},${PN}}{,:${SLOT%/*}}; do > - EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CTARGET}/${check} > - [[ -r ${EPATCH_SOURCE} ]] || > EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CHOST}/${check} > - [[ -r ${EPATCH_SOURCE} ]] || > EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${check} > - if [[ -d ${EPATCH_SOURCE} ]] ; then > - local > old_n_applied_patches=${EPATCH_N_APPLIED_PATCHES:-0} > - EPATCH_SOURCE=${EPATCH_SOURCE} \ > - EPATCH_SUFFIX="patch" \ > - EPATCH_FORCE="yes" \ > - EPATCH_MULTI_MSG="Applying user patches from > ${EPATCH_SOURCE} ..." \ > - epatch > - echo "${EPATCH_SOURCE}" > "${applied}" > - if [[ ${old_n_applied_patches} -lt > ${EPATCH_N_APPLIED_PATCHES} ]]; then > - has epatch_user_death_notice > ${EBUILD_DEATH_HOOKS} || \ > - EBUILD_DEATH_HOOKS+=" > epatch_user_death_notice" > - fi > - return 0 > - fi > - done > - echo "none" > "${applied}" > - return 1 > -} > - > -# @FUNCTION: epatch_user_death_notice > -# @INTERNAL > -# @DESCRIPTION: > -# Include an explicit notice in the die message itself that user patches were > -# applied to this build. > -epatch_user_death_notice() { > - ewarn "!!! User patches were applied to this build!" > -} > - > # @FUNCTION: einstalldocs > # @DESCRIPTION: > # Install documentation using DOCS and HTML_DOCS.
Merged. -- Best regards, Michał Górny
signature.asc
Description: This is a digitally signed message part