for various reasons/limitations/bugs/whatever, i rewrote epatch.  seems to
work for me, but in case someone wants to check before i release:
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

        # 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
                # Some people like to make dirs of patches w/out suffixes (vim)
                set -- "$1"/*${EPATCH_SUFFIX:+."${EPATCH_SUFFIX}"}

        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

        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} ]] ; then
                        # let people use globs in the exclude
                        eshopts_push -o noglob

                        local ex
                        for ex in ${EPATCH_EXCLUDE} ; do
                                if [[ ${patchname} == ${ex} ]] ; then
                                        eshopts_pop
                                        continue
                                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

                # 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 *****\n\n" "${patchname}" > "${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

                # Dynamically detect the correct -p# ... i'm lazy, so shoot me 
:/
                while [[ ${count} -lt 5 ]] ; do
                        # Generate some useful debug info ...
                        (
                        _epatch_draw_line "***** ${patchname} *****"
                        echo
                        echo "PATCH COMMAND:  patch -p${count} ${EPATCH_OPTS} < 
'${PATCH_TARGET}'"
                        echo
                        _epatch_draw_line "***** ${patchname} *****"
                        ) >> "${STDERR_TARGET}"

                        if (patch -p${count} ${EPATCH_OPTS} --dry-run -f < 
"${PATCH_TARGET}") >> "${STDERR_TARGET}" 2>&1 ; 
then
                                (
                                _epatch_draw_line "***** ${patchname} *****"
                                echo
                                echo "ACTUALLY APPLYING ${patchname} ..."
                                echo
                                _epatch_draw_line "***** ${patchname} *****"
                                patch -p${count} ${EPATCH_OPTS} < 
"${PATCH_TARGET}" 2>&1
                                ) >> "${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

                # 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 patch log
                rm -f "${STDERR_TARGET}"
                eend 0
        done

        [[ ${SINGLE_PATCH} == "no" ]] && einfo "Done with patching"
        : # everything worked
}
-mike

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to