Advertisement
Guest User

Untitled

a guest
Jan 14th, 2016
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 12.40 KB | None | 0 0
  1. GMT_EPATCH_SOURCE="${WORKDIR}/patch"
  2. GMT_EPATCH_SUFFIX="patch.bz2"
  3. GMT_EPATCH_OPTS=""
  4. GMT_EPATCH_COMMON_OPTS="-g0 -E --no-backup-if-mismatch"
  5. GMT_EPATCH_EXCLUDE=""
  6. GMT_EPATCH_SINGLE_MSG="(gmt_epatch)"
  7. GMT_EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates: (gmt_epatch) ..."
  8. GMT_EPATCH_FORCE="no"
  9.  
  10. post_src_prepare() {
  11.     if [[ ${GMT_EPATCH_USER_FORCE} == yes ]]; then
  12.         [[ ${GMT_EPATCH_USER_POST_SRC_PREPARE} == yes ]] || return 0
  13.         gmt_epatch_user || \
  14.             { ewarn "SHIT!"; ewarn "gmt_epatch_user failed for =${CATEGORY}/${P}" ; /bin/true ; }
  15.     fi
  16.     unset GMT_EPATCH_USER_FORCE
  17.     if [[ ${GMT_CPP11_POST_SRC_PREPARE} == yes ]]; then
  18.         CXXFLAGS="${CXXFLAGS} --std=c++11"
  19.     fi
  20.     # no unset here because in theory every src_prepare requires reapplication of flags
  21. }
  22.  
  23. gmt_epatch_user() {
  24.     [[ $# -ne 0 ]] && die "gmt_epatch_user takes no options"
  25.  
  26.     # Allow multiple calls to this function; ignore all but the first
  27.     local applied="${T}/gmt_epatch_user.log"
  28.     [[ -e ${applied} ]] && return 2
  29.  
  30.     # don't clobber any EPATCH vars that the parent might want
  31.     local GMT_EPATCH_SOURCE check base=${PORTAGE_CONFIGROOT%/}/etc/portage/patches
  32.     for check in ${CATEGORY}/{${P}-${PR},${P},${PN}}{,:${SLOT}}; do
  33.         GMT_EPATCH_SOURCE=${base}/${CTARGET}/${check}
  34.         [[ -r ${GMT_EPATCH_SOURCE} ]] || GMT_EPATCH_SOURCE=${base}/${CHOST}/${check}
  35.         [[ -r ${GMT_EPATCH_SOURCE} ]] || GMT_EPATCH_SOURCE=${base}/${check}
  36.         if [[ -d ${GMT_EPATCH_SOURCE} ]] ; then
  37.             GMT_EPATCH_SOURCE=${GMT_EPATCH_SOURCE} \
  38.             GMT_EPATCH_SUFFIX="patch" \
  39.             GMT_EPATCH_FORCE="yes" \
  40.             GMT_EPATCH_MULTI_MSG="Applying user patches from ${GMT_EPATCH_SOURCE} (gmt_epatch)" \
  41.             gmt_epatch
  42.             echo "${GMT_EPATCH_SOURCE}" > "${applied}"
  43.             has "${gmt_epatch_user_death_notice}" ${EBUILD_DEATH_HOOKS} || EBUILD_DEATH_HOOKS+=" gmt_epatch_user_death_notice"
  44.             return 0
  45.         fi
  46.     done
  47.     echo "none" > "${applied}"
  48.     return 1
  49. }
  50.  
  51. gmt_epatch_user_death_notice() {
  52.     ewarn "!!! User patches were wedged into this build gmt style!"
  53. }
  54.  
  55. gmt_epatch() {
  56.     _gmt_epatch_draw_line() {
  57.         # create a line of same length as input string
  58.         [[ -z $1 ]] && set "$(printf "%65s" '')"
  59.         echo "${1//?/=}"
  60.     }
  61.  
  62.     unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402
  63.  
  64.     # First process options.  We localize the GMT_EPATCH_OPTS setting
  65.     # from above so that we can pass it on in the loop below with
  66.     # any additional values the user has specified.
  67.     local GMT_EPATCH_OPTS=( ${GMT_EPATCH_OPTS[*]} )
  68.     while [[ $# -gt 0 ]] ; do
  69.         case $1 in
  70.         -*) GMT_EPATCH_OPTS+=( "$1" ) ;;
  71.         *) break ;;
  72.         esac
  73.         shift
  74.     done
  75.  
  76.     # Let the rest of the code process one user arg at a time --
  77.     # each arg may expand into multiple patches, and each arg may
  78.     # need to start off with the default global EPATCH_xxx values
  79.     if [[ $# -gt 1 ]] ; then
  80.         local m
  81.         for m in "$@" ; do
  82.             gmt_epatch "${m}"
  83.         done
  84.         return 0
  85.     fi
  86.  
  87.     local GMT_SINGLE_PATCH="no"
  88.     # no args means process ${GMT_EPATCH_SOURCE}
  89.     [[ $# -eq 0 ]] && set -- "${GMT_EPATCH_SOURCE}"
  90.  
  91.     if [[ -f $1 ]] ; then
  92.         GMT_SINGLE_PATCH="yes"
  93.         set -- "$1"
  94.         # Use the suffix from the single patch (localize it); the code
  95.         # below will find the suffix for us
  96.         local GMT_EPATCH_SUFFIX=$1
  97.  
  98.     elif [[ -d $1 ]] ; then
  99.         # We have to force sorting to C so that the wildcard expansion is consistent #471666.
  100.         gmt_evar_push_set LC_COLLATE C
  101.         # Some people like to make dirs of patches w/out suffixes (vim).
  102.         set -- "$1"/*${GMT_EPATCH_SUFFIX:+."${GMT_EPATCH_SUFFIX}"}
  103.         gmt_evar_pop
  104.  
  105.     elif [[ -f ${GMT_EPATCH_SOURCE}/$1 ]] ; then
  106.         # Re-use GMT_EPATCH_SOURCE as a search dir
  107.         gmt_epatch "${GMT_EPATCH_SOURCE}/$1"
  108.         return $?
  109.  
  110.     else
  111.         # sanity check ... if it isn't a dir or file, wtf man ?
  112.         [[ $# -ne 0 ]] && GMT_EPATCH_SOURCE=$1
  113.         echo
  114.         eerror "Cannot find \$GMT_EPATCH_SOURCE!  Value for \$GMT_EPATCH_SOURCE is:"
  115.         eerror
  116.         eerror "  ${GMT_EPATCH_SOURCE}"
  117.         eerror "  ( ${GMT_EPATCH_SOURCE##*/} )"
  118.         echo
  119.         die "Cannot find \$GMT_EPATCH_SOURCE!"
  120.     fi
  121.  
  122.     # Now that we know we're actually going to apply something, merge
  123.     # all of the patch options back in to a single variable for below.
  124.     GMT_EPATCH_OPTS="${EPATCH_COMMON_OPTS} ${GMT_EPATCH_OPTS[*]}"
  125.  
  126.     local PIPE_CMD
  127.     case ${GMT_EPATCH_SUFFIX##*\.} in
  128.         xz)      PIPE_CMD="xz -dc"    ;;
  129.         lzma)    PIPE_CMD="lzma -dc"  ;;
  130.         bz2)     PIPE_CMD="bzip2 -dc" ;;
  131.         gz|Z|z)  PIPE_CMD="gzip -dc"  ;;
  132.         ZIP|zip) PIPE_CMD="unzip -p"  ;;
  133.         *)       ;;
  134.     esac
  135.  
  136.     [[ ${GMT_SINGLE_PATCH} == "no" ]] && einfo "${GMT_EPATCH_MULTI_MSG}"
  137.  
  138.     local x
  139.     for x in "$@" ; do
  140.         # If the patch dir given contains subdirs, or our GMT_EPATCH_SUFFIX
  141.         # didn't match anything, ignore continue on
  142.         [[ ! -f ${x} ]] && continue
  143.  
  144.         local patchname=${x##*/}
  145.  
  146.         # Apply single patches, or forced sets of patches, or
  147.         # patches with ARCH dependant names.
  148.         #   ???_arch_foo.patch
  149.         # Else, skip this input altogether
  150.         local a=${patchname#*_} # strip the ???_
  151.         a=${a%%_*}              # strip the _foo.patch
  152.         if ! [[ ${GMT_SINGLE_PATCH} == "yes" || \
  153.                 ${GMT_EPATCH_FORCE} == "yes" || \
  154.                 ${a} == all     || \
  155.                 ${a} == ${ARCH} ]]
  156.         then
  157.             continue
  158.         fi
  159.  
  160.         # Let people filter things dynamically
  161.         if [[ -n ${GMT_EPATCH_EXCLUDE}${GMT_EPATCH_USER_EXCLUDE} ]] ; then
  162.             # let people use globs in the exclude
  163.             gmt_eshopts_push -o noglob
  164.  
  165.             local ex
  166.             for ex in ${GMT_EPATCH_EXCLUDE} ; do
  167.                 if [[ ${patchname} == ${ex} ]] ; then
  168.                     einfo "  Skipping ${patchname} due to GMT_EPATCH_EXCLUDE ..."
  169.                     gmt_eshopts_pop
  170.                     continue 2
  171.                 fi
  172.             done
  173.  
  174.             for ex in ${GMT_EPATCH_USER_EXCLUDE} ; do
  175.                 if [[ ${patchname} == ${ex} ]] ; then
  176.                     einfo "  Skipping ${patchname} due to GMT_EPATCH_USER_EXCLUDE ..."
  177.                     gmt_eshopts_pop
  178.                     continue 2
  179.                 fi
  180.             done
  181.  
  182.             gmt_eshopts_pop
  183.         fi
  184.  
  185.         if [[ ${GMT_SINGLE_PATCH} == "yes" ]] ; then
  186.             if [[ -n ${GMT_EPATCH_SINGLE_MSG} ]] ; then
  187.                 einfo "${GMT_EPATCH_SINGLE_MSG}"
  188.             else
  189.                 einfo "Applying ${patchname} ... (gmt)"
  190.             fi
  191.         else
  192.             einfo "  ${patchname} ..."
  193.         fi
  194.  
  195.         # Handle aliased patch command #404447 #461568
  196.         local patch="patch"
  197.         eval $(alias patch 2>/dev/null | sed 's:^alias ::')
  198.  
  199.         # most of the time, there will only be one run per unique name,
  200.         # but if there are more, make sure we get unique log filenames
  201.         local STDERR_TARGET="${T}/${patchname}.out"
  202.         if [[ -e ${STDERR_TARGET} ]] ; then
  203.             STDERR_TARGET="${T}/${patchname}-$$.out"
  204.         fi
  205.  
  206.         printf "***** %s *****\nPWD: %s\nPATCH TOOL: %s -> %s\nVERSION INFO:\n%s\n\n" \
  207.             "${patchname}" \
  208.             "${PWD}" \
  209.             "${patch}" \
  210.             "$(type -P "${patch}")" \
  211.             "$(${patch} --version)" \
  212.             > "${STDERR_TARGET}"
  213.  
  214.         # Decompress the patch if need be
  215.         local count=0
  216.         local PATCH_TARGET
  217.         if [[ -n ${PIPE_CMD} ]] ; then
  218.             PATCH_TARGET="${T}/$$.patch"
  219.             echo "PIPE_COMMAND:  ${PIPE_CMD} ${x} > ${PATCH_TARGET}" >> "${STDERR_TARGET}"
  220.  
  221.             if ! (${PIPE_CMD} "${x}" > "${PATCH_TARGET}") >> "${STDERR_TARGET}" 2>&1 ; then
  222.                 echo
  223.                 eerror "Could not extract patch!"
  224.                 #die "Could not extract patch!"
  225.                 count=5
  226.                 break
  227.             fi
  228.         else
  229.             PATCH_TARGET=${x}
  230.         fi
  231.  
  232.         # Check for absolute paths in patches.  If sandbox is disabled,
  233.         # people could (accidently) patch files in the root filesystem.
  234.         # Or trigger other unpleasantries #237667.  So disallow -p0 on
  235.         # such patches.
  236.         local abs_paths=$(egrep -n '^[-+]{3} /' "${PATCH_TARGET}" | awk '$2 != "/dev/null" { print }')
  237.         if [[ -n ${abs_paths} ]] ; then
  238.             count=1
  239.             printf "NOTE: skipping -p0 due to absolute paths in patch:\n%s\n" "${abs_paths}" >> "${STDERR_TARGET}"
  240.         fi
  241.         # Similar reason, but with relative paths.
  242.         local rel_paths=$(egrep -n '^[-+]{3} [^ ]*[.][.]/' "${PATCH_TARGET}")
  243.         if [[ -n ${rel_paths} ]] ; then
  244.             echo
  245.             eerror "Rejected Patch: ${patchname} !"
  246.             eerror " ( ${PATCH_TARGET} )"
  247.             eerror
  248.             eerror "Your patch uses relative paths '../':"
  249.             eerror "${rel_paths}"
  250.             echo
  251.             die "you need to fix the relative paths in patch"
  252.         fi
  253.  
  254.         # Dynamically detect the correct -p# ... i'm lazy, so shoot me :/
  255.         local patch_cmd
  256.         while [[ ${count} -lt 5 ]] ; do
  257.             patch_cmd="${patch} -p${count} ${GMT_EPATCH_OPTS}"
  258.  
  259.             # Generate some useful debug info ...
  260.             (
  261.             _gmt_epatch_draw_line "***** ${patchname} *****"
  262.             echo
  263.             echo "PATCH COMMAND:  ${patch_cmd} < '${PATCH_TARGET}'"
  264.             echo
  265.             _gmt_epatch_draw_line "***** ${patchname} *****"
  266.             ${patch_cmd} --dry-run -f < "${PATCH_TARGET}" 2>&1
  267.             ret=$?
  268.             echo
  269.             echo "patch program exited with status ${ret}"
  270.             exit ${ret}
  271.             ) >> "${STDERR_TARGET}"
  272.  
  273.             if [ $? -eq 0 ] ; then
  274.                 (
  275.                 _gmt_epatch_draw_line "***** ${patchname} *****"
  276.                 echo
  277.                 echo "ACTUALLY APPLYING ${patchname} ..."
  278.                 echo
  279.                 _gmt_epatch_draw_line "***** ${patchname} *****"
  280.                 ${patch_cmd} < "${PATCH_TARGET}" 2>&1
  281.                 ret=$?
  282.                 echo
  283.                 echo "patch program exited with status ${ret}"
  284.                 exit ${ret}
  285.                 ) >> "${STDERR_TARGET}"
  286.  
  287.                 if [ $? -ne 0 ] ; then
  288.                     echo
  289.                     eerror "A dry-run of patch command succeeded, but actually"
  290.                     eerror "applying the patch failed!"
  291.                     #die "Real world sux compared to the dreamworld!"
  292.                     count=5
  293.                 fi
  294.                 break
  295.             fi
  296.  
  297.             : $(( count++ ))
  298.         done
  299.  
  300.         # if we had to decompress the patch, delete the temp one
  301.         if [[ -n ${PIPE_CMD} ]] ; then
  302.             rm -f "${PATCH_TARGET}"
  303.         fi
  304.  
  305.         if [[ ${count} -ge 5 ]] ; then
  306.             echo
  307.             eerror "Failed Patch: ${patchname} ! (gmt_epatch)"
  308.             eerror " ( ${PATCH_TARGET} )"
  309.             eerror
  310.             eerror "Clues might be in:"
  311.             eerror
  312.             eerror "  ${STDERR_TARGET}"
  313.             echo
  314.             die "Failed Patch: ${patchname}! (gmt_epatch)"
  315.         fi
  316.  
  317.         # if everything worked, delete the full debug patch log
  318.         rm -f "${STDERR_TARGET}"
  319.  
  320.         # then log away the exact stuff for people to review later
  321.         cat <<-EOF >> "${T}/gmt_epatch.log"
  322.         PATCH: ${x}
  323.         CMD: ${patch_cmd}
  324.         PWD: ${PWD}
  325.  
  326.         EOF
  327.         eend 0
  328.     done
  329.  
  330.     [[ ${GMT_SINGLE_PATCH} == "no" ]] && einfo "Done with patching"
  331.     : # everything worked
  332. }
  333.  
  334. gmt_isdigit() {
  335.     local d
  336.     for d ; do
  337.         [[ ${d:-bad} == *[!0-9]* ]] && return 1
  338.     done
  339.     return 0
  340. }
  341.  
  342. gmt_estack_push() {
  343.     [[ $# -eq 0 ]] && die "gmt_estack_push: incorrect # of arguments"
  344.     local stack_name="_GMT_ESTACK_$1_" ; shift
  345.     eval ${stack_name}+=\( \"\$@\" \)
  346. }
  347.  
  348. gmt_estack_pop() {
  349.     [[ $# -eq 0 || $# -gt 2 ]] && die "gmt_estack_pop: incorrect # of arguments"
  350.     local _estack_name="_GMT_ESTACK_$1_" ; shift
  351.     local _estack_retvar=$1 ; shift
  352.     eval local _estack_i=\${#${_estack_name}\[@\]}
  353.     # Don't warn -- let the caller interpret this as a failure
  354.     # or as normal behavior (akin to `shift`)
  355.     [[ $(( --_estack_i )) -eq -1 ]] && return 1
  356.     if [[ -n ${_estack_retvar} ]] ; then
  357.         eval ${_estack_retvar}=\"\${${_estack_name}\[${_estack_i}\]}\"
  358.     fi
  359.     eval unset ${_estack_name}\[${_estack_i}\]
  360. }
  361.  
  362. gmt_evar_push() {
  363.     local var val
  364.     for var ; do
  365.         [[ ${!var+set} == "set" ]] \
  366.             && val=${!var} \
  367.             || val="unset_76xc3x46x065xb4cax59f9x9e6793f94"
  368.         gmt_estack_push evar "${var}" "${val}"
  369.     done
  370. }
  371.  
  372. gmt_evar_push_set() {
  373.     local var=$1
  374.     gmt_evar_push ${var}
  375.     case $# in
  376.     1) unset ${var} ;;
  377.     2) printf -v "${var}" '%s' "$2" ;;
  378.     *) die "${FUNCNAME}: incorrect # of args: $*" ;;
  379.     esac
  380. }
  381.  
  382. gmt_evar_pop() {
  383.     local cnt=${1:-bad}
  384.     case $# in
  385.     0) cnt=1 ;;
  386.     1) gmt_isdigit "${cnt}" || die "${FUNCNAME}: first arg must be a number: $*" ;;
  387.     *) die "${FUNCNAME}: only accepts one arg: $*" ;;
  388.     esac
  389.  
  390.     local var val
  391.     while (( cnt-- )) ; do
  392.         gmt_estack_pop evar val || die "${FUNCNAME}: unbalanced push"
  393.         gmt_estack_pop evar var || die "${FUNCNAME}: unbalanced push"
  394.         [[ ${val} == "unset_76xc3x46x065xb4cax59f9x9e6793f94" ]] \
  395.             && unset ${var} \
  396.             || printf -v "${var}" '%s' "${val}"
  397.     done
  398. }
  399.  
  400. gmt_eshopts_push() {
  401.     if [[ $1 == -[su] ]] ; then
  402.         gmt_estack_push eshopts "$(shopt -p)"
  403.         [[ $# -eq 0 ]] && return 0
  404.         shopt "$@" || die "${FUNCNAME}: bad options to shopt: $*"
  405.     else
  406.         gmt_estack_push eshopts $-
  407.         [[ $# -eq 0 ]] && return 0
  408.         set "$@" || die "${FUNCNAME}: bad options to set: $*"
  409.     fi
  410. }
  411.  
  412. # @FUNCTION: gmt_eshopts_pop
  413. # @USAGE:
  414. # @DESCRIPTION:
  415. # Restore the shell options to the state saved with the corresponding
  416. # gmt_eshopts_push call.  See that function for more details.
  417. gmt_eshopts_pop() {
  418.     local s
  419.     gmt_estack_pop eshopts s || die "${FUNCNAME}: unbalanced push"
  420.     if [[ ${s} == "shopt -"* ]] ; then
  421.         eval "${s}" || die "${FUNCNAME}: sanity: invalid shopt options: ${s}"
  422.     else
  423.         set +$-     || die "${FUNCNAME}: sanity: invalid shell settings: $-"
  424.         set -${s}   || die "${FUNCNAME}: sanity: unable to restore saved shell settings: ${s}"
  425.     fi
  426. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement