diff options
-rw-r--r-- | eclass/epatch.eclass | 458 | ||||
-rw-r--r-- | eclass/eutils.eclass | 440 |
2 files changed, 459 insertions, 439 deletions
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-system@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. |