diff options
Diffstat (limited to 'scripts/makepkg.sh.in')
-rw-r--r-- | scripts/makepkg.sh.in | 565 |
1 files changed, 321 insertions, 244 deletions
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index ec664692..16dc0b8f 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -1,9 +1,9 @@ -#!/bin/bash -e +#!@BASH_SHELL@ -e # # makepkg - make packages compatible for use with pacman # @configure_input@ # -# Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org> +# Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> # Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> # Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> # Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> @@ -27,7 +27,7 @@ # makepkg uses quite a few external programs during its execution. You # need to have at least the following installed for makepkg to function: -# bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils), +# awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils), # gettext, grep, gzip, openssl, sed, tput (ncurses), xz # gettext initialization @@ -45,7 +45,7 @@ srcdir="$startdir/src" pkgdir="$startdir/pkg" packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge') -other_options=('ccache' 'distcc' 'makeflags' 'force') +other_options=('ccache' 'distcc' 'buildflags' 'makeflags') splitpkg_overrides=('pkgver' 'pkgrel' 'pkgdesc' 'arch' 'license' 'groups' \ 'depends' 'optdepends' 'provides' 'conflicts' 'replaces' \ 'backup' 'options' 'install' 'changelog') @@ -71,6 +71,7 @@ SOURCEONLY=0 IGNOREARCH=0 HOLDVER=0 BUILDFUNC=0 +CHECKFUNC=0 PKGFUNC=0 SPLITPKG=0 PKGLIST=() @@ -135,25 +136,32 @@ clean_up() { 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 "$pkgdir" "$srcdir" if [[ -n $pkgbase ]]; then + # TODO: this wasn't properly fixed in commit 2020e629 + local fullver=$(get_full_version $epoch $pkgver $pkgrel) # Can't do this unless the BUILDSCRIPT has been sourced. if (( BUILDFUNC )); then - rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-build.log"* + 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}-${pkgver}-${pkgrel}-${CARCH}-package.log"* + rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"* elif (( SPLITPKG )); then for pkg in ${pkgname[@]}; do - rm -f "${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-package_${pkg}.log"* + 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}-*-*-${CARCH}${PKGEXT}; do + for file in ${pkg}-*-*-${CARCH}{${PKGEXT},${SRCEXT}}; do if [[ -h $file && ! -e $file ]]; then rm -f $file fi @@ -219,6 +227,19 @@ get_url() { } ## +# usage : get_full_version( $epoch, $pkgver, $pkgrel ) +# return : full version spec, including epoch (if necessary), pkgver, pkgrel +## +get_full_version() { + if [[ $1 -eq 0 ]]; then + # zero epoch case, don't include it in version + echo $2-$3 + else + echo $1:$2-$3 + fi +} + +## # Checks to see if options are present in makepkg.conf or PKGBUILD; # PKGBUILD options always take precedence. # @@ -308,7 +329,7 @@ get_downloadclient() { for i in "${DLAGENTS[@]}"; do local handler="${i%%::*}" if [[ $proto = $handler ]]; then - agent="${i##*::}" + local agent="${i##*::}" break fi done @@ -323,7 +344,7 @@ get_downloadclient() { # ensure specified program is installed local program="${agent%% *}" if [[ ! -x $program ]]; then - local baseprog=$(basename $program) + local baseprog="${program##*/}" error "$(gettext "The download program %s is not installed.")" "$baseprog" plain "$(gettext "Aborting...")" exit 1 # $E_MISSING_PROGRAM @@ -370,7 +391,7 @@ download_file() { run_pacman() { local cmd printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@" - if (( ! ASROOT )) && [[ $1 != "-T" && $1 != "-Qq" ]]; then + if (( ! ASROOT )) && [[ ! $1 =~ ^-(T|Qq)$ ]]; then if [ "$(type -p sudo)" ]; then cmd="sudo $cmd" else @@ -387,6 +408,7 @@ check_deps() { # Also, a non-zero return value is not unexpected and we are manually dealing them set +E local ret=0 + local pmout pmout=$(run_pacman -T "$@") || ret=$? set -E @@ -394,7 +416,7 @@ check_deps() { echo "$pmout" elif (( ret )); then error "$(gettext "'%s' returned a fatal error (%i): %s")" "$PACMAN" "$ret" "$pmout" - exit 1 + return "$ret" fi } @@ -434,17 +456,16 @@ resolve_deps() { local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 - local deplist="$(check_deps $*)" - if [[ -z $deplist ]]; then - return $R_DEPS_SATISFIED - fi + # 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="$(check_deps $*)" + deplist="$(set +E; check_deps $*)" || exit 1 [[ -z $deplist ]] && return $R_DEPS_SATISFIED - elif (( DEP_BIN )); then - error "$(gettext "Failed to install all missing dependencies.")" fi msg "$(gettext "Missing Dependencies:")" @@ -486,8 +507,8 @@ download_sources() { local netfile for netfile in "${source[@]}"; do - local file - if file=$(get_filepath "$netfile"); then + local file=$(get_filepath "$netfile" || true) + if [[ -n "$file" ]]; then msg2 "$(gettext "Found %s")" "${file##*/}" ln -sf "$file" "$srcdir/" continue @@ -543,7 +564,7 @@ generate_checksums() { msg "$(gettext "Generating checksums for source files...")" plain "" - if [ ! $(type -p openssl) ]; then + if ! type -p openssl >/dev/null; then error "$(gettext "Cannot find openssl.")" exit 1 # $E_MISSING_PROGRAM fi @@ -593,7 +614,7 @@ generate_checksums() { check_checksums() { (( ! ${#source[@]} )) && return 0 - if [ ! $(type -p openssl) ]; then + if ! type -p openssl >/dev/null; then error "$(gettext "Cannot find openssl.")" exit 1 # $E_MISSING_PROGRAM fi @@ -654,7 +675,7 @@ extract_sources() { msg "$(gettext "Extracting Sources...")" local netfile for netfile in "${source[@]}"; do - file=$(get_filename "$netfile") + local file=$(get_filename "$netfile") if in_array "$file" ${noextract[@]}; then #skip source files in the noextract=() array # these are marked explicitly to NOT be extracted @@ -685,9 +706,12 @@ extract_sources() { *) continue;; esac ;; *) - # Don't know what to use to extract this file, - # skip to the next file - continue;; + # See if bsdtar can recognize the file + if bsdtar -tf "$file" -q '*' &>/dev/null; then + cmd="bsdtar" + else + continue + fi ;; esac local ret=0 @@ -717,6 +741,7 @@ error_function() { fi # first exit all subshells, then print the error if (( ! BASH_SUBSHELL )); then + error "$(gettext "A failure occurred in %s().")" "$1" plain "$(gettext "Aborting...")" remove_deps fi @@ -727,7 +752,14 @@ run_function() { if [[ -z $1 ]]; then return 1 fi - pkgfunc="$1" + local pkgfunc="$1" + + # clear user-specified buildflags if requested + if [[ $(check_option buildflags) = "n" ]]; then + CFLAGS="" + CXXFLAGS="" + LDFLAGS="" + fi # clear user-specified makeflags if requested if [[ $(check_option makeflags) = "n" ]]; then @@ -743,8 +775,10 @@ run_function() { local shellopts=$(shopt -p) local ret=0 + local restoretrap if (( LOGGING )); then - BUILDLOG="${startdir}/${pkgbase}-${pkgver}-${pkgrel}-${CARCH}-$pkgfunc.log" + local fullver=$(get_full_version $epoch $pkgver $pkgrel) + local BUILDLOG="${startdir}/${pkgbase}-${fullver}-${CARCH}-$pkgfunc.log" if [[ -f $BUILDLOG ]]; then local i=1 while true; do @@ -759,12 +793,12 @@ run_function() { # ensure overridden package variables survive tee with split packages logpipe=$(mktemp -u "$startdir/logpipe.XXXXXXXX") - mknod "$logpipe" p + mkfifo "$logpipe" exec 3>&1 tee "$BUILDLOG" < "$logpipe" & exec 1>"$logpipe" 2>"$logpipe" restoretrap=$(trap -p ERR) - trap 'error_function' ERR + trap 'error_function $pkgfunc' ERR $pkgfunc 2>&1 eval $restoretrap sync @@ -772,7 +806,7 @@ run_function() { rm "$logpipe" else restoretrap=$(trap -p ERR) - trap 'error_function' ERR + trap 'error_function $pkgfunc' ERR $pkgfunc 2>&1 eval $restoretrap fi @@ -798,7 +832,12 @@ run_build() { run_function "build" } +run_check() { + run_function "check" +} + run_package() { + local pkgfunc if [[ -z $1 ]]; then pkgfunc="package" else @@ -865,13 +904,13 @@ tidy_install() { done fi - if [[ $(check_option strip) = y && -n ${STRIP_DIRS[*]} ]]; then + if [[ $(check_option strip) = y ]]; then msg2 "$(gettext "Stripping unneeded symbols from binaries and libraries...")" # make sure library stripping variables are defined to prevent excess stripping [[ -z ${STRIP_SHARED+x} ]] && STRIP_SHARED="-S" [[ -z ${STRIP_STATIC+x} ]] && STRIP_STATIC="-S" local binary - find ${STRIP_DIRS[@]} -type f -perm -u+w 2>/dev/null | while read binary ; do + find . -type f -perm -u+w 2>/dev/null | while read binary ; do case "$(file -bi "$binary")" in *application/x-sharedlib*) # Libraries (.so) /usr/bin/strip $STRIP_SHARED "$binary";; @@ -905,56 +944,38 @@ write_pkginfo() { size="$(( ${size%%[^0-9]*} * 1024 ))" msg2 "$(gettext "Generating .PKGINFO file...")" - echo "# Generated by makepkg $myver" >.PKGINFO + echo "# Generated by makepkg $myver" if (( INFAKEROOT )); then - echo "# using $(fakeroot -v)" >>.PKGINFO - fi - echo "# $(LC_ALL=C date -u)" >>.PKGINFO - echo "pkgname = $1" >>.PKGINFO - (( SPLITPKG )) && echo pkgbase = $pkgbase >>.PKGINFO - echo "pkgver = $pkgver-$pkgrel" >>.PKGINFO - echo "pkgdesc = $pkgdesc" >>.PKGINFO - echo "url = $url" >>.PKGINFO - echo "builddate = $builddate" >>.PKGINFO - echo "packager = $packager" >>.PKGINFO - echo "size = $size" >>.PKGINFO - echo "arch = $PKGARCH" >>.PKGINFO - if [[ $(check_option force) = "y" ]]; then - echo "force = true" >> .PKGINFO - fi + echo "# using $(fakeroot -v)" + fi + echo "# $(LC_ALL=C date -u)" + echo "pkgname = $1" + (( SPLITPKG )) && echo pkgbase = $pkgbase + echo "pkgver = $(get_full_version $epoch $pkgver $pkgrel)" + echo "pkgdesc = $pkgdesc" + echo "url = $url" + echo "builddate = $builddate" + echo "packager = $packager" + echo "size = $size" + echo "arch = $PKGARCH" + + [[ $license ]] && printf "license = %s\n" "${license[@]}" + [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}" + [[ $groups ]] && printf "group = %s\n" "${groups[@]}" + [[ $depends ]] && printf "depend = %s\n" "${depends[@]}" + [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]}" + [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}" + [[ $provides ]] && printf "provides = %s\n" "${provides[@]}" + [[ $backup ]] && printf "backup = %s\n" "${backup[@]}" local it - for it in "${license[@]}"; do - echo "license = $it" >>.PKGINFO - done - for it in "${replaces[@]}"; do - echo "replaces = $it" >>.PKGINFO - done - for it in "${groups[@]}"; do - echo "group = $it" >>.PKGINFO - done - for it in "${depends[@]}"; do - echo "depend = $it" >>.PKGINFO - done - for it in "${optdepends[@]}"; do - echo "optdepend = $it" >>.PKGINFO - done - for it in "${conflicts[@]}"; do - echo "conflict = $it" >>.PKGINFO - done - for it in "${provides[@]}"; do - echo "provides = $it" >>.PKGINFO - done - for it in "${backup[@]}"; do - echo "backup = $it" >>.PKGINFO - done for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" if [[ $ret != "?" ]]; then if [[ $ret = y ]]; then - echo "makepkgopt = $it" >>.PKGINFO + echo "makepkgopt = $it" else - echo "makepkgopt = !$it" >>.PKGINFO + echo "makepkgopt = !$it" fi fi done @@ -974,14 +995,18 @@ check_package() { local file for file in "${backup[@]}"; do if [[ ! -f $file ]]; then - warning "$(gettext "Invalid backup entry : %s")" "$file" + warning "$(gettext "Backup entry file not in package : %s")" "$file" fi done - # check for references to the build directory - if find "${pkgdir}" -type f -exec grep -q "${srcdir}" {} +; then + # check for references to the build and package directory + if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${srcdir}" ; then warning "$(gettext "Package contains reference to %s")" "\$srcdir" fi + if find "${pkgdir}" -type f -print0 | xargs -0 grep -q -I "${pkgdir}" ; then + warning "$(gettext "Package contains reference to %s")" "\$pkgdir" + fi + } create_package() { @@ -996,6 +1021,7 @@ create_package() { cd "$pkgdir" msg "$(gettext "Creating package...")" + local nameofpkg if [[ -z $1 ]]; then nameofpkg="$pkgname" else @@ -1008,62 +1034,62 @@ create_package() { PKGARCH=$CARCH fi - write_pkginfo $nameofpkg + write_pkginfo $nameofpkg > .PKGINFO local comp_files=".PKGINFO" - # check for an install script - if [[ -n $install ]]; then - msg2 "$(gettext "Adding install script...")" - cp "$startdir/$install" .INSTALL - chmod 644 .INSTALL - comp_files="$comp_files .INSTALL" - fi - - # do we have a changelog? - if [[ -n $changelog ]]; then - msg2 "$(gettext "Adding package changelog...")" - cp "$startdir/$changelog" .CHANGELOG - chmod 644 .CHANGELOG - comp_files="$comp_files .CHANGELOG" - fi + # check for changelog/install files + for i in 'changelog' 'install'; do + orig=${!i} + dest=$(tr '[:lower:]' '[:upper:]' <<<".$i") + + if [[ -n $orig ]]; then + msg2 "$(gettext "Adding %s file...")" "$i" + cp "$startdir/$orig" "$dest" + chmod 644 "$dest" + comp_files+=" $dest" + fi + done # tar it up msg2 "$(gettext "Compressing package...")" + local EXT case "$PKGEXT" in *tar.gz) EXT=${PKGEXT%.gz} ;; *tar.bz2) EXT=${PKGEXT%.bz2} ;; *tar.xz) EXT=${PKGEXT%.xz} ;; + *tar) EXT=${PKGEXT} ;; *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$PKGEXT" ; EXT=$PKGEXT ;; esac - local tar_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${EXT}" - local pkg_file="$PKGDEST/${nameofpkg}-${pkgver}-${pkgrel}-${PKGARCH}${PKGEXT}" + local fullver=$(get_full_version $epoch $pkgver $pkgrel) + local pkg_file="$PKGDEST/${nameofpkg}-${fullver}-${PKGARCH}${PKGEXT}" local ret=0 # when fileglobbing, we want * in an empty directory to expand to # the null string rather than itself shopt -s nullglob - bsdtar -cf - $comp_files * > "$tar_file" || ret=$? - shopt -u nullglob + # TODO: Maybe this can be set globally for robustness + shopt -s -o pipefail + bsdtar -cf - $comp_files * | + case "$PKGEXT" in + *tar.gz) gzip -c -f -n ;; + *tar.bz2) bzip2 -c -f ;; + *tar.xz) xz -c -z - ;; + *tar) cat ;; + esac > ${pkg_file} || ret=$? - if (( ! ret )); then - case "$PKGEXT" in - *tar.gz) gzip -f -n "$tar_file" ;; - *tar.bz2) bzip2 -f "$tar_file" ;; - *tar.xz) xz -z -f "$tar_file" ;; - esac - ret=$? - fi + shopt -u nullglob + shopt -u -o pipefail if (( ret )); then error "$(gettext "Failed to create package file.")" exit 1 # TODO: error code fi - if (( ! ret )) && [[ "$PKGDEST" != "${startdir}" ]]; then + if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then ln -sf "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}" ret=$? fi @@ -1129,11 +1155,13 @@ create_srcpackage() { *tar.gz) TAR_OPT="z" ;; *tar.bz2) TAR_OPT="j" ;; *tar.xz) TAR_OPT="J" ;; + *tar) TAR_OPT="" ;; *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$SRCEXT" ;; esac - local pkg_file="$SRCPKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT}" + local fullver=$(get_full_version $epoch $pkgver $pkgrel) + local pkg_file="$SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT}" # tar it up msg2 "$(gettext "Compressing source package...")" @@ -1142,6 +1170,16 @@ create_srcpackage() { error "$(gettext "Failed to create source package file.")" exit 1 # TODO: error code fi + + if (( ! ret )) && [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then + ln -sf "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}" + ret=$? + fi + + if (( ret )); then + warning "$(gettext "Failed to create symlink to source package file.")" + fi + cd "${startdir}" rm -rf "${srclinks}" } @@ -1155,12 +1193,14 @@ install_package() { msg "$(gettext "Installing %s package group with %s -U...")" "$pkgbase" "$PACMAN" fi - local pkglist + local fullver pkg pkglist for pkg in ${pkgname[@]}; do - if [[ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} ]]; then - pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}" + # TODO: this wasn't properly fixed in commit 2020e629 + fullver=$(get_full_version $epoch $pkgver $pkgrel) + if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} ]]; then + pkglist+=" $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT}" else - pkglist="${pkglist} $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT}" + pkglist+=" $PKGDEST/${pkg}-${fullver}-any${PKGEXT}" fi done @@ -1172,38 +1212,38 @@ install_package() { check_sanity() { # check for no-no's in the build script - if [[ -z $pkgname ]]; then - error "$(gettext "%s is not allowed to be empty.")" "pkgname" - return 1 - fi - if [[ -z $pkgver ]]; then - error "$(gettext "%s is not allowed to be empty.")" "pkgver" - return 1 - fi - if [[ -z $pkgrel ]]; then - error "$(gettext "%s is not allowed to be empty.")" "pkgrel" - return 1 - fi + local i + local ret=0 + for i in 'pkgname' 'pkgrel' 'pkgver'; do + if [[ -z ${!i} ]]; then + error "$(gettext "%s is not allowed to be empty.")" "$i" + ret=1 + fi + done - local name - for name in "${pkgname[@]}"; do - if [[ ${name:0:1} = "-" ]]; then + for i in "${pkgname[@]}"; do + if [[ ${i:0:1} = "-" ]]; then error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgname" - return 1 + ret=1 fi done if [[ ${pkgbase:0:1} = "-" ]]; then error "$(gettext "%s is not allowed to start with a hyphen.")" "pkgbase" - return 1 + ret=1 fi - if [[ $pkgver != ${pkgver//-/} ]]; then - error "$(gettext "%s is not allowed to contain hyphens.")" "pkgver" - return 1 + if [[ $pkgver =~ [:-] ]]; then + error "$(gettext "%s is not allowed to contain colons or hyphens.")" "pkgver" + ret=1 fi if [[ $pkgrel != ${pkgrel//-/} ]]; then error "$(gettext "%s is not allowed to contain hyphens.")" "pkgrel" - return 1 + ret=1 + fi + + if [[ ! $epoch =~ ^[0-9]*$ ]]; then + error "$(gettext "%s must be an integer.")" "epoch" + ret=1 fi if [[ $arch != 'any' ]]; then @@ -1212,36 +1252,39 @@ check_sanity() { error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" plain "$(gettext "such as arch=('%s').")" "$CARCH" - return 1 + ret=1 fi fi fi - local provide - for provide in ${provides[@]}; do - if [[ $provide != ${provide//</} || $provide != ${provide//>/} ]]; then + local provides_list=() + eval $(awk '/^[[:space:]]*provides=/,/\)/' "$BUILDFILE" | sed "s/provides=/provides_list+=/") + for i in ${provides_list[@]}; do + if [[ $i != ${i//</} || $i != ${i//>/} ]]; then error "$(gettext "Provides array cannot contain comparison (< or >) operators.")" - return 1 + ret=1 fi done - local file - for file in "${backup[@]}"; do - if [[ ${file:0:1} = "/" ]]; then - error "$(gettext "Invalid backup entry : %s")" "$file" - return 1 + local backup_list=() + eval $(awk '/^[[:space:]]*backup=/,/\)/' "$BUILDFILE" | sed "s/backup=/backup_list+=/") + for i in "${backup_list[@]}"; do + if [[ ${i:0:1} = "/" ]]; then + error "$(gettext "Backup entry should not contain leading slash : %s")" "$i" + ret=1 fi done - local optdepend - for optdepend in "${optdepends[@]}"; do - pkg=${optdepend%%:*} - if [[ ! $pkg =~ ^[[:alnum:]\>\<\=\.\+\_\-]*$ ]]; then - error "$(gettext "Invalid syntax for optdepend : '%s'")" "$optdepend" + local optdepends_list=() + eval $(awk '/^[[:space:]]*optdepends=/,/\)/' "$BUILDFILE" | sed "s/optdepends=/optdepends_list+=/") + for i in "${optdepends_list[@]}"; do + local pkg=${i%%:*} + if [[ ! $pkg =~ ^[[:alnum:]\>\<\=\.\+\_\-]+$ ]]; then + error "$(gettext "Invalid syntax for optdepend : '%s'")" "$i" + ret=1 fi done - local i for i in 'changelog' 'install'; do local filelist=$(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE") local file @@ -1250,49 +1293,48 @@ check_sanity() { eval file=${file} if [[ ! -f $file ]]; then error "$(gettext "%s file (%s) does not exist.")" "$i" "$file" - return 1 + ret=1 fi done done local valid_options=1 - local opt known kopt - for opt in ${options[@]}; do + local known kopt options_list + eval $(awk '/^[[:space:]]*options=/,/\)/' "$BUILDFILE" | sed "s/options=/options_list+=/") + for i in ${options_list[@]}; do known=0 # check if option matches a known option or its inverse for kopt in ${packaging_options[@]} ${other_options[@]}; do - if [[ ${opt} = ${kopt} || ${opt} = "!${kopt}" ]]; then + if [[ ${i} = ${kopt} || ${i} = "!${kopt}" ]]; then known=1 fi done if (( ! known )); then - error "$(gettext "options array contains unknown option '%s'")" "$opt" + error "$(gettext "options array contains unknown option '%s'")" "$i" valid_options=0 fi done if (( ! valid_options )); then - return 1 + ret=1 fi if (( ${#pkgname[@]} > 1 )); then - for pkg in ${pkgname[@]}; do - if [ "$(type -t package_${pkg})" != "function" ]; then - error "$(gettext "missing package function for split package '%s'")" "$pkg" - return 1 + for i in ${pkgname[@]}; do + if ! declare -f package_${i} >/dev/null; then + error "$(gettext "missing package function for split package '%s'")" "$i" + ret=1 fi done fi - if [[ -n "${PKGLIST[@]}" ]]; then - for pkg in ${PKGLIST[@]}; do - if ! in_array $pkg ${pkgname[@]}; then - error "$(gettext "requested package %s is not provided in %s")" "$pkg" "$BUILDFILE" - return 1 - fi - done - fi + for i in ${PKGLIST[@]}; do + if ! in_array $i ${pkgname[@]}; then + error "$(gettext "requested package %s is not provided in %s")" "$i" "$BUILDFILE" + ret=1 + fi + done - return 0 + return $ret } devel_check() { @@ -1313,27 +1355,27 @@ devel_check() { # Also do a brief check to make sure we have the VCS tool available. oldpkgver=$pkgver if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then - [ $(type -p darcs) ] || return 0 + type -p darcs >/dev/null || return 0 msg "$(gettext "Determining latest darcs revision...")" newpkgver=$(date +%Y%m%d) elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then - [ $(type -p cvs) ] || return 0 + type -p cvs >/dev/null || return 0 msg "$(gettext "Determining latest cvs revision...")" newpkgver=$(date +%Y%m%d) elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then - [ $(type -p git) ] || return 0 + type -p git >/dev/null || return 0 msg "$(gettext "Determining latest git revision...")" newpkgver=$(date +%Y%m%d) elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then - [ $(type -p svn) ] || return 0 + type -p svn >/dev/null || return 0 msg "$(gettext "Determining latest svn revision...")" newpkgver=$(LC_ALL=C svn info $_svntrunk | sed -n 's/^Last Changed Rev: \([0-9]*\)$/\1/p') elif [[ -n ${_bzrtrunk} && -n ${_bzrmod} ]] ; then - [ $(type -p bzr) ] || return 0 + type -p bzr >/dev/null || return 0 msg "$(gettext "Determining latest bzr revision...")" newpkgver=$(bzr revno ${_bzrtrunk}) elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then - [ $(type -p hg) ] || return 0 + type -p hg >/dev/null || return 0 msg "$(gettext "Determining latest hg revision...")" if [[ -d ./src/$_hgrepo ]] ; then cd ./src/$_hgrepo @@ -1380,15 +1422,17 @@ devel_update() { } backup_package_variables() { + local var for var in ${splitpkg_overrides[@]}; do - indirect="${var}_backup" + local indirect="${var}_backup" eval "${indirect}=(\"\${$var[@]}\")" done } restore_package_variables() { + local var for var in ${splitpkg_overrides[@]}; do - indirect="${var}_backup" + local indirect="${var}_backup" if [[ -n ${!indirect} ]]; then eval "${var}=(\"\${$indirect[@]}\")" else @@ -1397,12 +1441,43 @@ restore_package_variables() { done } +run_split_packaging() { + local pkgname_backup=${pkgname[@]} + for pkgname in ${pkgname_backup[@]}; do + pkgdir="$pkgdir/$pkgname" + mkdir -p "$pkgdir" + chmod a-s "$pkgdir" + backup_package_variables + run_package $pkgname + tidy_install + create_package $pkgname + restore_package_variables + pkgdir="${pkgdir%/*}" + done + pkgname=${pkgname_backup[@]} +} + +# Canonicalize a directory path if it exists +canonicalize_path() { + local path="$1"; + + if [[ -d $path ]]; then + ( + cd "$path" + pwd -P + ) + else + echo "$path" + fi +} + # getopt like parser parse_options() { local short_options=$1; shift; local long_options=$1; shift; local ret=0; local unused_options="" + local i while [[ -n $1 ]]; do if [[ ${1:0:2} = '--' ]]; then @@ -1438,7 +1513,7 @@ parse_options() { elif [[ ${1:0:1} = '-' ]]; then for ((i=1; i<${#1}; i++)); do if [[ $short_options =~ ${1:i:1} ]]; then - if [[ $short_options =~ "${1:i:1}:" ]]; then + if [[ $short_options =~ ${1:i:1}: ]]; then if [[ -n ${1:$i+1} ]]; then printf ' -%s' "${1:i:1}" printf " '%s'" "${1:$i+1}" @@ -1508,8 +1583,10 @@ usage() { echo "$(gettext " -s, --syncdeps Install missing dependencies with pacman")" echo "$(gettext " --allsource Generate a source-only tarball including downloaded sources")" echo "$(gettext " --asroot Allow makepkg to run as root user")" + printf "$(gettext " --check Run the check() function in the %s")\n" "$BUILDSCRIPT" printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" - echo "$(gettext " --holdver Prevent automatic version bumping for development PKGBUILDs")" + printf "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT" + printf "$(gettext " --nocheck Do not run the check() function in the %s")\n" "$BUILDSCRIPT" echo "$(gettext " --pkg <list> Only build listed packages from a split package")" echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" @@ -1526,7 +1603,7 @@ usage() { version() { printf "makepkg (pacman) %s\n" "$myver" printf "$(gettext "\ -Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org>.\n\ +Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>.\n\ Copyright (C) 2002-2006 Judd Vinet <jvinet@zeroflux.org>.\n\n\ This is free software; see the source for copying conditions.\n\ There is NO WARRANTY, to the extent permitted by law.\n")" @@ -1535,7 +1612,7 @@ There is NO WARRANTY, to the extent permitted by law.\n")" # PROGRAM START # determine whether we have gettext; make it a no-op if we do not -if [ ! $(type -t gettext) ]; then +if ! type -p gettext >/dev/null; then gettext() { echo "$@" } @@ -1545,12 +1622,12 @@ ARGLIST=("$@") # Parse Command Line Options. OPT_SHORT="AcCdefFghiLmop:rRsV" -OPT_LONG="allsource,asroot,ignorearch,clean,cleancache,nodeps" -OPT_LONG="$OPT_LONG,noextract,force,forcever:,geninteg,help,holdver" -OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,pkg:,rmdeps,repackage,skipinteg" -OPT_LONG="$OPT_LONG,source,syncdeps,version,config:" +OPT_LONG="allsource,asroot,ignorearch,check,clean,cleancache,nodeps" +OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver" +OPT_LONG+=",install,log,nocolor,nobuild,nocheck,pkg:,rmdeps" +OPT_LONG+=",repackage,skipinteg,source,syncdeps,version,config:" # Pacman Options -OPT_LONG="$OPT_LONG,noconfirm,noprogressbar" +OPT_LONG+=",noconfirm,noprogressbar" OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')" if [[ $OPT_TEMP = *'PARSE_OPTIONS FAILED'* ]]; then # This is a small hack to stop the script bailing with 'set -e' @@ -1562,8 +1639,8 @@ unset OPT_SHORT OPT_LONG OPT_TEMP while true; do case "$1" in # Pacman Options - --noconfirm) PACMAN_OPTS="$PACMAN_OPTS --noconfirm" ;; - --noprogressbar) PACMAN_OPTS="$PACMAN_OPTS --noprogressbar" ;; + --noconfirm) PACMAN_OPTS+=" --noconfirm" ;; + --noprogressbar) PACMAN_OPTS+=" --noprogressbar" ;; # Makepkg Options --allsource) SOURCEONLY=2 ;; @@ -1571,6 +1648,7 @@ while true; do -A|--ignorearch) IGNOREARCH=1 ;; -c|--clean) CLEANUP=1 ;; -C|--cleancache) CLEANCACHE=1 ;; + --check) RUN_CHECK='y' ;; --config) shift; MAKEPKG_CONF=$1 ;; -d|--nodeps) NODEPS=1 ;; -e|--noextract) NOEXTRACT=1 ;; @@ -1583,6 +1661,7 @@ while true; do -i|--install) INSTALL=1 ;; -L|--log) LOGGING=1 ;; -m|--nocolor) USE_COLOR='n' ;; + --nocheck) RUN_CHECK='n' ;; -o|--nobuild) NOBUILD=1 ;; -p) shift; BUILDFILE=$1 ;; --pkg) shift; PKGLIST=($1) ;; @@ -1601,10 +1680,10 @@ while true; do shift done -#preserve environment variables -_PKGDEST=${PKGDEST} -_SRCDEST=${SRCDEST} -_SRCPKGDEST=${SRCPKGDEST} +# preserve environment variables and canonicalize path +[[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST}) +[[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST}) +[[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST}) # default config is makepkg.conf MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} @@ -1638,12 +1717,12 @@ if [[ -t 2 && ! $USE_COLOR = "n" && $(check_buildenv color) = "y" ]]; then RED="${BOLD}$(tput setaf 1)" YELLOW="${BOLD}$(tput setaf 3)" else - ALL_OFF="\033[1;0m" - BOLD="\033[1;1m" - BLUE="${BOLD}\033[1;34m" - GREEN="${BOLD}\033[1;32m" - RED="${BOLD}\033[1;31m" - YELLOW="${BOLD}\033[1;33m" + ALL_OFF="\e[1;0m" + BOLD="\e[1;1m" + BLUE="${BOLD}\e[1;34m" + GREEN="${BOLD}\e[1;32m" + RED="${BOLD}\e[1;31m" + YELLOW="${BOLD}\e[1;33m" fi fi readonly ALL_OFF BOLD BLUE GREEN RED YELLOW @@ -1666,7 +1745,7 @@ if [[ ! -w $SRCDEST ]] ; then fi SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST} -SRCPKGDEST=${SRCPKGDEST:-$PKGDEST} #default to $PKGDEST if undefined +SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then @@ -1677,7 +1756,7 @@ fi if (( CLEANCACHE )); then #fix flyspray feature request #5223 - if [[ -n $SRCDEST && $SRCDEST != $startdir ]]; then + if [[ -n $SRCDEST && ! $SRCDEST -ef "${startdir}" ]]; then msg "$(gettext "Cleaning up ALL files from %s.")" "$SRCDEST" echo -n "$(gettext " Are you sure you wish to do this? ")" echo -n "$(gettext "[y/N]")" @@ -1719,7 +1798,7 @@ if (( ! INFAKEROOT )); then plain "$(gettext "Please rerun makepkg without the --asroot flag.")" exit 1 # $E_USER_ABORT elif [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then - if [ ! $(type -p fakeroot) ]; then + if ! type -p fakeroot >/dev/null; then error "$(gettext "Fakeroot must be installed if using the 'fakeroot' option")" plain "$(gettext "in the BUILDENV array in %s.")" "$MAKEPKG_CONF" exit 1 @@ -1739,12 +1818,12 @@ fi # check for sudo if we will need it during makepkg execution if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then - if [ ! "$(type -p sudo)" ]; then + if ! type -p sudo >/dev/null; then warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")" fi fi -unset pkgname pkgbase pkgver pkgrel pkgdesc url license groups provides +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 @@ -1771,6 +1850,10 @@ else source "$BUILDFILE" fi +# set defaults if they weren't specified in buildfile +pkgbase=${pkgbase:-${pkgname[0]}} +epoch=${epoch:-0} + if (( GENINTEG )); then mkdir -p "$srcdir" chmod a-s "$srcdir" @@ -1795,27 +1878,30 @@ if (( ${#pkgname[@]} > 1 )); then fi # test for available PKGBUILD functions -# The exclamation mark is required here to avoid triggering the ERR trap when -# a tested function does not exist. -if [[ $(! type -t build) = "function" ]]; then +if declare -f build >/dev/null; then BUILDFUNC=1 fi -if [ "$(type -t package)" = "function" ]; then +if declare -f check >/dev/null; 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 declare -f package >/dev/null; then PKGFUNC=1 -elif [ $SPLITPKG -eq 0 -a "$(type -t package_${pkgname})" = "function" ]; then +elif [[ $SPLITPKG -eq 0 ]] && declare -f package_${pkgname} >/dev/null; then SPLITPKG=1 fi -pkgbase=${pkgbase:-${pkgname[0]}} - if [[ -n "${PKGLIST[@]}" ]]; then unset pkgname pkgname=("${PKGLIST[@]}") fi if (( ! SPLITPKG )); then - if [[ -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} \ - || -f $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-any${PKGEXT} ]] \ + fullver=$(get_full_version $epoch $pkgver $pkgrel) + if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \ + || -f $PKGDEST/${pkgname}-${fullver}-any${PKGEXT} ]] \ && ! (( FORCE || SOURCEONLY || NOBUILD )); then if (( INSTALL )); then warning "$(gettext "A package has already been built, installing existing package...")" @@ -1830,8 +1916,10 @@ else allpkgbuilt=1 somepkgbuilt=0 for pkg in ${pkgname[@]}; do - if [[ -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT} \ - || -f $PKGDEST/${pkg}-${pkgver}-${pkgrel}-any${PKGEXT} ]]; then + # TODO: this wasn't properly fixed in commit 2020e629 + fullver=$(get_full_version $epoch $pkgver $pkgrel) + if [[ -f $PKGDEST/${pkg}-${fullver}-${CARCH}${PKGEXT} \ + || -f $PKGDEST/${pkg}-${fullver}-any${PKGEXT} ]]; then somepkgbuilt=1 else allpkgbuilt=0 @@ -1863,6 +1951,7 @@ if (( INFAKEROOT )); then if (( ! REPKG )); then if (( BUILDFUNC )); then run_build + (( CHECKFUNC )) && run_check tidy_install fi else @@ -1875,28 +1964,19 @@ if (( INFAKEROOT )); then fi create_package else - for pkg in ${pkgname[@]}; do - pkgdir="$pkgdir/$pkg" - mkdir -p "$pkgdir" - chmod a-s "$pkgdir" - backup_package_variables - run_package $pkg - tidy_install - create_package $pkg - restore_package_variables - pkgdir="${pkgdir%/*}" - done + run_split_packaging fi msg "$(gettext "Leaving fakeroot environment.")" exit 0 # $E_OK fi -msg "$(gettext "Making package: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" +fullver=$(get_full_version $epoch $pkgver $pkgrel) +msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))" # if we are creating a source-only package, go no further if (( SOURCEONLY )); then - if [[ -f $SRCPKGDEST/${pkgbase}-${pkgver}-${pkgrel}${SRCEXT} ]] \ + if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \ && (( ! FORCE )); then error "$(gettext "A source package has already been built. (use -f to overwrite)")" exit 1 @@ -1911,20 +1991,24 @@ if (( NODEPS || ( (NOBUILD || REPKG) && !DEP_BIN ) )); then if (( NODEPS || ( REPKG && PKGFUNC ) )); then warning "$(gettext "Skipping dependency checks.")" fi -elif [ $(type -p "${PACMAN%% *}") ]; then +elif type -p "${PACMAN%% *}" >/dev/null; then if (( RMDEPS )); then - original_pkglist=($(run_pacman -Qq | sort)) # required by remove_dep + original_pkglist=($(run_pacman -Qq)) # required by remove_dep fi deperr=0 - msg "$(gettext "Checking Runtime Dependencies...")" + msg "$(gettext "Checking runtime dependencies...")" resolve_deps ${depends[@]} || deperr=1 - msg "$(gettext "Checking Buildtime Dependencies...")" + msg "$(gettext "Checking buildtime dependencies...")" resolve_deps ${makedepends[@]} || deperr=1 + if (( CHECKFUNC )); then + resolve_deps ${checkdepends[@]} || deperr=1 + fi + if (( RMDEPS )); then - current_pkglist=($(run_pacman -Qq | sort)) # required by remove_deps + current_pkglist=($(run_pacman -Qq)) # required by remove_deps fi if (( deperr )); then @@ -1988,6 +2072,7 @@ else if (( ! REPKG )); then devel_update (( BUILDFUNC )) && run_build + (( CHECKFUNC )) && run_check fi if (( ! SPLITPKG )); then if (( PKGFUNC )); then @@ -2003,22 +2088,13 @@ else fi create_package else - for pkg in ${pkgname[@]}; do - pkgdir="$pkgdir/$pkg" - mkdir -p "$pkgdir" - chmod a-s "$pkgdir" - backup_package_variables - run_package $pkg - tidy_install - create_package $pkg - restore_package_variables - pkgdir="${pkgdir%/*}" - done + run_split_packaging fi else if (( ! REPKG && ( PKGFUNC || SPLITPKG ) )); then devel_update (( BUILDFUNC )) && run_build + (( CHECKFUNC )) && run_check cd "$startdir" fi @@ -2032,7 +2108,8 @@ else fi fi -msg "$(gettext "Finished making: %s")" "$pkgbase $pkgver-$pkgrel ($(date))" +fullver=$(get_full_version $epoch $pkgver $pkgrel) +msg "$(gettext "Finished making: %s")" "$pkgbase $fullver ($(date))" install_package |