From 5657a2a461e5bcbdb58f6e872eed7a6f5e3c6ea3 Mon Sep 17 00:00:00 2001 From: Shadowigor Date: Sat, 10 Sep 2016 11:25:11 +0200 Subject: [PATCH 1/2] Added script to automatically update the PKGBUILD --- packaging/ARCH/PKGBUILD | 32 - packaging/ARCH/makepkg | 2400 ++++++++++++++++++++++++++++ packaging/ARCH/mksrcinfo | 262 +++ packaging/ARCH/update-osync-pkg.sh | 11 + 4 files changed, 2673 insertions(+), 32 deletions(-) delete mode 100644 packaging/ARCH/PKGBUILD create mode 100755 packaging/ARCH/makepkg create mode 100755 packaging/ARCH/mksrcinfo create mode 100755 packaging/ARCH/update-osync-pkg.sh diff --git a/packaging/ARCH/PKGBUILD b/packaging/ARCH/PKGBUILD deleted file mode 100644 index 62b86ab..0000000 --- a/packaging/ARCH/PKGBUILD +++ /dev/null @@ -1,32 +0,0 @@ -# Maintainer: Shadowigor -pkgname="osync" -pkgver=v1.00.r219.f70d8cd -pkgrel=1 -pkgdesc="A two way filesync script" -arch=("any") -url="https://github.com/deajan/osync" -license=('custom') -depends=('rsync') -makedepends=('git') -provides=("$pkgname") -source=('git+https://github.com/deajan/osync.git#branch=stable') -md5sums=('SKIP') - -pkgver() -{ - cd "$srcdir/$pkgname" - printf "%s" "$(git describe --long | sed 's/\([^-]*-\)g/r\1/;s/-/./g')" -} - -prepare() -{ - cd "$pkgname" - find . -type f -exec sed -i "s:/usr/local:/usr:g" {} ";" - find . -type f -exec sed -i "s:/lib:/usr/lib:g" {} ";" -} - -package() -{ - cd "$pkgname" - echo n | FAKEROOT="$pkgdir" bash ./install.sh > /dev/null -} diff --git a/packaging/ARCH/makepkg b/packaging/ARCH/makepkg new file mode 100755 index 0000000..fa46214 --- /dev/null +++ b/packaging/ARCH/makepkg @@ -0,0 +1,2400 @@ +#!/usr/bin/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 +# Copyright (c) 2002-2006 by Judd Vinet +# Copyright (c) 2005 by Aurelien Foret +# Copyright (c) 2006 by Miklos Vajna +# Copyright (c) 2005 by Christian Hamar +# Copyright (c) 2006 by Alex Smith +# Copyright (c) 2006 by Andras Voroskoi +# +# 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 . +# + +# 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, fakeroot, 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 +INFAKEROOT=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 + +### 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 + + if (( ! INFAKEROOT )); then + echo + error "$@" + fi + [[ -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 (( INFAKEROOT )); then + # Don't clean up when leaving fakeroot, we're not done yet. + return + fi + + 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" + 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 + if [[ $1 != -@(T|Qq|Q) ]]; then + if type -p sudo >/dev/null; then + cmd=(sudo "${cmd[@]}") + else + cmd=(su root -c "$(printf '%q ' "${cmd[@]}")") + fi + 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 + # 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 = *.so ]]; then + sodepends=1; + break; + fi + done + + if (( sodepends == 0 )); then + printf '%s\n' "${depends[@]}" + return; + fi + + local libdeps filename soarch sofile soname soversion; + declare -A libdeps; + + while read -r filename; do + # get architecture of the file; if soarch is empty it's not an ELF binary + soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') + [[ -n "$soarch" ]] || continue + + # process all libraries needed by the binary + for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p') + do + # extract the library name: libfoo.so + soname="${sofile%.so?(+(.+([0-9])))}".so + # extract the major version: 1 + soversion="${sofile##*\.so\.}" + + if [[ ${libdeps[$soname]} ]]; then + if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then + libdeps[$soname]+=" ${soversion}-${soarch}" + fi + else + libdeps[$soname]="${soversion}-${soarch}" + fi + done + done < <(find "$pkgdir" -type f -perm -u+x) + + local libdepends v + for d in "${depends[@]}"; do + case "$d" in + *.so) + 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 + *.so) + 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 + # check if we really have a shared object + if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then + # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1) + local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') + if [[ -z "$sofile" ]]; then + warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p" + libprovides+=("$p") + continue + fi + + # get the library architecture (32 or 64 bit) + local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') + + # extract the library major version + local soversion="${sofile##*\.so\.}" + + libprovides+=("${p}=${soversion}-${soarch}") + else + warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p" + libprovides+=("$p") + fi + 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 "# using %s\n" "$(fakeroot -v)" + 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 -} ;; + *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/usr/lib/debug"; 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 + + # check for sudo if we will need it during makepkg execution + if (( DEP_BIN || RMDEPS || INSTALL )); then + if ! type -p sudo >/dev/null; then + warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su" + fi + fi + + # fakeroot - correct package file permissions + if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then + if ! type -p fakeroot >/dev/null; then + error "$(gettext "Cannot find the %s binary.")" "fakeroot" + 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" + 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 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 Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" + printf -- "$(gettext " --holdver Do not update VCS sources")\n" + printf -- "$(gettext " --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 .\n\ +Copyright (C) 2002-2006 Judd Vinet .\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" "$@" + } +fi + +ARGLIST=("$@") + +# Parse Command Line Options. +OPT_SHORT="AcCdefFghiLmop: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 ;; + -F) INFAKEROOT=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} + +if (( ! INFAKEROOT )); then + if (( EUID == 0 )); then + error "$(gettext "Running %s as root is not allowed as it can cause permanent,\n\ +catastrophic damage to your system.")" "makepkg" + exit 1 # $E_USER_ABORT + fi +else + if [[ -z $FAKEROOTKEY ]]; then + error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg" + exit 1 # TODO: error code + fi +fi + +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 + +# Run the bare minimum in fakeroot +if (( INFAKEROOT )); then + if (( SOURCEONLY )); then + create_srcpackage + msg "$(gettext "Leaving %s environment.")" "fakeroot" + exit 0 # $E_OK + fi + + chmod 755 "$pkgdirbase" + if (( ! SPLITPKG )); then + pkgdir="$pkgdirbase/$pkgname" + mkdir "$pkgdir" + if (( PKGFUNC )); then + run_package + fi + tidy_install + lint_package + create_package + create_debug_package + else + run_split_packaging + fi + + msg "$(gettext "Leaving %s environment.")" "fakeroot" + exit 0 # $E_OK +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" + + enter_fakeroot + + 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 + + enter_fakeroot +fi + +# if inhibiting archive creation, go no further +if (( NOARCHIVE )); then + msg "$(gettext "Package directory is ready.")" + exit 0 +fi + +msg "$(gettext "Finished making: %s")" "$pkgbase $basever ($(date))" + +install_package + +exit 0 #E_OK + +# vim: set noet: diff --git a/packaging/ARCH/mksrcinfo b/packaging/ARCH/mksrcinfo new file mode 100755 index 0000000..fd3990b --- /dev/null +++ b/packaging/ARCH/mksrcinfo @@ -0,0 +1,262 @@ +#!/bin/bash + +shopt -s extglob + +array_build() { + local dest=$1 src=$2 i keys values + + # it's an error to try to copy a value which doesn't exist. + declare -p "$2" &>/dev/null || return 1 + + # Build an array of the indicies of the source array. + eval "keys=(\"\${!$2[@]}\")" + + # Clear the destination array + eval "$dest=()" + + # Read values indirectly via their index. This approach gives us support + # for associative arrays, sparse arrays, and empty strings as elements. + for i in "${keys[@]}"; do + values+=("printf -v '$dest[$i]' %s \"\${$src[$i]}\";") + done + + eval "${values[*]}" +} + +funcgrep() { + { declare -f "$1" || declare -f package; } 2>/dev/null | grep -E "$2" +} + +extract_global_var() { + # $1: variable name + # $2: multivalued + # $3: name of output var + + local attr=$1 isarray=$2 outputvar=$3 + + if (( isarray )); then + declare -n ref=$attr + # Still need to use array_build here because we can't handle the scoping + # semantics that would be included with the use of 'declare -n'. + [[ ${ref[@]} ]] && array_build "$outputvar" "$attr" + else + [[ ${!attr} ]] && printf -v "$outputvar" %s "${!attr}" + fi +} + +extract_function_var() { + # $1: function name + # $2: variable name + # $3: multivalued + # $4: name of output var + + local funcname=$1 attr=$2 isarray=$3 outputvar=$4 attr_regex= decl= r=1 + + if (( isarray )); then + printf -v attr_regex '^[[:space:]]* %s\+?=\(' "$2" + else + printf -v attr_regex '^[[:space:]]* %s\+?=[^(]' "$2" + fi + + while read -r; do + # strip leading whitespace and any usage of declare + decl=${REPLY##*([[:space:]])} + eval "${decl/#$attr/$outputvar}" + + # entering this loop at all means we found a match, so notify the caller. + r=0 + done < <(funcgrep "$funcname" "$attr_regex") + + return $r +} + +pkgbuild_get_attribute() { + # $1: package name + # $2: attribute name + # $3: multivalued + # $4: name of output var + + local pkgname=$1 attrname=$2 isarray=$3 outputvar=$4 + + printf -v "$outputvar" %s '' + + if [[ $pkgname ]]; then + extract_global_var "$attrname" "$isarray" "$outputvar" + extract_function_var "package_$pkgname" "$attrname" "$isarray" "$outputvar" + else + extract_global_var "$attrname" "$isarray" "$outputvar" + fi +} + +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 pkgbuild_get_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 + + pkgbuild_get_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 {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 +} + +srcinfo_write() { + local pkg + + srcinfo_write_global + + for pkg in "${pkgname[@]}"; do + srcinfo_write_package "$pkg" + done +} + +clear_environment() { + local environ + + mapfile -t environ < <(compgen -A variable | + grep -xvF "$(printf '%s\n' "$@")") + + # expect that some variables marked read only will complain here + unset -v "${environ[@]}" 2>/dev/null +} + +srcinfo_write_from_pkgbuild() {( + clear_environment PATH + + shopt -u extglob + . "$1" || exit 1 + shopt -s extglob + srcinfo_write +)} + + +usage() { + printf '%s\n' \ + 'mksrcinfo v8' \ + '' \ + 'mksrcinfo reads the target PKGBUILD and writes an equivalent .SRCINFO.' \ + 'Without passing any arguments, mksrcinfo will read from $PWD/PKGBUILD' \ + 'and write to $PWD/.SRCINFO.' \ + '' \ + 'Usage: mksrcinfo [/path/to/pkgbuild]' \ + ' -h display this help message and exit' \ + ' -o write output to ' +} + +error() { + printf "==> ERROR: $1\n" "${@:2}" >&2 +} + +die() { + error "$@" + exit 1 +} + +write_srcinfo_header() { + local timefmt='%a %b %e %H:%M:%S %Z %Y' + + # fiddle with the environment to ensure we get the a consistent language and + # timezone. + TZ=UTC LC_TIME=C \ + printf "# Generated by mksrcinfo %s\n# %($timefmt)T\n" 'v8' -1 +} + +srcinfo_dest=$PWD/.SRCINFO + +while getopts ':o:h' flag; do + case $flag in + o) + srcinfo_dest=$OPTARG + ;; + :) + die "option '-%s' requires an argument" "$OPTARG" + ;; + h) + usage + exit 0 + ;; + \?) + die "invalid option -- '-%s' (use -h for help)" "$OPTARG" + ;; + esac +done +shift $(( OPTIND - 1 )) + +[[ -f PKGBUILD ]] || die 'PKGBUILD not found in current directory' + +# TODO: replace this with 'makepkg --printsrcinfo' once makepkg>=4.3 is released. +{ + write_srcinfo_header + srcinfo_write_from_pkgbuild "${1:-$PWD/PKGBUILD}" +} >"$srcinfo_dest" + +# vim: set et ts=2 sw=2: diff --git a/packaging/ARCH/update-osync-pkg.sh b/packaging/ARCH/update-osync-pkg.sh new file mode 100755 index 0000000..a87dec4 --- /dev/null +++ b/packaging/ARCH/update-osync-pkg.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +git clone git+ssh://aur@aur.archlinux.org/osync.git osync.aur +cd "osync.aur" && +../makepkg -c && +rm -rf osync* && +../mksrcinfo && +git push origin master && +cd .. && +rm -rf "osync.aur" && +echo "Package updated successfully" From 38dc01ee399fcedccb744fd72d0d9b5b733434f0 Mon Sep 17 00:00:00 2001 From: Shadowigor Date: Sat, 10 Sep 2016 12:35:54 +0200 Subject: [PATCH 2/2] Removed makepkg dependency --- packaging/ARCH/makepkg | 2400 ---------------------------- packaging/ARCH/update-osync-pkg.sh | 13 +- 2 files changed, 10 insertions(+), 2403 deletions(-) delete mode 100755 packaging/ARCH/makepkg diff --git a/packaging/ARCH/makepkg b/packaging/ARCH/makepkg deleted file mode 100755 index fa46214..0000000 --- a/packaging/ARCH/makepkg +++ /dev/null @@ -1,2400 +0,0 @@ -#!/usr/bin/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 -# Copyright (c) 2002-2006 by Judd Vinet -# Copyright (c) 2005 by Aurelien Foret -# Copyright (c) 2006 by Miklos Vajna -# Copyright (c) 2005 by Christian Hamar -# Copyright (c) 2006 by Alex Smith -# Copyright (c) 2006 by Andras Voroskoi -# -# 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 . -# - -# 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, fakeroot, 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 -INFAKEROOT=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 - -### 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 - - if (( ! INFAKEROOT )); then - echo - error "$@" - fi - [[ -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 (( INFAKEROOT )); then - # Don't clean up when leaving fakeroot, we're not done yet. - return - fi - - 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" - 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 - if [[ $1 != -@(T|Qq|Q) ]]; then - if type -p sudo >/dev/null; then - cmd=(sudo "${cmd[@]}") - else - cmd=(su root -c "$(printf '%q ' "${cmd[@]}")") - fi - 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 - # 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 = *.so ]]; then - sodepends=1; - break; - fi - done - - if (( sodepends == 0 )); then - printf '%s\n' "${depends[@]}" - return; - fi - - local libdeps filename soarch sofile soname soversion; - declare -A libdeps; - - while read -r filename; do - # get architecture of the file; if soarch is empty it's not an ELF binary - soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') - [[ -n "$soarch" ]] || continue - - # process all libraries needed by the binary - for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p') - do - # extract the library name: libfoo.so - soname="${sofile%.so?(+(.+([0-9])))}".so - # extract the major version: 1 - soversion="${sofile##*\.so\.}" - - if [[ ${libdeps[$soname]} ]]; then - if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then - libdeps[$soname]+=" ${soversion}-${soarch}" - fi - else - libdeps[$soname]="${soversion}-${soarch}" - fi - done - done < <(find "$pkgdir" -type f -perm -u+x) - - local libdepends v - for d in "${depends[@]}"; do - case "$d" in - *.so) - 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 - *.so) - 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 - # check if we really have a shared object - if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then - # get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1) - local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') - if [[ -z "$sofile" ]]; then - warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p" - libprovides+=("$p") - continue - fi - - # get the library architecture (32 or 64 bit) - local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') - - # extract the library major version - local soversion="${sofile##*\.so\.}" - - libprovides+=("${p}=${soversion}-${soarch}") - else - warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p" - libprovides+=("$p") - fi - 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 "# using %s\n" "$(fakeroot -v)" - 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 -} ;; - *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/usr/lib/debug"; 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 - - # check for sudo if we will need it during makepkg execution - if (( DEP_BIN || RMDEPS || INSTALL )); then - if ! type -p sudo >/dev/null; then - warning "$(gettext "Cannot find the %s binary. Will use %s to acquire root privileges.")" "sudo" "su" - fi - fi - - # fakeroot - correct package file permissions - if check_buildenv "fakeroot" "y" && (( EUID > 0 )); then - if ! type -p fakeroot >/dev/null; then - error "$(gettext "Cannot find the %s binary.")" "fakeroot" - 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" - 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 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 Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" - printf -- "$(gettext " --holdver Do not update VCS sources")\n" - printf -- "$(gettext " --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 .\n\ -Copyright (C) 2002-2006 Judd Vinet .\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" "$@" - } -fi - -ARGLIST=("$@") - -# Parse Command Line Options. -OPT_SHORT="AcCdefFghiLmop: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 ;; - -F) INFAKEROOT=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} - -if (( ! INFAKEROOT )); then - if (( EUID == 0 )); then - error "$(gettext "Running %s as root is not allowed as it can cause permanent,\n\ -catastrophic damage to your system.")" "makepkg" - exit 1 # $E_USER_ABORT - fi -else - if [[ -z $FAKEROOTKEY ]]; then - error "$(gettext "Do not use the %s option. This option is only for use by %s.")" "'-F'" "makepkg" - exit 1 # TODO: error code - fi -fi - -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 - -# Run the bare minimum in fakeroot -if (( INFAKEROOT )); then - if (( SOURCEONLY )); then - create_srcpackage - msg "$(gettext "Leaving %s environment.")" "fakeroot" - exit 0 # $E_OK - fi - - chmod 755 "$pkgdirbase" - if (( ! SPLITPKG )); then - pkgdir="$pkgdirbase/$pkgname" - mkdir "$pkgdir" - if (( PKGFUNC )); then - run_package - fi - tidy_install - lint_package - create_package - create_debug_package - else - run_split_packaging - fi - - msg "$(gettext "Leaving %s environment.")" "fakeroot" - exit 0 # $E_OK -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" - - enter_fakeroot - - 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 - - enter_fakeroot -fi - -# if inhibiting archive creation, go no further -if (( NOARCHIVE )); then - msg "$(gettext "Package directory is ready.")" - exit 0 -fi - -msg "$(gettext "Finished making: %s")" "$pkgbase $basever ($(date))" - -install_package - -exit 0 #E_OK - -# vim: set noet: diff --git a/packaging/ARCH/update-osync-pkg.sh b/packaging/ARCH/update-osync-pkg.sh index a87dec4..57a1e5f 100755 --- a/packaging/ARCH/update-osync-pkg.sh +++ b/packaging/ARCH/update-osync-pkg.sh @@ -1,10 +1,17 @@ #!/bin/bash -git clone git+ssh://aur@aur.archlinux.org/osync.git osync.aur +git clone git+ssh://aur@aur.archlinux.org/osync.git osync.aur && cd "osync.aur" && -../makepkg -c && -rm -rf osync* && +srcdir="." && +source "PKGBUILD" && +url=$(echo -n ${source[0]} | sed 's/git+//g' | sed 's/#.*//g') && +branch=$(echo -n ${source[0]} | sed 's/.*#branch=//g') && +git clone -b $branch $url && +sed -i "s/pkgver=.*/pkgver=$(pkgver)/g" "PKGBUILD" && ../mksrcinfo && +rm -rf "osync" && +git add . && +git commit -m "Updated version" && git push origin master && cd .. && rm -rf "osync.aur" &&