diff options
Diffstat (limited to 'src/chroot-tools/libremakepkg')
-rwxr-xr-x | src/chroot-tools/libremakepkg | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/src/chroot-tools/libremakepkg b/src/chroot-tools/libremakepkg new file mode 100755 index 0000000..a226e38 --- /dev/null +++ b/src/chroot-tools/libremakepkg @@ -0,0 +1,289 @@ +#!/usr/bin/env bash +set -euE +# libremakepkg + +# Copyright (C) 2010-2012 Nicolás Reynolds <fauno@parabola.nu> +# Copyright (C) 2010-2012 Joshua Ismael Haase Hernández (xihh) <hahj87@gmail.com> +# Copyright (C) 2012 Michał Masłowski <mtjm@mtjm.eu> +# Copyright (C) 2012-2015 Luke Shumaker <lukeshu@sbcglobal.net> +# +# License: GNU GPLv2+ +# +# 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 2 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 <http://www.gnu.org/licenses/>. + +. "$(librelib conf)" +. "$(librelib messages)" +. "$(librelib chroot/makechrootpkg.sh)" + +set -o pipefail +shopt -s nullglob +umask 0022 + +# Global variables: +readonly _indent="$(librelib chroot/indent)" +readonly INCHROOT=$([[ -f /.arch-chroot ]] && echo true || echo false) +NONET=true # can be changed with the -N flag +# {PKG,SRC,SRCPKG,LOG}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() { + "$_indent" ' | ' +} + +# 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 + local repack=$2 + local makepkg_args=("${@:3}") + + local run_ynet=() + local run_nnet=() + if $INCHROOT; then + run_ynet=(unshare) + run_nnet=(unshare -n) + else + run_ynet=(librechroot "${librechroot_flags[@]}" run) + run_nnet=(librechroot "${librechroot_flags[@]}" -N run) + fi + $NONET || run_nnet=("${run_ynet[@]}") + + prepare_chroot "$copydir" "$LIBREHOME" "$repack" false + "${run_ynet[@]}" /chrootprepare "${makepkg_args[@]}" |& indent + run_hook pre_build "$copydir" + trap "run_hook post_build $(printf '%q' "$copydir")" EXIT + "${run_nnet[@]}" /chrootbuild "${makepkg_args[@]}" |& indent +) + +# The main program ############################################################# + +usage() { + print "Usage: %s [options]" "${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 `{PKG,SRC,SRCPKG,LOG}DEST` 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:' + print ' %s options:' librechroot + flag "-n <$(_ CHROOT)>" 'Name of the chroot to use' + flag "-l <$(_ COPY)>" 'Name of, or absolute path to, the chroot copy to use' + flag "-w <$(_ 'PATH[:PATH]')>" 'Bind mount a file or directory, read/write' + flag "-r <$(_ 'PATH[:PATH]')>" 'Bind mount a file or directory, read-only' + print ' %s options:' libremakepkg + 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:w:r: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;; + w|r) if $INCHROOT; then err_chflag "$flag"; else + librechroot_flags+=(-$flag "$OPTARG"); fi;; + N) NONET=false;; + R) repack=true; makepkg_args+=(-R);; + h) usage; return 0;; + *) usage >&2; return 1;; + esac + done + shift $(($OPTIND - 1)) + if [[ $# != 0 ]]; then + error 'Extra arguments: %s' "$*" + return 1 + fi + + # 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 + + # Load makepkg configuration ########################################### + # Note that all of these are globals + PKGDEST="$(get_var makepkg PKGDEST "$PWD")" + SRCDEST="$(get_var makepkg SRCDEST "$PWD")" + SRCPKGDEST="$(get_var makepkg SRCPKGDEST "$PWD")" + LOGDEST="$(get_var makepkg LOGDEST "$PWD")" + MAKEFLAGS="$(get_var makepkg MAKEFLAGS '')" + PACKAGER="$(get_var makepkg PACKAGER '')" + + # 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 + + # Make sure that the various *DEST directories exist + mkdir -p -- "$PKGDEST" "$SRCDEST" "$SRCPKGDEST" "$LOGDEST" + + # OK, we are starting now ############################################## + + if $INCHROOT; then + lock 9 "/build/.lock" \ + "Waiting for existing lock on build directory to be released" + else + librechroot_flags+=( + -r "$PWD:/startdir_host" + -r "$SRCDEST:/srcdest_host" + -n "$CHROOT" + -l "$copy" + ) + + # 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_var 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 "$@" |