Gentoo Archives: gentoo-dev

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

Attachments

File name MIME type
signature.asc application/pgp-signature