#!/bin/bash -euE # libremakepkg # Copyright 2010-2011 Nicolás Reynolds # Copyright 2011 Joshua Ismael Haase Hernández # Copyright 2012-2013 Luke Shumaker # # This file is part of Parabola. # # Parabola 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 3 of the License, or # (at your option) any later version. # # Parabola 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 Parabola. If not, see . . $(librelib conf) . $(librelib messages) . $(librelib chroot/makechrootpkg.sh) set -o pipefail shopt -s nullglob umask 0022 # Global variables: readonly INCHROOT=$([[ -f /.arch-chroot ]] && echo true || echo false) NONET=true # can be changed with the -N flag # {SRC,LOG,PKG}DEST set at runtime by makepkg.conf # MAKEFLAGS, PACKAGER set at runtime by makepkg.conf # LIBREUSER, LIBREHOME are set by conf.sh librechroot_flags=() # Hooks ######################################################################## hook_pre_build=(:) hook_post_build=(:) hook_check_pkgbuild=(:) hook_check_pkg=(:) . $(librelib chroot/hooks-chcleanup.sh) . $(librelib chroot/hooks-check.sh) . $(librelib chroot/hooks-distcc.sh) # Boring/mundane functions ##################################################### indent() { sed 's/^/ | /' } # Usage: exit_copy $copydir $src_owner # End immediately, but copy log files out exit_copy() { local copydir=$1 local src_owner=$2 if ! $INCHROOT; then msg "Copying log and package files out of the chroot..." move_products "$copydir" "$src_owner" fi } # Usage; run_hook $hookname $args... run_hook() { local hookname=$1; shift local hookvar="hook_${hookname}[@]" local fails=() for hook in "${!hookvar}"; do "$hook" "$@" || fails+=("$hook") done |& indent if [[ ${#fails[@]} -gt 0 ]]; then error "Failure(s) in %s: %s" "$hookname" "${fails[*]}" return 1 else return 0 fi } # Usage: add_to_local_repo $copydir $pkgfiles... add_to_local_repo() { local copydir=$1; shift mkdir -p "$copydir/repo" local pkgfile for pkgfile in "$@"; do cp "$pkgfile" "$copydir/repo" pushd "$copydir/repo" >/dev/null repo-add repo.db.tar.gz "${pkgfile##*/}" popd >/dev/null done } hook_post_build+=('cleanup') cleanup() { local copydir=$1 rm -f -- "$copydir"/chroot{prepare,build} } build() ( local copydir=$1; shift local repack=$1; shift local netflag='' local run=() if $INCHROOT; then ! $NONET || netflag='-N' run=(unshare) else ! $NONET || netflag='-n' run=(librechroot "${librechroot_flags[@]}" run) fi prepare_chroot "$copydir" "$LIBREHOME" "$repack" false "${run[@]}" /chrootprepare "$@" |& indent run_hook pre_build "$copydir" trap "run_hook post_build '$copydir'" EXIT "${run[@]}" /chrootbuild "$@" |& indent ) # The main program ############################################################# usage() { print "Usage: %s [options] [-- makepkg args]" "${0##*/}" print 'This program will build your package.' echo prose 'If run from outside of a chroot, command will make the following configuration changes in the chroot:' bullet 'whatever changes `librechroot` makes.' bullet 'set `PKGDEST` and `SRCDEST` in `/etc/makepkg.conf`' bullet 'set `PACKAGER` in `/etc/makepkg.conf` to reflect the value outside of the chroot.' bullet '(maybe) delete `/build/.makepkg.conf`' bullet '(maybe) delete `/build/.ssh/config`' prose 'If run from inside of a chroot, this command will:' bullet '(maybe) delete `~/.makepkg.conf`' bullet '(maybe) delete `~/.ssh/config`' prose 'The above "maybe"s happen as part of the workarounds to make distcc work in a network-less environment. They will happen if both `socat` and `distcc` are installed in the chroot.' echo prose 'The `-n` and `-l` options behave identically to librechroot, see the documentation there.' echo print 'Options:' flag "-n <$(_ CHROOT)>" 'Name of the chroot to use' flag "-l <$(_ COPY)>" 'Name of, or absolute path to, the chroot copy to use' flag '-N' "Don't disable networking during build() and package(). PLEASE don't use this unless you have a special reason, its use is a violation of Parabola policy." flag '-R' 'Repackage contents of the package without rebuilding' flag '-h' 'Show this message' } # Convenience method for use in option parsing err_chflag() { local flag=$1 error 'The -%s flag does not make sense inside of a chroot' "$flag" return 1 } main() { # Initial variable values ############################################## local copy=$([[ $LIBREUSER == root ]] && echo copy || echo "$LIBREUSER") local makepkg_args=(-s --noconfirm -L) local repack=false local chroot='' # Parse command line options ########################################### while getopts 'n:l:NRh' flag ; do case "${flag}" in n) if $INCHROOT; then err_chflag "$flag"; else chroot=$OPTARG; fi;; l) if $INCHROOT; then err_chflag "$flag"; else copy=$OPTARG; fi;; N) NONET=false;; R) repack=true; makepkg_args+=(-R);; h) usage; return 0;; *) usage >&2; return 1;; esac done shift $(($OPTIND - 1)) # Pass all arguments after -- right to makepkg makepkg_args+=("$@") # Resolve the chroot path ############################################## local copydir if $INCHROOT; then copydir='/' else load_files chroot check_vars chroot CHROOTDIR CHROOT [[ -z ${chroot} ]] || CHROOT=$chroot if [[ ${copy:0:1} = / ]]; then copydir=$copy else copydir="${CHROOTDIR}/${CHROOT}/${copy}" fi unset CHROOTDIR CHROOTEXTRAPKG fi unset chroot # Quick sanity check ################################################### if (( EUID )); then error "This program must be run as root" exit 1 fi if [[ ! -f PKGBUILD ]]; then # This is the message used by makepkg error "PKGBUILD does not exist." exit 1 fi # Load makepkg configuration ########################################### # Note that all of these are globals SRCDEST="$(get_conf_makepkg SRCDEST "$PWD")" PKGDEST="$(get_conf_makepkg PKGDEST "$PWD")" LOGDEST="$(get_conf_makepkg LOGDEST "$PWD")" mkdir -p "$SRCDEST" "$PKGDEST" "$LOGDEST" MAKEFLAGS="$(get_conf_makepkg MAKEFLAGS '')" PACKAGER="$(get_conf_makepkg PACKAGER '')" librechroot_flags=( -r "$PWD:/startdir_host" -r "$SRCDEST:/srcdest_host" -n "$CHROOT" -l "$copy" ) # OK, we are starting now ############################################## if $INCHROOT; then lock 9 "/build/.lock" \ "Waiting for existing lock on build directory to be released" else # Obtain a lock on the chroot lock 9 "$copydir.lock" \ "Waiting for existing lock on chroot copy to be released: [%s]" "$copy" # Create the chroot if it does not exist msg 'Initializing the chroot...' librechroot "${librechroot_flags[@]}" make |& indent fi # Set target CARCH # note that we waited until after locking/creating the chroot to do this export CARCH="$(MAKEPKG_CONF=$copydir/etc/makepkg.conf get_conf_makepkg CARCH)" # Pre-build msg 'Starting pre-build activities...' run_hook check_pkgbuild msg 'Downloading sources...' download_sources "$copydir" "$LIBREUSER" |& indent # Build msg 'Starting to build the package...' trap "exit_copy '$copydir' '$LIBREUSER'" EXIT build "$copydir" "$repack" "${makepkg_args[@]}" # Post-build msg 'Starting post-build activities...' run_hook check_pkg add_to_local_repo "$copydir" "$copydir"/pkgdest/*.pkg.tar* |& indent } main "$@"