#!/usr/bin/env sh # for busybox ash, dash, bash, and zsh. VERBOSE="${VERBOSE-1}" NAME="$0" die() { printf '%s:' "$NAME" printf ' %s' "$@" printf '\n' exit 1 } >&2 pl() { # print lines printf '%s\n' "$@" } backup() { : "${1:?missing argument}" pl "backing up $1" set -- "$1" "${backup_dir:?backup_dir unset}" # shorthand for my own sanity [ -d "$2" ] || mkdir "$2" || die "failed to create backup directory" if [ ${1%/*} != "$1" ]; then mkdir -p "$2/${1%/*}" || die "failed to create backup directory" fi ! [ -e "$2/$1" ] || die "backup already exists: $2/$1" mv "$1" "$2/$1" || die "failed to backup $1" } hardlink() { : "${1:?missing argument}" : "${2:?missing argument}" if [ -e "$1" ]; then ! [ "$1" -ef "$2" ] || return 0 if [ -h "$1" ]; then pl "removing symbolic link $1" rm "$1" || die "failed to remove symbolic link" fi if [ -s "$1" ]; then #diff -U3 "$1" "$2" >>/tmp/installed.patch backup "$1" fi fi ln "$2" "$1" || die "failed to hardlink $1" } softlink_nix() { : "${1:?missing argument}" : "${2:?missing argument}" if [ -e "$1" ]; then if [ -h "$1" ]; then [ "$(readlink "$1")" != "$2" ] || return 0 pl "removing symbolic link $1" rm "$1" || die "failed to remove symbolic link" else die "$1 already exists and is not a symbolic link" fi fi ln -s "$2" "$1" || die "failed to symlink $1" } list_files() { find "${1:-.}" -maxdepth 1 -printf "%P\n" | while read -r f; do [ "${#f}" != 0 ] || continue pl "$f" done } softlink_pseudo() ( : "${1:?missing argument}" : "${2:?missing argument}" [ -d "$2" ] || die "$1 is not a directory to softlink" [ -d "$1" ] || mkdir "$1" || die "failed to mkdir $1" list_files "$2" | while read -r f; do d1="$1/$f" d2="$2/$f" if [ -d "$d2" ]; then if [ "$d1" != ".vim/bundle" ]; then # buggy on Windows [ "$VERBOSE" -lt 2 ] || printf '\033[34m / \033[0m %s %s\n' "$d1" "$d2" >&2 softlink_pseudo "$d1" "$d2" || exit fi elif [ -f "$d2" ]; then [ "$VERBOSE" -lt 2 ] || printf '\033[34m * \033[0m %s\n' "$d1" >&2 hardlink "$d1" "$d2" || exit else die "i don't know how to pseudo-symlink $d2" fi done || exit ) find_new_files() ( : "${1:?missing argument}" : "${2:?missing argument}" list_files "$1" | while read -r f; do d1="$1/$f" d2="$2/$f" case "$d1" in (.vim/.netrwhist) continue;; (.vim/backup) continue;; (.vim/bundle) continue;; (.vim/swp) continue;; (.vim/undo) continue;; esac if [ -d "$d2" ]; then find_new_files "$d1" "$d2" || exit elif ! [ "$d1" -ef "$d2" ]; then [ -d "$d1" ] && ind=/ || ind= if [ "$VERBOSE" -lt 1 ]; then printf ' + %s%s\n' "$d1" "$ind" >&2 else #printf 'new destination file. consider manually moving it:\n' >&2 printf '\033[32m + \033[0m %s%s\n' "$d1" "$ind" >&2 fi fi done ) softlink() { if [ -n "$MSYSTEM" ]; then # MSYS2 does not have nor emulate symbolic links. softlink_pseudo "$@" || exit # to make up for git status not seeing new files: find_new_files "$@" || exit else softlink_nix "$@" fi } readlink -f / >/dev/null || die 'failed sanity check (check your $PATH)' unset CDPATH rc="$(readlink -f "$0")" && rc="${rc%/*}" && cd "$rc" || die "failed to determine rc directory" cd "${HOME:?HOME variable empty or unset}" || die "failed to change directory" backup_dir="$rc/backup-$(date -u +%s)" || die "failed to determine date" ! [ -d "$backup_dir" ] || die "backup directory already exists" for f in \ .shrc .bashrc .zshrc .prep .prezto-compinit .ls_colors \ .vimrc .inputrc .Xresources .screenrc .tmux.conf \ ; do hardlink "$f" "$rc/home/${f#.}" done for d in sh .vim; do softlink "$d" "$rc/${d#.}" done # ensure that .bashrc gets executed if ! [ -e .bash_profile ] || ! grep -qF .bashrc .bash_profile; then pl '' '! [ -f ~/.bashrc ] || . ~/.bashrc' >>.bash_profile fi # delete any directory structure that may have been included with the OS. for d in bin Desktop Documents Downloads Music Pictures Public Templates Video Videos; do ! [ -d "$d" ] || rmdir "$d" done # create instead my preferred directory structure. mkdir -p .local/bin src work play || die "failed to create directories"