Added local tool aptfile to use with apt based development installation. (#772)
This commit is contained in:
Executable
+292
@@ -0,0 +1,292 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
[[ $TRACE ]] && set -x && export TRACE=$TRACE
|
||||
|
||||
version() {
|
||||
local VERSION="dev-master"
|
||||
if [[ -f /var/lib/aptfile/VERSION ]]; then
|
||||
VERSION=$(cat /var/lib/aptfile/VERSION)
|
||||
fi
|
||||
echo "aptfile $VERSION"
|
||||
}
|
||||
|
||||
usage() {
|
||||
version
|
||||
echo "Usage: aptfile <aptfile>"
|
||||
}
|
||||
|
||||
help() {
|
||||
usage
|
||||
echo
|
||||
echo " <aptfile> is the path to a bash file with apt instructions."
|
||||
echo
|
||||
echo " -h, --help Display this help message"
|
||||
echo " -v, --version Display the version number"
|
||||
echo
|
||||
echo " For more information, see https://github.com/seatgeek/bash-aptfile"
|
||||
echo
|
||||
}
|
||||
|
||||
resolve_link() {
|
||||
$(type -p greadlink readlink | head -1) "$1"
|
||||
}
|
||||
|
||||
abs_dirname() {
|
||||
local cwd
|
||||
local path="$1"
|
||||
cwd="$(pwd)"
|
||||
|
||||
while [ -n "$path" ]; do
|
||||
cd "${path%/*}"
|
||||
local name="${path##*/}"
|
||||
path="$(resolve_link "$name" || true)"
|
||||
done
|
||||
|
||||
pwd
|
||||
cd "$cwd"
|
||||
}
|
||||
|
||||
expand_path() {
|
||||
{
|
||||
cd "$(dirname "$1")" 2>/dev/null
|
||||
local dirname="$PWD"
|
||||
cd "$OLDPWD"
|
||||
echo "$dirname/$(basename "$1")"
|
||||
} || echo "$1"
|
||||
}
|
||||
|
||||
options=()
|
||||
arguments=()
|
||||
for arg in "$@"; do
|
||||
if [ "${arg:0:1}" = "-" ]; then
|
||||
if [ "${arg:1:1}" = "-" ]; then
|
||||
options[${#options[*]}]="${arg:2}"
|
||||
else
|
||||
index=1
|
||||
while option="${arg:$index:1}"; do
|
||||
[ -n "$option" ] || break
|
||||
options[${#options[*]}]="$option"
|
||||
let index+=1
|
||||
done
|
||||
fi
|
||||
else
|
||||
arguments[${#arguments[*]}]="$arg"
|
||||
fi
|
||||
done
|
||||
|
||||
for option in "${options[@]}"; do
|
||||
case "$option" in
|
||||
"h" | "help")
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
"v" | "version")
|
||||
version
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "${#arguments[@]}" -eq 0 ]; then
|
||||
APTFILE_PATH=$(expand_path "aptfile")
|
||||
if [[ ! -f $APTFILE_PATH ]]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
set -- "aptfile" "$@"
|
||||
fi
|
||||
|
||||
export APTFILE_COLOR_OFF="\033[0m" # unsets color to term fg color
|
||||
export APTFILE_RED="\033[0;31m" # red
|
||||
export APTFILE_GREEN="\033[0;32m" # green
|
||||
export APTFILE_YELLOW="\033[0;33m" # yellow
|
||||
export APTFILE_MAGENTA="\033[0;35m" # magenta
|
||||
export APTFILE_CYAN="\033[0;36m" # cyan
|
||||
|
||||
logfile=$(basename "$0")
|
||||
TMP_APTFILE_LOGFILE=$(mktemp "/tmp/${logfile}.XXXXXX") || {
|
||||
log_fail "${APTFILE_RED}WARNING: Cannot create temp file using mktemp in /tmp dir ${APTFILE_COLOR_OFF}\n"
|
||||
}
|
||||
export TMP_APTFILE_LOGFILE="$TMP_APTFILE_LOGFILE"
|
||||
trap 'rm -rf "$TMP_APTFILE_LOGFILE" > /dev/null' INT TERM EXIT
|
||||
|
||||
log_fail() {
|
||||
[[ $TRACE ]] && set -x
|
||||
echo -e "${APTFILE_RED}$*${APTFILE_COLOR_OFF}" 1>&2
|
||||
[[ -f "$TMP_APTFILE_LOGFILE" ]] && echo -e "verbose logs:\n" 1>&2 && sed -e 's/^/ /' "$TMP_APTFILE_LOGFILE"
|
||||
exit 1
|
||||
}
|
||||
|
||||
log_info() {
|
||||
[[ $TRACE ]] && set -x
|
||||
echo -e "$@"
|
||||
}
|
||||
|
||||
update() {
|
||||
[[ $TRACE ]] && set -x
|
||||
log_info "Running update"
|
||||
apt-get update >"$TMP_APTFILE_LOGFILE" 2>&1
|
||||
[[ $? -eq 0 ]] || log_fail "Failed to run update"
|
||||
}
|
||||
|
||||
package() {
|
||||
[[ $TRACE ]] && set -x
|
||||
[[ -z $1 ]] && log_fail "Please specify a package to install"
|
||||
local pkg="$1"
|
||||
dpkg --force-confnew -s "$pkg" >"$TMP_APTFILE_LOGFILE" 2>&1 && log_info "${APTFILE_CYAN}[OK]${APTFILE_COLOR_OFF} package $pkg" && return 0
|
||||
apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -qq -y install "$pkg"
|
||||
[[ $? -eq 0 ]] || log_fail "${APTFILE_RED}[FAIL]${APTFILE_COLOR_OFF} package $pkg"
|
||||
log_info "${APTFILE_GREEN}[NEW]${APTFILE_COLOR_OFF} package $pkg"
|
||||
}
|
||||
|
||||
package_from_url() {
|
||||
[[ $TRACE ]] && set -x
|
||||
[[ -z $2 ]] && log_fail "Please specify a name and a download url to install the package from"
|
||||
local name=$1
|
||||
local url=$2
|
||||
if type curl >/dev/null 2>&1; then
|
||||
local dl_cmd="curl"
|
||||
local dl_options="-so"
|
||||
elif type wget >/dev/null 2>&1; then
|
||||
local dl_cmd="wget"
|
||||
local dl_options="-qO"
|
||||
else
|
||||
log_fail "Neither curl nor wget found. Unable to download $url"
|
||||
fi
|
||||
dpkg --force-confnew -s "$name" >"$TMP_APTFILE_LOGFILE" 2>&1 && log_info "${APTFILE_CYAN}[OK]${APTFILE_COLOR_OFF} package $name" && return 0
|
||||
tempdir=$(mktemp -d)
|
||||
$dl_cmd $dl_options $tempdir/${name}.deb $url \
|
||||
&& apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -qq -y install "$tempdir/${name}.deb"
|
||||
if [[ $? -ne 0 ]]; then
|
||||
rm -r $tempdir
|
||||
log_fail "${APTFILE_RED}[FAIL]${APTFILE_COLOR_OFF} package $name"
|
||||
fi
|
||||
rm -r $tempdir
|
||||
log_info "${APTFILE_GREEN}[NEW]${APTFILE_COLOR_OFF} package $name"
|
||||
}
|
||||
|
||||
packagelist() {
|
||||
[[ $TRACE ]] && set -x
|
||||
[[ -z $1 ]] && log_fail "Please specify at least one package to install"
|
||||
local input_packages=$@
|
||||
local install_packages=()
|
||||
for pkg in $input_packages; do
|
||||
dpkg --force-confnew -s "$pkg" >"$TMP_APTFILE_LOGFILE" 2>&1 && log_info "${APTFILE_CYAN}[OK]${APTFILE_COLOR_OFF} package $pkg" && continue
|
||||
install_packages+=($pkg)
|
||||
done
|
||||
if [[ ${#install_packages[@]} -gt 0 ]]; then
|
||||
apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -qq -y install ${install_packages[@]}
|
||||
[[ $? -eq 0 ]] || log_fail "${APTFILE_RED}[FAIL]${APTFILE_COLOR_OFF} packages ${install_packages[@]}"
|
||||
log_info "${APTFILE_GREEN}[NEW]${APTFILE_COLOR_OFF} packages ${install_packages[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
ppa() {
|
||||
[[ $TRACE ]] && set -x
|
||||
[[ -z $1 ]] && log_fail "Please specify a repository to setup"
|
||||
local repo="$1"
|
||||
if [[ -d /etc/apt/sources.list.d/ ]]; then
|
||||
grep ^ /etc/apt/sources.list /etc/apt/sources.list.d/* | grep -q "$repo" && log_info "${APTFILE_CYAN}[OK]${APTFILE_COLOR_OFF} ppa $repo" && return 0
|
||||
fi
|
||||
repository "ppa:$1"
|
||||
}
|
||||
|
||||
repository() {
|
||||
[[ $TRACE ]] && set -x
|
||||
[[ -z $1 ]] && log_fail "Please specify a repository to setup"
|
||||
local repo="$1"
|
||||
if [[ -d /etc/apt/sources.list.d/ ]]; then
|
||||
grep ^ /etc/apt/sources.list /etc/apt/sources.list.d/* | grep -Fq "$repo" && log_info "${APTFILE_CYAN}[OK]${APTFILE_COLOR_OFF} repository $repo" && return 0
|
||||
fi
|
||||
add-apt-repository -y "$repo" >"$TMP_APTFILE_LOGFILE" 2>&1
|
||||
[[ $? -eq 0 ]] || log_fail "${APTFILE_RED}[FAIL]${APTFILE_COLOR_OFF} repository $pkg"
|
||||
update
|
||||
log_info "${APTFILE_GREEN}[NEW]${APTFILE_COLOR_OFF} repository $repo"
|
||||
}
|
||||
|
||||
repository_file() {
|
||||
[[ $TRACE ]] && set -x
|
||||
[[ -z $2 ]] && log_fail "Please specify a filename and sourceline to setup"
|
||||
local repofile="$1"
|
||||
local repo="$2"
|
||||
# sourceline is not a complete repo configuration, needs modifying
|
||||
# i.e. not sourceline="deb http://domain.invalid/debian buster main extra"
|
||||
if [[ "$repo" != "deb "* ]]; then
|
||||
releasename=$(lsb_release -sc)
|
||||
if [[ "$repo" == *" "* ]]; then
|
||||
# Components given in sourceline, adding suite
|
||||
# i.e. sourceline="http://domain.invalid/debian main"
|
||||
repo="deb ${repo/ / $releasename }"
|
||||
else
|
||||
# only URL given, adding suite and component
|
||||
# i.e. sourceline="http://domain.invalid/debian"
|
||||
repo="deb ${repo} $releasename main"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$repofile" != *.list ]]; then
|
||||
# Adding extension to enable parsing file
|
||||
repofile=${repofile}.list
|
||||
fi
|
||||
# Adding path
|
||||
repofile="/etc/apt/sources.list.d/$repofile"
|
||||
|
||||
[[ -d "/etc/apt/sources.list.d" ]] || mkdir -p /etc/apt/sources.list.d
|
||||
|
||||
grep ^ /etc/apt/sources.list /etc/apt/sources.list.d/* | grep -Fq "$repo" && log_info "${APTFILE_CYAN}[OK]${APTFILE_COLOR_OFF} repository $repo" && return 0
|
||||
|
||||
echo "Writing '$repo' to file '$repofile'" >"$TMP_APTFILE_LOGFILE"
|
||||
echo "$repo" >"$repofile" 2>>"$TMP_APTFILE_LOGFILE"
|
||||
[[ $? -eq 0 ]] || log_fail "${APTFILE_RED}[FAIL]${APTFILE_COLOR_OFF} repository $pkg"
|
||||
update
|
||||
log_info "${APTFILE_GREEN}[NEW]${APTFILE_COLOR_OFF} repository $repo"
|
||||
}
|
||||
|
||||
debconf_selection() {
|
||||
[[ $TRACE ]] && set -x
|
||||
[[ -z $1 ]] && log_fail "Please specify a debconf line"
|
||||
echo "$1" | debconf-set-selections
|
||||
[[ $? -eq 0 ]] || log_fail "${APTFILE_RED}[FAIL]${APTFILE_COLOR_OFF} debconf: $1"
|
||||
log_info "${APTFILE_CYAN}[OK]${APTFILE_COLOR_OFF} set debconf line: $1"
|
||||
}
|
||||
|
||||
if [ -z "$TMPDIR" ]; then
|
||||
APTFILE_TMPDIR="/tmp"
|
||||
else
|
||||
APTFILE_TMPDIR="${TMPDIR%/}"
|
||||
fi
|
||||
|
||||
APTFILE_INPUT=$(expand_path "$1")
|
||||
APTFILE_TMPNAME="$APTFILE_TMPDIR/aptfile.$$"
|
||||
APTFILE_OUTPUT="${APTFILE_TMPNAME}.out"
|
||||
|
||||
aptfile_preprocess_source() {
|
||||
tail -n +2 "$1" >"$APTFILE_OUTPUT"
|
||||
trap "aptfile_cleanup_preprocessed_source" err exit
|
||||
trap "aptfile_cleanup_preprocessed_source; exit 1" int
|
||||
}
|
||||
|
||||
aptfile_cleanup_preprocessed_source() {
|
||||
rm -f "$APTFILE_TMPNAME"
|
||||
rm -f "$APTFILE_OUTPUT"
|
||||
}
|
||||
|
||||
aptfile_preprocess_source "$APTFILE_INPUT"
|
||||
|
||||
export -f update
|
||||
export -f package
|
||||
export -f package_from_url
|
||||
export -f packagelist
|
||||
export -f ppa
|
||||
export -f repository
|
||||
export -f repository_file
|
||||
export -f debconf_selection
|
||||
export -f log_fail
|
||||
export -f log_info
|
||||
|
||||
chmod +x "$APTFILE_OUTPUT"
|
||||
exec "$APTFILE_OUTPUT"
|
||||
Reference in New Issue
Block a user