3
\$\begingroup\$

This is a follow up to my previous question on Code Review. I did try to implement most of feedback provided by thiagoalessio.

This is what my updated code looks like:

#!/usr/bin/env bash

RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
RESET=$(tput sgr0)

is_symlink_dest_equal_to() { test "$(readlink $1)" == "$2"; }
can_create_dir() { mkdir -p "$1"; }
is_directory() { test -d "$1"; }
file_exists() { test -e "$1"; }
is_symlink() { test -L "$1"; }

create_symlink() {
  file_loc="$1"
  symlink_loc="$2"

  ln -s "$file_loc" "$symlink_loc"
  echo "Created a symlink $symlink_loc -> $file_loc"
  return 0
}

invalid_file_error() {
  file_loc="$1"
  symlink_loc="$2"

  echo "${RED}WARNING${RESET}: Failed to link $symlink_loc to $file_loc"
  echo "${RED}         ${RESET}$file_loc does not exist"
  return 1
}

handle_non_existing_symlink_directory() {
  file_loc="$1"
  symlink_loc="$2"
  symlink_dir=$(dirname "$symlink_loc")

  if ! can_create_dir "$symlink_dir" ; then
    echo "${RED}WARNING${RESET}: Failed to link $symlink_loc to $file_loc"
    echo "${RED}         ${RESET}Could not create folder $symlink_dir/"
    return 1
  else
    create_symlink "$file_loc" "$symlink_loc"
  fi
}

handle_wrong_existing_symlink() {
  file_loc="$1"
  symlink_loc="$2"
  current_dest=$(readlink "$symlink_loc")

  echo "It seems like $symlink_loc already is symlink to $current_dest."
  read -p "Do you want to replace it? [Y/N] " -n 1 -r
  if [[ $REPLY =~ ^[Yy]$ ]]
  then
    echo
    echo "Removing current symlink..."
    unlink "$symlink_loc"
    create_symlink "$file_loc" "$symlink_loc"
    return
  fi
}

handle_existing_symlink() {
  file_loc="$1"
  symlink_loc="$2"

  if is_symlink_dest_equal_to "$symlink_loc" "$file_loc" ; then
    echo "--> $symlink_loc -> $file_loc ${GREEN}exists${RESET}."
    return 0
  else
    handle_wrong_existing_symlink "$file_loc" "$symlink_loc"
  fi
}

handle_delete_previous_file() {
  file_loc="$1"
  symlink_loc="$2"

  printf "\\nDeleting %s...\\n" "$symlink_loc"
  rm -rf "$symlink_loc"
  create_symlink "$file_loc" "$symlink_loc"
}

handle_move_previous_file() {
  file_loc="$1"
  symlink_loc="$2"

  printf "\\nMoving %s to ~%s/.other..." "$symlink_loc" "$HOME"
  mkdir "$HOME/.other"
  mv "$symlink_loc" "$HOME/.other"
  create_symlink "$file_loc" "symlink_loc"
}

handle_existing_non_symlink() {
  file_loc="$1"
  symlink_loc="$2"

  echo "It seems like $symlink_loc already exists."
  read -p "Do you want to [d]elete, [m]ove (-> $HOME/.other/) or [k]eep $symlink_loc? " -n 1 -r
  if [[ $REPLY =~ ^[Dd]$ ]]
  then
    handle_delete_previous_file "$file_loc" "$symlink_loc"
  elif [[ $REPLY =~ ^[Mm]$ ]]; then
    handle_move_previous_file "$file_loc" "$symlink_loc"
  else
    printf "\\nKeeping %s...\\n" "$symlink_loc"
    return 0
  fi
}

handle_existing_file() {
  file_loc="$1"
  symlink_loc="$2"

  if is_symlink "$symlink_loc"; then
    handle_existing_symlink "$file_loc" "$symlink_loc"
  else
    handle_existing_non_symlink "$file_loc" "$symlink_loc"
  fi
}

custom_link() {
  file_loc="$1"
  symlink_loc="$2"

  if ! file_exists "$file_loc"; then
    invalid_file_error "$file_loc" "$symlink_loc"
  elif file_exists "$symlink_loc"; then
    handle_existing_file "$file_loc" "$symlink_loc"
  else
    symlink_dir=$(dirname "$symlink_loc")

    if ! is_directory "$symlink_loc"; then
      handle_non_existing_symlink_directory "$file_loc" "$symlink_loc"
    else
      create_symlink "$file_loc" "$symlink_loc"
    fi
  fi
}

custom_link "$HOME/.dotfiles/bash/.bash_profile" "$HOME/.bash_profile"
custom_link "$HOME/.dotfiles/bash/.bashrc" "$HOME/.bashrc"
custom_link "$HOME/.dotfiles/nvim/init.vim" "$HOME/.config/nvim/init.vim"
custom_link "$HOME/.dotfiles/tmux/.tmux.conf" "$HOME/.tmux.conf"

I'm not sure whether the outsourcing of that many methods makes sense/the code more readable. What do you think? How can I further improve my code?

\$\endgroup\$
1
  • \$\begingroup\$ Why this: "${RED} ${RESET}? (RED and RESET separate by whitespaces) \$\endgroup\$
    – hjpotter92
    Commented Dec 21, 2017 at 0:01

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.