summaryrefslogtreecommitdiff
path: root/src/chroot-tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/chroot-tools')
-rw-r--r--src/chroot-tools/Makefile3
-rwxr-xr-xsrc/chroot-tools/chcleanup76
-rw-r--r--src/chroot-tools/chroot.conf13
-rwxr-xr-xsrc/chroot-tools/librechroot230
-rwxr-xr-xsrc/chroot-tools/libremakepkg311
5 files changed, 633 insertions, 0 deletions
diff --git a/src/chroot-tools/Makefile b/src/chroot-tools/Makefile
new file mode 100644
index 0000000..3ae95ea
--- /dev/null
+++ b/src/chroot-tools/Makefile
@@ -0,0 +1,3 @@
+libre_execdir=$(sbindir)
+libre_datadir=$(sysconfdir)/libretools.d
+include ../../common.mk
diff --git a/src/chroot-tools/chcleanup b/src/chroot-tools/chcleanup
new file mode 100755
index 0000000..f957d3b
--- /dev/null
+++ b/src/chroot-tools/chcleanup
@@ -0,0 +1,76 @@
+#!/bin/bash -eE
+# (c) Nicolás Reynolds <fauno@parabola.nu>
+# Released under GPLv3
+#
+# Performs chroot cleanup smartly, it only removes the unneeded packages or
+# leaves you with a cleansystem
+#
+# See: HOOKPREBUILD
+
+DRYRUN=${DRYRUN:-false}
+
+################################################################################
+# Define these here to avoid having dependencies on outside files
+
+msg() {
+ local mesg=$1; shift
+ printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+}
+
+msg2() {
+ local mesg=$1; shift
+ printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+}
+
+error() {
+ local mesg=$1; shift
+ printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+}
+
+################################################################################
+
+if [[ ! -f /.arch-chroot ]] && ! ${DRYRUN}; then
+ error "(chcleanup): Must be run inside of a chroot"
+ exit 1
+fi
+
+source /etc/libretools.d/chroot.conf
+# If we're running makepkg
+if [ -f PKGBUILD ]; then
+ source PKGBUILD
+ CHROOTEXTRAPKG+=("${depends[@]}"
+ "${makedepends[@]}"
+ "${checkdepends[@]}")
+fi
+
+msg "Cleaning chroot..."
+
+TEMPDIR="$(mktemp --tmpdir -d $(basename $0).XXXXX)"
+cp -a /var/lib/pacman/sync "${TEMPDIR}/"
+cleanup_log="${TEMPDIR}"/libretools-cleanup.log
+
+# Get the full list of packages needed by dependencies, including the base system
+pacman -b "${TEMPDIR}" \
+ -Sp --print-format "%n" \
+ base-devel "${CHROOTEXTRAPKG[@]}" \
+ >"${cleanup_log}"
+
+# Diff installed packages against a clean chroot then remove leftovers
+packages=($(comm -23 <(pacman -Qq | sort -u) \
+ <(sort -u "${cleanup_log}")))
+
+RET=0
+if [[ ${#packages[@]} != 0 ]]; then
+ msg2 "Removing %d packages" ${#packages[@]}
+
+ if ${DRYRUN}; then
+ echo "${packages[@]}"
+ else
+ # Only remove leftovers, -Rcs removes too much
+ pacman --noconfirm -Rn "${packages[@]}" || RET=$?
+ fi
+fi
+# Cleanup
+rm -rf "${TEMPDIR}"
+
+exit $RET
diff --git a/src/chroot-tools/chroot.conf b/src/chroot-tools/chroot.conf
new file mode 100644
index 0000000..a161a61
--- /dev/null
+++ b/src/chroot-tools/chroot.conf
@@ -0,0 +1,13 @@
+# The full path to the chroot is
+# $CHROOTDIR/$CHROOT/$CHROOTCOPY
+# where $CHROOTCOPY is set at runtime, either
+# - based on the username
+# - set with the `-l COPY` flag
+# The purpose of having a $CHROOT setting is that multiple clones of the same
+# base $CHROOT can quickly and easily be created.
+CHROOTDIR=/var/lib/archbuild
+CHROOT=default
+
+# Extra packages to have installed on the chroot.
+# This is in addition to CHROOTPKG=(base-devel)
+CHROOTEXTRAPKG=(distcc ccache tsocks libretools)
diff --git a/src/chroot-tools/librechroot b/src/chroot-tools/librechroot
new file mode 100755
index 0000000..45aec10
--- /dev/null
+++ b/src/chroot-tools/librechroot
@@ -0,0 +1,230 @@
+#!/bin/bash -euE
+# librechroot
+
+# Copyright 2010 Nicolás Reynolds
+# Copyright 2011 Joshua Haase
+# 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 <http://www.gnu.org/licenses/>.
+
+. /usr/share/libretools/conf.sh
+load_conf_libretools_chroot
+
+. libremessages
+. /usr/share/devtools/makechrootpkg.sh
+
+# Because the makechrootpkg.sh library functions don't work with -euE
+normshell() (
+ set +euE
+ "$@"
+)
+
+cmd=${0##*/}
+usage() {
+ echo "Usage: $cmd [OPTIONS] COMMAND [ARGS...]"
+ echo 'Interacts with an archroot (arch chroot).'
+ echo ''
+ echo 'There may be multiple chroots; they are stored in $CHROOTDIR.'
+ echo ''
+ echo 'Each chroot is named; the default is configured with $CHROOT.'
+ echo ''
+ echo "Each named chroot has a master clean copy (named 'root'), and any"
+ echo 'number of other named copies; the copy used by default is the'
+ echo "current username (or \$SUDO_USER, or 'copy' if root)."
+ echo ''
+ echo 'The full path to the chroot copy is "$CHROOTDIR/$CHROOT/$COPY",'
+ echo 'Unless the copy name is manually specified as an absolute path,'
+ echo 'in which case, that path is used.'
+ echo ''
+ echo 'The current settings for the above varibles are:'
+ echo " CHROOTDIR : $CHROOTDIR"
+ echo " CHROOT : $CHROOT"
+ echo " COPY : $COPY"
+ echo " root path : $rootdir"
+ echo " copy path : $copydir"
+ echo ''
+ echo 'If the chroot, or copy does not exist, it will be created'
+ echo 'automatically.'
+ echo ''
+ echo 'This command will make the following configuration changes in'
+ echo 'the chroot:'
+ echo " - overwrite \`/etc/libretools.d/chroot.conf'"
+ echo " - overwrite \`/etc/pacman.d/mirrorlist'"
+ echo " - set \`CacheDir' in \`/etc/pacman.conf'"
+ echo ''
+ echo 'Creating a copy, deleting a copy, or syncing a copy can be fairly'
+ echo 'slow; but are very fast if $CHROOTDIR is on a btrfs partition.'
+ echo ''
+ echo 'Options:'
+ echo ' -n <CHROOT> Name of the chroot to use'
+ echo ' -l <COPY> Name of, or absolute path to, the copy to use'
+ echo ' -N Disable networking in the chroot'
+ echo ' -C <file> Location of pacman config file'
+ echo ' -M <file> Location of makepkg config file'
+ echo ''
+ echo 'Commands:'
+ echo ' Create/copy/delete:'
+ echo ' noop|make Do not do anything, but still creates the'
+ echo ' chroot copy if it does not exist'
+ echo " sync Sync the copy with the clean ('root') copy"
+ echo " delete delete the chroot copy"
+ echo ' Dealing with packages:'
+ echo ' install-file FILES... Like `pacman -U FILES...`'
+ echo ' install-name NAMES... Like `pacman -S NAMES...`'
+ echo ' update Like `pacman -Syu`'
+ echo ' clean-pkgs Remove all "exta" packages from the chroot copy'
+ echo ' Other:'
+ echo ' run CMD... Run CMD in the chroot copy'
+ echo ' enter Enter an interactive shell in the chroot copy'
+ echo ' clean-repo Clean /repo in the chroot copy'
+ echo ' help Show this message' # usage
+}
+
+# Globals: $CHROOTDIR, $CHROOT, $COPY, $rootdir and $copydir
+main() {
+ COPY=$LIBREUSER
+ [[ $COPY != root ]] || COPY=copy
+
+ # defaults
+ rootdir="${CHROOTDIR}/${CHROOT}/root"
+ copydir="${CHROOTDIR}/${CHROOT}/${COPY}"
+
+ local mode=enter
+ local archroot_args=()
+ while getopts 'n:l:NC:M:' arg; do
+ case $arg in
+ n) CHROOT=$OPTARG;;
+ l) COPY=$OPTARG;;
+ N)
+ # We do this so that it carries through to
+ # chroot_* functions
+ archroot() {
+ $(which archroot) -N "$@"
+ }
+ ;;
+ C|M) archroot_args+=(-$arg "$OPTARG");;
+ *) usage; return 1;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+ if [[ $# < 1 ]]; then
+ error "Must specify a command"
+ usage
+ return 1
+ fi
+ mode=$1
+ shift
+
+ rootdir="${CHROOTDIR}/${CHROOT}/root"
+ if [[ ${COPY:0:1} = / ]]; then
+ copydir=$COPY
+ else
+ copydir="${CHROOTDIR}/${CHROOT}/${COPY}"
+ fi
+
+ ########################################################################
+
+ if [[ $mode == help ]]; then
+ usage
+ return 0
+ fi
+
+ if (( EUID )); then
+ error "This program must be run as root."
+ return 1
+ fi
+
+ umask 0022
+
+ # Keep this lock as long as we are running
+ # Note that '9' is the same FD number as in (mk)archroot
+ lock_open_write 9 "$copydir" \
+ "Waiting for existing lock on chroot copy to be released: [$COPY]"
+
+ if [[ ! -d $rootdir ]]; then
+ msg "Creating 'root' copy for chroot [$CHROOT]"
+ set +u # if archroot_args is empty, it counts as unbound
+ archroot "${archroot_args[@]}" -m "$rootdir" base-devel
+ set -u
+ fi
+
+ if [[ ! -d $copydir ]] || [[ $mode == sync ]]; then
+ msg "Syncing copy [$COPY] with root copy"
+ normshell chroot_sync "$CHROOTDIR/$CHROOT" "$COPY"
+ fi
+
+ mkdir -p "$copydir/etc/libretools.d"
+ {
+ if [[ -n ${CHROOTEXTRAPKG[@]:-} ]]; then
+ printf 'CHROOTEXTRAPKG=('
+ printf "'%s' " "${CHROOTEXTRAPKG[@]}"
+ printf ')\n'
+ else
+ printf 'CHROOTEXTRAPKG=()\n'
+ fi
+ } > "$copydir"/etc/libretools.d/chroot.conf
+
+ if [[ $mode != delete ]]; then
+ # "touch" the chroot first
+ # this will
+ # - overwrite \`/etc/pacman.d/mirrorlist'"
+ # - set \`CacheDir' in \`/etc/pacman.conf'"
+ # - apply -C or -M flags
+ set +u # if archroot_args is empty, it counts as unbound
+ archroot "${archroot_args[@]}" -r "$copydir" true
+ set -u
+ fi
+
+ ########################################################################
+
+ case "$mode" in
+ # Creat/copy/delete
+ noop|make|sync) :;;
+ delete)
+ if [[ -d $copydir ]]; then
+ normshell chroot_delete "$copydir"
+ fi
+ ;;
+
+ # Dealing with packages
+ install-file) normshell chroot_install_pkgs "$copydir" "$@";;
+ install-name) archroot -r "$copydir" pacman -Sy "$@";;
+ clean-pkgs)
+ trap "rm -f '$copydir'/clean '$copydir'/chrootexec" EXIT
+ cp -a "$(which chcleanup)" "$copydir/clean"
+ echo '#!/bin/bash' > "$copydir/chrootexec"
+ echo 'mkdir /build' >> "$copydir/chrootexec"
+ echo 'cd /build; /clean' >> "$copydir/chrootexec"
+ chmod 755 "$copydir/chrootexec"
+ archroot -r "$copydir" /chrootexec
+ ;;
+
+ # Other
+ run) archroot -r "$copydir" "$@";;
+ enter) archroot -r "$copydir" bash;;
+ clean-repo)
+ rm -rf "${copydir}/repo/*"
+ bsdtar -czf "${copydir}/repo/repo.db.tar.gz" -T /dev/null
+ ln -s "repo.db.tar.gz" "${copydir}/repo/repo.db"
+ ;;
+ *)
+ error "Unrecognized command: \`$mode'"
+ return 1
+ ;;
+ esac
+}
+
+main "$@"
diff --git a/src/chroot-tools/libremakepkg b/src/chroot-tools/libremakepkg
new file mode 100755
index 0000000..b8cdca1
--- /dev/null
+++ b/src/chroot-tools/libremakepkg
@@ -0,0 +1,311 @@
+#!/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 <http://www.gnu.org/licenses/>.
+
+. /usr/share/libretools/conf.sh
+load_conf_libretools_chroot
+
+. libremessages
+
+shopt -s nullglob
+umask 0022
+
+# Boring/mundane functions #####################################################
+
+# End inmediately but print a useful message
+trap_exit() {
+ error "$*"
+ set +euE
+ . /usr/share/devtools/makechrootpkg.sh
+ chroot_copy_out_logs "$@"
+ exit 1
+}
+
+# Usage run [-N] $copydir "$cmd"
+# Runs cmd properly, whether in a chroot already or not.
+#
+# Note that $cmd is a quoted string, not a list of arguments.
+# $copydir=/ if INCHROOT=true
+#
+# Environment
+# - $INCHROOT is set
+run() {
+ local HASNET=true
+ [[ $1 == -N ]] && { HASNET=false; shift; }
+ local copydir=$1; shift
+ local cmd="$*"
+
+ cat >"$copydir/chrootexec" <<EOF
+#!/bin/bash
+. /etc/profile
+${INCHROOT} || export HOME=/build
+${INCHROOT} || cd /build
+
+${cmd}
+EOF
+ chmod 755 "$copydir/chrootexec"
+
+ local flags=''
+ if $INCHROOT; then
+ $HASNET || flags='-n'
+ unshare $flags -- /chrootexec
+ else
+ $HASNET || flags='-N'
+ librechroot $flags -l "$copydir" run /chrootexec
+ fi
+}
+
+# Usage: add_to_local_repo $copydir
+add_to_local_repo() (
+ set +euE
+ . /usr/share/devtools/makechrootpkg.sh
+ chroot_add_to_local_repo "$@"
+)
+
+# Usage: chroot_copy_in $copydir
+# Environment:
+# - In the dirctory of a PKGBUILD
+# - $SRCDEST is set
+chroot_copy_in() (
+ set +euE
+ . /usr/share/devtools/makechrootpkg.sh
+ chroot_copy_in "$@"
+)
+
+# Usage: chroot_copy_out $copydir $owner
+# Environment:
+# - $SRCDEST is set
+# - $PKGDEST is set
+chroot_copy_out() (
+ set +euE
+ . /usr/share/devtools/makechrootpkg.sh
+ chroot_copy_out_pkgs "$@"
+ chroot_copy_out_logs "$@"
+ chroot_copy_out_srcs "$@"
+)
+
+# Usage: chroot_let_nobody_use_pacman $copydir
+chroot_let_nobody_use_pacman() (
+ set +euE
+ . /usr/share/devtools/makechrootpkg.sh
+ chroot_let_nobody_use_pacman "$@"
+)
+
+# Usage: chroot_init $copydir $repack
+# Environment
+# - $LIBREHOME is set
+chroot_init() {
+ local copydir=$1
+ local repack=$2
+
+ librechroot -l "$copydir" make # make sure the chroot exists
+ mkdir -p "$copydir"/{build,pkgdest,srcdest}
+
+ # Remove anything in there UNLESS -R (repack) was passed
+ $repack || rm -rf "$copydir"/build/*
+
+ if [[ -r "$LIBREHOME/.gnupg/pubring.gpg" ]]; then
+ install -D "$LIBREHOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg"
+ fi
+ rm -f "$copydir/build/.makepkg.conf"
+
+ MAKEPKG_CONF="$copydir/etc/makepkg.conf" set_conf_makepkg PKGDEST /pkgdest
+ MAKEPKG_CONF="$copydir/etc/makepkg.conf" set_conf_makepkg SRCDEST /srcdest
+
+ if grep -q '^\[repo\]' "$copydir/etc/pacman.conf"; then
+ cat >> "$copydir/etc/makepkg.conf" <<EOF
+[repo]
+SigLevel = Optional TrustAll
+Server = file:///repo
+EOF
+ fi
+
+ chroot_let_nobody_use_pacman "$copydir"
+}
+
+# Core functions ###############################################################
+
+# Usage: extract
+# Extracts the sources (`makepkg -o`)
+# Environment:
+# - $INCHROOT is set
+# - $copydir is set
+# - $LIBREUSER is set
+extract() {
+ local user=$LIBREUSER
+ $INCHROOT || user=nobody
+
+ local clean
+ if $INCHROOT; then
+ clean=chcleanup
+ else
+ cp -a "$(which chcleanup)" "${copydir}/clean"
+ clean=/clean
+ fi
+
+ run "$copydir" "${clean} && sudo -u ${user} makepkg ${makepkg_args} -o"
+ rm -f "$copydir"/clean
+}
+
+# Usage: build
+# Builds the package (`makepkg -e`)
+# Environment:
+# - $INCHROOT is set
+# - $copydir is set
+# - $LIBREUSER is set
+build() {
+ local user=$LIBREUSER
+ $INCHROOT || user=nobody
+
+ run -N "$copydir" "sudo -u ${user} makepkg ${makepkg_args} -e"
+}
+
+# Functions that check for issues with the build ###############################
+
+check_pkgbuild() {
+ msg "Checking PKGBUILD for issues"
+ # TODO
+ if ! pkgbuild-check-nonfree -f; then
+ if [[ $? -eq 15 ]]; then
+ # other errors mean fail, not nonfree
+ error "PKGBUILD contains non-free issues"
+ exit 15
+ else
+ warning "PKGBUILD couldn't be check aganist non-free issues"
+ fi
+ fi
+}
+
+check_src() {
+ msg "Checking src directory for issues"
+ # TODO
+}
+
+check_pkg() {
+ msg "Checking final package for issues"
+ # TODO
+}
+
+
+# The main program #############################################################
+
+cmd=${0##*/}
+usage() {
+ echo "Usage: $cmd [options] [-- makepkg args]"
+ echo 'This program will build your package.'
+ echo ''
+ echo 'If run from outside of a chroot, this will set PKGDEST and'
+ echo "SRCDEST in the chroot's \`/etc/makepkg.conf', as well as making"
+ echo "whataver alterations to the chroot \`librechroot' makes."
+ echo ''
+ echo "The \`-n' and \`-l' options behave identically to librechroot,"
+ echo 'see the documentation there.'
+ echo ''
+ echo 'Options:'
+ echo ' -n <CHROOT> Name of the chroot to use'
+ echo ' -l <COPY> Name of, or absolute path to, the copy to use'
+ echo ' -R Repackage contents of the package without rebuilding'
+ echo ' -h Show this message'
+}
+
+# Globals: $CHROOTDIR, $CHROOT, $COPY and $copydir
+# Globals: $makepkg_args, $INCHROOT
+main() {
+ # Parse command line ###################################################
+
+ COPY=$LIBREUSER
+ [[ $COPY != root ]] || COPY=copy
+
+ makepkg_args='-s --noconfirm -L '
+ local repack=false
+
+ INCHROOT=false
+ if [[ -f /.arch-chroot ]]; then
+ INCHROOT=true
+ fi
+
+ while getopts 'n:l:Rh' arg ; do
+ case "${arg}" in
+ n) CHROOT=$OPTARG;;
+ l) COPY=$OPTARG;;
+ R) repack=true; makepkg_args+=" -R";;
+ h) usage; return 0;;
+ *) usage; return 1;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+ # Pass all arguments after -- right to makepkg
+ makepkg_args+=" $*"
+
+ if $INCHROOT; then
+ copydir='/'
+ elif [[ ${COPY:0:1} = / ]]; then
+ copydir=$COPY
+ else
+ copydir="${CHROOTDIR}/${CHROOT}/${COPY}"
+ fi
+
+ # Init #################################################################
+
+ if (( EUID )); then
+ error "This script 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
+
+ # Trap signals from makepkg
+ trap 'trap_exit "(libremakepkg): TERM signal caught. Exiting..."' TERM HUP QUIT
+ trap 'trap_exit "(libremakepkg): Aborted by user! Exiting..."' INT
+ trap 'trap_exit "(libremakepkg): An error has occurred. Exiting..."' ERR
+
+ SRCDEST="$(get_conf_makepkg SRCDEST .)"
+ PKGDEST="$(get_conf_makepkg PKGDEST .)"
+
+ # OK, we're starting now ###############################################
+
+ $INCHROOT || lock_open_write 9 "$copydir" \
+ "Waiting for existing lock on chroot copy to be released: [$COPY]"
+
+ # Set target CARCH as it might be used within the PKGBUILD to select
+ # correct sources
+ MAKEPKG_CONF=$copydir/etc/makepkg.conf
+ export CARCH="$(get_conf_makepkg CARCH)"
+ unset MAKEPKG_CONF
+
+ $INCHROOT || chroot_init "$copydir" "$repack"
+
+ check_pkgbuild
+ $INCHROOT || chroot_copy_in "$copydir"
+ $repack || extract
+ check_src
+ build
+ check_pkg
+
+ add_to_local_repo "$copydir"
+ $INCHROOT || chroot_copy_out "$copydir" "$LIBREUSER"
+}
+
+main "$@"