Source

dotfiles / dotlink.sh

Full commit
#!/bin/bash

##-- Helper functions -------------------------------------
# Prints usage, and exits with the specified exit code (or 2 if no exit code is
# explicitly provided).
function print_usage_and_exit {
  cat >&2 <<END
Usage: $0 <target> [source]"
  target: Name for the dotfile in ~ without leading dot, e.g. 'vimrc'.
  source: Relative path to the dotfile in \$DOTFILES, e.g. 'vim/vimrc'.  Default is \`target\`".

Environment variables:
  \$DOTFILES: points to the source directory to copy files from (defaults to
          ~/local/dotfiles).
END

  if [ $# -eq 1 ]; then
    exit $1
  else
    exit 2
  fi
}

# Fatally exits with the given error message.  Used in assertions for important
# commands.
function die {
  echo >&2 "$1"
  exit 1
}


##-- Entry point ------------------------------------------
# Make sure that we received enough parameters.
if [ $# -lt 1 -o $# -gt 2 ]; then
  print_usage_and_exit
fi

## Process parameters.
# `sourcerel` is the relative path from $DOTFILES to the file to link to.
# $2 if provided, otherwise $1.
[ $# -ge 2 ] && sourcerel="$2" || sourcerel="$1"

## Process env variables.
# If $DOTFILES is empty or not provided, set it to its default value.
if [ "x$DOTFILES" = "x" ]; then
  DOTFILES="${HOME}/local/dotfiles"
fi

## Locals
homename="$HOME/.$1"
homebak="${homename}~"
sourcename="$DOTFILES/$sourcerel"

if [ -e "$homename" -o -L "$homename" ]; then
  if [ -e "$homebak" -o -L "$homebak" ]; then
    # Make sure that we're not overwriting someone's backup file.
    echo >&2 "Error: both the target file $homename and its backup name $homebak" \
             'exist already!  Refuses to continue; manually remove the backup file.'
    exit 3
  fi

  # Backup the already-existing target file.
  echo >&2 "Warning: target $homename already exists. Backing it up as ${homebak}."
  mv "$homename" "$homebak" || die 'Error while backing up! Refuses to continue.'
fi

# All right, ready to do the actual linking.
ln -s "$sourcename" "$homename" || die 'Error while linking! Refuses to continue.'