net-irc/limnoria: use HTTPS for GitHub and HOMEPAGE
[gentoo.git] / eclass / eutils.eclass
1 # Copyright 1999-2017 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: eutils.eclass
5 # @MAINTAINER:
6 # base-system@gentoo.org
7 # @BLURB: many extra (but common) functions that are used in ebuilds
8 # @DESCRIPTION:
9 # The eutils eclass contains a suite of functions that complement
10 # the ones that ebuild.sh already contain.  The idea is that the functions
11 # are not required in all ebuilds but enough utilize them to have a common
12 # home rather than having multiple ebuilds implementing the same thing.
13 #
14 # Due to the nature of this eclass, some functions may have maintainers
15 # different from the overall eclass!
16
17 if [[ -z ${_EUTILS_ECLASS} ]]; then
18 _EUTILS_ECLASS=1
19
20 # implicitly inherited (now split) eclasses
21 case ${EAPI:-0} in
22 0|1|2|3|4|5|6)
23         inherit epatch estack ltprune multilib toolchain-funcs
24         ;;
25 esac
26
27 # @FUNCTION: eqawarn
28 # @USAGE: [message]
29 # @DESCRIPTION:
30 # Proxy to ewarn for package managers that don't provide eqawarn and use the PM
31 # implementation if available. Reuses PORTAGE_ELOG_CLASSES as set by the dev
32 # profile.
33 if ! declare -F eqawarn >/dev/null ; then
34         eqawarn() {
35                 has qa ${PORTAGE_ELOG_CLASSES} && ewarn "$@"
36                 :
37         }
38 fi
39
40 # @FUNCTION: ecvs_clean
41 # @USAGE: [list of dirs]
42 # @DESCRIPTION:
43 # Remove CVS directories recursiveley.  Useful when a source tarball contains
44 # internal CVS directories.  Defaults to $PWD.
45 ecvs_clean() {
46         [[ $# -eq 0 ]] && set -- .
47         find "$@" -type d -name 'CVS' -prune -print0 | xargs -0 rm -rf
48         find "$@" -type f -name '.cvs*' -print0 | xargs -0 rm -rf
49 }
50
51 # @FUNCTION: esvn_clean
52 # @USAGE: [list of dirs]
53 # @DESCRIPTION:
54 # Remove .svn directories recursiveley.  Useful when a source tarball contains
55 # internal Subversion directories.  Defaults to $PWD.
56 esvn_clean() {
57         [[ $# -eq 0 ]] && set -- .
58         find "$@" -type d -name '.svn' -prune -print0 | xargs -0 rm -rf
59 }
60
61 # @FUNCTION: egit_clean
62 # @USAGE: [list of dirs]
63 # @DESCRIPTION:
64 # Remove .git* directories/files recursiveley.  Useful when a source tarball
65 # contains internal Git directories.  Defaults to $PWD.
66 egit_clean() {
67         [[ $# -eq 0 ]] && set -- .
68         find "$@" -type d -name '.git*' -prune -print0 | xargs -0 rm -rf
69 }
70
71 # @FUNCTION: emktemp
72 # @USAGE: [temp dir]
73 # @DESCRIPTION:
74 # Cheap replacement for when debianutils (and thus mktemp)
75 # does not exist on the users system.
76 emktemp() {
77         local exe="touch"
78         [[ $1 == -d ]] && exe="mkdir" && shift
79         local topdir=$1
80
81         if [[ -z ${topdir} ]] ; then
82                 [[ -z ${T} ]] \
83                         && topdir="/tmp" \
84                         || topdir=${T}
85         fi
86
87         if ! type -P mktemp > /dev/null ; then
88                 # system lacks `mktemp` so we have to fake it
89                 local tmp=/
90                 while [[ -e ${tmp} ]] ; do
91                         tmp=${topdir}/tmp.${RANDOM}.${RANDOM}.${RANDOM}
92                 done
93                 ${exe} "${tmp}" || ${exe} -p "${tmp}"
94                 echo "${tmp}"
95         else
96                 # the args here will give slightly wierd names on BSD,
97                 # but should produce a usable file on all userlands
98                 if [[ ${exe} == "touch" ]] ; then
99                         TMPDIR="${topdir}" mktemp -t tmp.XXXXXXXXXX
100                 else
101                         TMPDIR="${topdir}" mktemp -dt tmp.XXXXXXXXXX
102                 fi
103         fi
104 }
105
106 # @FUNCTION: edos2unix
107 # @USAGE: <file> [more files ...]
108 # @DESCRIPTION:
109 # A handy replacement for dos2unix, recode, fixdos, etc...  This allows you
110 # to remove all of these text utilities from DEPEND variables because this
111 # is a script based solution.  Just give it a list of files to convert and
112 # they will all be changed from the DOS CRLF format to the UNIX LF format.
113 edos2unix() {
114         [[ $# -eq 0 ]] && return 0
115         sed -i 's/\r$//' -- "$@" || die
116 }
117
118 # @FUNCTION: make_desktop_entry
119 # @USAGE: make_desktop_entry(<command>, [name], [icon], [type], [fields])
120 # @DESCRIPTION:
121 # Make a .desktop file.
122 #
123 # @CODE
124 # binary:   what command does the app run with ?
125 # name:     the name that will show up in the menu
126 # icon:     the icon to use in the menu entry
127 #           this can be relative (to /usr/share/pixmaps) or
128 #           a full path to an icon
129 # type:     what kind of application is this?
130 #           for categories:
131 #           https://specifications.freedesktop.org/menu-spec/latest/apa.html
132 #           if unset, function tries to guess from package's category
133 # fields:       extra fields to append to the desktop file; a printf string
134 # @CODE
135 make_desktop_entry() {
136         [[ -z $1 ]] && die "make_desktop_entry: You must specify the executable"
137
138         local exec=${1}
139         local name=${2:-${PN}}
140         local icon=${3:-${PN}}
141         local type=${4}
142         local fields=${5}
143
144         if [[ -z ${type} ]] ; then
145                 local catmaj=${CATEGORY%%-*}
146                 local catmin=${CATEGORY##*-}
147                 case ${catmaj} in
148                         app)
149                                 case ${catmin} in
150                                         accessibility) type="Utility;Accessibility";;
151                                         admin)         type=System;;
152                                         antivirus)     type=System;;
153                                         arch)          type="Utility;Archiving";;
154                                         backup)        type="Utility;Archiving";;
155                                         cdr)           type="AudioVideo;DiscBurning";;
156                                         dicts)         type="Office;Dictionary";;
157                                         doc)           type=Documentation;;
158                                         editors)       type="Utility;TextEditor";;
159                                         emacs)         type="Development;TextEditor";;
160                                         emulation)     type="System;Emulator";;
161                                         laptop)        type="Settings;HardwareSettings";;
162                                         office)        type=Office;;
163                                         pda)           type="Office;PDA";;
164                                         vim)           type="Development;TextEditor";;
165                                         xemacs)        type="Development;TextEditor";;
166                                 esac
167                                 ;;
168
169                         dev)
170                                 type="Development"
171                                 ;;
172
173                         games)
174                                 case ${catmin} in
175                                         action|fps) type=ActionGame;;
176                                         arcade)     type=ArcadeGame;;
177                                         board)      type=BoardGame;;
178                                         emulation)  type=Emulator;;
179                                         kids)       type=KidsGame;;
180                                         puzzle)     type=LogicGame;;
181                                         roguelike)  type=RolePlaying;;
182                                         rpg)        type=RolePlaying;;
183                                         simulation) type=Simulation;;
184                                         sports)     type=SportsGame;;
185                                         strategy)   type=StrategyGame;;
186                                 esac
187                                 type="Game;${type}"
188                                 ;;
189
190                         gnome)
191                                 type="Gnome;GTK"
192                                 ;;
193
194                         kde)
195                                 type="KDE;Qt"
196                                 ;;
197
198                         mail)
199                                 type="Network;Email"
200                                 ;;
201
202                         media)
203                                 case ${catmin} in
204                                         gfx)
205                                                 type=Graphics
206                                                 ;;
207                                         *)
208                                                 case ${catmin} in
209                                                         radio) type=Tuner;;
210                                                         sound) type=Audio;;
211                                                         tv)    type=TV;;
212                                                         video) type=Video;;
213                                                 esac
214                                                 type="AudioVideo;${type}"
215                                                 ;;
216                                 esac
217                                 ;;
218
219                         net)
220                                 case ${catmin} in
221                                         dialup) type=Dialup;;
222                                         ftp)    type=FileTransfer;;
223                                         im)     type=InstantMessaging;;
224                                         irc)    type=IRCClient;;
225                                         mail)   type=Email;;
226                                         news)   type=News;;
227                                         nntp)   type=News;;
228                                         p2p)    type=FileTransfer;;
229                                         voip)   type=Telephony;;
230                                 esac
231                                 type="Network;${type}"
232                                 ;;
233
234                         sci)
235                                 case ${catmin} in
236                                         astro*)  type=Astronomy;;
237                                         bio*)    type=Biology;;
238                                         calc*)   type=Calculator;;
239                                         chem*)   type=Chemistry;;
240                                         elec*)   type=Electronics;;
241                                         geo*)    type=Geology;;
242                                         math*)   type=Math;;
243                                         physics) type=Physics;;
244                                         visual*) type=DataVisualization;;
245                                 esac
246                                 type="Education;Science;${type}"
247                                 ;;
248
249                         sys)
250                                 type="System"
251                                 ;;
252
253                         www)
254                                 case ${catmin} in
255                                         client) type=WebBrowser;;
256                                 esac
257                                 type="Network;${type}"
258                                 ;;
259
260                         *)
261                                 type=
262                                 ;;
263                 esac
264         fi
265         local slot=${SLOT%/*}
266         if [[ ${slot} == "0" ]] ; then
267                 local desktop_name="${PN}"
268         else
269                 local desktop_name="${PN}-${slot}"
270         fi
271         local desktop="${T}/$(echo ${exec} | sed 's:[[:space:]/:]:_:g')-${desktop_name}.desktop"
272         #local desktop=${T}/${exec%% *:-${desktop_name}}.desktop
273
274         # Don't append another ";" when a valid category value is provided.
275         type=${type%;}${type:+;}
276
277         if [[ -n ${icon} && ${icon} != /* ]] && [[ ${icon} == *.xpm || ${icon} == *.png || ${icon} == *.svg ]]; then
278                 ewarn "As described in the Icon Theme Specification, icon file extensions are not"
279                 ewarn "allowed in .desktop files if the value is not an absolute path."
280                 icon=${icon%.*}
281         fi
282
283         cat <<-EOF > "${desktop}"
284         [Desktop Entry]
285         Name=${name}
286         Type=Application
287         Comment=${DESCRIPTION}
288         Exec=${exec}
289         TryExec=${exec%% *}
290         Icon=${icon}
291         Categories=${type}
292         EOF
293
294         if [[ ${fields:-=} != *=* ]] ; then
295                 # 5th arg used to be value to Path=
296                 ewarn "make_desktop_entry: update your 5th arg to read Path=${fields}"
297                 fields="Path=${fields}"
298         fi
299         [[ -n ${fields} ]] && printf '%b\n' "${fields}" >> "${desktop}"
300
301         (
302                 # wrap the env here so that the 'insinto' call
303                 # doesn't corrupt the env of the caller
304                 insinto /usr/share/applications
305                 doins "${desktop}"
306         ) || die "installing desktop file failed"
307 }
308
309 # @FUNCTION: _eutils_eprefix_init
310 # @INTERNAL
311 # @DESCRIPTION:
312 # Initialized prefix variables for EAPI<3.
313 _eutils_eprefix_init() {
314         has "${EAPI:-0}" 0 1 2 && : ${ED:=${D}} ${EPREFIX:=} ${EROOT:=${ROOT}}
315 }
316
317 # @FUNCTION: validate_desktop_entries
318 # @USAGE: [directories]
319 # @DESCRIPTION:
320 # Validate desktop entries using desktop-file-utils
321 validate_desktop_entries() {
322         eqawarn "validate_desktop_entries is deprecated and should be not be used."
323         eqawarn ".desktop file validation is done implicitly by Portage now."
324
325         _eutils_eprefix_init
326         if [[ -x "${EPREFIX}"/usr/bin/desktop-file-validate ]] ; then
327                 einfo "Checking desktop entry validity"
328                 local directories=""
329                 for d in /usr/share/applications $@ ; do
330                         [[ -d ${ED}${d} ]] && directories="${directories} ${ED}${d}"
331                 done
332                 if [[ -n ${directories} ]] ; then
333                         for FILE in $(find ${directories} -name "*\.desktop" \
334                                                         -not -path '*.hidden*' | sort -u 2>/dev/null)
335                         do
336                                 local temp=$(desktop-file-validate ${FILE} | grep -v "warning:" | \
337                                                                 sed -e "s|error: ||" -e "s|${FILE}:|--|g" )
338                                 [[ -n $temp ]] && elog ${temp/--/${FILE/${ED}/}:}
339                         done
340                 fi
341                 echo ""
342         else
343                 einfo "Passing desktop entry validity check. Install dev-util/desktop-file-utils, if you want to help to improve Gentoo."
344         fi
345 }
346
347 # @FUNCTION: make_session_desktop
348 # @USAGE: <title> <command> [command args...]
349 # @DESCRIPTION:
350 # Make a GDM/KDM Session file.  The title is the file to execute to start the
351 # Window Manager.  The command is the name of the Window Manager.
352 #
353 # You can set the name of the file via the ${wm} variable.
354 make_session_desktop() {
355         [[ -z $1 ]] && eerror "$0: You must specify the title" && return 1
356         [[ -z $2 ]] && eerror "$0: You must specify the command" && return 1
357
358         local title=$1
359         local command=$2
360         local desktop=${T}/${wm:-${PN}}.desktop
361         shift 2
362
363         cat <<-EOF > "${desktop}"
364         [Desktop Entry]
365         Name=${title}
366         Comment=This session logs you into ${title}
367         Exec=${command} $*
368         TryExec=${command}
369         Type=XSession
370         EOF
371
372         (
373         # wrap the env here so that the 'insinto' call
374         # doesn't corrupt the env of the caller
375         insinto /usr/share/xsessions
376         doins "${desktop}"
377         )
378 }
379
380 # @FUNCTION: domenu
381 # @USAGE: <menus>
382 # @DESCRIPTION:
383 # Install the list of .desktop menu files into the appropriate directory
384 # (/usr/share/applications).
385 domenu() {
386         (
387         # wrap the env here so that the 'insinto' call
388         # doesn't corrupt the env of the caller
389         local i j ret=0
390         insinto /usr/share/applications
391         for i in "$@" ; do
392                 if [[ -f ${i} ]] ; then
393                         doins "${i}"
394                         ((ret+=$?))
395                 elif [[ -d ${i} ]] ; then
396                         for j in "${i}"/*.desktop ; do
397                                 doins "${j}"
398                                 ((ret+=$?))
399                         done
400                 else
401                         ((++ret))
402                 fi
403         done
404         exit ${ret}
405         )
406 }
407
408 # @FUNCTION: newmenu
409 # @USAGE: <menu> <newname>
410 # @DESCRIPTION:
411 # Like all other new* functions, install the specified menu as newname.
412 newmenu() {
413         (
414         # wrap the env here so that the 'insinto' call
415         # doesn't corrupt the env of the caller
416         insinto /usr/share/applications
417         newins "$@"
418         )
419 }
420
421 # @FUNCTION: _iconins
422 # @INTERNAL
423 # @DESCRIPTION:
424 # function for use in doicon and newicon
425 _iconins() {
426         (
427         # wrap the env here so that the 'insinto' call
428         # doesn't corrupt the env of the caller
429         local funcname=$1; shift
430         local size dir
431         local context=apps
432         local theme=hicolor
433
434         while [[ $# -gt 0 ]] ; do
435                 case $1 in
436                 -s|--size)
437                         if [[ ${2%%x*}x${2%%x*} == "$2" ]] ; then
438                                 size=${2%%x*}
439                         else
440                                 size=${2}
441                         fi
442                         case ${size} in
443                         16|22|24|32|36|48|64|72|96|128|192|256|512)
444                                 size=${size}x${size};;
445                         scalable)
446                                 ;;
447                         *)
448                                 eerror "${size} is an unsupported icon size!"
449                                 exit 1;;
450                         esac
451                         shift 2;;
452                 -t|--theme)
453                         theme=${2}
454                         shift 2;;
455                 -c|--context)
456                         context=${2}
457                         shift 2;;
458                 *)
459                         if [[ -z ${size} ]] ; then
460                                 insinto /usr/share/pixmaps
461                         else
462                                 insinto /usr/share/icons/${theme}/${size}/${context}
463                         fi
464
465                         if [[ ${funcname} == doicon ]] ; then
466                                 if [[ -f $1 ]] ; then
467                                         doins "${1}"
468                                 elif [[ -d $1 ]] ; then
469                                         shopt -s nullglob
470                                         doins "${1}"/*.{png,svg}
471                                         shopt -u nullglob
472                                 else
473                                         eerror "${1} is not a valid file/directory!"
474                                         exit 1
475                                 fi
476                         else
477                                 break
478                         fi
479                         shift 1;;
480                 esac
481         done
482         if [[ ${funcname} == newicon ]] ; then
483                 newins "$@"
484         fi
485         ) || die
486 }
487
488 # @FUNCTION: doicon
489 # @USAGE: [options] <icons>
490 # @DESCRIPTION:
491 # Install icon into the icon directory /usr/share/icons or into
492 # /usr/share/pixmaps if "--size" is not set.
493 # This is useful in conjunction with creating desktop/menu files.
494 #
495 # @CODE
496 #  options:
497 #  -s, --size
498 #    !!! must specify to install into /usr/share/icons/... !!!
499 #    size of the icon, like 48 or 48x48
500 #    supported icon sizes are:
501 #    16 22 24 32 36 48 64 72 96 128 192 256 512 scalable
502 #  -c, --context
503 #    defaults to "apps"
504 #  -t, --theme
505 #    defaults to "hicolor"
506 #
507 # icons: list of icons
508 #
509 # example 1: doicon foobar.png fuqbar.svg suckbar.png
510 # results in: insinto /usr/share/pixmaps
511 #             doins foobar.png fuqbar.svg suckbar.png
512 #
513 # example 2: doicon -s 48 foobar.png fuqbar.png blobbar.png
514 # results in: insinto /usr/share/icons/hicolor/48x48/apps
515 #             doins foobar.png fuqbar.png blobbar.png
516 # @CODE
517 doicon() {
518         _iconins ${FUNCNAME} "$@"
519 }
520
521 # @FUNCTION: newicon
522 # @USAGE: [options] <icon> <newname>
523 # @DESCRIPTION:
524 # Like doicon, install the specified icon as newname.
525 #
526 # @CODE
527 # example 1: newicon foobar.png NEWNAME.png
528 # results in: insinto /usr/share/pixmaps
529 #             newins foobar.png NEWNAME.png
530 #
531 # example 2: newicon -s 48 foobar.png NEWNAME.png
532 # results in: insinto /usr/share/icons/hicolor/48x48/apps
533 #             newins foobar.png NEWNAME.png
534 # @CODE
535 newicon() {
536         _iconins ${FUNCNAME} "$@"
537 }
538
539 # @FUNCTION: strip-linguas
540 # @USAGE: [<allow LINGUAS>|<-i|-u> <directories of .po files>]
541 # @DESCRIPTION:
542 # Make sure that LINGUAS only contains languages that
543 # a package can support.  The first form allows you to
544 # specify a list of LINGUAS.  The -i builds a list of po
545 # files found in all the directories and uses the
546 # intersection of the lists.  The -u builds a list of po
547 # files found in all the directories and uses the union
548 # of the lists.
549 strip-linguas() {
550         local ls newls nols
551         if [[ $1 == "-i" ]] || [[ $1 == "-u" ]] ; then
552                 local op=$1; shift
553                 ls=$(find "$1" -name '*.po' -exec basename {} .po ';'); shift
554                 local d f
555                 for d in "$@" ; do
556                         if [[ ${op} == "-u" ]] ; then
557                                 newls=${ls}
558                         else
559                                 newls=""
560                         fi
561                         for f in $(find "$d" -name '*.po' -exec basename {} .po ';') ; do
562                                 if [[ ${op} == "-i" ]] ; then
563                                         has ${f} ${ls} && newls="${newls} ${f}"
564                                 else
565                                         has ${f} ${ls} || newls="${newls} ${f}"
566                                 fi
567                         done
568                         ls=${newls}
569                 done
570         else
571                 ls="$@"
572         fi
573
574         nols=""
575         newls=""
576         for f in ${LINGUAS} ; do
577                 if has ${f} ${ls} ; then
578                         newls="${newls} ${f}"
579                 else
580                         nols="${nols} ${f}"
581                 fi
582         done
583         [[ -n ${nols} ]] \
584                 && einfo "Sorry, but ${PN} does not support the LINGUAS:" ${nols}
585         export LINGUAS=${newls:1}
586 }
587
588 # @FUNCTION: preserve_old_lib
589 # @USAGE: <libs to preserve> [more libs]
590 # @DESCRIPTION:
591 # These functions are useful when a lib in your package changes ABI SONAME.
592 # An example might be from libogg.so.0 to libogg.so.1.  Removing libogg.so.0
593 # would break packages that link against it.  Most people get around this
594 # by using the portage SLOT mechanism, but that is not always a relevant
595 # solution, so instead you can call this from pkg_preinst.  See also the
596 # preserve_old_lib_notify function.
597 preserve_old_lib() {
598         _eutils_eprefix_init
599         if [[ ${EBUILD_PHASE} != "preinst" ]] ; then
600                 eerror "preserve_old_lib() must be called from pkg_preinst() only"
601                 die "Invalid preserve_old_lib() usage"
602         fi
603         [[ -z $1 ]] && die "Usage: preserve_old_lib <library to preserve> [more libraries to preserve]"
604
605         # let portage worry about it
606         has preserve-libs ${FEATURES} && return 0
607
608         local lib dir
609         for lib in "$@" ; do
610                 [[ -e ${EROOT}/${lib} ]] || continue
611                 dir=${lib%/*}
612                 dodir ${dir} || die "dodir ${dir} failed"
613                 cp "${EROOT}"/${lib} "${ED}"/${lib} || die "cp ${lib} failed"
614                 touch "${ED}"/${lib}
615         done
616 }
617
618 # @FUNCTION: preserve_old_lib_notify
619 # @USAGE: <libs to notify> [more libs]
620 # @DESCRIPTION:
621 # Spit helpful messages about the libraries preserved by preserve_old_lib.
622 preserve_old_lib_notify() {
623         if [[ ${EBUILD_PHASE} != "postinst" ]] ; then
624                 eerror "preserve_old_lib_notify() must be called from pkg_postinst() only"
625                 die "Invalid preserve_old_lib_notify() usage"
626         fi
627
628         # let portage worry about it
629         has preserve-libs ${FEATURES} && return 0
630
631         _eutils_eprefix_init
632
633         local lib notice=0
634         for lib in "$@" ; do
635                 [[ -e ${EROOT}/${lib} ]] || continue
636                 if [[ ${notice} -eq 0 ]] ; then
637                         notice=1
638                         ewarn "Old versions of installed libraries were detected on your system."
639                         ewarn "In order to avoid breaking packages that depend on these old libs,"
640                         ewarn "the libraries are not being removed.  You need to run revdep-rebuild"
641                         ewarn "in order to remove these old dependencies.  If you do not have this"
642                         ewarn "helper program, simply emerge the 'gentoolkit' package."
643                         ewarn
644                 fi
645                 ewarn "  # revdep-rebuild --library '${lib}' && rm '${lib}'"
646         done
647 }
648
649 # @FUNCTION: built_with_use
650 # @USAGE: [--hidden] [--missing <action>] [-a|-o] <DEPEND ATOM> <List of USE flags>
651 # @DESCRIPTION:
652 #
653 # Deprecated: Use EAPI 2 use deps in DEPEND|RDEPEND and with has_version calls.
654 #
655 # A temporary hack until portage properly supports DEPENDing on USE
656 # flags being enabled in packages.  This will check to see if the specified
657 # DEPEND atom was built with the specified list of USE flags.  The
658 # --missing option controls the behavior if called on a package that does
659 # not actually support the defined USE flags (aka listed in IUSE).
660 # The default is to abort (call die).  The -a and -o flags control
661 # the requirements of the USE flags.  They correspond to "and" and "or"
662 # logic.  So the -a flag means all listed USE flags must be enabled
663 # while the -o flag means at least one of the listed IUSE flags must be
664 # enabled.  The --hidden option is really for internal use only as it
665 # means the USE flag we're checking is hidden expanded, so it won't be found
666 # in IUSE like normal USE flags.
667 #
668 # Remember that this function isn't terribly intelligent so order of optional
669 # flags matter.
670 built_with_use() {
671         _eutils_eprefix_init
672         local hidden="no"
673         if [[ $1 == "--hidden" ]] ; then
674                 hidden="yes"
675                 shift
676         fi
677
678         local missing_action="die"
679         if [[ $1 == "--missing" ]] ; then
680                 missing_action=$2
681                 shift ; shift
682                 case ${missing_action} in
683                         true|false|die) ;;
684                         *) die "unknown action '${missing_action}'";;
685                 esac
686         fi
687
688         local opt=$1
689         [[ ${opt:0:1} = "-" ]] && shift || opt="-a"
690
691         local PKG=$(best_version $1)
692         [[ -z ${PKG} ]] && die "Unable to resolve $1 to an installed package"
693         shift
694
695         local USEFILE=${EROOT}/var/db/pkg/${PKG}/USE
696         local IUSEFILE=${EROOT}/var/db/pkg/${PKG}/IUSE
697
698         # if the IUSE file doesn't exist, the read will error out, we need to handle
699         # this gracefully
700         if [[ ! -e ${USEFILE} ]] || [[ ! -e ${IUSEFILE} && ${hidden} == "no" ]] ; then
701                 case ${missing_action} in
702                         true)   return 0;;
703                         false)  return 1;;
704                         die)    die "Unable to determine what USE flags $PKG was built with";;
705                 esac
706         fi
707
708         if [[ ${hidden} == "no" ]] ; then
709                 local IUSE_BUILT=( $(<"${IUSEFILE}") )
710                 # Don't check USE_EXPAND #147237
711                 local expand
712                 for expand in $(echo ${USE_EXPAND} | tr '[:upper:]' '[:lower:]') ; do
713                         if [[ $1 == ${expand}_* ]] ; then
714                                 expand=""
715                                 break
716                         fi
717                 done
718                 if [[ -n ${expand} ]] ; then
719                         if ! has $1 ${IUSE_BUILT[@]#[-+]} ; then
720                                 case ${missing_action} in
721                                         true)  return 0;;
722                                         false) return 1;;
723                                         die)   die "$PKG does not actually support the $1 USE flag!";;
724                                 esac
725                         fi
726                 fi
727         fi
728
729         local USE_BUILT=$(<${USEFILE})
730         while [[ $# -gt 0 ]] ; do
731                 if [[ ${opt} = "-o" ]] ; then
732                         has $1 ${USE_BUILT} && return 0
733                 else
734                         has $1 ${USE_BUILT} || return 1
735                 fi
736                 shift
737         done
738         [[ ${opt} = "-a" ]]
739 }
740
741 # @FUNCTION: make_wrapper
742 # @USAGE: <wrapper> <target> [chdir] [libpaths] [installpath]
743 # @DESCRIPTION:
744 # Create a shell wrapper script named wrapper in installpath
745 # (defaults to the bindir) to execute target (default of wrapper) by
746 # first optionally setting LD_LIBRARY_PATH to the colon-delimited
747 # libpaths followed by optionally changing directory to chdir.
748 make_wrapper() {
749         _eutils_eprefix_init
750         local wrapper=$1 bin=$2 chdir=$3 libdir=$4 path=$5
751         local tmpwrapper=$(emktemp)
752
753         (
754         echo '#!/bin/sh'
755         [[ -n ${chdir} ]] && printf 'cd "%s"\n' "${EPREFIX}${chdir}"
756         if [[ -n ${libdir} ]] ; then
757                 local var
758                 if [[ ${CHOST} == *-darwin* ]] ; then
759                         var=DYLD_LIBRARY_PATH
760                 else
761                         var=LD_LIBRARY_PATH
762                 fi
763                 cat <<-EOF
764                         if [ "\${${var}+set}" = "set" ] ; then
765                                 export ${var}="\${${var}}:${EPREFIX}${libdir}"
766                         else
767                                 export ${var}="${EPREFIX}${libdir}"
768                         fi
769                 EOF
770         fi
771         # We don't want to quote ${bin} so that people can pass complex
772         # things as ${bin} ... "./someprog --args"
773         printf 'exec %s "$@"\n' "${bin/#\//${EPREFIX}/}"
774         ) > "${tmpwrapper}"
775         chmod go+rx "${tmpwrapper}"
776
777         if [[ -n ${path} ]] ; then
778                 (
779                 exeinto "${path}"
780                 newexe "${tmpwrapper}" "${wrapper}"
781                 ) || die
782         else
783                 newbin "${tmpwrapper}" "${wrapper}" || die
784         fi
785 }
786
787 # @FUNCTION: path_exists
788 # @USAGE: [-a|-o] <paths>
789 # @DESCRIPTION:
790 # Check if the specified paths exist.  Works for all types of paths
791 # (files/dirs/etc...).  The -a and -o flags control the requirements
792 # of the paths.  They correspond to "and" and "or" logic.  So the -a
793 # flag means all the paths must exist while the -o flag means at least
794 # one of the paths must exist.  The default behavior is "and".  If no
795 # paths are specified, then the return value is "false".
796 path_exists() {
797         local opt=$1
798         [[ ${opt} == -[ao] ]] && shift || opt="-a"
799
800         # no paths -> return false
801         # same behavior as: [[ -e "" ]]
802         [[ $# -eq 0 ]] && return 1
803
804         local p r=0
805         for p in "$@" ; do
806                 [[ -e ${p} ]]
807                 : $(( r += $? ))
808         done
809
810         case ${opt} in
811                 -a) return $(( r != 0 )) ;;
812                 -o) return $(( r == $# )) ;;
813         esac
814 }
815
816 # @FUNCTION: use_if_iuse
817 # @USAGE: <flag>
818 # @DESCRIPTION:
819 # Return true if the given flag is in USE and IUSE.
820 #
821 # Note that this function should not be used in the global scope.
822 use_if_iuse() {
823         in_iuse $1 || return 1
824         use $1
825 }
826
827 # @FUNCTION: optfeature
828 # @USAGE: <short description> <package atom to match> [other atoms]
829 # @DESCRIPTION:
830 # Print out a message suggesting an optional package (or packages) which
831 # provide the described functionality
832 #
833 # The following snippet would suggest app-misc/foo for optional foo support,
834 # app-misc/bar or app-misc/baz[bar] for optional bar support
835 # and either both app-misc/a and app-misc/b or app-misc/c for alphabet support.
836 # @CODE
837 #       optfeature "foo support" app-misc/foo
838 #       optfeature "bar support" app-misc/bar app-misc/baz[bar]
839 #       optfeature "alphabet support" "app-misc/a app-misc/b" app-misc/c
840 # @CODE
841 optfeature() {
842         debug-print-function ${FUNCNAME} "$@"
843         local i j msg
844         local desc=$1
845         local flag=0
846         shift
847         for i; do
848                 for j in ${i}; do
849                         if has_version "${j}"; then
850                                 flag=1
851                         else
852                                 flag=0
853                                 break
854                         fi
855                 done
856                 if [[ ${flag} -eq 1 ]]; then
857                         break
858                 fi
859         done
860         if [[ ${flag} -eq 0 ]]; then
861                 for i; do
862                         msg=" "
863                         for j in ${i}; do
864                                 msg+=" ${j} and"
865                         done
866                         msg="${msg:0: -4} for ${desc}"
867                         elog "${msg}"
868                 done
869         fi
870 }
871
872 check_license() {
873         die "you no longer need this as portage supports ACCEPT_LICENSE itself"
874 }
875
876 case ${EAPI:-0} in
877 0|1|2)
878
879 # @FUNCTION: epause
880 # @USAGE: [seconds]
881 # @DESCRIPTION:
882 # Sleep for the specified number of seconds (default of 5 seconds).  Useful when
883 # printing a message the user should probably be reading and often used in
884 # conjunction with the ebeep function.  If the EPAUSE_IGNORE env var is set,
885 # don't wait at all. Defined in EAPIs 0 1 and 2.
886 epause() {
887         [[ -z ${EPAUSE_IGNORE} ]] && sleep ${1:-5}
888 }
889
890 # @FUNCTION: ebeep
891 # @USAGE: [number of beeps]
892 # @DESCRIPTION:
893 # Issue the specified number of beeps (default of 5 beeps).  Useful when
894 # printing a message the user should probably be reading and often used in
895 # conjunction with the epause function.  If the EBEEP_IGNORE env var is set,
896 # don't beep at all. Defined in EAPIs 0 1 and 2.
897 ebeep() {
898         local n
899         if [[ -z ${EBEEP_IGNORE} ]] ; then
900                 for ((n=1 ; n <= ${1:-5} ; n++)) ; do
901                         echo -ne "\a"
902                         sleep 0.1 &>/dev/null ; sleep 0,1 &>/dev/null
903                         echo -ne "\a"
904                         sleep 1
905                 done
906         fi
907 }
908
909 ;;
910 *)
911
912 ebeep() {
913         ewarn "QA Notice: ebeep is not defined in EAPI=${EAPI}, please file a bug at https://bugs.gentoo.org"
914 }
915
916 epause() {
917         ewarn "QA Notice: epause is not defined in EAPI=${EAPI}, please file a bug at https://bugs.gentoo.org"
918 }
919
920 ;;
921 esac
922
923 case ${EAPI:-0} in
924 0|1|2|3|4)
925
926 # @FUNCTION: usex
927 # @USAGE: <USE flag> [true output] [false output] [true suffix] [false suffix]
928 # @DESCRIPTION:
929 # Proxy to declare usex for package managers or EAPIs that do not provide it
930 # and use the package manager implementation when available (i.e. EAPI >= 5).
931 # If USE flag is set, echo [true output][true suffix] (defaults to "yes"),
932 # otherwise echo [false output][false suffix] (defaults to "no").
933 usex() { use "$1" && echo "${2-yes}$4" || echo "${3-no}$5" ; } #382963
934
935 ;;
936 esac
937
938 case ${EAPI:-0} in
939 0|1|2|3|4|5)
940
941 # @FUNCTION: einstalldocs
942 # @DESCRIPTION:
943 # Install documentation using DOCS and HTML_DOCS.
944 #
945 # If DOCS is declared and non-empty, all files listed in it are
946 # installed. The files must exist, otherwise the function will fail.
947 # In EAPI 4 and subsequent EAPIs DOCS may specify directories as well,
948 # in other EAPIs using directories is unsupported.
949 #
950 # If DOCS is not declared, the files matching patterns given
951 # in the default EAPI implementation of src_install will be installed.
952 # If this is undesired, DOCS can be set to empty value to prevent any
953 # documentation from being installed.
954 #
955 # If HTML_DOCS is declared and non-empty, all files and/or directories
956 # listed in it are installed as HTML docs (using dohtml).
957 #
958 # Both DOCS and HTML_DOCS can either be an array or a whitespace-
959 # separated list. Whenever directories are allowed, '<directory>/.' may
960 # be specified in order to install all files within the directory
961 # without creating a sub-directory in docdir.
962 #
963 # Passing additional options to dodoc and dohtml is not supported.
964 # If you needed such a thing, you need to call those helpers explicitly.
965 einstalldocs() {
966         debug-print-function ${FUNCNAME} "${@}"
967
968         local dodoc_opts=-r
969         has ${EAPI} 0 1 2 3 && dodoc_opts=
970
971         if ! declare -p DOCS &>/dev/null ; then
972                 local d
973                 for d in README* ChangeLog AUTHORS NEWS TODO CHANGES \
974                                 THANKS BUGS FAQ CREDITS CHANGELOG ; do
975                         if [[ -s ${d} ]] ; then
976                                 dodoc "${d}" || die
977                         fi
978                 done
979         elif [[ $(declare -p DOCS) == "declare -a"* ]] ; then
980                 if [[ ${DOCS[@]} ]] ; then
981                         dodoc ${dodoc_opts} "${DOCS[@]}" || die
982                 fi
983         else
984                 if [[ ${DOCS} ]] ; then
985                         dodoc ${dodoc_opts} ${DOCS} || die
986                 fi
987         fi
988
989         if [[ $(declare -p HTML_DOCS 2>/dev/null) == "declare -a"* ]] ; then
990                 if [[ ${HTML_DOCS[@]} ]] ; then
991                         dohtml -r "${HTML_DOCS[@]}" || die
992                 fi
993         else
994                 if [[ ${HTML_DOCS} ]] ; then
995                         dohtml -r ${HTML_DOCS} || die
996                 fi
997         fi
998
999         return 0
1000 }
1001
1002 # @FUNCTION: in_iuse
1003 # @USAGE: <flag>
1004 # @DESCRIPTION:
1005 # Determines whether the given flag is in IUSE. Strips IUSE default prefixes
1006 # as necessary.
1007 #
1008 # Note that this function should not be used in the global scope.
1009 in_iuse() {
1010         debug-print-function ${FUNCNAME} "${@}"
1011         [[ ${#} -eq 1 ]] || die "Invalid args to ${FUNCNAME}()"
1012
1013         local flag=${1}
1014         local liuse=( ${IUSE} )
1015
1016         has "${flag}" "${liuse[@]#[+-]}"
1017 }
1018
1019 ;;
1020 esac
1021
1022 fi