144 lines
3.5 KiB
Bash
Executable file
144 lines
3.5 KiB
Bash
Executable file
#!/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 <<EOL
|
|
Usage: $0 [-iuldypLSU] [topic1] [topic2] [...]
|
|
|
|
-i Don't run install scripts
|
|
-u Don't run update scripts
|
|
-l Don't symlink dotfiles
|
|
-d Do a dry run (only output commands, no changes)
|
|
-y Overwrite conflicts (no prompts)
|
|
-p Prompt on file conflict (to overwrite)
|
|
-L Refresh links; the same as -ui
|
|
-S Server mode; only install the bare minimum
|
|
-U Update mode; run update scripts only
|
|
EOL
|
|
exit
|
|
;;
|
|
*) >&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:
|