#!/usr/bin/env bash
#
#   makepkg - make packages compatible for use with pacman
#   Generated from makepkg.sh.in; do not edit by hand.
#
#   Copyright (c) 2006-2016 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:
#   awk, bsdtar (libarchive), bzip2, coreutils, file, find (findutils),
#   gettext, gpg, grep, gzip, openssl, sed, tput (ncurses), xz

# gettext initialization
export TEXTDOMAIN='pacman-scripts'
export TEXTDOMAINDIR='/usr/share/locale'

# file -i does not work on Mac OSX unless legacy mode is set
export COMMAND_MODE='legacy'
# Ensure CDPATH doesn't screw with our cd calls
unset CDPATH
# Ensure GREP_OPTIONS doesn't screw with our grep calls
unset GREP_OPTIONS

declare -r makepkg_version='5.0.1'
declare -r confdir='/etc'
declare -r BUILDSCRIPT='PKGBUILD'
declare -r startdir="$PWD"

LIBRARY=${LIBRARY:-'/usr/share/makepkg'}

build_options=('ccache' 'distcc' 'buildflags' 'makeflags')
splitpkg_overrides=('pkgdesc' 'arch' 'url' 'license' 'groups' 'depends'
                    'optdepends' 'provides' 'conflicts' 'replaces' 'backup'
                    'options' 'install' 'changelog')
readonly -a build_options splitpkg_overrides

known_hash_algos=('md5' 'sha1' 'sha224' 'sha256' 'sha384' 'sha512' 'whirlpool')

# Options
ASDEPS=0
BUILDFUNC=0
CHECKFUNC=0
CLEANBUILD=0
CLEANUP=0
DEP_BIN=0
FORCE=0
GENINTEG=0
HOLDVER=0
IGNOREARCH=0
INSTALL=0
LOGGING=0
NEEDED=0
NOARCHIVE=0
NOBUILD=0
NODEPS=0
NOEXTRACT=0
PKGFUNC=0
PKGVERFUNC=0
PREPAREFUNC=0
REPKG=0
RMDEPS=0
SKIPCHECKSUMS=0
SKIPPGPCHECK=0
SIGNPKG=''
SPLITPKG=0
SOURCEONLY=0
VERIFYSOURCE=0

PACMAN_OPTS=

shopt -s extglob

if [[ -n "$MSYSTEM" ]]; then
  readonly -a UTILS_NAME=('bsdtar'
                          'bzip2'
                          'bzr'
                          'cat'
                          'ccache'
                          'distcc'
                          'git'
                          'gpg'
                          'gzip'
                          'hg'
                          'lzip'
                          'lzop'
                          'openssl'
                          'svn'
                          'tput'
                          'uncompress'
                          'upx'
                          'xargs'
                          'xz'
                         )

  for wrapper in ${UTILS_NAME[@]}; do
    eval "
    ${wrapper}"'() {
      local UTILS_PATH="/usr/bin/"
      if ! type -p ${UTILS_PATH}${FUNCNAME[0]} >/dev/null; then
        error "$(gettext "Cannot find the %s binary required for makepkg.")" "${UTILS_PATH}${FUNCNAME[0]}"
        exit 1
      fi
      ${UTILS_PATH}${FUNCNAME[0]} "$@"
    }'
  done
fi


### SUBROUTINES ###

# Import libmakepkg
for lib in "$LIBRARY"/*.sh; do
	source "$lib"
done

##
# 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() {
	local signal=$1; shift

	echo
	error "$@"

	[[ -n $srclinks ]] && rm -rf "$srclinks"

	# unset the trap for this signal, and then call the default handler
	trap -- "$signal"
	kill "-$signal" "$$"
}


##
# Clean up function. Called automatically when the script exits.
##
clean_up() {
	local EXIT_CODE=$?

	if (( ! EXIT_CODE && CLEANUP )); then
		local pkg file

		# If it's a clean exit and -c/--clean has been passed...
		msg "$(gettext "Cleaning up...")"
		rm -rf "$pkgdirbase" "$srcdir" "$destdir"
		if [[ -n $pkgbase ]]; then
			local fullver=$(get_full_version)
			# Can't do this unless the BUILDSCRIPT has been sourced.
			if (( BUILDFUNC )); then
				rm -f "${pkgbase}-${fullver}-${CARCH}-build.log"*
			fi
			if (( CHECKFUNC )); then
				rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
			fi
			if (( PKGFUNC )); then
				rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
			elif (( SPLITPKG )); then
				for pkg in ${pkgname[@]}; do
					rm -f "${pkgbase}-${fullver}-${CARCH}-package_${pkg}.log"*
				done
			fi

			# clean up dangling symlinks to packages
			for pkg in ${pkgname[@]}; do
				for file in ${pkg}-*-*-*{${PKGEXT},${SRCEXT}}; do
					if [[ -h $file && ! -e $file ]]; then
						rm -f "$file"
					fi
				done
			done
		fi
	fi

	remove_deps
}

enter_fakeroot() {
	msg "$(gettext "Entering %s environment...")" "fakeroot"
	fakeroot -- $0 -F "${ARGLIST[@]}" || exit $?
}

# Automatically update pkgver variable if a pkgver() function is provided
# Re-sources the PKGBUILD afterwards to allow for other variables that use $pkgver
update_pkgver() {
	newpkgver=$(run_function_safe pkgver)
	if ! check_pkgver "$newpkgver"; then
		error "$(gettext "pkgver() generated an invalid version: %s")" "$newpkgver"
		exit 1
	fi

	if [[ -n $newpkgver && $newpkgver != "$pkgver" ]]; then
		if [[ -f $BUILDFILE && -w $BUILDFILE ]]; then
			if ! sed --follow-symlinks -i "s:^pkgver=[^ ]*:pkgver=$newpkgver:" "$BUILDFILE"; then
				error "$(gettext "Failed to update %s from %s to %s")" \
						"pkgver" "$pkgver" "$newpkgver"
				exit 1
			fi
			sed --follow-symlinks -i "s:^pkgrel=[^ ]*:pkgrel=1:" "$BUILDFILE"
			source_safe "$BUILDFILE"
			local fullver=$(get_full_version)
			msg "$(gettext "Updated version: %s")" "$pkgbase $fullver"
		else
			warning "$(gettext "%s is not writeable -- pkgver will not be updated")" \
					"$BUILDFILE"
		fi
	fi
}

# Print 'source not found' error message and exit makepkg
missing_source_file() {
	error "$(gettext "Unable to find source file %s.")" "$(get_filename "$1")"
	plain "$(gettext "Aborting...")"
	exit 1 # $E_MISSING_FILE
}

source_has_signatures() {
	local file all_sources

	get_all_sources_for_arch 'all_sources'
	for file in "${all_sources[@]}"; do
		if [[ ${file%%::*} = *.@(sig?(n)|asc) ]]; then
			return 0
		fi
	done
	return 1
}

run_pacman() {
	local cmd
	if [[ $1 != -@(T|Qq) ]]; then
		cmd=("$PACMAN_PATH" $PACMAN_OPTS "$@")
	else
		cmd=("$PACMAN_PATH" "$@")
	fi

	"${cmd[@]}"
}

check_deps() {
	(( $# > 0 )) || return 0

	local ret=0
	local pmout
	pmout=$(run_pacman -T "$@")
	ret=$?

	if (( ret == 127 )); then #unresolved deps
		printf "%s\n" "$pmout"
	elif (( ret )); then
		error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout"
		return "$ret"
	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
	# save our shell options and turn off extglob
	local shellopts=$(shopt -p)
	shopt -u extglob
	source /etc/profile &>/dev/null
	eval "$shellopts"

	return $R_DEPS_SATISFIED
}

resolve_deps() {
	local R_DEPS_SATISFIED=0
	local R_DEPS_MISSING=1

	# deplist cannot be declared like this: local deplist=$(foo)
	# Otherwise, the return value will depend on the assignment.
	local deplist
	deplist="$(set +E; check_deps $*)" || exit 1
	[[ -z $deplist ]] && return $R_DEPS_SATISFIED

	if handle_deps $deplist; then
		# check deps again to make sure they were resolved
		deplist="$(set +E; check_deps $*)" || exit 1
		[[ -z $deplist ]] && return $R_DEPS_SATISFIED
	fi

	msg "$(gettext "Missing dependencies:")"
	local dep
	for dep in $deplist; do
		msg2 "$dep"
	done

	return $R_DEPS_MISSING
}

remove_deps() {
	(( ! RMDEPS )) && return

	# check for packages removed during dependency install (e.g. due to conflicts)
	# removing all installed packages is risky in this case
	if [[ -n $(grep -xvFf <(printf '%s\n' "${current_pkglist[@]}") \
			<(printf '%s\n' "${original_pkglist[@]}")) ]]; then
		warning "$(gettext "Failed to remove installed dependencies.")"
		return 0
	fi

	local deplist
	deplist=($(grep -xvFf <(printf "%s\n" "${original_pkglist[@]}") \
			<(printf "%s\n" "${current_pkglist[@]}")))
	if [[ -z $deplist ]]; then
		return 0
	fi

	msg "Removing installed dependencies..."
	# exit cleanly on failure to remove deps as package has been built successfully
	if ! run_pacman -Rn ${deplist[@]}; then
		warning "$(gettext "Failed to remove installed dependencies.")"
		return 0
	fi
}

get_integlist() {
	local integ
	local integlist=()

	for integ in "${known_hash_algos[@]}"; do
		local sumname="${integ}sums[@]"
		if [[ -n ${!sumname} ]]; then
			integlist+=("$integ")
		fi
	done

	if (( ${#integlist[@]} > 0 )); then
		printf "%s\n" "${integlist[@]}"
	else
		printf "%s\n" "${INTEGRITY_CHECK[@]}"
	fi
}

generate_one_checksum() {
	local integ=$1 arch=$2 sources numsrc indentsz idx

	if [[ $arch ]]; then
		array_build sources "source_$arch"
	else
		array_build sources 'source'
	fi

	numsrc=${#sources[*]}
	if (( numsrc == 0 )); then
		return
	fi

	if [[ $arch ]]; then
		printf "%ssums_%s=(%n" "$integ" "$arch" indentsz
	else
		printf "%ssums=(%n" "$integ" indentsz
	fi

	for (( idx = 0; idx < numsrc; ++idx )); do
		local netfile=${sources[idx]}
		local proto sum
		proto="$(get_protocol "$netfile")"

		case $proto in
			bzr*|git*|hg*|svn*)
				sum="SKIP"
				;;
			*)
				if [[ $netfile != *.@(sig?(n)|asc) ]]; then
					local file
					file="$(get_filepath "$netfile")" || missing_source_file "$netfile"
					sum="$(openssl dgst -${integ} "$file")"
					sum=${sum##* }
				else
					sum="SKIP"
				fi
				;;
		esac

		# indent checksum on lines after the first
		printf "%*s%s" $(( idx ? indentsz : 0 )) '' "'$sum'"

		# print a newline on lines before the last
		(( idx < (numsrc - 1) )) && echo
	done

	echo ")"
}

generate_checksums() {
	msg "$(gettext "Generating checksums for source files...")"

	if ! type -p openssl >/dev/null; then
		error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl"
		exit 1 # $E_MISSING_PROGRAM
	fi

	local integlist
	if (( $# == 0 )); then
		IFS=$'\n' read -rd '' -a integlist < <(get_integlist)
	else
		integlist=("$@")
	fi

	local integ
	for integ in "${integlist[@]}"; do
		if ! in_array "$integ" "${known_hash_algos[@]}"; then
			error "$(gettext "Invalid integrity algorithm '%s' specified.")" "$integ"
			exit 1 # $E_CONFIG_ERROR
		fi

		generate_one_checksum "$integ"
		for a in "${arch[@]}"; do
			generate_one_checksum "$integ" "$a"
		done
	done
}

verify_integrity_one() {
	local source_name=$1 integ=$2 expectedsum=$3

	local file="$(get_filename "$source_name")"
	printf '    %s ... ' "$file" >&2

	if [[ $expectedsum = 'SKIP' ]]; then
		printf '%s\n' "$(gettext "Skipped")" >&2
		return
	fi

	if ! file="$(get_filepath "$file")"; then
		printf '%s\n' "$(gettext "NOT FOUND")" >&2
		return 1
	fi

	local realsum="$(openssl dgst -${integ} "$file")"
	realsum="${realsum##* }"
	if [[ ${expectedsum,,} = "$realsum" ]]; then
		printf '%s\n' "$(gettext "Passed")" >&2
	else
		printf '%s\n' "$(gettext "FAILED")" >&2
		return 1
	fi

	return 0
}

verify_integrity_sums() {
	local integ=$1 arch=$2 integrity_sums=() sources=() srcname

	if [[ $arch ]]; then
		array_build integrity_sums "${integ}sums_$arch"
		srcname=source_$arch
	else
		array_build integrity_sums "${integ}sums"
		srcname=source
	fi

	array_build sources "$srcname"
	if (( ${#integrity_sums[@]} == 0 && ${#sources[@]} == 0 )); then
		return 1
	fi

	if (( ${#integrity_sums[@]} == ${#sources[@]} )); then
		msg "$(gettext "Validating %s files with %s...")" "$srcname" "${integ}sums"
		local idx errors=0
		for (( idx = 0; idx < ${#sources[*]}; idx++ )); do
			verify_integrity_one "${sources[idx]}" "$integ" "${integrity_sums[idx]}" || errors=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
	else
		return 1
	fi
}

check_checksums() {
	local integ a
	declare -A correlation
	(( SKIPCHECKSUMS )) && return 0

	# Initialize a map which we'll use to verify that every source array has at
	# least some kind of checksum array associated with it.
	(( ${#source[*]} )) && correlation['source']=1
	case $1 in
		all)
			for a in "${arch[@]}"; do
				array_build _ source_"$a" && correlation["source_$a"]=1
			done
			;;
		*)
			array_build _ source_"$CARCH" && correlation["source_$CARCH"]=1
			;;
	esac

	for integ in "${known_hash_algos[@]}"; do
		verify_integrity_sums "$integ" && unset "correlation[source]"

		case $1 in
			all)
				for a in "${arch[@]}"; do
					verify_integrity_sums "$integ" "$a" && unset "correlation[source_$a]"
				done
				;;
			*)
				verify_integrity_sums "$integ" "$CARCH" && unset "correlation[source_$CARCH]"
				;;
		esac
	done

	if (( ${#correlation[*]} )); then
		error "$(gettext "Integrity checks are missing for: %s")" "${!correlation[*]}"
		exit 1 # TODO: error code
	fi
}

parse_gpg_statusfile() {
	local type arg1 arg6 arg10

	while read -r _ type arg1 _ _ _ _ arg6 _ _ _ arg10 _; do
		case "$type" in
			GOODSIG)
				pubkey=$arg1
				success=1
				status="good"
				;;
			EXPSIG)
				pubkey=$arg1
				success=1
				status="expired"
				;;
			EXPKEYSIG)
				pubkey=$arg1
				success=1
				status="expiredkey"
				;;
			REVKEYSIG)
				pubkey=$arg1
				success=0
				status="revokedkey"
				;;
			BADSIG)
				pubkey=$arg1
				success=0
				status="bad"
				;;
			ERRSIG)
				pubkey=$arg1
				success=0
				if [[ $arg6 == 9 ]]; then
					status="missingkey"
				else
					status="error"
				fi
				;;
			VALIDSIG)
				if [[ $arg10 ]]; then
					# If the file was signed with a subkey, arg10 contains
					# the fingerprint of the primary key
					fingerprint=$arg10
				else
					fingerprint=$arg1
				fi
				;;
			TRUST_UNDEFINED|TRUST_NEVER)
				trusted=0
				;;
			TRUST_MARGINAL|TRUST_FULLY|TRUST_ULTIMATE)
				trusted=1
				;;
		esac
	done < "$1"
}

check_pgpsigs() {
	(( SKIPPGPCHECK )) && return 0
	! source_has_signatures && return 0

	msg "$(gettext "Verifying source file signatures with %s...")" "gpg"

	local file ext decompress found pubkey success status fingerprint trusted
	local warning=0
	local errors=0
	local statusfile=$(mktemp)
	local all_sources

	case $1 in
		all)
			get_all_sources 'all_sources'
			;;
		*)
			get_all_sources_for_arch 'all_sources'
			;;
	esac
	for file in "${all_sources[@]}"; do
		file="$(get_filename "$file")"
		if [[ $file != *.@(sig?(n)|asc) ]]; then
			continue
		fi

		printf "    %s ... " "${file%.*}" >&2

		if ! file="$(get_filepath "$file")"; then
			printf '%s\n' "$(gettext "SIGNATURE NOT FOUND")" >&2
			errors=1
			continue
		fi

		found=0
		for ext in "" gz bz2 xz lrz lzo Z; do
			if sourcefile="$(get_filepath "${file%.*}${ext:+.$ext}")"; then
				found=1
				break;
			fi
		done
		if (( ! found )); then
			printf '%s\n' "$(gettext "SOURCE FILE NOT FOUND")" >&2
			errors=1
			continue
		fi

		case "$ext" in
			gz)  decompress="gzip -c -d -f" ;;
			bz2) decompress="bzip2 -c -d -f" ;;
			xz)  decompress="xz -c -d" ;;
			lrz) decompress="lrzip -q -d" ;;
			lzo) decompress="lzop -c -d -q" ;;
			Z)   decompress="uncompress -c -f" ;;
			"")  decompress="cat" ;;
		esac

		$decompress < "$sourcefile" | gpg --quiet --batch --status-file "$statusfile" --verify "$file" - 2> /dev/null
		# these variables are assigned values in parse_gpg_statusfile
		success=0
		status=
		pubkey=
		fingerprint=
		trusted=
		parse_gpg_statusfile "$statusfile"
		if (( ! $success )); then
			printf '%s' "$(gettext "FAILED")" >&2
			case "$status" in
				"missingkey")
					printf ' (%s)' "$(gettext "unknown public key") $pubkey" >&2
					;;
				"revokedkey")
					printf " ($(gettext "public key %s has been revoked"))" "$pubkey" >&2
					;;
				"bad")
					printf ' (%s)' "$(gettext "bad signature from public key") $pubkey" >&2
					;;
				"error")
					printf ' (%s)' "$(gettext "error during signature verification")" >&2
					;;
			esac
			errors=1
		else
			if (( ${#validpgpkeys[@]} == 0 && !trusted )); then
				printf "%s ($(gettext "the public key %s is not trusted"))" $(gettext "FAILED") "$fingerprint" >&2
				errors=1
			elif (( ${#validpgpkeys[@]} > 0 )) && ! in_array "$fingerprint" "${validpgpkeys[@]}"; then
				printf "%s (%s %s)" "$(gettext "FAILED")" "$(gettext "invalid public key")" "$fingerprint"
				errors=1
			else
				printf '%s' "$(gettext "Passed")" >&2
				case "$status" in
					"expired")
						printf ' (%s)' "$(gettext "WARNING:") $(gettext "the signature has expired.")" >&2
						warnings=1
						;;
					"expiredkey")
						printf ' (%s)' "$(gettext "WARNING:") $(gettext "the key has expired.")" >&2
						warnings=1
						;;
				esac
			fi
		fi
		printf '\n' >&2
	done

	rm -f "$statusfile"

	if (( errors )); then
		error "$(gettext "One or more PGP signatures could not be verified!")"
		exit 1
	fi

	if (( warnings )); then
		warning "$(gettext "Warnings have occurred while verifying the signatures.")"
		plain "$(gettext "Please make sure you really trust them.")"
	fi
}

check_source_integrity() {
	if (( SKIPCHECKSUMS && SKIPPGPCHECK )); then
		warning "$(gettext "Skipping all source file integrity checks.")"
	elif (( SKIPCHECKSUMS )); then
		warning "$(gettext "Skipping verification of source file checksums.")"
		check_pgpsigs "$@"
	elif (( SKIPPGPCHECK )); then
		warning "$(gettext "Skipping verification of source file PGP signatures.")"
		check_checksums "$@"
	else
		check_checksums "$@"
		check_pgpsigs "$@"
	fi
}

error_function() {
	if [[ -p $logpipe ]]; then
		rm "$logpipe"
	fi
	# first exit all subshells, then print the error
	if (( ! BASH_SUBSHELL )); then
		error "$(gettext "A failure occurred in %s().")" "$1"
		plain "$(gettext "Aborting...")"
	fi
	exit 2 # $E_BUILD_FAILED
}

source_safe() {
	shopt -u extglob
	if ! source "$@"; then
		error "$(gettext "Failed to source %s")" "$1"
		exit 1
	fi
	shopt -s extglob
}

merge_arch_attrs() {
	local attr supported_attrs=(
		provides conflicts depends replaces optdepends
		makedepends checkdepends)

	for attr in "${supported_attrs[@]}"; do
		eval "$attr+=(\"\${${attr}_$CARCH[@]}\")"
	done

	# ensure that calling this function is idempotent.
	unset -v "${supported_attrs[@]/%/_$CARCH}"
}

source_buildfile() {
	source_safe "$@"
}

run_function_safe() {
	local restoretrap

	set -e
	set -E

	restoretrap=$(trap -p ERR)
	trap 'error_function $pkgfunc' ERR

	run_function "$1"

	eval $restoretrap

	set +E
	set +e
}

run_function() {
	if [[ -z $1 ]]; then
		return 1
	fi
	local pkgfunc="$1"

	# clear user-specified buildflags if requested
	if check_option "buildflags" "n"; then
		unset CPPFLAGS CFLAGS CXXFLAGS LDFLAGS
	fi

	if check_option "debug" "y"; then
		CFLAGS+=" $DEBUG_CFLAGS"
		CXXFLAGS+=" $DEBUG_CXXFLAGS"
	fi

	# clear user-specified makeflags if requested
	if check_option "makeflags" "n"; then
		unset MAKEFLAGS
	fi

	msg "$(gettext "Starting %s()...")" "$pkgfunc"
	cd_safe "$srcdir"

	# ensure all necessary build variables are exported
	export CPPFLAGS CFLAGS CXXFLAGS LDFLAGS MAKEFLAGS CHOST
	export MINGW_CHOST MINGW_PREFIX MINGW_PACKAGE_PREFIX
	export DXSDK_DIR ACLOCAL_PATH PKG_CONFIG_PATH
	# save our shell options so pkgfunc() can't override what we need
	local shellopts=$(shopt -p)

	local ret=0
	if (( LOGGING )); then
		local fullver=$(get_full_version)
		local BUILDLOG="$LOGDEST/${pkgbase}-${fullver}-${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 "$LOGDEST/logpipe.XXXXXXXX")
		mkfifo "$logpipe"
		tee "$BUILDLOG" < "$logpipe" &
		local teepid=$!

		$pkgfunc &>"$logpipe"

		wait $teepid
		rm "$logpipe"
	else
		"$pkgfunc"
	fi
	# reset our shell options
	eval "$shellopts"
}

run_prepare() {
	run_function_safe "prepare"
}

run_build() {
	local ccache=0

	# use ccache if it is requested (check buildenv and PKGBUILD opts)
	if check_buildoption "ccache" "y" && [[ -d /usr/lib/ccache/bin ]]; then
		export PATH="/usr/lib/ccache/bin:$PATH"
		ccache=1
	fi

	# use distcc if it is requested (check buildenv and PKGBUILD opts)
	if check_buildoption "distcc" "y"; then
		if (( ccache )); then
			export CCACHE_PREFIX="${CCACHE_PREFIX:+$CCACHE_PREFIX }distcc"
			export CCACHE_BASEDIR="$srcdir"
		elif [[ -d /usr/lib/distcc/bin ]]; then
			export PATH="/usr/lib/distcc/bin:$PATH"
		fi
		export DISTCC_HOSTS
	fi

	run_function_safe "build"
}

run_check() {
	run_function_safe "check"
}

run_package() {
	local pkgfunc
	if [[ -z $1 ]]; then
		pkgfunc="package"
	else
		pkgfunc="package_$1"
	fi

	run_function_safe "$pkgfunc"
}

find_libdepends() {
	local d sodepends;

	sodepends=0;
	for d in "${depends[@]}"; do
		if [[ $d = *.dll ]]; then
			sodepends=1;
			break;
		fi
	done

	if (( sodepends == 0 )); then
		printf '%s\n' "${depends[@]}"
		return;
	fi

	local libdeps filename soarch sofile soname;
	declare -A libdeps;

	while read -r filename; do
		# get architecture of the file; if soarch is empty it's not an binary
		soarch=$(LANG=en_US.UTF-8 LC_ALL=C objdump -a "$filename" | sed -n 's/.*file format.*pei-\(i386\|x86-64\)/\1/p')
		[[ -n "$soarch" ]] || continue
		case "$soarch" in
			i386)
				soarch=i686
			;;
			x86-64)
				soarch=x86_64
			;;
		esac

		# process all libraries needed by the binary
		for sofile in $(LC_ALL=C objdump -x "$filename" 2>/dev/null | sed -nr 's/.*DLL Name: (.*).*/\1/p')
		do
			soname=${sofile}

			if [[ ${libdeps[$soname]} ]]; then
				if [[ ${libdeps[$soname]} != *${soarch}* ]]; then
					libdeps[$soname]+=" ${soarch}"
				fi
			else
				libdeps[$soname]="${soarch}"
			fi
		done
	done < <(find "$pkgdir" -type f -perm -u+x)

	local libdepends v
	for d in "${depends[@]}"; do
		case "$d" in
			*.dll)
				if [[ ${libdeps[$d]} ]]; then
					for v in ${libdeps[$d]}; do
						libdepends+=("$d=$v")
					done
				else
					warning "$(gettext "Library listed in %s is not required by any files: %s")" "'depends'" "$d"
					libdepends+=("$d")
				fi
				;;
			*)
				libdepends+=("$d")
				;;
		esac
	done

	printf '%s\n' "${libdepends[@]}"
}


find_libprovides() {
	local p libprovides missing
	for p in "${provides[@]}"; do
		missing=0
		case "$p" in
			*.dll)
				mapfile -t filename < <(find "$pkgdir" -type f -name $p)
				if [[ $filename ]]; then
					# packages may provide multiple versions of the same library
					for fn in "${filename[@]}"; do
						# get the library architecture (32 or 64 bit)
						local soarch=$(LC_ALL=C objdump -a "$fn" | sed -n 's/.*file format.*pei-\(i386\|x86-64\)/\1/p')
						case "$soarch" in
							i386)
								soarch=i686
							;;
							x86-64)
								soarch=x86_64
							;;
						esac

						libprovides+=("${p}=${soarch}")
					done
				else
					libprovides+=("$p")
					missing=1
				fi
				;;
			*)
				libprovides+=("$p")
				;;
		esac

		if (( missing )); then
			warning "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$p"
		fi
	done

	printf '%s\n' "${libprovides[@]}"
}

srcinfo_open_section() {
	printf '%s = %s\n' "$1" "$2"
}

srcinfo_close_section() {
	echo
}

srcinfo_write_attr() {
	# $1: attr name
	# $2: attr values

	local attrname=$1 attrvalues=("${@:2}")

	# normalize whitespace, strip leading and trailing
	attrvalues=("${attrvalues[@]//+([[:space:]])/ }")
	attrvalues=("${attrvalues[@]#[[:space:]]}")
	attrvalues=("${attrvalues[@]%[[:space:]]}")

	printf "\t$attrname = %s\n" "${attrvalues[@]}"
}

pkgbuild_extract_to_srcinfo() {
	# $1: pkgname
	# $2: attr name
	# $3: multivalued

	local pkgname=$1 attrname=$2 isarray=$3 outvalue=

	if get_pkgbuild_attribute "$pkgname" "$attrname" "$isarray" 'outvalue'; then
		srcinfo_write_attr "$attrname" "${outvalue[@]}"
	fi
}

srcinfo_write_section_details() {
	local attr package_arch a
	local multivalued_arch_attrs=(source provides conflicts depends replaces
	                              optdepends makedepends checkdepends
	                              {md5,sha{1,224,256,384,512}}sums)

	for attr in "${singlevalued[@]}"; do
		pkgbuild_extract_to_srcinfo "$1" "$attr" 0
	done

	for attr in "${multivalued[@]}"; do
		pkgbuild_extract_to_srcinfo "$1" "$attr" 1
	done

	get_pkgbuild_attribute "$1" 'arch' 1 'package_arch'
	for a in "${package_arch[@]}"; do
		# 'any' is special. there's no support for, e.g. depends_any.
		[[ $a = any ]] && continue

		for attr in "${multivalued_arch_attrs[@]}"; do
			pkgbuild_extract_to_srcinfo "$1" "${attr}_$a" 1
		done
	done
}

srcinfo_write_global() {
	local singlevalued=(pkgdesc pkgver pkgrel epoch url install changelog)
	local multivalued=(arch groups license checkdepends makedepends
	                   depends optdepends provides conflicts replaces
	                   noextract options backup
	                   source validpgpkeys {md5,sha{1,224,256,384,512}}sums)

	srcinfo_open_section 'pkgbase' "${pkgbase:-$pkgname}"
	srcinfo_write_section_details ''
	srcinfo_close_section
}

srcinfo_write_package() {
	local singlevalued=(pkgdesc url install changelog)
	local multivalued=(arch groups license checkdepends depends optdepends
	                   provides conflicts replaces options backup)

	srcinfo_open_section 'pkgname' "$1"
	srcinfo_write_section_details "$1"
	srcinfo_close_section
}

write_srcinfo_header() {
	printf "# Generated by makepkg %s\n" "$makepkg_version"
	printf "# %s\n" "$(LC_ALL=C date -u)"
}

write_srcinfo_content() {
	local pkg

	srcinfo_write_global

	for pkg in "${pkgname[@]}"; do
		srcinfo_write_package "$pkg"
	done
}

write_srcinfo() {
	write_srcinfo_header
	write_srcinfo_content
}

write_pkginfo() {
	local builddate=$(date -u "+%s")
	if [[ -n $PACKAGER ]]; then
		local packager="$PACKAGER"
	else
		local packager="Unknown Packager"
	fi

	local size="$(/usr/bin/du -sk --apparent-size)"
	size="$(( ${size%%[^0-9]*} * 1024 ))"

	merge_arch_attrs

	msg2 "$(gettext "Generating %s file...")" ".PKGINFO"
	printf "# Generated by makepkg %s\n" "$makepkg_version"
	printf "# %s\n" "$(LC_ALL=C date -u)"

	printf "pkgname = %s\n" "$pkgname"
	if (( SPLITPKG )) || [[ "$pkgbase" != "$pkgname" ]]; then
		printf "pkgbase = %s\n" "$pkgbase"
	fi

	local fullver=$(get_full_version)
	printf "pkgver = %s\n" "$fullver"
	if [[ "$fullver" != "$basever" ]]; then
		printf "basever = %s\n" "$basever"
	fi

	# TODO: all fields should have this treatment
	local spd="${pkgdesc//+([[:space:]])/ }"
	spd=("${spd[@]#[[:space:]]}")
	spd=("${spd[@]%[[:space:]]}")

	printf "pkgdesc = %s\n" "$spd"
	printf "url = %s\n" "$url"
	printf "builddate = %s\n" "$builddate"
	printf "packager = %s\n" "$packager"
	printf "size = %s\n" "$size"
	printf "arch = %s\n" "$pkgarch"

	mapfile -t provides < <(find_libprovides)
	mapfile -t depends < <(find_libdepends)

	[[ $license ]]      && printf "license = %s\n"     "${license[@]}"
	[[ $replaces ]]     && printf "replaces = %s\n"    "${replaces[@]}"
	[[ $groups ]]       && printf "group = %s\n"       "${groups[@]}"
	[[ $conflicts ]]    && printf "conflict = %s\n"    "${conflicts[@]}"
	[[ $provides ]]     && printf "provides = %s\n"    "${provides[@]}"
	[[ $backup ]]       && printf "backup = %s\n"      "${backup[@]}"
	[[ $depends ]]      && printf "depend = %s\n"      "${depends[@]}"
	[[ $optdepends ]]   && printf "optdepend = %s\n"   "${optdepends[@]//+([[:space:]])/ }"
	[[ $makedepends ]]  && printf "makedepend = %s\n"  "${makedepends[@]}"
	[[ $checkdepends ]] && printf "checkdepend = %s\n" "${checkdepends[@]}"
}

write_buildinfo() {
	msg2 "$(gettext "Generating %s file...")" ".BUILDINFO"

	printf "builddir = %s\n"  "${BUILDDIR}"

	local sum="$(openssl dgst -sha256 "${BUILDFILE}")"
	sum=${sum##* }

	printf "pkgbuild_sha256sum = %s\n" $sum

	printf "buildenv = %s\n" "${BUILDENV[@]}"
	printf "options = %s\n" "${OPTIONS[@]}"

	local pkglist=($(run_pacman -Q | sed "s# #-#"))
	printf "installed = %s\n" "${pkglist[@]}"
}

create_package() {
	(( NOARCHIVE )) && return

	if [[ ! -d $pkgdir ]]; then
		error "$(gettext "Missing %s directory.")" "\$pkgdir/"
		plain "$(gettext "Aborting...")"
		exit 1 # $E_MISSING_PKGDIR
	fi

	cd_safe "$pkgdir"
	msg "$(gettext "Creating package \"%s\"...")" "$pkgname"

	pkgarch=$(get_pkg_arch)
	write_pkginfo > .PKGINFO
	write_buildinfo > .BUILDINFO

	local comp_files=('.PKGINFO' '.BUILDINFO')

	# check for changelog/install files
	for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do
		IFS='/' read -r orig dest < <(printf '%s\n' "$i")

		if [[ -n ${!orig} ]]; then
			msg2 "$(gettext "Adding %s file...")" "$orig"
			if ! cp "$startdir/${!orig}" "$dest"; then
				error "$(gettext "Failed to add %s file to package.")" "$orig"
				exit 1
			fi
			chmod 644 "$dest"
			comp_files+=("$dest")
		fi
	done

	# tar it up
	local fullver=$(get_full_version)
	local pkg_file="$PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT}"
	local ret=0

	[[ -f $pkg_file ]] && rm -f "$pkg_file"
	[[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"

	# when fileglobbing, we want * in an empty directory to expand to
	# the null string rather than itself
	shopt -s nullglob

	msg2 "$(gettext "Generating .MTREE file...")"
	LANG=C bsdtar -czf .MTREE --format=mtree \
		--options='!all,use-set,type,uid,gid,mode,time,size,md5,sha256,link' \
		"${comp_files[@]}" *
	comp_files+=(".MTREE")

	msg2 "$(gettext "Compressing package...")"
	# TODO: Maybe this can be set globally for robustness
	shopt -s -o pipefail
	# bsdtar's gzip compression always saves the time stamp, making one
	# archive created using the same command line distinct from another.
	# Disable bsdtar compression and use gzip -n for now.
	LANG=C bsdtar -cf - "${comp_files[@]}" * |
	case "$PKGEXT" in
		*tar.gz)  ${COMPRESSGZ[@]:-gzip -c -f -n} ;;
		*tar.bz2) ${COMPRESSBZ2[@]:-bzip2 -c -f} ;;
		*tar.xz)  ${COMPRESSXZ[@]:-xz -c -z -T0 -} ;;
		*tar.lrz) ${COMPRESSLRZ[@]:-lrzip -q} ;;
		*tar.lzo) ${COMPRESSLZO[@]:-lzop -q} ;;
		*tar.Z)   ${COMPRESSZ[@]:-compress -c -f} ;;
		*tar)     cat ;;
		*) warning "$(gettext "'%s' is not a valid archive extension.")" \
			"$PKGEXT"; cat ;;
	esac > "${pkg_file}" || ret=$?

	shopt -u nullglob
	shopt -u -o pipefail

	if (( ret )); then
		error "$(gettext "Failed to create package file.")"
		exit 1 # TODO: error code
	fi

	create_signature "$pkg_file"

	if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then
		rm -f "${pkg_file/$PKGDEST/$startdir}"
		ln -s "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
		ret=$?
		if [[ -f $pkg_file.sig ]]; then
			rm -f "${pkg_file/$PKGDEST/$startdir}.sig"
			ln -s "$pkg_file.sig" "${pkg_file/$PKGDEST/$startdir}.sig"
		fi
	fi

	if (( ret )); then
		warning "$(gettext "Failed to create symlink to package file.")"
	fi
}

create_debug_package() {
	# check if a debug package was requested
	if ! check_option "debug" "y" || ! check_option "strip" "y"; then
		return
	fi

	pkgdir="${pkgdir}-debug"
	# check if we have any debug symbols to package
	if dir_is_empty "$pkgdir"; then
		return
	fi

	depends=("$pkgname=$(get_full_version)")
	pkgdesc="Detached debugging symbols for $pkgname"
	pkgname=$pkgname-debug

	unset groups optdepends provides conflicts replaces backup install changelog

	create_package
}

create_signature() {
	if [[ $SIGNPKG != 'y' ]]; then
		return
	fi
	local ret=0
	local filename="$1"
	msg "$(gettext "Signing package...")"

	local SIGNWITHKEY=""
	if [[ -n $GPGKEY ]]; then
		SIGNWITHKEY="-u ${GPGKEY}"
	fi

	gpg --detach-sign --use-agent ${SIGNWITHKEY} --no-armor "$filename" &>/dev/null || ret=$?


	if (( ! ret )); then
		msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
	else
		warning "$(gettext "Failed to sign package file.")"
	fi
}

create_srcpackage() {
	local ret=0
	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}"

	msg2 "$(gettext "Generating %s file...")" .SRCINFO
	write_srcinfo > "$srclinks/$pkgbase"/.SRCINFO

	local file all_sources

	get_all_sources 'all_sources'
	for file in "${all_sources[@]}"; do
		if [[ "$file" = "$(get_filename "$file")" ]] || (( SOURCEONLY == 2 )); then
			local absfile
			absfile=$(get_filepath "$file") || missing_source_file "$file"
			msg2 "$(gettext "Adding %s...")" "${absfile##*/}"
			ln -s "$absfile" "$srclinks/$pkgbase"
		fi
	done

	local i
	for i in 'changelog' 'install'; do
		local file files

		[[ ${!i} ]] && files+=("${!i}")
		for name in "${pkgname[@]}"; do
			if extract_function_variable "package_$name" "$i" 0 file; then
				files+=("$file")
			fi
		done

		for file in "${files[@]}"; do
			if [[ $file && ! -f "${srclinks}/${pkgbase}/$file" ]]; then
				msg2 "$(gettext "Adding %s file (%s)...")" "$i" "${file}"
				ln -s "${startdir}/$file" "${srclinks}/${pkgbase}/"
			fi
		done
	done

	local TAR_OPT
	case "$SRCEXT" in
		*tar.gz)  TAR_OPT="-z" ;;
		*tar.bz2) TAR_OPT="-j" ;;
		*tar.xz)  TAR_OPT="-J" ;;
		*tar.lrz) TAR_OPT="--lrzip" ;;
		*tar.lzo) TAR_OPT="--lzop" ;;
		*tar.Z)   TAR_OPT="-Z" ;;
		*tar)     TAR_OPT=""  ;;
		*) warning "$(gettext "'%s' is not a valid archive extension.")" \
		"$SRCEXT" ;;
	esac

	local fullver=$(get_full_version)
	local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}"

	# tar it up
	msg2 "$(gettext "Compressing source package...")"
	cd_safe "${srclinks}"
	if ! LANG=C bsdtar -cL ${TAR_OPT} -f "$pkg_file" ${pkgbase}; then
		error "$(gettext "Failed to create source package file.")"
		exit 1 # TODO: error code
	fi

	create_signature "$pkg_file"

	if [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then
		rm -f "${pkg_file/$SRCPKGDEST/$startdir}"
		ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}"
		ret=$?
		if [[ -f $pkg_file.sig ]]; then
			rm -f "${pkg_file/$SRCPKGDEST/$startdir}.sig"
			ln -s "$pkg_file.sig" "${pkg_file/$SRCPKGDEST/$startdir}.sig"
		fi
	fi

	if (( ret )); then
		warning "$(gettext "Failed to create symlink to source package file.")"
	fi

	cd_safe "${startdir}"
	rm -rf "${srclinks}"
}

# this function always returns 0 to make sure clean-up will still occur
install_package() {
	(( ! INSTALL )) && return

	if (( ! SPLITPKG )); then
		msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U"
	else
		msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U"
	fi

	local fullver pkgarch pkg pkglist
	(( ASDEPS )) && pkglist+=('--asdeps')
	(( NEEDED )) && pkglist+=('--needed')

	for pkg in ${pkgname[@]}; do
		fullver=$(get_full_version)
		pkgarch=$(get_pkg_arch $pkg)
		pkglist+=("$PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT}")

		if [[ -f "$PKGDEST/${pkg}-debug-${fullver}-${pkgarch}${PKGEXT}" ]]; then
			pkglist+=("$PKGDEST/${pkg}-debug-${fullver}-${pkgarch}${PKGEXT}")
		fi
	done

	if ! run_pacman -U "${pkglist[@]}"; then
		warning "$(gettext "Failed to install built package(s).")"
		return 0
	fi
}

get_vcsclient() {
	local proto=${1%%+*}

	local i
	for i in "${VCSCLIENTS[@]}"; do
		local handler="${i%%::*}"
		if [[ $proto = "$handler" ]]; then
			local client="${i##*::}"
			break
		fi
	done

	# if we didn't find an client, return an error
	if [[ -z $client ]]; then
		error "$(gettext "Unknown download protocol: %s")" "$proto"
		plain "$(gettext "Aborting...")"
		exit 1 # $E_CONFIG_ERROR
	fi

	printf "%s\n" "$client"
}

check_vcs_software() {
	local all_sources all_deps deps ret=0

	if (( SOURCEONLY == 1 )); then
		# we will not download VCS sources
		return $ret
	fi

	if [[ -z $PACMAN_PATH ]]; then
		warning "$(gettext "Cannot find the %s binary needed to check VCS source requirements.")" "$PACMAN"
		return $ret
	fi

	# we currently only use global depends/makedepends arrays for --syncdeps
	for attr in depends makedepends; do
		get_pkgbuild_attribute "$pkg" "$attr" 1 'deps'
		all_deps+=("${deps[@]}")

		get_pkgbuild_attribute "$pkg" "${attr}_$CARCH" 1 'deps'
		all_deps+=("${deps[@]}")
	done

	get_all_sources_for_arch 'all_sources'
	for netfile in ${all_sources[@]}; do
		local proto=$(get_protocol "$netfile")

		case $proto in
			bzr*|git*|hg*|svn*)
				if ! type -p ${proto%%+*} > /dev/null; then
					local client
					client=$(get_vcsclient "$proto") || exit $?
					# ensure specified program is installed
					local uninstalled
					uninstalled="$(set +E; check_deps $client)" || exit 1
					# if not installed, check presence in depends or makedepends
					if [[ -n "$uninstalled" ]] && (( ! NODEPS || ( VERIFYSOURCE && !DEP_BIN ) )); then
						if ! in_array "$client" ${all_deps[@]}; then
							error "$(gettext "Cannot find the %s package needed to handle %s sources.")" \
									"$client" "${proto%%+*}"
							ret=1
						fi
					fi
				fi
				;;
			*)
				# non VCS source
				;;
		esac
	done

	return $ret
}

check_software() {
	# check for needed software
	local ret=0

	# check for PACMAN if we need it
	if (( ! NODEPS || DEP_BIN || RMDEPS || INSTALL )); then
		if [[ -z $PACMAN_PATH ]]; then
			error "$(gettext "Cannot find the %s binary required for dependency operations.")" "$PACMAN"
			ret=1
		fi
	fi

	# gpg - package signing
	if [[ $SIGNPKG == 'y' ]] || { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; }; then
		if ! type -p gpg >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for signing packages.")" "gpg"
			ret=1
		fi
	fi

	# gpg - source verification
	if (( ! SKIPPGPCHECK )) && source_has_signatures; then
		if ! type -p gpg >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for verifying source files.")" "gpg"
			ret=1
		fi
	fi

	# openssl - checksum operations
	if (( ! SKIPCHECKSUMS )); then
		if ! type -p openssl >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for validating source file checksums.")" "openssl"
			ret=1
		fi
	fi

	# upx - binary compression
	if check_option "upx" "y"; then
		if ! type -p upx >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for compressing binaries.")" "upx"
			ret=1
		fi
	fi

	# optipng - PNG image optimization
	if check_option "optipng" "y"; then
		if ! type -p optipng >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for optimizing PNG images.")" "optipng"
			ret=1
		fi
	fi

	# distcc - compilation with distcc
	if check_buildoption "distcc" "y"; then
		if ! type -p distcc >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for distributed compilation.")" "distcc"
			ret=1
		fi
	fi

	# ccache - compilation with ccache
	if check_buildoption "ccache" "y"; then
		if ! type -p ccache >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for compiler cache usage.")" "ccache"
			ret=1
		fi
	fi

	# strip - strip symbols from binaries/libraries
	if check_option "strip" "y"; then
		if ! type -p strip >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for object file stripping.")" "strip"
			ret=1
		fi
	fi

	# gzip - compressig man and info pages
	if check_option "zipman" "y"; then
		if ! type -p gzip >/dev/null; then
			error "$(gettext "Cannot find the %s binary required for compressing man and info pages.")" "gzip"
			ret=1
		fi
	fi

	# tools to download vcs sources
	if ! check_vcs_software; then
		ret=1
	fi

	return $ret
}

check_build_status() {
	if (( ! SPLITPKG )); then
		fullver=$(get_full_version)
		pkgarch=$(get_pkg_arch)
		if [[ -f $PKGDEST/${pkgname}-${fullver}-${pkgarch}${PKGEXT} ]] \
				 && ! (( FORCE || SOURCEONLY || NOBUILD || NOARCHIVE)); then
			if (( INSTALL )); then
				warning "$(gettext "A package has already been built, installing existing package...")"
				install_package
				exit 0
			else
				error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f"
				exit 1
			fi
		fi
	else
		allpkgbuilt=1
		somepkgbuilt=0
		for pkg in ${pkgname[@]}; do
			fullver=$(get_full_version)
			pkgarch=$(get_pkg_arch $pkg)
			if [[ -f $PKGDEST/${pkg}-${fullver}-${pkgarch}${PKGEXT} ]]; then
				somepkgbuilt=1
			else
				allpkgbuilt=0
			fi
		done
		if ! (( FORCE || SOURCEONLY || NOBUILD || NOARCHIVE)); then
			if (( allpkgbuilt )); then
				if (( INSTALL )); then
					warning "$(gettext "The package group has already been built, installing existing packages...")"
					install_package
					exit 0
				else
					error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f"
					exit 1
				fi
			fi
			if (( somepkgbuilt && ! PKGVERFUNC )); then
				error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f"
				exit 1
			fi
		fi
		unset allpkgbuilt somepkgbuilt
	fi
}

backup_package_variables() {
	local var
	for var in ${splitpkg_overrides[@]}; do
		local indirect="${var}_backup"
		eval "${indirect}=(\"\${$var[@]}\")"
	done
}

restore_package_variables() {
	local var
	for var in ${splitpkg_overrides[@]}; do
		local indirect="${var}_backup"
		if [[ -n ${!indirect} ]]; then
			eval "${var}=(\"\${$indirect[@]}\")"
		else
			unset ${var}
		fi
	done
}

run_split_packaging() {
	local pkgname_backup=("${pkgname[@]}")
	for pkgname in ${pkgname_backup[@]}; do
		pkgdir="$pkgdirbase/$pkgname"
		# clean existing pkg directory
		if [[ -d $pkgdir ]]; then
			msg "$(gettext "Removing existing %s directory...")" "\$pkgdir/"
			rm -rf "$pkgdir"
		fi
		mkdir "$pkgdir"
		backup_package_variables
		run_package $pkgname
		tidy_install
		lint_package
		create_package
		create_debug_package
		restore_package_variables
	done
	pkgname=("${pkgname_backup[@]}")
}

# getopt-like parser
parseopts() {
	local opt= optarg= i= shortopts=$1
	local -a longopts=() unused_argv=()

	shift
	while [[ $1 && $1 != '--' ]]; do
		longopts+=("$1")
		shift
	done
	shift

	longoptmatch() {
		local o longmatch=()
		for o in "${longopts[@]}"; do
			if [[ ${o%:} = "$1" ]]; then
				longmatch=("$o")
				break
			fi
			[[ ${o%:} = "$1"* ]] && longmatch+=("$o")
		done

		case ${#longmatch[*]} in
			1)
				# success, override with opt and return arg req (0 == none, 1 == required)
				opt=${longmatch%:}
				if [[ $longmatch = *: ]]; then
					return 1
				else
					return 0
				fi ;;
			0)
				# fail, no match found
				return 255 ;;
			*)
				# fail, ambiguous match
				printf "makepkg: $(gettext "option '%s' is ambiguous; possibilities:")" "--$1"
				printf " '%s'" "${longmatch[@]%:}"
				printf '\n'
				return 254 ;;
		esac >&2
	}

	while (( $# )); do
		case $1 in
			--) # explicit end of options
				shift
				break
				;;
			-[!-]*) # short option
				for (( i = 1; i < ${#1}; i++ )); do
					opt=${1:i:1}

					# option doesn't exist
					if [[ $shortopts != *$opt* ]]; then
						printf "makepkg: $(gettext "invalid option") -- '%s'\n" "$opt" >&2
						OPTRET=(--)
						return 1
					fi

					OPTRET+=("-$opt")
					# option requires optarg
					if [[ $shortopts = *$opt:* ]]; then
						# if we're not at the end of the option chunk, the rest is the optarg
						if (( i < ${#1} - 1 )); then
							OPTRET+=("${1:i+1}")
							break
						# if we're at the end, grab the the next positional, if it exists
						elif (( i == ${#1} - 1 )) && [[ $2 ]]; then
							OPTRET+=("$2")
							shift
							break
						# parse failure
						else
							printf "makepkg: $(gettext "option requires an argument") -- '%s'\n" "$opt" >&2
							OPTRET=(--)
							return 1
						fi
					fi
				done
				;;
			--?*=*|--?*) # long option
				IFS='=' read -r opt optarg <<< "${1#--}"
				longoptmatch "$opt"
				case $? in
					0)
						# parse failure
						if [[ $optarg ]]; then
							printf "makepkg: $(gettext "option '%s' does not allow an argument")\n" "--$opt" >&2
							OPTRET=(--)
							return 1
						# --longopt
						else
							OPTRET+=("--$opt")
						fi
						;;
					1)
						# --longopt=optarg
						if [[ $optarg ]]; then
							OPTRET+=("--$opt" "$optarg")
						# --longopt optarg
						elif [[ $2 ]]; then
							OPTRET+=("--$opt" "$2" )
							shift
						# parse failure
						else
							printf "makepkg: $(gettext "option '%s' requires an argument")\n" "--$opt" >&2
							OPTRET=(--)
							return 1
						fi
						;;
					254)
						# ambiguous option -- error was reported for us by longoptmatch()
						OPTRET=(--)
						return 1
						;;
					255)
						# parse failure
						printf "makepkg: $(gettext "invalid option") '--%s'\n" "$opt" >&2
						OPTRET=(--)
						return 1
						;;
				esac
				;;
			*) # non-option arg encountered, add it as a parameter
				unused_argv+=("$1")
				;;
		esac
		shift
	done

	# add end-of-opt terminator and any leftover positional parameters
	OPTRET+=('--' "${unused_argv[@]}" "$@")
	unset longoptmatch

	return 0
}


usage() {
	printf "makepkg (pacman) %s\n" "$makepkg_version"
	echo
	printf -- "$(gettext "Make packages compatible for use with pacman")\n"
	echo
	printf -- "$(gettext "Usage: %s [options]")\n" "$0"
	echo
	printf -- "$(gettext "Options:")\n"
	printf -- "$(gettext "  -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT"
	printf -- "$(gettext "  -c, --clean      Clean up work files after build")\n"
	printf -- "$(gettext "  -C, --cleanbuild Remove %s dir before building the package")\n" "\$srcdir/"
	printf -- "$(gettext "  -d, --nodeps     Skip all dependency checks")\n"
	printf -- "$(gettext "  -e, --noextract  Do not extract source files (use existing %s dir)")\n" "\$srcdir/"
	printf -- "$(gettext "  -f, --force      Overwrite existing package")\n"
	printf -- "$(gettext "  -g, --geninteg   Generate integrity checks for source files")\n"
	printf -- "$(gettext "  -h, --help       Show this help message and exit")\n"
	printf -- "$(gettext "  -i, --install    Install package after successful build")\n"
	printf -- "$(gettext "  -L, --log        Log package build process")\n"
	printf -- "$(gettext "  -m, --nocolor    Disable colorized output messages")\n"
	printf -- "$(gettext "  -o, --nobuild    Download and extract files only")\n"
	printf -- "$(gettext "  -p <file>        Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT"
	printf -- "$(gettext "  -r, --rmdeps     Remove installed dependencies after a successful build")\n"
	printf -- "$(gettext "  -R, --repackage  Repackage contents of the package without rebuilding")\n"
	printf -- "$(gettext "  -s, --syncdeps   Install missing dependencies with %s")\n" "pacman"
	printf -- "$(gettext "  -S, --source     Generate a source-only tarball without downloaded sources")\n"
	printf -- "$(gettext "  -V, --version    Show version information and exit")\n"
	printf -- "$(gettext "  --allsource      Generate a source-only tarball including downloaded sources")\n"
	printf -- "$(gettext "  --check          Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
	printf -- "$(gettext "  --config <file>  Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf"
	printf -- "$(gettext "  --holdver        Do not update VCS sources")\n"
	printf -- "$(gettext "  --key <key>      Specify a key to use for %s signing instead of the default")\n" "gpg"
	printf -- "$(gettext "  --noarchive      Do not create package archive")\n"
	printf -- "$(gettext "  --nocheck        Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
	printf -- "$(gettext "  --noprepare      Do not run the %s function in the %s")\n" "prepare()" "$BUILDSCRIPT"
	printf -- "$(gettext "  --nosign         Do not create a signature for the package")\n"
	printf -- "$(gettext "  --packagelist    Only list packages that would be produced, without PKGEXT")\n"
	printf -- "$(gettext "  --printsrcinfo   Print the generated SRCINFO and exit")\n"
	printf -- "$(gettext "  --sign           Sign the resulting package with %s")\n" "gpg"
	printf -- "$(gettext "  --skipchecksums  Do not verify checksums of the source files")\n"
	printf -- "$(gettext "  --skipinteg      Do not perform any verification checks on source files")\n"
	printf -- "$(gettext "  --skippgpcheck   Do not verify source files with PGP signatures")\n"
	printf -- "$(gettext "  --verifysource   Download source files (if needed) and perform integrity checks")\n"
	echo
	printf -- "$(gettext "These options can be passed to %s:")\n" "pacman"
	echo
	printf -- "$(gettext "  --asdeps         Install packages as non-explicitly installed")\n"
	printf -- "$(gettext "  --needed         Do not reinstall the targets that are already up to date")\n"
	printf -- "$(gettext "  --noconfirm      Do not ask for confirmation when resolving dependencies")\n"
	printf -- "$(gettext "  --noprogressbar  Do not show a progress bar when downloading files")\n"
	echo
	printf -- "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT"
	echo
}

version() {
	printf "makepkg (pacman) %s\n" "$makepkg_version"
	printf -- "$(gettext "\
Copyright (c) 2006-2016 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

# ensure we have a sane umask set
umask 0022

# determine whether we have gettext; make it a no-op if we do not
if ! type -p gettext >/dev/null; then
	gettext() {
		printf "%s\n" "$@"
	}
else
	gettext() {
		/usr/bin/gettext "$@"
	}
fi

ARGLIST=("$@")

# Parse Command Line Options.
OPT_SHORT="AcCdefghiLmop:rRsSV"
OPT_LONG=('allsource' 'check' 'clean' 'cleanbuild' 'config:' 'force' 'geninteg'
          'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'noarchive' 'nobuild'
          'nocolor' 'nocheck' 'nodeps' 'noextract' 'noprepare' 'nosign' 'packagelist'
          'printsrcinfo' 'repackage' 'rmdeps' 'sign' 'skipchecksums' 'skipinteg'
          'skippgpcheck' 'source' 'syncdeps' 'verifysource' 'version')

# Pacman Options
OPT_LONG+=('asdeps' 'noconfirm' 'needed' 'noprogressbar')

if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
	exit 1 # E_INVALID_OPTION;
fi
set -- "${OPTRET[@]}"
unset OPT_SHORT OPT_LONG OPTRET

while true; do
	case "$1" in
		# Pacman Options
		--asdeps)         ASDEPS=1;;
		--needed)         NEEDED=1;;
		--noconfirm)      PACMAN_OPTS+=" --noconfirm" ;;
		--noprogressbar)  PACMAN_OPTS+=" --noprogressbar" ;;

		# Makepkg Options
		--allsource)      SOURCEONLY=2 ;;
		-A|--ignorearch)  IGNOREARCH=1 ;;
		-c|--clean)       CLEANUP=1 ;;
		-C|--cleanbuild)  CLEANBUILD=1 ;;
		--check)          RUN_CHECK='y' ;;
		--config)         shift; MAKEPKG_CONF=$1 ;;
		-d|--nodeps)      NODEPS=1 ;;
		-e|--noextract)   NOEXTRACT=1 ;;
		-f|--force)       FORCE=1 ;;
		# generating integrity checks does not depend on architecture
		-g|--geninteg)    GENINTEG=1 IGNOREARCH=1;;
		--holdver)        HOLDVER=1 ;;
		-i|--install)     INSTALL=1 ;;
		--key)            shift; GPGKEY=$1 ;;
		-L|--log)         LOGGING=1 ;;
		-m|--nocolor)     USE_COLOR='n'; PACMAN_OPTS+=" --color never" ;;
		--noarchive)      NOARCHIVE=1 ;;
		--nocheck)        RUN_CHECK='n' ;;
		--noprepare)      RUN_PREPARE='n' ;;
		--nosign)         SIGNPKG='n' ;;
		-o|--nobuild)     NOBUILD=1 ;;
		-p)               shift; BUILDFILE=$1 ;;
		--packagelist)    PACKAGELIST=1 IGNOREARCH=1;;
		--printsrcinfo)   PRINTSRCINFO=1 ;;
		-r|--rmdeps)      RMDEPS=1 ;;
		-R|--repackage)   REPKG=1 ;;
		--sign)           SIGNPKG='y' ;;
		--skipchecksums)  SKIPCHECKSUMS=1 ;;
		--skipinteg)      SKIPCHECKSUMS=1; SKIPPGPCHECK=1 ;;
		--skippgpcheck)   SKIPPGPCHECK=1;;
		-s|--syncdeps)    DEP_BIN=1 ;;
		-S|--source)      SOURCEONLY=1 ;;
		--verifysource)   VERIFYSOURCE=1 ;;

		-h|--help)        usage; exit 0 ;; # E_OK
		-V|--version)     version; exit 0 ;; # E_OK

		--)               OPT_IND=0; shift; break 2;;
	esac
	shift
done

# attempt to consume any extra argv as environment variables. this supports
# overriding (e.g. CC=clang) as well as overriding (e.g. CFLAGS+=' -g').
extra_environment=()
while [[ $1 ]]; do
	if [[ $1 = [_[:alpha:]]*([[:alnum:]_])?(+)=* ]]; then
		extra_environment+=("$1")
	fi
	shift
done

# setup signal traps
trap 'clean_up' 0
for signal in TERM HUP QUIT; do
	trap "trap_exit $signal \"$(gettext "%s signal caught. Exiting...")\" \"$signal\"" "$signal"
done
trap 'trap_exit INT "$(gettext "Aborted by user! Exiting...")"' INT
trap 'trap_exit USR1 "$(gettext "An unknown error has occurred. Exiting...")"' ERR

# preserve environment variables and canonicalize path
[[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST})
[[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST})
[[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST})
[[ -n ${LOGDEST} ]] && _LOGDEST=$(canonicalize_path ${LOGDEST})
[[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR})
[[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT}
[[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT}
[[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY}
[[ -n ${PACKAGER} ]] && _PACKAGER=${PACKAGER}
[[ -n ${CARCH} ]] && _CARCH=${CARCH}

# 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_safe "$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, but only if no override config
# file was specified
XDG_PACMAN_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/pacman"
if [[ "$MAKEPKG_CONF" = "$confdir/makepkg.conf" ]]; then
	if [[ -r "$XDG_PACMAN_DIR/makepkg.conf" ]]; then
		source_safe "$XDG_PACMAN_DIR/makepkg.conf"
	elif [[ -r "$HOME/.makepkg.conf" ]]; then
		source_safe "$HOME/.makepkg.conf"
	fi
fi

# set pacman command if not already defined
PACMAN=${PACMAN:-pacman}
# save full path to command as PATH may change when sourcing /etc/profile
PACMAN_PATH=$(type -P $PACMAN)

# check if messages are to be printed using color
if [[ -t 2 && $USE_COLOR != "n" ]] && check_buildenv "color" "y"; then
	colorize
else
	unset ALL_OFF BOLD BLUE GREEN RED YELLOW
fi


# override settings with an environment variable for batch processing
BUILDDIR=${_BUILDDIR:-$BUILDDIR}
BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined
if [[ ! -d $BUILDDIR ]]; then
	if ! mkdir -p "$BUILDDIR"; then
		error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
		plain "$(gettext "Aborting...")"
		exit 1
	fi
	chmod a-s "$BUILDDIR"
fi
if [[ ! -w $BUILDDIR ]]; then
	error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR"
	plain "$(gettext "Aborting...")"
	exit 1
fi

# override settings from extra variables on commandline, if any
if (( ${#extra_environment[*]} )); then
	export "${extra_environment[@]}"
fi

PKGDEST=${_PKGDEST:-$PKGDEST}
PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined
if (( ! (NOBUILD || GENINTEG) )) && [[ ! -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:-$startdir} #default to $startdir if undefined
if (( SOURCEONLY )); then
	if [[ ! -w $SRCPKGDEST ]]; then
		error "$(gettext "You do not have write permission to store source tarballs in %s.")" "$SRCPKGDEST"
		plain "$(gettext "Aborting...")"
		exit 1
	fi

	# If we're only making a source tarball, then we need to ignore architecture-
	# dependent behavior.
	IGNOREARCH=1
fi

LOGDEST=${_LOGDEST:-$LOGDEST}
LOGDEST=${LOGDEST:-$startdir} #default to $startdir if undefined
if (( LOGGING )) && [[ ! -w $LOGDEST ]]; then
	error "$(gettext "You do not have write permission to store logs in %s.")" "$LOGDEST"
	plain "$(gettext "Aborting...")"
	exit 1
fi

PKGEXT=${_PKGEXT:-$PKGEXT}
SRCEXT=${_SRCEXT:-$SRCEXT}
GPGKEY=${_GPGKEY:-$GPGKEY}
PACKAGER=${_PACKAGER:-$PACKAGER}
CARCH=${_CARCH:-$CARCH}

unset pkgname pkgbase pkgver pkgrel epoch pkgdesc url license groups provides
unset md5sums replaces depends conflicts backup source install changelog build
unset makedepends optdepends options noextract validpgpkeys

BUILDFILE=${BUILDFILE:-$BUILDSCRIPT}
if [[ ! -f $BUILDFILE ]]; then
	error "$(gettext "%s does not exist.")" "$BUILDFILE"
	exit 1
else
	if [[ $(<"$BUILDFILE") = *$'\r'* ]]; then
		error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF"
		exit 1
	fi

	if [[ ! $BUILDFILE -ef $PWD/${BUILDFILE##*/} ]]; then
		error "$(gettext "%s must be in the current working directory.")" "$BUILDFILE"
		exit 1
	fi

	if [[ ${BUILDFILE:0:1} != "/" ]]; then
		BUILDFILE="$startdir/$BUILDFILE"
	fi
	source_buildfile "$BUILDFILE"
fi

pkgbase=${pkgbase:-${pkgname[0]}}

# check the PKGBUILD for some basic requirements
lint_pkgbuild || exit 1

if (( !SOURCEONLY )); then
	merge_arch_attrs
fi

basever=$(get_full_version)

if [[ $BUILDDIR = "$startdir" ]]; then
	srcdir="$BUILDDIR/src"
	pkgdirbase="$BUILDDIR/pkg"
else
	srcdir="$BUILDDIR/$pkgbase/src"
	pkgdirbase="$BUILDDIR/$pkgbase/pkg"

fi

# set pkgdir to something "sensible" for (not recommended) use during build()
pkgdir="$pkgdirbase/$pkgbase"

if (( GENINTEG )); then
	mkdir -p "$srcdir"
	chmod a-s "$srcdir"
	cd_safe "$srcdir"
	download_sources novcs allarch
	generate_checksums
	exit 0 # $E_OK
fi

if have_function pkgver; then
	PKGVERFUNC=1
fi

# check we have the software required to process the PKGBUILD
check_software || exit 1

if (( ${#pkgname[@]} > 1 )); then
	SPLITPKG=1
fi

# test for available PKGBUILD functions
if have_function prepare; then
	# "Hide" prepare() function if not going to be run
	if [[ $RUN_PREPARE != "n" ]]; then
		PREPAREFUNC=1
	fi
fi
if have_function build; then
	BUILDFUNC=1
fi
if have_function check; then
	# "Hide" check() function if not going to be run
	if [[ $RUN_CHECK = 'y' ]] || { ! check_buildenv "check" "n" && [[ $RUN_CHECK != "n" ]]; }; then
		CHECKFUNC=1
	fi
fi
if have_function package; then
	PKGFUNC=1
elif [[ $SPLITPKG -eq 0 ]] && have_function package_${pkgname}; then
	SPLITPKG=1
fi

# check if gpg signature is to be created and if signing key is valid
if { [[ -z $SIGNPKG ]] && check_buildenv "sign" "y"; } || [[ $SIGNPKG == 'y' ]]; then
	SIGNPKG='y'
	if ! gpg --list-key ${GPGKEY} &>/dev/null; then
		if [[ ! -z $GPGKEY ]]; then
			error "$(gettext "The key %s does not exist in your keyring.")" "${GPGKEY}"
		else
			error "$(gettext "There is no key in your keyring.")"
		fi
		exit 1
	fi
fi

if (( PACKAGELIST )); then
	print_all_package_names
	exit 0
fi

if (( PRINTSRCINFO )); then
	write_srcinfo_content
	exit 0
fi

if (( ! PKGVERFUNC )); then
	check_build_status
fi

msg "$(gettext "Making package: %s")" "$pkgbase $basever ($(date))"

# if we are creating a source-only package, go no further
if (( SOURCEONLY )); then
	if [[ -f $SRCPKGDEST/${pkgbase}-${basever}${SRCEXT} ]] \
			&& (( ! FORCE )); then
		error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f"
		exit 1
	fi

	# Get back to our src directory so we can begin with sources.
	mkdir -p "$srcdir"
	chmod a-s "$srcdir"
	cd_safe "$srcdir"
	if (( SOURCEONLY == 2 )); then
		download_sources allarch
	elif ( (( ! SKIPCHECKSUMS )) || \
			( (( ! SKIPPGPCHECK )) && source_has_signatures ) ); then
		download_sources allarch novcs
	fi
	check_source_integrity all
	cd_safe "$startdir"

	create_srcpackage

	msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))"
	exit 0
fi

if (( NODEPS || ( VERIFYSOURCE && !DEP_BIN ) )); then
	if (( NODEPS )); then
		warning "$(gettext "Skipping dependency checks.")"
	fi
else
	if (( RMDEPS && ! INSTALL )); then
		original_pkglist=($(run_pacman -Qq))    # required by remove_dep
	fi
	deperr=0

	msg "$(gettext "Checking runtime dependencies...")"
	resolve_deps ${depends[@]} || deperr=1

	if (( RMDEPS && INSTALL )); then
		original_pkglist=($(run_pacman -Qq))    # required by remove_dep
	fi

	msg "$(gettext "Checking buildtime dependencies...")"
	if (( CHECKFUNC )); then
		resolve_deps "${makedepends[@]}" "${checkdepends[@]}" || deperr=1
	else
		resolve_deps "${makedepends[@]}" || deperr=1
	fi

	if (( RMDEPS )); then
		current_pkglist=($(run_pacman -Qq))    # required by remove_deps
	fi

	if (( deperr )); then
		error "$(gettext "Could not resolve all dependencies.")"
		exit 1
	fi
fi

# get back to our src directory so we can begin with sources
mkdir -p "$srcdir"
chmod a-s "$srcdir"
cd_safe "$srcdir"

if (( !REPKG )); then
	if (( NOEXTRACT && ! VERIFYSOURCE )); then
		warning "$(gettext "Using existing %s tree")" "\$srcdir/"
	else
		download_sources
		check_source_integrity
		(( VERIFYSOURCE )) && exit 0 # $E_OK

		if (( CLEANBUILD )); then
			msg "$(gettext "Removing existing %s directory...")" "\$srcdir/"
			rm -rf "$srcdir"/*
		fi

		extract_sources
		if (( PREPAREFUNC )); then
			run_prepare
		fi
	fi

	if (( PKGVERFUNC )); then
		update_pkgver
		basever=$(get_full_version)
		check_build_status
	fi
fi

if (( NOBUILD )); then
	msg "$(gettext "Sources are ready.")"
	exit 0 #E_OK
else
	# clean existing pkg directory
	if [[ -d $pkgdirbase ]]; then
		msg "$(gettext "Removing existing %s directory...")" "\$pkgdir/"
		rm -rf "$pkgdirbase"
	fi
	mkdir -p "$pkgdirbase"
	chmod a-srw "$pkgdirbase"
	cd_safe "$startdir"

	if (( ! REPKG )); then
		(( BUILDFUNC )) && run_build
		(( CHECKFUNC )) && run_check
		cd_safe "$startdir"
	fi

	# if inhibiting archive creation, go no further
	if (( NOARCHIVE )); then
		msg "$(gettext "Package directory is ready.")"
		exit 0
	fi
	mkdir -p "$pkgdirbase"
	chmod a-srwx "$pkgdirbase"
	chmod 755 "$pkgdirbase"
	if (( ! SPLITPKG )); then
		pkgdir="$pkgdirbase/$pkgname"
		# clean existing pkg directory
		if [[ -d $pkgdir ]]; then
			msg "$(gettext "Removing existing %s directory...")" "\$pkgdir/"
			rm -rf "$pkgdir"
		fi
		mkdir "$pkgdir"
		if (( PKGFUNC )); then
			run_package
		fi
		tidy_install
		lint_package
		create_package
		create_debug_package
	else
		run_split_packaging
	fi
fi

msg "$(gettext "Finished making: %s")" "$pkgbase $basever ($(date))"

install_package

exit 0 #E_OK

# vim: set noet:
