diff options
Diffstat (limited to 'src/chroot-tools')
-rwxr-xr-x | src/chroot-tools/chcleanup | 57 | ||||
-rwxr-xr-x | src/chroot-tools/librechroot | 158 | ||||
-rw-r--r-- | src/chroot-tools/librechroot.gpl2 | 40 | ||||
-rwxr-xr-x | src/chroot-tools/libremakepkg | 195 | ||||
-rwxr-xr-x | src/chroot-tools/libremakepkg.gpl2 | 105 | ||||
-rwxr-xr-x | src/chroot-tools/libremkchroot | 65 |
6 files changed, 620 insertions, 0 deletions
diff --git a/src/chroot-tools/chcleanup b/src/chroot-tools/chcleanup new file mode 100755 index 0000000..17c1f02 --- /dev/null +++ b/src/chroot-tools/chcleanup @@ -0,0 +1,57 @@ +#!/bin/bash +# (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 + +set -e +DRYRUN=${DRYRUN:-false} + +source /etc/makepkg.conf +source /etc/libretools.conf +source ${HOME}/.makepkg.conf 2>/dev/null|| true + +msg "Cleaning chroot..." + +TMPDIR="$(mktemp -d /tmp/$(basename $0)-XXXXX)" +cleanup_log="${TMPDIR}"/libretools-cleanup.log + +cp -a /var/lib/pacman/sync "${TMPDIR}/" +touch ${cleanup_log} + +# If we're running makepkg +if [ -f PKGBUILD ]; then + source PKGBUILD || true + + check=(${depends[@]} ${makedepends[@]} ${checkdepends[@]}) + +fi + +# Get the full list of packages needed by dependencies, including the base system +sudo pacman -b "${TMPDIR}" \ + -Sp \ + --print-format "%n" \ + base base-devel sudo \ + ${CHROOTEXTRAPKG[@]} \ + ${check[@]} \ + >${cleanup_log} + +# Diff installed packages against a clean chroot then remove leftovers +packages=($(comm -23 <(pacman -Qq | sort) \ + <(sort -u ${cleanup_log}))) + +[ ${#packages[@]} -eq 0 ] && exit 0 + +msg2 "Removing %d packages" ${#packages[@]} + +# Only remove leftovers, -Rcs removes too much +${DRYRUN} || sudo pacman --noconfirm -Rn ${packages[@]} +${DRYRUN} && echo ${packages[@]} + +# Cleanup +${DRYRUN} || rm -fr ${TMPDIR} + +exit $? diff --git a/src/chroot-tools/librechroot b/src/chroot-tools/librechroot new file mode 100755 index 0000000..6594f15 --- /dev/null +++ b/src/chroot-tools/librechroot @@ -0,0 +1,158 @@ +#!/bin/bash -euE +# librechroot + +# Copyright 2010 Nicolás Reynolds +# Copyright 2011 Joshua Haase +# Copyright 2012 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/>. + +. /etc/libretools.conf + +# This file (librechroot) is GPLv3+, but I would like to use some code +# modified from devtools' "makechrootpkg", which is GPLv2. +. "$(dirname "$0")/librechroot.gpl2" +# This gives us the functions: +# - sync + +cmd=${0##*/} +usage() { + echo "Usage: $cmd [OPTIONS] " + echo 'Interacts with a chroot.' + echo '' + echo "The default CHROOT is \`${CHROOT}'." + echo '' + echo 'Options:' + echo ' Settings:' + echo " -n <CHROOT> Use this chroot instead of \`$CHROOT'" + echo ' -l <COPY> Use this as the chroot copy instead of basing it' + echo ' on the username' + echo ' -N Disable networking in the chroot' + echo '' + echo ' Modes: (the last mode given will be used)' + echo ' -C Clean /repo in the chroot' + echo ' -c Clean the packages installed in the chroot' + echo ' -I <FILE> Install the package FILE into the chroot' + echo ' -i <PKG> Install the package PKG from repos into the chroot' + echo ' -m Make sure the chroot exists; do nothing else' + echo ' -r <CMD> Run CMD in the chroot' + echo " -s Sync the copy with the 'root' copy" + echo ' -u Update the chroot' + echo ' -h Print this message' +} + +main() { + CHROOTCOPY=$LIBREUSER + [[ $CHROOTCOPY != root ]] || CHROOTCOPY=copy + + local mode=enter + local archroot_args=(-f) + local ARG='' + while getopts 'n:l:NCcI:i:mrsuh' arg; do + case $arg in + n) CHROOT=$OPTARG;; + l) CHROOTCOPY=$OPTARG;; + N) archroot_args+=(-N);; + + C) mode=clean_repo;; + c) mode=clean_pacman;; + I) mode=install_file; ARG=$OPTARG;; + i) mode=install_pkg; ARG=$OPTARG;; + m) mode=noop;; + r) mode=run; ARG=$OPTARG;; + s) mode=sync;; + u) mode=update;; + + h) usage; exit 0;; + *) usage; exit 1;; + esac + done + shift $(($OPTIND - 1)) + if [[ $# > 0 ]]; then + usage + exit 1 + fi + + # not local + rootdir="${CHROOTDIR}/${CHROOT}/root" + copydir="${CHROOTDIR}/${CHROOT}/${CHROOTCOPY}" + + ######################################################################## + + if (( EUID )); then + error "This script must be run as root." + exit 1 + fi + + # 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" "Locking chroot copy '$CHROOTCOPY'" + + if [[ ! -d $rootdir ]]; then + libremkchroot "$CHROOT" + fi + + if [[ ! -d $copydir ]] && [[ $mode != sync ]]; then + sync + fi + + ######################################################################## + + case "$mode" in + clean_repo) + msg "Cleaning local pacman repository" + rm -rf "${copydir}/repo" + mkdir "${copydir}/repo" + bsdtar -czf "${copydir}/repo/repo.db.tar.gz" -T /dev/null + ln -s "repo.db.tar.gz" "${copydir}/repo/repo.db" + ;; + clean_pacman) + msg "Intelligently cleaning packages" + cp -a "$(which chcleanup)" "${copydir}/clean" + echo '#!/bin/bash' > "${copydir}/cleanstrap" + echo 'mkdir /build' >> "${copydir}/cleanstrap" + echo 'cd /build; /clean' >> "${copydir}/cleanstrap" + chmod 755 "${copydir}/cleanstrap" + archroot "${archroot_args[@]}" "${copydir}" -r /cleanstrap + ;; + install_file) + msg "Installing package file: $ARG" + cp "$ARG" "$copydir/${ARG##*/}" + archroot "${archroot_args[@]}" "$copydir" -r "pacman -U /${ARG##*/} --noconfirm" + rm "$copydir/${ARG##*/}" + ;; + install_pkg) + msg "Installing package(s): $ARG" + archroot "${archroot_args[@]}" "$copydir" -i $ARG + ;; + noop) :;; + run) + msg "Running command" + archroot "${archroot_args[@]}" "${copydir}" -r "$ARG" + ;; + sync) sync;; + update) + msg "Updating chroot" + archroot "${archroot_args[@]}" "${copydir}" -u + ;; + enter) + msg "Entering chroot" + archroot "${archroot_args[@]}" "${copydir}" -r bash + ;; + esac +} + +main "$@" diff --git a/src/chroot-tools/librechroot.gpl2 b/src/chroot-tools/librechroot.gpl2 new file mode 100644 index 0000000..6ba361f --- /dev/null +++ b/src/chroot-tools/librechroot.gpl2 @@ -0,0 +1,40 @@ +#!/bin/bash +# Contains code derived from devtools' "makechrootpkg" + +# Copyright 2011-2012 The Arch Linux Development Team +# Copyright 2012 Luke Shumaker +# +# 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; version 2 of the License. +# +# 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. + +sync() { + if [[ $CHROOTCOPY = root ]]; then + error "Cannot sync the root copy with itself" + exit 1 + fi + + lock_open_read 8 "$rootdir" "Locking clean chroot" + + stat_busy 'Creating clean working copy' + local use_rsync=false + if type -P btrfs >/dev/null; then + [[ -d $copydir ]] && btrfs subvolume delete "$copydir" &>/dev/null + btrfs subvolume snapshot "$chrootdir/root" "$copydir" &>/dev/null || use_rsync=true + else + use_rsync=true + fi + + if $use_rsync; then + mkdir -p "$copydir" + rsync -a --delete -q -W -x "$CHROOTDIR/$CHROOT/root/" "$copydir" + fi + stat_done + + lock_close 8 +} diff --git a/src/chroot-tools/libremakepkg b/src/chroot-tools/libremakepkg new file mode 100755 index 0000000..4e810d1 --- /dev/null +++ b/src/chroot-tools/libremakepkg @@ -0,0 +1,195 @@ +#!/bin/bash -euE +# libremakepkg + +# Copyright 2010 - 2011 Nicolás Reynolds +# Copyright 2011 Joshua Ismael Haase Hernández +# Copyright 2012 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/>. + +. /etc/libretools.conf + +shopt -s nullglob + +# This file (libremakepkg) is GPLv3+, but I would like to use some code +# modified from devtools' "makechrootpkg", which is GPLv2. +. "$(dirname "$0")/libremakepkg.gpl2" +# This gives us the functions: +# - chroot_init +# - chroot_extract +# - chroot_build +# - copy_pkgs + +# Boring functions ############################################################# + +## +# copy logs if they exist +## +copy_logs() { + for l in "$copydir"/build/*.log; do + chown "$LIBREUSER" "$l" + mv "$l" . + done +} + +## +# End inmediately but print a useful message +## +trap_exit() { + copy_logs + error "$*" + exit 1 +} + +## +# Usage: makepkg_conf_get SETTING [DEFAULT] +## +makepkg_conf_get() { + local setting=$1 + if [[ -f $LIBREHOME/.makepkg.conf ]]; then + eval $(grep "^$setting=" "$LIBREHOME/.makepkg.conf") + fi + if [[ -z ${!setting:-} ]]; then + eval $(grep "^$setting=" "/etc/makepkg.conf") + fi + if [[ -z ${!setting:-} && -n ${2:-} ]]; then + eval "$setting='$2'" + fi +} + +chroot_makepkg_conf_get() { + local setting=$1 + eval $(grep "^$setting=" "$copydir/etc/makepkg.conf") +} + +chroot_makepkg_conf_set() { + local key=$1 + local val=$2 + sed -i "/^$key=/d" "$copydir/etc/makepkg.conf" + echo "$key='$val'" >> "$copydir/etc/makepkg.conf" +} + +# Functions that check for issues with the build ############################### + +libre_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 +} + +libre_check_src() { + msg "Checking src directory for issues" + # TODO +} + +libre_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 'OPTIONS:' + echo " -n <CHROOT> Use this chroot instead of \`$CHROOT'" + echo ' -l <COPY> Use this chroot copy instead of basing it' + echo ' on the username' + echo '' + echo " -m <MAKEPKG> Use the command MAKEPKG instead of 'makepkg'" + echo '' + echo ' -h Show this message' +} + +main() { + # Parse command line ################################################### + + CHROOTCOPY=$LIBREUSER + [[ $CHROOTCOPY != root ]] || CHROOTCOPY=copy + + makepkg_args='-s --noconfirm -L ' + MAKEPKG=makepkg + + while getopts 'n:l:m:Rh' arg ; do + case "${arg}" in + n) CHROOT=$OPTARG;; + l) CHROOTCOPY=$OPTARG;; + m) MAKEPKG=$OPTARG;; + h) usage; exit 0;; + *) usage; exit 1;; + esac + done + shift $(($OPTIND - 1)) + # Pass all arguments after -- right to makepkg + makepkg_args+=" $*" + + rootdir="${CHROOTDIR}/${CHROOT}/root" + copydir="${CHROOTDIR}/${CHROOT}/${CHROOTCOPY}" + + # 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 unknown error has occurred. Exiting..."' ERR + + makepkg_conf_get SRCDEST . + makepkg_conf_get PKGDEST . + + # OK, we're starting now ############################################### + + lock_open_write 9 "$copydir" "Locking chroot '$CHROOTCOPY'" + + # Set target CARCH as it might be used within the PKGBUILD to select correct sources + chroot_makepkg_conf_get CARCH + export CARCH + + chroot_init + + libre_check_pkgbuild + chroot_extract + libre_check_src + chroot_build + libre_check_pkg + + copy_pkgs + copy_logs +} + +main "$@" diff --git a/src/chroot-tools/libremakepkg.gpl2 b/src/chroot-tools/libremakepkg.gpl2 new file mode 100755 index 0000000..1077b66 --- /dev/null +++ b/src/chroot-tools/libremakepkg.gpl2 @@ -0,0 +1,105 @@ +#!/bin/bash +# Contains code derived from devtools' "makechrootpkg" + +# Copyright 2011-2012 The Arch Linux Development Team +# Copyright 2012 Luke Shumaker +# +# 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; version 2 of the License. +# +# 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. + +chroot_init() { + # make sure the chroot exists + librechroot -n "$CHROOT" -l "$CHROOTCOPY" -m + + if [[ -r "$LIBREHOME/.gnupg/pubring.gpg" ]]; then + install -D "$HOME/.gnupg/pubring.gpg" "$copydir/build/.gnupg/pubring.gpg" + fi + + mkdir -p "$copydir/pkgdest" + mkdir -p "$copydir/srcdest" + chroot_makepkg_conf_set PKGDEST /pkgdest + chroot_makepkg_conf_set SRCDEST /srcdest + + cat > "$copydir/etc/sudoers.d/nobody-pacman" <<EOF +Defaults env_keep += "HOME" +nobody ALL = NOPASSWD: /usr/bin/pacman +EOF + chmod 440 "$copydir/etc/sudoers.d/nobody-pacman" +} + +chroot_extract() { + rm -rf "$copydir"/build/* + cp PKGBUILD "$copydir/build/" + ( + set +euE + source PKGBUILD + + # Copy source files + for file in "${source[@]}"; do + file="${file%%::*}" + file="${file##*://*/}" + if [[ -f $file ]]; then + cp "$file" "$copydir/srcdest/" + elif [[ -f $SRCDEST/$file ]]; then + cp "$SRCDEST/$file" "$copydir/srcdest/" + fi + done + + # Find all changelog and install files, even inside functions + for i in 'changelog' 'install'; do + while read -r file; do + # evaluate any bash variables used + eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\" + if [[ -f $file ]]; then + cp "$file" "$copydir/build/" + fi + done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD) + done + ) + + chown -R nobody "$copydir"/{build,pkgdest,srcdest} + + cp -a "$(which chcleanup)" "${copydir}/clean" + local file="$copydir/chrootextract" + echo '#!/bin/bash' > "$file" + echo '. /etc/profile' >> "$file" + echo 'export HOME=/build' >> "$file" + echo 'cd /build' >> "$file" + echo '/clean' >> "$file" + echo "sudo -u nobody ${MAKEPKG} $makepkg_args -o" >> "$file" + chmod 755 "$file" + archroot "$copydir" -r /chrootextract +} + +chroot_build() { + local file="$copydir/chrootbuild" + echo '#!/bin/bash' > "$file" + echo '. /etc/profile' >> "$file" + echo 'export HOME=/build' >> "$file" + echo 'cd /build' >> "$file" + echo "sudo -u nobody ${MAKEPKG} $makepkg_args -e" >> "$file" + chmod 755 "$file" + archroot -N "$copydir" -r /chrootbuild +} + +copy_pkgs() { + for pkgfile in "$copydir"/pkgdest/*.pkg.tar*; do + mkdir -p "$copydir/repo" + pushd "$copydir/repo" >/dev/null + cp "$pkgfile" . + repo-add repo.db.tar.gz "${pkgfile##*/}" + popd >/dev/null + + chown "$LIBREUSER" "$pkgfile" + mv "$pkgfile" "$PKGDEST" + if [[ $PKGDEST != . ]]; then + ln -s "$PKGDEST/${pkgfile##*/}" . + fi + done +} diff --git a/src/chroot-tools/libremkchroot b/src/chroot-tools/libremkchroot new file mode 100755 index 0000000..d3652a5 --- /dev/null +++ b/src/chroot-tools/libremkchroot @@ -0,0 +1,65 @@ +#!/bin/bash -euE +# libremkchroot + +# Copyright 2011, 2012 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/>. + +. /etc/libretools.conf + +cmd=${0##*/} + +usage() { + echo "Usage: $cmd [OPTIONS] [CHROOT]" + echo 'This script will create a chroot to build packages in.' + echo "Use \`librechroot' to interact with the chroot after it is created." + echo '' + echo "The default CHROOT is \`${CHROOT}'." + echo '' + echo 'Options:' + echo ' -h Show this message' + echo '' + echo ' -C <file> Location of pacman config file.' + echo ' -M <file> Location of makepkg config file.' +} + +main() { + archroot_args=(-f); + while getopts 'hC:M:' arg; do + case "$arg" in + C|M) archroot_args+=("-$arg" "$OPTARG");; + + h) usage; exit 0;; + *) usage; exit 1;; + esac + done + shift $(($OPTIND - 1)) + case $# in + 0) :;; + 1) CHROOT="$1";; + *) usage; exit 1;; + esac + + if (( EUID )); then + error "This script must be run as root" + exit 1 + fi + + mkdir -p "${CHROOTDIR}/${CHROOT}" + archroot "${archroot_args[@]}" "${CHROOTDIR}/${CHROOT}/root" -i base base-devel sudo "${CHROOTEXTRAPKG[@]}" +} + +main "$@" |