[pacman-dev] makepkg3 improvements (for pacman-3.1)
Hi, I've been using pacman for over a year now on DIY-Linux (http://www.diy-linux.org), and to put it simply it's great easy to use and easy to setup. So I thought it was about time I contribute something back... an improved version of makepkg. For the impatient :p see the script attached. makepkg2's use of fakeroot was a bit hackish, it's now very hackish in makepkg3. It also kicks up a few strange bugs (flyspray #6208) because it's being used where it shouldn't be. So I've rewritten/reordered makepkg to reduce the amount of time spent in fakeroot. Specificly it's now only used for... fake_install() (if it exists. See below) build() (if there's no fake_install) tidy_install() - remove docs - move/compress man pages - strip binaries/libraries - remove libtool files - remove empty directories create_package() - create .PKGINFO & .FILELIST - tar it all up everything else is run outside of fakeroot. Over at DIY-Linux we have a patch that adds an extra function to PKGBUILD (fake_install). This way we can prepare, compile, and test the package as the user running makepkg. Then fake_install is run inside fakeroot to install the package. This further reduces the time spent in fakeroot and the possibility of any weird bugs popping up. If the build script doesn't contain a fake_install function the build function is run inside of fakeroot instead (maintaining backwards compatibility with how things work at the moment). Other changes... - reordered the code to reduce the number of if..then..else cases - renamed a lot of variables so they're a bit more descriptive - started to add error codes for the different reasons why makepkg exits - quoted all variables that contain paths so '/home/me/a folder with spaces' doesn't cause errors. (but build scripts are still a point of failure as the majority don't have $startdir in quotes.) - fixed flyspray bug #6468 -- Localized dates for build/install date - added some more error catching - added the ability to choose between usr/man and usr/share/man (var (_MAN_DIR) at the top of the script.) There are still a few things that need fixed, but some discussion is probably required. - Should build deps be removed after a successful build? At the moment deps are only removed if '-r' is used and it removes build deps and runtime deps. An extra option to remove build deps? - Should root be a loud to run makepkg? IMO running makepkg as root is a hanus crime, and anyone foolish enough to do so deserves to have their system burn to the ground as the result of a broken build script. One mistaken key stroke in a build script can result in a successful build or the destruction of a system :p I've added a warning that asks the user if they're sure the want to continue running makepkg as root. With sudo and fakeroot there's no need to run makepkg as root, but thats just my opinion. Andrew #!/bin/bash # # makepkg - make packages compatable for use with pacman # # Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> # Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> # Copyright (c) 2006 by Miklos Vajna <vmiklos@frugalware.org> # Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> # Copyright (c) 2006 by Alex Smith <alex@alex-smith.me.uk> # Copyright (c) 2006 by Andras Voroskoi <voroskoi@frugalware.org> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, # USA. # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # NOTES # ~~~~~~~ # TODO: Rename option names? # --syncdeps > --installdeps # --nodeps > --skipdeps # # TODO: Should root be aloud to run makepkg? # # TODO: Create error codes. # # TODO: Should build deps be removed after build? #____________________________________________________________________ set -e trap 'echo -e "\033[1;31mBANG! \033[1;37mThat didnt sound good. \033[1;33m:(\033[1;0m" >&2' ERR #set -x # For debugging, pipe the output to a file, there's lots of it. _DEBUG_MODE='n' #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Initialize Variables #---------------------------------------------------------------------- _VERSION='3.1.0' _BUG_REPORT_EMAIL='pacman-dev@archlinux.org' _ARG_LIST="$@" # Actions # ~~~~~~~~~ _CLEAN_CACHE='n' _CHECK_DEPS='y' _BUILD_DEPS='n' _SYNC_DEPS='n' _GENERATE_CHKSUM='n' _VALIDATE_CHKSUM='y' _EXTRACT_SOURCE='y' _BUILD_PACKAGE='y' _CLEANUP='n' _REMOVE_DEPS='n' _INSTALL_PACKAGE='n' # Options # ~~~~~~~~~ _FORCE='n' _REPACKAGE='n' _USE_SUDO='n' _LOG_BUILD='n' _USE_COLOR='n' # Miscellaneous # ~~~~~~~~~~~~~~~ _IN_FAKEROOT='n' _PACKAGE_NAME='UNKNOWN' _BUILD_SCRIPT='PKGBUILD' _PKG_EXT='pkg.tar.gz' _MAN_DIR='usr' # For Arch Linux #_MAN_DIR='usr/share' # For DIY-Linux _PACMAN_OPTS='' startdir="$(pwd)" # Exit/Error Codes # ~~~~~~~~~~~~~~~~~~ # TODO: Create exit codes for each different error. E_OK=0 E_UNKNOWN=1 E_USER_ABORT=4 E_INVALID_BUILD_SCRIPT=8 E_MISSING_PROGRAM=16 E_CONFIG_ERROR=32 # For dep checks # ~~~~~~~~~~~~~~~~ . /etc/abs/abs.conf _SRC_ROOT="$ABSROOT" #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # General purpose functions. #---------------------------------------------------------------------- # TODO: Use terminal safe coloring/bolding. See TODO.dan # TODO: Move general functions to an external library file, for all # pacman scripts to use. plain () { if [ $_USE_COLOR = 'y' ]; then echo -e " \033[1;37m$1\033[1;0m" >&2 else echo " $1" >&2 fi } msg () { if [ $_USE_COLOR = 'y' ]; then echo -e "\033[1;32m==>\033[1;37m $1\033[1;0m" >&2 else echo "==> $1" >&2 fi } msg2 () { if [ $_USE_COLOR = 'y' ]; then echo -e " \033[1;34m->\033[1;37m $1\033[1;0m" >&2 else echo " -> $1" >&2 fi } warning () { if [ $_USE_COLOR = 'y' ]; then echo -e "\033[1;33m==> WARNING:\033[1;37m $1\033[1;0m" >&2 else echo "==> WARNING: $1" >&2 fi } error () { if [ $_USE_COLOR = 'y' ]; then echo -e "\033[1;31m==> ERROR:\033[1;37m $1\033[1;0m" >&2 else echo "==> ERROR: $1" >&2 fi } debug () { [ $_DEBUG_MODE = 'y' ] || return if [ $_USE_COLOR = 'y' ]; then echo -e "\033[;35m**> DEBUG:\033[1;37m $1\033[1;0m" >&2 else echo "**> DEBUG: $1" >&2 fi } yn_question () { if [ $_USE_COLOR = 'y' ]; then echo -en " \033[1;1m$1\033[1;0m " >&2 else echo -n " $1 " >&2 fi local answer read answer answer="$(echo $answer | tr [:upper:] [:lower:])" if [ "$answer" = 'y' -o "$answer" = 'yes' ]; then return 0 else return 1 fi } strip_url () { echo "$1" | sed 's|^.*://.*/||g'; } in_array() { local needle=$1 shift 1 [ -z "$1" ] && return 1 for i in $*; do [ "$i" = "$needle" ] && return 0 done return 1 } in_array2 () { local needle=$(echo $1 | tr [:upper:] [:lower:]) local i shift 1 [ -z "$1" ] && return 2 for i in $*; do i=$(echo $i | tr [:upper:] [:lower:]) if [ "$i" = "$needle" ]; then return 0 elif [ "$i" = "!$needle" ]; then return 1 fi done return 2 } check_option () { local ret in_array2 $1 ${options[@]}; ret=$? [ $ret -eq 2 ] && { in_array2 $1 ${OPTIONS[@]}; ret=$?; } [ $ret -eq 2 ] && ret=1 return $ret } check_buildenv () { local ret in_array2 $1 ${BUILDENV[@]}; ret=$? [ $ret -eq -1 ] && ret=1 return $ret } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Usage functions. #---------------------------------------------------------------------- display_usage () { cat << EOF makepkg version $_VERSION Usage: $0 [options] Actions: -C, --cleancache Clean up source files from the cache. -g, --geninteg Generate integrity checks for source files. -c, --clean Clean up work files after build. -e, --noextract Do not extract source files (use existing src/ dir). -i, --install Install package after successful build. -o, --nobuild Download and extract files only. -R, --repackage Repackage contents of pkg/ without building. -b, --builddeps Build missing dependencies from source -d, --nodeps Skip all dependency checks -r, --rmdeps Remove installed dependencies after a successful build -s, --syncdeps Install missing dependencies with pacman Options: -f, --force Overwrite existing package. -L, --log Log package build process. -m, --nocolor Disable colorized output messages. -p <buildscript> Use an alternate build script (instead of '${_BUILD_SCRIPT}'). If -p is not specified, makepkg will look for '${_BUILD_SCRIPT}'. -S, --usesudo When calling pacman, use sudo. -h, --help Display this help and exit -V, --version Output version information and exit Variables: SRCDEST ... PKGDEST ... Exit Codes: 0 Ok 1 Unknown 4 User abort 8 Invalid build script 16 Missing program 32 Config error These options can be passed to pacman: --noconfirm Do not ask for confirmation when resolving dependencies --noprogressbar Do not show a progress bar when downloading files Report bugs to <${_BUG_REPORT_EMAIL}> EOF } display_version () { echo "makepkg $_VERSION"; } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # makepkg functions. #---------------------------------------------------------------------- run_build () { if [ "$(type -t $1)" != "function" ]; then error "Unknown function '$1'." exit 1 fi # use distcc if it is requested (check buildenv and PKGBUILD opts) if check_buildenv distcc && [ $(check_option distcc) -ne 1 ]; then [ -d /usr/lib/distcc/bin ] && export PATH="/usr/lib/distcc/bin:$PATH" elif [ $(check_option distcc) -eq 1 ]; then # if it is not wanted, clear the makeflags too export MAKEFLAGS="" fi # use ccache if it is requested (check buildenv and PKGBUILD opts) if check_buildenv ccache && [ $(check_option ccache) -ne 1 ]; then [ -d /usr/lib/ccache/bin ] && export PATH="/usr/lib/ccache/bin:$PATH" fi # clear user-specified makeflags if requested if [ $(check_option makeflags) -eq 1 ]; then export MAKEFLAGS="" fi msg "Running '$1'..." cd "${startdir}/src" # Some locales can break builds. local _LC_ALL="$LC_ALL" ; export LC_ALL='C' local _LANG="$LANG" ; export LANG='C' umask 0022 local ret=0 if [ $_LOG_BUILD = 'y' ]; then local build_log="${startdir}/${_PACKAGE_NAME}-${1}.log" if [ -f "$build_log" ]; then local i=1 while true; do if [ -f "${build_log}.$i" ]; then i=$(($i+1)) else break fi done mv "${build_log}" "${build_log}.$i" fi msg2 "$1 will be logged to $build_log" $1 2>&1 | tee "${build_log}" || ret=${PIPESTATUS[0]} else $1 2>&1 || ret=$? fi export LC_ALL="$_LC_ALL" export LANG="$_LANG" if [ $ret -gt 0 ]; then error "Build FAILED. Aborting" exit 2 # TODO: error code fi } tidy_install () { cd "${startdir}/pkg" msg "Tidying Install..." if ! check_option docs; then msg2 "Removing documentation files..." #fix flyspray bug #5021 rm -rf ${DOC_DIRS[@]} fi local old_man_dir if [ "$_MAN_DIR" = 'usr' ]; then old_man_dir='usr/share' else old_man_dir='usr' fi if [ -d $old_man_dir ]; then msg2 "Moving ${old_man_dir}/man files to /${_MAN_DIR}/man..." mkdir -p ${_MAN_DIR}/man cp -a ${old_man_dir}/man/* ${_MAN_DIR}/man/ rm -rf ${old_man_dir}/man fi if [ -d usr/info ]; then msg2 "Moving /usr/info files to /usr/share/info..." mkdir -p usr/share/info cp -a usr/info/* usr/share/info/ rm -rf usr/info fi [ -e usr/share/info/dir ] && rm -f usr/share/info/dir msg2 "Compressing man pages..." find {${_MAN_DIR}/,usr/local/,opt/*/}man -type f 2>/dev/null | while read i ; do ext="${i##*.}" fn="${i##*/}" if [ "$ext" != "gz" -a "$ext" != "bz2" ]; then # update symlinks to this manpage find {${_MAN_DIR},usr/local/,opt/*/}man -lname "$fn" 2> /dev/null | while read ln ; do rm -f "$ln" ln -sf "${fn}.gz" "${ln}.gz" done # compress the original gzip -9 "$i" fi done if check_option strip; then local file msg2 "Stripping debugging symbols from libraries..." for file in $(LC_ALL=C LANG=C \ find {,usr/,usr/local/,opt/*/}lib -type f -not -name "*.dll" -not -name "*.exe" \ -exec file '{}' \; 2>/dev/null | \ grep 'LSB shared object,' | cut -d : -f 1 ); do strip --strip-debug "${file}" done msg2 "Stripping symbols from binaries..." for file in $(LC_ALL=C LANG=C \ find {,usr/,usr/local/,opt/*/}{bin,sbin} -type f -not -name "*.dll" -not -name "*.exe" \ -exec file '{}' \; 2>/dev/null | \ grep 'LSB executable,' | cut -d : -f 1); do strip --strip-unneeded "${file}" done fi if ! check_option libtool; then msg2 "Removing libtool .la files..." find -type f -name "*.la" -exec rm -f -- '{}' \; fi if ! check_option emptydirs; then msg2 "Removing empty directories..." find -depth -type d -empty -delete; fi } create_package () { cd "${startdir}/pkg" msg "Creating package..." # get some package meta info # flyspray bug 6468 -- Localized dates for build/install date local builddate="$(LC_ALL=C ; LANG=C ; date -u +"%Y-%m-%dT%T%:z")" if [ "$PACKAGER" != "" ]; then local packager="$PACKAGER" else local packager="Arch Linux (http://www.archlinux.org)" fi local size=$(du -sb | awk '{print $1}') # build a filelist - do this first to keep meta files out of the list msg2 "Generating .FILELIST file..." tar -cvf /dev/null * | sort >.FILELIST # write the .PKGINFO file msg2 "Generating .PKGINFO file..." echo "# Generated by makepkg $_VERSION" >.PKGINFO echo "# $(LC_ALL=C; LANG=C; date -u)" >>.PKGINFO echo "pkgname = $pkgname" >>.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 if [ "$CARCH" != "" ]; then echo "arch = $CARCH" >>.PKGINFO fi local it for it in "${license[@]}"; do echo "license = $it" >>.PKGINFO done for it in "${replaces[@]}"; do echo "replaces = $it" >>.PKGINFO done for it in "${groups[@]}"; do echo "group = $it" >>.PKGINFO done for it in "${depends[@]}"; do echo "depend = $it" >>.PKGINFO done for it in "${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 # TODO: maybe remove this at some point # warn if license array is not present or empty if [ "$license" = "" ]; then warning "Please add a license line to your ${_BUILD_SCRIPT}!" plain "example for GPL'ed software: license=('GPL')." fi local comp_files # check for an install script if [ "$install" != "" ]; then msg2 "Copying install script..." cp "$startdir/$install" .INSTALL comp_files="${comp_files} .INSTALL" fi # do we have a changelog? if [ -f "$startdir/ChangeLog" ]; then msg2 "Copying package change log" cp "$startdir/ChangeLog" .CHANGELOG comp_files="${comp_files} .CHANGELOG" fi # tar it up msg2 "Compressing package..." local pkg_file="$PKGDEST/${_PACKAGE_NAME}.${_PKG_EXT}" comp_files="${comp_files} .PKGINFO .FILELIST" if ! tar -czf $pkg_file $comp_files *; then error "Failed to create package file." exit 1 # TODO: error code fi } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Dependencie check functions #---------------------------------------------------------------------- checkdeps() { debug "checkdeps() $*" [ $# -eq 0 ] && return pmout=$(pacman $PACMAN_OPTS -T $*) ret=$? if [ $ret -eq 127 ]; then #unresolved deps #strip out the pacman prefix from "requires: xyz" echo $pmout | sed 's|requires:||g' elif [ $ret -ne 0 ]; then error "pacman returned a fatal error ($ret): $pmout" exit 1 fi } handledeps() { debug "handledeps() $*" local R_DEPS_SATISFIED=0 local R_MISSING_DEPS=1 [ $# -eq 0 ] && return $R_DEPS_SATISFIED local deplist="$*" local striplist local dep for dep in $deplist; do depstrip="$(echo $dep | sed -e 's|=.*$||' -e 's|>.*$||' -e 's|<.*$||')" striplist="$striplist $depstrip" done if [ $_BUILD_DEPS = 'n' -a $_SYNC_DEPS = 'n' ]; then return $R_MISSING_DEPS elif [ $_USE_SUDO = 'n' -a $EUID -gt 0 ]; then warning "Cannot auto-install missing dependencies as a normal user without sudo!" plain "Run makepkg as root or with -S to resolve dependencies automatically." return $R_MISSING_DEPS fi if [ $_SYNC_DEPS = 'y' ]; then msg "Installing missing dependencies..." local ret=0 if [ $_USE_SUDO = 'y' ]; then # install missing deps from binary packages (using pacman -S and sudo) sudo pacman $_PACMAN_OPTS -S $striplist || ret=$? else # install missing deps from binary packages (using pacman -S) pacman $_PACMAN_OPTS -S $striplist || ret=$? fi if [ $ret -eq 1 ]; then error "Pacman failed to install missing dependencies." exit 1 # TODO: error code fi elif [ $_BUILD_DEPS = 'y' ]; then msg "Building missing dependencies..." # install missing deps by building them from source. # we look for each package name in $SRCROOT and build it. if [ "$_SRC_ROOT" = "" ]; then error "Source root cannot be found - please make sure it is specified in /etc/abs/abs.conf" exit $E_CONFIG_ERROR fi # TODO: handle version comparators (eg, glibc>=2.2.5) for dep in $striplist; do local candidates="$(find $_SRC_ROOT -type d -name "$dep")" if [ -z "$candidates" ]; then error "Could not find \"$dep\" under $_SRC_ROOT" exit 1 # TODO: error code fi local makepkg_opts='-i -c -b' [ $_REMOVE_DEPS = 'y' ] && makepkg_opts="-r $makepkg_opts" local ret=0 local pkgdir for pkgdir in $candidates; do if [ -f "$pkgdir/$_BUILD_SCRIPT" ]; then cd "$pkgdir" ret=0 PKGBUILD="$PKGBUILD" makepkg $makepkg_opts || ret=$? if [ $ret -eq 0 ]; then continue 2 fi fi done error "Failed to build \"$dep\"" exit 1 # TODO: error code done fi # rerun any additional sh scripts found in /etc/profile.d/ local i for i in /etc/profile.d/*.sh do if [ -x $i ]; then . $i &>/dev/null fi done return $R_DEPS_SATISFIED } resolvedeps() { debug "resolvedeps() $*" local R_DEPS_SATISFIED=0 local R_DEPS_MISSING=1 deplist="$(checkdeps $*)" [ -z "$deplist" ] && return $R_DEPS_SATISFIED if handledeps $deplist; then # check deps again to make sure they were resolved deplist="$(checkdeps $*)" [ -z "$deplist" ] && return $R_DEPS_SATISFIED elif [ $_SYNC_DEPS = 'y' -o $_BUILD_DEPS = 'y' ]; then error "Failed to install all missing dependencies." fi msg "Missing Dependencies:" local dep for dep in $deplist; do msg2 "$dep" done return $R_DEPS_MISSING } # fix flyspray bug #5923 removedeps() { [ $_REMOVE_DEPS = 'n' ] && return [ $_USE_SUDO = 'n' -a $EUID -gt 0 ] && return # runtimedeps and buildtimedeps are set when resolving deps local deplist="$runtimedeps $buildtimedeps" local striplist="" [ -z "$deplist" ] && return local dep for dep in $deplist; do striplist="$striplist $(echo $dep | sed -e 's|=.*$||' -e 's|>.*$||' -e 's|<.*$||')" done msg "Removing installed dependencies..." if [ $_USE_SUDO = 'y' ]; then sudo pacman $_PACMAN_OPTS -Rs $striplist else pacman $_PACMAN_OPTS -Rs $striplist fi # TODO: is error checking (pacman) required/helpful here? } install_package () { [ $_INSTALL_PACKAGE = 'n' ] && return [ $_USE_SUDO = 'n' -a $EUID -gt 0 ] && return local ret=0 msg "Installing package with 'pacman -U'..." if [ $_USE_SUDO = 'y' ]; then sudo pacman $_PACMAN_OPTS -U "${PKGDEST}/${_PACKAGE_NAME}.${_PKG_EXT}" || ret=$? else pacman $_PACMAN_OPTS -U "${PKGDEST}/${_PACKAGE_NAME}.${_PKG_EXT}" || ret=$? fi exit $ret } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Load config files #---------------------------------------------------------------------- # Preserve enviroment _PKGDEST="${PKGDEST}" _SRCDEST="${SRCDEST}" if [ -r /etc/makepkg.conf ]; then . /etc/makepkg.conf else error "/etc/makepkg.conf not found. cannot continue" exit $E_CONFIG_ERROR fi [ -r ~/.makepkg.conf ] && . ~/.makepkg.conf if check_buildenv color; then _USE_COLOR='y' fi # Environment overrules config file. PKGDEST="${_PKGDEST:-$PKGDEST}"; PKGDEST="${PKGDEST:-$startdir}" # default to $startdir if undefined SRCDEST="${_SRCDEST:-$SRCDEST}"; SRCDEST="${SRCDEST:-$startdir}" # default to $startdir if undefined unset _PKGDEST _SRCDEST #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Parse command line options #---------------------------------------------------------------------- _OPT_SHORT="bcCdefFghiLmop:rRsSV" _OPT_LONG="builddeps,clean,cleancache,nodeps,noextract,force,geninteg,help," _OPT_LONG="${_OPT_LONG}install,log,nocolor,nobuild,rmdeps,repackage,syncdeps," _OPT_LONG="${_OPT_LONG}version,usesudo,noconfirm,noprogressbar" _OPT_TEMP=$(getopt -o $_OPT_SHORT --long $_OPT_LONG -n "$0" -- "$@") eval set -- "$_OPT_TEMP" unset _OPT_SHORT _OPT_LONG _OPT_TEMP while true; do case $1 in # makepkg Options -b|--builddeps) _BUILD_DEPS='y';; -c|--clean) _CLEANUP='y';; -C|--cleancache) _CLEAN_CACHE='y';; -d|--nodeps) _CHECK_DEPS='n';; -e|--noextract) _EXTRACT_SOURCE='n';; -f|--force) _FORCE='y';; -F) _IN_FAKEROOT='y';; -g|--geninteg) _GENERATE_CHKSUM='y';; -i|--install) _INSTALL_PACKAGE='y';; -L|--log) _LOG_BUILD='y';; -m|--nocolor) _USE_COLOR='n';; -o|--nobuild) _BUILD_PACKAGE='n';; -r|--rmdeps) _REMOVE_DEPS='y';; -R|--repackage) _REPACKAGE='y';; -s|--syncdeps) _SYNC_DEPS='y';; -S|--usesudo) _USE_SUDO='y';; -p) _BUILD_SCRIPT="$2"; shift;; # pacman Options --noconfirm) _PACMAN_OPTS="$_PACMAN_OPTS --noconfirm";; --noprogressbar) _PACMAN_OPTS="$_PACMAN_OPTS --noprogressbar";; -h|--help) display_usage; exit $E_OK;; -V|--version) display_version; exit $E_OK;; --) OPTIND=0; shift; break;; *) display_usage; exit $E_UNKNOWN;; esac shift done #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Clean Cache #---------------------------------------------------------------------- if [ $_CLEAN_CACHE = 'y' ]; then #fix flyspray feature request #5223 if [ -n "$SRCDEST" -a "$SRCDEST" != "$startdir" ]; then msg "Cleaning up ALL files from ${SRCDEST}." if yn_question "Are you sure you wish to do this? [Y/n]"; then ret=0 rm "$SRCDEST"/* || ret=$? if [ $ret -ne 0 ]; then error "Problem removing files; you may not have correct permissions in $SRCDEST" exit 1 # TODO: error code else # removal worked msg "Source cache cleaned." exit $E_OK fi else # answer = no msg "No files have been removed." exit $E_OK fi else # $SRCDEST is $startdir, two possibilities error "Source destination must be defined in makepkg.conf." plain "In addition, please run makepkg -C outside of your cache directory." exit $E_CONFIG_ERROR fi fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Privilage checks #---------------------------------------------------------------------- if [ $_IN_FAKEROOT = 'n' ]; then if [ $EUID -eq 0 ]; then warning "Running makepkg as root is a \033[1;31mBAD\033[1;37m idea!" plain "" if ! yn_question "Are you sure you want to continue? [N/y]"; then error "Aborting..." exit $E_USER_ABORT fi elif check_buildenv fakeroot; then if ! type -p fakeroot &>/dev/null; then warning "Fakeroot is not installed. Building as an unprivileged user" plain "will result in non-root ownership of the packaged files. Install" plain "the fakeroot package to correctly build as a non-root user." plain "" if ! yn_question "Are you sure you want to continue? [N/y]"; then error "Aborting..." exit $E_USER_ABORT fi fi else warning "Running makepkg as an unprivileged user will result in non-root" plain "ownership of the packaged files. Try using the fakeroot environment by" plain "placing 'fakeroot' in the BUILDENV array in /etc/makepkg.conf." plain "" if ! yn_question "Are you sure you want to continue? [N/y]"; then error "Aborting..." exit $E_USER_ABORT fi fi else if [ -z "$FAKEROOTKEY" ]; then error "Do not use the -F option. This option is only used by makepkg when" plain "it is calling it's self inside fakeroot." plain "" exit 1 # TODO: error code fi fi if [ $_USE_SUDO = 'y' -a ! "$(type -p sudo)" ]; then error "Can not find the sudo binary! Is sudo installed?" exit $E_MISSING_PROGRAM elif [ $EUID -gt 0 -a $_INSTALL_PACKAGE = 'y' ]; then # TODO: Should this be an error and exit? warning "makepkg will not be able to install this package as an unprivilaged user." plain "Use the --usesudo (or -s) option to install this package after it has been" plain "built." plain "" sleep 3 fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Load $_BUILD_SCRIPT. #---------------------------------------------------------------------- unset pkgname pkgver pkgrel pkgdesc url license groups provides md5sums force unset replaces depends conflicts backup source install build makedepends unset options noextract if [ ! -r "$_BUILD_SCRIPT" ]; then error "$_BUILD_SCRIPT does not exist." exit $E_INVALID_BUILD_SCRIPT #TODO this is an attempt at a generic way to unset all package specific #variables in a PKGBUILD #else # #this is fun.... we'll unset # for var in $(grep "=" $_BUILD_SCRIPT | sed "s|.*\(\<.*\>\)=.*|\1|g"); do # unset $var # done fi source "$_BUILD_SCRIPT" #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Sanity checks for $_BUILD_SCRIPT. #---------------------------------------------------------------------- # check for no-no's in the build script if [ -z "$pkgver" ]; then error "pkgver is not allowed to be empty." exit $E_INVALID_BUILD_SCRIPT fi if echo "$pkgver" | grep -q '-'; then error "pkgver is not allowed to contain hyphens." exit $E_INVALID_BUILD_SCRIPT fi if [ -z "$pkgrel" ]; then error "pkgrel is not allowed to be empty." exit $E_INVALID_BUILD_SCRIPT fi if echo "$pkgrel" | grep -q '-'; then error "pkgrel is not allowed to contain hyphens." exit $E_INVALID_BUILD_SCRIPT fi if ! in_array $CARCH ${arch[@]}; then error "$pkgname is not available for the '$CARCH' architecture." plain "Note that many packages may need a line added to their $_BUILD_SCRIPT" plain "such as arch=('$CARCH')." exit 1 # TODO: error code fi _PACKAGE_NAME="${pkgname}-${pkgver}-${pkgrel}-${CARCH}" if [ "$install" -a ! -f "$install" ]; then error "install scriptlet ($install) does not exist." exit $E_INVALID_BUILD_SCRIPT fi if [ -f "$PKGDEST/${_PACKAGE_NAME}.${_PKG_EXT}" \ -a $_FORCE = 'n' -a $_GENERATE_CHKSUM = 'n' ]; then if [ $_INSTALL_PACKAGE = 'y' ]; then warning "a package has already been built, installing existing package." installpackage else error "a package has already been built. (use -f to overwrite)" exit 1 # TODO: error code fi fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Build package inside fakeroot. #---------------------------------------------------------------------- # Run the bear minimum in fakeroot. # flyspray bug 6208 -- using makepkg with fakeroot gives an error if [ $_IN_FAKEROOT = 'y' ]; then if [ $_REPACKAGE = 'y' ]; then warning "Skipping build..." else if [ "$(type -t fake_install)" != "function" ]; then run_build build else run_build fake_install fi tidy_install fi create_package msg "Leaving fakeroot enviroment." exit $E_OK fi msg "Making package: $pkgname $pkgver-$pkgrel ($(date))" if [ $_REPACKAGE = 'n' ]; then msg "Preparing work area..." if [ -d "${startdir}/src" ]; then msg2 "Removing existing src/ directory..." rm -rf "${startdir}/src" fi if [ -d "${startdir}/pkg" ]; then msg2 "Removing existing pkg/ directory..." rm -rf "${startdir}/pkg" fi fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Check dependencies. #---------------------------------------------------------------------- # fix flyspray bug #5973 if [ $_CHECK_DEPS = 'n' -o $_GENERATE_CHKSUM = 'y' -o \ $_BUILD_PACKAGE = 'n' -o $_REPACKAGE = 'y' ]; then if [ $_CHECK_DEPS = 'n' ]; then warning "Skipping dependecy checks." fi elif [ ! "$(type -p pacman)" ]; then warning "pacman was not found in PATH. skipping dependency checks." else deperr=0 unset runtimedeps buildtimedeps msg "Checking Runtime Dependencies..." if resolvedeps ${depends[@]}; then # deplist is a global variable set by resolvedeps runtimedeps="$deplist" else deperr=1 fi msg "Checking Buildtime Dependencies..." if resolvedeps ${makedepends[@]}; then # deplist is a global variable set by resolvedeps buildtimedeps="$deplist" else deperr=1 fi if [ $deperr -eq 1 ]; then error "could not resolve all dependencies." exit 1 # TODO: error code fi unset deperr fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Retrieve source. #---------------------------------------------------------------------- msg "Retrieving source files..." cd "${startdir}" mkdir -p src; cd src for netfile in ${source[@]}; do file="$(strip_url "$netfile")" if [ -f "../$file" ]; then msg2 "Found $file in build directory." cp "../$file" . elif [ -f "$SRCDEST/$file" ]; then msg2 "Using cached copy of ${file}." cp "$SRCDEST/$file" . else # check for a download utility if [ -z "$FTPAGENT" ]; then error "FTPAGENT is not configured. Check the /etc/makepkg.conf file." msg "Aborting..." exit $E_CONFIG_ERROR fi ftpclient="$(echo $FTPAGENT | awk {'print $1'})" if [ ! -x "$ftpclient" ]; then error "ftpclient $(basename $ftpclient) is not installed." msg "Aborting..." exit $E_MISSING_PROGRAM fi proto="$(echo "$netfile" | sed 's|://.*||')" if [ "$proto" != 'ftp' -a "$proto" != 'http' -a "$proto" != 'https' ]; then error "$netfile was not found in the build directory and is not a proper URL." msg "Aborting..." exit 1 # TODO: error code fi msg2 "Downloading ${file}..." ret=0 $FTPAGENT "$netfile" || ret=$? # fix flyspray bug #3289 if [ $ret -gt 0 ]; then error "Failure while downloading $file" msg "Aborting..." #rm "$file" exit 1 # TODO: error code fi if [ -n "$SRCDEST" ]; then ret=0 mkdir -p "$SRCDEST" && cp "$file" "$SRCDEST" || ret=$? if [ $ret -ne 0 ]; then warning "You do not have correct permissions to cache source in $SRCDEST" cp "$file" .. fi else cp "$file" .. fi fi done unset netfile file ftpclient proto ret #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Generate source file checksums. #---------------------------------------------------------------------- if [ $_GENERATE_CHKSUM = 'y' ]; then msg "Generating checksums for source files..." plain "" for integ in ${INTEGRITY_CHECK[@]}; do integ="$(echo $integ | tr [:upper:] [:lower:])" case "$integ" in md5|sha1|sha256|sha384|sha512) : ;; *) error "Invalid integrity algorithm '$integ' specified." exit $E_CONFIG_ERROR;; esac if ! type -p "${integ}sum" &>/dev/null; then error "Can not find the ${integ}sum program." exit $E_MISSING_PROGRAM fi ct=0 numsrc=${#source[@]} echo -n "${integ}sums=(" for netfile in "${source[@]}"; do file="$(strip_url "$netfile")" if [ ! -r "${file}" ]; then plain "" error "Unable to find '${file}' to generate checksum." exit 1 # TODO: error code fi sum=$(${integ}sum "$file" | cut -d ' ' -f 1) [ $ct -gt 0 ] && echo -ne "\t " echo -n "'$sum'" ct=$(($ct+1)) [ $ct -lt $numsrc ] && echo done echo ')' done exit $E_OK fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Validate source file checksums. #---------------------------------------------------------------------- if [ $_EXTRACT_SOURCE = 'n' -o $_REPACKAGE = 'y' ]; then warning "Skipping source integrity checks." elif [ $_VALIDATE_CHKSUM = 'y' ]; then for integ in ${INTEGRITY_CHECK[@]}; do integ="$(echo $integ | tr [:upper:] [:lower:])" case "$integ" in md5|sha1|sha256|sha384|sha512) : ;; *) error "Invalid integrity algorithm '$integ' specified." exit $E_CONFIG_ERROR;; esac if ! type -p "${integ}sum" &>/dev/null; then error "Can not find the ${integ}sum program." exit $E_MISSING_PROGRAM fi chksums=($(eval echo \${${integ}sums[@]})) if [ ${#chksums[@]} -ne ${#source[@]} ]; then warning "Integrity checks (${integ}) are missing or incomplete." else msg "Validating source files with ${integ}sums..." errors=0 idx=0 for netfile in "${source[@]}"; do file="$(strip_url "$netfile")" echo -n " $file ... " >&2 if echo "${chksums[$idx]} $file" | ${integ}sum --status -c -; then echo "Passed" >&2 else echo "FAILED" >&2 errors=1 fi idx=$(($idx+1)) done if [ $errors -gt 0 ]; then error "One or more files did not pass the validity check!" exit 1 # TODO: error code fi fi done unset integ chksums errors idx netfile file fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Extract sources. #---------------------------------------------------------------------- if [ $_EXTRACT_SOURCE = 'n' -o $_REPACKAGE = 'y' ]; then warning "Skipping source extraction -- using existing src/ tree." else msg "Extracting Sources..." for netfile in "${source[@]}"; do unziphack=0 file="$(strip_url "$netfile")" if in_array "$file" ${noextract[@]}; then #skip source files in the noextract=() array # these are marked explicitly to NOT be extracted continue fi # fix flyspray #6246 file_type="$(file -biz "$file")" cmd='' case "$file_type" in *application/x-tar*) cmd="tar --no-same-owner -xf $file" ;; *application/x-zip*) unziphack=1 cmd="unzip -qqo $file" ;; *application/x-cpio*) cmd="bsdtar -x -f $file" ;; *application/x-gzip*) cmd="gunzip -f $file" ;; *application/x-bzip*) cmd="bunzip2 -f $file" ;; esac if [ "$cmd" != "" ]; then msg2 "$cmd" ret=0 $cmd || ret=$? if [ $ret -ne 0 ]; then # unzip will return a 1 as a warning, it is not an error if [ $unziphack -eq 1 -o $ret -ne 1 ]; then error "Failed to extract $file" msg "Aborting..." exit 1 # TODO: error code fi fi fi done unset netfile file file_type cmd unziphack ret fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Build package #---------------------------------------------------------------------- if [ $_BUILD_PACKAGE = 'n' ]; then msg "Sources are ready." exit $E_OK else cd "$startdir" mkdir -p pkg if [ $EUID -eq 0 ]; then warning "It is not a good idea to run makepkg as root." if [ $_REPACKAGE = 'y' ]; then warning "Skipping build." else cd "${startdir}/src" run_build build [ "$(type -t fake_install)" = "function" ] && run_build fake_install tidy_install fi create_package else cd "${startdir}/src" if [ $_REPACKAGE = 'n' -a "$(type -t fake_install)" = "function" ]; then run_build build fi msg "Entering fakeroot environment." cd "${startdir}" ret=0 fakeroot -- $0 -F $_ARG_LIST || ret=$? [ $ret -ne 0 ] && exit $ret unset ret fi fi #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Clean up #---------------------------------------------------------------------- if [ $_CLEANUP = 'y' ]; then msg "Cleaning up..." cd "$startdir" rm -rf src pkg rm -f "${_PACKAGE_NAME}.log*" fi removedeps msg "Finished making: $pkgname ($(date))" install_package exit $E_OK # vim:set ts=2 sw=2 noet:
On 3/23/07, Andrew Fyfe <andrew@neptune-one.net> wrote:
Hi, I've been using pacman for over a year now on DIY-Linux (http://www.diy-linux.org), and to put it simply it's great easy to use and easy to setup. So I thought it was about time I contribute something back... an improved version of makepkg. For the impatient :p see the script attached.
Welcome to the list, good to have a few new voices.
makepkg2's use of fakeroot was a bit hackish, it's now very hackish in makepkg3. It also kicks up a few strange bugs (flyspray #6208) because it's being used where it shouldn't be. So I've rewritten/reordered makepkg to reduce the amount of time spent in fakeroot. Specificly it's now only used for...
fake_install() (if it exists. See below) build() (if there's no fake_install) tidy_install() - remove docs - move/compress man pages - strip binaries/libraries - remove libtool files - remove empty directories create_package() - create .PKGINFO & .FILELIST - tar it all up
everything else is run outside of fakeroot.
Yes, this is definitely a better way to go about doing this. makepkg itself is getting a bit unwieldy, and the original method of recalling itself with fakeroot is quite ugly.
Over at DIY-Linux we have a patch that adds an extra function to PKGBUILD (fake_install). This way we can prepare, compile, and test the package as the user running makepkg. Then fake_install is run inside fakeroot to install the package. This further reduces the time spent in fakeroot and the possibility of any weird bugs popping up. If the build script doesn't contain a fake_install function the build function is run inside of fakeroot instead (maintaining backwards compatibility with how things work at the moment).
So if I understand correctly, each PKGBUILD would have a build() function to actually build, and a fake_install() function that usually contains something like 'make install'? This seems like a pretty sane idea, although some of our PKGBUILDs are a bit convoluted.
Other changes... - reordered the code to reduce the number of if..then..else cases Probably needed on our end as well.
- renamed a lot of variables so they're a bit more descriptive. +1
- started to add error codes for the different reasons why makepkg exits +1, this is something I started thinking about but never got around to doing.
- quoted all variables that contain paths so '/home/me/a folder with spaces' doesn't cause errors. (but build scripts are still a point of failure as the majority don't have $startdir in quotes.) I think I got all of these in my last run through of the script, but don't quote me on that (wow, bad joke). :) - fixed flyspray bug #6468 -- Localized dates for build/install date Ooo, we'll definitely look at this.
- added some more error catching - added the ability to choose between usr/man and usr/share/man (var (_MAN_DIR) at the top of the script.) This should maybe even be in makepkg.conf.
There are still a few things that need fixed, but some discussion is probably required.
- Should build deps be removed after a successful build? At the moment deps are only removed if '-r' is used and it removes build deps and runtime deps. An extra option to remove build deps?
- Should root be a loud to run makepkg? IMO running makepkg as root is a hanus crime, and anyone foolish enough to do so deserves to have their system burn to the ground as the result of a broken build script. One mistaken key stroke in a build script can result in a successful build or the destruction of a system :p I've added a warning that asks the user if they're sure the want to continue running makepkg as root. With sudo and fakeroot there's no need to run makepkg as root, but thats just my opinion. It's my opinion too. I think we should definitely have a warning and prompt that has to be answered when building as root.
Welcome to the list, hope you can help us get a lot of these fixes into the upstream makepkg. -Dan
So if I understand correctly, each PKGBUILD would have a build() function to actually build, and a fake_install() function that usually contains something like 'make install'? This seems like a pretty sane idea, although some of our PKGBUILDs are a bit convoluted. Yes, that's correct.
- fixed flyspray bug #6468 -- Localized dates for build/install date Ooo, we'll definitely look at this. Well fixed probably isn't the right word. I followed the suggestion of using the ISO 8601 date format YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) in .PKGINFO, pacman/libalm still needs patched to localize the date.
- added the ability to choose between usr/man and usr/share/man (var (_MAN_DIR) at the top of the script.) This should maybe even be in makepkg.conf. Yeah that would be better.
Welcome to the list, hope you can help us get a lot of these fixes into the upstream makepkg. Thanks :)
-Dan
_______________________________________________ pacman-dev mailing list pacman-dev@archlinux.org http://www.archlinux.org/mailman/listinfo/pacman-dev
- fixed flyspray bug #6468 -- Localized dates for build/install date Ooo, we'll definitely look at this. Well fixed probably isn't the right word. I followed the suggestion of using the ISO 8601 date format YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) in .PKGINFO, pacman/libalm still needs patched to localize the date. Why the hell did I say fixed. I've thought of a better solution. Set builddate (in .PKGINFO) to unix epoch, then when pacman displays it use ctime() (time.h). It converts a unix epoch to a localized time string based on /etc/localtime or the TZ enviroment variable.
Andrew
On 3/24/07, Andrew Fyfe <andrew@neptune-one.net> wrote:
- fixed flyspray bug #6468 -- Localized dates for build/install date Ooo, we'll definitely look at this. Well fixed probably isn't the right word. I followed the suggestion of using the ISO 8601 date format YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) in .PKGINFO, pacman/libalm still needs patched to localize the date. Why the hell did I say fixed. I've thought of a better solution. Set builddate (in .PKGINFO) to unix epoch, then when pacman displays it use ctime() (time.h). It converts a unix epoch to a localized time string based on /etc/localtime or the TZ enviroment variable.
Interested in working on this? We need to make it backwards compatible as well. What if we stuck both an old formatted time and new formatted time in there, allowed pacman to read both (but prefer the newer), and eventually phase out the old style? We need a way for it to transition well. -Dan
On 6/10/07, Dan McGee <dpmcgee@gmail.com> wrote:
On 3/24/07, Andrew Fyfe <andrew@neptune-one.net> wrote:
- fixed flyspray bug #6468 -- Localized dates for build/install date Ooo, we'll definitely look at this. Well fixed probably isn't the right word. I followed the suggestion of using the ISO 8601 date format YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) in .PKGINFO, pacman/libalm still needs patched to localize the date. Why the hell did I say fixed. I've thought of a better solution. Set builddate (in .PKGINFO) to unix epoch, then when pacman displays it use ctime() (time.h). It converts a unix epoch to a localized time string based on /etc/localtime or the TZ enviroment variable.
Interested in working on this? We need to make it backwards compatible as well. What if we stuck both an old formatted time and new formatted time in there, allowed pacman to read both (but prefer the newer), and eventually phase out the old style? We need a way for it to transition well.
Carving my way through some old emails.... How does this sound for a sanity check while we do this conversion: If build/install date start with a non-digit, use old code, otherwise asssume it's an epoch? Dan checked this out, it doesn't seem to be localized and hasn't changed in a while: builddate=$(LC_ALL= ; LANG= ; date -u "+%a %b %e %H:%M:%S %Y") If no one sees problems with this, I will move it to the master branch when I get a chance. - Aaron
2007/9/19, Aaron Griffin <aaronmgriffin@gmail.com>:
Carving my way through some old emails....
How does this sound for a sanity check while we do this conversion: If build/install date start with a non-digit, use old code, otherwise asssume it's an epoch?
What do you mean by epoch? ISO 8601 date format YYYY-MM-DDThh:mm:ssTZD (e.g. 1997-07-16T19:20:30+01:00) or just the Unix timestamp (number of seconds since 1970)?
Dan checked this out, it doesn't seem to be localized and hasn't changed in a while:
builddate=$(LC_ALL= ; LANG= ; date -u "+%a %b %e %H:%M:%S %Y")
If no one sees problems with this, I will move it to the master branch when I get a chance.
-- Roman Kyrylych (Роман Кирилич)
On 9/19/07, Roman Kyrylych <roman.kyrylych@gmail.com> wrote:
2007/9/19, Aaron Griffin <aaronmgriffin@gmail.com>:
Carving my way through some old emails....
How does this sound for a sanity check while we do this conversion: If build/install date start with a non-digit, use old code, otherwise asssume it's an epoch?
What do you mean by epoch? ISO 8601 date format YYYY-MM-DDThh:mm:ssTZD (e.g. 1997-07-16T19:20:30+01:00) or just the Unix timestamp (number of seconds since 1970)?
2007/9/19, Aaron Griffin <aaronmgriffin@gmail.com>:
On 9/19/07, Roman Kyrylych <roman.kyrylych@gmail.com> wrote:
2007/9/19, Aaron Griffin <aaronmgriffin@gmail.com>:
Carving my way through some old emails....
How does this sound for a sanity check while we do this conversion: If build/install date start with a non-digit, use old code, otherwise asssume it's an epoch?
What do you mean by epoch? ISO 8601 date format YYYY-MM-DDThh:mm:ssTZD (e.g. 1997-07-16T19:20:30+01:00) or just the Unix timestamp (number of seconds since 1970)?
Huh? "The Unix epoch is the time 00:00:00 UTC on January 1, 1970". :-P I knew this before, nothing new. I asked about the string format used to represent the time. "For brevity, the remainder of this section will use ISO 8601 date format, in which the Unix epoch is 1970-01-01T00:00:00Z." So? ;-) -- Roman Kyrylych (Роман Кирилич)
On 9/19/07, Roman Kyrylych <roman.kyrylych@gmail.com> wrote:
2007/9/19, Aaron Griffin <aaronmgriffin@gmail.com>:
On 9/19/07, Roman Kyrylych <roman.kyrylych@gmail.com> wrote:
2007/9/19, Aaron Griffin <aaronmgriffin@gmail.com>:
Carving my way through some old emails....
How does this sound for a sanity check while we do this conversion: If build/install date start with a non-digit, use old code, otherwise asssume it's an epoch?
What do you mean by epoch? ISO 8601 date format YYYY-MM-DDThh:mm:ssTZD (e.g. 1997-07-16T19:20:30+01:00) or just the Unix timestamp (number of seconds since 1970)?
Huh?
"The Unix epoch is the time 00:00:00 UTC on January 1, 1970". :-P I knew this before, nothing new. I asked about the string format used to represent the time.
"For brevity, the remainder of this section will use ISO 8601 date format, in which the Unix epoch is 1970-01-01T00:00:00Z."
So? ;-)
"it is the number of seconds elapsed since midnight UTC of January 1, 1970" "number of seconds" is the operative term. It is not a string format, it is a number. Using _any_ string format will cause problems in the future. As an aside though, the strptime parsing of the old-format dates in the patch on my working branch also gives us timezone adjustments. Yay.
Andrew Fyfe wrote:
makepkg2's use of fakeroot was a bit hackish, it's now very hackish in makepkg3. It also kicks up a few strange bugs (flyspray #6208) because it's being used where it shouldn't be. So I've rewritten/reordered makepkg to reduce the amount of time spent in fakeroot. Specificly it's now only used for...
fake_install() (if it exists. See below) build() (if there's no fake_install) tidy_install() - remove docs - move/compress man pages - strip binaries/libraries - remove libtool files - remove empty directories create_package() - create .PKGINFO & .FILELIST - tar it all up
everything else is run outside of fakeroot.
Attached are 6 patches to clean up fakeroot. I've split them up into separate patches to make it's easier to read. It's mostly white space and moving code from one end of the script to the other. Patches 1-4 reorder and clean up makepkg in preperation for the cleaner method of running fakeroot. Patch 5 is the new fakeroot implementation. Patch 6 is the fake_install implementation. See the top of each patch for a more detailed outline of the changes. Apply the patches in this order... [1] pacman-cvs-chksums.patch [2] pacman-cvs-create_package.patch [3] pacman-cvs-tidy_install.patch [4] pacman-cvs-run_build.patch [5] pacman-cvs-fakeroot.patch [6] pacman-cvs-fake_install.patch When I get the chance I'll make patches for the other features/fixes I've added to makepkg. Andrew ------------------------------------------------------------ revno: 2 committer: Andrew Fyfe <andrew@neptune-one.net> branch nick: feature_chksums timestamp: Sat 2007-03-24 03:52:10 +0000 message: * Cleaned up and reordered generate/validate checksum code * Renamed GENINTEG to _GENERATE_CHKSUMS === modified file 'scripts/makepkg' --- old/scripts/makepkg 2007-03-24 03:49:27 +0000 +++ new/scripts/makepkg 2007-03-24 03:51:07 +0000 @@ -41,7 +41,7 @@ DEP_SRC=0 SUDO=0 FORCE=0 -GENINTEG=0 +_GENERATE_CHKSUMS='n' INSTALL=0 NOBUILD=0 NODEPS=0 @@ -445,7 +445,7 @@ --force) FORCE=1 ;; --nobuild) NOBUILD=1 ;; --nocolor) USE_COLOR="n" ;; - --geninteg) GENINTEG=1 ;; + --geninteg) _GENERATE_CHKSUMS='y';; --rmdeps) RMDEPS=1 ;; --repackage) REPKG=1 ;; --log) LOGGING=1 ;; @@ -466,7 +466,7 @@ d) NODEPS=1 ;; e) NOEXTRACT=1 ;; f) FORCE=1 ;; - g) GENINTEG=1 ;; + g) _GENERATE_CHKSUMS='y';; h) usage exit 0 @@ -582,7 +582,7 @@ fi if [ -f "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}.${PKGEXT}" \ - -a "$FORCE" = "0" -a "$GENINTEG" = "0" ]; then + -a "$FORCE" = "0" -a $_GENERATE_CHKSUMS = 'n' ]; then if [ "$INSTALL" = "1" ]; then warning "a package has already been built, installing existing package." installpackage @@ -621,7 +621,7 @@ msg "Making package: $pkgname $pkgver-$pkgrel ($(date))" # fix flyspray bug #5973 -if [ "$NODEPS" = "1" -o "$GENINTEG" = "1" -o "$NOBUILD" = "1" -o "$REPKG" = "1" ]; then +if [ "$NODEPS" = "1" -o $_GENERATE_CHKSUMS = 'y' -o "$NOBUILD" = "1" -o "$REPKG" = "1" ]; then if [ "$NODEPS" = "1" ]; then warning "skipping dependency checks" fi @@ -712,84 +712,82 @@ fi done +if [ $_GENERATE_CHKSUMS = 'y' ]; then + msg "Generating checksums for source files..." + plain "" + + for integ in ${INTEGRITY_CHECK[@]}; do + integ="$(echo $integ | tr [:upper:] [:lower:])" + case "$integ" in + md5|sha1|sha256|sha384|sha512) : ;; + *) error "Invalid integrity algorithm '$integ' specified."; exit 1;; # $E_CONFIG_ERROR + esac + + if [ ! $(type -p "${integ}sum") ]; then + error "Cannot fin the '${integ}sum' program." + exit 1 # $E_MISSING_PROGRAM + fi + + ct=0 + numsrc=${#source[@]} + echo -n "${integ}sums=(" + + for netfile in ${source[@]}; do + file="$(strip_url "$netfile")" + sum="$(${integ}sum "$file" | cut -d ' ' -f 1)" + [ $ct -gt 0 ] && echo -ne "\t " + echo -n "'$sum'" + ct=$(($ct+1)) + [ $ct -lt $numsrc ] && echo + done + + echo ")" + done + + exit 0 # $E_OK +fi + if [ "$NOEXTRACT" = "1" -o "$REPKG" = "1" ]; then warning "Skipping source integrity checks -- using existing src/ tree" else - # TODO we end up checking $GENINTEG 3 times, could probably be refactored - if [ "$GENINTEG" = "1" ]; then - msg "Generating checksums for source files" - plain "" - fi - for integ in ${INTEGRITY_CHECK[@]}; do - integ="$(echo $integ | tr A-Z a-z)" + integ="$(echo $integ | tr [:upper:] [:lower:])" case "$integ" in - md5) integrity_name="md5sum" ;; - sha1) integrity_name="sha1sum" ;; - sha256) integrity_name="sha256sum" ;; - sha384) integrity_name="sha384sum" ;; - sha512) integrity_name="sha512sum" ;; - *) error "Invalid integrity algorithm '$integ' specified"; exit 1;; + md5|sha1|sha256|sha384|sha512) : ;; + *) error "Invalid integrity algorithm '$integ' specified"; exit 1;; # $E_CONFIG_ERROR esac - if [ ! $(type -p $integrity_name) ]; then - error "Cannot find the $integrity_name program." - exit 1 + + if [ ! $(type -p "${integ}sum") ]; then + error "Cannot find the ${integ}sum program." + exit 1 # $E_MISSING_PROGRAM fi - #Generate integrity checks - if [ "$GENINTEG" = "1" ]; then - ct=0 - numsrc=${#source[@]} - for netfile in "${source[@]}"; do - file=$(strip_url "$netfile") - sum=$(eval "$integrity_name '$file' | cut -d' ' -f 1") - if [ $ct -eq 0 ]; then - echo -n "${integrity_name}s=(" - else - echo -ne "\t " - fi - echo -n "'$sum'" - ct=$(($ct+1)) - if [ $ct -eq $numsrc ]; then - echo ')' - else - echo - fi + integrity_sums=($(eval echo \${${integrity_name}s[@]})) + if [ ${#integrity_sums[@]} -eq ${#source[@]} ]; then + msg "Validating source files with ${integ}sums" + errors=0 + idx=0 + for file in "${source[@]}"; do + file="$(strip_url "$netfile")" + echo -n " $file ... " >&2 + if echo "${integrity_sums[$idx]} $file" | ${integ}sum --status -c -; then + echo "Passed" >&2 + else + echo "FAILED" >&2 + errors=1 + fi + idx=$(($idx+1)) done - #Validate integrity checks - else - integrity_sums=($(eval echo \${${integrity_name}s[@]})) - - if [ ${#integrity_sums[@]} -eq ${#source[@]} ]; then - msg "Validating source files with ${integrity_name}s" - errors=0 - idx=0 - for netfile in "${source[@]}"; do - file=$(strip_url "$netfile") - echo -n " $file ... " >&2 - echo "${integrity_sums[$idx]} $file" | $integrity_name -c - >/dev/null 2>&1 - if [ $? -ne 0 ]; then - echo "FAILED" >&2 - errors=1 - else - echo "Passed" >&2 - fi - idx=$(($idx+1)) - done - if [ $errors -gt 0 ]; then - error "One or more files did not pass the validity check!" - exit 1 - fi - else - warning "Integrity checks ($integ) are missing or incomplete." + if [ $errors -gt 0 ]; then + error "One or more files did not pass the validity check!" + exit 1 # TODO: error code fi + else + warning "Integrity checks ($integ) are missing or incomplete." fi done - if [ "$GENINTEG" = "1" ]; then - plain "" - exit 0 - fi + unset integ integrity_sums errors idx file fi #Extract sources ------------------------------------------------------------ revno: 2 committer: Andrew Fyfe <andrew@neptune-one.net> branch nick: feature_create_package timestamp: Sat 2007-03-24 03:55:00 +0000 message: * moved create package commands into create_package () * cleaned up create_package () === modified file 'scripts/makepkg' --- old/scripts/makepkg 2007-03-24 03:49:27 +0000 +++ new/scripts/makepkg 2007-03-24 03:54:24 +0000 @@ -348,6 +348,98 @@ fi } +create_package () { + cd "$startdir/pkg" + msg "Creating package..." + + # get some package meta info + # fix flyspray bug 6468 -- Localized dates for build/install date + local builddate="$(LC_ALL=C ; LANG=C ; date -u +"%Y-%m-%dT%T%:z")" + if [ "$PACKAGER" != "" ]; then + local packager="$PACKAGER" + else + local packager="Arch Linux (http://www.archlinux.org)" + fi + local size=$(du -sb | awk '{print $1}') + + # build a filelist - do this first to keep meta files out of the list + msg2 "Generating .FILELIST file..." + tar -cvf /dev/null * | sort >.FILELIST + + # write the .PKGINFO file + msg2 "Generating .PKGINFO file..." + echo "# Generated by makepkg $myver" >.PKGINFO + echo "# $(LC_ALL=C; LANG=C; date -u)" >>.PKGINFO + echo "pkgname = $pkgname" >>.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 + if [ "$CARCH" != "" ]; then + echo "arch = $CARCH" >>.PKGINFO + fi + + local it + for it in "${license[@]}"; do + echo "license = $it" >>.PKGINFO + done + for it in "${replaces[@]}"; do + echo "replaces = $it" >>.PKGINFO + done + for it in "${groups[@]}"; do + echo "group = $it" >>.PKGINFO + done + for it in "${depends[@]}"; do + echo "depend = $it" >>.PKGINFO + done + for it in "${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 + + # TODO: maybe remove this at some point + # warn if license array is not present or empty + if [ "$license" = "" ]; then + warning "Please add a license line to your ${_BUILD_SCRIPT}!" + plain "example for GPL'ed software: license=('GPL')." + fi + + local comp_files + + # check for an install script + if [ "$install" != "" ]; then + msg2 "Copying install script..." + cp "$startdir/$install" .INSTALL + comp_files="${comp_files} .INSTALL" + fi + + # do we have a changelog? + if [ -f "$startdir/ChangeLog" ]; then + msg2 "Copying package change log" + cp "$startdir/ChangeLog" .CHANGELOG + comp_files="${comp_files} .CHANGELOG" + fi + + + # tar it up + msg2 "Compressing package..." + + local pkg_file="$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}.${PKGEXT}" + comp_files="${comp_files} .PKGINFO .FILELIST" + + if ! tar -czf $pkg_file $comp_files *; then + error "Failed to create package file." + exit 1 # TODO: error code + fi +} + installpackage() { if [ "$INSTALL" = "1" -a "$SUDO" = "1" ]; then msg "Installing package with pacman -U..." @@ -979,92 +1071,7 @@ find -depth -type d -empty -delete; fi -# get some package meta info -builddate=$(LC_ALL= ; LANG= ; date -u "+%a %b %e %H:%M:%S %Y") -if [ "$PACKAGER" != "" ]; then - packager="$PACKAGER" -else - packager="Arch Linux (http://www.archlinux.org)" -fi -size=$(du -cb "$startdir/pkg" | tail -n 1 | awk '{print $1}') - -# build a filelist - do this first to keep meta files out of the list -msg "Generating .FILELIST file..." -cd "$startdir/pkg" -tar cvf /dev/null * | sort >.FILELIST - -# write the .PKGINFO file -msg "Generating .PKGINFO file..." -cd "$startdir/pkg" -echo "# Generated by makepkg $myver" >.PKGINFO -echo -n "# " >>.PKGINFO -date >>.PKGINFO -echo "pkgname = $pkgname" >>.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 -if [ "$CARCH" != "" ]; then - echo "arch = $CARCH" >>.PKGINFO -fi - -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 "${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 - -# TODO maybe remove this at some point -# warn if license array is not present or empty -if [ "$license" = "" ]; then - warning "Please add a license line to your $BUILDSCRIPT!" - plain "example for GPL'ed software: license=('GPL')." -fi - -# check for an install script -if [ "$install" != "" ]; then - msg "Copying install script..." - cp "$startdir/$install" "$startdir/pkg/.INSTALL" -fi - -# do we have a changelog? -have_changelog=0 -if [ -f "$startdir/ChangeLog" ]; then - msg "Copying package changelog" - cp "$startdir/ChangeLog" "$startdir/pkg/.CHANGELOG" - have_changelog=1 -fi - -# tar it up -msg "Compressing package..." -cd "$startdir/pkg" - -pkg_file="$PKGDEST/$pkgname-$pkgver-$pkgrel-${CARCH}.${PKGEXT}" -comp_files=".PKGINFO .FILELIST ${install:+.INSTALL}" -[ $have_changelog -eq 1 ] && comp_files=".CHANGELOG $comp_files" - -if ! tar czf $pkg_file $comp_files *; then - error "Failed to create package file." - exit 1 -fi +create_package cd "$startdir" if [ "$CLEANUP" = "1" ]; then ------------------------------------------------------------ revno: 10 committer: Andrew Fyfe <andrew@neptune-one.net> branch nick: feature_fake_install timestamp: Sat 2007-03-24 06:48:03 +0000 message: * Added support for fake_install() === modified file 'scripts/makepkg' --- old/scripts/makepkg 2007-03-24 06:14:55 +0000 +++ new/scripts/makepkg 2007-03-24 06:47:43 +0000 @@ -833,7 +833,12 @@ if [ "$REPKG" = "1" ]; then warning "Skipping build." else - run_build build + if [ "$(type -t fake_install)" != "function" ]; then + run_build build + else + run_build fake_install + fi + tidy_install fi @@ -1080,11 +1085,16 @@ warning "Skipping build." else run_build build + [ "$(type -t fake_install)" = "function" ] && run_build fake_install tidy_install fi create_package else + if [ "$REPKG" = "0" -a "$(type -t fake_install)" = "function" ]; then + run_build build + fi + msg "Entering fakeroot environment..." cd "$startdir" ------------------------------------------------------------ revno: 9 committer: Andrew Fyfe <andrew@neptune-one.net> branch nick: feature_fakeroot timestamp: Sat 2007-03-24 06:14:55 +0000 message: * renamed INFAKEROOT to _IN_FAKEROOT ------------------------------------------------------------ revno: 7 committer: Andrew Fyfe <andrew@neptune-one.net> branch nick: feature_fakeroot timestamp: Sat 2007-03-24 06:09:11 +0000 message: * reduced time in fakeroot to only build() tidy_install() and create_package() * removed fakeroot hack from... installpackage() removedeps() handledeps() * cleaned up... installpackage() removedeps() ------------------------------------------------------------ revno: 5 committer: Andrew Fyfe <andrew@neptune-one.net> branch nick: feature_fakeroot timestamp: Sat 2007-03-24 05:14:30 +0000 message: * added yn_question () - Asks the user a yes/no question. returns 0 for yes or y and 1 for anything else. * moved fakeroot/permissions check up. * added check for in proper use of '-F' option. * added warning about running makepkg as root. * moved sudo check to just after fakeroot/permissions check. === modified file 'scripts/makepkg' --- old/scripts/makepkg 2007-03-24 06:25:38 +0000 +++ new/scripts/makepkg 2007-03-24 06:14:32 +0000 @@ -49,16 +49,10 @@ RMDEPS=0 REPKG=0 _LOG_BUILD='n' +_IN_FAKEROOT='n' PACMAN_OPTS= -#determine if we are running with fakeroot -if [ "$1" = "-F" ]; then - INFAKEROOT=1 - shift -else - INFAKEROOT=0 -fi ### SUBROUTINES ### @@ -196,7 +190,7 @@ local depstrip="" local striplist="" local haveperm=0 - if [ \( "$EUID" = "0" -a "$INFAKEROOT" != "1" \) -o "$SUDO" = 1 ]; then + if [ "$EUID" = "0" -o "$SUDO" = 1 ]; then haveperm=1 fi @@ -209,21 +203,11 @@ if [ "$DEP_BIN" = "1" -a "$SUDO" = "1" ]; then # install missing deps from binary packages (using pacman -S and sudo) msg "Installing missing dependencies..." - if [ "$INFAKEROOT" = "1" ]; then - # kinda hacky, but we need to make pacman think that we're NOT - # in fakeroot so it will go ahead and install the dependencies. - FAKEROOTKEY2=$FAKEROOTKEY - unset FAKEROOTKEY - fi sudo pacman $PACMAN_OPTS -S $striplist if [ $? -eq 1 ]; then error "Pacman failed to install missing dependencies." exit 1 fi - if [ "$INFAKEROOT" = "1" ]; then - export FAKEROOTKEY=$FAKEROOTKEY2 - unset FAKEROOTKEY2 - fi elif [ "$DEP_BIN" = "1" ]; then # install missing deps from binary packages (using pacman -S) msg "Installing missing dependencies..." @@ -321,29 +305,23 @@ # fix flyspray bug #5923 removedeps() { + [ "$RMDEPS" = "0" ] && return + [ "$SUDO" = "0" -a $EUID -gt 0 ] && return # runtimedeps and buildtimedeps are set when resolving deps local deplist="$runtimedeps $buildtimedeps" - local depstrip="" local striplist="" + [ -z "$deplist" ] && return + + local dep for dep in $deplist; do - depstrip=$(echo $dep | sed 's|=.*$||' | sed 's|>.*$||' | sed 's|<.*$||') - striplist="$striplist $depstrip" + striplist="$striplist $(echo $dep | sed -e 's|=.*$||' -e 's|>.*$||' -e 's|<.*$||')" done - if [ "$RMDEPS" = "1" -a "$SUDO" = "1" -a -n "$deplist" ]; then - msg "Removing installed dependencies..." - if [ "$INFAKEROOT" = "1" ]; then - export FAKEROOTKEY2=$FAKEROOTKEY - unset FAKEROOTKEY - fi + msg "Removing installed dependencies..." + if [ "$SUDO" = "1" ]; then sudo pacman $PACMAN_OPTS -Rs $striplist - if [ "$INFAKEROOT" = "1" ]; then - export FAKEROOTKEY=$FAKEROOTKEY2 - unset FAKEROOTKEY2 - fi - elif [ "$RMDEPS" = "1" -a "$EUID" = "0" -a "$INFAKEROOT" != "1" -a -n "$deplist" ]; then - msg "Removing installed dependencies..." + else pacman $PACMAN_OPTS -Rs $striplist fi } @@ -564,24 +542,16 @@ } installpackage() { - if [ "$INSTALL" = "1" -a "$SUDO" = "1" ]; then - msg "Installing package with pacman -U..." - if [ "$INFAKEROOT" = "1" ]; then - FAKEROOTKEY2=$FAKEROOTKEY - unset FAKEROOTKEY - fi - sudo pacman $PACMAN_OPTS -U $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}.${PKGEXT} - local exitcode=$? - if [ "$INFAKEROOT" = "1" ]; then - export FAKEROOTKEY=$FAKEROOTKEY2 - unset FAKEROOTKEY2 - fi - exit $exitcode - elif [ "$INSTALL" = "1" -a "$EUID" = "0" -a "$INFAKEROOT" != "1" ]; then - msg "Installing package with pacman -U..." - pacman $PACMAN_OPTS -U $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}.${PKGEXT} - exit $? + [ "$INSTALL" = "0" ] && return + [ "$SUDO" = "0" -a $EUID -gt 0 ] && return + local ret=0 + msg "Installing package with pacman -U..." + if [ "$SUDO" = "1" ]; then + sudo pacman $PACMAN_OPTS -U "$PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}.${PKGEXT}" || ret=$? + else + pacman $PACMAN_OPTS -U $PKGDEST/${pkgname}-${pkgver}-${pkgrel}-${CARCH}.${PKGEXT} || ret=$? fi + exit $ret } usage() { @@ -673,7 +643,7 @@ exit 1 ;; -*) - while getopts "bcCdefghiLmop:rRsS-" opt; do + while getopts "bcCdefFghiLmop:rRsS-" opt; do case $opt in b) DEP_SRC=1 ;; c) CLEANUP=1 ;; @@ -681,6 +651,7 @@ d) NODEPS=1 ;; e) NOEXTRACT=1 ;; f) FORCE=1 ;; + F) _IN_FAKEROOT='y';; g) _GENERATE_CHKSUMS='y';; h) usage @@ -713,12 +684,6 @@ shift done -# check for sudo -if [ "$SUDO" = "1" -a ! "$(type -p sudo)" ]; then - error "Cannot find the sudo binary! Is sudo installed?" - exit 1 -fi - if [ "$CLEANCACHE" = "1" ]; then #fix flyspray feature request #5223 if [ -n "$SRCDEST" -a "$SRCDEST" != "$startdir" ]; then @@ -749,6 +714,60 @@ fi fi +if [ $_IN_FAKEROOT = 'n' ]; then + if [ $EUID -eq 0 ]; then + # Warn those who like to live dangerously. + warning "Running makepkg as root is a \033[1;31mBAD\033[1;37m idea!" + plain "" + plain "Running makepkg as root can result in permanent, catastropic damage to " + plain "your system." + plain "" + if ! yn_question "Are you sure you want to continue? [N/y]"; then + error "Aborting..." + exit 1 # $E_USER_ABORT + fi + elif [ $(check_buildenv fakeroot) = 'y' ]; then + if [ ! $(type -p fakeroot) ]; then + warning "Fakeroot is not installed. Building as an unprivileged user" + plain "will result in non-root ownership of the packaged files. Install" + plain "the fakeroot package to correctly build as a non-root user." + plain "" + if ! yn_question "Are you sure you want to continue? [N/y]"; then + error "Aborting..." + exit 1 # $E_USER_ABORT + fi + fi + else + warning "Running makepkg as an unprivileged user will result in non-root" + plain "ownership of the packaged files. Try using the fakeroot environment by" + plain "placing 'fakeroot' in the BUILDENV array in /etc/makepkg.conf" + plain "" + if ! yn_question "Are you sure you want to continue? [N/y]"; then + error "Aborting..." + exit 1 # $E_USER_ABORT + fi + fi +else + if [ -z "$FAKEROOTKEY" ]; then + error "Do not use the '-F' option. This option is only for use by makepkg." + exit 1 # TODO: error code + fi +fi + +if [ "$SUDO" = "1" ]; then + if [ ! "$(type -p sudo)" ]; then + error "Can not find the sudo binary! Is sudo installed?" + exit 1 # $E_MISSING_PROGRAM + fi +elif [ $EUID -gt 0 -a "$INSTALL" = "1" ]; then + # TODO: Should this be an error and exit? + warning "makepkg will not be able to install this package as an unprivilaged user." + plain "Use the --usesudo (or -s) option to install this package after it has been" + plain "build." + plain "" + sleep 3 +fi + unset pkgname pkgver pkgrel pkgdesc url license groups provides md5sums force unset replaces depends conflicts backup source install build makedepends unset options noextract @@ -808,29 +827,20 @@ fi fi -# Enter the fakeroot environment if necessary. This will call the makepkg -# script again as the fake root user. We detect this by passing a sentinel -# option (-F) to makepkg. -if [ "$EUID" != "0" ]; then - if [ "$(check_buildenv fakeroot)" = "y" ]; then - if [ $(type -p fakeroot) ]; then - msg "Entering fakeroot environment" - fakeroot -- $0 -F $ARGLIST - exit $? - else - warning "Fakeroot is not installed. Building as an unprivileged user" - plain "will result in non-root ownership of the packaged files. Install" - plain "the fakeroot package to correctly build as a non-root user." - plain "" - sleep 1 - fi +# Run the bear minimum in fakeroot +# fix flyspray bug 6208 -- using makepkg with fakeroot gives an error +if [ $_IN_FAKEROOT = 'y' ]; then + if [ "$REPKG" = "1" ]; then + warning "Skipping build." else - warning "Running makepkg as an unprivileged user will result in non-root" - plain "ownership of the packaged files. Try using the fakeroot environment" - plain "by placing 'fakeroot' in the BUILDENV array in makepkg.conf." - plain "" - sleep 1 + run_build build + tidy_install fi + + create_package + + msg "Leaveing fakeroot environment." + exit 0 # $E_OK fi msg "Making package: $pkgname $pkgver-$pkgrel ($(date))" @@ -1057,23 +1067,35 @@ if [ "$NOBUILD" = "1" ]; then msg "Sources are ready." exit 0 -elif [ "$REPKG" = "1" ]; then - warning "Skipping build" else # check for existing pkg directory - if [ -d "$startdir/pkg" ]; then + if [ -d "$startdir/pkg" -a "$REPKG" = "0" ]; then msg "Removing existing pkg/ directory..." rm -rf "$startdir/pkg" fi mkdir -p "$startdir/pkg" - run_build build + if [ $EUID -eq 0 ]; then + if [ "$REPKG" = "1" ]; then + warning "Skipping build." + else + run_build build + tidy_install + fi + + create_package + else + msg "Entering fakeroot environment..." + cd "$startdir" + + ret=0 + fakeroot -- $0 -F $ARGLIST || ret=$? + [ $ret -ne 0 ] && exit $ret + + unset ret + fi fi -tidy_install - -create_package - cd "$startdir" if [ "$CLEANUP" = "1" ]; then msg "Cleaning up..." ------------------------------------------------------------ revno: 3 committer: Andrew Fyfe <andrew@neptune-one.net> branch nick: feature_run_build timestamp: Sat 2007-03-24 05:37:34 +0000 message: * moved the build commands to run_build (). * cleaned up run_build (). * renamed LOGGING to _LOG_BUILD * simplified the 'set -e' check. Idealy the whole script should run with 'set -e' enabled. === modified file 'scripts/makepkg' --- old/scripts/makepkg 2007-03-24 03:49:27 +0000 +++ new/scripts/makepkg 2007-03-24 05:37:22 +0000 @@ -48,7 +48,7 @@ NOEXTRACT=0 RMDEPS=0 REPKG=0 -LOGGING=0 +_LOG_BUILD='n' PACMAN_OPTS= @@ -348,6 +348,71 @@ fi } +run_build () { + if [ "$(type -t $1)" != "function" ]; then + error "Unknown function '$1'." + error "Aborting..." + exit 1 # TODO: error code + fi + + # use distcc if it is requested (check buildenv and PKGBUILD opts) + if [ $(check_buildenv distcc) = 'y' -a $(check_option distcc) != 'n' ]; then + [ -d /usr/lib/distcc/bin ] && export PATH="/usr/lib/distcc/bin:$PATH" + elif [ $(check_option distcc) = 'n' ]; then + # if it is not wanted, clear the makeflags too + export MAKEFLAGS="" + fi + + # use ccache if it is requested (check buildenv and PKGBUILD opts) + if [ $(check_buildenv ccache) = 'y' -a $(check_option distcc) != 'n' ]; then + [ -d /usr/lib/ccache/bin ] && export PATH="/usr/lib/ccache/bin:$PATH" + fi + + # clear user-specified makeflags if requested + if [ $(check_option makeflags) = 'n' ]; then + export MAKEFLAGS="" + fi + + msg "Running '$1'..." + cd "$startdir/src" + + # Some locales can break builds. + local _LC_ALL="$LC_ALL" ; LC_ALL='C' + local _LANG="$LANG" ; LANG='C' + umask 0022 + + local ret=0 + if [ $_LOG_BUILD = 'y' ]; then + local build_log="${startdir}/${pkgname}-${pkgver}-${pkgrel}-${CARCH}-${1}.log" + if [ -f "$build_log" ]; then + local i=1 + while true; do + if [ -f "${build_log}.$i" ]; then + i=$(($i+1)) + else + break + fi + done + mv "$build_log" "${build_log}.$i" + fi + + msg2 "'$1' will be logged to $build_log" + (set -e; $1 2>&1) | tee "$build_log" || ret=${PIPESTATUS[0]} + else + (set -e; $1 2>&1) || ret=$? + fi + + # restore locales + export LC_ALL="$_LC_ALL" + export LANG="$_LANG" + + if [ $ret -gt 0 ]; then + error "'$1' FAILED. Aborting..." + removedeps + exit 2 # TODO: error code + fi +} + installpackage() { if [ "$INSTALL" = "1" -a "$SUDO" = "1" ]; then msg "Installing package with pacman -U..." @@ -448,7 +513,7 @@ --geninteg) GENINTEG=1 ;; --rmdeps) RMDEPS=1 ;; --repackage) REPKG=1 ;; - --log) LOGGING=1 ;; + --log) _LOG_BUILD='y';; --help) usage exit 0 @@ -472,7 +537,7 @@ exit 0 ;; i) INSTALL=1 ;; - L) LOGGING=1 ;; + L) _LOG_BUILD='y';; m) USE_COLOR="n" ;; o) NOBUILD=1 ;; p) BUILDSCRIPT=$OPTARG ;; @@ -854,70 +919,7 @@ fi mkdir -p "$startdir/pkg" - # use distcc if it is requested (check buildenv and PKGBUILD opts) - if [ "$(check_buildenv distcc)" = "y" -a "$(check_option distcc)" != "n" ]; then - [ -d /usr/lib/distcc/bin ] && export PATH=/usr/lib/distcc/bin:$PATH - elif [ "$(check_option distcc)" = "n" ]; then - # if it is not wanted, clear the makeflags too - export MAKEFLAGS="" - fi - - # use ccache if it is requested (check buildenv and PKGBUILD opts) - if [ "$(check_buildenv ccache)" = "y" -a "$(check_option ccache)" != "n" ]; then - [ -d /usr/lib/ccache/bin ] && export PATH=/usr/lib/ccache/bin:$PATH - fi - - # clear user-specified makeflags if requested - if [ "$(check_option makeflags)" = "n" ]; then - export MAKEFLAGS="" - fi - - # build - msg "Starting build()..." - - # some applications (eg, blackbox) will not build with some languages - unset LC_ALL LANG - umask 0022 - - #check for "exit on syntax error" shell option - echo $SHELLOPTS | grep errexit 2>&1 >/dev/null - set_e=$? - - if [ "$LOGGING" = "1" ]; then - BUILDLOG="${startdir}/${pkgname}-${pkgver}-${pkgrel}-${CARCH}.log" - if [ -f "$BUILDLOG" ]; then - i=1 - while true; do - if [ -f "$BUILDLOG.$i" ]; then - i=$(($i +1)) - else - break - fi - done - mv "$BUILDLOG" "$BUILDLOG.$i" - fi - - #use 'errexit' to bail on syntax error - [ $set_e -eq 1 ] && set -e - build 2>&1 | tee "$BUILDLOG" - [ $set_e -eq 1 ] && set +e - - if [ ${PIPESTATUS[0]} -gt 0 ]; then - error "Build Failed. Aborting..." - removedeps - exit 2 - fi - else - #use 'errexit' to bail on syntax error - [ $set_e -eq 1 ] && set -e - build 2>&1 - [ $set_e -eq 1 ] && set +e - if [ $? -gt 0 ]; then - error "Build Failed. Aborting..." - removedeps - exit 2 - fi - fi + run_build build fi if [ "$(check_option docs)" = "n" ]; then ------------------------------------------------------------ revno: 2 committer: Andrew Fyfe <andrew@neptune-one.net> branch nick: feature_tidy_install timestamp: Sat 2007-03-24 03:53:42 +0000 message: * moved the following into tidy_install () - Remove info/doc files - Move usr/share/man files to usr/man - Compress man pages - Strip binaries and libraries - Remove libtool files - Remove empty directories * cleaned up tidy_install () * added 'LC_ALL=C LANG=C' to find commands for stripping binaries and libraries. Fixes issues with greps not working on different locales. === modified file 'scripts/makepkg' --- old/scripts/makepkg 2007-03-24 03:49:27 +0000 +++ new/scripts/makepkg 2007-03-24 03:52:44 +0000 @@ -348,6 +348,64 @@ fi } +tidy_install () { + cd "$startdir/pkg" + msg "Tidying install..." + + if [ $(check_option docs) = 'n' ]; then + msg2 "Removing info/doc files..." + #fix flyspray bug #5021 + rm -rf ${DOC_DIRS[@]} + fi + + if [ -d usr/share/man ]; then + msg2 "Moving usr/share/man files to usr/man..." + mkdir -p usr/man + cp -a usr/share/man/* usr/man/ + rm -rf usr/share/man + fi + + msg2 "Compressing man pages..." + local manpage ext file link + find {usr{,/local},opt/*}/man -type f 2>/dev/null | while read manpage ; do + ext="${manpage##*.}" + file="${manpage##*/}" + if [ "$ext" != "gz" -a "$ext" != "bz2" ]; then + # update symlinks to this manpage + find {usr{,/local},opt/*}/man -lname "$file" 2>/dev/null | while read link; do + rm -f "$link" + ln -sf "${file}.gz" "${link}.gz" + done + # compress the original + gzip -9 "$manpage" + fi + done + + if [ $(check_option strip) = 'y' ]; then + msg2 "Stripping debugging symbols from libraries..." + LC_ALL=C LANG=C \ + find {.,usr{,/local},opt/*}/lib -type f -not -name "*.dll" -not -name "*.exe" \ + -exec /usr/bin/strip --strip-debug '{}' ';' 2>&1 \ + | grep -v "No such file" | grep -v "format not recognized" + + msg "Stripping symbols from binaries..." + LC_ALL=C LANG=C \ + find {.,usr{,/local}.opt/*}/{bin,sbin} -type f -not -name "*.dll" -not -name "*.exe" \ + -exec /usr/bin/strip --strip-debug '{}' ';' 2>&1 \ + | grep -v "No such file" | grep -v "format not recognized" + fi + + if [ $(check_option libtool) = 'n' ]; then + msg2 "Removing libtool .la files..." + find -type f -name "*.la" -exec rm -f -- '{}' ';' + fi + + if [ $(check_option emptydirs) = 'n' ]; then + msg2 "Removing empty directories..." + find -depth -type d -empty -delete + fi +} + installpackage() { if [ "$INSTALL" = "1" -a "$SUDO" = "1" ]; then msg "Installing package with pacman -U..." @@ -920,64 +978,7 @@ fi fi -if [ "$(check_option docs)" = "n" ]; then - # remove info/doc files - msg "Removing info/doc files..." - cd "$startdir/pkg" - #fix flyspray bug #5021 - rm -rf ${DOC_DIRS[@]} -fi - -# move /usr/share/man files to /usr/man -if [ -d $startdir/pkg/usr/share/man ]; then - cd "$startdir" - mkdir -p pkg/usr/man - cp -a pkg/usr/share/man/* pkg/usr/man/ - rm -rf pkg/usr/share/man -fi - -# compress man pages -msg "Compressing man pages..." -find "$startdir"/pkg/{usr{,/local},opt/*}/man -type f 2>/dev/null | while read i ; do - ext="${i##*.}" - fn="${i##*/}" - if [ "$ext" != "gz" -a "$ext" != "bz2" ]; then - # update symlinks to this manpage - find "$startdir"/pkg/{usr{,/local},opt/*}/man -lname "$fn" 2> /dev/null | while read ln ; do - rm -f "$ln" - ln -sf "${fn}.gz" "${ln}.gz" - done - # compress the original - gzip -9 "$i" - fi -done - -cd "$startdir" - -# strip binaries -if [ "$(check_option strip)" = "y" ]; then - msg "Stripping debugging symbols from libraries..." - find pkg/{,usr,usr/local,opt/*}/lib -type f -not -name "*.dll" -not -name "*.exe" \ - -exec /usr/bin/strip --strip-debug '{}' \; 2>&1 \ - | grep -v "No such file" | grep -v "format not recognized" - msg "Stripping symbols from binaries..." - find pkg/{,usr,usr/local,opt/*}/{bin,sbin} -type f -not -name "*.dll" -not -name "*.exe" \ - -exec /usr/bin/strip '{}' \; 2>&1 \ - | grep -v "No such file" | grep -v "format not recognized" -fi - -# remove libtool (.la) files -if [ "$(check_option libtool)" = "n" ]; then - msg "Removing libtool .la files..." - find pkg -type f -name "*.la" -exec rm -f -- '{}' \; -fi - -# remove empty directories -if [ "$(check_option emptydirs)" = "n" ]; then - msg "Removing empty directories..." - cd "$startdir/pkg" - find -depth -type d -empty -delete; -fi +tidy_install # get some package meta info builddate=$(LC_ALL= ; LANG= ; date -u "+%a %b %e %H:%M:%S %Y")
participants (4)
-
Aaron Griffin
-
Andrew Fyfe
-
Dan McGee
-
Roman Kyrylych