From a23e896c1ae2d67c4f30239e8fa36fe3db702859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Gro=C3=9F?= Date: Sat, 12 Nov 2016 00:03:51 +0100 Subject: [PATCH] Simplified bootstrapper, source optional bootstrap script in each topic instead which in turn is responsible for symlinking files and installing things --- README.markdown | 51 +++++++----- bash/.exclude-platforms | 1 - bash/bootstrap | 5 ++ bootstrap | 167 +++++++++++++------------------------- elixir/bootstrap | 1 + git/bootstrap | 6 ++ gpg/bootstrap | 3 + htop/.exclude-platforms | 2 - htop/bootstrap | 5 ++ mintty/.exclude-platforms | 4 - mintty/bootstrap | 3 + ruby/bootstrap | 4 + screen/.exclude-platforms | 1 - screen/bootstrap | 3 + ssh/.exclude-platforms | 3 - ssh/bootstrap | 3 + tmux/.exclude-platforms | 1 - tmux/bootstrap | 3 + vim/.exclude-platforms | 1 - vim/bootstrap | 4 + wget/bootstrap | 1 + zsh/.exclude-platforms | 2 - zsh/bootstrap | 5 ++ 23 files changed, 133 insertions(+), 146 deletions(-) delete mode 100644 bash/.exclude-platforms create mode 100644 bash/bootstrap create mode 100644 elixir/bootstrap create mode 100644 git/bootstrap create mode 100644 gpg/bootstrap delete mode 100644 htop/.exclude-platforms create mode 100644 htop/bootstrap delete mode 100644 mintty/.exclude-platforms create mode 100644 mintty/bootstrap create mode 100644 ruby/bootstrap delete mode 100644 screen/.exclude-platforms create mode 100644 screen/bootstrap delete mode 100644 ssh/.exclude-platforms create mode 100644 ssh/bootstrap delete mode 100644 tmux/.exclude-platforms create mode 100644 tmux/bootstrap delete mode 100644 vim/.exclude-platforms create mode 100644 vim/bootstrap create mode 100644 wget/bootstrap delete mode 100644 zsh/.exclude-platforms create mode 100644 zsh/bootstrap diff --git a/README.markdown b/README.markdown index 0b225b4b..38d9674a 100644 --- a/README.markdown +++ b/README.markdown @@ -50,28 +50,42 @@ agross@linux ~/.dotfiles $ ./bootstrap [ INFO ] Installing dotfiles from /home/agross/.dotfiles - [ INFO ] Installing dotfiles in /home/agross for platform linux + [ INFO ] Installing dotfiles to $HOME=/home/agross for $OSTYPE=linux [ OK ] Linked /home/agross/.dotfiles == /home/agross/.dotfiles + [ INFO ] Running /home/agross/.dotfiles/bash/bootstrap [ OK ] Linked /home/agross/.dotfiles/bash/bash_profile.symlink == /home/agross/.bash_profile [ OK ] Linked /home/agross/.dotfiles/bash/bashrc.symlink == /home/agross/.bashrc [ OK ] Linked /home/agross/.dotfiles/bash/inputrc.symlink == /home/agross/.inputrc + [ INFO ] Running /home/agross/.dotfiles/git/bootstrap + [ OK ] Linked /home/agross/.dotfiles/git/gitconfig.symlink == /home/agross/.gitconfig + [ OK ] Linked /home/agross/.dotfiles/git/gitconfig.training.symlink == /home/agross/.gitconfig.training [ OK ] Linked /home/agross/.dotfiles/git/git-wtfrc.symlink == /home/agross/.git-wtfrc [ OK ] Linked /home/agross/.dotfiles/git/gitshrc.symlink == /home/agross/.gitshrc - [ OK ] Linked /home/agross/.dotfiles/git/gitconfig.symlink == /home/agross/.gitconfig - [ INFO ] Skipped /home/agross/.dotfiles/mintty as it is excluded for platform linux + [ INFO ] Running /home/agross/.dotfiles/mintty/bootstrap + [ INFO ] Running /home/agross/.dotfiles/ruby/bootstrap [ OK ] Linked /home/agross/.dotfiles/ruby/gemrc.symlink == /home/agross/.gemrc [ OK ] Linked /home/agross/.dotfiles/ruby/guard.rb.symlink == /home/agross/.guard.rb [ OK ] Linked /home/agross/.dotfiles/ruby/irbrc.symlink == /home/agross/.irbrc + [ OK ] Linked /home/agross/.dotfiles/ruby/pryrc.symlink == /home/agross/.pryrc + [ INFO ] Running /home/agross/.dotfiles/screen/bootstrap [ OK ] Linked /home/agross/.dotfiles/screen/screenrc.symlink == /home/agross/.screenrc - [ INFO ] Skipped /home/agross/.dotfiles/ssh as it is excluded for platform linux + [ INFO ] Running /home/agross/.dotfiles/ssh/bootstrap + [ INFO ] Running /home/agross/.dotfiles/tmux/bootstrap + [ OK ] Linked /home/agross/.dotfiles/tmux/tmux.conf.symlink == /home/agross/.tmux.conf + [ INFO ] Running /home/agross/.dotfiles/vim/bootstrap [ OK ] Linked /home/agross/.dotfiles/vim/vim.symlink == /home/agross/.vim [ OK ] Linked /home/agross/.dotfiles/vim/vimrc.symlink == /home/agross/.vimrc + [ INFO ] Running /home/agross/.dotfiles/wget/bootstrap [ OK ] Linked /home/agross/.dotfiles/wget/wgetrc.symlink == /home/agross/.wgetrc - [ OK ] Linked /home/agross/.dotfiles/zsh/zlogin.symlink == /home/agross/.zlogin + [ INFO ] Running /home/agross/.dotfiles/zsh/bootstrap [ OK ] Linked /home/agross/.dotfiles/zsh/zprofile.symlink == /home/agross/.zprofile - [ OK ] Linked /home/agross/.dotfiles/zsh/zshrc.symlink == /home/agross/.zshrc [ OK ] Linked /home/agross/.dotfiles/zsh/zshenv.symlink == /home/agross/.zshenv - [ OK ] Linked /home/agross/.dotfiles/tmux/tmux.conf.symlink to /home/agross/.tmux.conf + [ OK ] Linked /home/agross/.dotfiles/zsh/zshrc.symlink == /home/agross/.zshrc + [ INFO ] Running /home/agross/.dotfiles/htop/bootstrap + [ OK ] Linked /home/agross/.dotfiles/htop/htoprc.symlink == /home/agross/.htoprc + [ INFO ] Running /home/agross/.dotfiles/elixir/bootstrap + [ OK ] Linked /home/agross/.dotfiles/elixir/iex.exs.symlink == /home/agross/.iex.exs + [ INFO ] Running /home/agross/.dotfiles/gpg/bootstrap [ INFO ] All installed from /home/agross/.dotfiles ``` @@ -83,9 +97,7 @@ dotfiles are structured around topics. Topics are directories under the dotfiles ``` dotfiles ├─ example -| ├─ .exclude-platforms # bootstrapper #1: specifies excluded platforms for this topic -| ├─ example.symlink # bootstrapper #2: symlinked to ~/.example -| ├─ .install.sh # bootstrapper #3: performs additional installation after symlinking +| ├─ bootstrap # bootstrapper: script to symlink files and install additional programs | ├─ zprofile.zsh # zsh #1: run for login shells | ├─ path.zsh # zsh #2: modifies $PATH | ├─ something.zsh # zsh #3: additional setup @@ -104,21 +116,22 @@ There are some special files that either the `bootstrap` script or [zsh](#shell) ### `bootstrap`-specific files -#### topic/\*.symlink - -Files and directories with a `.symlink` extension are symlinked to your home directory with the `.symlink` extension removed and a dot character prepended. +The bootstrapper will create an implicit symlink for the dotfiles directory itself. It will always be symlinked to `$HOME/.dotfiles` (unless you [`git clone`d the dotfiles](#installation) there.) This makes it easier to refer to other dotfiles from within dotfiles as you can use a static path. For example, [my git mergetool scripts point to `$HOME/.dotfiles/git/tools`](https://github.com/agross/dotfiles/blob/master/git/gitconfig.symlink#L56). -There is an implicit symlink for the dotfiles directory itself: It will always be symlinked to `$HOME/.dotfiles` (unless you [`git clone`d the dotfiles](#installation) there.) +#### topic/bootstrap -#### topic/.install.sh +`bootstrap` will source each `topic/bootstrap` file and thereby run it using bash. The script can then -An optional installer script that is run after the topic's symlinks have been created. +* symlink files using the `symlink $source $target` function. `$target` may be omitted, e.g. `symlink foo.symlink` will create the symlink as `$HOME/.foo` pointing to `$DOTFILES/topic/foo.symlink`. +* install additional programs at the script's discretion. -#### topic/.exclude-platforms +Each `topic/bootstrap` has the following environment variables available: -`bootstrap` will not process the topic if the current platform is listed in the file (one platform per line). The bootstrapper currently detects platforms `cygwin`, `windows`, `linux`, `mac`, `msys` and `freebsd`. +| Variable | Description | +| ----------| ----------- | +| `$OSTYPE` | Normalized operating system, e.g. `linux`, `mac`, `windows` for msysgit and Git for Windows, `cygwin`, or the original `$OSTYPE` | +| `$HOME` | Home directory for the operating system, e.g. `$HOME` for all Linux-style `$OSTYPE`s and `/c/Users//` for `$OSTYPE == 'windows'` | -If the `.exclude-platforms` file does not exist or if it is empty, the topic is processed on all platforms. ### [zsh](#shell)-specific files diff --git a/bash/.exclude-platforms b/bash/.exclude-platforms deleted file mode 100644 index 8e1a5599..00000000 --- a/bash/.exclude-platforms +++ /dev/null @@ -1 +0,0 @@ -windows diff --git a/bash/bootstrap b/bash/bootstrap new file mode 100644 index 00000000..34d59a92 --- /dev/null +++ b/bash/bootstrap @@ -0,0 +1,5 @@ +[[ "$OSTYPE" == 'windows' ]] && return + +symlink "$topic/bash_profile.symlink" +symlink "$topic/bashrc.symlink" +symlink "$topic/inputrc.symlink" diff --git a/bootstrap b/bootstrap index 42247ee8..33ff0312 100755 --- a/bootstrap +++ b/bootstrap @@ -8,7 +8,7 @@ set -e # Show executed commands. -# set -x +#set -x light_red="\e[01;31m" green="\e[0;32m" @@ -37,32 +37,19 @@ fail () { } platforms () { - if [ -n "$platforms_cache" ]; then - printf "$platforms_cache" - return - fi - - if [ "$(uname)" == "Darwin" ]; then - printf 'mac' - elif [ "$(uname -s)" == "Linux" ]; then - printf 'linux' - elif [ "$(uname -s)" == "FreeBSD" ]; then - printf 'freebsd' - elif [ "$(uname -o)" == "Cygwin" ]; then - printf "cygwin\nwindows" - elif [ "$(uname -o)" == "Msys" ]; then - printf 'msys' - else - printf 'unknown' - fi + case "$OSTYPE" in + linux*) printf 'linux';; + darwin) printf 'mac';; + msys) printf 'windows';; + cygwin) printf "cygwin\nwindows";; + *) printf "$OSTYPE";; + esac } -# Cache value. -export platforms_cache="$(platforms)" readlink_e () { - local file=$1 + local file="$1" - if [ "$(platforms)" == 'freebsd' -o "$(platforms)" == 'mac' ]; then + if [[ "$(platforms)" == 'mac' ]]; then printf "$(realpath "$file")" return $? fi @@ -71,49 +58,33 @@ readlink_e () { } home_directory () { - local platform=$1 - - case "$platform" in - mac|linux|msys|cygwin|freebsd ) - home=$HOME - ;; - windows ) - home="$(printf "%s" "$(cygpath --unix $USERPROFILE)")" - ;; - * ) - fail "$(printf "Cannot determine home directories for platform %b%s%b" $green "$platform" $reset_color)" - ;; + case "${1?Need platform}" in + windows) printf "$(cygpath --unix $USERPROFILE)";; + *) printf "$HOME";; esac } -platform_excluded () { - local topic=$1 - local platform=$2 - local exclude_file="$topic/.exclude-platforms" - - if [ ! -f "$exclude_file" ]; then - return 1 - fi - - if [ -n "$(/bin/grep "$platform" "$exclude_file")" ]; then - return 0 +symlink () { + local src="${1?Need link source}" + # If dst is not given, use src file name in $HOME, prepended with ., minus .symlink extension. + local dst="$2" + if [[ -z "$dst" ]]; then + local filename="$(basename "$src")" + local dst="$HOME/.${filename%.*}" fi - return 1 -} - -link_file () { - local src=$1 - local dst=$2 - local overwrite= backup= skip= local action= - if [ -f "$dst" -o -d "$dst" -o -L "$dst" ]; then - if [ "$overwrite_all" == "false" ] && [ "$backup_all" == "false" ] && [ "$skip_all" == "false" ]; then - local current_src="$(readlink_e "$dst")" + if [[ -f "$dst" ]] || \ + [[ -d "$dst" ]] || \ + [[ -L "$dst" ]]; then + if [[ "$overwrite_all" == "false" ]] && \ + [[ "$backup_all" == "false" ]] && \ + [[ "$skip_all" == "false" ]]; then + local current_target="$(readlink_e "$dst")" - if [ "$current_src" == "$src" ]; then + if [[ "$current_target" == "$src" ]]; then skip=true; else user "$(printf "File already exists: %b%s%b (%b%s%b) @@ -134,32 +105,13 @@ link_file () { read -n 1 action < /dev/tty case "$action" in - o ) - overwrite=true - break - ;; - O ) - overwrite_all=true - break - ;; - b ) - backup=true - break - ;; - B ) - backup_all=true - break - ;; - s ) - skip=true - break - ;; - S ) - skip_all=true - break - ;; - * ) - ;; + o) overwrite=true; break;; + O) overwrite_all=true; break;; + b) backup=true; break;; + B) backup_all=true break;; + s) skip=true; break;; + S) skip_all=true; break ;; + *) ;; esac done fi @@ -184,12 +136,11 @@ link_file () { fi fi - if [ "$skip" != "true" ]; then # "false" or empty + if [ "$skip" != "true" ]; then # "false" or empty. # Create native symlinks on Windows. - export CYGWIN=winsymlinks:nativestrict - ln -s "$1" "$2" + CYGWIN=winsymlinks:nativestrict ln --symbolic "$src" "$dst" - success "$(printf "Linked %b%s%b to %b%s%b" $green "$1" $reset_color $green "$2" $reset_color)" + success "$(printf "Linked %b%s%b to %b%s%b" $green "$src" $reset_color $green "$dst" $reset_color)" fi } @@ -202,40 +153,32 @@ install_dotfiles () { local platforms="$(platforms)" while IFS=$'\n' read -r platform; do - local home - home_directory "$platform" + local HOME="$(home_directory "$platform")" + local OSTYPE="$platform" echo - info "$(printf "Installing dotfiles in %b%s%b for platform %b%s%b" $green "$home" $reset_color $green "$platform" $reset_color)" + info "$(printf "Installing dotfiles to %b\$HOME%b=%b%s%b for %b\$OSTYPE%b=%b%s%b" \ + $light_red $reset_color \ + $green "$HOME" $reset_color \ + $light_red $reset_color \ + $light_yellow "$OSTYPE" $reset_color)" # First, add a symlink for this dotfiles directory. - local dotfiles="$home/.dotfiles" - link_file "$dotfiles_root" "$dotfiles" + symlink "$dotfiles_root" "$HOME/.dotfiles" - # Find direct child directories (topics), exclude those starting with dots. - local topics="$(/usr/bin/find "$dotfiles_root" -mindepth 1 -maxdepth 1 -type d -not -name '\.*')" + # Find direct child directories (topics). + local topics="$(/usr/bin/find "$dotfiles_root" -mindepth 1 -maxdepth 1 -type d)" while IFS=$'\n' read -r topic; do [[ -z "$topic" ]] && continue - if platform_excluded "$topic" "$platform"; then - info "$(printf "Skipped %b%s%b as it is excluded for platform %b%s%b" $green "$topic" $reset_color $green "$platform" $reset_color)" - continue - fi - - # Find files and directories named *.symlink below each topic directory, exclude dot files. - local symlinks="$(/usr/bin/find "$topic" -mindepth 1 -maxdepth 1 \( -type f -or -type d \) -name '*.symlink' -not -name '\.*')" - while IFS=$'\n' read -r src; do - [[ -z "$src" ]] && continue - - dst="$home/.$(basename "${src%.*}")" - link_file "$src" "$dst" - done <<< "$symlinks" + # Find (optional) topic/bootstrap script and run it. + local bootstrap="$topic/bootstrap" + if [[ -f "$bootstrap" ]]; then + info "$(printf "Running %b%s%b" \ + $green "$bootstrap" $reset_color)" - # Run optional install script. - local install="$topic/.install.sh" - if [ -x "$install" ]; then - info "$(printf "Running %b%s%b" $green "$install" $reset_color)" - sh -c "$install" + # Run script from inside topic. + source "$bootstrap" fi done <<< "$topics" done <<< "$platforms" diff --git a/elixir/bootstrap b/elixir/bootstrap new file mode 100644 index 00000000..a635cc1f --- /dev/null +++ b/elixir/bootstrap @@ -0,0 +1 @@ +symlink "$topic/iex.exs.symlink" diff --git a/git/bootstrap b/git/bootstrap new file mode 100644 index 00000000..38507e90 --- /dev/null +++ b/git/bootstrap @@ -0,0 +1,6 @@ +symlink "$topic/gitconfig.symlink" +symlink "$topic/gitconfig.training.symlink" +symlink "$topic/git-wtfrc.symlink" + +[[ "$OSTYPE" == "windows" ]] && return +symlink "$topic/gitshrc.symlink" diff --git a/gpg/bootstrap b/gpg/bootstrap new file mode 100644 index 00000000..a02ff140 --- /dev/null +++ b/gpg/bootstrap @@ -0,0 +1,3 @@ +[[ "$OSTYPE" == 'windows' ]] && return + +[[ -d "$topic/gnupg.symlink" ]] && symlink "$topic/gnupg.symlink" diff --git a/htop/.exclude-platforms b/htop/.exclude-platforms deleted file mode 100644 index 9c456e29..00000000 --- a/htop/.exclude-platforms +++ /dev/null @@ -1,2 +0,0 @@ -cygwin -windows diff --git a/htop/bootstrap b/htop/bootstrap new file mode 100644 index 00000000..148bbd20 --- /dev/null +++ b/htop/bootstrap @@ -0,0 +1,5 @@ +[[ "$OSTYPE" == 'cygwin' ]] || \ +[[ "$OSTYPE" == 'windows' ]] && \ +return + +symlink "$topic/htoprc.symlink" diff --git a/mintty/.exclude-platforms b/mintty/.exclude-platforms deleted file mode 100644 index cc4f99d2..00000000 --- a/mintty/.exclude-platforms +++ /dev/null @@ -1,4 +0,0 @@ -freebsd -linux -mac -windows diff --git a/mintty/bootstrap b/mintty/bootstrap new file mode 100644 index 00000000..c7ca7432 --- /dev/null +++ b/mintty/bootstrap @@ -0,0 +1,3 @@ +[[ "$OSTYPE" != 'cygwin' ]] && return + +symlink "$topic/minttyrc.symlink" diff --git a/ruby/bootstrap b/ruby/bootstrap new file mode 100644 index 00000000..9890e212 --- /dev/null +++ b/ruby/bootstrap @@ -0,0 +1,4 @@ +symlink "$topic/gemrc.symlink" +symlink "$topic/guard.rb.symlink" +symlink "$topic/irbrc.symlink" +symlink "$topic/pryrc.symlink" diff --git a/screen/.exclude-platforms b/screen/.exclude-platforms deleted file mode 100644 index 8e1a5599..00000000 --- a/screen/.exclude-platforms +++ /dev/null @@ -1 +0,0 @@ -windows diff --git a/screen/bootstrap b/screen/bootstrap new file mode 100644 index 00000000..6050f4fd --- /dev/null +++ b/screen/bootstrap @@ -0,0 +1,3 @@ +[[ "$OSTYPE" == 'windows' ]] && return + +symlink "$topic/screenrc.symlink" diff --git a/ssh/.exclude-platforms b/ssh/.exclude-platforms deleted file mode 100644 index 06a4381b..00000000 --- a/ssh/.exclude-platforms +++ /dev/null @@ -1,3 +0,0 @@ -freebsd -linux -mac diff --git a/ssh/bootstrap b/ssh/bootstrap new file mode 100644 index 00000000..e3722bd1 --- /dev/null +++ b/ssh/bootstrap @@ -0,0 +1,3 @@ +[[ "$OSTYPE" != 'cygwin' ]] && [[ "$OSTYPE" != 'windows' ]] && return + +symlink "$topic/ssh.symlink" diff --git a/tmux/.exclude-platforms b/tmux/.exclude-platforms deleted file mode 100644 index 8e1a5599..00000000 --- a/tmux/.exclude-platforms +++ /dev/null @@ -1 +0,0 @@ -windows diff --git a/tmux/bootstrap b/tmux/bootstrap new file mode 100644 index 00000000..a7913e7c --- /dev/null +++ b/tmux/bootstrap @@ -0,0 +1,3 @@ +[[ "$OSTYPE" == 'windows' ]] && return + +symlink "$topic/tmux.conf.symlink" diff --git a/vim/.exclude-platforms b/vim/.exclude-platforms deleted file mode 100644 index 8e1a5599..00000000 --- a/vim/.exclude-platforms +++ /dev/null @@ -1 +0,0 @@ -windows diff --git a/vim/bootstrap b/vim/bootstrap new file mode 100644 index 00000000..a6443b5f --- /dev/null +++ b/vim/bootstrap @@ -0,0 +1,4 @@ +[[ "$OSTYPE" == 'windows' ]] && return + +symlink "$topic/vim.symlink" +symlink "$topic/vimrc.symlink" diff --git a/wget/bootstrap b/wget/bootstrap new file mode 100644 index 00000000..5ed63c25 --- /dev/null +++ b/wget/bootstrap @@ -0,0 +1 @@ +symlink "$topic/wgetrc.symlink" diff --git a/zsh/.exclude-platforms b/zsh/.exclude-platforms deleted file mode 100644 index 634c000f..00000000 --- a/zsh/.exclude-platforms +++ /dev/null @@ -1,2 +0,0 @@ -msys -windows diff --git a/zsh/bootstrap b/zsh/bootstrap new file mode 100644 index 00000000..4bc2816a --- /dev/null +++ b/zsh/bootstrap @@ -0,0 +1,5 @@ +[[ "$OSTYPE" == 'windows' ]] && return + +symlink "$topic/zprofile.symlink" +symlink "$topic/zshenv.symlink" +symlink "$topic/zshrc.symlink"