#!/bin/bash -e # # makepkg - make packages compatible for use with pacman # @configure_input@ # # Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org> # Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> # Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> # Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> # Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> # Copyright (c) 2006 by Alex Smith <alex@alex-smith.me.uk> # Copyright (c) 2006 by Andras Voroskoi <voroskoi@frugalware.org> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: # bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils), # gettext, grep, gzip, openssl, sed, tput (ncurses), xz # gettext initialization export TEXTDOMAIN='pacman' export TEXTDOMAINDIR='@localedir@' # file -i does not work on Mac OSX unless legacy mode is set export COMMAND_MODE='legacy' myver='@PACKAGE_VERSION@' confdir='@sysconfdir@' BUILDSCRIPT='@BUILDSCRIPT@' startdir="$PWD" srcdir="$startdir/src" pkgdir="$startdir/pkg" packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge') other_options=('ccache' 'distcc' 'makeflags' 'force') splitpkg_overrides=('pkgver' 'pkgrel' 'pkgdesc' 'arch' 'license' 'groups' \ 'depends' 'optdepends' 'provides' 'conflicts' 'replaces' \ 'backup' 'options' 'install' 'changelog') readonly -a packaging_options other_options splitpkg_overrides # Options ASROOT=0 CLEANUP=0 CLEANCACHE=0 DEP_BIN=0 FORCE=0 INFAKEROOT=0 GENINTEG=0 SKIPINTEG=0 INSTALL=0 NOBUILD=0 NODEPS=0 NOEXTRACT=0 RMDEPS=0 REPKG=0 LOGGING=0 SOURCEONLY=0 IGNOREARCH=0 HOLDVER=0 BUILDFUNC=0 PKGFUNC=0 SPLITPKG=0 PKGLIST="" # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call # when dealing with svn/cvs/etc PKGBUILDs. FORCE_VER="" PACMAN_OPTS= ### SUBROUTINES ### plain() { local mesg=$1; shift printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } msg() { local mesg=$1; shift printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } msg2() { local mesg=$1; shift printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } warning() { local mesg=$1; shift printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } error() { local mesg=$1; shift printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } ## # Special exit call for traps, Don't print any error messages when inside, # the fakeroot call, the error message will be printed by the main call. ## trap_exit() { if (( ! INFAKEROOT )); then echo error "$@" fi [[ -n $srclinks ]] && rm -rf "$srclinks" exit 1 } ## # Clean up function. Called automatically when the script exits. ## clean_up() { local EXIT_CODE=$? if (( INFAKEROOT )); then # Don't clean up when leaving fakeroot, we're not done yet. return fi if (( ! EXIT_CODE && CLEANUP )); then # If it's a clean exit and -c/--clean has been passed... msg "$(gettext "Cleaning up...")" rm -rf "$pkgdir" "$srcdir" if [[ -n $pkgbase ]]; then # Can't do this unless the BUILDSCRIPT has been sourced. if (( BUILDFUNC )); then rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log"* fi if (( PKGFUNC )); then rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-package.log"* elif (( SPLITPKG )); then for pkg in ${pkgname[@]}; do rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-package_${pkg}.log"* done fi # clean up dangling symlinks to packages for pkg in ${pkgname[@]}; do for file in ${pkg}-*-*-${CARCH}${PKGEXT}; do if [[ -h $file && ! -e $file ]]; then rm -f $file fi done done fi fi remove_deps } ## # Signal Traps ## set -E trap 'clean_up' 0 trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR # a source entry can have two forms : # 1) "filename::http://path/to/file" # 2) "http://path/to/file" # extract the filename from a source entry get_filename() { # if a filename is specified, use it local filename="${1%%::*}" # if it is just an URL, we only keep the last component echo "${filename##*/}" } # extract the URL from a source entry get_url() { # strip an eventual filename echo "${1#*::}" } ## # Checks to see if options are present in makepkg.conf or PKGBUILD; # PKGBUILD options always take precedence. # # usage : check_option( $option ) # return : y - enabled # n - disabled # ? - not found ## check_option() { local ret=$(in_opt_array "$1" ${options[@]}) if [[ $ret != '?' ]]; then echo $ret return fi # fall back to makepkg.conf options ret=$(in_opt_array "$1" ${OPTIONS[@]}) if [[ $ret != '?' ]]; then echo $ret return fi echo '?' # Not Found } ## # Check if option is present in BUILDENV # # usage : check_buildenv( $option ) # return : y - enabled # n - disabled # ? - not found ## check_buildenv() { echo $(in_opt_array "$1" ${BUILDENV[@]}) } ## # usage : in_opt_array( $needle, $haystack ) # return : y - enabled # n - disabled # ? - not found ## in_opt_array() { local needle="${1,,}"; shift local opt for opt in "$@"; do opt="${opt,,}" if [[ $opt = $needle ]]; then echo 'y' # Enabled return elif [[ $opt = "!$needle" ]]; then echo 'n' # Disabled return fi done echo '?' # Not Found } ## # usage : in_array( $needle, $haystack ) # return : 0 - found # 1 - not found ## in_array() { local needle=$1; shift [[ -z $1 ]] && return 1 # Not Found local item for item in "$@"; do [[ $item = $needle ]] && return 0 # Found done return 1 # Not Found } get_downloadclient() { # $1 = URL with valid protocol prefix local url=$1 local proto="${url%%://*}" # loop through DOWNLOAD_AGENTS variable looking for protocol local i for i in "${DLAGENTS[@]}"; do local handler="${i%%::*}" if [[ $proto = $handler ]]; then agent="${i##*::}" break fi done # if we didn't find an agent, return an error if [[ -z $agent ]]; then error "$(gettext "There is no agent set up to handle %s URLs. Check %s.")" "$proto" "$MAKEPKG_CONF" plain "$(gettext "Aborting...")" exit 1 # $E_CONFIG_ERROR fi # ensure specified program is installed local program="${agent%% *}" if [[ ! -x $program ]]; then local baseprog=$(basename $program) error "$(gettext "The download program %s is not installed.")" "$baseprog" plain "$(gettext "Aborting...")" exit 1 # $E_MISSING_PROGRAM fi echo "$agent" } download_file() { # download command local dlcmd=$1 # URL of the file local url=$2 # destination file local file=$3 # temporary download file, default to last component of the URL local dlfile="${url##*/}" # replace %o by the temporary dlfile if it exists if echo "$dlcmd" | grep -q "%o" ; then dlcmd=${dlcmd//\%o/\"$file.part\"} dlfile="$file.part" fi # add the URL, either in place of %u or at the end if echo "$dlcmd" | grep -q "%u" ; then dlcmd=${dlcmd//\%u/\"$url\"} else dlcmd="$dlcmd \"$url\"" fi local ret=0 eval "$dlcmd || ret=\$?" if (( ret )); then [[ ! -s $dlfile ]] && rm -f -- "$dlfile" return $ret fi # rename the temporary download file to the final destination if [[ $dlfile != $file ]]; then mv -f "$SRCDEST/$dlfile" "$SRCDEST/$file" fi } run_pacman() { local ret=0 if (( ! ASROOT )) && [[ $1 != "-T" ]] && sudo -l $PACMAN &>/dev/null; then sudo $PACMAN $PACMAN_OPTS "$@" || ret=$? else $PACMAN $PACMAN_OPTS "$@" || ret=$? fi return $ret } check_deps() { (( $# > 0 )) || return local ret=0 pmout=$(run_pacman -T "$@") ret=$? if (( ret == 127 )); then #unresolved deps echo "$pmout" elif (( ret )); then error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout" exit 1 fi } handle_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 (( $# == 0 )) && return $R_DEPS_SATISFIED local deplist="$*" if (( ! DEP_BIN )); then return $R_DEPS_MISSING fi if (( DEP_BIN )); then # install missing deps from binary packages (using pacman -S) msg "$(gettext "Installing missing dependencies...")" if ! run_pacman -S --asdeps $deplist; then error "$(gettext "'%s' failed to install missing dependencies.")" "$PACMAN" exit 1 # TODO: error code fi fi # we might need the new system environment # avoid triggering the ERR trap local restoretrap=$(trap -p ERR) trap - ERR source /etc/profile &>/dev/null eval $restoretrap return $R_DEPS_SATISFIED } resolve_deps() { # $pkgdeps is a GLOBAL variable, used by remove_deps() local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 local deplist="$(check_deps $*)" if [[ -z $deplist ]]; then return $R_DEPS_SATISFIED fi if handle_deps $deplist; then pkgdeps="$pkgdeps $deplist" # check deps again to make sure they were resolved deplist="$(check_deps $*)" [[ -z $deplist ]] && return $R_DEPS_SATISFIED elif (( DEP_BIN )); then error "$(gettext "Failed to install all missing dependencies.")" fi msg "$(gettext "Missing Dependencies:")" local dep for dep in $deplist; do msg2 "$dep" done return $R_DEPS_MISSING } # fix flyspray bug #5923 remove_deps() { # $pkgdeps is a GLOBAL variable, set by resolve_deps() (( ! RMDEPS )) && return [[ -z $pkgdeps ]] && return local dep depstrip deplist deplist="" for dep in $pkgdeps; do depstrip="${dep%%[<=>]*}" deplist="$deplist $depstrip" done msg "Removing installed dependencies..." # exit cleanly on failure to remove deps as package has been built successfully if ! run_pacman -Rns $deplist; then warning "$(gettext "Failed to remove installed dependencies.")" return 0 fi } download_sources() { msg "$(gettext "Retrieving Sources...")" pushd "$SRCDEST" &>/dev/null local netfile for netfile in "${source[@]}"; do local file=$(get_filename "$netfile") local url=$(get_url "$netfile") if [[ -f $startdir/$file ]]; then msg2 "$(gettext "Found %s in build dir")" "$file" rm -f "$srcdir/$file" ln -s "$startdir/$file" "$srcdir/" continue elif [[ -f $SRCDEST/$file ]]; then msg2 "$(gettext "Using cached copy of %s")" "$file" rm -f "$srcdir/$file" ln -s "$SRCDEST/$file" "$srcdir/" continue fi # if we get here, check to make sure it was a URL, else fail if [[ $file = $url ]]; then error "$(gettext "%s was not found in the build directory and is not a URL.")" "$file" exit 1 # $E_MISSING_FILE fi # find the client we should use for this URL local dlclient=$(get_downloadclient "$url") || exit $? msg2 "$(gettext "Downloading %s...")" "$file" # fix flyspray bug #3289 local ret=0 download_file "$dlclient" "$url" "$file" || ret=$? if (( ret )); then error "$(gettext "Failure while downloading %s")" "$file" plain "$(gettext "Aborting...")" exit 1 fi rm -f "$srcdir/$file" ln -s "$SRCDEST/$file" "$srcdir/" done popd &>/dev/null } generate_checksums() { msg "$(gettext "Generating checksums for source files...")" plain "" if [ ! $(type -p openssl) ]; then error "$(gettext "Cannot find openssl.")" exit 1 # $E_MISSING_PROGRAM fi local integ for integ in ${INTEGRITY_CHECK[@]}; do integ="${integ,,}" case "$integ" in md5|sha1|sha256|sha384|sha512) : ;; *) error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ" exit 1;; # $E_CONFIG_ERROR esac local ct=0 local numsrc=${#source[@]} echo -n "${integ}sums=(" local i local indent='' for (( i = 0; i < ${#integ} + 6; i++ )); do indent="$indent " done local netfile for netfile in "${source[@]}"; do local file="$(get_filename "$netfile")" if [[ ! -f $file ]] ; then if [[ ! -f $SRCDEST/$file ]] ; then error "$(gettext "Unable to find source file %s to generate checksum.")" "$file" plain "$(gettext "Aborting...")" exit 1 else file="$SRCDEST/$file" fi fi local sum="$(openssl dgst -${integ} "$file")" sum=${sum##* } (( ct )) && echo -n "$indent" echo -n "'$sum'" ct=$(($ct+1)) (( $ct < $numsrc )) && echo done echo ")" done } check_checksums() { (( ! ${#source[@]} )) && return 0 if [ ! $(type -p openssl) ]; then error "$(gettext "Cannot find openssl.")" exit 1 # $E_MISSING_PROGRAM fi local correlation=0 local integ required for integ in md5 sha1 sha256 sha384 sha512; do local integrity_sums=($(eval echo "\${${integ}sums[@]}")) if (( ${#integrity_sums[@]} == ${#source[@]} )); then msg "$(gettext "Validating source files with %s...")" "${integ}sums" correlation=1 local errors=0 local idx=0 local file for file in "${source[@]}"; do local found=1 file="$(get_filename "$file")" echo -n " $file ... " >&2 if [[ ! -f $file ]] ; then if [[ ! -f $SRCDEST/$file ]] ; then echo "$(gettext "NOT FOUND")" >&2 errors=1 found=0 else file="$SRCDEST/$file" fi fi if (( $found )) ; then local expectedsum="${integrity_sums[$idx],,}" local realsum="$(openssl dgst -${integ} "$file")" realsum="${realsum##* }" if [[ $expectedsum = $realsum ]]; then echo "$(gettext "Passed")" >&2 else echo "$(gettext "FAILED")" >&2 errors=1 fi fi idx=$((idx + 1)) done if (( errors )); then error "$(gettext "One or more files did not pass the validity check!")" exit 1 # TODO: error code fi elif (( ${#integrity_sums[@]} )); then error "$(gettext "Integrity checks (%s) differ in size from the source array.")" "$integ" exit 1 # TODO: error code fi done if (( ! correlation )); then if (( SKIPINTEG )); then warning "$(gettext "Integrity checks are missing.")" else error "$(gettext "Integrity checks are missing.")" exit 1 # TODO: error code fi fi } extract_sources() { msg "$(gettext "Extracting Sources...")" local netfile for netfile in "${source[@]}"; do file=$(get_filename "$netfile") if in_array "$file" ${noextract[@]}; then #skip source files in the noextract=() array # these are marked explicitly to NOT be extracted continue fi if [[ ! -f $file ]] ; then if [[ ! -f $SRCDEST/$file ]] ; then error "$(gettext "Unable to find source file %s for extraction.")" "$file" plain "$(gettext "Aborting...")" exit 1 else file="$SRCDEST/$file" fi fi # fix flyspray #6246 local file_type=$(file -bizL "$file") local ext=${file##*.} local cmd='' case "$file_type" in *application/x-tar*|*application/zip*|*application/x-zip*|*application/x-cpio*) cmd="bsdtar" ;; *application/x-gzip*) case "$ext" in gz|z|Z) cmd="gzip" ;; *) continue;; esac ;; *application/x-bzip*) case "$ext" in bz2|bz) cmd="bzip2" ;; *) continue;; esac ;; *application/x-xz*) case "$ext" in xz) cmd="xz" ;; *) continue;; esac ;; *) # Don't know what to use to extract this file, # skip to the next file continue;; esac local ret=0 msg2 "$(gettext "Extracting %s with %s")" "$file" "$cmd" if [[ $cmd = bsdtar ]]; then $cmd -xf "$file" || ret=? else rm -f "${file%.*}" $cmd -dcf "$file" > "${file%.*}" || ret=? fi if (( ret )); then error "$(gettext "Failed to extract %s")" "$file" plain "$(gettext "Aborting...")" exit 1 fi done if (( EUID == 0 )); then # change perms of all source files to root user & root group chown -R 0:0 "$srcdir" fi } error_function() { if [[ -p $logpipe ]]; then rm "$logpipe" fi # first exit all subshells, then print the error if (( ! BASH_SUBSHELL )); then plain "$(gettext "Aborting...")" remove_deps fi exit 2 # $E_BUILD_FAILED } run_function() { if [[ -z $1 ]]; then return 1 fi pkgfunc="$1" # clear user-specified makeflags if requested if [[ $(check_option makeflags) = "n" ]]; then MAKEFLAGS="" fi msg "$(gettext "Starting %s()...")" "$pkgfunc" cd "$srcdir" # ensure all necessary build variables are exported export CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST # save our shell options so pkgfunc() can't override what we need local shellopts=$(shopt -p) local ret=0 if (( LOGGING )); then BUILDLOG="${startdir}/${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-$pkgfunc.log" if [[ -f $BUILDLOG ]]; then local i=1 while true; do if [[ -f $BUILDLOG.$i ]]; then i=$(($i +1)) else break fi done mv "$BUILDLOG" "$BUILDLOG.$i" fi # ensure overridden package variables survive tee with split packages logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX") mknod "$logpipe" p exec 3>&1 tee "$BUILDLOG" < "$logpipe" & exec 1>"$logpipe" 2>"$logpipe" restoretrap=$(trap -p ERR) trap 'error_function' ERR $pkgfunc 2>&1 eval $restoretrap sync exec 1>&3 2>&3 3>&- rm "$logpipe" else restoretrap=$(trap -p ERR) trap 'error_function' ERR $pkgfunc 2>&1 eval $restoretrap fi # reset our shell options eval "$shellopts" } run_build() { # use distcc if it is requested (check buildenv and PKGBUILD opts) if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH" export DISTCC_HOSTS elif [[ $(check_option distcc) = "n" ]]; then # if it is not wanted, clear the makeflags too MAKEFLAGS="" fi # use ccache if it is requested (check buildenv and PKGBUILD opts) if [[ $(check_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; then [[ -d /usr/lib/ccache/bin ]] && export PATH="/usr/lib/ccache/bin:$PATH" fi run_function "build" } run_package() { if [[ -z $1 ]]; then pkgfunc="package" else pkgfunc="package_$1" fi run_function "$pkgfunc" } tidy_install() { cd "$pkgdir" msg "$(gettext "Tidying install...")" if [[ $(check_option docs) = "n" && -n ${DOC_DIRS[*]} ]]; then msg2 "$(gettext "Removing doc files...")" rm -rf ${DOC_DIRS[@]} fi if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then msg2 "$(gettext "Purging other files...")" local pt for pt in "${PURGE_TARGETS[@]}"; do if [[ ${pt} = ${pt//\/} ]]; then find . -type f -name "${pt}" -exec rm -f -- '{}' \; else rm -f ${pt} fi done fi if [[ $(check_option zipman) = "y" && -n ${MAN_DIRS[*]} ]]; then msg2 "$(gettext "Compressing man and info pages...")" local manpage ext file link hardlinks hl find ${MAN_DIRS[@]} -type f 2>/dev/null | while read manpage ; do ext="${manpage##*.}" file="${manpage##*/}" if [[ $ext != gz && $ext != bz2 ]]; then # update symlinks to this manpage find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null | while read link ; do rm -f "$link" ln -sf "${file}.gz" "${link}.gz" done # check file still exists (potentially already compressed due to hardlink) if [[ -f ${manpage} ]]; then # find hard links and remove them # the '|| true' part keeps the script from bailing if find returned an # error, such as when one of the man directories doesn't exist hardlinks="$(find ${MAN_DIRS[@]} \! -name "$file" -samefile "$manpage" 2>/dev/null)" || true for hl in ${hardlinks}; do rm -f "${hl}"; done # compress the original gzip -9 "$manpage" # recreate hard links removed earlier for hl in ${hardlinks}; do ln "${manpage}.gz" "${hl}.gz" chmod 644 ${hl}.gz done fi fi done fi if [[ $(check_option strip) = y && -n ${STRIP_DIRS[*]} ]]; then msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")" local binary find ${STRIP_DIRS[@]} -type f -writable 2>/dev/null | while read binary ; do case "$(file -biz "$binary")" in *compressed-encoding*) # Skip compressed binaries ;; *application/x-sharedlib*) # Libraries (.so) /usr/bin/strip $STRIP_SHARED "$binary";; *application/x-archive*) # Libraries (.a) /usr/bin/strip $STRIP_STATIC "$binary";; *application/x-executable*) # Binaries /usr/bin/strip $STRIP_BINARIES "$binary";; esac done fi if [[ $(check_option libtool) = "n" ]]; then msg2 "$(gettext "Removing libtool .la files...")" find . ! -type d -name "*.la" -exec rm -f -- '{}' \; fi if [[ $(check_option emptydirs) = "n" ]]; then msg2 "$(gettext "Removing empty directories...")" find . -depth -type d -empty -delete fi } write_pkginfo() { local builddate=$(date -u "+%s") if [[ -n $PACKAGER ]]; then local packager="$PACKAGER" else local packager="Unknown Packager" fi local size="$(du -sk)" size="$(( ${size%%[^0-9]*} * 1024 ))" msg2 "$(gettext "Generating .PKGINFO file...")" echo "# Generated by makepkg $myver" >.PKGINFO if (( INFAKEROOT )); then echo "# using $(fakeroot -v)" >>.PKGINFO fi echo "# $(LC_ALL=C date -u)" >>.PKGINFO echo "pkgname = $1" >>.PKGINFO (( SPLITPKG )) && echo pkgbase = $pkgbase >>.PKGINFO echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO echo "pkgdesc = $pkgdesc" >>.PKGINFO echo "url = $url" >>.PKGINFO echo "builddate = $builddate" >>.PKGINFO echo "packager = $packager" >>.PKGINFO echo "size = $size" >>.PKGINFO echo "arch = $PKGARCH" >>.PKGINFO if [[ $(check_option force) = "y" ]]; then echo "force = true" >> .PKGINFO fi local it for it in "${license[@]}"; do echo "license = $it" >>.PKGINFO done for it in "${replaces[@]}"; do echo "replaces = $it" >>.PKGINFO done for it in "${groups[@]}"; do echo "group = $it" >>.PKGINFO done for it in "${depends[@]}"; do echo "depend = $it" >>.PKGINFO done for it in "${optdepends[@]}"; do echo "optdepend = $it" >>.PKGINFO done for it in "${conflicts[@]}"; do echo "conflict = $it" >>.PKGINFO done for it in "${provides[@]}"; do echo "provides = $it" >>.PKGINFO done for it in "${backup[@]}"; do echo "backup = $it" >>.PKGINFO done for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" if [[ $ret != "?" ]]; then if [[ $ret = y ]]; then echo "makepkgopt = $it" >>.PKGINFO else echo "makepkgopt = !$it" >>.PKGINFO fi fi done # TODO maybe remove this at some point # warn if license array is not present or empty if [[ -z $license ]]; then warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT" plain "$(gettext "Example for GPL\'ed software: license=('GPL').")" fi } check_package() { cd "$pkgdir" # check existence of backup files local file for file in "${backup[@]}"; do if [[ ! -f $file ]]; then warning "$(gettext "Invalid backup entry : %s")" "$file" fi done # check for references to the build directory if grep -R "${srcdir}" "${pkgdir}" &>/dev/null; then warning "$(gettext "Package contains reference to %s")" "\$srcdir" fi } create_package() { if [[ ! -d $pkgdir ]]; then error "$(gettext "Missing pkg/ directory.")" plain "$(gettext "Aborting...")" exit 1 # $E_MISSING_PKGDIR fi check_package cd "$pkgdir" msg "$(gettext "Creating package...")" if [[ -z $1 ]]; then nameofpkg="$pkgname" else nameofpkg="$1" fi if [[ $arch = "any" ]]; then PKGARCH="any" else PKGARCH=$CARCH fi write_pkginfo $nameofpkg local comp_files=".PKGINFO" # check for an install script if [[ -n $install ]]; then msg2 "$(gettext "Adding install script...")" cp "$startdir/$install" .INSTALL comp_files="$comp_files .INSTALL" fi # do we have a changelog? if [[ -n $changelog ]]; then msg2 "$(gettext "Adding package changelog...")" cp "$startdir/$changelog" .CHANGELOG comp_files="$comp_files .CHANGELOG" fi # tar it up msg2 "$(gettext "Compressing package...")" case "$PKGEXT" in *tar.gz) EXT=${PKGEXT%.gz} ;; *tar.bz2) EXT=${PKGEXT%.bz2} ;; *tar.xz) EXT=${PKGEXT%.xz} ;; *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$PKGEXT" ; EXT=$PKGEXT ;; esac local tar_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${EXT}" local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${PKGEXT}" local ret=0 # when fileglobbing, we want * in an empty directory to expand to # the null string rather than itself shopt -s nullglob bsdtar -cf - $comp_files * > "$tar_file" || ret=$? shopt -u nullglob if (( ! ret )); then case "$PKGEXT" in *tar.gz) gzip -f -n "$tar_file" ;; *tar.bz2) bzip2 -f "$tar_file" ;; *tar.xz) xz -z -f "$tar_file" ;; esac ret=$? fi if (( ret )); then error "$(gettext "Failed to create package file.")" exit 1 # TODO: error code fi if (( ! ret )) && [[ "$PKGDEST" != "${startdir}" ]]; then ln -sf "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}" ret=$? fi if (( ret )); then warning "$(gettext "Failed to create symlink to package file.")" fi } create_srcpackage() { cd "$startdir" # Get back to our src directory so we can begin with sources. mkdir -p "$srcdir" chmod a-s "$srcdir" cd "$srcdir" download_sources # We can only check checksums if we have all files. check_checksums cd "$startdir" msg "$(gettext "Creating source package...")" local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)" mkdir "${srclinks}"/${pkgbase} msg2 "$(gettext "Adding %s...")" "$BUILDSCRIPT" ln -s "${BUILDFILE}" "${srclinks}/${pkgbase}/${BUILDSCRIPT}" if [[ -n $install ]]; then if [[ -f $install ]]; then msg2 "$(gettext "Adding install script...")" ln -s "${startdir}/$install" "${srclinks}/${pkgbase}/" else error "$(gettext "Install scriptlet (%s) does not exist.")" "$install" fi fi if [[ -n $changelog ]]; then if [[ -f $changelog ]]; then msg2 "$(gettext "Adding package changelog...")" ln -s "${startdir}/$changelog" "${srclinks}/${pkgbase}/" else error "$(gettext "Changelog file (%s) does not exist.")" "$changelog" fi fi local netfile for netfile in "${source[@]}"; do local file=$(get_filename "$netfile") if [[ -f $netfile ]]; then msg2 "$(gettext "Adding %s...")" "$netfile" ln -s "${startdir}/$netfile" "${srclinks}/${pkgbase}" elif (( SOURCEONLY == 2 )) && [[ -f $SRCDEST/$file ]]; then msg2 "$(gettext "Adding %s...")" "$file" ln -s "$SRCDEST/$file" "${srclinks}/${pkgbase}/" fi done local TAR_OPT case "$SRCEXT" in *tar.gz) TAR_OPT="z" ;; *tar.bz2) TAR_OPT="j" ;; *tar.xz) TAR_OPT="J" ;; *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$SRCEXT" ;; esac local pkg_file="$SRCPKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT}" # tar it up msg2 "$(gettext "Compressing source package...")" cd "${srclinks}" if ! bsdtar -c${TAR_OPT}Lf "$pkg_file" ${pkgbase}; then error "$(gettext "Failed to create source package file.")" exit 1 # TODO: error code fi cd "${startdir}" rm -rf "${srclinks}" } install_package() { (( ! INSTALL )) && return if (( ! SPLITPKG )); then msg "$(gettext "Installing package %s with %s -U...")" "$pkgname" "$PACMAN" else msg "$(gettext "Installing %s package group with %s -U...")" "$pkgbase" "$PACMAN" fi local pkglist for pkg in ${pkgname[@]}; do if [[ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} ]]; then pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" else pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT}" fi done if ! run_pacman -U $pkglist; then warning "$(gettext "Failed to install built package(s).")" return 0 fi } check_sanity() { # check for no-no's in the build script if [[ -z $pkgname ]]; then error "$(gettext "%s is not allowed to be empty.")" "pkgname" return 1 fi if [[ -z $pkgver ]]; then error "$(gettext "%s is not allowed to be empty.")" "pkgver" return 1 fi if [[ -z $pkgrel ]]; then error "$(gettext "%s is not allowed to be empty.")" "pkgrel" return 1 fi local name for name in "${pkgname[@]}"; do if [[ ${name:0:1} = "-" ]]; then error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname" return 1 fi done if [[ ${pkgbase:0:1} = "-" ]]; then error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase" return 1 fi if [[ $pkgver != ${pkgver//-/} ]]; then error "$(gettext "%s is not allowed to contain hyphens.")" "pkgver" return 1 fi if [[ $pkgrel != ${pkgrel//-/} ]]; then error "$(gettext "%s is not allowed to contain hyphens.")" "pkgrel" return 1 fi if [[ $arch != 'any' ]]; then if ! in_array $CARCH ${arch[@]}; then if (( ! IGNOREARCH )); then error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" plain "$(gettext "such as arch=('%s').")" "$CARCH" return 1 fi fi fi local provide for provide in ${provides[@]}; do if [[ $provide != ${provide//</} || $provide != ${provide//>/} ]]; then error "$(gettext "Provides array cannot contain comparison (< or >) operators.")" return 1 fi done local file for file in "${backup[@]}"; do if [[ ${file:0:1} = "/" ]]; then error "$(gettext "Invalid backup entry : %s")" "$file" return 1 fi done local optdepend for optdepend in "${optdepends[@]}"; do pkg=${optdepend%%:*} if [[ ! $pkg =~ ^[[:alnum:]\>\<\=\.\+\_\-]*$ ]]; then error "$(gettext "Invalid syntax for optdepend : '%s'")" "$optdepend" fi done if [[ $install && ! -f $install ]]; then error "$(gettext "Install scriptlet (%s) does not exist.")" "$install" return 1 fi if [[ -n $changelog && ! -f $changelog ]]; then error "$(gettext "Changelog file (%s) does not exist.")" "$changelog" return 1 fi local valid_options=1 local opt known kopt for opt in ${options[@]}; do known=0 # check if option matches a known option or its inverse for kopt in ${packaging_options[@]} ${other_options[@]}; do if [[ ${opt} = ${kopt} || ${opt} = "!${kopt}" ]]; then known=1 fi done if (( ! known )); then error "$(gettext "options array contains unknown option '%s'")" "$opt" valid_options=0 fi done if (( ! valid_options )); then return 1 fi if (( ${#pkgname[@]} > 1 )); then for pkg in ${pkgname[@]}; do if [ "$(type -t package_${pkg})" != "function" ]; then error "$(gettext "missing package function for split package '%s'")" "$pkg" return 1 fi done fi if [[ -n "${PKGLIST[@]}" ]]; then for pkg in ${PKGLIST[@]}; do if ! in_array $pkg ${pkgname[@]}; then error "$(gettext "requested package %s is not provided in %s")" "$pkg" "$BUILDSCRIPT" return 1 fi done fi return 0 } devel_check() { newpkgver="" # Do not update pkgver if --holdver is set, when building a source package, repackaging, # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w) if (( HOLDVER || SOURCEONLY || REPKG )) \ || [[ ! -f $BUILDFILE || ! -w $BUILDFILE ]]; then return fi if [[ -z $FORCE_VER ]]; then # Check if this is a svn/cvs/etc PKGBUILD; set $newpkgver if so. # This will only be used on the first call to makepkg; subsequent # calls to makepkg via fakeroot will explicitly pass the version # number to avoid having to determine the version number twice. # Also do a brief check to make sure we have the VCS tool available. oldpkgver=$pkgver if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then [ $(type -p darcs) ] || return 0 msg "$(gettext "Determining latest darcs revision...")" newpkgver=$(date +%Y%m%d) elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then [ $(type -p cvs) ] || return 0 msg "$(gettext "Determining latest cvs revision...")" newpkgver=$(date +%Y%m%d) elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then [ $(type -p git) ] || return 0 msg "$(gettext "Determining latest git revision...")" newpkgver=$(date +%Y%m%d) elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then [ $(type -p svn) ] || return 0 msg "$(gettext "Determining latest svn revision...")" newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p') elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then [ $(type -p bzr) ] || return 0 msg "$(gettext "Determining latest bzr revision...")" newpkgver=$(bzr revno ${_bzrtrunk}) elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then [ $(type -p hg) ] || return 0 msg "$(gettext "Determining latest hg revision...")" if [[ -d ./src/$_hgrepo ]] ; then cd ./src/$_hgrepo hg pull hg update else [[ ! -d ./src/ ]] && mkdir ./src/ hg clone $_hgroot/$_hgrepo ./src/$_hgrepo cd ./src/$_hgrepo fi newpkgver=$(hg tip --template "{rev}") cd ../../ fi if [[ -n $newpkgver ]]; then msg2 "$(gettext "Version found: %s")" "$newpkgver" fi else # Version number retrieved from fakeroot->makepkg argument newpkgver=$FORCE_VER fi } devel_update() { # This is lame, but if we're wanting to use an updated pkgver for # retrieving svn/cvs/etc sources, we'll update the PKGBUILD with # the new pkgver and then re-source it. This is the most robust # method for dealing with PKGBUILDs that use, e.g.: # # pkgver=23 # ... # _foo=pkgver # if [[ -n $newpkgver ]]; then if [[ $newpkgver != $pkgver ]]; then if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then @SEDINPLACE@ "s/^pkgver=[^ ]*/pkgver=$newpkgver/" "$BUILDFILE" @SEDINPLACE@ "s/^pkgrel=[^ ]*/pkgrel=1/" "$BUILDFILE" source "$BUILDFILE" fi fi fi } backup_package_variables() { for var in ${splitpkg_overrides[@]}; do indirect="${var}_backup" eval "${indirect}=(\"\${$var[@]}\")" done } restore_package_variables() { for var in ${splitpkg_overrides[@]}; do indirect="${var}_backup" if [[ -n ${!indirect} ]]; then eval "${var}=(\"\${$indirect[@]}\")" else unset ${var} fi done } # getopt like parser parse_options() { local short_options=$1; shift; local long_options=$1; shift; local ret=0; local unused_options="" while [[ -n $1 ]]; do if [[ ${1:0:2} = '--' ]]; then if [[ -n ${1:2} ]]; then local match="" for i in ${long_options//,/ }; do if [[ ${1:2} = ${i//:} ]]; then match=$i break fi done if [[ -n $match ]]; then if [[ ${1:2} = $match ]]; then printf ' %s' "$1" else if [[ -n $2 ]]; then printf ' %s' "$1" shift printf " '%s'" "$1" else echo "makepkg: option '$1' $(gettext "requires an argument")" >&2 ret=1 fi fi else echo "makepkg: $(gettext "unrecognized option") '$1'" >&2 ret=1 fi else shift break fi elif [[ ${1:0:1} = '-' ]]; then for ((i=1; i<${#1}; i++)); do if [[ $short_options =~ ${1:i:1} ]]; then if [[ $short_options =~ "${1:i:1}:" ]]; then if [[ -n ${1:$i+1} ]]; then printf ' -%s' "${1:i:1}" printf " '%s'" "${1:$i+1}" else if [[ -n $2 ]]; then printf ' -%s' "${1:i:1}" shift printf " '%s'" "${1}" else echo "makepkg: option $(gettext "requires an argument") -- '${1:i:1}'" >&2 ret=1 fi fi break else printf ' -%s' "${1:i:1}" fi else echo "makepkg: $(gettext "invalid option") -- '${1:i:1}'" >&2 ret=1 fi done else unused_options="${unused_options} '$1'" fi shift done printf " --" if [[ -n $unused_options ]]; then for i in ${unused_options[@]}; do printf ' %s' "$i" done fi if [[ -n $1 ]]; then while [[ -n $1 ]]; do printf " '%s'" "${1}" shift done fi printf "\n" return $ret } usage() { printf "makepkg (pacman) %s\n" "$myver" echo printf "$(gettext "Usage: %s [options]")\n" "$0" echo echo "$(gettext "Options:")" printf "$(gettext " -A, --ignorearch Ignore incomplete arch field in %s")\n" "$BUILDSCRIPT" echo "$(gettext " -c, --clean Clean up work files after build")" echo "$(gettext " -C, --cleancache Clean up source files from the cache")" echo "$(gettext " -d, --nodeps Skip all dependency checks")" echo "$(gettext " -e, --noextract Do not extract source files (use existing src/ dir)")" echo "$(gettext " -f, --force Overwrite existing package")" echo "$(gettext " -g, --geninteg Generate integrity checks for source files")" echo "$(gettext " -h, --help This help")" echo "$(gettext " -i, --install Install package after successful build")" echo "$(gettext " -L, --log Log package build process")" echo "$(gettext " -m, --nocolor Disable colorized output messages")" echo "$(gettext " -o, --nobuild Download and extract files only")" printf "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" echo "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")" echo "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")" echo "$(gettext " -s, --syncdeps Install missing dependencies with pacman")" echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")" echo "$(gettext " --asroot Allow makepkg to run as root user")" printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")" echo "$(gettext " --pkg <list> Only build listed packages from a split package")" echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" echo echo "$(gettext "These options can be passed to pacman:")" echo echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")" echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")" echo printf "$(gettext "If -p is not specified, makepkg will look for '%s'")\n" "$BUILDSCRIPT" echo } version() { printf "makepkg (pacman) %s\n" "$myver" printf "$(gettext "\ Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org>.\n\ Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\ This is free software; see the source for copying conditions.\n\ There is NO WARRANTY, to the extent permitted by law.\n")" } # PROGRAM START # determine whether we have gettext; make it a no-op if we do not if [ ! $(type -t gettext) ]; then gettext() { echo "$@" } fi ARGLIST=("$@") # Parse Command Line Options. OPT_SHORT="AcCdefFghiLmop:rRsV" OPT_LONG="allsource,asroot,ignorearch,clean,cleancache,nodeps" OPT_LONG="$OPT_LONG,noextract,force,forcever:,geninteg,help,holdver" OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,pkg:,rmdeps,repackage,skipinteg" OPT_LONG="$OPT_LONG,source,syncdeps,version,config:" # Pacman Options OPT_LONG="$OPT_LONG,noconfirm,noprogressbar" OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')" if echo "$OPT_TEMP" | grep -q 'PARSE_OPTIONS FAILED'; then # This is a small hack to stop the script bailing with 'set -e' echo; usage; exit 1 # E_INVALID_OPTION; fi eval set -- "$OPT_TEMP" unset OPT_SHORT OPT_LONG OPT_TEMP while true; do case "$1" in # Pacman Options --noconfirm) PACMAN_OPTS="$PACMAN_OPTS --noconfirm" ;; --noprogressbar) PACMAN_OPTS="$PACMAN_OPTS --noprogressbar" ;; # Makepkg Options --allsource) SOURCEONLY=2 ;; --asroot) ASROOT=1 ;; -A|--ignorearch) IGNOREARCH=1 ;; -c|--clean) CLEANUP=1 ;; -C|--cleancache) CLEANCACHE=1 ;; --config) shift; MAKEPKG_CONF=$1 ;; -d|--nodeps) NODEPS=1 ;; -e|--noextract) NOEXTRACT=1 ;; -f|--force) FORCE=1 ;; #hidden opt used by fakeroot call for svn/cvs/etc PKGBUILDs to set pkgver --forcever) shift; FORCE_VER=$1;; -F) INFAKEROOT=1 ;; -g|--geninteg) GENINTEG=1 ;; --holdver) HOLDVER=1 ;; -i|--install) INSTALL=1 ;; -L|--log) LOGGING=1 ;; -m|--nocolor) USE_COLOR='n' ;; -o|--nobuild) NOBUILD=1 ;; -p) shift; BUILDFILE=$1 ;; --pkg) shift; PKGLIST=$1 ;; -r|--rmdeps) RMDEPS=1 ;; -R|--repackage) REPKG=1 ;; --skipinteg) SKIPINTEG=1 ;; --source) SOURCEONLY=1 ;; -s|--syncdeps) DEP_BIN=1 ;; -h|--help) usage; exit 0 ;; # E_OK -V|--version) version; exit 0 ;; # E_OK --) OPT_IND=0; shift; break;; *) usage; exit 1 ;; # E_INVALID_OPTION esac shift done #preserve environment variables _PKGDEST=${PKGDEST} _SRCDEST=${SRCDEST} _SRCPKGDEST=${SRCPKGDEST} # default config is makepkg.conf MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} # Source the config file; fail if it is not found if [[ -r $MAKEPKG_CONF ]]; then source "$MAKEPKG_CONF" else error "$(gettext "%s not found.")" "$MAKEPKG_CONF" plain "$(gettext "Aborting...")" exit 1 # $E_CONFIG_ERROR fi # Source user-specific makepkg.conf overrides if [[ -r ~/.makepkg.conf ]]; then source ~/.makepkg.conf fi # set pacman command if not already defined PACMAN=${PACMAN:-pacman} # check if messages are to be printed using color unset ALL_OFF BOLD BLUE GREEN RED YELLOW if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then ALL_OFF="$(tput sgr0)" BOLD="$(tput bold)" BLUE="${BOLD}$(tput setaf 4)" GREEN="${BOLD}$(tput setaf 2)" RED="${BOLD}$(tput setaf 1)" YELLOW="${BOLD}$(tput setaf 3)" fi readonly ALL_OFF BOLD BLUE GREEN RED YELLOW # override settings with an environment variable for batch processing PKGDEST=${_PKGDEST:-$PKGDEST} PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined if [[ ! -w $PKGDEST ]]; then error "$(gettext "You do not have write permission to store packages in %s.")" "$PKGDEST" plain "$(gettext "Aborting...")" exit 1 fi SRCDEST=${_SRCDEST:-$SRCDEST} SRCDEST=${SRCDEST:-$startdir} #default to $startdir if undefined if [[ ! -w $SRCDEST ]] ; then error "$(gettext "You do not have write permission to store downloads in %s.")" "$SRCDEST" plain "$(gettext "Aborting...")" exit 1 fi SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST} SRCPKGDEST=${SRCPKGDEST:-$PKGDEST} #default to $PKGDEST if undefined if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then # The '\\0' is here to prevent gettext from thinking --holdver is an option error "$(gettext "\\0--holdver and --forcever cannot both be specified" )" exit 1 fi if (( CLEANCACHE )); then #fix flyspray feature request #5223 if [[ -n $SRCDEST && $SRCDEST != $startdir ]]; then msg "$(gettext "Cleaning up ALL files from %s.")" "$SRCDEST" echo -n "$(gettext " Are you sure you wish to do this? ")" echo -n "$(gettext "[y/N]")" read answer answer="${answer^^}" if [[ $answer = $(gettext YES) || $answer = $(gettext Y) ]]; then rm "$SRCDEST"/* if (( $? )); then error "$(gettext "Problem removing files; you may not have correct permissions in %s")" "$SRCDEST" exit 1 else # removal worked msg "$(gettext "Source cache cleaned.")" exit 0 fi else # answer = no msg "$(gettext "No files have been removed.")" exit 0 fi else # $SRCDEST is $startdir, two possibilities error "$(gettext "Source destination must be defined in %s.")" "$MAKEPKG_CONF" plain "$(gettext "In addition, please run makepkg -C outside of your cache directory.")" exit 1 fi fi if (( ! INFAKEROOT )); then if (( EUID == 0 && ! ASROOT )); then # Warn those who like to live dangerously. error "$(gettext "Running makepkg as root is a BAD idea and can cause")" plain "$(gettext "permanent, catastrophic damage to your system. If you")" plain "$(gettext "wish to run as root, please use the --asroot option.")" exit 1 # $E_USER_ABORT elif (( EUID > 0 && ASROOT )); then # Warn those who try to use the --asroot option when they are not root error "$(gettext "The --asroot option is meant for the root user only.")" plain "$(gettext "Please rerun makepkg without the --asroot flag.")" exit 1 # $E_USER_ABORT elif [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then if [ ! $(type -p fakeroot) ]; then error "$(gettext "Fakeroot must be installed if using the 'fakeroot' option")" plain "$(gettext "in the BUILDENV array in %s.")" "$MAKEPKG_CONF" exit 1 fi elif (( EUID > 0 )); then warning "$(gettext "Running makepkg as an unprivileged user will result in non-root")" plain "$(gettext "ownership of the packaged files. Try using the fakeroot environment by")" plain "$(gettext "placing 'fakeroot' in the BUILDENV array in %s.")" "$MAKEPKG_CONF" sleep 1 fi else if [[ -z $FAKEROOTKEY ]]; then error "$(gettext "Do not use the '-F' option. This option is only for use by makepkg.")" exit 1 # TODO: error code fi fi # check for sudo if we will need it during makepkg execution if (( ! ASROOT && ( DEP_BIN || RMDEPS || INSTALL ) )); then if [ ! "$(type -p sudo)" ]; then error "$(gettext "Cannot find the sudo binary! Is sudo installed?")" plain "$(gettext "Missing dependencies cannot be installed or removed as a normal user")" plain "$(gettext "without sudo; install and configure sudo to auto-resolve dependencies.")" exit 1 fi fi unset pkgname pkgbase pkgver pkgrel pkgdesc url license groups provides unset md5sums replaces depends conflicts backup source install changelog build unset makedepends optdepends options noextract BUILDFILE=${BUILDFILE:-$BUILDSCRIPT} if [[ ! -f $BUILDFILE ]]; then if [[ -t 0 ]]; then error "$(gettext "%s does not exist.")" "$BUILDFILE" exit 1 else # PKGBUILD passed through a pipe BUILDFILE=/dev/stdin source "$BUILDFILE" fi else crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true) if [[ -n $crlftest ]]; then error "$(gettext "%s contains CRLF characters and cannot be sourced.")" "$BUILDFILE" exit 1 fi if [[ ${BUILDFILE:0:1} != "/" ]]; then BUILDFILE="$startdir/$BUILDFILE" fi source "$BUILDFILE" fi if (( GENINTEG )); then mkdir -p "$srcdir" chmod a-s "$srcdir" cd "$srcdir" download_sources generate_checksums exit 0 # $E_OK fi # check the PKGBUILD for some basic requirements check_sanity || exit 1 # We need to run devel_update regardless of whether we are in the fakeroot # build process so that if the user runs makepkg --forcever manually, we # 1) output the correct pkgver, and 2) use the correct filename when # checking if the package file already exists - fixes FS #9194 devel_check devel_update if (( ${#pkgname[@]} > 1 )); then SPLITPKG=1 fi # test for available PKGBUILD functions # The exclamation mark is required here to avoid triggering the ERR trap when # a tested function does not exist. if [[ $(! type -t build) = "function" ]]; then BUILDFUNC=1 fi if [ "$(type -t package)" = "function" ]; then PKGFUNC=1 elif [ $SPLITPKG -eq 0 -a "$(type -t package_${pkgname})" = "function" ]; then SPLITPKG=1 fi pkgbase=${pkgbase:-${pkgname[0]}} if [[ -n "${PKGLIST[@]}" ]]; then unset pkgname pkgname="${PKGLIST[@]}" fi if (( ! SPLITPKG )); then if [[ -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} \ || -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-any${PKGEXT} ]] \ && ! (( FORCE || SOURCEONLY || NOBUILD )); then if (( INSTALL )); then warning "$(gettext "A package has already been built, installing existing package...")" install_package exit $? else error "$(gettext "A package has already been built. (use -f to overwrite)")" exit 1 fi fi else allpkgbuilt=1 somepkgbuilt=0 for pkg in ${pkgname[@]}; do if [[ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} \ || -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT} ]]; then somepkgbuilt=1 else allpkgbuilt=0 fi done if ! (( FORCE || SOURCEONLY || NOBUILD )); then if (( allpkgbuilt )); then if (( INSTALL )); then warning "$(gettext "The package group has already been built, installing existing packages...")" install_package exit $? else error "$(gettext "The package group has already been built. (use -f to overwrite)")" exit 1 fi fi if (( somepkgbuilt )); then error "$(gettext "Part of the package group has already been built. (use -f to overwrite)")" exit 1 fi fi unset allpkgbuilt somepkgbuilt fi # Run the bare minimum in fakeroot if (( INFAKEROOT )); then if (( ! SPLITPKG )); then if (( ! PKGFUNC )); then if (( ! REPKG )); then if (( BUILDFUNC )); then run_build tidy_install fi else warning "$(gettext "Repackaging without the use of a package() function is deprecated.")" plain "$(gettext "File permissions may not be preserved.")" fi else run_package tidy_install fi create_package else for pkg in ${pkgname[@]}; do pkgdir="$pkgdir/$pkg" mkdir -p "$pkgdir" chmod a-s "$pkgdir" backup_package_variables run_package $pkg tidy_install create_package $pkg restore_package_variables pkgdir="${pkgdir%/*}" done fi msg "$(gettext "Leaving fakeroot environment.")" exit 0 # $E_OK fi msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" # if we are creating a source-only package, go no further if (( SOURCEONLY )); then if [[ -f $SRCPKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT} ]] \ && (( ! FORCE )); then error "$(gettext "A source package has already been built. (use -f to overwrite)")" exit 1 fi create_srcpackage msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))" exit 0 fi # fix flyspray bug #5973 if (( NODEPS || NOBUILD || REPKG )); then # no warning message needed for nobuild, repkg if (( NODEPS )); then warning "$(gettext "Skipping dependency checks.")" fi elif [ $(type -p "${PACMAN%% *}") ]; then unset pkgdeps # Set by resolve_deps() and used by remove_deps() deperr=0 msg "$(gettext "Checking Runtime Dependencies...")" resolve_deps ${depends[@]} || deperr=1 msg "$(gettext "Checking Buildtime Dependencies...")" resolve_deps ${makedepends[@]} || deperr=1 if (( deperr )); then error "$(gettext "Could not resolve all dependencies.")" exit 1 fi else warning "$(gettext "%s was not found in PATH; skipping dependency checks.")" "${PACMAN%% *}" fi # ensure we have a sane umask set umask 0022 # get back to our src directory so we can begin with sources mkdir -p "$srcdir" chmod a-s "$srcdir" cd "$srcdir" if (( NOEXTRACT )); then warning "$(gettext "Skipping source retrieval -- using existing src/ tree")" warning "$(gettext "Skipping source integrity checks -- using existing src/ tree")" warning "$(gettext "Skipping source extraction -- using existing src/ tree")" if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then error "$(gettext "The source directory is empty, there is nothing to build!")" plain "$(gettext "Aborting...")" exit 1 fi elif (( REPKG )); then if (( ! PKGFUNC && ! SPLITPKG )) \ && [[ ! -d $pkgdir || -z $(ls "$pkgdir" 2>/dev/null) ]]; then error "$(gettext "The package directory is empty, there is nothing to repackage!")" plain "$(gettext "Aborting...")" exit 1 fi else download_sources check_checksums extract_sources fi if (( NOBUILD )); then msg "$(gettext "Sources are ready.")" exit 0 #E_OK else # check for existing pkg directory; don't remove if we are repackaging if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then msg "$(gettext "Removing existing pkg/ directory...")" rm -rf "$pkgdir" fi mkdir -p "$pkgdir" chmod a-s "$pkgdir" cd "$startdir" # if we are root or if fakeroot is not enabled, then we don't use it if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then if (( ! REPKG )); then devel_update (( BUILDFUNC )) && run_build fi if (( ! SPLITPKG )); then if (( PKGFUNC )); then run_package tidy_install else if (( ! REPKG )); then tidy_install else warning "$(gettext "Repackaging without the use of a package() function is deprecated.")" plain "$(gettext "File permissions may not be preserved.")" fi fi create_package else for pkg in ${pkgname[@]}; do pkgdir="$pkgdir/$pkg" mkdir -p "$pkgdir" chmod a-s "$pkgdir" backup_package_variables run_package $pkg tidy_install create_package $pkg restore_package_variables pkgdir="${pkgdir%/*}" done fi else if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then devel_update (( BUILDFUNC )) && run_build cd "$startdir" fi msg "$(gettext "Entering fakeroot environment...")" if [[ -n $newpkgver ]]; then fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $? else fakeroot -- $0 -F "${ARGLIST[@]}" || exit $? fi fi fi msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" install_package exit 0 #E_OK # vim: set ts=2 sw=2 noet: