#!/usr/bin/env bash # Manually Installed and Source-Compiled usage() { cat >&2 < 0)) || usage 1 [[ "$DEBUG" ]] && set -x # Variables MISC_PLAN="$1" shift MISC_FULL_PLAN="$MISC_PLAN_ROOT/$MISC_PLAN" MISC_REPO="$MISC_REPO_ROOT/$MISC_PLAN" MISC_DONE= SOURCE= CHECKOUT=master CONFIGURE_ARGS=() MISC_DEPENDENCIES=() APT_DEPENDENCIES=( build-essential git ) export LD_LIBRARY_PATH="$MISC_INSTALL_PREFIX/lib:$LD_LIBRARY_PATH" export PKG_CONFIG_PATH="$MISC_INSTALL_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH" # Check that plan exists [[ -r "$MISC_FULL_PLAN" ]] || die 2 "Plan not found: \"$MISC_PLAN\"" _MISC_PREVIOUS_DIR="$PWD" trap finish EXIT INT if [[ ! "$PWD" == "$MISC_REPO_ROOT" ]]; then mkdir -p "$MISC_REPO_ROOT" run cd "$MISC_REPO_ROOT" fi . "$MISC_FULL_PLAN" || die "$?" "Error executing plan: \"$MISC_PLAN\"" # If the recipe is just variables, run the default plan if [[ -z "$MISC_DONE" ]]; then install_deps repo_pull repo_ready configure || true # Not always have configure make install fi } config() { MISC_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/misc/misc.sh" [[ -f "$MISC_CONFIG" ]] && . "$MISC_CONFIG" MISC_REPO_ROOT="${MISC_ROOT:-$XDG_DATA_HOME/misc}" MISC_PLAN_ROOT="${MISC_PLAN_ROOT:-$XDG_CONFIG_HOME/misc}" MISC_INSTALL_PREFIX="${MISC_INSTALL_PREFIX:-$HOME/.local}" _ARGS=() _DRY_RUN=false _NUKE=false DEBUG= while getopts :hdnvr:p:i: opt; do case "$opt" in h) usage ;; n) _NUKE=true _ARGS+=(-n) ;; d) _DRY_RUN=true _ARGS+=(-d) ;; v) DEBUG=true _ARGS+=(-v) ;; r) MISC_REPO_ROOT="$OPTARG" _ARGS+=(-r "$OPTARG") ;; p) MISC_PLAN_ROOT="$OPTARG" _ARGS+=(-p "$OPTARG") ;; i) MISC_INSTALL_PREFIX="$OPTARG" _ARGS+=(-i "$OPTARG") ;; \?) log "Unknown flag \"-$OPTARG\"" usage 1 ;; esac done } finish() { cd "$_MISC_PREVIOUS_DIR" } ## Utilities say() { # say WORD ... printf '%s\n' "$*" } log() { # log WORD ... say "$@" >&2 } die() { # die CODE WORD ... code="$1" shift log "$@" exit "$code" } run() { # run COMMAND ... log "$@" if ! "$_DRY_RUN"; then eval "$@" fi } cmd() { # cmd COMMAND ... log "$@" if ! "$_DRY_RUN"; then command "$@" fi } with_repo() { # with_repo COMMAND ... ## Run COMMAND in $MISC_REPO. run cd "$MISC_REPO" || die 4 "No such directory \"$MISC_REPO\"" run "$@" } ## Library install_deps() { # install_deps for dep in "${MISC_DEPENDENCIES[@]}"; do run misc "${_ARGS[@]}" "$dep" || die 60 "Error installing dependency: \"$dep\"" done if command -v apt >/dev/null 2>&1; then for dep in "${APT_DEPENDENCIES[@]}"; do # XXX: I don't like how hacky this is. if [[ "$(apt list --installed "$dep" 2>/dev/null | wc -l)" -lt 2 ]]; then run sudo apt install "$dep" || die 65 "Error installing dependency: \"$dep\"" fi done fi } repo_pull() { # repo_pull [CHECKOUT] ## Pull the latest CHECKOUT from $REPO. MISC_DONE=1 local source checkout checkout="${1:-$CHECKOUT}" { [[ -n "$SOURCE" ]] || "$_DRY_RUN"; } || die 10 "No source specified for \"$MISC_PLAN\"" if [[ -d "$MISC_REPO" ]]; then git pull origin "$checkout" || die "$?" "Error running 'git pull'" git checkout "$checkout" || die "$?" "Error running 'git checkout'" else _git clone -b "$checkout" "$SOURCE" "$MISC_REPO" || die "$?" "Error running 'git clone'" fi } repo_download_extract() { # repo_download_extract run 'curl -RL "$SOURCE" | tar -zxf-' } repo_ready() { # repo_ready [TARGET ...] ## Ready $MISC_ for building. ## If TARGET ... is specified, they're passed to make; otherwise `make ## clean` is run in the repo directory. MISC_DONE=1 { [[ -d "$MISC_REPO" ]] || "$_DRY_RUN"; } || die 20 "No directory for \"$MISC_PLAN\"" make "${@:-clean}" if git status >/dev/null 2>&1; then git clean -dxf fi } repo_nuke() { # repo_nuke ## Fully remove $MISC_FULL_PLAN { [[ -n "$MISC_REPO" ]] || "$_DRY_RUN"; } || die 40 "No directory to remove" run rm -rf "$MISC_REPO" } ## Commands (with arguments) make() { MISC_DONE=1 cmd make \ -C "$MISC_REPO" \ PREFIX="$MISC_INSTALL_PREFIX" \ "$@" } _make() { cmd make "$@"; } make_install() { MISC_DONE=1 if make "$@"; then make install else die 23 "Make error in \"$MISC_PLAN\": $@" fi } configure() { MISC_DONE=1 if (($# == 0)); then with_repo ./configure "${CONFIGURE_ARGS[@]}" else with_repo ./configure "$@" fi } git() { cmd git \ -C "$MISC_REPO" \ "$@" } _git() { cmd git "$@"; } tar() { cmd tar \ -C "$MISC_REPO" \ "$@" } _tar() { cmd tar "$@"; } ## Finally ... if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then main "$@" fi