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

Replies