# Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/eclass/eutils.eclass,v 1.298 2008/02/20 12:36:14 hollow Exp $
# @ECLASS: eutils.eclass
# @MAINTAINER:
# base-system@gentoo.org
# @BLURB: many extra (but common) functions that are used in ebuilds
# @DESCRIPTION:
# The eutils eclass contains a suite of functions that complement
# the ones that ebuild.sh already contain. The idea is that the functions
# are not required in all ebuilds but enough utilize them to have a common
# home rather than having multiple ebuilds implementing the same thing.
#
# Due to the nature of this eclass, some functions may have maintainers
# different from the overall eclass!
inherit multilib portability
DESCRIPTION="Based on the ${ECLASS} eclass"
# @FUNCTION: epause
# @USAGE: [seconds]
# @DESCRIPTION:
# Sleep for the specified number of seconds (default of 5 seconds). Useful when
# printing a message the user should probably be reading and often used in
# conjunction with the ebeep function. If the EPAUSE_IGNORE env var is set,
# don't wait at all.
epause() {
[[ -z ${EPAUSE_IGNORE} ]] && sleep ${1:-5}
}
# @FUNCTION: ebeep
# @USAGE: [number of beeps]
# @DESCRIPTION:
# Issue the specified number of beeps (default of 5 beeps). Useful when
# printing a message the user should probably be reading and often used in
# conjunction with the epause function. If the EBEEP_IGNORE env var is set,
# don't beep at all.
ebeep() {
local n
if [[ -z ${EBEEP_IGNORE} ]] ; then
for ((n=1 ; n <= ${1:-5} ; n++)) ; do
echo -ne "\a"
sleep 0.1 &>/dev/null ; sleep 0,1 &>/dev/null
echo -ne "\a"
sleep 1
done
fi
}
# @FUNCTION: ecvs_clean
# @USAGE:
[more dirs ...]
# @DESCRIPTION:
# Remove CVS directories recursiveley. Useful when a source tarball contains
# internal CVS directories.
ecvs_clean() {
[[ $# -gt 0 ]] || set -- .
find "$@" -type d -name 'CVS' -prune -print0 | xargs -0 rm -rf
find "$@" -type f -name '.cvs*' -print0 | xargs -0 rm -rf
}
# @FUNCTION: esvn_clean
# @USAGE: [more dirs ...]
# @DESCRIPTION:
# Remove .svn directories recursiveley. Useful when a source tarball contains
# internal Subversion directories.
esvn_clean() {
[[ $# -gt 0 ]] || set -- .
find "$@" -type d -name '.svn' -prune -print0 | xargs -0 rm -rf
}
# Default directory where patches are located
EPATCH_SOURCE="${WORKDIR}/patch"
# Default extension for patches
EPATCH_SUFFIX="patch.bz2"
# Default options for patch
# Set -g0 to keep RCS, ClearCase, Perforce and SCCS happy. Bug #24571
# Set --no-backup-if-mismatch so we don't leave '.orig' files behind.
# Set -E to automatically remove empty files.
EPATCH_OPTS="-g0 -E --no-backup-if-mismatch"
# List of patches not to apply. Not this is only file names,
# and not the full path ..
EPATCH_EXCLUDE=""
# Change the printed message for a single patch.
EPATCH_SINGLE_MSG=""
# Change the printed message for multiple patches.
EPATCH_MULTI_MSG="Applying various patches (bugfixes/updates) ..."
# Force applying bulk patches even if not following the style:
#
# ??_${ARCH}_foo.${EPATCH_SUFFIX}
#
EPATCH_FORCE="no"
# This function is for bulk patching, or in theory for just one
# or two patches.
#
# It should work with .bz2, .gz, .zip and plain text patches.
# Currently all patches should be the same format.
#
# You do not have to specify '-p' option to patch, as it will
# try with -p0 to -p5 until it succeed, or fail at -p5.
#
# Above EPATCH_* variables can be used to control various defaults,
# bug they should be left as is to ensure an ebuild can rely on
# them for.
#
# Patches are applied in current directory.
#
# Bulk Patches should preferibly have the form of:
#
# ??_${ARCH}_foo.${EPATCH_SUFFIX}
#
# For example:
#
# 01_all_misc-fix.patch.bz2
# 02_sparc_another-fix.patch.bz2
#
# This ensures that there are a set order, and you can have ARCH
# specific patches.
#
# If you however give an argument to epatch(), it will treat it as a
# single patch that need to be applied if its a file. If on the other
# hand its a directory, it will set EPATCH_SOURCE to this.
#
# (10 Nov 2002)
#
epatch() {
_epatch_draw_line() {
[[ -z $1 ]] && set "$(printf "%65s" '')"
echo "${1//?/=}"
}
_epatch_assert() { local _pipestatus=${PIPESTATUS[*]}; [[ ${_pipestatus// /} -eq 0 ]] ; }
local PIPE_CMD=""
local STDERR_TARGET="${T}/$$.out"
local PATCH_TARGET="${T}/$$.patch"
local PATCH_SUFFIX=""
local SINGLE_PATCH="no"
local x=""
unset P4CONFIG P4PORT P4USER # keep perforce at bay #56402
if [ "$#" -gt 1 ]
then
local m=""
for m in "$@" ; do
epatch "${m}"
done
return 0
fi
if [ -n "$1" -a -f "$1" ]
then
SINGLE_PATCH="yes"
local EPATCH_SOURCE="$1"
local EPATCH_SUFFIX="${1##*\.}"
elif [ -n "$1" -a -d "$1" ]
then
# Allow no extension if EPATCH_FORCE=yes ... used by vim for example ...
if [ "${EPATCH_FORCE}" = "yes" ] && [ -z "${EPATCH_SUFFIX}" ]
then
local EPATCH_SOURCE="$1/*"
else
local EPATCH_SOURCE="$1/*.${EPATCH_SUFFIX}"
fi
else
if [[ ! -d ${EPATCH_SOURCE} ]] || [[ -n $1 ]] ; then
if [ -n "$1" -a "${EPATCH_SOURCE}" = "${WORKDIR}/patch" ]
then
EPATCH_SOURCE="$1"
fi
echo
eerror "Cannot find \$EPATCH_SOURCE! Value for \$EPATCH_SOURCE is:"
eerror
eerror " ${EPATCH_SOURCE}"
eerror " ( ${EPATCH_SOURCE##*/} )"
echo
die "Cannot find \$EPATCH_SOURCE!"
fi
local EPATCH_SOURCE="${EPATCH_SOURCE}/*.${EPATCH_SUFFIX}"
fi
case ${EPATCH_SUFFIX##*\.} in
bz2)
PIPE_CMD="bzip2 -dc"
PATCH_SUFFIX="bz2"
;;
gz|Z|z)
PIPE_CMD="gzip -dc"
PATCH_SUFFIX="gz"
;;
ZIP|zip)
PIPE_CMD="unzip -p"
PATCH_SUFFIX="zip"
;;
*)
PIPE_CMD="cat"
PATCH_SUFFIX="patch"
;;
esac
if [ "${SINGLE_PATCH}" = "no" ]
then
einfo "${EPATCH_MULTI_MSG}"
fi
for x in ${EPATCH_SOURCE}
do
# New ARCH dependant patch naming scheme ...
#
# ???_arch_foo.patch
#
if [ -f ${x} ] && \
([ "${SINGLE_PATCH}" = "yes" -o "${x/_all_}" != "${x}" -o "${x/_${ARCH}_}" != "${x}" ] || \
[ "${EPATCH_FORCE}" = "yes" ])
then
local count=0
local popts="${EPATCH_OPTS}"
local patchname=${x##*/}
if [ -n "${EPATCH_EXCLUDE}" ]
then
if [ "${EPATCH_EXCLUDE/${patchname}}" != "${EPATCH_EXCLUDE}" ]
then
continue
fi
fi
if [ "${SINGLE_PATCH}" = "yes" ]
then
if [ -n "${EPATCH_SINGLE_MSG}" ]
then
einfo "${EPATCH_SINGLE_MSG}"
else
einfo "Applying ${patchname} ..."
fi
else
einfo " ${patchname} ..."
fi
echo "***** ${patchname} *****" > ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
echo >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
# Allow for prefix to differ ... im lazy, so shoot me :/
while [ "${count}" -lt 5 ]
do
# Generate some useful debug info ...
_epatch_draw_line "***** ${patchname} *****" >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
echo >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
if [ "${PATCH_SUFFIX}" != "patch" ]
then
echo -n "PIPE_COMMAND: " >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
echo "${PIPE_CMD} ${x} > ${PATCH_TARGET}" >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
else
PATCH_TARGET="${x}"
fi
echo -n "PATCH COMMAND: " >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
echo "patch -p${count} ${popts} < ${PATCH_TARGET}" >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
echo >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
_epatch_draw_line "***** ${patchname} *****" >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
if [ "${PATCH_SUFFIX}" != "patch" ]
then
if ! (${PIPE_CMD} ${x} > ${PATCH_TARGET}) >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/} 2>&1
then
echo
eerror "Could not extract patch!"
#die "Could not extract patch!"
count=5
break
fi
fi
if (cat ${PATCH_TARGET} | patch -p${count} ${popts} --dry-run -f ; _epatch_assert) >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/} 2>&1
then
_epatch_draw_line "***** ${patchname} *****" > ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}.real
echo >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}.real
echo "ACTUALLY APPLYING ${patchname} ..." >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}.real
echo >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}.real
_epatch_draw_line "***** ${patchname} *****" >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}.real
cat ${PATCH_TARGET} | patch -p${count} ${popts} >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}.real 2>&1
_epatch_assert
if [ "$?" -ne 0 ]
then
cat ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}.real >> ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
echo
eerror "A dry-run of patch command succeeded, but actually"
eerror "applying the patch failed!"
#die "Real world sux compared to the dreamworld!"
count=5
fi
rm -f ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}.real
break
fi
count=$((count + 1))
done
if [ "${PATCH_SUFFIX}" != "patch" ]
then
rm -f ${PATCH_TARGET}
fi
if [ "${count}" -eq 5 ]
then
echo
eerror "Failed Patch: ${patchname} !"
eerror " ( ${PATCH_TARGET} )"
eerror
eerror "Include in your bugreport the contents of:"
eerror
eerror " ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}"
echo
die "Failed Patch: ${patchname}!"
fi
rm -f ${STDERR_TARGET%/*}/${patchname}-${STDERR_TARGET##*/}
eend 0
fi
done
if [ "${SINGLE_PATCH}" = "no" ]
then
einfo "Done with patching"
fi
}
# @FUNCTION: emktemp
# @USAGE: [temp dir]
# @DESCRIPTION:
# Cheap replacement for when debianutils (and thus mktemp)
# does not exist on the users system.
emktemp() {
local exe="touch"
[[ $1 == -d ]] && exe="mkdir" && shift
local topdir=$1
if [[ -z ${topdir} ]] ; then
[[ -z ${T} ]] \
&& topdir="/tmp" \
|| topdir=${T}
fi
if ! type -P mktemp > /dev/null ; then
# system lacks `mktemp` so we have to fake it
local tmp=/
while [[ -e ${tmp} ]] ; do
tmp=${topdir}/tmp.${RANDOM}.${RANDOM}.${RANDOM}
done
${exe} "${tmp}" || ${exe} -p "${tmp}"
echo "${tmp}"
else
# the args here will give slightly wierd names on BSD,
# but should produce a usable file on all userlands
if [[ ${exe} == "touch" ]] ; then
TMPDIR="${topdir}" mktemp -t tmp.XXXXXXXXXX
else
TMPDIR="${topdir}" mktemp -dt tmp.XXXXXXXXXX
fi
fi
}
# @FUNCTION: egetent
# @USAGE:
# @MAINTAINER:
# base-system@gentoo.org (Linux)
# Joe Jezak (OS X)
# usata@gentoo.org (OS X)
# Aaron Walker (FreeBSD)
# @DESCRIPTION:
# Small wrapper for getent (Linux), nidump (Mac OS X),
# and pw (FreeBSD) used in enewuser()/enewgroup()
egetent() {
case ${CHOST} in
*-darwin*)
case "$2" in
*[!0-9]*) # Non numeric
nidump $1 . | awk -F":" "{ if (\$1 ~ /^$2$/) {print \$0;exit;} }"
;;
*) # Numeric
nidump $1 . | awk -F":" "{ if (\$3 == $2) {print \$0;exit;} }"
;;
esac
;;
*-freebsd*|*-dragonfly*)
local opts action="user"
[[ $1 == "passwd" ]] || action="group"
# lookup by uid/gid
if [[ $2 == [[:digit:]]* ]] ; then
[[ ${action} == "user" ]] && opts="-u" || opts="-g"
fi
pw show ${action} ${opts} "$2" -q
;;
*-netbsd*|*-openbsd*)
grep "$2:\*:" /etc/$1
;;
*)
type -p nscd >& /dev/null && nscd -i "$1"
getent "$1" "$2"
;;
esac
}
# @FUNCTION: enewuser
# @USAGE: [uid] [shell] [homedir] [groups] [params]
# @DESCRIPTION:
# Same as enewgroup, you are not required to understand how to properly add
# a user to the system. The only required parameter is the username.
# Default uid is (pass -1 for this) next available, default shell is
# /bin/false, default homedir is /dev/null, there are no default groups,
# and default params sets the comment as 'added by portage for ${PN}'.
enewuser() {
case ${EBUILD_PHASE} in
unpack|compile|test|install)
eerror "'enewuser()' called from '${EBUILD_PHASE}()' which is not a pkg_* function."
eerror "Package fails at QA and at life. Please file a bug."
die "Bad package! enewuser is only for use in pkg_* functions!"
esac
# get the username
local euser=$1; shift
if [[ -z ${euser} ]] ; then
eerror "No username specified !"
die "Cannot call enewuser without a username"
fi
# lets see if the username already exists
if [[ -n $(egetent passwd "${euser}") ]] ; then
return 0
fi
einfo "Adding user '${euser}' to your system ..."
# options to pass to useradd
local opts=
# handle uid
local euid=$1; shift
if [[ -n ${euid} && ${euid} != -1 ]] ; then
if [[ ${euid} -gt 0 ]] ; then
if [[ -n $(egetent passwd ${euid}) ]] ; then
euid="next"
fi
else
eerror "Userid given but is not greater than 0 !"
die "${euid} is not a valid UID"
fi
else
euid="next"
fi
if [[ ${euid} == "next" ]] ; then
for ((euid = 101; euid <= 999; euid++)); do
[[ -z $(egetent passwd ${euid}) ]] && break
done
fi
opts="${opts} -u ${euid}"
einfo " - Userid: ${euid}"
# handle shell
local eshell=$1; shift
if [[ ! -z ${eshell} ]] && [[ ${eshell} != "-1" ]] ; then
if [[ ! -e ${ROOT}${eshell} ]] ; then
eerror "A shell was specified but it does not exist !"
die "${eshell} does not exist in ${ROOT}"
fi
if [[ ${eshell} == */false || ${eshell} == */nologin ]] ; then
eerror "Do not specify ${eshell} yourself, use -1"
die "Pass '-1' as the shell parameter"
fi
else
for shell in /sbin/nologin /usr/sbin/nologin /bin/false /usr/bin/false /dev/null ; do
[[ -x ${ROOT}${shell} ]] && break
done
if [[ ${shell} == "/dev/null" ]] ; then
eerror "Unable to identify the shell to use, proceeding with userland default."
case ${USERLAND} in
GNU) shell="/bin/false" ;;
BSD) shell="/sbin/nologin" ;;
Darwin) shell="/usr/sbin/nologin" ;;
*) die "Unable to identify the default shell for userland ${USERLAND}"
esac
fi
eshell=${shell}
fi
einfo " - Shell: ${eshell}"
opts="${opts} -s ${eshell}"
# handle homedir
local ehome=$1; shift
if [[ -z ${ehome} ]] || [[ ${ehome} == "-1" ]] ; then
ehome="/dev/null"
fi
einfo " - Home: ${ehome}"
opts="${opts} -d ${ehome}"
# handle groups
local egroups=$1; shift
if [[ ! -z ${egroups} ]] ; then
local oldifs=${IFS}
local defgroup="" exgroups=""
export IFS=","
for g in ${egroups} ; do
export IFS=${oldifs}
if [[ -z $(egetent group "${g}") ]] ; then
eerror "You must add group ${g} to the system first"
die "${g} is not a valid GID"
fi
if [[ -z ${defgroup} ]] ; then
defgroup=${g}
else
exgroups="${exgroups},${g}"
fi
export IFS=","
done
export IFS=${oldifs}
opts="${opts} -g ${defgroup}"
if [[ ! -z ${exgroups} ]] ; then
opts="${opts} -G ${exgroups:1}"
fi
else
egroups="(none)"
fi
einfo " - Groups: ${egroups}"
# handle extra and add the user
local oldsandbox=${SANDBOX_ON}
export SANDBOX_ON="0"
case ${CHOST} in
*-darwin*)
### Make the user
if [[ -z $@ ]] ; then
dscl . create /users/${euser} uid ${euid}
dscl . create /users/${euser} shell ${eshell}
dscl . create /users/${euser} home ${ehome}
dscl . create /users/${euser} realname "added by portage for ${PN}"
### Add the user to the groups specified
local oldifs=${IFS}
export IFS=","
for g in ${egroups} ; do
dscl . merge /groups/${g} users ${euser}
done
export IFS=${oldifs}
else
einfo "Extra options are not supported on Darwin yet"
einfo "Please report the ebuild along with the info below"
einfo "eextra: $@"
die "Required function missing"
fi
;;
*-freebsd*|*-dragonfly*)
if [[ -z $@ ]] ; then
pw useradd ${euser} ${opts} \
-c "added by portage for ${PN}" \
die "enewuser failed"
else
einfo " - Extra: $@"
pw useradd ${euser} ${opts} \
"$@" || die "enewuser failed"
fi
;;
*-netbsd*)
if [[ -z $@ ]] ; then
useradd ${opts} ${euser} || die "enewuser failed"
else
einfo " - Extra: $@"
useradd ${opts} ${euser} "$@" || die "enewuser failed"
fi
;;
*-openbsd*)
if [[ -z $@ ]] ; then
useradd -u ${euid} -s ${eshell} \
-d ${ehome} -c "Added by portage for ${PN}" \
-g ${egroups} ${euser} || die "enewuser failed"
else
einfo " - Extra: $@"
useradd -u ${euid} -s ${eshell} \
-d ${ehome} -c "Added by portage for ${PN}" \
-g ${egroups} ${euser} "$@" || die "enewuser failed"
fi
;;
*)
if [[ -z $@ ]] ; then
useradd ${opts} ${euser} \
-c "added by portage for ${PN}" \
|| die "enewuser failed"
else
einfo " - Extra: $@"
useradd ${opts} ${euser} "$@" \
|| die "enewuser failed"
fi
;;
esac
if [[ ! -e ${ROOT}/${ehome} ]] ; then
einfo " - Creating ${ehome} in ${ROOT}"
mkdir -p "${ROOT}/${ehome}"
chown ${euser} "${ROOT}/${ehome}"
chmod 755 "${ROOT}/${ehome}"
fi
export SANDBOX_ON=${oldsandbox}
}
# @FUNCTION: enewgroup
# @USAGE: [gid]
# @DESCRIPTION:
# This function does not require you to understand how to properly add a
# group to the system. Just give it a group name to add and enewgroup will
# do the rest. You may specify the gid for the group or allow the group to
# allocate the next available one.
enewgroup() {
case ${EBUILD_PHASE} in
unpack|compile|test|install)
eerror "'enewgroup()' called from '${EBUILD_PHASE}()' which is not a pkg_* function."
eerror "Package fails at QA and at life. Please file a bug."
die "Bad package! enewgroup is only for use in pkg_* functions!"
esac
# get the group
local egroup="$1"; shift
if [ -z "${egroup}" ]
then
eerror "No group specified !"
die "Cannot call enewgroup without a group"
fi
# see if group already exists
if [[ -n $(egetent group "${egroup}") ]]; then
return 0
fi
einfo "Adding group '${egroup}' to your system ..."
# options to pass to useradd
local opts=
# handle gid
local egid="$1"; shift
if [ ! -z "${egid}" ]
then
if [ "${egid}" -gt 0 ]
then
if [ -z "`egetent group ${egid}`" ]
then
if [[ "${CHOST}" == *-darwin* ]]; then
opts="${opts} ${egid}"
else
opts="${opts} -g ${egid}"
fi
else
egid="next available; requested gid taken"
fi
else
eerror "Groupid given but is not greater than 0 !"
die "${egid} is not a valid GID"
fi
else
egid="next available"
fi
einfo " - Groupid: ${egid}"
# handle extra
local eextra="$@"
opts="${opts} ${eextra}"
# add the group
local oldsandbox="${SANDBOX_ON}"
export SANDBOX_ON="0"
case ${CHOST} in
*-darwin*)
if [ ! -z "${eextra}" ];
then
einfo "Extra options are not supported on Darwin/OS X yet"
einfo "Please report the ebuild along with the info below"
einfo "eextra: ${eextra}"
die "Required function missing"
fi
# If we need the next available
case ${egid} in
*[!0-9]*) # Non numeric
for ((egid = 101; egid <= 999; egid++)); do
[[ -z $(egetent group ${egid}) ]] && break
done
esac
dscl . create /groups/${egroup} gid ${egid}
dscl . create /groups/${egroup} passwd '*'
;;
*-freebsd*|*-dragonfly*)
case ${egid} in
*[!0-9]*) # Non numeric
for ((egid = 101; egid <= 999; egid++)); do
[[ -z $(egetent group ${egid}) ]] && break
done
esac
pw groupadd ${egroup} -g ${egid} || die "enewgroup failed"
;;
*-netbsd*)
case ${egid} in
*[!0-9]*) # Non numeric
for ((egid = 101; egid <= 999; egid++)); do
[[ -z $(egetent group ${egid}) ]] && break
done
esac
groupadd -g ${egid} ${egroup} || die "enewgroup failed"
;;
*)
groupadd ${opts} ${egroup} || die "enewgroup failed"
;;
esac
export SANDBOX_ON="${oldsandbox}"
}
# @FUNCTION: edos2unix
# @USAGE: [more files ...]
# @DESCRIPTION:
# A handy replacement for dos2unix, recode, fixdos, etc... This allows you
# to remove all of these text utilities from DEPEND variables because this
# is a script based solution. Just give it a list of files to convert and
# they will all be changed from the DOS CRLF format to the UNIX LF format.
edos2unix() {
echo "$@" | xargs sed -i 's/\r$//'
}
# Make a desktop file !
# Great for making those icons in kde/gnome startmenu !
# Amaze your friends ! Get the women ! Join today !
#
# make_desktop_entry(, [name], [icon], [type], [path])
#
# binary: what command does the app run with ?
# name: the name that will show up in the menu
# icon: give your little like a pretty little icon ...
# this can be relative (to /usr/share/pixmaps) or
# a full path to an icon
# type: what kind of application is this ? for categories:
# http://standards.freedesktop.org/menu-spec/latest/apa.html
# path: if your app needs to startup in a specific dir
make_desktop_entry() {
[[ -z $1 ]] && eerror "make_desktop_entry: You must specify the executable" && return 1
local exec=${1}
local name=${2:-${PN}}
local icon=${3:-${PN}}
local type=${4}
local path=${5}
if [[ -z ${type} ]] ; then
local catmaj=${CATEGORY%%-*}
local catmin=${CATEGORY##*-}
case ${catmaj} in
app)
case ${catmin} in
accessibility) type=Accessibility;;
admin) type=System;;
antivirus) type=System;;
arch) type=Archiving;;
backup) type=Archiving;;
cdr) type=DiscBurning;;
dicts) type=Dictionary;;
doc) type=Documentation;;
editors) type=TextEditor;;
emacs) type=TextEditor;;
emulation) type=Emulator;;
laptop) type=HardwareSettings;;
office) type=Office;;
pda) type=PDA;;
vim) type=TextEditor;;
xemacs) type=TextEditor;;
*) type=;;
esac
;;
dev)
type="Development"
;;
games)
case ${catmin} in
action|fps) type=ActionGame;;
arcade) type=ArcadeGame;;
board) type=BoardGame;;
emulation) type=Emulator;;
kids) type=KidsGame;;
puzzle) type=LogicGame;;
roguelike) type=RolePlaying;;
rpg) type=RolePlaying;;
simulation) type=Simulation;;
sports) type=SportsGame;;
strategy) type=StrategyGame;;
*) type=;;
esac
type="Game;${type}"
;;
gnome)
type="Gnome;GTK"
;;
kde)
type="KDE;Qt"
;;
mail)
type="Network;Email"
;;
media)
case ${catmin} in
gfx) type=Graphics;;
radio) type=Tuner;;
sound) type=Audio;;
tv) type=TV;;
video) type=Video;;
*) type=;;
esac
type="AudioVideo;${type}"
;;
net)
case ${catmin} in
dialup) type=Dialup;;
ftp) type=FileTransfer;;
im) type=InstantMessaging;;
irc) type=IRCClient;;
mail) type=Email;;
news) type=News;;
nntp) type=News;;
p2p) type=FileTransfer;;
*) type=;;
esac
type="Network;${type}"
;;
sci)
case ${catmin} in
astro*) type=Astronomy;;
bio*) type=Biology;;
calc*) type=Calculator;;
chem*) type=Chemistry;;
elec*) type=Electronics;;
geo*) type=Geology;;
math*) type=Math;;
physics) type=Physics;;
visual*) type=DataVisualization;;
*) type=;;
esac
type="Science;${type}"
;;
sys)
type="System"
;;
www)
case ${catmin} in
client) type=WebBrowser;;
*) type=;;
esac
type="Network"
;;
*)
type=
;;
esac
fi
if [ "${SLOT}" == "0" ] ; then
local desktop_name="${PN}"
else
local desktop_name="${PN}-${SLOT}"
fi
local desktop="${T}/$(echo ${exec} | sed 's:[[:space:]/:]:_:g')-${desktop_name}.desktop"
#local desktop=${T}/${exec%% *:-${desktop_name}}.desktop
cat <<-EOF > "${desktop}"
[Desktop Entry]
Version=1.0
Name=${name}
Type=Application
Comment=${DESCRIPTION}
Exec=${exec}
TryExec=${exec%% *}
Icon=${icon}
Categories=${type};
EOF
[[ ${path} ]] && echo "Path=${path}" >> "${desktop}"
(
# wrap the env here so that the 'insinto' call
# doesn't corrupt the env of the caller
insinto /usr/share/applications
doins "${desktop}"
)
}
# @FUNCTION: validate_desktop_entries
# @USAGE: [directories]
# @MAINTAINER:
# Carsten Lohrke
# @DESCRIPTION:
# Validate desktop entries using desktop-file-utils
validate_desktop_entries() {
if [[ -x /usr/bin/desktop-file-validate ]] ; then
einfo "Checking desktop entry validity"
local directories=""
for d in /usr/share/applications $@ ; do
[[ -d ${D}${d} ]] && directories="${directories} ${D}${d}"
done
if [[ -n ${directories} ]] ; then
for FILE in $(find ${directories} -name "*\.desktop" \
-not -path '*.hidden*' | sort -u 2>/dev/null)
do
local temp=$(desktop-file-validate ${FILE} | grep -v "warning:" | \
sed -e "s|error: ||" -e "s|${FILE}:|--|g" )
[[ -n $temp ]] && elog ${temp/--/${FILE/${D}/}:}
done
fi
echo ""
else
einfo "Passing desktop entry validity check. Install dev-util/desktop-file-utils, if you want to help to improve Gentoo."
fi
}
# @FUNCTION: make_session_desktop
# @USAGE:
# @DESCRIPTION:
# Make a GDM/KDM Session file. The title is the file to execute to start the
# Window Manager. The command is the name of the Window Manager.
make_session_desktop() {
[[ -z $1 ]] && eerror "make_session_desktop: You must specify the title" && return 1
[[ -z $2 ]] && eerror "make_session_desktop: You must specify the command" && return 1
local title=$1
local command=$2
local desktop=${T}/${wm}.desktop
cat <<-EOF > "${desktop}"
[Desktop Entry]
Name=${title}
Comment=This session logs you into ${title}
Exec=${command}
TryExec=${command}
Type=Application
EOF
(
# wrap the env here so that the 'insinto' call
# doesn't corrupt the env of the caller
insinto /usr/share/xsessions
doins "${desktop}"
)
}
# @FUNCTION: domenu
# @USAGE:
# @DESCRIPTION:
# Install the list of .desktop menu files into the appropriate directory
# (/usr/share/applications).
domenu() {
(
# wrap the env here so that the 'insinto' call
# doesn't corrupt the env of the caller
local i j ret=0
insinto /usr/share/applications
for i in "$@" ; do
if [[ -f ${i} ]] ; then
doins "${i}"
((ret+=$?))
elif [[ -d ${i} ]] ; then
for j in "${i}"/*.desktop ; do
doins "${j}"
((ret+=$?))
done
else
((++ret))
fi
done
exit ${ret}
)
}
# @FUNCTION: newmenu
# @USAGE: