helm/bootstrap
2016-11-15 14:08:35 +01:00

129 lines
3.2 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/bin/* to ~/.bin/
# 2. symlink $topic/.* => ~/ and $topic/.*/* => ~/.$1/
# 3. run $topic/install the first time
# 4. run $topic/update on consecutive runs
#
# NOTE: Be sure to add ~/.bin to PATH
#
# Options:
# -i Don't run install scripts
# -u Don't run update scripts
# -l Don't symlink dotfiles or bin scripts
# -d Do a dry run (only output commands, no changes)
# -y Overwrite conflicts (no prompts)
# -n Don't overwrite conflicts (no prompts
set -e
DOTFILES=$(cd $(dirname $0) && pwd -P)
source "$DOTFILES/shell/common.sh"
shopt -s nullglob
#
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 ]] || { $@ | sed 's/^/ => /'; }
}
_link() {
if [[ -f "$2" || ( -d "$2" && -f "$2/${1##*/}" ) ]]; then
if [[ $yes ]]; then
[[ $yes = 1 ]] && choice=y || choice=n
else
read -n 1 -p "? ${1##*/} exists in $2 -- overwrite? [y/n] " choice
echo
fi
case $choice in
y|Y) 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
}
##
install=1
link=1
update=1
yes=
while getopts iuldyn opt; do
case $opt in
d) DRYRUN=1 ;;
i) install= ;;
l) link= ;;
n) yes=0 ;;
u) update= ;;
y) yes=1 ;;
*) >&2 echo "Aborted."
exit 1 ;;
esac
done
shift $((OPTIND-1))
#
[[ -d ~/.bin ]] || _run mkdir -p ~/.bin
PATH="$DOTFILES/.bin:$PATH"
for topic in ${@:-$(find "$DOTFILES/.enabled.d" -maxdepth 1 -type l)}; do
[[ -d $topic ]] || continue
tpath=$(realpath "$topic")
tname="$(basename $(dirname $tpath))_${tpath##*/}"
echo -e "${green}${tname//_//}${nc}"
# Link binaries
for bin in $tpath/bin/*; do
[[ "$link" && -x "$bin" ]] && _link "$bin" "~/.bin/"
done
# Link topic to .enabled.d
if [[ -h "$DOTFILES/.enabled.d/$tname" ]]; then
[[ "$update" && -x $tpath/update ]] && _run "$tpath/update"
else
# Register topic as 'enabled'
_run ln -svf "$tpath" "$DOTFILES/.enabled.d/$tname"
# Run install script
[[ "$install" && -x $tpath/install ]] && _run "$tpath/install"
fi
# Symlink dotfiles from topic directories (2 levels deep)
[[ "$link" ]] || continue
for file in "$tpath"/.[a-zA-Z]*; do
if [[ -d $file ]]; then
for subfile in "$file"/*; do
base="$HOME/${file##*/}/"
[[ -d $base ]] || _run mkdir -p "$base"
_link "$subfile" "$base"
done
elif [[ -f $file ]]; then
_link "$file" "$HOME/"
fi
done
done
# vim:set ft=sh: