#!/usr/bin/env bash # My (idempotent) dotfile deployment script. # # You pass the directories of "topics" to it to install them. It will: # 1. symlink $topic/.* => ~/ and $topic/.(config|local)/* => ~/.\1/ # 2. run $topic/install the first time # 3. run $topic/update on consecutive runs CWD="$(cd "$(dirname "$0")" && pwd)" pushd "$CWD" >/dev/null set -e shopt -s nullglob # shellcheck source=shell/common.sh source "shell/common.sh" # blue="\033[34m" magenta="\033[35m" green="\033[32m" orange="\033[33m" grey="\033[36m" red="\033[31m" nc="\033[0m" # _run() { local cmd="${*//$DOTFILES\//}" cmd="${cmd//$HOME/~}" local clr="" case $cmd in *~/.bin/) clr="${magenta}" ;; ln*) clr="" ;; mkdir*) clr="${blue}" ;; *) clr="${orange}" esac echo -e " $PREFIX$clr$cmd$nc" [[ $DRYRUN ]] || { $@ 2>&1 | sed 's/^/ => /'; } } _link() { if [[ -f "$2" || ( -d "$2" && -f "$2/${1##*/}" ) ]]; then if [[ $yes ]]; then [[ $yes = 1 ]] && choice=y || choice=n else read -r -n 1 -p "? ${1##*/} exists in $2 -- overwrite? [y/n] " choice echo fi case $choice in y|Y) _run rm -rf "$2" PREFIX="${red}OVERWRITE:${nc} " _run ln -svf "$1" "$2" ;; *) PREFIX="${red}ABORTED:${nc} " DRYRUN=1 _run ln -svf "$1" "$2" ;; esac else _run ln -svf "$1" "$2" fi } ## export SERVER= install=1 link=1 update=1 yes=0 while getopts iuldypLSUh opt; do case $opt in d) DRYRUN=1 ;; i) install= ;; l) link= ;; p) yes= ;; u) update= ;; y) yes=1 ;; S) SERVER=1 ;; U) install= yes=0 ;; L) update= install= yes=0 ;; h) cat <&2 echo "Aborted." exit 1 ;; esac done shift $((OPTIND-1)) # ENABLED_DIR=".enabled.d" for topic in "${@:-$(ls -1 "$ENABLED_DIR" | sed 's%_%/%')}"; do [[ -d $topic ]] || continue echo -e "${green}${topic}${nc}" tpath="$CWD/$topic" if [[ $link ]]; then # Symlink dotfiles from topics (2 levels deep) + parent (1 level deep) for file in "$tpath"{,../}/.[a-zA-Z]*; do if [[ -d "$file" && "${file##*/}" == .@(config|local) ]]; then for subfile in "$file"/*; do base="$HOME/${file##*/}/" [[ -d $base ]] || _run mkdir -p "$base" _link "$subfile" "$base" done elif [[ -e $file ]]; then _link "$file" "$HOME/" fi done fi # Link topic to .enabled.d linkpath="${ENABLED_DIR}/${topic//\//_}" if [[ -h "$linkpath" ]]; then [[ "$update" && -x ${linkpath}/update ]] && _run "$tpath/update" else # Register topic as 'enabled' _run ln -svf "$tpath" "$linkpath" # Run install script [[ "$install" && -x ${linkpath}/install ]] && _run "$tpath/install" fi done popd >/dev/null # vim:set ft=sh: