index : pacman | |
Archlinux32 fork of pacman | gitolite user |
summaryrefslogtreecommitdiff |
-rw-r--r-- | scripts/makepkg.sh.in | 638 |
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 8fa64f7b..a4e71564 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -1,4 +1,4 @@ -#!@BASH_SHELL@ -e +#!/bin/bash -e # # makepkg - make packages compatible for use with pacman # @configure_input@ @@ -28,10 +28,10 @@ # 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, grep, gzip, openssl, sed, tput (ncurses), xz +# gettext, gpg, grep, gzip, openssl, sed, tput (ncurses), xz # gettext initialization -export TEXTDOMAIN='pacman' +export TEXTDOMAIN='pacman-scripts' export TEXTDOMAINDIR='@localedir@' # file -i does not work on Mac OSX unless legacy mode is set @@ -41,10 +41,8 @@ myver='@PACKAGE_VERSION@' confdir='@sysconfdir@' BUILDSCRIPT='@BUILDSCRIPT@' startdir="$PWD" -srcdir="$startdir/src" -pkgdir="$startdir/pkg" -packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge') +packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge' 'upx') other_options=('ccache' 'distcc' 'buildflags' 'makeflags') splitpkg_overrides=('pkgver' 'pkgrel' 'pkgdesc' 'arch' 'license' 'groups' \ 'depends' 'optdepends' 'provides' 'conflicts' 'replaces' \ @@ -54,7 +52,6 @@ readonly -a packaging_options other_options splitpkg_overrides # Options ASROOT=0 CLEANUP=0 -CLEANCACHE=0 DEP_BIN=0 FORCE=0 INFAKEROOT=0 @@ -75,6 +72,7 @@ CHECKFUNC=0 PKGFUNC=0 SPLITPKG=0 PKGLIST=() +SIGNPKG='' # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call # when dealing with svn/cvs/etc PKGBUILDs. @@ -183,6 +181,17 @@ trap 'trap_exit "$(gettext "TERM signal caught. Exiting...")"' TERM HUP QUIT trap 'trap_exit "$(gettext "Aborted by user! Exiting...")"' INT trap 'trap_exit "$(gettext "An unknown error has occurred. Exiting...")"' ERR +enter_fakeroot() { + msg "$(gettext "Entering %s environment...")" "fakeroot" + + if [[ -n $newpkgver ]]; then + fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $? + else + fakeroot -- $0 -F "${ARGLIST[@]}" || exit $? + fi +} + + # a source entry can have two forms : # 1) "filename::http://path/to/file" # 2) "http://path/to/file" @@ -275,7 +284,7 @@ check_option() { # ? - not found ## check_buildenv() { - echo $(in_opt_array "$1" ${BUILDENV[@]}) + in_opt_array "$1" ${BUILDENV[@]} } @@ -310,7 +319,6 @@ in_opt_array() { ## in_array() { local needle=$1; shift - [[ -z $1 ]] && return 1 # Not Found local item for item in "$@"; do [[ $item = $needle ]] && return 0 # Found @@ -391,7 +399,7 @@ run_pacman() { local cmd printf -v cmd "%q " "$PACMAN" $PACMAN_OPTS "$@" if (( ! ASROOT )) && [[ ! $1 =~ ^-(T|Qq)$ ]]; then - if [ "$(type -p sudo)" ]; then + if type -p sudo >/dev/null; then cmd="sudo $cmd" else cmd="su root -c '$cmd'" @@ -509,7 +517,8 @@ download_sources() { local file=$(get_filepath "$netfile" || true) if [[ -n "$file" ]]; then msg2 "$(gettext "Found %s")" "${file##*/}" - ln -sf "$file" "$srcdir/" + rm -f "$srcdir/${file##*/}" + ln -s "$file" "$srcdir/" continue fi @@ -564,7 +573,7 @@ generate_checksums() { plain "" if ! type -p openssl >/dev/null; then - error "$(gettext "Cannot find openssl.")" + error "$(gettext "Cannot find the %s binary required for generating sourcefile checksums.")" "openssl" exit 1 # $E_MISSING_PROGRAM fi @@ -612,11 +621,6 @@ generate_checksums() { check_checksums() { (( ! ${#source[@]} )) && return 0 - if ! type -p openssl >/dev/null; then - error "$(gettext "Cannot find openssl.")" - exit 1 # $E_MISSING_PROGRAM - fi - local correlation=0 local integ required for integ in md5 sha1 sha256 sha384 sha512; do @@ -817,9 +821,6 @@ run_build() { if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; then [[ -d /usr/lib/distcc/bin ]] && export PATH="/usr/lib/distcc/bin:$PATH" export DISTCC_HOSTS - elif [[ $(check_option distcc) = "n" ]]; then - # if it is not wanted, clear the makeflags too - MAKEFLAGS="" fi # use ccache if it is requested (check buildenv and PKGBUILD opts) @@ -855,7 +856,7 @@ tidy_install() { fi if [[ $(check_option purge) = "y" && -n ${PURGE_TARGETS[*]} ]]; then - msg2 "$(gettext "Purging other files...")" + msg2 "$(gettext "Purging unwanted files...")" local pt for pt in "${PURGE_TARGETS[@]}"; do if [[ ${pt} = ${pt//\/} ]]; then @@ -877,8 +878,8 @@ tidy_install() { # update symlinks to this manpage find ${MAN_DIRS[@]} -lname "$file" 2>/dev/null | while read link ; do - rm -f "$link" - ln -sf "${file}.gz" "${link}.gz" + rm -f "$link" "${link}.gz" + ln -s "${file}.gz" "${link}.gz" done # check file still exists (potentially already compressed due to hardlink) @@ -921,7 +922,7 @@ tidy_install() { fi if [[ $(check_option libtool) = "n" ]]; then - msg2 "$(gettext "Removing libtool .la files...")" + msg2 "$(gettext "Removing "%s" files...")" "libtool" find . ! -type d -name "*.la" -exec rm -f -- '{}' \; fi @@ -929,6 +930,69 @@ tidy_install() { msg2 "$(gettext "Removing empty directories...")" find . -depth -type d -empty -delete fi + + if [[ $(check_option upx) = "y" ]]; then + msg2 "$(gettext "Compressing binaries with %s...")" "UPX" + local binary + find . -type f -perm -u+w 2>/dev/null | while read binary ; do + if [[ $(file -bi "$binary") = *'application/x-executable'* ]]; then + upx $UPXFLAGS "$binary" &>/dev/null || + warning "$(gettext "Could not compress binary : %s")" "${binary/$pkgdir\//}" + fi + done + fi +} + +find_libdepends() { + local libdepends + find "$pkgdir" -type f -perm -u+x | while read 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\.*}.so" + # extract the major version: 1 + soversion="${sofile##*\.so\.}" + if in_array "${soname}" ${depends[@]}; then + if ! in_array "${soname}=${soversion}-${soarch}" ${libdepends[@]}; then + # libfoo.so=1-64 + echo "${soname}=${soversion}-${soarch}" + libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}") + fi + fi + done + done +} + +find_libprovides() { + local libprovides + find "$pkgdir" -type f -name \*.so\* | while read filename + do + # check if we really have a shared object + if LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then + # 64 + soarch=$(LC_ALL=C readelf -h "$filename" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') + # get the string binaries link to: libfoo.so.1.2 -> libfoo.so.1 + sofile=$(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') + [ -z "$sofile" ] && sofile="${filename##*/}" + + # extract the library name: libfoo.so + soname="${sofile%%\.so\.*}.so" + # extract the major version: 1 + soversion="${sofile##*\.so\.}" + if in_array "${soname}" ${provides[@]}; then + if ! in_array "${soname}=${soversion}-${soarch}" ${libprovides[@]}; then + # libfoo.so=1-64 + echo "${soname}=${soversion}-${soarch}" + libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}") + fi + fi + fi + done } write_pkginfo() { @@ -941,7 +1005,7 @@ write_pkginfo() { local size="$(@DUPATH@ -sk)" size="$(( ${size%%[^0-9]*} * 1024 ))" - msg2 "$(gettext "Generating .PKGINFO file...")" + msg2 "$(gettext "Generating %s file...")" ".PKGINFO" echo "# Generated by makepkg $myver" if (( INFAKEROOT )); then echo "# using $(fakeroot -v)" @@ -960,13 +1024,44 @@ write_pkginfo() { [[ $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 + + libprovides=$(find_libprovides) + libdepends=$(find_libdepends) + provides=("${provides[@]}" ${libprovides}) + depends=("${depends[@]}" ${libdepends}) + + for it in "${depends[@]}"; do + if [[ $it = *.so ]]; then + # check if the entry has been found by find_libdepends + # if not, it's unneeded; tell the user so he can remove it + if [[ ! $libdepends =~ (^|\s)${it}=.* ]]; then + error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it" + return 1 + fi + else + echo "depend = $it" + fi + done + + for it in "${provides[@]}"; do + # ignore versionless entires (those come from the PKGBUILD) + if [[ $it = *.so ]]; then + # check if the entry has been found by find_libprovides + # if not, it's unneeded; tell the user so he can remove it + if [[ ! $libprovides =~ (^|\s)${it}=.* ]]; then + error "$(gettext "Cannot find library listed in %s: %s")" "'provides'" "$it" + return 1 + fi + else + echo "provides = $it" + fi + done + for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" if [[ $ret != "?" ]]; then @@ -982,7 +1077,7 @@ write_pkginfo() { # warn if license array is not present or empty if [[ -z $license ]]; then warning "$(gettext "Please add a license line to your %s!")" "$BUILDSCRIPT" - plain "$(gettext "Example for GPL\'ed software: license=('GPL').")" + plain "$(gettext "Example for GPL\'ed software: %s.")" "license=('GPL')" fi } @@ -993,7 +1088,7 @@ check_package() { local file for file in "${backup[@]}"; do if [[ ! -f $file ]]; then - warning "$(gettext "Backup entry file not in package : %s")" "$file" + warning "$(gettext "%s entry file not in package : %s")" "backup" "$file" fi done @@ -1009,7 +1104,7 @@ check_package() { create_package() { if [[ ! -d $pkgdir ]]; then - error "$(gettext "Missing pkg/ directory.")" + error "$(gettext "Missing %s directory.")" "pkg/" plain "$(gettext "Aborting...")" exit 1 # $E_MISSING_PKGDIR fi @@ -1038,7 +1133,7 @@ create_package() { # check for changelog/install files for i in 'changelog/.CHANGELOG' 'install/.INSTALL'; do - IFS='/' read -r orig dest <<< "$i" + IFS='/' read -r orig dest < <(printf '%s\n' "$i") if [[ -n ${!orig} ]]; then msg2 "$(gettext "Adding %s file...")" "$orig" @@ -1056,6 +1151,7 @@ create_package() { *tar.gz) EXT=${PKGEXT%.gz} ;; *tar.bz2) EXT=${PKGEXT%.bz2} ;; *tar.xz) EXT=${PKGEXT%.xz} ;; + *tar.Z) EXT=${PKGEXT%.Z} ;; *tar) EXT=${PKGEXT} ;; *) warning "$(gettext "'%s' is not a valid archive extension.")" \ "$PKGEXT" ; EXT=$PKGEXT ;; @@ -1065,6 +1161,9 @@ create_package() { local pkg_file="$PKGDEST/${nameofpkg}-${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 @@ -1075,6 +1174,7 @@ create_package() { *tar.gz) gzip -c -f -n ;; *tar.bz2) bzip2 -c -f ;; *tar.xz) xz -c -z - ;; + *tar.Z) compress -c -f ;; *tar) cat ;; esac > "${pkg_file}" || ret=$? @@ -1086,9 +1186,16 @@ create_package() { exit 1 # TODO: error code fi + create_signature "$pkg_file" + if (( ! ret )) && [[ ! "$PKGDEST" -ef "${startdir}" ]]; then - ln -sf "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}" + 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 @@ -1096,24 +1203,30 @@ create_package() { fi } -create_srcpackage() { - cd "$startdir" +create_signature() { + if [[ $SIGNPKG != 'y' ]]; then + return + fi + local ret=0 + local filename="$1" + msg "$(gettext "Signing package...")" - # Get back to our src directory so we can begin with sources. - mkdir -p "$srcdir" - chmod a-s "$srcdir" - cd "$srcdir" - if (( ! SKIPINTEG || SOURCEONLY == 2 )); then - download_sources + local SIGNWITHKEY="" + if [[ -n $GPGKEY ]]; then + SIGNWITHKEY="-u ${GPGKEY}" fi - if (( ! SKIPINTEG )); then - # We can only check checksums if we have all files. - check_checksums + # The signature will be generated directly in ascii-friendly format + gpg --detach-sign --use-agent ${SIGNWITHKEY} "$filename" &>/dev/null || ret=$? + + + if (( ! ret )); then + msg2 "$(gettext "Created signature file %s.")" "$filename.sig" else - warning "$(gettext "Skipping integrity checks.")" + warning "$(gettext "Failed to sign package file.")" fi - cd "$startdir" +} +create_srcpackage() { msg "$(gettext "Creating source package...")" local srclinks="$(mktemp -d "$startdir"/srclinks.XXXXXXXXX)" mkdir "${srclinks}"/${pkgbase} @@ -1169,7 +1282,8 @@ create_srcpackage() { fi if (( ! ret )) && [[ ! "$SRCPKGDEST" -ef "${startdir}" ]]; then - ln -sf "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}" + rm -f "${pkg_file/$SRCPKGDEST/$startdir}" + ln -s "${pkg_file}" "${pkg_file/$SRCPKGDEST/$startdir}" ret=$? fi @@ -1185,9 +1299,9 @@ install_package() { (( ! INSTALL )) && return if (( ! SPLITPKG )); then - msg "$(gettext "Installing package %s with %s -U...")" "$pkgname" "$PACMAN" + msg "$(gettext "Installing package %s with %s...")" "$pkgname" "$PACMAN -U" else - msg "$(gettext "Installing %s package group with %s -U...")" "$pkgbase" "$PACMAN" + msg "$(gettext "Installing %s package group with %s...")" "$pkgbase" "$PACMAN -U" fi local fullver pkg pkglist @@ -1248,7 +1362,7 @@ check_sanity() { if (( ! IGNOREARCH )); then error "$(gettext "%s is not available for the '%s' architecture.")" "$pkgbase" "$CARCH" plain "$(gettext "Note that many packages may need a line added to their %s")" "$BUILDSCRIPT" - plain "$(gettext "such as arch=('%s').")" "$CARCH" + plain "$(gettext "such as %s.")" "arch=('$CARCH')" ret=1 fi fi @@ -1259,7 +1373,7 @@ check_sanity() { sed -e "s/provides=/provides_list+=/" -e "s/#.*//" -e 's/\\$//') for i in ${provides_list[@]}; do if [[ $i != ${i//</} || $i != ${i//>/} ]]; then - error "$(gettext "Provides array cannot contain comparison (< or >) operators.")" + error "$(gettext "%s array cannot contain comparison (< or >) operators.")" "provides" ret=1 fi done @@ -1269,7 +1383,7 @@ check_sanity() { sed -e "s/backup=/backup_list+=/" -e "s/#.*//" -e 's/\\$//') for i in "${backup_list[@]}"; do if [[ ${i:0:1} = "/" ]]; then - error "$(gettext "Backup entry should not contain leading slash : %s")" "$i" + error "$(gettext "%s entry should not contain leading slash : %s")" "backup" "$i" ret=1 fi done @@ -1280,7 +1394,7 @@ check_sanity() { for i in "${optdepends_list[@]}"; do local pkg=${i%%:*} if [[ ! $pkg =~ ^[[:alnum:]\>\<\=\.\+\_\-]+$ ]]; then - error "$(gettext "Invalid syntax for optdepend : '%s'")" "$i" + error "$(gettext "Invalid syntax for %s : '%s'")" "optdepend" "$i" ret=1 fi done @@ -1311,7 +1425,7 @@ check_sanity() { fi done if (( ! known )); then - error "$(gettext "options array contains unknown option '%s'")" "$i" + error "$(gettext "%s array contains unknown option '%s'")" "options" "$i" valid_options=0 fi done @@ -1322,7 +1436,7 @@ check_sanity() { if (( ${#pkgname[@]} > 1 )); then for i in ${pkgname[@]}; do if ! declare -f package_${i} >/dev/null; then - error "$(gettext "missing package function for split package '%s'")" "$i" + error "$(gettext "Missing %s function for split package '%s'")" "package_$i()" "$i" ret=1 fi done @@ -1330,7 +1444,7 @@ check_sanity() { for i in ${PKGLIST[@]}; do if ! in_array $i ${pkgname[@]}; then - error "$(gettext "requested package %s is not provided in %s")" "$i" "$BUILDFILE" + error "$(gettext "Requested package %s is not provided in %s")" "$i" "$BUILDFILE" ret=1 fi done @@ -1338,13 +1452,91 @@ check_sanity() { return $ret } +check_software() { + # check for needed software + local ret=0 + + # check for sudo if we will need it during makepkg execution + if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); then + if ! type -p sudo >/dev/null; then + warning "$(gettext "Sudo can not be found. Will use su to acquire root privileges.")" + fi + fi + + # fakeroot - building as non-root user + if [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); then + if ! type -p fakeroot >/dev/null; then + error "$(gettext "Cannot find the %s binary required for building as non-root user.")" "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 + + # openssl - checksum operations + if (( ! SKIPINTEG )); then + if ! type -p openssl >/dev/null; then + error "$(gettext "Cannot find the %s binary required for validating sourcefile 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 + + # distcc - compilation with distcc + if [[ $(check_buildenv distcc) = "y" && $(check_option distcc) != "n" ]]; 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_buildenv ccache) = "y" && $(check_option ccache) != "n" ]]; 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 + + return $ret +} + devel_check() { newpkgver="" # Do not update pkgver if --holdver is set, when building a source package, repackaging, # reading PKGBUILD from pipe (-f), or if we cannot write to the file (-w) - if (( HOLDVER || SOURCEONLY || REPKG )) \ - || [[ ! -f $BUILDFILE || ! -w $BUILDFILE ]]; then + if (( HOLDVER || SOURCEONLY || REPKG )) || + [[ ! -f $BUILDFILE || ! -w $BUILDFILE || $BUILDFILE = /dev/stdin ]]; then return fi @@ -1353,30 +1545,48 @@ devel_check() { # This will only be used on the first call to makepkg; subsequent # calls to makepkg via fakeroot will explicitly pass the version # number to avoid having to determine the version number twice. - # Also do a brief check to make sure we have the VCS tool available. + # Also do a check to make sure we have the VCS tool available. oldpkgver=$pkgver if [[ -n ${_darcstrunk} && -n ${_darcsmod} ]] ; then - type -p darcs >/dev/null || return 0 + if ! type -p darcs >/dev/null; then + warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "darcs" "darcs" + return 0 + fi msg "$(gettext "Determining latest %s revision...")" 'darcs' newpkgver=$(date +%Y%m%d) elif [[ -n ${_cvsroot} && -n ${_cvsmod} ]] ; then - type -p cvs >/dev/null || return 0 + if ! type -p cvs >/dev/null; then + warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "cvs" "cvs" + return 0 + fi msg "$(gettext "Determining latest %s revision...")" 'cvs' newpkgver=$(date +%Y%m%d) elif [[ -n ${_gitroot} && -n ${_gitname} ]] ; then - type -p git >/dev/null || return 0 + if ! type -p git >/dev/null; then + warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "git" "git" + return 0 + fi msg "$(gettext "Determining latest %s revision...")" 'git' newpkgver=$(date +%Y%m%d) elif [[ -n ${_svntrunk} && -n ${_svnmod} ]] ; then - type -p svn >/dev/null || return 0 + if ! type -p svn >/dev/null; then + warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "svn" "svn" + return 0 + fi msg "$(gettext "Determining latest %s revision...")" 'svn' 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 >/dev/null || return 0 + if ! type -p bzr >/dev/null; then + warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "bzr" "bzr" + return 0 + fi msg "$(gettext "Determining latest %s revision...")" 'bzr' newpkgver=$(bzr revno ${_bzrtrunk}) elif [[ -n ${_hgroot} && -n ${_hgrepo} ]] ; then - type -p hg >/dev/null || return 0 + if ! type -p hg >/dev/null; then + warning "$(gettext "Cannot find the %s binary required to determine latest %s revision.")" "hg" "hg" + return 0 + fi msg "$(gettext "Determining latest %s revision...")" 'hg' if [[ -d ./src/$_hgrepo ]] ; then cd ./src/$_hgrepo @@ -1472,93 +1682,7 @@ canonicalize_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 - if [[ -n ${1:2} ]]; then - local match="" - for i in ${long_options//,/ }; do - if [[ ${1:2} = ${i//:} ]]; then - match=$i - break - fi - done - if [[ -n $match ]]; then - if [[ ${1:2} = $match ]]; then - printf ' %s' "$1" - else - if [[ -n $2 ]]; then - printf ' %s' "$1" - shift - printf " '%s'" "$1" - else - echo "makepkg: option '$1' $(gettext "requires an argument")" >&2 - ret=1 - fi - fi - else - echo "makepkg: $(gettext "unrecognized option") '$1'" >&2 - ret=1 - fi - else - shift - break - fi - elif [[ ${1:0:1} = '-' ]]; then - for ((i=1; i<${#1}; i++)); do - if [[ $short_options =~ ${1:i:1} ]]; then - if [[ $short_options =~ ${1:i:1}: ]]; then - if [[ -n ${1:$i+1} ]]; then - printf ' -%s' "${1:i:1}" - printf " '%s'" "${1:$i+1}" - else - if [[ -n $2 ]]; then - printf ' -%s' "${1:i:1}" - shift - printf " '%s'" "${1}" - else - echo "makepkg: option $(gettext "requires an argument") -- '${1:i:1}'" >&2 - ret=1 - fi - fi - break - else - printf ' -%s' "${1:i:1}" - fi - else - echo "makepkg: $(gettext "invalid option") -- '${1:i:1}'" >&2 - ret=1 - fi - done - else - unused_options="${unused_options} '$1'" - fi - shift - done - - printf " --" - if [[ -n $unused_options ]]; then - for i in ${unused_options[@]}; do - printf ' %s' "$i" - done - fi - if [[ -n $1 ]]; then - while [[ -n $1 ]]; do - printf " '%s'" "${1}" - shift - done - fi - printf "\n" - - return $ret -} +m4_include(library/parse_options.sh) usage() { printf "makepkg (pacman) %s\n" "$myver" @@ -1566,14 +1690,13 @@ usage() { printf "$(gettext "Usage: %s [options]")\n" "$0" echo echo "$(gettext "Options:")" - printf "$(gettext " -A, --ignorearch Ignore incomplete arch field in %s")\n" "$BUILDSCRIPT" + printf "$(gettext " -A, --ignorearch Ignore incomplete %s field in %s")\n" "arch" "$BUILDSCRIPT" echo "$(gettext " -c, --clean Clean up work files after build")" - echo "$(gettext " -C, --cleancache Clean up source files from the cache")" echo "$(gettext " -d, --nodeps Skip all dependency checks")" - echo "$(gettext " -e, --noextract Do not extract source files (use existing src/ dir)")" + printf "$(gettext " -e, --noextract Do not extract source files (use existing %s dir)")\n" "src/" echo "$(gettext " -f, --force Overwrite existing package")" echo "$(gettext " -g, --geninteg Generate integrity checks for source files")" - echo "$(gettext " -h, --help This help")" + echo "$(gettext " -h, --help Show this help message and exit")" echo "$(gettext " -i, --install Install package after successful build")" echo "$(gettext " -L, --log Log package build process")" echo "$(gettext " -m, --nocolor Disable colorized output messages")" @@ -1581,23 +1704,26 @@ usage() { printf "$(gettext " -p <file> Use an alternate build script (instead of '%s')")\n" "$BUILDSCRIPT" echo "$(gettext " -r, --rmdeps Remove installed dependencies after a successful build")" echo "$(gettext " -R, --repackage Repackage contents of the package without rebuilding")" - echo "$(gettext " -s, --syncdeps Install missing dependencies with pacman")" + printf "$(gettext " -s, --syncdeps Install missing dependencies with %s")\n" "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 " --asroot Allow %s to run as root user")\n" "makepkg" + printf "$(gettext " --check Run the %s function in the %s")\n" "check()" "$BUILDSCRIPT" printf "$(gettext " --config <file> Use an alternate config file (instead of '%s')")\n" "$confdir/makepkg.conf" printf "$(gettext " --holdver Prevent automatic version bumping for development %ss")\n" "$BUILDSCRIPT" - printf "$(gettext " --nocheck Do not run the check() function in the %s")\n" "$BUILDSCRIPT" + printf "$(gettext " --key <key> Specify a key to use for %s signing instead of the default")\n" "gpg" + printf "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT" + echo "$(gettext " --nosign Do not create a signature for the package")" echo "$(gettext " --pkg <list> Only build listed packages from a split package")" + printf "$(gettext " --sign Sign the resulting package with %s")\n" "gpg" echo "$(gettext " --skipinteg Do not fail when integrity checks are missing")" echo "$(gettext " --source Generate a source-only tarball without downloaded sources")" echo - echo "$(gettext "These options can be passed to pacman:")" + printf "$(gettext "These options can be passed to %s:")\n" "pacman" echo echo "$(gettext " --noconfirm Do not ask for confirmation when resolving dependencies")" echo "$(gettext " --noprogressbar Do not show a progress bar when downloading files")" echo - printf "$(gettext "If -p is not specified, makepkg will look for '%s'")\n" "$BUILDSCRIPT" + printf "$(gettext "If %s is not specified, %s will look for '%s'")\n" "-p" "makepkg" "$BUILDSCRIPT" echo } @@ -1622,16 +1748,14 @@ fi ARGLIST=("$@") # Parse Command Line Options. -OPT_SHORT="AcCdefFghiLmop:rRsV" -OPT_LONG="allsource,asroot,ignorearch,check,clean,cleancache,nodeps" +OPT_SHORT="AcdefFghiLmop:rRsV" +OPT_LONG="allsource,asroot,ignorearch,check,clean,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:" +OPT_LONG+=",install,key:,log,nocolor,nobuild,nocheck,nosign,pkg:,rmdeps" +OPT_LONG+=",repackage,skipinteg,sign,source,syncdeps,version,config:" # Pacman Options 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' +if ! OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@")"; then echo; usage; exit 1 # E_INVALID_OPTION; fi eval set -- "$OPT_TEMP" @@ -1648,7 +1772,6 @@ while true; do --asroot) ASROOT=1 ;; -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 ;; @@ -1660,15 +1783,18 @@ while true; do -g|--geninteg) GENINTEG=1 ;; --holdver) HOLDVER=1 ;; -i|--install) INSTALL=1 ;; + --key) shift; GPGKEY=$1 ;; -L|--log) LOGGING=1 ;; -m|--nocolor) USE_COLOR='n' ;; --nocheck) RUN_CHECK='n' ;; + --nosign) SIGNPKG='n' ;; -o|--nobuild) NOBUILD=1 ;; -p) shift; BUILDFILE=$1 ;; --pkg) shift; PKGLIST=($1) ;; -r|--rmdeps) RMDEPS=1 ;; -R|--repackage) REPKG=1 ;; --skipinteg) SKIPINTEG=1 ;; + --sign) SIGNPKG='y' ;; --source) SOURCEONLY=1 ;; -s|--syncdeps) DEP_BIN=1 ;; @@ -1685,6 +1811,10 @@ done [[ -n ${PKGDEST} ]] && _PKGDEST=$(canonicalize_path ${PKGDEST}) [[ -n ${SRCDEST} ]] && _SRCDEST=$(canonicalize_path ${SRCDEST}) [[ -n ${SRCPKGDEST} ]] && _SRCPKGDEST=$(canonicalize_path ${SRCPKGDEST}) +[[ -n ${BUILDDIR} ]] && _BUILDDIR=$(canonicalize_path ${BUILDDIR}) +[[ -n ${PKGEXT} ]] && _PKGEXT=${PKGEXT} +[[ -n ${SRCEXT} ]] && _SRCEXT=${SRCEXT} +[[ -n ${GPGKEY} ]] && _GPGKEY=${GPGKEY} # default config is makepkg.conf MAKEPKG_CONF=${MAKEPKG_CONF:-$confdir/makepkg.conf} @@ -1698,8 +1828,9 @@ else exit 1 # $E_CONFIG_ERROR fi -# Source user-specific makepkg.conf overrides -if [[ -r ~/.makepkg.conf ]]; then +# Source user-specific makepkg.conf overrides, but only if no override config +# file was specified +if [[ $MAKEPKG_CONF = "$confdir/makepkg.conf" && -r ~/.makepkg.conf ]]; then source ~/.makepkg.conf fi @@ -1729,9 +1860,24 @@ fi readonly ALL_OFF BOLD BLUE GREEN RED YELLOW # override settings with an environment variable for batch processing +BUILDDIR=${_BUILDDIR:-$BUILDDIR} +BUILDDIR=${BUILDDIR:-$startdir} #default to $startdir if undefined +if [[ ! -d $BUILDDIR ]]; then + mkdir -p "$BUILDDIR" || + error "$(gettext "You do not have write permission to create packages in %s.")" "$BUILDDIR" + 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 +srcdir="$BUILDDIR/src" +pkgdir="$BUILDDIR/pkg" + PKGDEST=${_PKGDEST:-$PKGDEST} PKGDEST=${PKGDEST:-$startdir} #default to $startdir if undefined -if [[ ! -w $PKGDEST ]]; then +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 @@ -1748,82 +1894,41 @@ fi SRCPKGDEST=${_SRCPKGDEST:-$SRCPKGDEST} SRCPKGDEST=${SRCPKGDEST:-$startdir} #default to $startdir if undefined +PKGEXT=${_PKGEXT:-$PKGEXT} +SRCEXT=${_SRCEXT:-$SRCEXT} +GPGKEY=${_GPGKEY:-$GPGKEY} if (( HOLDVER )) && [[ -n $FORCE_VER ]]; then # The '\\0' is here to prevent gettext from thinking --holdver is an option - error "$(gettext "\\0--holdver and --forcever cannot both be specified" )" + error "$(gettext "\\0%s and %s cannot both be specified" )" "--holdver" "--forcever" exit 1 fi -if (( CLEANCACHE )); then - #fix flyspray feature request #5223 - 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]")" - read answer - answer=$(tr '[:lower:]' '[:upper:]' <<< "$answer") - if [[ $answer = $(gettext YES) || $answer = $(gettext Y) ]]; then - rm "$SRCDEST"/* - if (( $? )); then - error "$(gettext "Problem removing files; you may not have correct permissions in %s")" "$SRCDEST" - exit 1 - else - # removal worked - msg "$(gettext "Source cache cleaned.")" - exit 0 - fi - else - # answer = no - msg "$(gettext "No files have been removed.")" - exit 0 - fi - else - # $SRCDEST is $startdir, two possibilities - error "$(gettext "Source destination must be defined in %s.")" "$MAKEPKG_CONF" - plain "$(gettext "In addition, please run makepkg -C outside of your cache directory.")" - exit 1 - fi -fi - if (( ! INFAKEROOT )); then if (( EUID == 0 && ! ASROOT )); then # Warn those who like to live dangerously. - error "$(gettext "Running makepkg as root is a BAD idea and can cause")" + error "$(gettext "Running %s as root is a BAD idea and can cause")" "makepkg" plain "$(gettext "permanent, catastrophic damage to your system. If you")" - plain "$(gettext "wish to run as root, please use the --asroot option.")" + plain "$(gettext "wish to run as root, please use the %s option.")" "--asroot" exit 1 # $E_USER_ABORT elif (( EUID > 0 && ASROOT )); then # Warn those who try to use the --asroot option when they are not root - error "$(gettext "The --asroot option is meant for the root user only.")" - plain "$(gettext "Please rerun makepkg without the --asroot flag.")" + error "$(gettext "The %s option is meant for the root user only.")" "--asroot" + plain "$(gettext "Please rerun %s without the %s flag.")" "makepkg" "--asroot" exit 1 # $E_USER_ABORT - elif [[ $(check_buildenv fakeroot) = "y" ]] && (( EUID > 0 )); 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 - fi - elif (( EUID > 0 )); then - warning "$(gettext "Running makepkg as an unprivileged user will result in non-root")" - plain "$(gettext "ownership of the packaged files. Try using the fakeroot environment by")" - plain "$(gettext "placing 'fakeroot' in the BUILDENV array in %s.")" "$MAKEPKG_CONF" + elif (( EUID > 0 )) && [[ $(check_buildenv fakeroot) != "y" ]]; then + warning "$(gettext "Running %s as an unprivileged user will result in non-root")" "makepkg" + plain "$(gettext "ownership of the packaged files. Try using the %s environment by")" "fakeroot" + plain "$(gettext "placing %s in the %s array in %s.")" "'fakeroot'" "BUILDENV" "$MAKEPKG_CONF" sleep 1 fi else if [[ -z $FAKEROOTKEY ]]; then - error "$(gettext "Do not use the '-F' option. This option is only for use by makepkg.")" + 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 -# check for sudo if we will need it during makepkg execution -if (( ! ( ASROOT || INFAKEROOT ) && ( DEP_BIN || RMDEPS || INSTALL ) )); 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 epoch pkgdesc url license groups provides unset md5sums replaces depends conflicts backup source install changelog build unset makedepends optdepends options noextract @@ -1841,7 +1946,7 @@ if [[ ! -f $BUILDFILE ]]; then else crlftest=$(file "$BUILDFILE" | grep -F 'CRLF' || true) if [[ -n $crlftest ]]; then - error "$(gettext "%s contains CRLF characters and cannot be sourced.")" "$BUILDFILE" + error "$(gettext "%s contains %s characters and cannot be sourced.")" "$BUILDFILE" "CRLF" exit 1 fi @@ -1867,6 +1972,9 @@ fi # check the PKGBUILD for some basic requirements check_sanity || exit 1 +# check we have the software required to process the PKGBUILD +check_software || exit 1 + # We need to run devel_update regardless of whether we are in the fakeroot # build process so that if the user runs makepkg --forcever manually, we # 1) output the correct pkgver, and 2) use the correct filename when @@ -1899,6 +2007,20 @@ if [[ -n "${PKGLIST[@]}" ]]; then pkgname=("${PKGLIST[@]}") fi +# check if gpg signature is to be created and if signing key is valid +[[ -z $SIGNPKG ]] && SIGNPKG=$(check_buildenv sign) +if [[ $SIGNPKG == 'y' ]]; then + 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 (( ! SPLITPKG )); then fullver=$(get_full_version $epoch $pkgver $pkgrel) if [[ -f $PKGDEST/${pkgname}-${fullver}-${CARCH}${PKGEXT} \ @@ -1909,7 +2031,7 @@ if (( ! SPLITPKG )); then install_package exit $? else - error "$(gettext "A package has already been built. (use -f to overwrite)")" + error "$(gettext "A package has already been built. (use %s to overwrite)")" "-f" exit 1 fi fi @@ -1933,12 +2055,12 @@ else install_package exit $? else - error "$(gettext "The package group has already been built. (use -f to overwrite)")" + error "$(gettext "The package group has already been built. (use %s to overwrite)")" "-f" exit 1 fi fi if (( somepkgbuilt )); then - error "$(gettext "Part of the package group has already been built. (use -f to overwrite)")" + error "$(gettext "Part of the package group has already been built. (use %s to overwrite)")" "-f" exit 1 fi fi @@ -1947,6 +2069,12 @@ 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 + if (( ! SPLITPKG )); then if (( ! PKGFUNC )); then if (( ! REPKG )); then @@ -1956,7 +2084,7 @@ if (( INFAKEROOT )); then tidy_install fi else - warning "$(gettext "Repackaging without the use of a package() function is deprecated.")" + warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()" plain "$(gettext "File permissions may not be preserved.")" fi else @@ -1968,7 +2096,7 @@ if (( INFAKEROOT )); then run_split_packaging fi - msg "$(gettext "Leaving fakeroot environment.")" + msg "$(gettext "Leaving %s environment.")" "fakeroot" exit 0 # $E_OK fi @@ -1979,10 +2107,32 @@ msg "$(gettext "Making package: %s")" "$pkgbase $fullver ($(date))" if (( SOURCEONLY )); then if [[ -f $SRCPKGDEST/${pkgbase}-${fullver}${SRCEXT} ]] \ && (( ! FORCE )); then - error "$(gettext "A source package has already been built. (use -f to overwrite)")" + error "$(gettext "A source package has already been built. (use %s to overwrite)")" "-f" exit 1 fi - create_srcpackage + + # Get back to our src directory so we can begin with sources. + mkdir -p "$srcdir" + chmod a-s "$srcdir" + cd "$srcdir" + if (( ! SKIPINTEG || SOURCEONLY == 2 )); then + download_sources + fi + if (( ! SKIPINTEG )); then + # We can only check checksums if we have all files. + check_checksums + else + warning "$(gettext "Skipping integrity checks.")" + fi + cd "$startdir" + + # if we are root or if fakeroot is not enabled, then we don't use it + if [[ $(check_buildenv fakeroot) != "y" ]] || (( EUID == 0 )); then + create_srcpackage + else + enter_fakeroot + fi + msg "$(gettext "Source package created: %s")" "$pkgbase ($(date))" exit 0 fi @@ -2017,7 +2167,7 @@ elif type -p "${PACMAN%% *}" >/dev/null; then exit 1 fi else - warning "$(gettext "%s was not found in PATH; skipping dependency checks.")" "${PACMAN%% *}" + warning "$(gettext "%s was not found in %s; skipping dependency checks.")" "${PACMAN%% *}" "PATH" fi # ensure we have a sane umask set @@ -2029,9 +2179,9 @@ chmod a-s "$srcdir" cd "$srcdir" if (( NOEXTRACT )); then - warning "$(gettext "Skipping source retrieval -- using existing src/ tree")" - warning "$(gettext "Skipping source integrity checks -- using existing src/ tree")" - warning "$(gettext "Skipping source extraction -- using existing src/ tree")" + warning "$(gettext "Skipping source retrieval -- using existing %s tree")" "src/" + warning "$(gettext "Skipping source integrity checks -- using existing %s tree")" "src/" + warning "$(gettext "Skipping source extraction -- using existing %s tree")" "src/" if (( NOEXTRACT )) && [[ -z $(ls "$srcdir" 2>/dev/null) ]]; then error "$(gettext "The source directory is empty, there is nothing to build!")" @@ -2061,7 +2211,7 @@ if (( NOBUILD )); then else # check for existing pkg directory; don't remove if we are repackaging if [[ -d $pkgdir ]] && (( ! REPKG || PKGFUNC || SPLITPKG )); then - msg "$(gettext "Removing existing pkg/ directory...")" + msg "$(gettext "Removing existing %s directory...")" "pkg/" rm -rf "$pkgdir" fi mkdir -p "$pkgdir" @@ -2083,7 +2233,7 @@ else if (( ! REPKG )); then tidy_install else - warning "$(gettext "Repackaging without the use of a package() function is deprecated.")" + warning "$(gettext "Repackaging without the use of a %s function is deprecated.")" "package()" plain "$(gettext "File permissions may not be preserved.")" fi fi @@ -2099,13 +2249,7 @@ else cd "$startdir" fi - msg "$(gettext "Entering fakeroot environment...")" - - if [[ -n $newpkgver ]]; then - fakeroot -- $0 --forcever $newpkgver -F "${ARGLIST[@]}" || exit $? - else - fakeroot -- $0 -F "${ARGLIST[@]}" || exit $? - fi + enter_fakeroot fi fi |