Gentoo Archives: gentoo-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-dev@l.g.o
Cc: "Michał Górny" <mgorny@g.o>
Subject: [gentoo-dev] [PATCH] epatch.eclass: Split epatch* logic from eutils
Date: Sat, 11 Mar 2017 13:52:15
Message-Id: 20170311135137.5343-1-mgorny@gentoo.org
1 Move epatch and epatch_user (along with the descriptions for all their
2 variables) into a dedicated epatch.eclass. This function is very
3 complex, therefore it benefits from separate eclass and a dedicated
4 maintainer. Furthermore, it is mostly obsoleted by eapply* in EAPI 6.
5
6 The new eclass is implicitly inherited by eutils to preserve
7 compatibility. However, the inherit will be removed in EAPI 7,
8 and the ebuilds should switch to inheriting epatch directly or using
9 eapply*.
10 -
11 [Review note: this is 1:1 code move, no changes between the code]
12 --
13 eclass/epatch.eclass | 453 +++++++++++++++++++++++++++++++++++++++++++++++++++
14 eclass/eutils.eclass | 440 +------------------------------------------------
15 2 files changed, 454 insertions(+), 439 deletions(-)
16 create mode 100644 eclass/epatch.eclass
17
18 diff --git a/eclass/epatch.eclass b/eclass/epatch.eclass
19 new file mode 100644
20 index 000000000000..9727dae6bee7
21 --- /dev/null
22 +++ b/eclass/epatch.eclass
23 @@ -0,0 +1,453 @@
24 +# Copyright 1999-2017 Gentoo Foundation
25 +# Distributed under the terms of the GNU General Public License v2
26 +
27 +# @ECLASS: epatch.eclass
28 +# @MAINTAINER:
29 +# base-system@g.o
30 +# @BLURB: easy patch application functions
31 +# @DESCRIPTION:
32 +# An eclass providing epatch and epatch_user functions to easily apply
33 +# patches to ebuilds. Mostly superseded by eapply* in EAPI 6.
34 +
35 +# @VARIABLE: EPATCH_SOURCE
36 +# @DESCRIPTION:
37 +# Default directory to search for patches.
38 +EPATCH_SOURCE="${WORKDIR}/patch"
39 +# @VARIABLE: EPATCH_SUFFIX
40 +# @DESCRIPTION:
41 +# Default extension for patches (do not prefix the period yourself).
42 +EPATCH_SUFFIX="patch.bz2"
43 +# @VARIABLE: EPATCH_OPTS
44 +# @DESCRIPTION:
45 +# Options to pass to patch. Meant for ebuild/package-specific tweaking
46 +# such as forcing the patch level (-p#) or fuzz (-F#) factor. Note that
47 +# for single patch tweaking, you can also pass flags directly to epatch.
48 +EPATCH_OPTS=""
49 +# @VARIABLE: EPATCH_COMMON_OPTS
50 +# @DESCRIPTION:
51 +# Common options to pass to `patch`. You probably should never need to
52 +# change these. If you do, please discuss it with base-system first to
53 +# be sure.
54 +# @CODE
55 +# -g0 - keep RCS, ClearCase, Perforce and SCCS happy #24571
56 +# --no-backup-if-mismatch - do not leave .orig files behind
57 +# -E - automatically remove empty files
58 +# @CODE
59 +EPATCH_COMMON_OPTS="-g0 -E --no-backup-if-mismatch"
60 +# @VARIABLE: EPATCH_EXCLUDE
61 +# @DESCRIPTION:
62 +# List of patches not to apply. Note this is only file names,
63 +# and not the full path. Globs accepted.
64 +EPATCH_EXCLUDE=""
65 +# @VARIABLE: EPATCH_SINGLE_MSG
66 +# @DESCRIPTION:
67 +# Change the printed message for a single patch.
68 +EPATCH_SINGLE_MSG=""
69 +# @VARIABLE: EPATCH_MULTI_MSG
70 +# @DESCRIPTION:
71 +# Change the printed message for multiple patches.
72 +EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates) ..."
73 +# @VARIABLE: EPATCH_FORCE
74 +# @DESCRIPTION:
75 +# Only require patches to match EPATCH_SUFFIX rather than the extended
76 +# arch naming style.
77 +EPATCH_FORCE="no"
78 +# @VARIABLE: EPATCH_USER_EXCLUDE
79 +# @DEFAULT_UNSET
80 +# @DESCRIPTION:
81 +# List of patches not to apply. Note this is only file names,
82 +# and not the full path. Globs accepted.
83 +
84 +# @FUNCTION: epatch
85 +# @USAGE: [options] [patches] [dirs of patches]
86 +# @DESCRIPTION:
87 +# epatch is designed to greatly simplify the application of patches. It can
88 +# process patch files directly, or directories of patches. The patches may be
89 +# compressed (bzip/gzip/etc...) or plain text. You generally need not specify
90 +# the -p option as epatch will automatically attempt -p0 to -p4 until things
91 +# apply successfully.
92 +#
93 +# If you do not specify any patches/dirs, then epatch will default to the
94 +# directory specified by EPATCH_SOURCE.
95 +#
96 +# Any options specified that start with a dash will be passed down to patch
97 +# for this specific invocation. As soon as an arg w/out a dash is found, then
98 +# arg processing stops.
99 +#
100 +# When processing directories, epatch will apply all patches that match:
101 +# @CODE
102 +# if ${EPATCH_FORCE} != "yes"
103 +# ??_${ARCH}_foo.${EPATCH_SUFFIX}
104 +# else
105 +# *.${EPATCH_SUFFIX}
106 +# @CODE
107 +# The leading ?? are typically numbers used to force consistent patch ordering.
108 +# The arch field is used to apply patches only for the host architecture with
109 +# the special value of "all" means apply for everyone. Note that using values
110 +# other than "all" is highly discouraged -- you should apply patches all the
111 +# time and let architecture details be detected at configure/compile time.
112 +#
113 +# If EPATCH_SUFFIX is empty, then no period before it is implied when searching
114 +# for patches to apply.
115 +#
116 +# Refer to the other EPATCH_xxx variables for more customization of behavior.
117 +epatch() {
118 + _epatch_draw_line() {
119 + # create a line of same length as input string
120 + [[ -z $1 ]] && set "$(printf "%65s" '')"
121 + echo "${1//?/=}"
122 + }
123 +
124 + unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402
125 +
126 + # First process options. We localize the EPATCH_OPTS setting
127 + # from above so that we can pass it on in the loop below with
128 + # any additional values the user has specified.
129 + local EPATCH_OPTS=( ${EPATCH_OPTS[*]} )
130 + while [[ $# -gt 0 ]] ; do
131 + case $1 in
132 + -*) EPATCH_OPTS+=( "$1" ) ;;
133 + *) break ;;
134 + esac
135 + shift
136 + done
137 +
138 + # Let the rest of the code process one user arg at a time --
139 + # each arg may expand into multiple patches, and each arg may
140 + # need to start off with the default global EPATCH_xxx values
141 + if [[ $# -gt 1 ]] ; then
142 + local m
143 + for m in "$@" ; do
144 + epatch "${m}"
145 + done
146 + return 0
147 + fi
148 +
149 + local SINGLE_PATCH="no"
150 + # no args means process ${EPATCH_SOURCE}
151 + [[ $# -eq 0 ]] && set -- "${EPATCH_SOURCE}"
152 +
153 + if [[ -f $1 ]] ; then
154 + SINGLE_PATCH="yes"
155 + set -- "$1"
156 + # Use the suffix from the single patch (localize it); the code
157 + # below will find the suffix for us
158 + local EPATCH_SUFFIX=$1
159 +
160 + elif [[ -d $1 ]] ; then
161 + # We have to force sorting to C so that the wildcard expansion is consistent #471666.
162 + evar_push_set LC_COLLATE C
163 + # Some people like to make dirs of patches w/out suffixes (vim).
164 + set -- "$1"/*${EPATCH_SUFFIX:+."${EPATCH_SUFFIX}"}
165 + evar_pop
166 +
167 + elif [[ -f ${EPATCH_SOURCE}/$1 ]] ; then
168 + # Re-use EPATCH_SOURCE as a search dir
169 + epatch "${EPATCH_SOURCE}/$1"
170 + return $?
171 +
172 + else
173 + # sanity check ... if it isn't a dir or file, wtf man ?
174 + [[ $# -ne 0 ]] && EPATCH_SOURCE=$1
175 + echo
176 + eerror "Cannot find \$EPATCH_SOURCE! Value for \$EPATCH_SOURCE is:"
177 + eerror
178 + eerror " ${EPATCH_SOURCE}"
179 + eerror " ( ${EPATCH_SOURCE##*/} )"
180 + echo
181 + die "Cannot find \$EPATCH_SOURCE!"
182 + fi
183 +
184 + # Now that we know we're actually going to apply something, merge
185 + # all of the patch options back in to a single variable for below.
186 + EPATCH_OPTS="${EPATCH_COMMON_OPTS} ${EPATCH_OPTS[*]}"
187 +
188 + local PIPE_CMD
189 + case ${EPATCH_SUFFIX##*\.} in
190 + xz) PIPE_CMD="xz -dc" ;;
191 + lzma) PIPE_CMD="lzma -dc" ;;
192 + bz2) PIPE_CMD="bzip2 -dc" ;;
193 + gz|Z|z) PIPE_CMD="gzip -dc" ;;
194 + ZIP|zip) PIPE_CMD="unzip -p" ;;
195 + *) ;;
196 + esac
197 +
198 + [[ ${SINGLE_PATCH} == "no" ]] && einfo "${EPATCH_MULTI_MSG}"
199 +
200 + local x
201 + for x in "$@" ; do
202 + # If the patch dir given contains subdirs, or our EPATCH_SUFFIX
203 + # didn't match anything, ignore continue on
204 + [[ ! -f ${x} ]] && continue
205 +
206 + local patchname=${x##*/}
207 +
208 + # Apply single patches, or forced sets of patches, or
209 + # patches with ARCH dependant names.
210 + # ???_arch_foo.patch
211 + # Else, skip this input altogether
212 + local a=${patchname#*_} # strip the ???_
213 + a=${a%%_*} # strip the _foo.patch
214 + if ! [[ ${SINGLE_PATCH} == "yes" || \
215 + ${EPATCH_FORCE} == "yes" || \
216 + ${a} == all || \
217 + ${a} == ${ARCH} ]]
218 + then
219 + continue
220 + fi
221 +
222 + # Let people filter things dynamically
223 + if [[ -n ${EPATCH_EXCLUDE}${EPATCH_USER_EXCLUDE} ]] ; then
224 + # let people use globs in the exclude
225 + eshopts_push -o noglob
226 +
227 + local ex
228 + for ex in ${EPATCH_EXCLUDE} ; do
229 + if [[ ${patchname} == ${ex} ]] ; then
230 + einfo " Skipping ${patchname} due to EPATCH_EXCLUDE ..."
231 + eshopts_pop
232 + continue 2
233 + fi
234 + done
235 +
236 + for ex in ${EPATCH_USER_EXCLUDE} ; do
237 + if [[ ${patchname} == ${ex} ]] ; then
238 + einfo " Skipping ${patchname} due to EPATCH_USER_EXCLUDE ..."
239 + eshopts_pop
240 + continue 2
241 + fi
242 + done
243 +
244 + eshopts_pop
245 + fi
246 +
247 + if [[ ${SINGLE_PATCH} == "yes" ]] ; then
248 + if [[ -n ${EPATCH_SINGLE_MSG} ]] ; then
249 + einfo "${EPATCH_SINGLE_MSG}"
250 + else
251 + einfo "Applying ${patchname} ..."
252 + fi
253 + else
254 + einfo " ${patchname} ..."
255 + fi
256 +
257 + # Handle aliased patch command #404447 #461568
258 + local patch="patch"
259 + eval $(alias patch 2>/dev/null | sed 's:^alias ::')
260 +
261 + # most of the time, there will only be one run per unique name,
262 + # but if there are more, make sure we get unique log filenames
263 + local STDERR_TARGET="${T}/${patchname}.out"
264 + if [[ -e ${STDERR_TARGET} ]] ; then
265 + STDERR_TARGET="${T}/${patchname}-$$.out"
266 + fi
267 +
268 + printf "***** %s *****\nPWD: %s\nPATCH TOOL: %s -> %s\nVERSION INFO:\n%s\n\n" \
269 + "${patchname}" \
270 + "${PWD}" \
271 + "${patch}" \
272 + "$(type -P "${patch}")" \
273 + "$(${patch} --version)" \
274 + > "${STDERR_TARGET}"
275 +
276 + # Decompress the patch if need be
277 + local count=0
278 + local PATCH_TARGET
279 + if [[ -n ${PIPE_CMD} ]] ; then
280 + PATCH_TARGET="${T}/$$.patch"
281 + echo "PIPE_COMMAND: ${PIPE_CMD} ${x} > ${PATCH_TARGET}" >> "${STDERR_TARGET}"
282 +
283 + if ! (${PIPE_CMD} "${x}" > "${PATCH_TARGET}") >> "${STDERR_TARGET}" 2>&1 ; then
284 + echo
285 + eerror "Could not extract patch!"
286 + #die "Could not extract patch!"
287 + count=5
288 + break
289 + fi
290 + else
291 + PATCH_TARGET=${x}
292 + fi
293 +
294 + # Check for absolute paths in patches. If sandbox is disabled,
295 + # people could (accidently) patch files in the root filesystem.
296 + # Or trigger other unpleasantries #237667. So disallow -p0 on
297 + # such patches.
298 + local abs_paths=$(egrep -n '^[-+]{3} /' "${PATCH_TARGET}" | awk '$2 != "/dev/null" { print }')
299 + if [[ -n ${abs_paths} ]] ; then
300 + count=1
301 + printf "NOTE: skipping -p0 due to absolute paths in patch:\n%s\n" "${abs_paths}" >> "${STDERR_TARGET}"
302 + fi
303 + # Similar reason, but with relative paths.
304 + local rel_paths=$(egrep -n '^[-+]{3} [^ ]*[.][.]/' "${PATCH_TARGET}")
305 + if [[ -n ${rel_paths} ]] ; then
306 + echo
307 + eerror "Rejected Patch: ${patchname} !"
308 + eerror " ( ${PATCH_TARGET} )"
309 + eerror
310 + eerror "Your patch uses relative paths '../':"
311 + eerror "${rel_paths}"
312 + echo
313 + die "you need to fix the relative paths in patch"
314 + fi
315 +
316 + # Dynamically detect the correct -p# ... i'm lazy, so shoot me :/
317 + local patch_cmd
318 + while [[ ${count} -lt 5 ]] ; do
319 + patch_cmd="${patch} -p${count} ${EPATCH_OPTS}"
320 +
321 + # Generate some useful debug info ...
322 + (
323 + _epatch_draw_line "***** ${patchname} *****"
324 + echo
325 + echo "PATCH COMMAND: ${patch_cmd} --dry-run -f < '${PATCH_TARGET}'"
326 + echo
327 + _epatch_draw_line "***** ${patchname} *****"
328 + ${patch_cmd} --dry-run -f < "${PATCH_TARGET}" 2>&1
329 + ret=$?
330 + echo
331 + echo "patch program exited with status ${ret}"
332 + exit ${ret}
333 + ) >> "${STDERR_TARGET}"
334 +
335 + if [ $? -eq 0 ] ; then
336 + (
337 + _epatch_draw_line "***** ${patchname} *****"
338 + echo
339 + echo "ACTUALLY APPLYING ${patchname} ..."
340 + echo "PATCH COMMAND: ${patch_cmd} < '${PATCH_TARGET}'"
341 + echo
342 + _epatch_draw_line "***** ${patchname} *****"
343 + ${patch_cmd} < "${PATCH_TARGET}" 2>&1
344 + ret=$?
345 + echo
346 + echo "patch program exited with status ${ret}"
347 + exit ${ret}
348 + ) >> "${STDERR_TARGET}"
349 +
350 + if [ $? -ne 0 ] ; then
351 + echo
352 + eerror "A dry-run of patch command succeeded, but actually"
353 + eerror "applying the patch failed!"
354 + #die "Real world sux compared to the dreamworld!"
355 + count=5
356 + fi
357 + break
358 + fi
359 +
360 + : $(( count++ ))
361 + done
362 +
363 + (( EPATCH_N_APPLIED_PATCHES++ ))
364 +
365 + # if we had to decompress the patch, delete the temp one
366 + if [[ -n ${PIPE_CMD} ]] ; then
367 + rm -f "${PATCH_TARGET}"
368 + fi
369 +
370 + if [[ ${count} -ge 5 ]] ; then
371 + echo
372 + eerror "Failed Patch: ${patchname} !"
373 + eerror " ( ${PATCH_TARGET} )"
374 + eerror
375 + eerror "Include in your bugreport the contents of:"
376 + eerror
377 + eerror " ${STDERR_TARGET}"
378 + echo
379 + die "Failed Patch: ${patchname}!"
380 + fi
381 +
382 + # if everything worked, delete the full debug patch log
383 + rm -f "${STDERR_TARGET}"
384 +
385 + # then log away the exact stuff for people to review later
386 + cat <<-EOF >> "${T}/epatch.log"
387 + PATCH: ${x}
388 + CMD: ${patch_cmd}
389 + PWD: ${PWD}
390 +
391 + EOF
392 + eend 0
393 + done
394 +
395 + [[ ${SINGLE_PATCH} == "no" ]] && einfo "Done with patching"
396 + : # everything worked
397 +}
398 +
399 +case ${EAPI:-0} in
400 +0|1|2|3|4|5)
401 +
402 +# @VARIABLE: EPATCH_USER_SOURCE
403 +# @DESCRIPTION:
404 +# Location for user patches, see the epatch_user function.
405 +# Should be set by the user. Don't set this in ebuilds.
406 +: ${EPATCH_USER_SOURCE:=${PORTAGE_CONFIGROOT%/}/etc/portage/patches}
407 +
408 +# @FUNCTION: epatch_user
409 +# @USAGE:
410 +# @DESCRIPTION:
411 +# Applies user-provided patches to the source tree. The patches are
412 +# taken from /etc/portage/patches/<CATEGORY>/<P-PR|P|PN>[:SLOT]/, where the first
413 +# of these three directories to exist will be the one to use, ignoring
414 +# any more general directories which might exist as well. They must end
415 +# in ".patch" to be applied.
416 +#
417 +# User patches are intended for quick testing of patches without ebuild
418 +# modifications, as well as for permanent customizations a user might
419 +# desire. Obviously, there can be no official support for arbitrarily
420 +# patched ebuilds. So whenever a build log in a bug report mentions that
421 +# user patches were applied, the user should be asked to reproduce the
422 +# problem without these.
423 +#
424 +# Not all ebuilds do call this function, so placing patches in the
425 +# stated directory might or might not work, depending on the package and
426 +# the eclasses it inherits and uses. It is safe to call the function
427 +# repeatedly, so it is always possible to add a call at the ebuild
428 +# level. The first call is the time when the patches will be
429 +# applied.
430 +#
431 +# Ideally, this function should be called after gentoo-specific patches
432 +# have been applied, so that their code can be modified as well, but
433 +# before calls to e.g. eautoreconf, as the user patches might affect
434 +# autotool input files as well.
435 +epatch_user() {
436 + [[ $# -ne 0 ]] && die "epatch_user takes no options"
437 +
438 + # Allow multiple calls to this function; ignore all but the first
439 + local applied="${T}/epatch_user.log"
440 + [[ -e ${applied} ]] && return 2
441 +
442 + # don't clobber any EPATCH vars that the parent might want
443 + local EPATCH_SOURCE check
444 + for check in ${CATEGORY}/{${P}-${PR},${P},${PN}}{,:${SLOT%/*}}; do
445 + EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CTARGET}/${check}
446 + [[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CHOST}/${check}
447 + [[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${check}
448 + if [[ -d ${EPATCH_SOURCE} ]] ; then
449 + local old_n_applied_patches=${EPATCH_N_APPLIED_PATCHES:-0}
450 + EPATCH_SOURCE=${EPATCH_SOURCE} \
451 + EPATCH_SUFFIX="patch" \
452 + EPATCH_FORCE="yes" \
453 + EPATCH_MULTI_MSG="Applying user patches from ${EPATCH_SOURCE} ..." \
454 + epatch
455 + echo "${EPATCH_SOURCE}" > "${applied}"
456 + if [[ ${old_n_applied_patches} -lt ${EPATCH_N_APPLIED_PATCHES} ]]; then
457 + has epatch_user_death_notice ${EBUILD_DEATH_HOOKS} || \
458 + EBUILD_DEATH_HOOKS+=" epatch_user_death_notice"
459 + fi
460 + return 0
461 + fi
462 + done
463 + echo "none" > "${applied}"
464 + return 1
465 +}
466 +
467 +# @FUNCTION: epatch_user_death_notice
468 +# @INTERNAL
469 +# @DESCRIPTION:
470 +# Include an explicit notice in the die message itself that user patches were
471 +# applied to this build.
472 +epatch_user_death_notice() {
473 + ewarn "!!! User patches were applied to this build!"
474 +}
475 +
476 +esac
477 diff --git a/eclass/eutils.eclass b/eclass/eutils.eclass
478 index 7cca864025a6..2726333622bb 100644
479 --- a/eclass/eutils.eclass
480 +++ b/eclass/eutils.eclass
481 @@ -17,7 +17,7 @@
482 if [[ -z ${_EUTILS_ECLASS} ]]; then
483 _EUTILS_ECLASS=1
484
485 -inherit estack multilib toolchain-funcs
486 +inherit epatch estack multilib toolchain-funcs
487
488 # @FUNCTION: eqawarn
489 # @USAGE: [message]
490 @@ -63,370 +63,6 @@ egit_clean() {
491 find "$@" -type d -name '.git*' -prune -print0 | xargs -0 rm -rf
492 }
493
494 -# @VARIABLE: EPATCH_SOURCE
495 -# @DESCRIPTION:
496 -# Default directory to search for patches.
497 -EPATCH_SOURCE="${WORKDIR}/patch"
498 -# @VARIABLE: EPATCH_SUFFIX
499 -# @DESCRIPTION:
500 -# Default extension for patches (do not prefix the period yourself).
501 -EPATCH_SUFFIX="patch.bz2"
502 -# @VARIABLE: EPATCH_OPTS
503 -# @DESCRIPTION:
504 -# Options to pass to patch. Meant for ebuild/package-specific tweaking
505 -# such as forcing the patch level (-p#) or fuzz (-F#) factor. Note that
506 -# for single patch tweaking, you can also pass flags directly to epatch.
507 -EPATCH_OPTS=""
508 -# @VARIABLE: EPATCH_COMMON_OPTS
509 -# @DESCRIPTION:
510 -# Common options to pass to `patch`. You probably should never need to
511 -# change these. If you do, please discuss it with base-system first to
512 -# be sure.
513 -# @CODE
514 -# -g0 - keep RCS, ClearCase, Perforce and SCCS happy #24571
515 -# --no-backup-if-mismatch - do not leave .orig files behind
516 -# -E - automatically remove empty files
517 -# @CODE
518 -EPATCH_COMMON_OPTS="-g0 -E --no-backup-if-mismatch"
519 -# @VARIABLE: EPATCH_EXCLUDE
520 -# @DESCRIPTION:
521 -# List of patches not to apply. Note this is only file names,
522 -# and not the full path. Globs accepted.
523 -EPATCH_EXCLUDE=""
524 -# @VARIABLE: EPATCH_SINGLE_MSG
525 -# @DESCRIPTION:
526 -# Change the printed message for a single patch.
527 -EPATCH_SINGLE_MSG=""
528 -# @VARIABLE: EPATCH_MULTI_MSG
529 -# @DESCRIPTION:
530 -# Change the printed message for multiple patches.
531 -EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates) ..."
532 -# @VARIABLE: EPATCH_FORCE
533 -# @DESCRIPTION:
534 -# Only require patches to match EPATCH_SUFFIX rather than the extended
535 -# arch naming style.
536 -EPATCH_FORCE="no"
537 -# @VARIABLE: EPATCH_USER_EXCLUDE
538 -# @DEFAULT_UNSET
539 -# @DESCRIPTION:
540 -# List of patches not to apply. Note this is only file names,
541 -# and not the full path. Globs accepted.
542 -
543 -# @FUNCTION: epatch
544 -# @USAGE: [options] [patches] [dirs of patches]
545 -# @DESCRIPTION:
546 -# epatch is designed to greatly simplify the application of patches. It can
547 -# process patch files directly, or directories of patches. The patches may be
548 -# compressed (bzip/gzip/etc...) or plain text. You generally need not specify
549 -# the -p option as epatch will automatically attempt -p0 to -p4 until things
550 -# apply successfully.
551 -#
552 -# If you do not specify any patches/dirs, then epatch will default to the
553 -# directory specified by EPATCH_SOURCE.
554 -#
555 -# Any options specified that start with a dash will be passed down to patch
556 -# for this specific invocation. As soon as an arg w/out a dash is found, then
557 -# arg processing stops.
558 -#
559 -# When processing directories, epatch will apply all patches that match:
560 -# @CODE
561 -# if ${EPATCH_FORCE} != "yes"
562 -# ??_${ARCH}_foo.${EPATCH_SUFFIX}
563 -# else
564 -# *.${EPATCH_SUFFIX}
565 -# @CODE
566 -# The leading ?? are typically numbers used to force consistent patch ordering.
567 -# The arch field is used to apply patches only for the host architecture with
568 -# the special value of "all" means apply for everyone. Note that using values
569 -# other than "all" is highly discouraged -- you should apply patches all the
570 -# time and let architecture details be detected at configure/compile time.
571 -#
572 -# If EPATCH_SUFFIX is empty, then no period before it is implied when searching
573 -# for patches to apply.
574 -#
575 -# Refer to the other EPATCH_xxx variables for more customization of behavior.
576 -epatch() {
577 - _epatch_draw_line() {
578 - # create a line of same length as input string
579 - [[ -z $1 ]] && set "$(printf "%65s" '')"
580 - echo "${1//?/=}"
581 - }
582 -
583 - unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402
584 -
585 - # First process options. We localize the EPATCH_OPTS setting
586 - # from above so that we can pass it on in the loop below with
587 - # any additional values the user has specified.
588 - local EPATCH_OPTS=( ${EPATCH_OPTS[*]} )
589 - while [[ $# -gt 0 ]] ; do
590 - case $1 in
591 - -*) EPATCH_OPTS+=( "$1" ) ;;
592 - *) break ;;
593 - esac
594 - shift
595 - done
596 -
597 - # Let the rest of the code process one user arg at a time --
598 - # each arg may expand into multiple patches, and each arg may
599 - # need to start off with the default global EPATCH_xxx values
600 - if [[ $# -gt 1 ]] ; then
601 - local m
602 - for m in "$@" ; do
603 - epatch "${m}"
604 - done
605 - return 0
606 - fi
607 -
608 - local SINGLE_PATCH="no"
609 - # no args means process ${EPATCH_SOURCE}
610 - [[ $# -eq 0 ]] && set -- "${EPATCH_SOURCE}"
611 -
612 - if [[ -f $1 ]] ; then
613 - SINGLE_PATCH="yes"
614 - set -- "$1"
615 - # Use the suffix from the single patch (localize it); the code
616 - # below will find the suffix for us
617 - local EPATCH_SUFFIX=$1
618 -
619 - elif [[ -d $1 ]] ; then
620 - # We have to force sorting to C so that the wildcard expansion is consistent #471666.
621 - evar_push_set LC_COLLATE C
622 - # Some people like to make dirs of patches w/out suffixes (vim).
623 - set -- "$1"/*${EPATCH_SUFFIX:+."${EPATCH_SUFFIX}"}
624 - evar_pop
625 -
626 - elif [[ -f ${EPATCH_SOURCE}/$1 ]] ; then
627 - # Re-use EPATCH_SOURCE as a search dir
628 - epatch "${EPATCH_SOURCE}/$1"
629 - return $?
630 -
631 - else
632 - # sanity check ... if it isn't a dir or file, wtf man ?
633 - [[ $# -ne 0 ]] && EPATCH_SOURCE=$1
634 - echo
635 - eerror "Cannot find \$EPATCH_SOURCE! Value for \$EPATCH_SOURCE is:"
636 - eerror
637 - eerror " ${EPATCH_SOURCE}"
638 - eerror " ( ${EPATCH_SOURCE##*/} )"
639 - echo
640 - die "Cannot find \$EPATCH_SOURCE!"
641 - fi
642 -
643 - # Now that we know we're actually going to apply something, merge
644 - # all of the patch options back in to a single variable for below.
645 - EPATCH_OPTS="${EPATCH_COMMON_OPTS} ${EPATCH_OPTS[*]}"
646 -
647 - local PIPE_CMD
648 - case ${EPATCH_SUFFIX##*\.} in
649 - xz) PIPE_CMD="xz -dc" ;;
650 - lzma) PIPE_CMD="lzma -dc" ;;
651 - bz2) PIPE_CMD="bzip2 -dc" ;;
652 - gz|Z|z) PIPE_CMD="gzip -dc" ;;
653 - ZIP|zip) PIPE_CMD="unzip -p" ;;
654 - *) ;;
655 - esac
656 -
657 - [[ ${SINGLE_PATCH} == "no" ]] && einfo "${EPATCH_MULTI_MSG}"
658 -
659 - local x
660 - for x in "$@" ; do
661 - # If the patch dir given contains subdirs, or our EPATCH_SUFFIX
662 - # didn't match anything, ignore continue on
663 - [[ ! -f ${x} ]] && continue
664 -
665 - local patchname=${x##*/}
666 -
667 - # Apply single patches, or forced sets of patches, or
668 - # patches with ARCH dependant names.
669 - # ???_arch_foo.patch
670 - # Else, skip this input altogether
671 - local a=${patchname#*_} # strip the ???_
672 - a=${a%%_*} # strip the _foo.patch
673 - if ! [[ ${SINGLE_PATCH} == "yes" || \
674 - ${EPATCH_FORCE} == "yes" || \
675 - ${a} == all || \
676 - ${a} == ${ARCH} ]]
677 - then
678 - continue
679 - fi
680 -
681 - # Let people filter things dynamically
682 - if [[ -n ${EPATCH_EXCLUDE}${EPATCH_USER_EXCLUDE} ]] ; then
683 - # let people use globs in the exclude
684 - eshopts_push -o noglob
685 -
686 - local ex
687 - for ex in ${EPATCH_EXCLUDE} ; do
688 - if [[ ${patchname} == ${ex} ]] ; then
689 - einfo " Skipping ${patchname} due to EPATCH_EXCLUDE ..."
690 - eshopts_pop
691 - continue 2
692 - fi
693 - done
694 -
695 - for ex in ${EPATCH_USER_EXCLUDE} ; do
696 - if [[ ${patchname} == ${ex} ]] ; then
697 - einfo " Skipping ${patchname} due to EPATCH_USER_EXCLUDE ..."
698 - eshopts_pop
699 - continue 2
700 - fi
701 - done
702 -
703 - eshopts_pop
704 - fi
705 -
706 - if [[ ${SINGLE_PATCH} == "yes" ]] ; then
707 - if [[ -n ${EPATCH_SINGLE_MSG} ]] ; then
708 - einfo "${EPATCH_SINGLE_MSG}"
709 - else
710 - einfo "Applying ${patchname} ..."
711 - fi
712 - else
713 - einfo " ${patchname} ..."
714 - fi
715 -
716 - # Handle aliased patch command #404447 #461568
717 - local patch="patch"
718 - eval $(alias patch 2>/dev/null | sed 's:^alias ::')
719 -
720 - # most of the time, there will only be one run per unique name,
721 - # but if there are more, make sure we get unique log filenames
722 - local STDERR_TARGET="${T}/${patchname}.out"
723 - if [[ -e ${STDERR_TARGET} ]] ; then
724 - STDERR_TARGET="${T}/${patchname}-$$.out"
725 - fi
726 -
727 - printf "***** %s *****\nPWD: %s\nPATCH TOOL: %s -> %s\nVERSION INFO:\n%s\n\n" \
728 - "${patchname}" \
729 - "${PWD}" \
730 - "${patch}" \
731 - "$(type -P "${patch}")" \
732 - "$(${patch} --version)" \
733 - > "${STDERR_TARGET}"
734 -
735 - # Decompress the patch if need be
736 - local count=0
737 - local PATCH_TARGET
738 - if [[ -n ${PIPE_CMD} ]] ; then
739 - PATCH_TARGET="${T}/$$.patch"
740 - echo "PIPE_COMMAND: ${PIPE_CMD} ${x} > ${PATCH_TARGET}" >> "${STDERR_TARGET}"
741 -
742 - if ! (${PIPE_CMD} "${x}" > "${PATCH_TARGET}") >> "${STDERR_TARGET}" 2>&1 ; then
743 - echo
744 - eerror "Could not extract patch!"
745 - #die "Could not extract patch!"
746 - count=5
747 - break
748 - fi
749 - else
750 - PATCH_TARGET=${x}
751 - fi
752 -
753 - # Check for absolute paths in patches. If sandbox is disabled,
754 - # people could (accidently) patch files in the root filesystem.
755 - # Or trigger other unpleasantries #237667. So disallow -p0 on
756 - # such patches.
757 - local abs_paths=$(egrep -n '^[-+]{3} /' "${PATCH_TARGET}" | awk '$2 != "/dev/null" { print }')
758 - if [[ -n ${abs_paths} ]] ; then
759 - count=1
760 - printf "NOTE: skipping -p0 due to absolute paths in patch:\n%s\n" "${abs_paths}" >> "${STDERR_TARGET}"
761 - fi
762 - # Similar reason, but with relative paths.
763 - local rel_paths=$(egrep -n '^[-+]{3} [^ ]*[.][.]/' "${PATCH_TARGET}")
764 - if [[ -n ${rel_paths} ]] ; then
765 - echo
766 - eerror "Rejected Patch: ${patchname} !"
767 - eerror " ( ${PATCH_TARGET} )"
768 - eerror
769 - eerror "Your patch uses relative paths '../':"
770 - eerror "${rel_paths}"
771 - echo
772 - die "you need to fix the relative paths in patch"
773 - fi
774 -
775 - # Dynamically detect the correct -p# ... i'm lazy, so shoot me :/
776 - local patch_cmd
777 - while [[ ${count} -lt 5 ]] ; do
778 - patch_cmd="${patch} -p${count} ${EPATCH_OPTS}"
779 -
780 - # Generate some useful debug info ...
781 - (
782 - _epatch_draw_line "***** ${patchname} *****"
783 - echo
784 - echo "PATCH COMMAND: ${patch_cmd} --dry-run -f < '${PATCH_TARGET}'"
785 - echo
786 - _epatch_draw_line "***** ${patchname} *****"
787 - ${patch_cmd} --dry-run -f < "${PATCH_TARGET}" 2>&1
788 - ret=$?
789 - echo
790 - echo "patch program exited with status ${ret}"
791 - exit ${ret}
792 - ) >> "${STDERR_TARGET}"
793 -
794 - if [ $? -eq 0 ] ; then
795 - (
796 - _epatch_draw_line "***** ${patchname} *****"
797 - echo
798 - echo "ACTUALLY APPLYING ${patchname} ..."
799 - echo "PATCH COMMAND: ${patch_cmd} < '${PATCH_TARGET}'"
800 - echo
801 - _epatch_draw_line "***** ${patchname} *****"
802 - ${patch_cmd} < "${PATCH_TARGET}" 2>&1
803 - ret=$?
804 - echo
805 - echo "patch program exited with status ${ret}"
806 - exit ${ret}
807 - ) >> "${STDERR_TARGET}"
808 -
809 - if [ $? -ne 0 ] ; then
810 - echo
811 - eerror "A dry-run of patch command succeeded, but actually"
812 - eerror "applying the patch failed!"
813 - #die "Real world sux compared to the dreamworld!"
814 - count=5
815 - fi
816 - break
817 - fi
818 -
819 - : $(( count++ ))
820 - done
821 -
822 - (( EPATCH_N_APPLIED_PATCHES++ ))
823 -
824 - # if we had to decompress the patch, delete the temp one
825 - if [[ -n ${PIPE_CMD} ]] ; then
826 - rm -f "${PATCH_TARGET}"
827 - fi
828 -
829 - if [[ ${count} -ge 5 ]] ; then
830 - echo
831 - eerror "Failed Patch: ${patchname} !"
832 - eerror " ( ${PATCH_TARGET} )"
833 - eerror
834 - eerror "Include in your bugreport the contents of:"
835 - eerror
836 - eerror " ${STDERR_TARGET}"
837 - echo
838 - die "Failed Patch: ${patchname}!"
839 - fi
840 -
841 - # if everything worked, delete the full debug patch log
842 - rm -f "${STDERR_TARGET}"
843 -
844 - # then log away the exact stuff for people to review later
845 - cat <<-EOF >> "${T}/epatch.log"
846 - PATCH: ${x}
847 - CMD: ${patch_cmd}
848 - PWD: ${PWD}
849 -
850 - EOF
851 - eend 0
852 - done
853 -
854 - [[ ${SINGLE_PATCH} == "no" ]] && einfo "Done with patching"
855 - : # everything worked
856 -}
857 -
858 # @FUNCTION: emktemp
859 # @USAGE: [temp dir]
860 # @DESCRIPTION:
861 @@ -1486,80 +1122,6 @@ esac
862 case ${EAPI:-0} in
863 0|1|2|3|4|5)
864
865 -# @VARIABLE: EPATCH_USER_SOURCE
866 -# @DESCRIPTION:
867 -# Location for user patches, see the epatch_user function.
868 -# Should be set by the user. Don't set this in ebuilds.
869 -: ${EPATCH_USER_SOURCE:=${PORTAGE_CONFIGROOT%/}/etc/portage/patches}
870 -
871 -# @FUNCTION: epatch_user
872 -# @USAGE:
873 -# @DESCRIPTION:
874 -# Applies user-provided patches to the source tree. The patches are
875 -# taken from /etc/portage/patches/<CATEGORY>/<P-PR|P|PN>[:SLOT]/, where the first
876 -# of these three directories to exist will be the one to use, ignoring
877 -# any more general directories which might exist as well. They must end
878 -# in ".patch" to be applied.
879 -#
880 -# User patches are intended for quick testing of patches without ebuild
881 -# modifications, as well as for permanent customizations a user might
882 -# desire. Obviously, there can be no official support for arbitrarily
883 -# patched ebuilds. So whenever a build log in a bug report mentions that
884 -# user patches were applied, the user should be asked to reproduce the
885 -# problem without these.
886 -#
887 -# Not all ebuilds do call this function, so placing patches in the
888 -# stated directory might or might not work, depending on the package and
889 -# the eclasses it inherits and uses. It is safe to call the function
890 -# repeatedly, so it is always possible to add a call at the ebuild
891 -# level. The first call is the time when the patches will be
892 -# applied.
893 -#
894 -# Ideally, this function should be called after gentoo-specific patches
895 -# have been applied, so that their code can be modified as well, but
896 -# before calls to e.g. eautoreconf, as the user patches might affect
897 -# autotool input files as well.
898 -epatch_user() {
899 - [[ $# -ne 0 ]] && die "epatch_user takes no options"
900 -
901 - # Allow multiple calls to this function; ignore all but the first
902 - local applied="${T}/epatch_user.log"
903 - [[ -e ${applied} ]] && return 2
904 -
905 - # don't clobber any EPATCH vars that the parent might want
906 - local EPATCH_SOURCE check
907 - for check in ${CATEGORY}/{${P}-${PR},${P},${PN}}{,:${SLOT%/*}}; do
908 - EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CTARGET}/${check}
909 - [[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CHOST}/${check}
910 - [[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${check}
911 - if [[ -d ${EPATCH_SOURCE} ]] ; then
912 - local old_n_applied_patches=${EPATCH_N_APPLIED_PATCHES:-0}
913 - EPATCH_SOURCE=${EPATCH_SOURCE} \
914 - EPATCH_SUFFIX="patch" \
915 - EPATCH_FORCE="yes" \
916 - EPATCH_MULTI_MSG="Applying user patches from ${EPATCH_SOURCE} ..." \
917 - epatch
918 - echo "${EPATCH_SOURCE}" > "${applied}"
919 - if [[ ${old_n_applied_patches} -lt ${EPATCH_N_APPLIED_PATCHES} ]]; then
920 - has epatch_user_death_notice ${EBUILD_DEATH_HOOKS} || \
921 - EBUILD_DEATH_HOOKS+=" epatch_user_death_notice"
922 - fi
923 - return 0
924 - fi
925 - done
926 - echo "none" > "${applied}"
927 - return 1
928 -}
929 -
930 -# @FUNCTION: epatch_user_death_notice
931 -# @INTERNAL
932 -# @DESCRIPTION:
933 -# Include an explicit notice in the die message itself that user patches were
934 -# applied to this build.
935 -epatch_user_death_notice() {
936 - ewarn "!!! User patches were applied to this build!"
937 -}
938 -
939 # @FUNCTION: einstalldocs
940 # @DESCRIPTION:
941 # Install documentation using DOCS and HTML_DOCS.
942 --
943 2.12.0

Replies