summaryrefslogtreecommitdiff
path: root/src/chroot-tools
diff options
context:
space:
mode:
authorLuke Shumaker <LukeShu@sbcglobal.net>2013-09-11 10:56:46 -0400
committerLuke Shumaker <LukeShu@sbcglobal.net>2013-09-11 15:55:15 -0400
commit6eddc77d5e6abb25f33751308419fa0c62518188 (patch)
tree4f1d004e46d5be3f54efb04d6fd6c5cc6b50c0da /src/chroot-tools
parent2a971c6ad1e55f95f5486b265307160e57b47e5f (diff)
Update to the new version of devtools (huge commit).
User-facing changes: - libremessages: `lock_open_write` became `lock` - libremessages: `lock_open_read` became `slock` - librechroot: learned the `-r` and `-w` flags to do bind mounts. Internal changes: The changes to librechroot were pretty straight-forward; the biggest change is that `archroot` got split into `mkarchroot` and `arch-nspawn`. libremakepkg got a major overhaul Honestly, the changes to libremakepklg probably could have been a lot smaller, but... I wanted to do it right/be clean. makechrootpkg in devtools got cleaned up a lot, actually a lot of the same changes I was making. But, the small differences between the way we did things made it less than simple to adjust. The biggest changes in terms of conflict for me are how devtools now uses bind-mounts to put files in the chroot, and that the /chrootbuild file is more complicated. I handled a lot of the complexity by moving things out of the main program, and adding hooks for non-core functionality, including chcleanup, distcc compatability hacks, and PKGBUILD/pkg checking. Unfortunately, the files containing the hooks are currently hard-coded. Perhaps they will be truly pluggable in the future. That might be neat. Or over-complicated. We'll see where it goes.
Diffstat (limited to 'src/chroot-tools')
-rw-r--r--src/chroot-tools/.gitignore4
-rw-r--r--src/chroot-tools/Makefile48
-rw-r--r--src/chroot-tools/hooks-chcleanup.sh15
-rw-r--r--src/chroot-tools/hooks-check.sh38
-rw-r--r--src/chroot-tools/hooks-distcc.sh86
-rwxr-xr-xsrc/chroot-tools/librechroot128
-rwxr-xr-xsrc/chroot-tools/libremakepkg410
-rw-r--r--src/chroot-tools/makechrootpkg.sh.patch450
8 files changed, 630 insertions, 549 deletions
diff --git a/src/chroot-tools/.gitignore b/src/chroot-tools/.gitignore
index fbb07f7..80e1000 100644
--- a/src/chroot-tools/.gitignore
+++ b/src/chroot-tools/.gitignore
@@ -1,3 +1,5 @@
makechrootpkg.sh*
!makechrootpkg.sh.patch
-archroot* \ No newline at end of file
+
+arch-nspawn*
+mkarchroot*
diff --git a/src/chroot-tools/Makefile b/src/chroot-tools/Makefile
index 258caea..0540636 100644
--- a/src/chroot-tools/Makefile
+++ b/src/chroot-tools/Makefile
@@ -1,31 +1,39 @@
-# The makechrootpkg flow is:
-# $(devtoolsdir)/*.in -> *.sh.in + *.sh.patch -> *.sh.ugly -> *.sh
-
-copy_files = makechrootpkg.sh.in archroot.in
-libs = makechrootpkg.sh
-progs = archroot
+# These files are coming from devtools
+copy_files = makechrootpkg.sh.in mkarchroot.in arch-nspawn.in
+# These are programs that we will use internally, but shouldn't be in PATH
+libexecs = mkarchroot arch-nspawn distcc-tool chcleanup
+no-progs = $(libexecs)
+# These are the shell libraries we will use
+libs = makechrootpkg.sh $(wildcard hooks-*.sh)
+
+pkglibexecdir = $(libexecdir)/libretools/chroot
clean_files = makechrootpkg.sh.ugly* *~
include ../../common.mk
-# Copy ###############################################################
+# Usage: $(call indent,FILENAME)
+# Command to auto-indent a file.
+indent = emacs --batch $1 \
+ --eval '(setq sh-basic-offset 8)' \
+ --eval '(indent-region (point-min) (point-max) nil)' \
+ -f save-buffer &>/dev/null
-makechrootpkg.sh.in: %.sh.in: $(devtoolsdir)/%.in
- cp $< $@
+# makechrootpkg.sh is special, we patch it and do fancy stuff
+# The flow is:
+# $(devtoolsdir)/*.in -> *.sh.in + *.sh.patch -> *.sh.ugly -> *.sh
-archroot.in: $(devtoolsdir)/mkarchroot.in
+makechrootpkg.sh.in: %.sh.in: $(devtoolsdir)/%.in
cp $< $@
-
-# Build ##############################################################
-
makechrootpkg.sh.ugly: %.ugly: %.in %.patch Makefile
- @echo "GEN $@"
- @cp $*.in $@
- @patch $@ $*.patch || { rm -f -- '$@'; false; }
-
+ cp $*.in $@
+ @echo 'PATCH $@ $*.patch'; patch $@ $*.patch || { rm -f -- '$@'; false; }
makechrootpkg.sh: %: %.ugly Makefile
- @echo "GEN $@"
- @$(edit) <"$<" >"$@" || { rm -f -- '$@'; false; }
- $(call indent,$@) || { rm -f -- '$@'; false; }
+ @echo 'EDIT < $< > $@'; $(edit) <'$<' >'$@' || { rm -f -- '$@'; false; }
+ @echo 'INDENT $@'; $(call indent,$@) || { rm -f -- '$@'; false; }
+
+mkarchroot: mkarchroot.in Makefile
+ @echo '< $< M4_EDIT | SED > $@'
+ @<'$<' $(edit) | sed 's|arch-nspawn|$$(librelib chroot/&)|' >'$@' || { rm -f -- '$@'; false; }
+ @echo 'CHMOD $<'; chmod 755 "$@" || { rm -f -- '$@'; false; }
archroot: %: %.in Makefile
@echo "GEN $@"
diff --git a/src/chroot-tools/hooks-chcleanup.sh b/src/chroot-tools/hooks-chcleanup.sh
new file mode 100644
index 0000000..6a95dfb
--- /dev/null
+++ b/src/chroot-tools/hooks-chcleanup.sh
@@ -0,0 +1,15 @@
+#!/bin/bash -euE
+
+hooks_pre_build+=("clean_chroot")
+
+clean_chroot() (
+ set +x
+ local copydir=$1
+ if $INCHROOT; then
+ cd /build
+ sudo -u nobody "$(librelib chroot/chcleanup)"
+ else
+ librechroot -l "$copydir" clean-pkgs
+ fi
+ r=$?; echo clean_chroot returning $r; return $r
+)
diff --git a/src/chroot-tools/hooks-check.sh b/src/chroot-tools/hooks-check.sh
new file mode 100644
index 0000000..dee7c04
--- /dev/null
+++ b/src/chroot-tools/hooks-check.sh
@@ -0,0 +1,38 @@
+#!/bin/bash -euE
+
+hook_check_pkgbuild+=("check_pkgbuild_dependencies")
+check_pkgbuild_dependencies() {
+ local s=0
+ sudo -EH -u "$LIBREUSER" pkgbuild-check-nonfree -f || s=$?
+ case $s in
+ 0) :;;
+ 15) error "This PKGBUILD links to known unfree packages"; return 1;;
+ *) warning "pkgbuild-check-nonfree failed to run";;
+ esac
+}
+
+hook_check_pkgbuild+=("check_pkgbuild_license")
+check_pkgbuild_license() {
+ local s=0
+ sudo -EH -u "$LIBREUSER" pkgbuild-check-licenses -f || s=$?
+ for i in 1 2 4; do
+ if [[ $i -eq $(($s & $i)) ]]; then
+ case $i in
+ 1) warning "pkgbuild-check-licenses encountered an error";;
+ 2) warning "This PKGBUILD has an uncommon license";;
+ 4) error "This PKGBUILD has a known nonfree license"; ret=1;;
+ esac
+ fi
+ done
+}
+
+#hook_check_pkgbuild+=("check_pkgbuild_namcap")
+check_pkgbuild_namcap() {
+ sudo -EH -u "$LIBREUSER" namcap PKGBUILD
+}
+
+#hook_check_pkg+=("check_pkg")
+check_pkg() {
+ # TODO
+ :
+}
diff --git a/src/chroot-tools/hooks-distcc.sh b/src/chroot-tools/hooks-distcc.sh
new file mode 100644
index 0000000..bbbc3e9
--- /dev/null
+++ b/src/chroot-tools/hooks-distcc.sh
@@ -0,0 +1,86 @@
+#!/bin/bash -euE
+
+hook_pre_build+=("distcc_start")
+hook_post_build+=("distcc_stop")
+
+_distcc_check() {
+ local copydir=$1
+ local home=$2
+
+ local files=(
+ "$copydir/bin/distcc-tool"
+ "$copydir/run/distcc-tool.pid"
+ "$home/.makepkg.conf"
+ "$home/.ssh/config"
+ )
+
+ local file_err=false
+ for files in "${files[@]}"; do
+ if [[ -f $file ]]; then
+ file_err=true
+ error "Auto-generated file already exists, remove it: %s" "$file"
+ fi
+ done
+ if $file_err; then
+ exit 1
+ fi
+}
+
+distcc_start() {
+ local copydir=$1
+
+ # Because /{,usr/}{,s}bin are all symlinked together for
+ # fileystem 2013.05-2 and up, I can take shortcuts when checking for
+ # existance of programs.
+ if $NONET && [[ -f "$copydir/bin/socat" && -f "$copydir/bin/distcc" ]]; then
+ local home
+ if $INCHROOT; then
+ home=$LIBREHOME
+ else
+ home="$copydir/build"
+ fi
+
+ _distcc_check
+
+ local _distcc_tool=$(librelib chroot/distcc-tool)
+ install -m755 "$_distcc_tool" "$copydir/bin/distcc-tool"
+
+ mkdir -p "$home/.ssh"
+
+ printf '%s\n' \
+ '/bin/distcc-tool idaemon "$DISTCC_HOSTS" &' \
+ 'DISTCC_HOSTS="$(/bin/distcc-tool rewrite "$DISTCC_HOSTS")"' \
+ > "$home/.makepkg.conf"
+
+ printf '%s\n' \
+ 'Host *' \
+ ' ProxyCommand /bin/distcc-tool client %h %p' \
+ > "$home/.ssh/config"
+
+ "$_distcc_tool" odaemon "$copydir" &
+ echo $! > "$copydir/run/distcc-tool.pid"
+ fi
+}
+
+distcc_stop() {
+ local copydir=$1
+
+ local home
+ if $INCHROOT; then
+ home=$LIBREHOME
+ else
+ home="$copydir/build"
+ fi
+
+ if [[ -f "$copydir/run/distcc-tool.pid" ]]; then
+
+ odaemon=$(cat "$copydir/distcc-tool.pid")
+ kill -- "$odaemon"
+
+ rm -f -- \
+ "$home/.makepkg.conf" \
+ "$home/.ssh/config" \
+ "$copydir/bin/distcc-tool" \
+ "$copydir/run/distcc-tool.pid"
+ fi
+}
diff --git a/src/chroot-tools/librechroot b/src/chroot-tools/librechroot
index e82b18c..e5ca1f7 100755
--- a/src/chroot-tools/librechroot
+++ b/src/chroot-tools/librechroot
@@ -25,18 +25,26 @@
# - the commands=() array
# - the case statement in main()
-. $(librelib conf.sh)
+. $(librelib conf)
load_files chroot
. libremessages
-. $(librelib makechrootpkg)
+
+shopt -s nullglob
+umask 0022
+
+readonly _arch_nspawn=$(librelib chroot/arch-nspawn)
+readonly _mkarchroot=$(librelib chroot/mkarchroot)
+readonly _makechrootpkg=$(librelib chroot/makechrootpkg.sh)
# Because the makechrootpkg.sh library functions don't work with -euE
-normshell() (
+_makechrootpkg() (
set +euE
+ . "$_makechrootpkg"
"$@"
)
+# Usage: make_empty_repo $copydir
make_empty_repo() {
local copydir=$1
mkdir -p "${copydir}/repo"
@@ -44,8 +52,21 @@ make_empty_repo() {
ln -s "repo.db.tar.gz" "${copydir}/repo/repo.db"
}
+# Usage: chroot_add_to_local_repo $copydir $pkgfiles...
+chroot_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
+}
+
usage() {
- calculate_directories
+ eval "$(calculate_directories)"
print "Usage: %s [OPTIONS] COMMAND [ARGS...]" "${0##*/}"
print 'Interacts with an archroot (arch chroot).'
echo
@@ -99,6 +120,8 @@ usage() {
flag '-N' 'Disable networking in the chroot'
flag "-C <$(_ FILE)>" 'Copy this file to `$copydir/etc/pacman.conf`'
flag "-M <$(_ FILE)>" 'Copy this file to `$copydir/etc/makepkg.conf`'
+ flag "-w <$(_ 'PATH[:PATH]')>" 'Bind mount a file or directory, read/write'
+ flag "-r <$(_ 'PATH[:PATH]')>" 'Bind mount a file or directory, read-only'
echo
print 'Commands:'
print ' Create/copy/delete:'
@@ -120,7 +143,7 @@ usage() {
flag 'clean-repo' 'Clean /repo in the chroot copy'
flag 'help' 'Show this message'
}
-commands=(
+readonly commands=(
noop make sync delete
install-file install-name update clean-pkgs
run enter clean-repo help
@@ -130,6 +153,7 @@ commands=(
calculate_directories() {
# Don't assume that CHROOTDIR or CHROOT are set,
# but assume that COPY is set.
+ local rootdir copydir
if [[ -n ${CHROOTDIR:-} ]] && [[ -n ${CHROOT:-} ]]; then
rootdir="${CHROOTDIR}/${CHROOT}/root"
@@ -144,6 +168,18 @@ calculate_directories() {
else
copydir=''
fi
+
+ declare -p rootdir
+ declare -p copydir
+}
+
+arch_nspawn_flags=()
+sysd_nspawn_flags=()
+arch-nspawn() {
+ local copydir=$1; shift
+ set +u # if an array is empty, it counts as unbound
+ "$_arch_nspawn" "${arch_nspawn_flags[@]}" "$copydir" "${sysd_nspawn_flags[@]}" -- "$@"
+ set -u
}
# Globals: $CHROOTDIR, $CHROOT, $COPY, $rootdir and $copydir
@@ -152,19 +188,14 @@ main() {
[[ $COPY != root ]] || COPY=copy
local mode=enter
- local archroot_args=()
- while getopts 'n:l:NC:M:' arg; do
- case $arg in
+ while getopts 'n:l:NC:M:w:r:' opt; do
+ case $opt 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");;
+ N) sysd_nspawn_flags+=(--private-network);;
+ C|M) arch_nspawn_flags+=(-$opt "$OPTARG");;
+ w) sysd_nspawn_flags+=("--bind=$OPTARG");;
+ r) sysd_nspawn_flags+=("--bind-ro=$OPTARG");;
*) usage >/dev/stderr; return 1;;
esac
done
@@ -188,7 +219,12 @@ main() {
fi
check_vars chroot CHROOTDIR CHROOT
- calculate_directories
+ eval "$(calculate_directories)"
+
+ readonly LIBREUSER LIBREHOME
+ readonly CHROOTDIR CHROOT COPY
+ readonly rootdir copydir
+ readonly mode
########################################################################
@@ -200,29 +236,27 @@ main() {
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" \
+ # Note that '9' is the same FD number as in mkarchroot et al.
+ lock 9 "$copydir.lock" \
"Waiting for existing lock on chroot copy to be released: [%s]" "$COPY"
if [[ ! -d $rootdir ]]; then
msg "Creating 'root' copy for chroot [%s]" "$CHROOT"
- set +u # if archroot_args is empty, it counts as unbound
- archroot "${archroot_args[@]}" -m "$rootdir" base-devel
+ set +u # if an array is empty, it counts as unbound
+ "$_mkarchroot" "${arch_nspawn_flags[@]}" "$rootdir" base-devel
set -u
make_empty_repo "$rootdir"
fi
if [[ ! -d $copydir ]] || [[ $mode == sync ]]; then
msg "Syncing copy [%s] with root copy" "$COPY"
- normshell chroot_sync "$CHROOTDIR/$CHROOT" "$COPY"
+ _makechrootpkg sync_chroot "$CHROOTDIR/$CHROOT" "$COPY"
fi
mkdir -p "$copydir/etc/libretools.d"
{
- if [[ -n ${CHROOTEXTRAPKG[@]:-} ]]; then
- printf 'CHROOTEXTRAPKG=('
- printf "'%s' " "${CHROOTEXTRAPKG[@]}"
- printf ')\n'
+ if [[ -n ${CHROOTEXTRAPKG[*]:-} ]]; then
+ declare -p CHROOTEXTRAPKG | sed -r 's/declare( -.)* //'
else
printf 'CHROOTEXTRAPKG=()\n'
fi
@@ -234,9 +268,8 @@ main() {
# - 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
+ arch-nspawn "$copydir" true
+ arch_nspawn_flags=() # XXX dirty hack, don't apply -C or -M again
fi
########################################################################
@@ -246,30 +279,41 @@ main() {
noop|make|sync) :;;
delete)
if [[ -d $copydir ]]; then
- normshell chroot_delete "$copydir"
+ _makechrootpkg delete_chroot "$copydir" "$COPY"
fi
;;
# Dealing with packages
install-file)
- normshell chroot_install_pkgs "$copydir" "$@"
- normshell chroot_add_to_local_repo "$copydir" "$@"
+ _makechrootpkg install_packages "$copydir" "$@"
+ chroot_add_to_local_repo "$copydir" "$@"
+ ;;
+ install-name)
+ arch-nspawn "$copydir" pacman -Sy "$@"
+ ;;
+ update)
+ arch-nspawn "$copydir" pacman -Syu --noconfirm
;;
- install-name) archroot -r "$copydir" pacman -Sy "$@";;
- update) archroot -u "$copydir";;
clean-pkgs)
- trap "rm -f '$copydir'/clean '$copydir'/chrootexec" EXIT
- cp -a "$(which chcleanup)" "$copydir/clean"
- echo '#!/bin/bash' > "$copydir/chrootexec"
- echo 'mkdir -p /build' >> "$copydir/chrootexec"
- echo 'cd /build; /clean' >> "$copydir/chrootexec"
+ trap "rm -f '$copydir'/bin/chcleanup '$copydir'/chrootexec" EXIT
+ install -m755 "$(librelib chroot/chcleanup)" "$copydir/bin/chcleanup"
+ printf '%s\n' \
+ '#!/bin/bash' \
+ 'mkdir -p /build' \
+ 'cd /build' \
+ '/bin/chcleanup' \
+ > "$copydir/chrootexec"
chmod 755 "$copydir/chrootexec"
- archroot -r "$copydir" /chrootexec
+ arch-nspawn "$copydir" /chrootexec
;;
# Other
- run) archroot -r "$copydir" "$@";;
- enter) archroot -r "$copydir" bash;;
+ run)
+ arch-nspawn "$copydir" "$@"
+ ;;
+ enter)
+ arch-nspawn "$copydir" bash
+ ;;
clean-repo)
rm -rf "${copydir}"/repo/*
make_empty_repo "$copydir"
diff --git a/src/chroot-tools/libremakepkg b/src/chroot-tools/libremakepkg
index a1d30d4..22e7a7f 100755
--- a/src/chroot-tools/libremakepkg
+++ b/src/chroot-tools/libremakepkg
@@ -20,251 +20,94 @@
# 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.sh)
-load_files chroot
-
-. libremessages
-makechrootpkg=$(librelib makechrootpkg)
+. $(librelib conf)
+. $(librelib messages)
+. $(librelib chroot/makechrootpkg.sh)
shopt -s nullglob
umask 0022
-# Boring/mundane functions #####################################################
-
-# End inmediately but print a useful message
-trap_exit() {
- error "$*"
- $INCHROOT || chroot_copy_out "$copydir" "$LIBREUSER"
- 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="$*"
+# 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
- if $HASNET; then
- trap "rm -f -- '$copydir/chrootexec'" EXIT
- else
- distcc_start "$copydir"
- trap "rm -f -- '$copydir/chrootexec'; distcc_stop '$copydir'" EXIT
- fi
+# Hooks ########################################################################
- cat >"$copydir/chrootexec" <<EOF
-#!/bin/bash
-. /etc/profile
-${INCHROOT} || export HOME=/build
-${INCHROOT} || cd /build
+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)
-${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
-)
+# Boring/mundane functions #####################################################
-distcc_start() {
+# Usage: exit_copy $copydir $src_owner
+# End immediately, but copy log files out
+exit_copy() {
local copydir=$1
- # Because /{,usr/}{,s}bin are all symlinked together for
- # fileystem 2013.05-2 and up, I can take shortcuts when checking for
- # existance of programs.
- if [[ -f "$copydir/bin/socat" && -f "$copydir/bin/distcc" ]]; then
- local home=$LIBREHOME
- $INCHROOT || home="$copydir/build"
-
- cp -a "$(which distcc-tool)" "$copydir/distcc-tool"
-
- mkdir -p "$home/.ssh"
-
- printf '%s\n' \
- '/distcc-tool idaemon "$DISTCC_HOSTS" &' \
- 'DISTCC_HOSTS="$(/distcc-tool rewrite "$DISTCC_HOSTS")"' \
- > "$home/.makepkg.conf"
-
- printf '%s\n' \
- 'Host *' \
- ' ProxyCommand /distcc-tool client %h %p' \
- > "$home/.ssh/config"
-
- distcc-tool odaemon "$copydir" &
- echo $! > "$copydir/distcc-tool.pid"
+ local src_owner=$2
+ if ! $INCHROOT; then
+ msg "Copying log and package files out of the chroot..."
+ move_products "$copydir" "$src_owner"
fi
}
-distcc_stop() {
- local copydir=$1
- local home=$LIBREHOME
- $INCHROOT || home="$copydir/build"
- if [[ -f "$copydir/distcc-tool.pid" ]]; then
-
- odaemon=$(cat "$copydir/distcc-tool.pid")
- kill -- $odaemon
-
- rm -f -- \
- "$copydir/distcc-tool" \
- "$home/.makepkg.conf" \
- "$home/.ssh/config" \
- "$copydir/distcc-tool.pid"
+# Usage; run_hook $hookname $args...
+run_hook() {
+ local hookname=$1; shift
+ local hookvar="hook_${hookname}[@]"
+ local fails=()
+ msg "Running hook: %s" "$hookname"
+ for hook in "${!hookvar}"; do
+ msg2 'hook: %s' "$hook"
+ "$hook" "$@" || { error "result: %s" $?; fails+=("$hook"); }
+ done
+ if [[ ${#fails[@]} -gt 0 ]]; then
+ error "Failure(s) in %s: %s" "$hookname" "${fails[*]}"
+ return 1
fi
+ return 0
}
# Usage: add_to_local_repo $copydir $pkgfiles...
-add_to_local_repo() (
- set +euE
- . $makechrootpkg
- 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
- . $makechrootpkg
- chroot_copy_in "$@"
-)
-
-# Usage: chroot_copy_out $copydir $owner
-# Environment:
-# - $SRCDEST is set
-# - $PKGDEST is set
-chroot_copy_out() (
- set +euE
- . $makechrootpkg
- 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
- . $makechrootpkg
- 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
- local PACKAGER="$(get_conf_makepkg PACKAGER '')"
- if [[ -n $PACKAGER ]]; then
- MAKEPKG_CONF="$copydir/etc/makepkg.conf" set_conf_makepkg PACKAGER "$PACKAGER"
- fi
- unset PACKAGER
-
- if ! grep -q '^\[repo\]' "$copydir/etc/pacman.conf"; then
- cat >> "$copydir/etc/pacman.conf" <<EOF
-[repo]
-SigLevel = Optional TrustAll
-Server = file:///repo
-EOF
- fi
-
- chroot_let_nobody_use_pacman "$copydir"
+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
}
-# Core functions ###############################################################
+build() (
+ local copydir=$1; shift
+ local cmd=(/chrootbuild "$@")
-# Usage: extract
-# Extracts the sources (`makepkg -o`)
-# Environment:
-# - $INCHROOT is set
-# - $copydir is set
-# - $LIBREUSER is set
-extract() (
- local user=$LIBREUSER
- $INCHROOT || user=nobody
+ run_hook pre_build "$copydir"
+ trap "run_hook post_build '$copydir'" EXIT
- local clean
+ local netflag=''
if $INCHROOT; then
- clean=chcleanup
+ ! $NONET || netflag='-n'
+ unshare $netflag -- "${cmd[@]}"
else
- trap "rm -f '$copydir/clean'" EXIT
- cp -a "$(which chcleanup)" "${copydir}/clean"
- clean=/clean
+ ! $NONET || netflag='-N'
+ librechroot $netflag \
+ -r "$PWD:/startdir_host" \
+ -r "$SRCDEST:/srcdest_host" \
+ -l "$copydir" \
+ run "${cmd[@]}"
fi
-
- run "$copydir" "${clean} && sudo -u ${user} -- makepkg ${makepkg_args} -o"
)
-# Usage: build
-# Builds the package (`makepkg -e`)
-# Environment:
-# - $INCHROOT is set
-# - $copydir is set
-# - $LIBREUSER is set
-build() {
- local user=$LIBREUSER
- $INCHROOT || user=nobody
-
- if $NONET; then
- run -N "$copydir" "sudo -u ${user} -- makepkg ${makepkg_args} -e"
- else
- run "$copydir" "sudo -u ${user} -- makepkg ${makepkg_args} -e"
- fi
-}
-
-# 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 #############################################################
usage() {
@@ -291,59 +134,65 @@ usage() {
echo
print 'Options:'
flag "-n <$(_ CHROOT)>" 'Name of the chroot to use'
- flag "-l <$(_ COPY)>" 'Name of, or absolute path to, the 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 "-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'
}
-# Globals: $CHROOTDIR, $CHROOT, $COPY and $copydir
-# Globals: $makepkg_args, $INCHROOT
-main() {
- # Parse command line ###################################################
-
- COPY=$LIBREUSER
- [[ $COPY != root ]] || COPY=copy
+# 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
+}
- makepkg_args='-s --noconfirm -L '
+main() {
+ # Initial variable values ##############################################
+ local copy=$([[ $LIBREUSER == root ]] && echo copy || echo "$LIBREUSER")
+ local makepkg_args=(-s --noconfirm -L)
local repack=false
+ local chroot=''
- INCHROOT=false
- if [[ -f /.arch-chroot ]]; then
- INCHROOT=true
- fi
-
- NONET=true
- while getopts 'n:l:NRh' arg ; do
- case "${arg}" in
- n) CHROOT=$OPTARG;;
- l) COPY=$OPTARG;;
+ # 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";;
+ R) repack=true; makepkg_args+=(-R);;
h) usage; return 0;;
- *) usage; return 1;;
+ *) usage >&2; return 1;;
esac
done
shift $(($OPTIND - 1))
# Pass all arguments after -- right to makepkg
- makepkg_args+=" $*"
+ makepkg_args+=("$@")
+ # Resolve the chroot path ##############################################
+ local copydir
if $INCHROOT; then
copydir='/'
else
+ load_files chroot
check_vars chroot CHROOTDIR CHROOT
- if [[ ${COPY:0:1} = / ]]; then
- copydir=$COPY
+ [[ -z ${chroot} ]] || CHROOT=$chroot
+ if [[ ${copy:0:1} = / ]]; then
+ copydir=$copy
else
- copydir="${CHROOTDIR}/${CHROOT}/${COPY}"
+ copydir="${CHROOTDIR}/${CHROOT}/${copy}"
fi
+ unset CHROOTDIR CHROOTEXTRAPKG
fi
+ unset chroot
- # Init #################################################################
+ # Quick sanity check ###################################################
if (( EUID )); then
- error "This script must be run as root"
+ error "This program must be run as root"
exit 1
fi
@@ -353,36 +202,47 @@ main() {
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: [%s]" "$COPY"
+ # 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 '')"
- # 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
+ # OK, we are starting now ##############################################
- $INCHROOT || chroot_init "$copydir" "$repack"
-
- check_pkgbuild
- $INCHROOT || chroot_copy_in "$copydir"
- $repack || extract
- check_src
- build
- check_pkg
+ 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
+ librechroot -n "$CHROOT" -l "$copy" make
+ 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
+ run_hook check_pkgbuild
+ download_sources "$copydir" "$LIBREUSER"
+ prepare_chroot "$copydir" "$LIBREHOME" "$repack" false
+ clean_chroot "$copydir"
+
+ # Build
+ trap "exit_copy '$copydir' '$LIBREUSER'" EXIT
+ warning 'Entering build...'
+ build "$copydir" "${makepkg_args[@]}"
+ # Post-build
+ warning 'Entering hook check_pkg...'
+ run_hook check_pkg
+ warning 'Entering add_to_local_repo ...'
add_to_local_repo "$copydir" "$copydir"/pkgdest/*.pkg.tar*
- $INCHROOT || chroot_copy_out "$copydir" "$LIBREUSER"
}
main "$@"
diff --git a/src/chroot-tools/makechrootpkg.sh.patch b/src/chroot-tools/makechrootpkg.sh.patch
index 505b96a..f5b8ed7 100644
--- a/src/chroot-tools/makechrootpkg.sh.patch
+++ b/src/chroot-tools/makechrootpkg.sh.patch
@@ -1,52 +1,81 @@
---- makechrootpkg.sh.in
-+++ makechrootpkg.sh.ugly
-@@ -12,12 +12,7 @@
+--- makechrootpkg.sh.in 2013-09-08 23:01:20.000000000 -0400
++++ makechrootpkg.sh.ugly 2013-09-09 15:43:06.000000000 -0400
+@@ -12,6 +12,7 @@
shopt -s nullglob
--# So that usage conflicts between upstream and -par mkarchroot don't get hidden
--# silently in a merge.
--archroot() {
-- mkarchroot "$@"
--}
--
+init_variables() {
- makepkg_args='-s --noconfirm -L'
+ _makepkg_args=(-s --noconfirm -L --holdver)
+ makepkg_args=("${_makepkg_args[@]}")
repack=false
- update_first=false
-@@ -28,13 +23,14 @@
- temp_chroot=false
- chrootdir=
- passeddir=
--declare -a install_pkgs
--declare -i ret=0
-+declare -ag install_pkgs
-+declare -ig ret=0
+@@ -26,9 +27,10 @@
+ declare -i ret=0
copy=$USER
- [[ -n $SUDO_USER ]] && copy=$SUDO_USER
+-[[ -n $SUDO_USER ]] && copy=$SUDO_USER
++[[ -n ${SUDO_USER:-} ]] && copy=$SUDO_USER
[[ -z "$copy" || $copy = root ]] && copy=copy
src_owner=${SUDO_USER:-$USER}
+}
usage() {
echo "Usage: ${0##*/} [options] -r <chrootdir> [--] [makepkg args]"
-@@ -69,6 +65,7 @@
+@@ -62,6 +64,7 @@
exit 1
}
+parse_options_init() {
- while getopts 'hcudr:I:l:nT' arg; do
+ while getopts 'hcur:I:l:nT' arg; do
case "$arg" in
h) usage ;;
-@@ -129,8 +126,20 @@
- # Note this is the same FD number as in mkarchroot
- lock_open_write 9 "$copydir" \
- "Waiting for existing lock on chroot copy to be released: [$copy]"
+@@ -86,9 +89,6 @@
+ [[ ! -d $chrootdir ]] && die "No chroot dir defined, or invalid path '%s'" "$passeddir"
+ [[ ! -d $chrootdir/root ]] && die "Missing chroot dir root directory. Try using: mkarchroot %s/root base-devel" "$chrootdir"
+
+-# Detect chrootdir filesystem type
+-chroottype=$(stat -f -c %T "$chrootdir")
+-
+ if [[ ${copy:0:1} = / ]]; then
+ copydir=$copy
+ else
+@@ -103,30 +103,47 @@
+ repack=true
+ fi
+
+-if [[ -n $SUDO_USER ]]; then
++if [[ -n ${SUDO_USER:-} ]]; then
+ USER_HOME=$(eval echo ~$SUDO_USER)
+ else
+ USER_HOME=$HOME
+ fi
+}
-+
-+# Usage: chroot_sync $CHROOTDIR/$CHROOT [$CHROOTCOPY|$copydir]
-+chroot_sync() {
+
+ # {{{ functions
++# Usage: load_vars $makepkg_conf
++# Globals:
++# - SRCDEST
++# - LOGDEST
++# - PKGDEST
++# - MAKEFLAGS
++# - PACKAGER
+ load_vars() {
+ local makepkg_conf="$1" var
+
+ [[ -f $makepkg_conf ]] || return 1
+
+ for var in {SRC,PKG,LOG}DEST MAKEFLAGS PACKAGER; do
+- [[ -z ${!var} ]] && eval $(grep "^${var}=" "$makepkg_conf")
++ [[ -z ${!var:-} ]] && eval $(grep "^${var}=" "$makepkg_conf")
+ done
+
+ return 0
+ }
+
+-create_chroot() {
+- # Lock the chroot we want to use. We'll keep this lock until we exit.
+- lock 9 "$copydir.lock" "Locking chroot copy [%s]" "$copy"
++# Usage: sync_chroot $CHROOTDIR/$CHROOT <$CHROOTCOPY|$copydir>
++sync_chroot() {
+ local chrootdir=$1
+ local copy=$2
+ local copydir=''
@@ -55,221 +84,220 @@
+ else
+ copydir="$chrootdir/$copy"
+ fi
++
++ # Detect chrootdir filesystem type
+ local chroottype=$(stat -f -c %T "$chrootdir")
--if [[ ! -d $copydir ]] || $clean_first; then
- # Get a read lock on the root chroot to make
- # sure we don't clone a half-updated chroot
- lock_open_read 8 "$chrootdir/root" \
-@@ -152,9 +161,16 @@
+- if [[ ! -d $copydir ]] || $clean_first; then
+ # Get a read lock on the root chroot to make
+ # sure we don't clone a half-updated chroot
+ slock 8 "$chrootdir/root.lock" "Locking clean chroot"
+@@ -147,10 +164,15 @@
- # Drop the read lock again
- lock_close 8
--fi
-+}
+ # Drop the read lock again
+ lock_close 8
+- fi
+ }
+
+-clean_temporary() {
++# Usage: delete_chroot $copydir [$copy]
++delete_chroot() {
++ local copydir=$1
++ local copy=${2:-$copydir}
++ # Detect chrootdir filesystem type
++ local chroottype=$(stat -f -c %T "$copydir")
+
-+# Usage: chroot_install_pkgs $copydir $pkgs...
-+chroot_install_pkgs() {
+ stat_busy "Removing temporary copy [%s]" "$copy"
+ if [[ "$chroottype" == btrfs ]]; then
+ btrfs subvolume delete "$copydir" >/dev/null ||
+@@ -166,9 +188,14 @@
+ stat_done
+ }
+
++# Usage: install_packages $copydir $pkgs...
+ install_packages() {
+ local copydir=$1
-+ shift
++ local install_pkgs=("${@:2}")
+ declare -i ret=0
-+ declare -a install_pkgs=("$@")
-+ local pkgname
+ local pkgname
--if [[ -n "${install_pkgs[*]}" ]]; then
++ local install_pkg
for install_pkg in "${install_pkgs[@]}"; do
pkgname="${install_pkg##*/}"
cp "$install_pkg" "$copydir/$pkgname"
-@@ -165,10 +181,10 @@
+@@ -179,11 +206,19 @@
rm "$copydir/$pkgname"
done
-- # If there is no PKGBUILD we have done
+- # If there is no PKGBUILD we are done
- [[ -f PKGBUILD ]] || exit $ret
--fi
+ return $ret
-+}
+ }
-+func1() {
- $update_first && archroot -u "$copydir"
++# Usage: prepare_chroot $copydir $HOME $repack $run_namcap
++# Globals:
++# - MAKEFLAGS
++# - PACKAGER
+ prepare_chroot() {
++ local copydir=$1
++ local USER_HOME=$2
++ local repack=$3
++ local run_namcap=$4
++
+ $repack || rm -rf "$copydir/build"
- mkdir -p "$copydir/build"
-@@ -230,14 +246,24 @@
- # Set target CARCH as it might be used within the PKGBUILD to select correct sources
- eval $(grep '^CARCH=' "$copydir/etc/makepkg.conf")
- export CARCH
-+}
+ mkdir -p "$copydir/build"
+@@ -217,12 +252,12 @@
-+# Usage: chroot_copy_in $copydir
-+# Environment:
-+# - In the dirctory of a PKGBUILD
-+# - $SRCDEST is set
-+chroot_copy_in() {
-+local copydir=$1
- # Copy PKGBUILD and sources
--cp PKGBUILD "$copydir/build/"
-+for recipe in PKGBUILD SRCBUILD; do
-+if [[ -f $recipe ]]; then
-+cp $recipe "$copydir/build/"
- (
-- source PKGBUILD
-- for file in "${source[@]}"; do
-+ source $recipe
-+ for file in "${source[@]}" "${mksource[@]}"; do
- file="${file%%::*}"
- file="${file##*://*/}"
-+ file="${file##*://}"
- if [[ -f $file ]]; then
- cp "$file" "$copydir/srcdest/"
- elif [[ -f $SRCDEST/$file ]]; then
-@@ -251,18 +277,30 @@
- # evaluate any bash variables used
- eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
- [[ -f $file ]] && cp "$file" "$copydir/build/"
-- done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD)
-+ done < <(sed -n "s/^[[:space:]]*$i=//p" $recipe)
- done
- )
-+fi
-+done
+ chown -R nobody "$copydir"/{build,pkgdest,logdest,srcdest,startdir}
- chown -R nobody "$copydir"/{build,pkgdest,srcdest}
-+}
+- if [[ -n $MAKEFLAGS ]]; then
++ if [[ -n ${MAKEFLAGS:-} ]]; then
+ sed -i '/^MAKEFLAGS=/d' "$copydir/etc/makepkg.conf"
+ echo "MAKEFLAGS='${MAKEFLAGS}'" >> "$copydir/etc/makepkg.conf"
+ fi
-+# Usage: chroot_let_nobody_use_pacman $copydir
-+chroot_let_nobody_use_pacman() {
-+local copydir=$1
- 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"
-+}
+- if [[ -n $PACKAGER ]]; then
++ if [[ -n ${PACKAGER:-} ]]; then
+ sed -i '/^PACKAGER=/d' "$copydir/etc/makepkg.conf"
+ echo "PACKAGER='${PACKAGER}'" >> "$copydir/etc/makepkg.conf"
+ fi
+@@ -235,6 +270,14 @@
+ chmod 440 "$copydir/etc/sudoers.d/nobody-pacman"
+ fi
-+# Usage: chroot_build $copydir $makepkg_args $run_namcap
-+chroot_build() {
-+local copydir=$1
-+local makepkg_args=$2
-+local run_namcap=$3
- # This is a little gross, but this way the script is recreated every time in the
- # working copy
- cat >"$copydir/chrootbuild" <<EOF
-@@ -284,37 +322,62 @@
- exit 0
- EOF
- chmod +x "$copydir/chrootbuild"
-+archroot -r "$copydir" "/chrootbuild"
-+}
++ if ! grep -q '^\[repo\]' "$copydir/etc/pacman.conf"; then
++ cat >> "$copydir/etc/pacman.conf" <<EOF
++[repo]
++SigLevel = Optional TrustAll
++Server = file:///repo
++EOF
++ fi
++
+ # This is a little gross, but this way the script is recreated every time in the
+ # working copy
+ printf $'#!/bin/bash\n%s\n_chrootbuild %q "$@"' "$(declare -f _chrootbuild)" \
+@@ -242,13 +285,19 @@
+ chmod +x "$copydir/chrootbuild"
+ }
--if archroot -r "$copydir" "/chrootbuild"; then
-+# Usage: chroot_add_to_local_repo $copydir $pkgfiles...
-+chroot_add_to_local_repo() {
-+ local copydir=$1; shift
- mkdir -p "$copydir/repo"
-- for pkgfile in "$copydir"/pkgdest/*.pkg.tar.?z; do
-- if $add_to_db; then
-+ for pkgfile in "$@"; do
- cp "$pkgfile" "$copydir/repo"
- pushd "$copydir/repo" >/dev/null
- repo-add repo.db.tar.gz "${pkgfile##*/}"
- popd >/dev/null
-- fi
-+ done
-+}
++# Usage: download_sources $copydir $src_owner
++# Globals:
++# - SRCDEST
+ download_sources() {
++ local copydir=$1
++ local src_owner=$2
++
+ local builddir="$(mktemp -d)"
+ chmod 1777 "$builddir"
+
+ # Ensure sources are downloaded
+- if [[ -n $SUDO_USER ]]; then
+- sudo -u $SUDO_USER env SRCDEST="$SRCDEST" BUILDDIR="$builddir" \
++ if [[ $USER != $src_owner ]]; then
++ sudo -u $src_owner env SRCDEST="$SRCDEST" BUILDDIR="$builddir" \
+ makepkg --config="$copydir/etc/makepkg.conf" --verifysource -o
+ else
+ ( export SRCDEST BUILDDIR="$builddir"
+@@ -258,7 +307,7 @@
+ (( $? != 0 )) && die "Could not download sources."
+
+ # Clean up garbage from verifysource
+- rm -rf $builddir
++ rm -rf "$builddir"
+ }
+
+ _chrootbuild() {
+@@ -295,6 +344,7 @@
-+# Usage: chroot_copy_out_pkgs $copydir $user
-+# Environment:
-+# - $PKGDEST is set
-+chroot_copy_out_pkgs() {
+ # Safety check
+ if [[ ! -w PKGBUILD ]]; then
++ # XXX: internationalize this message
+ echo "Can't write to PKGBUILD!"
+ exit 1
+ fi
+@@ -312,12 +362,24 @@
+ exit 0
+ }
+
++# Usage: move_products $copydir $owner
++# Globals:
++# - PKGDEST
++# - LOGDEST
+ move_products() {
+ local copydir=$1
+ local src_owner=$2
-+ for pkgfile in "$copydir"/pkgdest/*.pkg.tar*; do
++
++ local pkgfile
+ for pkgfile in "$copydir"/pkgdest/*; do
chown "$src_owner" "$pkgfile"
mv "$pkgfile" "$PKGDEST"
-+ if [[ $PKGDEST != . ]]; then
++ if [[ $PKGDEST != $PWD ]]; then
+ ln -sf "$PKGDEST/${pkgfile##*/}" .
+ fi
done
-+}
-- for l in "$copydir"/build/*-{build,check,namcap,package,package_*}.log; do
-+# Usage: chroot_copy_out_pkgs $copydir $user
-+chroot_copy_out_logs() {
-+ local copydir=$1
-+ local src_owner=$2
-+ for l in "$copydir"/build/*.log; do
++ local l
+ for l in "$copydir"/logdest/*; do
chown "$src_owner" "$l"
- [[ -f $l ]] && mv "$l" .
- done
--else
-- # Just in case. We returned 1, make sure we fail
-- ret=1
--fi
-+}
+ mv "$l" "$LOGDEST"
+@@ -325,6 +387,10 @@
+ }
+ # }}}
-+# Usage: chroot_copy_out_srcs $copydir $user
-+# Environment:
-+# - $SRCDEST is set
-+chroot_copy_out_srcs() {
-+local copydir=$1
-+local src_owner=$2
- for f in "$copydir"/srcdest/*; do
- chown "$src_owner" "$f"
- mv "$f" "$SRCDEST"
- done
-+}
++main() {
++init_variables
++parse_options_init
++
+ umask 0022
--if $temp_chroot; then
-- stat_busy "Removing temporary directoy [$copy]"
-+# Usage: chroot_delete $copydir
-+chroot_delete() {
-+ local chroottype=$(stat -f -c %T "$copydir")
-+ stat_busy "Removing chroot copy [$copydir]"
- if [[ "$chroottype" == btrfs ]]; then
- btrfs subvolume delete "$copydir" >/dev/null ||
- die "Unable to delete subvolume $copydir"
-@@ -326,8 +389,39 @@
- # remove lock file
- rm --force "$copydir.lock"
- stat_done
--elif (( ret != 0 )); then
-- die "Build failed, check $copydir/build"
--else
-- true
--fi
-+}
+ load_vars /etc/makepkg.conf
+@@ -335,27 +401,37 @@
+ [[ -d $SRCDEST ]] || SRCDEST=$PWD
+ [[ -d $LOGDEST ]] || LOGDEST=$PWD
+
+-create_chroot
++# Lock the chroot we want to use. We'll keep this lock until we exit.
++lock 9 "$copydir.lock" "Locking chroot copy [%s]" "$copy"
+
-+main() {
-+ init_variables
-+ parse_options_init "$@"
-+ if [[ ! -d $copydir ]] || $clean_first; then
-+ chroot_sync "$chrootdir" "$copy"
-+ fi
-+ if [[ -n "${install_pkgs[*]}" ]]; then
-+ chroot_install_pkgs "$copydir" "${install_pkgs[@]}"
-+ ret=$?
-+ # If there is no PKGBUILD we have done
-+ [[ -f PKGBUILD ]] || exit $ret
-+ fi
-+ func1
-+ chroot_copy_in "$copydir"
-+ chroot_let_nobody_use_pacman "$copydir"
-+ chroot_build "$copydir" "$makepkg_args" "$run_namcap"
-+ func2
-+ if chroot_build; then
-+ chroot_add_to_local_repo "$copydir" "$copydir"/pkgdest/*.pkg.tar*
-+ chroot_copy_out_pkgs "$copydir" "$src_owner"
-+ chroot_copy_out_logs "$copydir" "$src_owner"
-+ else
-+ # Just in case. We returned 1, make sure we fail
-+ ret=1
-+ fi
-+ chroot_copy_out_srcs "$copydir" "$src_owner"
-+ if $temp_chroot; then
-+ chroot_delete "$copydir"
-+ elif (( ret != 0 )); then
-+ die "Build failed, check $copydir/build"
-+ else
-+ true
-+ fi
++if [[ ! -d $copydir ]] || $clean_first; then
++ sync_chroot "$chrootdir" "$copy"
++fi
+
+ $update_first && arch-nspawn "$copydir" pacman -Syu --noconfirm
+
+-[[ -n ${install_pkgs[*]} ]] && install_packages
++if [[ -n ${install_pkgs[*]:-} ]]; then
++ install_packages "$copydir" "${install_pkgs[@]}"
++ ret=$?
++ # If there is no PKGBUILD we have done
++ [[ -f PKGBUILD ]] || exit $ret
++fi
+
+-prepare_chroot
++prepare_chroot "$copydir" "$USER_HOME" "$repack"
+
+-download_sources
++download_sources "$copydir" "$src_owner"
+
+ if arch-nspawn "$copydir" \
+ --bind-ro="$PWD:/startdir_host" \
+ --bind-ro="$SRCDEST:/srcdest_host" \
+ /chrootbuild "${makepkg_args[@]}"
+ then
+- move_products
++ move_products "$copydir" "$src_owner"
+ else
+ (( ret += 1 ))
+ fi
+
+-$temp_chroot && clean_temporary
++$temp_chroot && delete_chroot "$copydir" "$copy"
+
+ if (( ret != 0 )); then
+ if $temp_chroot; then
+@@ -366,3 +442,4 @@
+ else
+ true
+ fi
+}