From aaa68e49e8e5a68950a63b9aa4a8c1f6aed2e2d2 Mon Sep 17 00:00:00 2001
From: Pierre Schmitz <pierre@archlinux.de>
Date: Tue, 1 Nov 2011 15:33:08 +0100
Subject: [PATCH] Move common functions to a shared file

* common.sh is included on build time
* most functions are copied from makepkg
---
 Makefile         |   4 +-
 archbuild.in     |  14 +++---
 archco.in        |   5 +-
 archrelease.in   |  24 +++++----
 archrm.in        |   2 +
 checkpkg.in      |  27 ++++-------
 commitpkg.in     |  88 +++++++++++++--------------------
 find-libdeps.in  |  34 ++++---------
 finddeps.in      |   4 +-
 lddd.in          |   8 +--
 lib/common.sh    | 124 +++++++++++++++++++++++++++++++++++++++++++++++
 makechrootpkg.in |  30 +++++-------
 mkarchroot.in    |  31 +++++-------
 rebuildpkgs.in   |  28 +++++------
 14 files changed, 252 insertions(+), 171 deletions(-)
 create mode 100644 lib/common.sh

diff --git a/Makefile b/Makefile
index cd6cbda..d9c158d 100644
--- a/Makefile
+++ b/Makefile
@@ -50,9 +50,11 @@ ARCHBUILD_LINKS = \
 
 all: $(BINPROGS) $(SBINPROGS) bash_completion zsh_completion
 
+edit = sed -e "s|@pkgdatadir[@]|$(DESTDIR)$(PREFIX)/share/devtools|g"
+
 %: %.in
 	@echo "GEN $@"
-	@sed -e "s|@pkgdatadir[@]|$(DESTDIR)$(PREFIX)/share/devtools|g" "$<" >"$@"
+	@m4 -P $@.in | $(edit) >$@
 	@chmod a-w "$@"
 	@chmod +x "$@"
 
diff --git a/archbuild.in b/archbuild.in
index 5b5ab21..e3e5f13 100644
--- a/archbuild.in
+++ b/archbuild.in
@@ -1,6 +1,9 @@
 #!/bin/bash
 
-base_packages=(base base-devel sudo)
+m4_include(lib/common.sh)
+
+# FIXME: temporary added curl until pacman 4.0 moves to [core]
+base_packages=(base base-devel sudo curl)
 
 cmd="${0##*/}"
 if [[ "${cmd%%-*}" == 'multilib' ]]; then
@@ -31,16 +34,15 @@ while getopts 'cr:' arg; do
 done
 
 if [[ "$EUID" != '0' ]]; then
-	echo 'This script must be run as root.'
-	exit 1
+	die 'This script must be run as root.'
 fi
 
 if ${clean_first} || [[ ! -d "${chroots}/${repo}-${arch}" ]]; then
-	echo "Creating chroot for [${repo}] (${arch})..."
+	msg "Creating chroot for [${repo}] (${arch})..."
 
 	for copy in "${chroots}/${repo}-${arch}"/*; do
 		[[ -d $copy ]] || continue
-		echo "Deleting chroot copy '$(basename "${copy}")'..."
+		msg2 "Deleting chroot copy '$(basename "${copy}")'..."
 
 		# Lock the copy
 		exec 9>"${copy}.lock"
@@ -71,5 +73,5 @@ else
 		"${chroots}/${repo}-${arch}/root"
 fi
 
-echo "Building in chroot for [${repo}] (${arch})..."
+msg "Building in chroot for [${repo}] (${arch})..."
 setarch "${arch}" makechrootpkg -c -r "${chroots}/${repo}-${arch}"
diff --git a/archco.in b/archco.in
index 31134f4..a1e5f96 100644
--- a/archco.in
+++ b/archco.in
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+m4_include(lib/common.sh)
+
 scriptname=${0##*/}
 
 if [ "$1" = '' ]; then
@@ -13,8 +15,7 @@ case $scriptname in
 	communityco)
 		SVNURL="svn+ssh://aur.archlinux.org/srv/svn-packages";;
 	*)
-		echo "error: couldn't find svn url for $scriptname"
-		exit 1
+		die "error: couldn't find svn url for $scriptname"
 		;;
 esac
 
diff --git a/archrelease.in b/archrelease.in
index 2f7725e..6fccfc9 100644
--- a/archrelease.in
+++ b/archrelease.in
@@ -1,18 +1,16 @@
 #!/bin/bash
 
-abort() {
-	echo ${1:-'archrelease: Cancelled'}
-	exit 1
-}
+m4_include(lib/common.sh)
 
 if [[ -z $1 ]]; then
-	abort 'Usage: archrelease <repo>...'
+	echo 'Usage: archrelease <repo>...'
+	exit 1
 fi
 
 # TODO: validate repo is really repo-arch
 
 if [[ ! -f PKGBUILD ]]; then
-	abort 'archrelease: PKGBUILD not found'
+	die 'archrelease: PKGBUILD not found'
 fi
 
 trunk=${PWD##*/}
@@ -21,24 +19,24 @@ trunk=${PWD##*/}
 # such as 'gnome-unstable'
 IFS='/' read -r -d '' -a parts <<< "$PWD"
 if [[ "${parts[@]:(-2):1}" == "repos" ]]; then
-	abort 'archrelease: Should not be in repos dir (try from trunk/)'
+	die 'archrelease: Should not be in repos dir (try from trunk/)'
 fi
 unset parts
 
 if [[ $(svn status -q) ]]; then
-	abort 'archrelease: You have not committed your changes yet!'
+	die 'archrelease: You have not committed your changes yet!'
 fi
 
 pushd .. >/dev/null
 IFS=$'\n' read -r -d '' -a known_files < <(svn ls -r HEAD "$trunk")
 for file in "${known_files[@]}"; do
 	if [[ ${file:(-1)} = '/' ]]; then
-		abort "archrelease: subdirectories are not supported in package directories!"
+		die "archrelease: subdirectories are not supported in package directories!"
 	fi
 done
 
 for tag in "$@"; do
-	echo -n "copying ${trunk} to ${tag}..."
+	stat_busy "copying ${trunk} to ${tag}"
 
 	if [[ -d repos/$tag ]]; then
 		declare -a trash
@@ -55,12 +53,12 @@ for tag in "$@"; do
 	# copy all files at once from trunk to the subdirectory in repos/
 	svn copy -q -r HEAD ${known_files[@]/#/$trunk/} "repos/$tag/"
 
-	echo 'done'
+	stat_done
 done
 
-echo -n "releasing package..."
+stat_busy "releasing package"
 printf -v tag_list ", %s" "$@"; tag_list="${tag_list#, }"
 svn commit -q -m "archrelease: copy ${trunk} to $tag_list" || abort
-echo 'done'
+stat_done
 
 popd >/dev/null
diff --git a/archrm.in b/archrm.in
index 4a683f6..a4830ee 100644
--- a/archrm.in
+++ b/archrm.in
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+m4_include(lib/common.sh)
+
 if [ "$1" = '' ]; then
 	echo 'Usage: archrm <path to checkout>'
 	exit 1
diff --git a/checkpkg.in b/checkpkg.in
index cde3dc2..d3a63ba 100644
--- a/checkpkg.in
+++ b/checkpkg.in
@@ -1,11 +1,12 @@
 #!/bin/bash
 
+m4_include(lib/common.sh)
+
 # Source makepkg.conf; fail if it is not found
 if [[ -r '/etc/makepkg.conf' ]]; then
 	source '/etc/makepkg.conf'
 else
-	echo '/etc/makepkg.conf not found!'
-	exit 1
+	die '/etc/makepkg.conf not found!'
 fi
 
 # Source user-specific makepkg.conf overrides
@@ -14,8 +15,7 @@ if [[ -r ~/.makepkg.conf ]]; then
 fi
 
 if [[ ! -f PKGBUILD ]]; then
-	echo 'This must be run in the directory of a built package.'
-	exit 1
+	die 'This must be run in the directory of a built package.'
 fi
 
 . PKGBUILD
@@ -28,33 +28,26 @@ TEMPDIR=$(mktemp -d --tmpdir checkpkg-script.XXXX)
 cd "$TEMPDIR"
 
 for _pkgname in "${pkgname[@]}"; do
-	if [[ -z ${epoch} ]] ; then
-		pkgfile=${_pkgname}-${pkgver}-${pkgrel}-${CARCH}${PKGEXT}
-	else
-		pkgfile=${_pkgname}-${epoch}:${pkgver}-${pkgrel}-${CARCH}${PKGEXT}
-	fi
+	pkgfile=${_pkgname}-$(get_full_version $_pkgname)-${CARCH}${PKGEXT}
 
 	if [[ -f "$STARTDIR/$pkgfile" ]]; then
 		ln -s "$STARTDIR/$pkgfile" "$pkgfile"
 	elif [[ -f "$PKGDEST/$pkgfile" ]]; then
 		ln -s "$PKGDEST/$pkgfile" "$pkgfile"
 	else
-		echo "File \"$pkgfile\" doesn't exist"
-		exit 1
+		die "File \"$pkgfile\" doesn't exist"
 	fi
 
 	pkgurl=$(pacman -Spdd --print-format '%l' --noconfirm "$_pkgname")
 
 	if [[ $? -ne 0 ]]; then
-		echo "Couldn't download previous package for $_pkgname."
-		exit 1
+		die "Couldn't download previous package for $_pkgname."
 	fi
 
 	oldpkg=${pkgurl##*://*/}
 
 	if [[ ${oldpkg##*/} = ${pkgfile##*/} ]]; then
-		echo "The built package ($_pkgname) is the one in the repo right now!"
-		exit 1
+		die "The built package ($_pkgname) is the one in the repo right now!"
 	fi
 
 	if [[ ! -f $oldpkg ]]; then
@@ -83,8 +76,8 @@ for _pkgname in "${pkgname[@]}"; do
 		done
 		cd ..
 	else
-		echo "No soname differences for $_pkgname."
+		msg "No soname differences for $_pkgname."
 	fi
 done
 
-echo "Files saved to $TEMPDIR"
+msg "Files saved to $TEMPDIR"
diff --git a/commitpkg.in b/commitpkg.in
index 2d8b6c9..d7f7513 100644
--- a/commitpkg.in
+++ b/commitpkg.in
@@ -1,40 +1,22 @@
 #!/bin/bash
 
-abort() {
-	echo ${1:-'Cancelled'}
-	exit 1
-}
+m4_include(lib/common.sh)
 
 getpkgfile() {
 	if [[ ${#} -ne 1 ]]; then
-		echo 'ERROR: No canonical package found!' >&2
-		exit 1
+		die 'ERROR: No canonical package found!'
 	elif [ ! -f "${1}" ]; then
-		echo "ERROR: Package ${1} not found!" >&2
-		exit 1
+		die "ERROR: Package ${1} not found!"
 	fi
 
 	echo ${1}
 }
 
-##
-#  usage : get_full_version( $epoch, $pkgver, $pkgrel )
-# return : full version spec, including epoch (if necessary), pkgver, pkgrel
-##
-get_full_version() {
-	if [[ $1 -eq 0 ]]; then
-		# zero epoch case, don't include it in version
-		echo $2-$3
-	else
-		echo $1:$2-$3
-	fi
-}
-
 # Source makepkg.conf; fail if it is not found
 if [ -r '/etc/makepkg.conf' ]; then
 	source '/etc/makepkg.conf'
 else
-	abort '/etc/makepkg.conf not found!'
+	die '/etc/makepkg.conf not found!'
 fi
 
 # Source user-specific makepkg.conf overrides
@@ -45,7 +27,7 @@ fi
 cmd=${0##*/}
 
 if [ ! -f PKGBUILD ]; then
-	abort 'No PKGBUILD file'
+	die 'No PKGBUILD file'
 fi
 
 . PKGBUILD
@@ -54,7 +36,7 @@ pkgbase=${pkgbase:-$pkgname}
 case "$cmd" in
 	commitpkg)
 		if [ $# -eq 0 ]; then
-			abort 'usage: commitpkg <reponame> [-l limit] [-a arch] [commit message]'
+			die 'usage: commitpkg <reponame> [-l limit] [-a arch] [commit message]'
 		fi
 		repo="$1"
 		shift
@@ -63,7 +45,7 @@ case "$cmd" in
 		repo="${cmd%pkg}"
 		;;
 	*)
-		abort 'usage: commitpkg <reponame> [-l limit] [-a arch] [commit message]'
+		die 'usage: commitpkg <reponame> [-l limit] [-a arch] [commit message]'
 		;;
 esac
 
@@ -74,13 +56,13 @@ case "$repo" in
 		server='aur.archlinux.org' ;;
 	*)
 		server='gerolde.archlinux.org'
-		echo "Non-standard repository $repo in use, defaulting to server $server" ;;
+		msg "Non-standard repository $repo in use, defaulting to server $server" ;;
 esac
 
 # check if all local source files are under version control
 for s in "${source[@]}"; do
 	if [[ $s != *://* ]] && ! svn status -v "$s" | grep -q '^[ AMRX~]'; then
-		abort "$s is not under version control"
+		die "$s is not under version control"
 	fi
 done
 
@@ -90,7 +72,7 @@ for i in 'changelog' 'install'; do
 		# evaluate any bash variables used
 		eval file=\"$(sed 's/^\(['\''"]\)\(.*\)\1$/\2/' <<< "$file")\"
 		if ! svn status -v "${file}" | grep -q '^[ AMRX~]'; then
-			abort "${file} is not under version control"
+			die "${file} is not under version control"
 		fi
 	done < <(sed -n "s/^[[:space:]]*$i=//p" PKGBUILD)
 done
@@ -101,20 +83,19 @@ while getopts ':l:a:' flag; do
 	case $flag in
 		l) rsyncopts+=("--bwlimit=$2") ;;
 		a) commit_arch=$2 ;;
-		:) echo "option requires an argument -- '$OPTARG'" >&2
-			exit 1 ;;
-		\?) echo "invalid option -- '$OPTARG'" >&2
-			exit 1 ;;
+		:) die "option requires an argument -- '$OPTARG'" ;;
+		\?) die "invalid option -- '$OPTARG'" ;;
 	esac
 done
 shift $(( OPTIND - 1 ))
 
 if [ -n "$(svn status -q)" ]; then
-	echo -n 'committing changes to trunk...'
-	msgtemplate="upgpkg: $pkgbase $(get_full_version ${epoch:-0} $pkgver $pkgrel)"$'\n\n'
 	if [ -n "$1" ]; then
-		svn commit -q -m "${msgtemplate}${1}" || abort
+		stat_busy 'committing changes to trunk'
+		svn commit -q -m "${msgtemplate}${1}" || die
+		stat_done
 	else
+		msgtemplate="upgpkg: $pkgbase $(get_full_version)"$'\n\n'
 		msgfile="$(mktemp)"
 		echo "$msgtemplate" > "$msgfile"
 		if [ -n "$SVN_EDITOR" ]; then
@@ -126,23 +107,24 @@ if [ -n "$(svn status -q)" ]; then
 		else
 			vi "$msgfile"
 		fi
-		[ -s "$msgfile" ] || abort
-		svn commit -q -F "$msgfile" || abort
+		[ -s "$msgfile" ] || die
+		stat_busy 'committing changes to trunk'
+		svn commit -q -F "$msgfile" || die
 		unlink "$msgfile"
+		stat_done
 	fi
-	echo 'done'
 fi
 
 declare -a uploads
 
 for _arch in ${arch[@]}; do
 	if [ -n "$commit_arch" ] && [ "${_arch}" != "$commit_arch" ]; then
-		echo "skipping ${_arch}"
+		warning "skipping ${_arch}"
 		continue
 	fi
 
 	for _pkgname in ${pkgname[@]}; do
-		fullver=$(get_full_version ${epoch:-0} $pkgver $pkgrel)
+		fullver=$(get_full_version $_pkgname)
 		pkgfile=$(getpkgfile "$_pkgname-$fullver-${_arch}".pkg.tar.?z 2>/dev/null)
 		pkgdestfile=$(getpkgfile "$PKGDEST/$_pkgname-$fullver-${_arch}".pkg.tar.?z 2>/dev/null)
 
@@ -151,58 +133,58 @@ for _arch in ${arch[@]}; do
 		elif [ -f "$pkgdestfile" ]; then
 			pkgfile="$pkgdestfile"
 		else
-			echo "skipping ${_arch}"
+			warning "skipping ${_arch}"
 			continue 2
 		fi
 		uploads+=("$pkgfile")
 
 		sigfile="${pkgfile}.sig"
 		if [[ $SIGNPKG == 'y' ]] && [ ! -f "${sigfile}" ]; then
-			echo "Signing package ${pkgfile}..."
+			msg "Signing package ${pkgfile}..."
 			if [[ -n $GPGKEY ]]; then
 				SIGNWITHKEY="-u ${GPGKEY}"
 			fi
-			gpg --detach-sign --use-agent ${SIGNWITHKEY} "${pkgfile}" || abort
+			gpg --detach-sign --use-agent ${SIGNWITHKEY} "${pkgfile}" || die
 		fi
 		if [ -f "${sigfile}" ]; then
 			if ! gpg --verify "$sigfile" >/dev/null 2>&1; then
-				abort "Signature ${pkgfile}.sig is incorrect!"
+				die "Signature ${pkgfile}.sig is incorrect!"
 			fi
 			uploads+=("$sigfile")
 		else
-			abort "Signature ${pkgfile}.sig was not found"
+			die "Signature ${pkgfile}.sig was not found"
 		fi
 	done
 done
 
 if [[ -n $commit_arch ]]; then
-	archrelease "$repo-$commit_arch" || abort
+	archrelease "$repo-$commit_arch" || die
 else
-	archrelease "${arch[@]/#/$repo-}" || abort
+	archrelease "${arch[@]/#/$repo-}" || die
 fi
 
 if [[ ${#uploads[*]} -gt 0 ]]; then
-	echo 'uploading all package and signature files'
-	rsync "${rsyncopts[@]}" "${uploads[@]}" "$server:staging/$repo/" || abort
+	msg 'uploading all package and signature files'
+	rsync "${rsyncopts[@]}" "${uploads[@]}" "$server:staging/$repo/" || die
 fi
 
 if [ "${arch[*]}" == 'any' ]; then
 	if [ -d ../repos/$repo-i686 -a -d ../repos/$repo-x86_64 ]; then
 		pushd ../repos/ >/dev/null
-		echo "removing $repo-i686 and $repo-x86_64..."
+		stat_busy "removing $repo-i686 and $repo-x86_64"
 		svn rm $repo-i686
 		svn rm $repo-x86_64
 		svn commit -q -m "removed $repo-i686 and $repo-x86_64 for $pkgname"
-		echo 'done'
+		stat_done
 		popd >/dev/null
 	fi
 else
 	if [ -d ../repos/$repo-any ]; then
 		pushd ../repos/ >/dev/null
-		echo "removing $repo-any..."
+		stat_busy "removing $repo-any"
 		svn rm $repo-any
 		svn commit -q -m "removed $repo-any for $pkgname"
-		echo 'done'
+		stat_done
 		popd >/dev/null
 	fi
 fi
diff --git a/find-libdeps.in b/find-libdeps.in
index 8fff939..3f44903 100644
--- a/find-libdeps.in
+++ b/find-libdeps.in
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+m4_include(lib/common.sh)
+
 set -e
 
 IGNORE_INTERNAL=0
@@ -13,7 +15,7 @@ script_mode=${0##*/find-lib}
 
 case $script_mode in
 	deps|provides) true;;
-	*) echo "error: unknown mode $script_mode"; exit 1;;
+	*) die "unknown mode $script_mode" ;;
 esac
 
 if [[ -z $1 ]]; then
@@ -23,36 +25,19 @@ if [[ -z $1 ]]; then
 	exit 1
 fi
 
-cleanup() {
-	if [[ $tmpdir ]]; then
-		rm -rf $tmpdir;
-	fi
-}
-
 if [[ -d $1 ]]; then
-	cd $1
+	pushd $1 >/dev/null
 else
-	tmpdir=$(mktemp -d /tmp/find-sodeps.XXXXXXX)
-	trap "cleanup" EXIT INT TERM
+	setup_workdir
 
 	case ${script_mode} in
-		deps) bsdtar -C $tmpdir -xf "$1";;
-		provides)bsdtar -C $tmpdir -xf "$1" --include="*.so*";;
+		deps) bsdtar -C $WORKDIR -xf "$1";;
+		provides) bsdtar -C $WORKDIR -xf "$1" --include="*.so*";;
 	esac
 
-	cd $tmpdir
+	pushd $WORKDIR >/dev/null
 fi
 
-in_array() {
-	local needle=$1; shift
-	[[ -z $1 ]] && return 1 # Not Found
-	local item
-	for item in "$@"; do
-	[[ $item = $needle ]] && return 0 # Found
-	done
-	return 1 # Not Found
-}
-
 process_sofile() {
 	# extract the library name: libfoo.so
 	soname="${sofile%%\.so\.*}.so"
@@ -68,7 +53,7 @@ process_sofile() {
 	fi
 }
 
-case $script_mode in 
+case $script_mode in
 	deps) find_args="-perm -u+x";;
 	provides) find_args="-name *.so*";;
 esac
@@ -98,3 +83,4 @@ find . -type f $find_args | while read filename; do
 	fi
 done
 
+popd >/dev/null
diff --git a/finddeps.in b/finddeps.in
index 4651fd9..1526fb8 100644
--- a/finddeps.in
+++ b/finddeps.in
@@ -3,6 +3,8 @@
 # finddeps - find packages that depend on a given depname
 #
 
+m4_include(lib/common.sh)
+
 match=$1
 
 if [[ -z $match ]]; then
@@ -11,7 +13,7 @@ if [[ -z $match ]]; then
 	echo 'Find packages that depend on a given depname.'
 	echo 'Run this script from the top-level directory of your ABS tree.'
 	echo ''
-	exit 0
+	exit 1
 fi
 
 find . -type d | while read d; do
diff --git a/lddd.in b/lddd.in
index c011674..ae6c2b5 100644
--- a/lddd.in
+++ b/lddd.in
@@ -3,6 +3,8 @@
 # lddd - find broken library links on your machine
 #
 
+m4_include(lib/common.sh)
+
 ifs=$IFS
 IFS="${IFS}:"
 
@@ -11,10 +13,10 @@ extras=
 
 TEMPDIR=$(mktemp -d --tmpdir lddd-script.XXXX)
 
-echo 'Go out and drink some tea, this will take a while :) ...'
+msg 'Go out and drink some tea, this will take a while :) ...'
 #  Check ELF binaries in the PATH and specified dir trees.
 for tree in $PATH $libdirs $extras; do
-	echo DIR $tree
+	msg2 "DIR $tree"
 
 	#  Get list of files in tree.
 	files=$(find $tree -type f ! -name '*.a' ! -name '*.la' ! -name '*.py*' ! -name '*.txt' ! -name '*.h' ! -name '*.ttf' ! \
@@ -43,4 +45,4 @@ done
 # clean list
 sort -u $TEMPDIR/pacman.txt >> $TEMPDIR/possible-rebuilds.txt
 
-echo "Files saved to $TEMPDIR"
+msg "Files saved to $TEMPDIR"
diff --git a/lib/common.sh b/lib/common.sh
new file mode 100644
index 0000000..feb5080
--- /dev/null
+++ b/lib/common.sh
@@ -0,0 +1,124 @@
+# Avoid any encoding problems
+export LANG=C
+
+# check if messages are to be printed using color
+unset ALL_OFF BOLD BLUE GREEN RED YELLOW
+if [[ -t 2 ]]; then
+	# prefer terminal safe colored and bold text when tput is supported
+	if tput setaf 0 &>/dev/null; then
+		ALL_OFF="$(tput sgr0)"
+		BOLD="$(tput bold)"
+		BLUE="${BOLD}$(tput setaf 4)"
+		GREEN="${BOLD}$(tput setaf 2)"
+		RED="${BOLD}$(tput setaf 1)"
+		YELLOW="${BOLD}$(tput setaf 3)"
+	else
+		ALL_OFF="\e[1;0m"
+		BOLD="\e[1;1m"
+		BLUE="${BOLD}\e[1;34m"
+		GREEN="${BOLD}\e[1;32m"
+		RED="${BOLD}\e[1;31m"
+		YELLOW="${BOLD}\e[1;33m"
+	fi
+fi
+readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
+
+plain() {
+	local mesg=$1; shift
+	printf "${BOLD}    ${mesg}${ALL_OFF}\n" "$@" >&2
+}
+
+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
+}
+
+warning() {
+	local mesg=$1; shift
+	printf "${YELLOW}==> WARNING:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+}
+
+error() {
+	local mesg=$1; shift
+	printf "${RED}==> ERROR:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
+}
+
+stat_busy() {
+	local mesg=$1; shift
+	printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}...${ALL_OFF}" >&2
+}
+
+stat_done() {
+	printf "${BOLD}done${ALL_OFF}\n" >&2
+}
+
+setup_workdir() {
+	[ -z "$WORKDIR" ] && WORKDIR=$(mktemp -d /tmp/$(basename $0).XXXXXXXXXX)
+}
+
+cleanup() {
+	trap - EXIT INT QUIT TERM
+
+	[ -n "$WORKDIR" ] && rm -rf "$WORKDIR"
+	[ "$1" ] && exit $1
+}
+
+abort() {
+	msg 'Aborting...'
+	cleanup 0
+}
+
+die() {
+	error "$*"
+	cleanup 1
+}
+
+trap abort INT QUIT TERM HUP
+trap 'cleanup 0' EXIT
+
+##
+#  usage : in_array( $needle, $haystack )
+# return : 0 - found
+#          1 - not found
+##
+in_array() {
+	local needle=$1; shift
+	local item
+	for item in "$@"; do
+		[[ $item = $needle ]] && return 0 # Found
+	done
+	return 1 # Not Found
+}
+
+##
+#  usage : get_full_version( [$pkgname] )
+# return : full version spec, including epoch (if necessary), pkgver, pkgrel
+##
+get_full_version() {
+	# set defaults if they weren't specified in buildfile
+	pkgbase=${pkgbase:-${pkgname[0]}}
+	epoch=${epoch:-0}
+	if [[ -z $1 ]]; then
+		if [[ $epoch ]] && (( ! $epoch )); then
+			echo $pkgver-$pkgrel
+		else
+			echo $epoch:$pkgver-$pkgrel
+		fi
+	else
+		for i in pkgver pkgrel epoch; do
+			local indirect="${i}_override"
+			eval $(declare -f package_$1 | sed -n "s/\(^[[:space:]]*$i=\)/${i}_override=/p")
+			[[ -z ${!indirect} ]] && eval ${indirect}=\"${!i}\"
+		done
+		if (( ! $epoch_override )); then
+			echo $pkgver_override-$pkgrel_override
+		else
+			echo $epoch_override:$pkgver_override-$pkgrel_override
+		fi
+	fi
+}
diff --git a/makechrootpkg.in b/makechrootpkg.in
index b172bdf..ed71c1c 100644
--- a/makechrootpkg.in
+++ b/makechrootpkg.in
@@ -8,6 +8,8 @@
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 
+m4_include(lib/common.sh)
+
 shopt -s nullglob
 
 makepkg_args='-s --noconfirm -L'
@@ -91,24 +93,19 @@ for arg in ${*:$OPTIND}; do
 done
 
 if (( EUID )); then
-	echo 'This script must be run as root.'
-	exit 1
+	die 'This script must be run as root.'
 fi
 
 if [[ ! -f PKGBUILD && -z $install_pkg ]]; then
-	echo 'This must be run in a directory containing a PKGBUILD.'
-	exit 1
+	die 'This must be run in a directory containing a PKGBUILD.'
 fi
 
 if [[ ! -d $chrootdir ]]; then
-	echo "No chroot dir defined, or invalid path '$chrootdir'"
-	exit 1
+	die "No chroot dir defined, or invalid path '$chrootdir'"
 fi
 
 if [[ ! -d $chrootdir/root ]]; then
-	echo 'Missing chroot dir root directory.'
-	echo "Try using: mkarchroot $chrootdir/root base base-devel sudo"
-	exit 1
+	die "Missing chroot dir root directory. Try using: mkarchroot $chrootdir/root base base-devel sudo"
 fi
 
 umask 0022
@@ -117,9 +114,9 @@ umask 0022
 # Note this is the same FD number as in mkarchroot
 exec 9>"$copydir.lock"
 if ! flock -n 9; then
-	echo -n "locking chroot copy '$copy'..."
+	stat_busy "locking chroot copy '$copy'"
 	flock 9
-	echo "done"
+	stat_done
 fi
 
 if [[ ! -d $copydir ]] || $clean_first; then
@@ -128,12 +125,12 @@ if [[ ! -d $copydir ]] || $clean_first; then
 	exec 8>"$chrootdir/root.lock"
 
 	if ! flock -sn 8; then
-		echo -n "locking clean chroot..."
+		stat_busy "locking clean chroot"
 		flock -s 8
-		echo "done"
+		stat_done
 	fi
 
-	echo -n 'creating clean working copy...'
+	stat_busy 'creating clean working copy'
 	use_rsync=false
 	if type -P btrfs >/dev/null; then
 		[[ -d $copydir ]] && btrfs subvolume delete "$copydir" &>/dev/null
@@ -147,7 +144,7 @@ if [[ ! -d $copydir ]] || $clean_first; then
 		mkdir -p "$copydir"
 		rsync -a --delete -q -W -x "$chrootdir/root/" "$copydir"
 	fi
-	echo 'done'
+	stat_done
 
 	# Drop the read lock again
 	exec 8>&-
@@ -310,7 +307,6 @@ for f in "$copydir"/srcdest/*; do
 done
 
 if [[ -e $copydir/build/BUILD_FAILED ]]; then
-	echo "Build failed, check $copydir/build"
 	rm "$copydir/build/BUILD_FAILED"
-	exit 1
+	die "Build failed, check $copydir/build"
 fi
diff --git a/mkarchroot.in b/mkarchroot.in
index 0debb13..9361bef 100644
--- a/mkarchroot.in
+++ b/mkarchroot.in
@@ -8,6 +8,8 @@
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 
+m4_include(lib/common.sh)
+
 FORCE='n'
 RUN=''
 NOCOPY='n'
@@ -28,7 +30,7 @@ usage() {
 	echo '    -n            Do not copy config files into the chroot'
 	echo '    -c <dir>      Set pacman cache. Default: /var/cache/pacman/pkg'
 	echo '    -h            This message'
-	exit $1
+	exit 1
 }
 
 while getopts 'r:ufnhC:M:c:' arg; do
@@ -41,29 +43,26 @@ while getopts 'r:ufnhC:M:c:' arg; do
 		n) NOCOPY='y' ;;
 		c) cache_dir="$OPTARG" ;;
 		h|?) usage 0 ;;
-		*) echo "invalid argument '${arg}'"; usage 1 ;;
+		*) error "invalid argument '${arg}'"; usage ;;
 	esac
 done
 
 if [ "$EUID" != '0' ]; then
-	echo 'error: this script must be run as root.'
-	exit 1
+	die 'this script must be run as root.'
 fi
 
 shift $(($OPTIND - 1))
 
 if [ "$RUN" = '' -a $# -lt 2 ]; then
-	echo 'you must specify a directory and one or more packages'
-	usage 1
+	die 'you must specify a directory and one or more packages'
 elif [ $# -lt 1 ]; then
-	echo 'you must specify a directory'
-	usage 1
+	die 'you must specify a directory'
 fi
 
 working_dir="$(readlink -f ${1})"
 shift 1
 
-[ "${working_dir}" = '' ] && echo 'error: please specify a working directory' && usage 1
+[ "${working_dir}" = '' ] && die 'please specify a working directory'
 
 if [ -z "$cache_dir" ]; then
 	cache_conf=${working_dir}/etc/pacman.conf
@@ -150,9 +149,9 @@ chroot_lock () {
 
 	# Lock the chroot. Take note of the FD number.
 	if ! flock -n 9; then
-		echo -n "locking chroot..."
+		stat_busy "locking chroot"
 		flock 9
-		echo "done"
+		stat_done
 	fi
 }
 # }}}
@@ -162,9 +161,7 @@ if [ "$RUN" != "" ]; then
 	# run chroot {{{
 	#Sanity check
 	if [ ! -f "${working_dir}/.arch-chroot" ]; then
-		echo "error: '${working_dir}' does not appear to be a Arch chroot"
-		echo '       please build the image using mkarchroot'
-		exit 1
+		die "'${working_dir}' does not appear to be a Arch chroot"
 	fi
 
 	chroot_lock
@@ -177,8 +174,7 @@ if [ "$RUN" != "" ]; then
 else
 	# {{{ build chroot
 	if [ -e "${working_dir}" -a "${FORCE}" = "n" ]; then
-		echo "error: working dir '${working_dir}' already exists - try using -f"
-		exit 1
+		die "working dir '${working_dir}' already exists - try using -f"
 	fi
 
 	if { type -P btrfs && btrfs subvolume create "${working_dir}"; } &>/dev/null; then
@@ -202,8 +198,7 @@ else
 			op="${op}f"
 		fi
 		if ! pacman ${op} ${pacargs} $@; then
-			echo 'error: failed to install all packages'
-			exit 1
+			die 'failed to install all packages'
 		fi
 	fi
 
diff --git a/rebuildpkgs.in b/rebuildpkgs.in
index be279bb..d8fbdbe 100644
--- a/rebuildpkgs.in
+++ b/rebuildpkgs.in
@@ -9,6 +9,8 @@
 # Currently uses $(pwd)/rebuilds as the directory for rebuilding...
 # TODO make this work for community too
 
+m4_include(lib/common.sh)
+
 if [ $# -le 1 ]; then
 	echo "usage: $(basename $0) <chrootdir> <packages to rebuild>"
 	echo "  example: $(basename $0) ~/chroot readline bash foo bar baz"
@@ -19,15 +21,9 @@ fi
 if [ -r '/etc/makepkg.conf' ]; then
 	source '/etc/makepkg.conf'
 else
-	echo '/etc/makepkg.conf not found!'
-	exit 1
+	die '/etc/makepkg.conf not found!'
 fi
 
-die () {
-	echo $@ >&2
-	exit 1
-}
-
 bump_pkgrel() {
 	# Get the current pkgrel from SVN and update the working copy with it
 	# This prevents us from incrementing out of control :)
@@ -53,7 +49,7 @@ pkgs="$@"
 
 SVNPATH='svn+ssh://gerolde.archlinux.org/srv/svn-packages'
 
-echo ":: Work will be done in $(pwd)/rebuilds"
+msg "Work will be done in $(pwd)/rebuilds"
 
 REBUILD_ROOT="$(pwd)/rebuilds"
 mkdir -p "$REBUILD_ROOT"
@@ -65,11 +61,11 @@ FAILED=""
 for pkg in $pkgs; do
 	cd "$REBUILD_ROOT/svn-packages"
 
-	echo ":: Building '$pkg'"
+	msg2 "Building '$pkg'"
 	/usr/bin/svn update "$pkg"
 	if [ ! -d "$pkg/trunk" ]; then
 		FAILED="$FAILED $pkg"
-		echo ":: $pkg does not exist in SVN"
+		warning "$pkg does not exist in SVN"
 		continue
 	fi
 	cd "$pkg/trunk/"
@@ -78,24 +74,24 @@ for pkg in $pkgs; do
 
 	if ! sudo makechrootpkg -u -d -r "$chrootdir" -- --noconfirm; then
 		FAILED="$FAILED $pkg"
-		echo ":: $pkg Failed!"
+		error "$pkg Failed!"
 	else
 		pkgfile=$(pkg_from_pkgbuild)
 		if [ -e "$pkgfile" ]; then
-			echo ":: $pkg Complete"
+			msg2 "$pkg Complete"
 		else
 			FAILED="$FAILED $pkg"
-			echo ":: $pkg Failed, no package built!"
+			error "$pkg Failed, no package built!"
 		fi
 	fi
 done
 
 cd "$REBUILD_ROOT"
 if [ "$FAILED" != "" ]; then
-	echo 'Packages failed:'
+	msg 'Packages failed:'
 	for pkg in $FAILED; do
-		echo -e "\t$pkg"
+		msg2 "$pkg"
 	done
 fi
 
-echo 'SVN pkgbumps in svn-packages/ - commit when ready'
+msg 'SVN pkgbumps in svn-packages/ - commit when ready'
-- 
GitLab