1 |
# Copyright 1999-2012 Gentoo Foundation |
2 |
# Distributed under the terms of the GNU General Public License v2 |
3 |
# $Header: /var/cvsroot/gentoo-x86/eclass/eutils.eclass,v 1.386 2012/03/01 22:10:50 naota Exp $ |
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 [[ ${___ECLASS_ONCE_EUTILS} != "recur -_+^+_- spank" ]] ; then |
19 |
___ECLASS_ONCE_EUTILS="recur -_+^+_- spank" |
20 |
|
21 |
inherit multilib user |
22 |
|
23 |
DESCRIPTION="Based on the ${ECLASS} eclass" |
24 |
|
25 |
if has "${EAPI:-0}" 0 1 2; then |
26 |
|
27 |
# @FUNCTION: epause |
28 |
# @USAGE: [seconds] |
29 |
# @DESCRIPTION: |
30 |
# Sleep for the specified number of seconds (default of 5 seconds). Useful when |
31 |
# printing a message the user should probably be reading and often used in |
32 |
# conjunction with the ebeep function. If the EPAUSE_IGNORE env var is set, |
33 |
# don't wait at all. Defined in EAPIs 0 1 and 2. |
34 |
epause() { |
35 |
[[ -z ${EPAUSE_IGNORE} ]] && sleep ${1:-5} |
36 |
} |
37 |
|
38 |
# @FUNCTION: ebeep |
39 |
# @USAGE: [number of beeps] |
40 |
# @DESCRIPTION: |
41 |
# Issue the specified number of beeps (default of 5 beeps). Useful when |
42 |
# printing a message the user should probably be reading and often used in |
43 |
# conjunction with the epause function. If the EBEEP_IGNORE env var is set, |
44 |
# don't beep at all. Defined in EAPIs 0 1 and 2. |
45 |
ebeep() { |
46 |
local n |
47 |
if [[ -z ${EBEEP_IGNORE} ]] ; then |
48 |
for ((n=1 ; n <= ${1:-5} ; n++)) ; do |
49 |
echo -ne "\a" |
50 |
sleep 0.1 &>/dev/null ; sleep 0,1 &>/dev/null |
51 |
echo -ne "\a" |
52 |
sleep 1 |
53 |
done |
54 |
fi |
55 |
} |
56 |
|
57 |
else |
58 |
|
59 |
ebeep() { |
60 |
ewarn "QA Notice: ebeep is not defined in EAPI=${EAPI}, please file a bug at http://bugs.gentoo.org" |
61 |
} |
62 |
|
63 |
epause() { |
64 |
ewarn "QA Notice: epause is not defined in EAPI=${EAPI}, please file a bug at http://bugs.gentoo.org" |
65 |
} |
66 |
|
67 |
fi |
68 |
|
69 |
# @FUNCTION: eqawarn |
70 |
# @USAGE: [message] |
71 |
# @DESCRIPTION: |
72 |
# Proxy to ewarn for package managers that don't provide eqawarn and use the PM |
73 |
# implementation if available. Reuses PORTAGE_ELOG_CLASSES as set by the dev |
74 |
# profile. |
75 |
if ! declare -F eqawarn >/dev/null ; then |
76 |
eqawarn() { |
77 |
has qa ${PORTAGE_ELOG_CLASSES} && ewarn "$@" |
78 |
: |
79 |
} |
80 |
fi |
81 |
|
82 |
# @FUNCTION: ecvs_clean |
83 |
# @USAGE: [list of dirs] |
84 |
# @DESCRIPTION: |
85 |
# Remove CVS directories recursiveley. Useful when a source tarball contains |
86 |
# internal CVS directories. Defaults to $PWD. |
87 |
ecvs_clean() { |
88 |
[[ -z $* ]] && set -- . |
89 |
find "$@" -type d -name 'CVS' -prune -print0 | xargs -0 rm -rf |
90 |
find "$@" -type f -name '.cvs*' -print0 | xargs -0 rm -rf |
91 |
} |
92 |
|
93 |
# @FUNCTION: esvn_clean |
94 |
# @USAGE: [list of dirs] |
95 |
# @DESCRIPTION: |
96 |
# Remove .svn directories recursiveley. Useful when a source tarball contains |
97 |
# internal Subversion directories. Defaults to $PWD. |
98 |
esvn_clean() { |
99 |
[[ -z $* ]] && set -- . |
100 |
find "$@" -type d -name '.svn' -prune -print0 | xargs -0 rm -rf |
101 |
} |
102 |
|
103 |
# @FUNCTION: estack_push |
104 |
# @USAGE: <stack> [items to push] |
105 |
# @DESCRIPTION: |
106 |
# Push any number of items onto the specified stack. Pick a name that |
107 |
# is a valid variable (i.e. stick to alphanumerics), and push as many |
108 |
# items as you like onto the stack at once. |
109 |
# |
110 |
# The following code snippet will echo 5, then 4, then 3, then ... |
111 |
# @CODE |
112 |
# estack_push mystack 1 2 3 4 5 |
113 |
# while estack_pop mystack i ; do |
114 |
# echo "${i}" |
115 |
# done |
116 |
# @CODE |
117 |
estack_push() { |
118 |
[[ $# -eq 0 ]] && die "estack_push: incorrect # of arguments" |
119 |
local stack_name="__ESTACK_$1__" ; shift |
120 |
eval ${stack_name}+=\( \"\$@\" \) |
121 |
} |
122 |
|
123 |
# @FUNCTION: estack_pop |
124 |
# @USAGE: <stack> [variable] |
125 |
# @DESCRIPTION: |
126 |
# Pop a single item off the specified stack. If a variable is specified, |
127 |
# the popped item is stored there. If no more items are available, return |
128 |
# 1, else return 0. See estack_push for more info. |
129 |
estack_pop() { |
130 |
[[ $# -eq 0 || $# -gt 2 ]] && die "estack_pop: incorrect # of arguments" |
131 |
|
132 |
# We use the fugly __estack_xxx var names to avoid collision with |
133 |
# passing back the return value. If we used "local i" and the |
134 |
# caller ran `estack_pop ... i`, we'd end up setting the local |
135 |
# copy of "i" rather than the caller's copy. The __estack_xxx |
136 |
# garbage is preferable to using $1/$2 everywhere as that is a |
137 |
# bit harder to read. |
138 |
local __estack_name="__ESTACK_$1__" ; shift |
139 |
local __estack_retvar=$1 ; shift |
140 |
eval local __estack_i=\${#${__estack_name}\[@\]} |
141 |
# Don't warn -- let the caller interpret this as a failure |
142 |
# or as normal behavior (akin to `shift`) |
143 |
[[ $(( --__estack_i )) -eq -1 ]] && return 1 |
144 |
|
145 |
if [[ -n ${__estack_retvar} ]] ; then |
146 |
eval ${__estack_retvar}=\"\${${__estack_name}\[${__estack_i}\]}\" |
147 |
fi |
148 |
eval unset ${__estack_name}\[${__estack_i}\] |
149 |
} |
150 |
|
151 |
# @FUNCTION: eshopts_push |
152 |
# @USAGE: [options to `set` or `shopt`] |
153 |
# @DESCRIPTION: |
154 |
# Often times code will want to enable a shell option to change code behavior. |
155 |
# Since changing shell options can easily break other pieces of code (which |
156 |
# assume the default state), eshopts_push is used to (1) push the current shell |
157 |
# options onto a stack and (2) pass the specified arguments to set. |
158 |
# |
159 |
# If the first argument is '-s' or '-u', we assume you want to call `shopt` |
160 |
# rather than `set` as there are some options only available via that. |
161 |
# |
162 |
# A common example is to disable shell globbing so that special meaning/care |
163 |
# may be used with variables/arguments to custom functions. That would be: |
164 |
# @CODE |
165 |
# eshopts_push -s noglob |
166 |
# for x in ${foo} ; do |
167 |
# if ...some check... ; then |
168 |
# eshopts_pop |
169 |
# return 0 |
170 |
# fi |
171 |
# done |
172 |
# eshopts_pop |
173 |
# @CODE |
174 |
eshopts_push() { |
175 |
if [[ $1 == -[su] ]] ; then |
176 |
estack_push eshopts "$(shopt -p)" |
177 |
[[ $# -eq 0 ]] && return 0 |
178 |
shopt "$@" || die "${FUNCNAME}: bad options to shopt: $*" |
179 |
else |
180 |
estack_push eshopts $- |
181 |
[[ $# -eq 0 ]] && return 0 |
182 |
set "$@" || die "${FUNCNAME}: bad options to set: $*" |
183 |
fi |
184 |
} |
185 |
|
186 |
# @FUNCTION: eshopts_pop |
187 |
# @USAGE: |
188 |
# @DESCRIPTION: |
189 |
# Restore the shell options to the state saved with the corresponding |
190 |
# eshopts_push call. See that function for more details. |
191 |
eshopts_pop() { |
192 |
local s |
193 |
estack_pop eshopts s || die "${FUNCNAME}: unbalanced push" |
194 |
if [[ ${s} == "shopt -"* ]] ; then |
195 |
eval "${s}" || die "${FUNCNAME}: sanity: invalid shopt options: ${s}" |
196 |
else |
197 |
set +$- || die "${FUNCNAME}: sanity: invalid shell settings: $-" |
198 |
set -${s} || die "${FUNCNAME}: sanity: unable to restore saved shell settings: ${s}" |
199 |
fi |
200 |
} |
201 |
|
202 |
# @FUNCTION: eumask_push |
203 |
# @USAGE: <new umask> |
204 |
# @DESCRIPTION: |
205 |
# Set the umask to the new value specified while saving the previous |
206 |
# value onto a stack. Useful for temporarily changing the umask. |
207 |
eumask_push() { |
208 |
estack_push eumask "$(umask)" |
209 |
umask "$@" || die "${FUNCNAME}: bad options to umask: $*" |
210 |
} |
211 |
|
212 |
# @FUNCTION: eumask_pop |
213 |
# @USAGE: |
214 |
# @DESCRIPTION: |
215 |
# Restore the previous umask state. |
216 |
eumask_pop() { |
217 |
[[ $# -eq 0 ]] || die "${FUNCNAME}: we take no options" |
218 |
local s |
219 |
estack_pop eumask s || die "${FUNCNAME}: unbalanced push" |
220 |
umask ${s} || die "${FUNCNAME}: sanity: could not restore umask: ${s}" |
221 |
} |
222 |
|
223 |
# @VARIABLE: EPATCH_SOURCE |
224 |
# @DESCRIPTION: |
225 |
# Default directory to search for patches. |
226 |
EPATCH_SOURCE="${WORKDIR}/patch" |
227 |
# @VARIABLE: EPATCH_SUFFIX |
228 |
# @DESCRIPTION: |
229 |
# Default extension for patches (do not prefix the period yourself). |
230 |
EPATCH_SUFFIX="patch.bz2" |
231 |
# @VARIABLE: EPATCH_OPTS |
232 |
# @DESCRIPTION: |
233 |
# Default options for patch: |
234 |
# @CODE |
235 |
# -g0 - keep RCS, ClearCase, Perforce and SCCS happy #24571 |
236 |
# --no-backup-if-mismatch - do not leave .orig files behind |
237 |
# -E - automatically remove empty files |
238 |
# @CODE |
239 |
EPATCH_OPTS="-g0 -E --no-backup-if-mismatch" |
240 |
# @VARIABLE: EPATCH_EXCLUDE |
241 |
# @DESCRIPTION: |
242 |
# List of patches not to apply. Note this is only file names, |
243 |
# and not the full path. Globs accepted. |
244 |
EPATCH_EXCLUDE="" |
245 |
# @VARIABLE: EPATCH_SINGLE_MSG |
246 |
# @DESCRIPTION: |
247 |
# Change the printed message for a single patch. |
248 |
EPATCH_SINGLE_MSG="" |
249 |
# @VARIABLE: EPATCH_MULTI_MSG |
250 |
# @DESCRIPTION: |
251 |
# Change the printed message for multiple patches. |
252 |
EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates) ..." |
253 |
# @VARIABLE: EPATCH_FORCE |
254 |
# @DESCRIPTION: |
255 |
# Only require patches to match EPATCH_SUFFIX rather than the extended |
256 |
# arch naming style. |
257 |
EPATCH_FORCE="no" |
258 |
|
259 |
# @FUNCTION: epatch |
260 |
# @USAGE: [patches] [dirs of patches] |
261 |
# @DESCRIPTION: |
262 |
# epatch is designed to greatly simplify the application of patches. It can |
263 |
# process patch files directly, or directories of patches. The patches may be |
264 |
# compressed (bzip/gzip/etc...) or plain text. You generally need not specify |
265 |
# the -p option as epatch will automatically attempt -p0 to -p5 until things |
266 |
# apply successfully. |
267 |
# |
268 |
# If you do not specify any options, then epatch will default to the directory |
269 |
# specified by EPATCH_SOURCE. |
270 |
# |
271 |
# When processing directories, epatch will apply all patches that match: |
272 |
# @CODE |
273 |
# if ${EPATCH_FORCE} != "yes" |
274 |
# ??_${ARCH}_foo.${EPATCH_SUFFIX} |
275 |
# else |
276 |
# *.${EPATCH_SUFFIX} |
277 |
# @CODE |
278 |
# The leading ?? are typically numbers used to force consistent patch ordering. |
279 |
# The arch field is used to apply patches only for the host architecture with |
280 |
# the special value of "all" means apply for everyone. Note that using values |
281 |
# other than "all" is highly discouraged -- you should apply patches all the |
282 |
# time and let architecture details be detected at configure/compile time. |
283 |
# |
284 |
# If EPATCH_SUFFIX is empty, then no period before it is implied when searching |
285 |
# for patches to apply. |
286 |
# |
287 |
# Refer to the other EPATCH_xxx variables for more customization of behavior. |
288 |
epatch() { |
289 |
_epatch_draw_line() { |
290 |
# create a line of same length as input string |
291 |
[[ -z $1 ]] && set "$(printf "%65s" '')" |
292 |
echo "${1//?/=}" |
293 |
} |
294 |
|
295 |
unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402 |
296 |
|
297 |
# Let the rest of the code process one user arg at a time -- |
298 |
# each arg may expand into multiple patches, and each arg may |
299 |
# need to start off with the default global EPATCH_xxx values |
300 |
if [[ $# -gt 1 ]] ; then |
301 |
local m |
302 |
for m in "$@" ; do |
303 |
epatch "${m}" |
304 |
done |
305 |
return 0 |
306 |
fi |
307 |
|
308 |
local SINGLE_PATCH="no" |
309 |
# no args means process ${EPATCH_SOURCE} |
310 |
[[ $# -eq 0 ]] && set -- "${EPATCH_SOURCE}" |
311 |
|
312 |
if [[ -f $1 ]] ; then |
313 |
SINGLE_PATCH="yes" |
314 |
set -- "$1" |
315 |
# Use the suffix from the single patch (localize it); the code |
316 |
# below will find the suffix for us |
317 |
local EPATCH_SUFFIX=$1 |
318 |
|
319 |
elif [[ -d $1 ]] ; then |
320 |
# Some people like to make dirs of patches w/out suffixes (vim) |
321 |
set -- "$1"/*${EPATCH_SUFFIX:+."${EPATCH_SUFFIX}"} |
322 |
|
323 |
elif [[ -f ${EPATCH_SOURCE}/$1 ]] ; then |
324 |
# Re-use EPATCH_SOURCE as a search dir |
325 |
epatch "${EPATCH_SOURCE}/$1" |
326 |
return $? |
327 |
|
328 |
else |
329 |
# sanity check ... if it isn't a dir or file, wtf man ? |
330 |
[[ $# -ne 0 ]] && EPATCH_SOURCE=$1 |
331 |
echo |
332 |
eerror "Cannot find \$EPATCH_SOURCE! Value for \$EPATCH_SOURCE is:" |
333 |
eerror |
334 |
eerror " ${EPATCH_SOURCE}" |
335 |
eerror " ( ${EPATCH_SOURCE##*/} )" |
336 |
echo |
337 |
die "Cannot find \$EPATCH_SOURCE!" |
338 |
fi |
339 |
|
340 |
local PIPE_CMD |
341 |
case ${EPATCH_SUFFIX##*\.} in |
342 |
xz) PIPE_CMD="xz -dc" ;; |
343 |
lzma) PIPE_CMD="lzma -dc" ;; |
344 |
bz2) PIPE_CMD="bzip2 -dc" ;; |
345 |
gz|Z|z) PIPE_CMD="gzip -dc" ;; |
346 |
ZIP|zip) PIPE_CMD="unzip -p" ;; |
347 |
*) ;; |
348 |
esac |
349 |
|
350 |
[[ ${SINGLE_PATCH} == "no" ]] && einfo "${EPATCH_MULTI_MSG}" |
351 |
|
352 |
local x |
353 |
for x in "$@" ; do |
354 |
# If the patch dir given contains subdirs, or our EPATCH_SUFFIX |
355 |
# didn't match anything, ignore continue on |
356 |
[[ ! -f ${x} ]] && continue |
357 |
|
358 |
local patchname=${x##*/} |
359 |
|
360 |
# Apply single patches, or forced sets of patches, or |
361 |
# patches with ARCH dependant names. |
362 |
# ???_arch_foo.patch |
363 |
# Else, skip this input altogether |
364 |
local a=${patchname#*_} # strip the ???_ |
365 |
a=${a%%_*} # strip the _foo.patch |
366 |
if ! [[ ${SINGLE_PATCH} == "yes" || \ |
367 |
${EPATCH_FORCE} == "yes" || \ |
368 |
${a} == all || \ |
369 |
${a} == ${ARCH} ]] |
370 |
then |
371 |
continue |
372 |
fi |
373 |
|
374 |
# Let people filter things dynamically |
375 |
if [[ -n ${EPATCH_EXCLUDE} ]] ; then |
376 |
# let people use globs in the exclude |
377 |
eshopts_push -o noglob |
378 |
|
379 |
local ex |
380 |
for ex in ${EPATCH_EXCLUDE} ; do |
381 |
if [[ ${patchname} == ${ex} ]] ; then |
382 |
eshopts_pop |
383 |
continue 2 |
384 |
fi |
385 |
done |
386 |
|
387 |
eshopts_pop |
388 |
fi |
389 |
|
390 |
if [[ ${SINGLE_PATCH} == "yes" ]] ; then |
391 |
if [[ -n ${EPATCH_SINGLE_MSG} ]] ; then |
392 |
einfo "${EPATCH_SINGLE_MSG}" |
393 |
else |
394 |
einfo "Applying ${patchname} ..." |
395 |
fi |
396 |
else |
397 |
einfo " ${patchname} ..." |
398 |
fi |
399 |
|
400 |
# most of the time, there will only be one run per unique name, |
401 |
# but if there are more, make sure we get unique log filenames |
402 |
local STDERR_TARGET="${T}/${patchname}.out" |
403 |
if [[ -e ${STDERR_TARGET} ]] ; then |
404 |
STDERR_TARGET="${T}/${patchname}-$$.out" |
405 |
fi |
406 |
|
407 |
printf "***** %s *****\nPWD: %s\n\n" "${patchname}" "${PWD}" > "${STDERR_TARGET}" |
408 |
|
409 |
# Decompress the patch if need be |
410 |
local count=0 |
411 |
local PATCH_TARGET |
412 |
if [[ -n ${PIPE_CMD} ]] ; then |
413 |
PATCH_TARGET="${T}/$$.patch" |
414 |
echo "PIPE_COMMAND: ${PIPE_CMD} ${x} > ${PATCH_TARGET}" >> "${STDERR_TARGET}" |
415 |
|
416 |
if ! (${PIPE_CMD} "${x}" > "${PATCH_TARGET}") >> "${STDERR_TARGET}" 2>&1 ; then |
417 |
echo |
418 |
eerror "Could not extract patch!" |
419 |
#die "Could not extract patch!" |
420 |
count=5 |
421 |
break |
422 |
fi |
423 |
else |
424 |
PATCH_TARGET=${x} |
425 |
fi |
426 |
|
427 |
# Check for absolute paths in patches. If sandbox is disabled, |
428 |
# people could (accidently) patch files in the root filesystem. |
429 |
# Or trigger other unpleasantries #237667. So disallow -p0 on |
430 |
# such patches. |
431 |
local abs_paths=$(egrep -n '^[-+]{3} /' "${PATCH_TARGET}" | awk '$2 != "/dev/null" { print }') |
432 |
if [[ -n ${abs_paths} ]] ; then |
433 |
count=1 |
434 |
printf "NOTE: skipping -p0 due to absolute paths in patch:\n%s\n" "${abs_paths}" >> "${STDERR_TARGET}" |
435 |
fi |
436 |
# Similar reason, but with relative paths. |
437 |
local rel_paths=$(egrep -n '^[-+]{3} [^ ]*[.][.]/' "${PATCH_TARGET}") |
438 |
if [[ -n ${rel_paths} ]] ; then |
439 |
eqawarn "QA Notice: Your patch uses relative paths '../'." |
440 |
eqawarn " In the future this will cause a failure." |
441 |
eqawarn "${rel_paths}" |
442 |
fi |
443 |
|
444 |
# Dynamically detect the correct -p# ... i'm lazy, so shoot me :/ |
445 |
local patch_cmd |
446 |
while [[ ${count} -lt 5 ]] ; do |
447 |
patch_cmd="${BASH_ALIASES[patch]:-patch} -p${count} ${EPATCH_OPTS}" |
448 |
|
449 |
# Generate some useful debug info ... |
450 |
( |
451 |
_epatch_draw_line "***** ${patchname} *****" |
452 |
echo |
453 |
echo "PATCH COMMAND: ${patch_cmd} < '${PATCH_TARGET}'" |
454 |
echo |
455 |
_epatch_draw_line "***** ${patchname} *****" |
456 |
${patch_cmd} --dry-run -f < "${PATCH_TARGET}" 2>&1 |
457 |
ret=$? |
458 |
echo |
459 |
echo "patch program exited with status ${ret}" |
460 |
exit ${ret} |
461 |
) >> "${STDERR_TARGET}" |
462 |
|
463 |
if [ $? -eq 0 ] ; then |
464 |
( |
465 |
_epatch_draw_line "***** ${patchname} *****" |
466 |
echo |
467 |
echo "ACTUALLY APPLYING ${patchname} ..." |
468 |
echo |
469 |
_epatch_draw_line "***** ${patchname} *****" |
470 |
${patch_cmd} < "${PATCH_TARGET}" 2>&1 |
471 |
ret=$? |
472 |
echo |
473 |
echo "patch program exited with status ${ret}" |
474 |
exit ${ret} |
475 |
) >> "${STDERR_TARGET}" |
476 |
|
477 |
if [ $? -ne 0 ] ; then |
478 |
echo |
479 |
eerror "A dry-run of patch command succeeded, but actually" |
480 |
eerror "applying the patch failed!" |
481 |
#die "Real world sux compared to the dreamworld!" |
482 |
count=5 |
483 |
fi |
484 |
break |
485 |
fi |
486 |
|
487 |
: $(( count++ )) |
488 |
done |
489 |
|
490 |
# if we had to decompress the patch, delete the temp one |
491 |
if [[ -n ${PIPE_CMD} ]] ; then |
492 |
rm -f "${PATCH_TARGET}" |
493 |
fi |
494 |
|
495 |
if [[ ${count} -ge 5 ]] ; then |
496 |
echo |
497 |
eerror "Failed Patch: ${patchname} !" |
498 |
eerror " ( ${PATCH_TARGET} )" |
499 |
eerror |
500 |
eerror "Include in your bugreport the contents of:" |
501 |
eerror |
502 |
eerror " ${STDERR_TARGET}" |
503 |
echo |
504 |
die "Failed Patch: ${patchname}!" |
505 |
fi |
506 |
|
507 |
# if everything worked, delete the full debug patch log |
508 |
rm -f "${STDERR_TARGET}" |
509 |
|
510 |
# then log away the exact stuff for people to review later |
511 |
cat <<-EOF >> "${T}/epatch.log" |
512 |
PATCH: ${x} |
513 |
CMD: ${patch_cmd} |
514 |
PWD: ${PWD} |
515 |
|
516 |
EOF |
517 |
eend 0 |
518 |
done |
519 |
|
520 |
[[ ${SINGLE_PATCH} == "no" ]] && einfo "Done with patching" |
521 |
: # everything worked |
522 |
} |
523 |
|
524 |
# @FUNCTION: epatch_user |
525 |
# @USAGE: |
526 |
# @DESCRIPTION: |
527 |
# Applies user-provided patches to the source tree. The patches are |
528 |
# taken from /etc/portage/patches/<CATEGORY>/<PF|P|PN>/, where the first |
529 |
# of these three directories to exist will be the one to use, ignoring |
530 |
# any more general directories which might exist as well. They must end |
531 |
# in ".patch" to be applied. |
532 |
# |
533 |
# User patches are intended for quick testing of patches without ebuild |
534 |
# modifications, as well as for permanent customizations a user might |
535 |
# desire. Obviously, there can be no official support for arbitrarily |
536 |
# patched ebuilds. So whenever a build log in a bug report mentions that |
537 |
# user patches were applied, the user should be asked to reproduce the |
538 |
# problem without these. |
539 |
# |
540 |
# Not all ebuilds do call this function, so placing patches in the |
541 |
# stated directory might or might not work, depending on the package and |
542 |
# the eclasses it inherits and uses. It is safe to call the function |
543 |
# repeatedly, so it is always possible to add a call at the ebuild |
544 |
# level. The first call is the time when the patches will be |
545 |
# applied. |
546 |
# |
547 |
# Ideally, this function should be called after gentoo-specific patches |
548 |
# have been applied, so that their code can be modified as well, but |
549 |
# before calls to e.g. eautoreconf, as the user patches might affect |
550 |
# autotool input files as well. |
551 |
epatch_user() { |
552 |
[[ $# -ne 0 ]] && die "epatch_user takes no options" |
553 |
|
554 |
# Allow multiple calls to this function; ignore all but the first |
555 |
local applied="${T}/epatch_user.log" |
556 |
[[ -e ${applied} ]] && return 2 |
557 |
|
558 |
# don't clobber any EPATCH vars that the parent might want |
559 |
local EPATCH_SOURCE check base=${PORTAGE_CONFIGROOT%/}/etc/portage/patches |
560 |
for check in ${CATEGORY}/{${P}-${PR},${P},${PN}}; do |
561 |
EPATCH_SOURCE=${base}/${CTARGET}/${check} |
562 |
[[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${base}/${CHOST}/${check} |
563 |
[[ -r ${EPATCH_SOURCE} ]] || EPATCH_SOURCE=${base}/${check} |
564 |
if [[ -d ${EPATCH_SOURCE} ]] ; then |
565 |
EPATCH_SOURCE=${EPATCH_SOURCE} \ |
566 |
EPATCH_SUFFIX="patch" \ |
567 |
EPATCH_FORCE="yes" \ |
568 |
EPATCH_MULTI_MSG="Applying user patches from ${EPATCH_SOURCE} ..." \ |
569 |
epatch |
570 |
echo "${EPATCH_SOURCE}" > "${applied}" |
571 |
return 0 |
572 |
fi |
573 |
done |
574 |
echo "none" > "${applied}" |
575 |
return 1 |
576 |
} |
577 |
|
578 |
# @FUNCTION: emktemp |
579 |
# @USAGE: [temp dir] |
580 |
# @DESCRIPTION: |
581 |
# Cheap replacement for when debianutils (and thus mktemp) |
582 |
# does not exist on the users system. |
583 |
emktemp() { |
584 |
local exe="touch" |
585 |
[[ $1 == -d ]] && exe="mkdir" && shift |
586 |
local topdir=$1 |
587 |
|
588 |
if [[ -z ${topdir} ]] ; then |
589 |
[[ -z ${T} ]] \ |
590 |
&& topdir="/tmp" \ |
591 |
|| topdir=${T} |
592 |
fi |
593 |
|
594 |
if ! type -P mktemp > /dev/null ; then |
595 |
# system lacks `mktemp` so we have to fake it |
596 |
local tmp=/ |
597 |
while [[ -e ${tmp} ]] ; do |
598 |
tmp=${topdir}/tmp.${RANDOM}.${RANDOM}.${RANDOM} |
599 |
done |
600 |
${exe} "${tmp}" || ${exe} -p "${tmp}" |
601 |
echo "${tmp}" |
602 |
else |
603 |
# the args here will give slightly wierd names on BSD, |
604 |
# but should produce a usable file on all userlands |
605 |
if [[ ${exe} == "touch" ]] ; then |
606 |
TMPDIR="${topdir}" mktemp -t tmp.XXXXXXXXXX |
607 |
else |
608 |
TMPDIR="${topdir}" mktemp -dt tmp.XXXXXXXXXX |
609 |
fi |
610 |
fi |
611 |
} |
612 |
|
613 |
# @FUNCTION: edos2unix |
614 |
# @USAGE: <file> [more files ...] |
615 |
# @DESCRIPTION: |
616 |
# A handy replacement for dos2unix, recode, fixdos, etc... This allows you |
617 |
# to remove all of these text utilities from DEPEND variables because this |
618 |
# is a script based solution. Just give it a list of files to convert and |
619 |
# they will all be changed from the DOS CRLF format to the UNIX LF format. |
620 |
edos2unix() { |
621 |
[[ $# -eq 0 ]] && return 0 |
622 |
sed -i 's/\r$//' -- "$@" || die |
623 |
} |
624 |
|
625 |
# @FUNCTION: make_desktop_entry |
626 |
# @USAGE: make_desktop_entry(<command>, [name], [icon], [type], [fields]) |
627 |
# @DESCRIPTION: |
628 |
# Make a .desktop file. |
629 |
# |
630 |
# @CODE |
631 |
# binary: what command does the app run with ? |
632 |
# name: the name that will show up in the menu |
633 |
# icon: give your little like a pretty little icon ... |
634 |
# this can be relative (to /usr/share/pixmaps) or |
635 |
# a full path to an icon |
636 |
# type: what kind of application is this? |
637 |
# for categories: |
638 |
# http://standards.freedesktop.org/menu-spec/latest/apa.html |
639 |
# if unset, function tries to guess from package's category |
640 |
# fields: extra fields to append to the desktop file; a printf string |
641 |
# @CODE |
642 |
make_desktop_entry() { |
643 |
[[ -z $1 ]] && die "make_desktop_entry: You must specify the executable" |
644 |
|
645 |
local exec=${1} |
646 |
local name=${2:-${PN}} |
647 |
local icon=${3:-${PN}} |
648 |
local type=${4} |
649 |
local fields=${5} |
650 |
|
651 |
if [[ -z ${type} ]] ; then |
652 |
local catmaj=${CATEGORY%%-*} |
653 |
local catmin=${CATEGORY##*-} |
654 |
case ${catmaj} in |
655 |
app) |
656 |
case ${catmin} in |
657 |
accessibility) type="Utility;Accessibility";; |
658 |
admin) type=System;; |
659 |
antivirus) type=System;; |
660 |
arch) type="Utility;Archiving";; |
661 |
backup) type="Utility;Archiving";; |
662 |
cdr) type="AudioVideo;DiscBurning";; |
663 |
dicts) type="Office;Dictionary";; |
664 |
doc) type=Documentation;; |
665 |
editors) type="Utility;TextEditor";; |
666 |
emacs) type="Development;TextEditor";; |
667 |
emulation) type="System;Emulator";; |
668 |
laptop) type="Settings;HardwareSettings";; |
669 |
office) type=Office;; |
670 |
pda) type="Office;PDA";; |
671 |
vim) type="Development;TextEditor";; |
672 |
xemacs) type="Development;TextEditor";; |
673 |
esac |
674 |
;; |
675 |
|
676 |
dev) |
677 |
type="Development" |
678 |
;; |
679 |
|
680 |
games) |
681 |
case ${catmin} in |
682 |
action|fps) type=ActionGame;; |
683 |
arcade) type=ArcadeGame;; |
684 |
board) type=BoardGame;; |
685 |
emulation) type=Emulator;; |
686 |
kids) type=KidsGame;; |
687 |
puzzle) type=LogicGame;; |
688 |
roguelike) type=RolePlaying;; |
689 |
rpg) type=RolePlaying;; |
690 |
simulation) type=Simulation;; |
691 |
sports) type=SportsGame;; |
692 |
strategy) type=StrategyGame;; |
693 |
esac |
694 |
type="Game;${type}" |
695 |
;; |
696 |
|
697 |
gnome) |
698 |
type="Gnome;GTK" |
699 |
;; |
700 |
|
701 |
kde) |
702 |
type="KDE;Qt" |
703 |
;; |
704 |
|
705 |
mail) |
706 |
type="Network;Email" |
707 |
;; |
708 |
|
709 |
media) |
710 |
case ${catmin} in |
711 |
gfx) |
712 |
type=Graphics |
713 |
;; |
714 |
*) |
715 |
case ${catmin} in |
716 |
radio) type=Tuner;; |
717 |
sound) type=Audio;; |
718 |
tv) type=TV;; |
719 |
video) type=Video;; |
720 |
esac |
721 |
type="AudioVideo;${type}" |
722 |
;; |
723 |
esac |
724 |
;; |
725 |
|
726 |
net) |
727 |
case ${catmin} in |
728 |
dialup) type=Dialup;; |
729 |
ftp) type=FileTransfer;; |
730 |
im) type=InstantMessaging;; |
731 |
irc) type=IRCClient;; |
732 |
mail) type=Email;; |
733 |
news) type=News;; |
734 |
nntp) type=News;; |
735 |
p2p) type=FileTransfer;; |
736 |
voip) type=Telephony;; |
737 |
esac |
738 |
type="Network;${type}" |
739 |
;; |
740 |
|
741 |
sci) |
742 |
case ${catmin} in |
743 |
astro*) type=Astronomy;; |
744 |
bio*) type=Biology;; |
745 |
calc*) type=Calculator;; |
746 |
chem*) type=Chemistry;; |
747 |
elec*) type=Electronics;; |
748 |
geo*) type=Geology;; |
749 |
math*) type=Math;; |
750 |
physics) type=Physics;; |
751 |
visual*) type=DataVisualization;; |
752 |
esac |
753 |
type="Education;Science;${type}" |
754 |
;; |
755 |
|
756 |
sys) |
757 |
type="System" |
758 |
;; |
759 |
|
760 |
www) |
761 |
case ${catmin} in |
762 |
client) type=WebBrowser;; |
763 |
esac |
764 |
type="Network;${type}" |
765 |
;; |
766 |
|
767 |
*) |
768 |
type= |
769 |
;; |
770 |
esac |
771 |
fi |
772 |
if [ "${SLOT}" == "0" ] ; then |
773 |
local desktop_name="${PN}" |
774 |
else |
775 |
local desktop_name="${PN}-${SLOT}" |
776 |
fi |
777 |
local desktop="${T}/$(echo ${exec} | sed 's:[[:space:]/:]:_:g')-${desktop_name}.desktop" |
778 |
#local desktop=${T}/${exec%% *:-${desktop_name}}.desktop |
779 |
|
780 |
# Don't append another ";" when a valid category value is provided. |
781 |
type=${type%;}${type:+;} |
782 |
|
783 |
eshopts_push -s extglob |
784 |
if [[ -n ${icon} && ${icon} != /* ]] && [[ ${icon} == *.xpm || ${icon} == *.png || ${icon} == *.svg ]]; then |
785 |
ewarn "As described in the Icon Theme Specification, icon file extensions are not" |
786 |
ewarn "allowed in .desktop files if the value is not an absolute path." |
787 |
icon=${icon%.@(xpm|png|svg)} |
788 |
fi |
789 |
eshopts_pop |
790 |
|
791 |
cat <<-EOF > "${desktop}" |
792 |
[Desktop Entry] |
793 |
Name=${name} |
794 |
Type=Application |
795 |
Comment=${DESCRIPTION} |
796 |
Exec=${exec} |
797 |
TryExec=${exec%% *} |
798 |
Icon=${icon} |
799 |
Categories=${type} |
800 |
EOF |
801 |
|
802 |
if [[ ${fields:-=} != *=* ]] ; then |
803 |
# 5th arg used to be value to Path= |
804 |
ewarn "make_desktop_entry: update your 5th arg to read Path=${fields}" |
805 |
fields="Path=${fields}" |
806 |
fi |
807 |
[[ -n ${fields} ]] && printf '%b\n' "${fields}" >> "${desktop}" |
808 |
|
809 |
( |
810 |
# wrap the env here so that the 'insinto' call |
811 |
# doesn't corrupt the env of the caller |
812 |
insinto /usr/share/applications |
813 |
doins "${desktop}" |
814 |
) || die "installing desktop file failed" |
815 |
} |
816 |
|
817 |
# @FUNCTION: validate_desktop_entries |
818 |
# @USAGE: [directories] |
819 |
# @MAINTAINER: |
820 |
# Carsten Lohrke <carlo@gentoo.org> |
821 |
# @DESCRIPTION: |
822 |
# Validate desktop entries using desktop-file-utils |
823 |
validate_desktop_entries() { |
824 |
if [[ -x /usr/bin/desktop-file-validate ]] ; then |
825 |
einfo "Checking desktop entry validity" |
826 |
local directories="" |
827 |
for d in /usr/share/applications $@ ; do |
828 |
[[ -d ${D}${d} ]] && directories="${directories} ${D}${d}" |
829 |
done |
830 |
if [[ -n ${directories} ]] ; then |
831 |
for FILE in $(find ${directories} -name "*\.desktop" \ |
832 |
-not -path '*.hidden*' | sort -u 2>/dev/null) |
833 |
do |
834 |
local temp=$(desktop-file-validate ${FILE} | grep -v "warning:" | \ |
835 |
sed -e "s|error: ||" -e "s|${FILE}:|--|g" ) |
836 |
[[ -n $temp ]] && elog ${temp/--/${FILE/${D}/}:} |
837 |
done |
838 |
fi |
839 |
echo "" |
840 |
else |
841 |
einfo "Passing desktop entry validity check. Install dev-util/desktop-file-utils, if you want to help to improve Gentoo." |
842 |
fi |
843 |
} |
844 |
|
845 |
# @FUNCTION: make_session_desktop |
846 |
# @USAGE: <title> <command> [command args...] |
847 |
# @DESCRIPTION: |
848 |
# Make a GDM/KDM Session file. The title is the file to execute to start the |
849 |
# Window Manager. The command is the name of the Window Manager. |
850 |
# |
851 |
# You can set the name of the file via the ${wm} variable. |
852 |
make_session_desktop() { |
853 |
[[ -z $1 ]] && eerror "$0: You must specify the title" && return 1 |
854 |
[[ -z $2 ]] && eerror "$0: You must specify the command" && return 1 |
855 |
|
856 |
local title=$1 |
857 |
local command=$2 |
858 |
local desktop=${T}/${wm:-${PN}}.desktop |
859 |
shift 2 |
860 |
|
861 |
cat <<-EOF > "${desktop}" |
862 |
[Desktop Entry] |
863 |
Name=${title} |
864 |
Comment=This session logs you into ${title} |
865 |
Exec=${command} $* |
866 |
TryExec=${command} |
867 |
Type=XSession |
868 |
EOF |
869 |
|
870 |
( |
871 |
# wrap the env here so that the 'insinto' call |
872 |
# doesn't corrupt the env of the caller |
873 |
insinto /usr/share/xsessions |
874 |
doins "${desktop}" |
875 |
) |
876 |
} |
877 |
|
878 |
# @FUNCTION: domenu |
879 |
# @USAGE: <menus> |
880 |
# @DESCRIPTION: |
881 |
# Install the list of .desktop menu files into the appropriate directory |
882 |
# (/usr/share/applications). |
883 |
domenu() { |
884 |
( |
885 |
# wrap the env here so that the 'insinto' call |
886 |
# doesn't corrupt the env of the caller |
887 |
local i j ret=0 |
888 |
insinto /usr/share/applications |
889 |
for i in "$@" ; do |
890 |
if [[ -f ${i} ]] ; then |
891 |
doins "${i}" |
892 |
((ret+=$?)) |
893 |
elif [[ -d ${i} ]] ; then |
894 |
for j in "${i}"/*.desktop ; do |
895 |
doins "${j}" |
896 |
((ret+=$?)) |
897 |
done |
898 |
else |
899 |
((++ret)) |
900 |
fi |
901 |
done |
902 |
exit ${ret} |
903 |
) |
904 |
} |
905 |
|
906 |
# @FUNCTION: newmenu |
907 |
# @USAGE: <menu> <newname> |
908 |
# @DESCRIPTION: |
909 |
# Like all other new* functions, install the specified menu as newname. |
910 |
newmenu() { |
911 |
( |
912 |
# wrap the env here so that the 'insinto' call |
913 |
# doesn't corrupt the env of the caller |
914 |
insinto /usr/share/applications |
915 |
newins "$@" |
916 |
) |
917 |
} |
918 |
|
919 |
# @FUNCTION: doicon |
920 |
# @USAGE: <list of icons> |
921 |
# @DESCRIPTION: |
922 |
# Install the list of icons into the icon directory (/usr/share/pixmaps). |
923 |
# This is useful in conjunction with creating desktop/menu files. |
924 |
doicon() { |
925 |
( |
926 |
# wrap the env here so that the 'insinto' call |
927 |
# doesn't corrupt the env of the caller |
928 |
local i j ret |
929 |
insinto /usr/share/pixmaps |
930 |
for i in "$@" ; do |
931 |
if [[ -f ${i} ]] ; then |
932 |
doins "${i}" |
933 |
((ret+=$?)) |
934 |
elif [[ -d ${i} ]] ; then |
935 |
for j in "${i}"/*.png ; do |
936 |
doins "${j}" |
937 |
((ret+=$?)) |
938 |
done |
939 |
else |
940 |
((++ret)) |
941 |
fi |
942 |
done |
943 |
exit ${ret} |
944 |
) |
945 |
} |
946 |
|
947 |
# @FUNCTION: newicon |
948 |
# @USAGE: <icon> <newname> |
949 |
# @DESCRIPTION: |
950 |
# Like all other new* functions, install the specified icon as newname. |
951 |
newicon() { |
952 |
( |
953 |
# wrap the env here so that the 'insinto' call |
954 |
# doesn't corrupt the env of the caller |
955 |
insinto /usr/share/pixmaps |
956 |
newins "$@" |
957 |
) |
958 |
} |
959 |
|
960 |
# @FUNCTION: strip-linguas |
961 |
# @USAGE: [<allow LINGUAS>|<-i|-u> <directories of .po files>] |
962 |
# @DESCRIPTION: |
963 |
# Make sure that LINGUAS only contains languages that |
964 |
# a package can support. The first form allows you to |
965 |
# specify a list of LINGUAS. The -i builds a list of po |
966 |
# files found in all the directories and uses the |
967 |
# intersection of the lists. The -u builds a list of po |
968 |
# files found in all the directories and uses the union |
969 |
# of the lists. |
970 |
strip-linguas() { |
971 |
local ls newls nols |
972 |
if [[ $1 == "-i" ]] || [[ $1 == "-u" ]] ; then |
973 |
local op=$1; shift |
974 |
ls=$(find "$1" -name '*.po' -exec basename {} .po ';'); shift |
975 |
local d f |
976 |
for d in "$@" ; do |
977 |
if [[ ${op} == "-u" ]] ; then |
978 |
newls=${ls} |
979 |
else |
980 |
newls="" |
981 |
fi |
982 |
for f in $(find "$d" -name '*.po' -exec basename {} .po ';') ; do |
983 |
if [[ ${op} == "-i" ]] ; then |
984 |
has ${f} ${ls} && newls="${newls} ${f}" |
985 |
else |
986 |
has ${f} ${ls} || newls="${newls} ${f}" |
987 |
fi |
988 |
done |
989 |
ls=${newls} |
990 |
done |
991 |
else |
992 |
ls="$@" |
993 |
fi |
994 |
|
995 |
nols="" |
996 |
newls="" |
997 |
for f in ${LINGUAS} ; do |
998 |
if has ${f} ${ls} ; then |
999 |
newls="${newls} ${f}" |
1000 |
else |
1001 |
nols="${nols} ${f}" |
1002 |
fi |
1003 |
done |
1004 |
[[ -n ${nols} ]] \ |
1005 |
&& ewarn "Sorry, but ${PN} does not support the LINGUAS:" ${nols} |
1006 |
export LINGUAS=${newls:1} |
1007 |
} |
1008 |
|
1009 |
# @FUNCTION: preserve_old_lib |
1010 |
# @USAGE: <libs to preserve> [more libs] |
1011 |
# @DESCRIPTION: |
1012 |
# These functions are useful when a lib in your package changes ABI SONAME. |
1013 |
# An example might be from libogg.so.0 to libogg.so.1. Removing libogg.so.0 |
1014 |
# would break packages that link against it. Most people get around this |
1015 |
# by using the portage SLOT mechanism, but that is not always a relevant |
1016 |
# solution, so instead you can call this from pkg_preinst. See also the |
1017 |
# preserve_old_lib_notify function. |
1018 |
preserve_old_lib() { |
1019 |
if [[ ${EBUILD_PHASE} != "preinst" ]] ; then |
1020 |
eerror "preserve_old_lib() must be called from pkg_preinst() only" |
1021 |
die "Invalid preserve_old_lib() usage" |
1022 |
fi |
1023 |
[[ -z $1 ]] && die "Usage: preserve_old_lib <library to preserve> [more libraries to preserve]" |
1024 |
|
1025 |
# let portage worry about it |
1026 |
has preserve-libs ${FEATURES} && return 0 |
1027 |
|
1028 |
local lib dir |
1029 |
for lib in "$@" ; do |
1030 |
[[ -e ${ROOT}/${lib} ]] || continue |
1031 |
dir=${lib%/*} |
1032 |
dodir ${dir} || die "dodir ${dir} failed" |
1033 |
cp "${ROOT}"/${lib} "${D}"/${lib} || die "cp ${lib} failed" |
1034 |
touch "${D}"/${lib} |
1035 |
done |
1036 |
} |
1037 |
|
1038 |
# @FUNCTION: preserve_old_lib_notify |
1039 |
# @USAGE: <libs to notify> [more libs] |
1040 |
# @DESCRIPTION: |
1041 |
# Spit helpful messages about the libraries preserved by preserve_old_lib. |
1042 |
preserve_old_lib_notify() { |
1043 |
if [[ ${EBUILD_PHASE} != "postinst" ]] ; then |
1044 |
eerror "preserve_old_lib_notify() must be called from pkg_postinst() only" |
1045 |
die "Invalid preserve_old_lib_notify() usage" |
1046 |
fi |
1047 |
|
1048 |
# let portage worry about it |
1049 |
has preserve-libs ${FEATURES} && return 0 |
1050 |
|
1051 |
local lib notice=0 |
1052 |
for lib in "$@" ; do |
1053 |
[[ -e ${ROOT}/${lib} ]] || continue |
1054 |
if [[ ${notice} -eq 0 ]] ; then |
1055 |
notice=1 |
1056 |
ewarn "Old versions of installed libraries were detected on your system." |
1057 |
ewarn "In order to avoid breaking packages that depend on these old libs," |
1058 |
ewarn "the libraries are not being removed. You need to run revdep-rebuild" |
1059 |
ewarn "in order to remove these old dependencies. If you do not have this" |
1060 |
ewarn "helper program, simply emerge the 'gentoolkit' package." |
1061 |
ewarn |
1062 |
fi |
1063 |
# temp hack for #348634 #357225 |
1064 |
[[ ${PN} == "mpfr" ]] && lib=${lib##*/} |
1065 |
ewarn " # revdep-rebuild --library '${lib}'" |
1066 |
done |
1067 |
if [[ ${notice} -eq 1 ]] ; then |
1068 |
ewarn |
1069 |
ewarn "Once you've finished running revdep-rebuild, it should be safe to" |
1070 |
ewarn "delete the old libraries. Here is a copy & paste for the lazy:" |
1071 |
for lib in "$@" ; do |
1072 |
ewarn " # rm '${lib}'" |
1073 |
done |
1074 |
fi |
1075 |
} |
1076 |
|
1077 |
# @FUNCTION: built_with_use |
1078 |
# @USAGE: [--hidden] [--missing <action>] [-a|-o] <DEPEND ATOM> <List of USE flags> |
1079 |
# @DESCRIPTION: |
1080 |
# |
1081 |
# Deprecated: Use EAPI 2 use deps in DEPEND|RDEPEND and with has_version calls. |
1082 |
# |
1083 |
# A temporary hack until portage properly supports DEPENDing on USE |
1084 |
# flags being enabled in packages. This will check to see if the specified |
1085 |
# DEPEND atom was built with the specified list of USE flags. The |
1086 |
# --missing option controls the behavior if called on a package that does |
1087 |
# not actually support the defined USE flags (aka listed in IUSE). |
1088 |
# The default is to abort (call die). The -a and -o flags control |
1089 |
# the requirements of the USE flags. They correspond to "and" and "or" |
1090 |
# logic. So the -a flag means all listed USE flags must be enabled |
1091 |
# while the -o flag means at least one of the listed IUSE flags must be |
1092 |
# enabled. The --hidden option is really for internal use only as it |
1093 |
# means the USE flag we're checking is hidden expanded, so it won't be found |
1094 |
# in IUSE like normal USE flags. |
1095 |
# |
1096 |
# Remember that this function isn't terribly intelligent so order of optional |
1097 |
# flags matter. |
1098 |
built_with_use() { |
1099 |
local hidden="no" |
1100 |
if [[ $1 == "--hidden" ]] ; then |
1101 |
hidden="yes" |
1102 |
shift |
1103 |
fi |
1104 |
|
1105 |
local missing_action="die" |
1106 |
if [[ $1 == "--missing" ]] ; then |
1107 |
missing_action=$2 |
1108 |
shift ; shift |
1109 |
case ${missing_action} in |
1110 |
true|false|die) ;; |
1111 |
*) die "unknown action '${missing_action}'";; |
1112 |
esac |
1113 |
fi |
1114 |
|
1115 |
local opt=$1 |
1116 |
[[ ${opt:0:1} = "-" ]] && shift || opt="-a" |
1117 |
|
1118 |
local PKG=$(best_version $1) |
1119 |
[[ -z ${PKG} ]] && die "Unable to resolve $1 to an installed package" |
1120 |
shift |
1121 |
|
1122 |
local USEFILE=${ROOT}/var/db/pkg/${PKG}/USE |
1123 |
local IUSEFILE=${ROOT}/var/db/pkg/${PKG}/IUSE |
1124 |
|
1125 |
# if the IUSE file doesn't exist, the read will error out, we need to handle |
1126 |
# this gracefully |
1127 |
if [[ ! -e ${USEFILE} ]] || [[ ! -e ${IUSEFILE} && ${hidden} == "no" ]] ; then |
1128 |
case ${missing_action} in |
1129 |
true) return 0;; |
1130 |
false) return 1;; |
1131 |
die) die "Unable to determine what USE flags $PKG was built with";; |
1132 |
esac |
1133 |
fi |
1134 |
|
1135 |
if [[ ${hidden} == "no" ]] ; then |
1136 |
local IUSE_BUILT=( $(<"${IUSEFILE}") ) |
1137 |
# Don't check USE_EXPAND #147237 |
1138 |
local expand |
1139 |
for expand in $(echo ${USE_EXPAND} | tr '[:upper:]' '[:lower:]') ; do |
1140 |
if [[ $1 == ${expand}_* ]] ; then |
1141 |
expand="" |
1142 |
break |
1143 |
fi |
1144 |
done |
1145 |
if [[ -n ${expand} ]] ; then |
1146 |
if ! has $1 ${IUSE_BUILT[@]#[-+]} ; then |
1147 |
case ${missing_action} in |
1148 |
true) return 0;; |
1149 |
false) return 1;; |
1150 |
die) die "$PKG does not actually support the $1 USE flag!";; |
1151 |
esac |
1152 |
fi |
1153 |
fi |
1154 |
fi |
1155 |
|
1156 |
local USE_BUILT=$(<${USEFILE}) |
1157 |
while [[ $# -gt 0 ]] ; do |
1158 |
if [[ ${opt} = "-o" ]] ; then |
1159 |
has $1 ${USE_BUILT} && return 0 |
1160 |
else |
1161 |
has $1 ${USE_BUILT} || return 1 |
1162 |
fi |
1163 |
shift |
1164 |
done |
1165 |
[[ ${opt} = "-a" ]] |
1166 |
} |
1167 |
|
1168 |
# @FUNCTION: epunt_cxx |
1169 |
# @USAGE: [dir to scan] |
1170 |
# @DESCRIPTION: |
1171 |
# Many configure scripts wrongly bail when a C++ compiler could not be |
1172 |
# detected. If dir is not specified, then it defaults to ${S}. |
1173 |
# |
1174 |
# http://bugs.gentoo.org/73450 |
1175 |
epunt_cxx() { |
1176 |
local dir=$1 |
1177 |
[[ -z ${dir} ]] && dir=${S} |
1178 |
ebegin "Removing useless C++ checks" |
1179 |
local f |
1180 |
find "${dir}" -name configure | while read f ; do |
1181 |
patch --no-backup-if-mismatch -p0 "${f}" "${PORTDIR}/eclass/ELT-patches/nocxx/nocxx.patch" > /dev/null |
1182 |
done |
1183 |
eend 0 |
1184 |
} |
1185 |
|
1186 |
# @FUNCTION: make_wrapper |
1187 |
# @USAGE: <wrapper> <target> [chdir] [libpaths] [installpath] |
1188 |
# @DESCRIPTION: |
1189 |
# Create a shell wrapper script named wrapper in installpath |
1190 |
# (defaults to the bindir) to execute target (default of wrapper) by |
1191 |
# first optionally setting LD_LIBRARY_PATH to the colon-delimited |
1192 |
# libpaths followed by optionally changing directory to chdir. |
1193 |
make_wrapper() { |
1194 |
local wrapper=$1 bin=$2 chdir=$3 libdir=$4 path=$5 |
1195 |
local tmpwrapper=$(emktemp) |
1196 |
# We don't want to quote ${bin} so that people can pass complex |
1197 |
# things as $bin ... "./someprog --args" |
1198 |
cat << EOF > "${tmpwrapper}" |
1199 |
#!/bin/sh |
1200 |
cd "${chdir:-.}" |
1201 |
if [ -n "${libdir}" ] ; then |
1202 |
if [ "\${LD_LIBRARY_PATH+set}" = "set" ] ; then |
1203 |
export LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}:${libdir}" |
1204 |
else |
1205 |
export LD_LIBRARY_PATH="${libdir}" |
1206 |
fi |
1207 |
fi |
1208 |
exec ${bin} "\$@" |
1209 |
EOF |
1210 |
chmod go+rx "${tmpwrapper}" |
1211 |
if [[ -n ${path} ]] ; then |
1212 |
( |
1213 |
exeinto "${path}" |
1214 |
newexe "${tmpwrapper}" "${wrapper}" |
1215 |
) || die |
1216 |
else |
1217 |
newbin "${tmpwrapper}" "${wrapper}" || die |
1218 |
fi |
1219 |
} |
1220 |
|
1221 |
# @FUNCTION: path_exists |
1222 |
# @USAGE: [-a|-o] <paths> |
1223 |
# @DESCRIPTION: |
1224 |
# Check if the specified paths exist. Works for all types of paths |
1225 |
# (files/dirs/etc...). The -a and -o flags control the requirements |
1226 |
# of the paths. They correspond to "and" and "or" logic. So the -a |
1227 |
# flag means all the paths must exist while the -o flag means at least |
1228 |
# one of the paths must exist. The default behavior is "and". If no |
1229 |
# paths are specified, then the return value is "false". |
1230 |
path_exists() { |
1231 |
local opt=$1 |
1232 |
[[ ${opt} == -[ao] ]] && shift || opt="-a" |
1233 |
|
1234 |
# no paths -> return false |
1235 |
# same behavior as: [[ -e "" ]] |
1236 |
[[ $# -eq 0 ]] && return 1 |
1237 |
|
1238 |
local p r=0 |
1239 |
for p in "$@" ; do |
1240 |
[[ -e ${p} ]] |
1241 |
: $(( r += $? )) |
1242 |
done |
1243 |
|
1244 |
case ${opt} in |
1245 |
-a) return $(( r != 0 )) ;; |
1246 |
-o) return $(( r == $# )) ;; |
1247 |
esac |
1248 |
} |
1249 |
|
1250 |
# @FUNCTION: in_iuse |
1251 |
# @USAGE: <flag> |
1252 |
# @DESCRIPTION: |
1253 |
# Determines whether the given flag is in IUSE. Strips IUSE default prefixes |
1254 |
# as necessary. |
1255 |
# |
1256 |
# Note that this function should not be used in the global scope. |
1257 |
in_iuse() { |
1258 |
debug-print-function ${FUNCNAME} "${@}" |
1259 |
[[ ${#} -eq 1 ]] || die "Invalid args to ${FUNCNAME}()" |
1260 |
|
1261 |
local flag=${1} |
1262 |
local liuse=( ${IUSE} ) |
1263 |
|
1264 |
has "${flag}" "${liuse[@]#[+-]}" |
1265 |
} |
1266 |
|
1267 |
# @FUNCTION: use_if_iuse |
1268 |
# @USAGE: <flag> |
1269 |
# @DESCRIPTION: |
1270 |
# Return true if the given flag is in USE and IUSE. |
1271 |
# |
1272 |
# Note that this function should not be used in the global scope. |
1273 |
use_if_iuse() { |
1274 |
in_iuse $1 || return 1 |
1275 |
use $1 |
1276 |
} |
1277 |
|
1278 |
# @FUNCTION: usex |
1279 |
# @USAGE: <USE flag> [true output] [false output] [true suffix] [false suffix] |
1280 |
# @DESCRIPTION: |
1281 |
# If USE flag is set, echo [true output][true suffix] (defaults to "yes"), |
1282 |
# otherwise echo [false output][false suffix] (defaults to "no"). |
1283 |
usex() { use "$1" && echo "${2-yes}$4" || echo "${3-no}$5" ; } #382963 |
1284 |
|
1285 |
check_license() { die "you no longer need this as portage supports ACCEPT_LICENSE itself"; } |
1286 |
|
1287 |
fi |