Merge remote-tracking branch 'github/pr/379'.
[gentoo.git] / eclass / eutils.eclass
1 # Copyright 1999-2015 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Id$
4
5 # @ECLASS: eutils.eclass
6 # @MAINTAINER:
7 # base-system@gentoo.org
8 # @BLURB: many extra (but common) functions that are used in ebuilds
9 # @DESCRIPTION:
10 # The eutils eclass contains a suite of functions that complement
11 # the ones that ebuild.sh already contain.  The idea is that the functions
12 # are not required in all ebuilds but enough utilize them to have a common
13 # home rather than having multiple ebuilds implementing the same thing.
14 #
15 # Due to the nature of this eclass, some functions may have maintainers
16 # different from the overall eclass!
17
18 if [[ -z ${_EUTILS_ECLASS} ]]; then
19 _EUTILS_ECLASS=1
20
21 inherit multilib toolchain-funcs
22
23 if has "${EAPI:-0}" 0 1 2; then
24
25 # @FUNCTION: epause
26 # @USAGE: [seconds]
27 # @DESCRIPTION:
28 # Sleep for the specified number of seconds (default of 5 seconds).  Useful when
29 # printing a message the user should probably be reading and often used in
30 # conjunction with the ebeep function.  If the EPAUSE_IGNORE env var is set,
31 # don't wait at all. Defined in EAPIs 0 1 and 2.
32 epause() {
33         [[ -z ${EPAUSE_IGNORE} ]] && sleep ${1:-5}
34 }
35
36 # @FUNCTION: ebeep
37 # @USAGE: [number of beeps]
38 # @DESCRIPTION:
39 # Issue the specified number of beeps (default of 5 beeps).  Useful when
40 # printing a message the user should probably be reading and often used in
41 # conjunction with the epause function.  If the EBEEP_IGNORE env var is set,
42 # don't beep at all. Defined in EAPIs 0 1 and 2.
43 ebeep() {
44         local n
45         if [[ -z ${EBEEP_IGNORE} ]] ; then
46                 for ((n=1 ; n <= ${1:-5} ; n++)) ; do
47                         echo -ne "\a"
48                         sleep 0.1 &>/dev/null ; sleep 0,1 &>/dev/null
49                         echo -ne "\a"
50                         sleep 1
51                 done
52         fi
53 }
54
55 else
56
57 ebeep() {
58         ewarn "QA Notice: ebeep is not defined in EAPI=${EAPI}, please file a bug at https://bugs.gentoo.org"
59 }
60
61 epause() {
62         ewarn "QA Notice: epause is not defined in EAPI=${EAPI}, please file a bug at https://bugs.gentoo.org"
63 }
64
65 fi
66
67 # @FUNCTION: eqawarn
68 # @USAGE: [message]
69 # @DESCRIPTION:
70 # Proxy to ewarn for package managers that don't provide eqawarn and use the PM
71 # implementation if available. Reuses PORTAGE_ELOG_CLASSES as set by the dev
72 # profile.
73 if ! declare -F eqawarn >/dev/null ; then
74         eqawarn() {
75                 has qa ${PORTAGE_ELOG_CLASSES} && ewarn "$@"
76                 :
77         }
78 fi
79
80 # @FUNCTION: ecvs_clean
81 # @USAGE: [list of dirs]
82 # @DESCRIPTION:
83 # Remove CVS directories recursiveley.  Useful when a source tarball contains
84 # internal CVS directories.  Defaults to $PWD.
85 ecvs_clean() {
86         [[ -z $* ]] && set -- .
87         find "$@" -type d -name 'CVS' -prune -print0 | xargs -0 rm -rf
88         find "$@" -type f -name '.cvs*' -print0 | xargs -0 rm -rf
89 }
90
91 # @FUNCTION: esvn_clean
92 # @USAGE: [list of dirs]
93 # @DESCRIPTION:
94 # Remove .svn directories recursiveley.  Useful when a source tarball contains
95 # internal Subversion directories.  Defaults to $PWD.
96 esvn_clean() {
97         [[ -z $* ]] && set -- .
98         find "$@" -type d -name '.svn' -prune -print0 | xargs -0 rm -rf
99 }
100
101 # @FUNCTION: estack_push
102 # @USAGE: <stack> [items to push]
103 # @DESCRIPTION:
104 # Push any number of items onto the specified stack.  Pick a name that
105 # is a valid variable (i.e. stick to alphanumerics), and push as many
106 # items as you like onto the stack at once.
107 #
108 # The following code snippet will echo 5, then 4, then 3, then ...
109 # @CODE
110 #               estack_push mystack 1 2 3 4 5
111 #               while estack_pop mystack i ; do
112 #                       echo "${i}"
113 #               done
114 # @CODE
115 estack_push() {
116         [[ $# -eq 0 ]] && die "estack_push: incorrect # of arguments"
117         local stack_name="_ESTACK_$1_" ; shift
118         eval ${stack_name}+=\( \"\$@\" \)
119 }
120
121 # @FUNCTION: estack_pop
122 # @USAGE: <stack> [variable]
123 # @DESCRIPTION:
124 # Pop a single item off the specified stack.  If a variable is specified,
125 # the popped item is stored there.  If no more items are available, return
126 # 1, else return 0.  See estack_push for more info.
127 estack_pop() {
128         [[ $# -eq 0 || $# -gt 2 ]] && die "estack_pop: incorrect # of arguments"
129
130         # We use the fugly _estack_xxx var names to avoid collision with
131         # passing back the return value.  If we used "local i" and the
132         # caller ran `estack_pop ... i`, we'd end up setting the local
133         # copy of "i" rather than the caller's copy.  The _estack_xxx
134         # garbage is preferable to using $1/$2 everywhere as that is a
135         # bit harder to read.
136         local _estack_name="_ESTACK_$1_" ; shift
137         local _estack_retvar=$1 ; shift
138         eval local _estack_i=\${#${_estack_name}\[@\]}
139         # Don't warn -- let the caller interpret this as a failure
140         # or as normal behavior (akin to `shift`)
141         [[ $(( --_estack_i )) -eq -1 ]] && return 1
142
143         if [[ -n ${_estack_retvar} ]] ; then
144                 eval ${_estack_retvar}=\"\${${_estack_name}\[${_estack_i}\]}\"
145         fi
146         eval unset ${_estack_name}\[${_estack_i}\]
147 }
148
149 # @FUNCTION: evar_push
150 # @USAGE: <variable to save> [more vars to save]
151 # @DESCRIPTION:
152 # This let's you temporarily modify a variable and then restore it (including
153 # set vs unset semantics).  Arrays are not supported at this time.
154 #
155 # This is meant for variables where using `local` does not work (such as
156 # exported variables, or only temporarily changing things in a func).
157 #
158 # For example:
159 # @CODE
160 #               evar_push LC_ALL
161 #               export LC_ALL=C
162 #               ... do some stuff that needs LC_ALL=C set ...
163 #               evar_pop
164 #
165 #               # You can also save/restore more than one var at a time
166 #               evar_push BUTTERFLY IN THE SKY
167 #               ... do stuff with the vars ...
168 #               evar_pop     # This restores just one var, SKY
169 #               ... do more stuff ...
170 #               evar_pop 3   # This pops the remaining 3 vars
171 # @CODE
172 evar_push() {
173         local var val
174         for var ; do
175                 [[ ${!var+set} == "set" ]] \
176                         && val=${!var} \
177                         || val="unset_76fc3c462065bb4ca959f939e6793f94"
178                 estack_push evar "${var}" "${val}"
179         done
180 }
181
182 # @FUNCTION: evar_push_set
183 # @USAGE: <variable to save> [new value to store]
184 # @DESCRIPTION:
185 # This is a handy shortcut to save and temporarily set a variable.  If a value
186 # is not specified, the var will be unset.
187 evar_push_set() {
188         local var=$1
189         evar_push ${var}
190         case $# in
191         1) unset ${var} ;;
192         2) printf -v "${var}" '%s' "$2" ;;
193         *) die "${FUNCNAME}: incorrect # of args: $*" ;;
194         esac
195 }
196
197 # @FUNCTION: evar_pop
198 # @USAGE: [number of vars to restore]
199 # @DESCRIPTION:
200 # Restore the variables to the state saved with the corresponding
201 # evar_push call.  See that function for more details.
202 evar_pop() {
203         local cnt=${1:-bad}
204         case $# in
205         0) cnt=1 ;;
206         1) isdigit "${cnt}" || die "${FUNCNAME}: first arg must be a number: $*" ;;
207         *) die "${FUNCNAME}: only accepts one arg: $*" ;;
208         esac
209
210         local var val
211         while (( cnt-- )) ; do
212                 estack_pop evar val || die "${FUNCNAME}: unbalanced push"
213                 estack_pop evar var || die "${FUNCNAME}: unbalanced push"
214                 [[ ${val} == "unset_76fc3c462065bb4ca959f939e6793f94" ]] \
215                         && unset ${var} \
216                         || printf -v "${var}" '%s' "${val}"
217         done
218 }
219
220 # @FUNCTION: eshopts_push
221 # @USAGE: [options to `set` or `shopt`]
222 # @DESCRIPTION:
223 # Often times code will want to enable a shell option to change code behavior.
224 # Since changing shell options can easily break other pieces of code (which
225 # assume the default state), eshopts_push is used to (1) push the current shell
226 # options onto a stack and (2) pass the specified arguments to set.
227 #
228 # If the first argument is '-s' or '-u', we assume you want to call `shopt`
229 # rather than `set` as there are some options only available via that.
230 #
231 # A common example is to disable shell globbing so that special meaning/care
232 # may be used with variables/arguments to custom functions.  That would be:
233 # @CODE
234 #               eshopts_push -o noglob
235 #               for x in ${foo} ; do
236 #                       if ...some check... ; then
237 #                               eshopts_pop
238 #                               return 0
239 #                       fi
240 #               done
241 #               eshopts_pop
242 # @CODE
243 eshopts_push() {
244         if [[ $1 == -[su] ]] ; then
245                 estack_push eshopts "$(shopt -p)"
246                 [[ $# -eq 0 ]] && return 0
247                 shopt "$@" || die "${FUNCNAME}: bad options to shopt: $*"
248         else
249                 estack_push eshopts $-
250                 [[ $# -eq 0 ]] && return 0
251                 set "$@" || die "${FUNCNAME}: bad options to set: $*"
252         fi
253 }
254
255 # @FUNCTION: eshopts_pop
256 # @USAGE:
257 # @DESCRIPTION:
258 # Restore the shell options to the state saved with the corresponding
259 # eshopts_push call.  See that function for more details.
260 eshopts_pop() {
261         local s
262         estack_pop eshopts s || die "${FUNCNAME}: unbalanced push"
263         if [[ ${s} == "shopt -"* ]] ; then
264                 eval "${s}" || die "${FUNCNAME}: sanity: invalid shopt options: ${s}"
265         else
266                 set +$-     || die "${FUNCNAME}: sanity: invalid shell settings: $-"
267                 set -${s}   || die "${FUNCNAME}: sanity: unable to restore saved shell settings: ${s}"
268         fi
269 }
270
271 # @FUNCTION: eumask_push
272 # @USAGE: <new umask>
273 # @DESCRIPTION:
274 # Set the umask to the new value specified while saving the previous
275 # value onto a stack.  Useful for temporarily changing the umask.
276 eumask_push() {
277         estack_push eumask "$(umask)"
278         umask "$@" || die "${FUNCNAME}: bad options to umask: $*"
279 }
280
281 # @FUNCTION: eumask_pop
282 # @USAGE:
283 # @DESCRIPTION:
284 # Restore the previous umask state.
285 eumask_pop() {
286         [[ $# -eq 0 ]] || die "${FUNCNAME}: we take no options"
287         local s
288         estack_pop eumask s || die "${FUNCNAME}: unbalanced push"
289         umask ${s} || die "${FUNCNAME}: sanity: could not restore umask: ${s}"
290 }
291
292 # @FUNCTION: isdigit
293 # @USAGE: <number> [more numbers]
294 # @DESCRIPTION:
295 # Return true if all arguments are numbers.
296 isdigit() {
297         local d
298         for d ; do
299                 [[ ${d:-bad} == *[!0-9]* ]] && return 1
300         done
301         return 0
302 }
303
304 # @VARIABLE: EPATCH_SOURCE
305 # @DESCRIPTION:
306 # Default directory to search for patches.
307 EPATCH_SOURCE="${WORKDIR}/patch"
308 # @VARIABLE: EPATCH_SUFFIX
309 # @DESCRIPTION:
310 # Default extension for patches (do not prefix the period yourself).
311 EPATCH_SUFFIX="patch.bz2"
312 # @VARIABLE: EPATCH_OPTS
313 # @DESCRIPTION:
314 # Options to pass to patch.  Meant for ebuild/package-specific tweaking
315 # such as forcing the patch level (-p#) or fuzz (-F#) factor.  Note that
316 # for single patch tweaking, you can also pass flags directly to epatch.
317 EPATCH_OPTS=""
318 # @VARIABLE: EPATCH_COMMON_OPTS
319 # @DESCRIPTION:
320 # Common options to pass to `patch`.  You probably should never need to
321 # change these.  If you do, please discuss it with base-system first to
322 # be sure.
323 # @CODE
324 #       -g0 - keep RCS, ClearCase, Perforce and SCCS happy #24571
325 #       --no-backup-if-mismatch - do not leave .orig files behind
326 #       -E - automatically remove empty files
327 # @CODE
328 EPATCH_COMMON_OPTS="-g0 -E --no-backup-if-mismatch"
329 # @VARIABLE: EPATCH_EXCLUDE
330 # @DESCRIPTION:
331 # List of patches not to apply.  Note this is only file names,
332 # and not the full path.  Globs accepted.
333 EPATCH_EXCLUDE=""
334 # @VARIABLE: EPATCH_SINGLE_MSG
335 # @DESCRIPTION:
336 # Change the printed message for a single patch.
337 EPATCH_SINGLE_MSG=""
338 # @VARIABLE: EPATCH_MULTI_MSG
339 # @DESCRIPTION:
340 # Change the printed message for multiple patches.
341 EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates) ..."
342 # @VARIABLE: EPATCH_FORCE
343 # @DESCRIPTION:
344 # Only require patches to match EPATCH_SUFFIX rather than the extended
345 # arch naming style.
346 EPATCH_FORCE="no"
347 # @VARIABLE: EPATCH_USER_EXCLUDE
348 # @DEFAULT_UNSET
349 # @DESCRIPTION:
350 # List of patches not to apply.  Note this is only file names,
351 # and not the full path.  Globs accepted.
352
353 # @VARIABLE: EPATCH_USER_SOURCE
354 # @DESCRIPTION:
355 # Location for user patches, see the epatch_user function.
356 # Should be set by the user. Don't set this in ebuilds.
357 : ${EPATCH_USER_SOURCE:=${PORTAGE_CONFIGROOT%/}/etc/portage/patches}
358
359 # @FUNCTION: epatch
360 # @USAGE: [options] [patches] [dirs of patches]
361 # @DESCRIPTION:
362 # epatch is designed to greatly simplify the application of patches.  It can
363 # process patch files directly, or directories of patches.  The patches may be
364 # compressed (bzip/gzip/etc...) or plain text.  You generally need not specify
365 # the -p option as epatch will automatically attempt -p0 to -p4 until things
366 # apply successfully.
367 #
368 # If you do not specify any patches/dirs, then epatch will default to the
369 # directory specified by EPATCH_SOURCE.
370 #
371 # Any options specified that start with a dash will be passed down to patch
372 # for this specific invocation.  As soon as an arg w/out a dash is found, then
373 # arg processing stops.
374 #
375 # When processing directories, epatch will apply all patches that match:
376 # @CODE
377 #       if ${EPATCH_FORCE} != "yes"
378 #               ??_${ARCH}_foo.${EPATCH_SUFFIX}
379 #       else
380 #               *.${EPATCH_SUFFIX}
381 # @CODE
382 # The leading ?? are typically numbers used to force consistent patch ordering.
383 # The arch field is used to apply patches only for the host architecture with
384 # the special value of "all" means apply for everyone.  Note that using values
385 # other than "all" is highly discouraged -- you should apply patches all the
386 # time and let architecture details be detected at configure/compile time.
387 #
388 # If EPATCH_SUFFIX is empty, then no period before it is implied when searching
389 # for patches to apply.
390 #
391 # Refer to the other EPATCH_xxx variables for more customization of behavior.
392 epatch() {
393         _epatch_draw_line() {
394                 # create a line of same length as input string
395                 [[ -z $1 ]] && set "$(printf "%65s" '')"
396                 echo "${1//?/=}"
397         }
398
399         unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402
400
401         # First process options.  We localize the EPATCH_OPTS setting
402         # from above so that we can pass it on in the loop below with
403         # any additional values the user has specified.
404         local EPATCH_OPTS=( ${EPATCH_OPTS[*]} )
405         while [[ $# -gt 0 ]] ; do
406                 case $1 in
407                 -*) EPATCH_OPTS+=( "$1" ) ;;
408                 *) break ;;
409                 esac
410                 shift
411         done
412
413         # Let the rest of the code process one user arg at a time --
414         # each arg may expand into multiple patches, and each arg may
415         # need to start off with the default global EPATCH_xxx values
416         if [[ $# -gt 1 ]] ; then
417                 local m
418                 for m in "$@" ; do
419                         epatch "${m}"
420                 done
421                 return 0
422         fi
423
424         local SINGLE_PATCH="no"
425         # no args means process ${EPATCH_SOURCE}
426         [[ $# -eq 0 ]] && set -- "${EPATCH_SOURCE}"
427
428         if [[ -f $1 ]] ; then
429                 SINGLE_PATCH="yes"
430                 set -- "$1"
431                 # Use the suffix from the single patch (localize it); the code
432                 # below will find the suffix for us
433                 local EPATCH_SUFFIX=$1
434
435         elif [[ -d $1 ]] ; then
436                 # We have to force sorting to C so that the wildcard expansion is consistent #471666.
437                 evar_push_set LC_COLLATE C
438                 # Some people like to make dirs of patches w/out suffixes (vim).
439                 set -- "$1"/*${EPATCH_SUFFIX:+."${EPATCH_SUFFIX}"}
440                 evar_pop
441
442         elif [[ -f ${EPATCH_SOURCE}/$1 ]] ; then
443                 # Re-use EPATCH_SOURCE as a search dir
444                 epatch "${EPATCH_SOURCE}/$1"
445                 return $?
446
447         else
448                 # sanity check ... if it isn't a dir or file, wtf man ?
449                 [[ $# -ne 0 ]] && EPATCH_SOURCE=$1
450                 echo
451                 eerror "Cannot find \$EPATCH_SOURCE!  Value for \$EPATCH_SOURCE is:"
452                 eerror
453                 eerror "  ${EPATCH_SOURCE}"
454                 eerror "  ( ${EPATCH_SOURCE##*/} )"
455                 echo
456                 die "Cannot find \$EPATCH_SOURCE!"
457         fi
458
459         # Now that we know we're actually going to apply something, merge
460         # all of the patch options back in to a single variable for below.
461         EPATCH_OPTS="${EPATCH_COMMON_OPTS} ${EPATCH_OPTS[*]}"
462
463         local PIPE_CMD
464         case ${EPATCH_SUFFIX##*\.} in
465                 xz)      PIPE_CMD="xz -dc"    ;;
466                 lzma)    PIPE_CMD="lzma -dc"  ;;
467                 bz2)     PIPE_CMD="bzip2 -dc" ;;
468                 gz|Z|z)  PIPE_CMD="gzip -dc"  ;;
469                 ZIP|zip) PIPE_CMD="unzip -p"  ;;
470                 *)       ;;
471         esac
472
473         [[ ${SINGLE_PATCH} == "no" ]] && einfo "${EPATCH_MULTI_MSG}"
474
475         local x
476         for x in "$@" ; do
477                 # If the patch dir given contains subdirs, or our EPATCH_SUFFIX
478                 # didn't match anything, ignore continue on
479                 [[ ! -f ${x} ]] && continue
480
481                 local patchname=${x##*/}
482
483                 # Apply single patches, or forced sets of patches, or
484                 # patches with ARCH dependant names.
485                 #       ???_arch_foo.patch
486                 # Else, skip this input altogether
487                 local a=${patchname#*_} # strip the ???_
488                 a=${a%%_*}              # strip the _foo.patch
489                 if ! [[ ${SINGLE_PATCH} == "yes" || \
490                                 ${EPATCH_FORCE} == "yes" || \
491                                 ${a} == all     || \
492                                 ${a} == ${ARCH} ]]
493                 then
494                         continue
495                 fi
496
497                 # Let people filter things dynamically
498                 if [[ -n ${EPATCH_EXCLUDE}${EPATCH_USER_EXCLUDE} ]] ; then
499                         # let people use globs in the exclude
500                         eshopts_push -o noglob
501
502                         local ex
503                         for ex in ${EPATCH_EXCLUDE} ; do
504                                 if [[ ${patchname} == ${ex} ]] ; then
505                                         einfo "  Skipping ${patchname} due to EPATCH_EXCLUDE ..."
506                                         eshopts_pop
507                                         continue 2
508                                 fi
509                         done
510
511                         for ex in ${EPATCH_USER_EXCLUDE} ; do
512                                 if [[ ${patchname} == ${ex} ]] ; then
513                                         einfo "  Skipping ${patchname} due to EPATCH_USER_EXCLUDE ..."
514                                         eshopts_pop
515                                         continue 2
516                                 fi
517                         done
518
519                         eshopts_pop
520                 fi
521
522                 if [[ ${SINGLE_PATCH} == "yes" ]] ; then
523                         if [[ -n ${EPATCH_SINGLE_MSG} ]] ; then
524                                 einfo "${EPATCH_SINGLE_MSG}"
525                         else
526                                 einfo "Applying ${patchname} ..."
527                         fi
528                 else
529                         einfo "  ${patchname} ..."
530                 fi
531
532                 # Handle aliased patch command #404447 #461568
533                 local patch="patch"
534                 eval $(alias patch 2>/dev/null | sed 's:^alias ::')
535
536                 # most of the time, there will only be one run per unique name,
537                 # but if there are more, make sure we get unique log filenames
538                 local STDERR_TARGET="${T}/${patchname}.out"
539                 if [[ -e ${STDERR_TARGET} ]] ; then
540                         STDERR_TARGET="${T}/${patchname}-$$.out"
541                 fi
542
543                 printf "***** %s *****\nPWD: %s\nPATCH TOOL: %s -> %s\nVERSION INFO:\n%s\n\n" \
544                         "${patchname}" \
545                         "${PWD}" \
546                         "${patch}" \
547                         "$(type -P "${patch}")" \
548                         "$(${patch} --version)" \
549                         > "${STDERR_TARGET}"
550
551                 # Decompress the patch if need be
552                 local count=0
553                 local PATCH_TARGET
554                 if [[ -n ${PIPE_CMD} ]] ; then
555                         PATCH_TARGET="${T}/$$.patch"
556                         echo "PIPE_COMMAND:  ${PIPE_CMD} ${x} > ${PATCH_TARGET}" >> "${STDERR_TARGET}"
557
558                         if ! (${PIPE_CMD} "${x}" > "${PATCH_TARGET}") >> "${STDERR_TARGET}" 2>&1 ; then
559                                 echo
560                                 eerror "Could not extract patch!"
561                                 #die "Could not extract patch!"
562                                 count=5
563                                 break
564                         fi
565                 else
566                         PATCH_TARGET=${x}
567                 fi
568
569                 # Check for absolute paths in patches.  If sandbox is disabled,
570                 # people could (accidently) patch files in the root filesystem.
571                 # Or trigger other unpleasantries #237667.  So disallow -p0 on
572                 # such patches.
573                 local abs_paths=$(egrep -n '^[-+]{3} /' "${PATCH_TARGET}" | awk '$2 != "/dev/null" { print }')
574                 if [[ -n ${abs_paths} ]] ; then
575                         count=1
576                         printf "NOTE: skipping -p0 due to absolute paths in patch:\n%s\n" "${abs_paths}" >> "${STDERR_TARGET}"
577                 fi
578                 # Similar reason, but with relative paths.
579                 local rel_paths=$(egrep -n '^[-+]{3} [^ ]*[.][.]/' "${PATCH_TARGET}")
580                 if [[ -n ${rel_paths} ]] ; then
581                         echo
582                         eerror "Rejected Patch: ${patchname} !"
583                         eerror " ( ${PATCH_TARGET} )"
584                         eerror
585                         eerror "Your patch uses relative paths '../':"
586                         eerror "${rel_paths}"
587                         echo
588                         die "you need to fix the relative paths in patch"
589                 fi
590
591                 # Dynamically detect the correct -p# ... i'm lazy, so shoot me :/
592                 local patch_cmd
593                 while [[ ${count} -lt 5 ]] ; do
594                         patch_cmd="${patch} -p${count} ${EPATCH_OPTS}"
595
596                         # Generate some useful debug info ...
597                         (
598                         _epatch_draw_line "***** ${patchname} *****"
599                         echo
600                         echo "PATCH COMMAND:  ${patch_cmd} --dry-run -f < '${PATCH_TARGET}'"
601                         echo
602                         _epatch_draw_line "***** ${patchname} *****"
603                         ${patch_cmd} --dry-run -f < "${PATCH_TARGET}" 2>&1
604                         ret=$?
605                         echo
606                         echo "patch program exited with status ${ret}"
607                         exit ${ret}
608                         ) >> "${STDERR_TARGET}"
609
610                         if [ $? -eq 0 ] ; then
611                                 (
612                                 _epatch_draw_line "***** ${patchname} *****"
613                                 echo
614                                 echo "ACTUALLY APPLYING ${patchname} ..."
615                                 echo "PATCH COMMAND:  ${patch_cmd} < '${PATCH_TARGET}'"
616                                 echo
617                                 _epatch_draw_line "***** ${patchname} *****"
618                                 ${patch_cmd} < "${PATCH_TARGET}" 2>&1
619                                 ret=$?
620                                 echo
621                                 echo "patch program exited with status ${ret}"
622                                 exit ${ret}
623                                 ) >> "${STDERR_TARGET}"
624
625                                 if [ $? -ne 0 ] ; then
626                                         echo
627                                         eerror "A dry-run of patch command succeeded, but actually"
628                                         eerror "applying the patch failed!"
629                                         #die "Real world sux compared to the dreamworld!"
630                                         count=5
631                                 fi
632                                 break
633                         fi
634
635                         : $(( count++ ))
636                 done
637
638                 # if we had to decompress the patch, delete the temp one
639                 if [[ -n ${PIPE_CMD} ]] ; then
640                         rm -f "${PATCH_TARGET}"
641                 fi
642
643                 if [[ ${count} -ge 5 ]] ; then
644                         echo
645                         eerror "Failed Patch: ${patchname} !"
646                         eerror " ( ${PATCH_TARGET} )"
647                         eerror
648                         eerror "Include in your bugreport the contents of:"
649                         eerror
650                         eerror "  ${STDERR_TARGET}"
651                         echo
652                         die "Failed Patch: ${patchname}!"
653                 fi
654
655                 # if everything worked, delete the full debug patch log
656                 rm -f "${STDERR_TARGET}"
657
658                 # then log away the exact stuff for people to review later
659                 cat <<-EOF >> "${T}/epatch.log"
660                 PATCH: ${x}
661                 CMD: ${patch_cmd}
662                 PWD: ${PWD}
663
664                 EOF
665                 eend 0
666         done
667
668         [[ ${SINGLE_PATCH} == "no" ]] && einfo "Done with patching"
669         : # everything worked
670 }
671
672 # @FUNCTION: epatch_user
673 # @USAGE:
674 # @DESCRIPTION:
675 # Applies user-provided patches to the source tree. The patches are
676 # taken from /etc/portage/patches/<CATEGORY>/<P-PR|P|PN>[:SLOT]/, where the first
677 # of these three directories to exist will be the one to use, ignoring
678 # any more general directories which might exist as well. They must end
679 # in ".patch" to be applied.
680 #
681 # User patches are intended for quick testing of patches without ebuild
682 # modifications, as well as for permanent customizations a user might
683 # desire. Obviously, there can be no official support for arbitrarily
684 # patched ebuilds. So whenever a build log in a bug report mentions that
685 # user patches were applied, the user should be asked to reproduce the
686 # problem without these.
687 #
688 # Not all ebuilds do call this function, so placing patches in the
689 # stated directory might or might not work, depending on the package and
690 # the eclasses it inherits and uses. It is safe to call the function
691 # repeatedly, so it is always possible to add a call at the ebuild
692 # level. The first call is the time when the patches will be
693 # applied.
694 #
695 # Ideally, this function should be called after gentoo-specific patches
696 # have been applied, so that their code can be modified as well, but
697 # before calls to e.g. eautoreconf, as the user patches might affect
698 # autotool input files as well.
699 epatch_user() {
700         [[ $# -ne 0 ]] && die "epatch_user takes no options"
701
702         # Allow multiple calls to this function; ignore all but the first
703         local applied="${T}/epatch_user.log"
704         [[ -e ${applied} ]] && return 2
705
706         # don't clobber any EPATCH vars that the parent might want
707         local EPATCH_SOURCE check
708         for check in ${CATEGORY}/{${P}-${PR},${P},${PN}}{,:${SLOT}}; do
709                 EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CTARGET}/${check}
710                 [[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${CHOST}/${check}
711                 [[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${EPATCH_USER_SOURCE}/${check}
712                 if [[ -d ${EPATCH_SOURCE} ]] ; then
713                         EPATCH_SOURCE=${EPATCH_SOURCE} \
714                         EPATCH_SUFFIX="patch" \
715                         EPATCH_FORCE="yes" \
716                         EPATCH_MULTI_MSG="Applying user patches from ${EPATCH_SOURCE} ..." \
717                         epatch
718                         echo "${EPATCH_SOURCE}" > "${applied}"
719                         has epatch_user_death_notice ${EBUILD_DEATH_HOOKS} || EBUILD_DEATH_HOOKS+=" epatch_user_death_notice"
720                         return 0
721                 fi
722         done
723         echo "none" > "${applied}"
724         return 1
725 }
726 # @FUNCTION: epatch_user_death_notice
727 # @INTERNAL
728 # @DESCRIPTION:
729 # Include an explicit notice in the die message itself that user patches were
730 # applied to this build.
731 epatch_user_death_notice() {
732         ewarn "!!! User patches were applied to this build!"
733 }
734
735 # @FUNCTION: emktemp
736 # @USAGE: [temp dir]
737 # @DESCRIPTION:
738 # Cheap replacement for when debianutils (and thus mktemp)
739 # does not exist on the users system.
740 emktemp() {
741         local exe="touch"
742         [[ $1 == -d ]] && exe="mkdir" && shift
743         local topdir=$1
744
745         if [[ -z ${topdir} ]] ; then
746                 [[ -z ${T} ]] \
747                         && topdir="/tmp" \
748                         || topdir=${T}
749         fi
750
751         if ! type -P mktemp > /dev/null ; then
752                 # system lacks `mktemp` so we have to fake it
753                 local tmp=/
754                 while [[ -e ${tmp} ]] ; do
755                         tmp=${topdir}/tmp.${RANDOM}.${RANDOM}.${RANDOM}
756                 done
757                 ${exe} "${tmp}" || ${exe} -p "${tmp}"
758                 echo "${tmp}"
759         else
760                 # the args here will give slightly wierd names on BSD,
761                 # but should produce a usable file on all userlands
762                 if [[ ${exe} == "touch" ]] ; then
763                         TMPDIR="${topdir}" mktemp -t tmp.XXXXXXXXXX
764                 else
765                         TMPDIR="${topdir}" mktemp -dt tmp.XXXXXXXXXX
766                 fi
767         fi
768 }
769
770 # @FUNCTION: edos2unix
771 # @USAGE: <file> [more files ...]
772 # @DESCRIPTION:
773 # A handy replacement for dos2unix, recode, fixdos, etc...  This allows you
774 # to remove all of these text utilities from DEPEND variables because this
775 # is a script based solution.  Just give it a list of files to convert and
776 # they will all be changed from the DOS CRLF format to the UNIX LF format.
777 edos2unix() {
778         [[ $# -eq 0 ]] && return 0
779         sed -i 's/\r$//' -- "$@" || die
780 }
781
782 # @FUNCTION: make_desktop_entry
783 # @USAGE: make_desktop_entry(<command>, [name], [icon], [type], [fields])
784 # @DESCRIPTION:
785 # Make a .desktop file.
786 #
787 # @CODE
788 # binary:   what command does the app run with ?
789 # name:     the name that will show up in the menu
790 # icon:     the icon to use in the menu entry
791 #           this can be relative (to /usr/share/pixmaps) or
792 #           a full path to an icon
793 # type:     what kind of application is this?
794 #           for categories:
795 #           http://standards.freedesktop.org/menu-spec/latest/apa.html
796 #           if unset, function tries to guess from package's category
797 # fields:       extra fields to append to the desktop file; a printf string
798 # @CODE
799 make_desktop_entry() {
800         [[ -z $1 ]] && die "make_desktop_entry: You must specify the executable"
801
802         local exec=${1}
803         local name=${2:-${PN}}
804         local icon=${3:-${PN}}
805         local type=${4}
806         local fields=${5}
807
808         if [[ -z ${type} ]] ; then
809                 local catmaj=${CATEGORY%%-*}
810                 local catmin=${CATEGORY##*-}
811                 case ${catmaj} in
812                         app)
813                                 case ${catmin} in
814                                         accessibility) type="Utility;Accessibility";;
815                                         admin)         type=System;;
816                                         antivirus)     type=System;;
817                                         arch)          type="Utility;Archiving";;
818                                         backup)        type="Utility;Archiving";;
819                                         cdr)           type="AudioVideo;DiscBurning";;
820                                         dicts)         type="Office;Dictionary";;
821                                         doc)           type=Documentation;;
822                                         editors)       type="Utility;TextEditor";;
823                                         emacs)         type="Development;TextEditor";;
824                                         emulation)     type="System;Emulator";;
825                                         laptop)        type="Settings;HardwareSettings";;
826                                         office)        type=Office;;
827                                         pda)           type="Office;PDA";;
828                                         vim)           type="Development;TextEditor";;
829                                         xemacs)        type="Development;TextEditor";;
830                                 esac
831                                 ;;
832
833                         dev)
834                                 type="Development"
835                                 ;;
836
837                         games)
838                                 case ${catmin} in
839                                         action|fps) type=ActionGame;;
840                                         arcade)     type=ArcadeGame;;
841                                         board)      type=BoardGame;;
842                                         emulation)  type=Emulator;;
843                                         kids)       type=KidsGame;;
844                                         puzzle)     type=LogicGame;;
845                                         roguelike)  type=RolePlaying;;
846                                         rpg)        type=RolePlaying;;
847                                         simulation) type=Simulation;;
848                                         sports)     type=SportsGame;;
849                                         strategy)   type=StrategyGame;;
850                                 esac
851                                 type="Game;${type}"
852                                 ;;
853
854                         gnome)
855                                 type="Gnome;GTK"
856                                 ;;
857
858                         kde)
859                                 type="KDE;Qt"
860                                 ;;
861
862                         mail)
863                                 type="Network;Email"
864                                 ;;
865
866                         media)
867                                 case ${catmin} in
868                                         gfx)
869                                                 type=Graphics
870                                                 ;;
871                                         *)
872                                                 case ${catmin} in
873                                                         radio) type=Tuner;;
874                                                         sound) type=Audio;;
875                                                         tv)    type=TV;;
876                                                         video) type=Video;;
877                                                 esac
878                                                 type="AudioVideo;${type}"
879                                                 ;;
880                                 esac
881                                 ;;
882
883                         net)
884                                 case ${catmin} in
885                                         dialup) type=Dialup;;
886                                         ftp)    type=FileTransfer;;
887                                         im)     type=InstantMessaging;;
888                                         irc)    type=IRCClient;;
889                                         mail)   type=Email;;
890                                         news)   type=News;;
891                                         nntp)   type=News;;
892                                         p2p)    type=FileTransfer;;
893                                         voip)   type=Telephony;;
894                                 esac
895                                 type="Network;${type}"
896                                 ;;
897
898                         sci)
899                                 case ${catmin} in
900                                         astro*)  type=Astronomy;;
901                                         bio*)    type=Biology;;
902                                         calc*)   type=Calculator;;
903                                         chem*)   type=Chemistry;;
904                                         elec*)   type=Electronics;;
905                                         geo*)    type=Geology;;
906                                         math*)   type=Math;;
907                                         physics) type=Physics;;
908                                         visual*) type=DataVisualization;;
909                                 esac
910                                 type="Education;Science;${type}"
911                                 ;;
912
913                         sys)
914                                 type="System"
915                                 ;;
916
917                         www)
918                                 case ${catmin} in
919                                         client) type=WebBrowser;;
920                                 esac
921                                 type="Network;${type}"
922                                 ;;
923
924                         *)
925                                 type=
926                                 ;;
927                 esac
928         fi
929         local slot=${SLOT%/*}
930         if [[ ${slot} == "0" ]] ; then
931                 local desktop_name="${PN}"
932         else
933                 local desktop_name="${PN}-${slot}"
934         fi
935         local desktop="${T}/$(echo ${exec} | sed 's:[[:space:]/:]:_:g')-${desktop_name}.desktop"
936         #local desktop=${T}/${exec%% *:-${desktop_name}}.desktop
937
938         # Don't append another ";" when a valid category value is provided.
939         type=${type%;}${type:+;}
940
941         eshopts_push -s extglob
942         if [[ -n ${icon} && ${icon} != /* ]] && [[ ${icon} == *.xpm || ${icon} == *.png || ${icon} == *.svg ]]; then
943                 ewarn "As described in the Icon Theme Specification, icon file extensions are not"
944                 ewarn "allowed in .desktop files if the value is not an absolute path."
945                 icon=${icon%.@(xpm|png|svg)}
946         fi
947         eshopts_pop
948
949         cat <<-EOF > "${desktop}"
950         [Desktop Entry]
951         Name=${name}
952         Type=Application
953         Comment=${DESCRIPTION}
954         Exec=${exec}
955         TryExec=${exec%% *}
956         Icon=${icon}
957         Categories=${type}
958         EOF
959
960         if [[ ${fields:-=} != *=* ]] ; then
961                 # 5th arg used to be value to Path=
962                 ewarn "make_desktop_entry: update your 5th arg to read Path=${fields}"
963                 fields="Path=${fields}"
964         fi
965         [[ -n ${fields} ]] && printf '%b\n' "${fields}" >> "${desktop}"
966
967         (
968                 # wrap the env here so that the 'insinto' call
969                 # doesn't corrupt the env of the caller
970                 insinto /usr/share/applications
971                 doins "${desktop}"
972         ) || die "installing desktop file failed"
973 }
974
975 # @FUNCTION: _eutils_eprefix_init
976 # @INTERNAL
977 # @DESCRIPTION:
978 # Initialized prefix variables for EAPI<3.
979 _eutils_eprefix_init() {
980         has "${EAPI:-0}" 0 1 2 && : ${ED:=${D}} ${EPREFIX:=} ${EROOT:=${ROOT}}
981 }
982
983 # @FUNCTION: validate_desktop_entries
984 # @USAGE: [directories]
985 # @MAINTAINER:
986 # Carsten Lohrke <carlo@gentoo.org>
987 # @DESCRIPTION:
988 # Validate desktop entries using desktop-file-utils
989 validate_desktop_entries() {
990         _eutils_eprefix_init
991         if [[ -x "${EPREFIX}"/usr/bin/desktop-file-validate ]] ; then
992                 einfo "Checking desktop entry validity"
993                 local directories=""
994                 for d in /usr/share/applications $@ ; do
995                         [[ -d ${ED}${d} ]] && directories="${directories} ${ED}${d}"
996                 done
997                 if [[ -n ${directories} ]] ; then
998                         for FILE in $(find ${directories} -name "*\.desktop" \
999                                                         -not -path '*.hidden*' | sort -u 2>/dev/null)
1000                         do
1001                                 local temp=$(desktop-file-validate ${FILE} | grep -v "warning:" | \
1002                                                                 sed -e "s|error: ||" -e "s|${FILE}:|--|g" )
1003                                 [[ -n $temp ]] && elog ${temp/--/${FILE/${ED}/}:}
1004                         done
1005                 fi
1006                 echo ""
1007         else
1008                 einfo "Passing desktop entry validity check. Install dev-util/desktop-file-utils, if you want to help to improve Gentoo."
1009         fi
1010 }
1011
1012 # @FUNCTION: make_session_desktop
1013 # @USAGE: <title> <command> [command args...]
1014 # @DESCRIPTION:
1015 # Make a GDM/KDM Session file.  The title is the file to execute to start the
1016 # Window Manager.  The command is the name of the Window Manager.
1017 #
1018 # You can set the name of the file via the ${wm} variable.
1019 make_session_desktop() {
1020         [[ -z $1 ]] && eerror "$0: You must specify the title" && return 1
1021         [[ -z $2 ]] && eerror "$0: You must specify the command" && return 1
1022
1023         local title=$1
1024         local command=$2
1025         local desktop=${T}/${wm:-${PN}}.desktop
1026         shift 2
1027
1028         cat <<-EOF > "${desktop}"
1029         [Desktop Entry]
1030         Name=${title}
1031         Comment=This session logs you into ${title}
1032         Exec=${command} $*
1033         TryExec=${command}
1034         Type=XSession
1035         EOF
1036
1037         (
1038         # wrap the env here so that the 'insinto' call
1039         # doesn't corrupt the env of the caller
1040         insinto /usr/share/xsessions
1041         doins "${desktop}"
1042         )
1043 }
1044
1045 # @FUNCTION: domenu
1046 # @USAGE: <menus>
1047 # @DESCRIPTION:
1048 # Install the list of .desktop menu files into the appropriate directory
1049 # (/usr/share/applications).
1050 domenu() {
1051         (
1052         # wrap the env here so that the 'insinto' call
1053         # doesn't corrupt the env of the caller
1054         local i j ret=0
1055         insinto /usr/share/applications
1056         for i in "$@" ; do
1057                 if [[ -f ${i} ]] ; then
1058                         doins "${i}"
1059                         ((ret+=$?))
1060                 elif [[ -d ${i} ]] ; then
1061                         for j in "${i}"/*.desktop ; do
1062                                 doins "${j}"
1063                                 ((ret+=$?))
1064                         done
1065                 else
1066                         ((++ret))
1067                 fi
1068         done
1069         exit ${ret}
1070         )
1071 }
1072
1073 # @FUNCTION: newmenu
1074 # @USAGE: <menu> <newname>
1075 # @DESCRIPTION:
1076 # Like all other new* functions, install the specified menu as newname.
1077 newmenu() {
1078         (
1079         # wrap the env here so that the 'insinto' call
1080         # doesn't corrupt the env of the caller
1081         insinto /usr/share/applications
1082         newins "$@"
1083         )
1084 }
1085
1086 # @FUNCTION: _iconins
1087 # @INTERNAL
1088 # @DESCRIPTION:
1089 # function for use in doicon and newicon
1090 _iconins() {
1091         (
1092         # wrap the env here so that the 'insinto' call
1093         # doesn't corrupt the env of the caller
1094         local funcname=$1; shift
1095         local size dir
1096         local context=apps
1097         local theme=hicolor
1098
1099         while [[ $# -gt 0 ]] ; do
1100                 case $1 in
1101                 -s|--size)
1102                         if [[ ${2%%x*}x${2%%x*} == "$2" ]] ; then
1103                                 size=${2%%x*}
1104                         else
1105                                 size=${2}
1106                         fi
1107                         case ${size} in
1108                         16|22|24|32|36|48|64|72|96|128|192|256|512)
1109                                 size=${size}x${size};;
1110                         scalable)
1111                                 ;;
1112                         *)
1113                                 eerror "${size} is an unsupported icon size!"
1114                                 exit 1;;
1115                         esac
1116                         shift 2;;
1117                 -t|--theme)
1118                         theme=${2}
1119                         shift 2;;
1120                 -c|--context)
1121                         context=${2}
1122                         shift 2;;
1123                 *)
1124                         if [[ -z ${size} ]] ; then
1125                                 insinto /usr/share/pixmaps
1126                         else
1127                                 insinto /usr/share/icons/${theme}/${size}/${context}
1128                         fi
1129
1130                         if [[ ${funcname} == doicon ]] ; then
1131                                 if [[ -f $1 ]] ; then
1132                                         doins "${1}"
1133                                 elif [[ -d $1 ]] ; then
1134                                         shopt -s nullglob
1135                                         doins "${1}"/*.{png,svg}
1136                                         shopt -u nullglob
1137                                 else
1138                                         eerror "${1} is not a valid file/directory!"
1139                                         exit 1
1140                                 fi
1141                         else
1142                                 break
1143                         fi
1144                         shift 1;;
1145                 esac
1146         done
1147         if [[ ${funcname} == newicon ]] ; then
1148                 newins "$@"
1149         fi
1150         ) || die
1151 }
1152
1153 # @FUNCTION: doicon
1154 # @USAGE: [options] <icons>
1155 # @DESCRIPTION:
1156 # Install icon into the icon directory /usr/share/icons or into
1157 # /usr/share/pixmaps if "--size" is not set.
1158 # This is useful in conjunction with creating desktop/menu files.
1159 #
1160 # @CODE
1161 #  options:
1162 #  -s, --size
1163 #    !!! must specify to install into /usr/share/icons/... !!!
1164 #    size of the icon, like 48 or 48x48
1165 #    supported icon sizes are:
1166 #    16 22 24 32 36 48 64 72 96 128 192 256 scalable
1167 #  -c, --context
1168 #    defaults to "apps"
1169 #  -t, --theme
1170 #    defaults to "hicolor"
1171 #
1172 # icons: list of icons
1173 #
1174 # example 1: doicon foobar.png fuqbar.svg suckbar.png
1175 # results in: insinto /usr/share/pixmaps
1176 #             doins foobar.png fuqbar.svg suckbar.png
1177 #
1178 # example 2: doicon -s 48 foobar.png fuqbar.png blobbar.png
1179 # results in: insinto /usr/share/icons/hicolor/48x48/apps
1180 #             doins foobar.png fuqbar.png blobbar.png
1181 # @CODE
1182 doicon() {
1183         _iconins ${FUNCNAME} "$@"
1184 }
1185
1186 # @FUNCTION: newicon
1187 # @USAGE: [options] <icon> <newname>
1188 # @DESCRIPTION:
1189 # Like doicon, install the specified icon as newname.
1190 #
1191 # @CODE
1192 # example 1: newicon foobar.png NEWNAME.png
1193 # results in: insinto /usr/share/pixmaps
1194 #             newins foobar.png NEWNAME.png
1195 #
1196 # example 2: newicon -s 48 foobar.png NEWNAME.png
1197 # results in: insinto /usr/share/icons/hicolor/48x48/apps
1198 #             newins foobar.png NEWNAME.png
1199 # @CODE
1200 newicon() {
1201         _iconins ${FUNCNAME} "$@"
1202 }
1203
1204 # @FUNCTION: strip-linguas
1205 # @USAGE: [<allow LINGUAS>|<-i|-u> <directories of .po files>]
1206 # @DESCRIPTION:
1207 # Make sure that LINGUAS only contains languages that
1208 # a package can support.  The first form allows you to
1209 # specify a list of LINGUAS.  The -i builds a list of po
1210 # files found in all the directories and uses the
1211 # intersection of the lists.  The -u builds a list of po
1212 # files found in all the directories and uses the union
1213 # of the lists.
1214 strip-linguas() {
1215         local ls newls nols
1216         if [[ $1 == "-i" ]] || [[ $1 == "-u" ]] ; then
1217                 local op=$1; shift
1218                 ls=$(find "$1" -name '*.po' -exec basename {} .po ';'); shift
1219                 local d f
1220                 for d in "$@" ; do
1221                         if [[ ${op} == "-u" ]] ; then
1222                                 newls=${ls}
1223                         else
1224                                 newls=""
1225                         fi
1226                         for f in $(find "$d" -name '*.po' -exec basename {} .po ';') ; do
1227                                 if [[ ${op} == "-i" ]] ; then
1228                                         has ${f} ${ls} && newls="${newls} ${f}"
1229                                 else
1230                                         has ${f} ${ls} || newls="${newls} ${f}"
1231                                 fi
1232                         done
1233                         ls=${newls}
1234                 done
1235         else
1236                 ls="$@"
1237         fi
1238
1239         nols=""
1240         newls=""
1241         for f in ${LINGUAS} ; do
1242                 if has ${f} ${ls} ; then
1243                         newls="${newls} ${f}"
1244                 else
1245                         nols="${nols} ${f}"
1246                 fi
1247         done
1248         [[ -n ${nols} ]] \
1249                 && einfo "Sorry, but ${PN} does not support the LINGUAS:" ${nols}
1250         export LINGUAS=${newls:1}
1251 }
1252
1253 # @FUNCTION: preserve_old_lib
1254 # @USAGE: <libs to preserve> [more libs]
1255 # @DESCRIPTION:
1256 # These functions are useful when a lib in your package changes ABI SONAME.
1257 # An example might be from libogg.so.0 to libogg.so.1.  Removing libogg.so.0
1258 # would break packages that link against it.  Most people get around this
1259 # by using the portage SLOT mechanism, but that is not always a relevant
1260 # solution, so instead you can call this from pkg_preinst.  See also the
1261 # preserve_old_lib_notify function.
1262 preserve_old_lib() {
1263         _eutils_eprefix_init
1264         if [[ ${EBUILD_PHASE} != "preinst" ]] ; then
1265                 eerror "preserve_old_lib() must be called from pkg_preinst() only"
1266                 die "Invalid preserve_old_lib() usage"
1267         fi
1268         [[ -z $1 ]] && die "Usage: preserve_old_lib <library to preserve> [more libraries to preserve]"
1269
1270         # let portage worry about it
1271         has preserve-libs ${FEATURES} && return 0
1272
1273         local lib dir
1274         for lib in "$@" ; do
1275                 [[ -e ${EROOT}/${lib} ]] || continue
1276                 dir=${lib%/*}
1277                 dodir ${dir} || die "dodir ${dir} failed"
1278                 cp "${EROOT}"/${lib} "${ED}"/${lib} || die "cp ${lib} failed"
1279                 touch "${ED}"/${lib}
1280         done
1281 }
1282
1283 # @FUNCTION: preserve_old_lib_notify
1284 # @USAGE: <libs to notify> [more libs]
1285 # @DESCRIPTION:
1286 # Spit helpful messages about the libraries preserved by preserve_old_lib.
1287 preserve_old_lib_notify() {
1288         if [[ ${EBUILD_PHASE} != "postinst" ]] ; then
1289                 eerror "preserve_old_lib_notify() must be called from pkg_postinst() only"
1290                 die "Invalid preserve_old_lib_notify() usage"
1291         fi
1292
1293         # let portage worry about it
1294         has preserve-libs ${FEATURES} && return 0
1295
1296         _eutils_eprefix_init
1297
1298         local lib notice=0
1299         for lib in "$@" ; do
1300                 [[ -e ${EROOT}/${lib} ]] || continue
1301                 if [[ ${notice} -eq 0 ]] ; then
1302                         notice=1
1303                         ewarn "Old versions of installed libraries were detected on your system."
1304                         ewarn "In order to avoid breaking packages that depend on these old libs,"
1305                         ewarn "the libraries are not being removed.  You need to run revdep-rebuild"
1306                         ewarn "in order to remove these old dependencies.  If you do not have this"
1307                         ewarn "helper program, simply emerge the 'gentoolkit' package."
1308                         ewarn
1309                 fi
1310                 ewarn "  # revdep-rebuild --library '${lib}' && rm '${lib}'"
1311         done
1312 }
1313
1314 # @FUNCTION: built_with_use
1315 # @USAGE: [--hidden] [--missing <action>] [-a|-o] <DEPEND ATOM> <List of USE flags>
1316 # @DESCRIPTION:
1317 #
1318 # Deprecated: Use EAPI 2 use deps in DEPEND|RDEPEND and with has_version calls.
1319 #
1320 # A temporary hack until portage properly supports DEPENDing on USE
1321 # flags being enabled in packages.  This will check to see if the specified
1322 # DEPEND atom was built with the specified list of USE flags.  The
1323 # --missing option controls the behavior if called on a package that does
1324 # not actually support the defined USE flags (aka listed in IUSE).
1325 # The default is to abort (call die).  The -a and -o flags control
1326 # the requirements of the USE flags.  They correspond to "and" and "or"
1327 # logic.  So the -a flag means all listed USE flags must be enabled
1328 # while the -o flag means at least one of the listed IUSE flags must be
1329 # enabled.  The --hidden option is really for internal use only as it
1330 # means the USE flag we're checking is hidden expanded, so it won't be found
1331 # in IUSE like normal USE flags.
1332 #
1333 # Remember that this function isn't terribly intelligent so order of optional
1334 # flags matter.
1335 built_with_use() {
1336         _eutils_eprefix_init
1337         local hidden="no"
1338         if [[ $1 == "--hidden" ]] ; then
1339                 hidden="yes"
1340                 shift
1341         fi
1342
1343         local missing_action="die"
1344         if [[ $1 == "--missing" ]] ; then
1345                 missing_action=$2
1346                 shift ; shift
1347                 case ${missing_action} in
1348                         true|false|die) ;;
1349                         *) die "unknown action '${missing_action}'";;
1350                 esac
1351         fi
1352
1353         local opt=$1
1354         [[ ${opt:0:1} = "-" ]] && shift || opt="-a"
1355
1356         local PKG=$(best_version $1)
1357         [[ -z ${PKG} ]] && die "Unable to resolve $1 to an installed package"
1358         shift
1359
1360         local USEFILE=${EROOT}/var/db/pkg/${PKG}/USE
1361         local IUSEFILE=${EROOT}/var/db/pkg/${PKG}/IUSE
1362
1363         # if the IUSE file doesn't exist, the read will error out, we need to handle
1364         # this gracefully
1365         if [[ ! -e ${USEFILE} ]] || [[ ! -e ${IUSEFILE} && ${hidden} == "no" ]] ; then
1366                 case ${missing_action} in
1367                         true)   return 0;;
1368                         false)  return 1;;
1369                         die)    die "Unable to determine what USE flags $PKG was built with";;
1370                 esac
1371         fi
1372
1373         if [[ ${hidden} == "no" ]] ; then
1374                 local IUSE_BUILT=( $(<"${IUSEFILE}") )
1375                 # Don't check USE_EXPAND #147237
1376                 local expand
1377                 for expand in $(echo ${USE_EXPAND} | tr '[:upper:]' '[:lower:]') ; do
1378                         if [[ $1 == ${expand}_* ]] ; then
1379                                 expand=""
1380                                 break
1381                         fi
1382                 done
1383                 if [[ -n ${expand} ]] ; then
1384                         if ! has $1 ${IUSE_BUILT[@]#[-+]} ; then
1385                                 case ${missing_action} in
1386                                         true)  return 0;;
1387                                         false) return 1;;
1388                                         die)   die "$PKG does not actually support the $1 USE flag!";;
1389                                 esac
1390                         fi
1391                 fi
1392         fi
1393
1394         local USE_BUILT=$(<${USEFILE})
1395         while [[ $# -gt 0 ]] ; do
1396                 if [[ ${opt} = "-o" ]] ; then
1397                         has $1 ${USE_BUILT} && return 0
1398                 else
1399                         has $1 ${USE_BUILT} || return 1
1400                 fi
1401                 shift
1402         done
1403         [[ ${opt} = "-a" ]]
1404 }
1405
1406 # If an overlay has eclass overrides, but doesn't actually override the
1407 # libtool.eclass, we'll have ECLASSDIR pointing to the active overlay's
1408 # eclass/ dir, but libtool.eclass is still in the main Gentoo tree.  So
1409 # add a check to locate the ELT-patches/ regardless of what's going on.
1410 # Note: Duplicated in libtool.eclass.
1411 _EUTILS_ECLASSDIR_LOCAL=${BASH_SOURCE[0]%/*}
1412 eutils_elt_patch_dir() {
1413         local d="${ECLASSDIR}/ELT-patches"
1414         if [[ ! -d ${d} ]] ; then
1415                 d="${_EUTILS_ECLASSDIR_LOCAL}/ELT-patches"
1416         fi
1417         echo "${d}"
1418 }
1419
1420 # @FUNCTION: epunt_cxx
1421 # @USAGE: [dir to scan]
1422 # @DESCRIPTION:
1423 # Many configure scripts wrongly bail when a C++ compiler could not be
1424 # detected.  If dir is not specified, then it defaults to ${S}.
1425 #
1426 # https://bugs.gentoo.org/73450
1427 epunt_cxx() {
1428         local dir=$1
1429         [[ -z ${dir} ]] && dir=${S}
1430         ebegin "Removing useless C++ checks"
1431         local f p any_found
1432         while IFS= read -r -d '' f; do
1433                 for p in "$(eutils_elt_patch_dir)"/nocxx/*.patch ; do
1434                         if patch --no-backup-if-mismatch -p1 "${f}" "${p}" >/dev/null ; then
1435                                 any_found=1
1436                                 break
1437                         fi
1438                 done
1439         done < <(find "${dir}" -name configure -print0)
1440
1441         if [[ -z ${any_found} ]]; then
1442                 eqawarn "epunt_cxx called unnecessarily (no C++ checks to punt)."
1443         fi
1444         eend 0
1445 }
1446
1447 # @FUNCTION: make_wrapper
1448 # @USAGE: <wrapper> <target> [chdir] [libpaths] [installpath]
1449 # @DESCRIPTION:
1450 # Create a shell wrapper script named wrapper in installpath
1451 # (defaults to the bindir) to execute target (default of wrapper) by
1452 # first optionally setting LD_LIBRARY_PATH to the colon-delimited
1453 # libpaths followed by optionally changing directory to chdir.
1454 make_wrapper() {
1455         _eutils_eprefix_init
1456         local wrapper=$1 bin=$2 chdir=$3 libdir=$4 path=$5
1457         local tmpwrapper=$(emktemp)
1458
1459         (
1460         echo '#!/bin/sh'
1461         [[ -n ${chdir} ]] && printf 'cd "%s"\n' "${EPREFIX}${chdir}"
1462         if [[ -n ${libdir} ]] ; then
1463                 local var
1464                 if [[ ${CHOST} == *-darwin* ]] ; then
1465                         var=DYLD_LIBRARY_PATH
1466                 else
1467                         var=LD_LIBRARY_PATH
1468                 fi
1469                 cat <<-EOF
1470                         if [ "\${${var}+set}" = "set" ] ; then
1471                                 export ${var}="\${${var}}:${EPREFIX}${libdir}"
1472                         else
1473                                 export ${var}="${EPREFIX}${libdir}"
1474                         fi
1475                 EOF
1476         fi
1477         # We don't want to quote ${bin} so that people can pass complex
1478         # things as ${bin} ... "./someprog --args"
1479         printf 'exec %s "$@"\n' "${bin/#\//${EPREFIX}/}"
1480         ) > "${tmpwrapper}"
1481         chmod go+rx "${tmpwrapper}"
1482
1483         if [[ -n ${path} ]] ; then
1484                 (
1485                 exeinto "${path}"
1486                 newexe "${tmpwrapper}" "${wrapper}"
1487                 ) || die
1488         else
1489                 newbin "${tmpwrapper}" "${wrapper}" || die
1490         fi
1491 }
1492
1493 # @FUNCTION: path_exists
1494 # @USAGE: [-a|-o] <paths>
1495 # @DESCRIPTION:
1496 # Check if the specified paths exist.  Works for all types of paths
1497 # (files/dirs/etc...).  The -a and -o flags control the requirements
1498 # of the paths.  They correspond to "and" and "or" logic.  So the -a
1499 # flag means all the paths must exist while the -o flag means at least
1500 # one of the paths must exist.  The default behavior is "and".  If no
1501 # paths are specified, then the return value is "false".
1502 path_exists() {
1503         local opt=$1
1504         [[ ${opt} == -[ao] ]] && shift || opt="-a"
1505
1506         # no paths -> return false
1507         # same behavior as: [[ -e "" ]]
1508         [[ $# -eq 0 ]] && return 1
1509
1510         local p r=0
1511         for p in "$@" ; do
1512                 [[ -e ${p} ]]
1513                 : $(( r += $? ))
1514         done
1515
1516         case ${opt} in
1517                 -a) return $(( r != 0 )) ;;
1518                 -o) return $(( r == $# )) ;;
1519         esac
1520 }
1521
1522 # @FUNCTION: in_iuse
1523 # @USAGE: <flag>
1524 # @DESCRIPTION:
1525 # Determines whether the given flag is in IUSE. Strips IUSE default prefixes
1526 # as necessary.
1527 #
1528 # Note that this function should not be used in the global scope.
1529 if has "${EAPI:-0}" 0 1 2 3 4 5; then
1530         in_iuse() {
1531                 debug-print-function ${FUNCNAME} "${@}"
1532                 [[ ${#} -eq 1 ]] || die "Invalid args to ${FUNCNAME}()"
1533
1534                 local flag=${1}
1535                 local liuse=( ${IUSE} )
1536
1537                 has "${flag}" "${liuse[@]#[+-]}"
1538         }
1539 fi
1540
1541 # @FUNCTION: use_if_iuse
1542 # @USAGE: <flag>
1543 # @DESCRIPTION:
1544 # Return true if the given flag is in USE and IUSE.
1545 #
1546 # Note that this function should not be used in the global scope.
1547 use_if_iuse() {
1548         in_iuse $1 || return 1
1549         use $1
1550 }
1551
1552 # @FUNCTION: usex
1553 # @USAGE: <USE flag> [true output] [false output] [true suffix] [false suffix]
1554 # @DESCRIPTION:
1555 # Proxy to declare usex for package managers or EAPIs that do not provide it
1556 # and use the package manager implementation when available (i.e. EAPI >= 5).
1557 # If USE flag is set, echo [true output][true suffix] (defaults to "yes"),
1558 # otherwise echo [false output][false suffix] (defaults to "no").
1559 if has "${EAPI:-0}" 0 1 2 3 4; then
1560         usex() { use "$1" && echo "${2-yes}$4" || echo "${3-no}$5" ; } #382963
1561 fi
1562
1563 # @FUNCTION: prune_libtool_files
1564 # @USAGE: [--all|--modules]
1565 # @DESCRIPTION:
1566 # Locate unnecessary libtool files (.la) and libtool static archives
1567 # (.a) and remove them from installation image.
1568 #
1569 # By default, .la files are removed whenever the static linkage can
1570 # either be performed using pkg-config or doesn't introduce additional
1571 # flags.
1572 #
1573 # If '--modules' argument is passed, .la files for modules (plugins) are
1574 # removed as well. This is usually useful when the package installs
1575 # plugins and the plugin loader does not use .la files.
1576 #
1577 # If '--all' argument is passed, all .la files are removed without
1578 # performing any heuristic on them. You shouldn't ever use that,
1579 # and instead report a bug in the algorithm instead.
1580 #
1581 # The .a files are only removed whenever corresponding .la files state
1582 # that they should not be linked to, i.e. whenever these files
1583 # correspond to plugins.
1584 #
1585 # Note: if your package installs both static libraries and .pc files
1586 # which use variable substitution for -l flags, you need to add
1587 # pkg-config to your DEPEND.
1588 prune_libtool_files() {
1589         debug-print-function ${FUNCNAME} "$@"
1590
1591         local removing_all removing_modules opt
1592         _eutils_eprefix_init
1593         for opt; do
1594                 case "${opt}" in
1595                         --all)
1596                                 removing_all=1
1597                                 removing_modules=1
1598                                 ;;
1599                         --modules)
1600                                 removing_modules=1
1601                                 ;;
1602                         *)
1603                                 die "Invalid argument to ${FUNCNAME}(): ${opt}"
1604                 esac
1605         done
1606
1607         local f
1608         local queue=()
1609         while IFS= read -r -d '' f; do # for all .la files
1610                 local archivefile=${f/%.la/.a}
1611
1612                 # The following check is done by libtool itself.
1613                 # It helps us avoid removing random files which match '*.la',
1614                 # see bug #468380.
1615                 if ! sed -n -e '/^# Generated by .*libtool/q0;4q1' "${f}"; then
1616                         continue
1617                 fi
1618
1619                 [[ ${f} != ${archivefile} ]] || die 'regex sanity check failed'
1620                 local reason= pkgconfig_scanned=
1621                 local snotlink=$(sed -n -e 's:^shouldnotlink=::p' "${f}")
1622
1623                 if [[ ${snotlink} == yes ]]; then
1624
1625                         # Remove static libs we're not supposed to link against.
1626                         if [[ -f ${archivefile} ]]; then
1627                                 einfo "Removing unnecessary ${archivefile#${D%/}} (static plugin)"
1628                                 queue+=( "${archivefile}" )
1629                         fi
1630
1631                         # The .la file may be used by a module loader, so avoid removing it
1632                         # unless explicitly requested.
1633                         if [[ ${removing_modules} ]]; then
1634                                 reason='module'
1635                         fi
1636
1637                 else
1638
1639                         # Remove .la files when:
1640                         # - user explicitly wants us to remove all .la files,
1641                         # - respective static archive doesn't exist,
1642                         # - they are covered by a .pc file already,
1643                         # - they don't provide any new information (no libs & no flags).
1644
1645                         if [[ ${removing_all} ]]; then
1646                                 reason='requested'
1647                         elif [[ ! -f ${archivefile} ]]; then
1648                                 reason='no static archive'
1649                         elif [[ ! $(sed -nre \
1650                                         "s/^(dependency_libs|inherited_linker_flags)='(.*)'$/\2/p" \
1651                                         "${f}") ]]; then
1652                                 reason='no libs & flags'
1653                         else
1654                                 if [[ ! ${pkgconfig_scanned} ]]; then
1655                                         # Create a list of all .pc-covered libs.
1656                                         local pc_libs=()
1657                                         if [[ ! ${removing_all} ]]; then
1658                                                 local pc
1659                                                 local tf=${T}/prune-lt-files.pc
1660                                                 local pkgconf=$(tc-getPKG_CONFIG)
1661
1662                                                 while IFS= read -r -d '' pc; do # for all .pc files
1663                                                         local arg libs
1664
1665                                                         # Use pkg-config if available (and works),
1666                                                         # fallback to sed.
1667                                                         if ${pkgconf} --exists "${pc}" &>/dev/null; then
1668                                                                 sed -e '/^Requires:/d' "${pc}" > "${tf}"
1669                                                                 libs=$(${pkgconf} --libs "${tf}")
1670                                                         else
1671                                                                 libs=$(sed -ne 's/^Libs://p' "${pc}")
1672                                                         fi
1673
1674                                                         for arg in ${libs}; do
1675                                                                 if [[ ${arg} == -l* ]]; then
1676                                                                         if [[ ${arg} == '*$*' ]]; then
1677                                                                                 eqawarn "${FUNCNAME}: variable substitution likely failed in ${pc}"
1678                                                                                 eqawarn "(arg: ${arg})"
1679                                                                                 eqawarn "Most likely, you need to add virtual/pkgconfig to DEPEND."
1680                                                                         fi
1681
1682                                                                         pc_libs+=( lib${arg#-l}.la )
1683                                                                 fi
1684                                                         done
1685                                                 done < <(find "${D}" -type f -name '*.pc' -print0)
1686
1687                                                 rm -f "${tf}"
1688                                         fi
1689
1690                                         pkgconfig_scanned=1
1691                                 fi # pkgconfig_scanned
1692
1693                                 has "${f##*/}" "${pc_libs[@]}" && reason='covered by .pc'
1694                         fi # removal due to .pc
1695
1696                 fi # shouldnotlink==no
1697
1698                 if [[ ${reason} ]]; then
1699                         einfo "Removing unnecessary ${f#${D%/}} (${reason})"
1700                         queue+=( "${f}" )
1701                 fi
1702         done < <(find "${ED}" -xtype f -name '*.la' -print0)
1703
1704         if [[ ${queue[@]} ]]; then
1705                 rm -f "${queue[@]}"
1706         fi
1707 }
1708
1709 # @FUNCTION: einstalldocs
1710 # @DESCRIPTION:
1711 # Install documentation using DOCS and HTML_DOCS.
1712 #
1713 # If DOCS is declared and non-empty, all files listed in it are
1714 # installed. The files must exist, otherwise the function will fail.
1715 # In EAPI 4 and subsequent EAPIs DOCS may specify directories as well,
1716 # in other EAPIs using directories is unsupported.
1717 #
1718 # If DOCS is not declared, the files matching patterns given
1719 # in the default EAPI implementation of src_install will be installed.
1720 # If this is undesired, DOCS can be set to empty value to prevent any
1721 # documentation from being installed.
1722 #
1723 # If HTML_DOCS is declared and non-empty, all files and/or directories
1724 # listed in it are installed as HTML docs (using dohtml).
1725 #
1726 # Both DOCS and HTML_DOCS can either be an array or a whitespace-
1727 # separated list. Whenever directories are allowed, '<directory>/.' may
1728 # be specified in order to install all files within the directory
1729 # without creating a sub-directory in docdir.
1730 #
1731 # Passing additional options to dodoc and dohtml is not supported.
1732 # If you needed such a thing, you need to call those helpers explicitly.
1733 if has "${EAPI:-0}" 0 1 2 3 4 5; then
1734         einstalldocs() {
1735                 debug-print-function ${FUNCNAME} "${@}"
1736
1737                 local dodoc_opts=-r
1738                 has ${EAPI} 0 1 2 3 && dodoc_opts=
1739
1740                 if ! declare -p DOCS &>/dev/null ; then
1741                         local d
1742                         for d in README* ChangeLog AUTHORS NEWS TODO CHANGES \
1743                                         THANKS BUGS FAQ CREDITS CHANGELOG ; do
1744                                 if [[ -s ${d} ]] ; then
1745                                         dodoc "${d}" || die
1746                                 fi
1747                         done
1748                 elif [[ $(declare -p DOCS) == "declare -a"* ]] ; then
1749                         if [[ ${DOCS[@]} ]] ; then
1750                                 dodoc ${dodoc_opts} "${DOCS[@]}" || die
1751                         fi
1752                 else
1753                         if [[ ${DOCS} ]] ; then
1754                                 dodoc ${dodoc_opts} ${DOCS} || die
1755                         fi
1756                 fi
1757
1758                 if [[ $(declare -p HTML_DOCS 2>/dev/null) == "declare -a"* ]] ; then
1759                         if [[ ${HTML_DOCS[@]} ]] ; then
1760                                 dohtml -r "${HTML_DOCS[@]}" || die
1761                         fi
1762                 else
1763                         if [[ ${HTML_DOCS} ]] ; then
1764                                 dohtml -r ${HTML_DOCS} || die
1765                         fi
1766                 fi
1767
1768                 return 0
1769         }
1770 fi
1771
1772 check_license() { die "you no longer need this as portage supports ACCEPT_LICENSE itself"; }
1773
1774 # @FUNCTION: optfeature
1775 # @USAGE: <short description> <package atom to match> [other atoms]
1776 # @DESCRIPTION:
1777 # Print out a message suggesting an optional package (or packages) which
1778 # provide the described functionality
1779 #
1780 # The following snippet would suggest app-misc/foo for optional foo support,
1781 # app-misc/bar or app-misc/baz[bar] for optional bar support
1782 # and either both app-misc/a and app-misc/b or app-misc/c for alphabet support.
1783 # @CODE
1784 #       optfeature "foo support" app-misc/foo
1785 #       optfeature "bar support" app-misc/bar app-misc/baz[bar]
1786 #       optfeature "alphabet support" "app-misc/a app-misc/b" app-misc/c
1787 # @CODE
1788 optfeature() {
1789         debug-print-function ${FUNCNAME} "$@"
1790         local i j msg
1791         local desc=$1
1792         local flag=0
1793         shift
1794         for i; do
1795                 for j in ${i}; do
1796                         if has_version "${j}"; then
1797                                 flag=1
1798                         else
1799                                 flag=0
1800                                 break
1801                         fi
1802                 done
1803                 if [[ ${flag} -eq 1 ]]; then
1804                         break
1805                 fi
1806         done
1807         if [[ ${flag} -eq 0 ]]; then
1808                 for i; do
1809                         msg=" "
1810                         for j in ${i}; do
1811                                 msg+=" ${j} and"
1812                         done
1813                         msg="${msg:0: -4} for ${desc}"
1814                         elog "${msg}"
1815                 done
1816         fi
1817 }
1818
1819 fi