C_RED="$(echo -e '\e[31m')" C_GREEN="$(echo -e '\e[32m')" C_YELLOW="$(echo -e '\e[33m')" C_NORMAL="$(echo -e '\e[0m')" export DEBIAN_FRONTEND=noninteractive B_APT_UPDATED= progress () { echo "${C_GREEN}$1${C_NORMAL}" >&2 } note () { echo "${C_YELLOW}$1${C_NORMAL}" >&2 } warn () { echo "${C_RED}WARNING: $1${C_NORMAL}" >&2 } die () { echo "${C_RED}ERROR: $1${C_NORMAL}" >&2 exit 1 } update-pkgs () { if [ -z "$B_APT_UPDATED" ] ; then apt update B_APT_UPDATED=1 fi } install-pkgs () { update-pkgs apt install -y --no-install-recommends --no-install-suggests "$@" } install-config () { [ $# = 2 ] || die "Usage: install-config ( | /)" local S=$1 local T=$2 if [ ${T%/} != $T ] ; then T=$T$(basename $S) fi local B=$BUILD_CONFIG$T mkdir -p $(dirname $B) $(dirname $T) if [ -f $T ] ; then if [ ! -f $B.orig ] ; then echo "Backing up $T to $B.orig" cp $T $B.orig else echo "Backup of $T already present in $B.orig" fi fi if [ -f $S ] ; then # Just a new file: overwrite echo "Overwriting $T" cp $S $T cp $S $B.new elif [ -f $S.orig -a -f $S.new ] ; then # Try 3-way merge if cmp --quiet $S.new $T ; then warn "Skipping merge of $T: changes already present" else echo "Merging $T" if diff3 -m $S.new $S.orig $T >$B.new ; then cp $B.new $T else die "Merge failed, please review $B.new" fi fi else die "Do not know how to install config $T" fi } sed-config () { [ $# = 2 ] || die "Usage: sed-config " local T=$1 local SCRIPT=$2 local B=$BUILD_CONFIG$T mkdir -p $(dirname $B) [ -f $T ] || die "Want to sed $T, but it is missing" if [ ! -f $B.orig ] ; then echo "Backing up $T to $B.orig" cp $T $B.orig else echo "Backup of $T already present in $B.orig" fi sed -ri "$SCRIPT" $T cp $T $B.new } pipe-config () { [ $# = 1 ] || die "Usage: | pipe-config " local TMP=$(mktemp) cat >$TMP install-config $TMP $1 rm $TMP } rm-config () { [ $# = 1 ] || die "Usage: rm-config " local T=$1 local B=$BUILD_CONFIG$T if [ -f $T ] ; then if [ ! -f $B.orig ] ; then echo "Backing up $T to $B.orig" cp $T $B.orig fi echo "Removing $T" rm -f $T else echo "Wanted to remove $T, but it does not exist" fi } download () { [ $# = 3 ] || die "Usage: download " local URL=$1 local HTYPE=$2 local HASH=$3 local DEST=$(basename $URL) local CACHE=/root/.cache/download if [ -d $CACHE ] ; then if [ -f $CACHE/$DEST ] ; then echo "Using cached $DEST" else echo "Downloading $URL with caching" curl $URL >$CACHE/$DEST.tmp mv $CACHE/$DEST.tmp $CACHE/$DEST fi ln -s $CACHE/$DEST . else warn "Cache $CACHE not found: downloading directly" echo "Downloading $URL" curl $URL >$DEST fi local H=$(${HTYPE}sum $DEST | cut -d' ' -f1) [ $H == $HASH ] || die "Mismatched hash: got $H, want $HASH" }