#!/usr/bin/env bash
#
# author:  joez
# date:    2018.07.04

COMMAND="help"
SYNC="y"
SIZE="1G"
SOURCE="/local/work"
TARGET="/local/ramdisk"

# you should not change it
CONFIG_ROOT="$HOME/.ramdisk"
VERSION="v0.2"

function usage() {
  local self=`basename $0`

  cat <<EOF
Usage: $self <command> [<options>] [<args>]
  setup a ramdisk as a super fast storage for a workspace

  version: $VERSION

  CAUTION: need sudo permission to operate a ramdisk

Commands:
  mount [-n] [-s size] [<source>] [<target>]
    setup a ramdisk and sync workspace to it if necessary

    -n:         do not sync the workspace with the target ramdisk
    -s <size>:  memory size to used for the ramdisk, default $SIZE
    <source>:   workspace to be put into the ramdisk, default $SOURCE
    <target>:   ramdisk mount point path, default $TARGET

  umount [-n] [<target>]
    sync ramdisk with workspace if necessary and close it

    -n:         do not sync the workspace with the target ramdisk
    <target>:   ramdisk mount point path, default $TARGET

  info [<target>]
    check the information of the target ramdisk

    <target>:   ramdisk mount point path, default $TARGET

  help
    print the usage message

Examples:
  $self mount $SOURCE $TARGET
    setup a ramdisk at $TARGET and sync content from $SOURCE

  $self info $TARGET
    check the information about the ramdisk mounted at $TARGET

  $self umount $TARGET
    sync content from $TARGET to the original workspace and close it
EOF

}

function absdir() {
  (cd $1 2>/dev/null && PWD= /bin/pwd)
}

function ensure_dir() {
  if [ ! -e "$1" ]; then
    mkdir -p "$1"
    if [ $? -ne 0 ]; then
      exit 1
    fi
  fi
}

function ensure_sudo () {
  echo "SUDO permission is required to operate the ramdisk"
  echo "let's check it first, your credential may be requried"

  if sudo -v; then
    echo "ok"
  else
    echo "failed"
    exit 1
  fi
}

function setup_config () {
  ensure_dir $CONFIG_ROOT
  CONFIG_ROOT=$(absdir $CONFIG_ROOT)
}

function config_file() {
  local target=$(absdir $TARGET)
  if [ -n "$target" ]; then
    echo "$CONFIG_ROOT${target}source"
  else
    echo ""
  fi
}

function save_config() {
  local path=$(config_file)
  if [ -n "$path" ]; then
    ensure_dir $(dirname $path)
    echo $SOURCE > $path
  fi
}

function load_config() {
  local path=$(config_file)
  if [ -n "$path" ] && [ -e "$path" ]; then
    local val=`cat $path`
    if [ -n "$val" ]; then
      SOURCE=$val
    fi
  fi
}


# first arg is the command
if [ -n "$1" ]; then
  COMMAND="$1"
  shift
fi

# then the options
while getopts "ns:" OPTION
do
  case $OPTION in
    n ) SYNC="n";;
    s ) SIZE=$OPTARG;;
    * ) echo "Invalid option passed to '$0' (options:$@)"
    usage && exit 1;;
  esac
done

shift $((OPTIND-1))

# setup configuration folder
setup_config

# handle the command
if [ "$COMMAND" = "help" ]; then
  usage && exit
elif [ "$COMMAND" = "info" ]; then
  if [ -n "$1" ]; then
    if [ -e "$1" ]; then
      TARGET=$(absdir $1)
    else
      echo "$1 does not exist"
    fi
  fi
  load_config

  out=`df -h -t 'tmpfs' $TARGET 2>/dev/null`
  if [ $? -ne 0 ]; then
    echo "no ramdisk found at $TARGET"
  else
    echo "current ramdisk info:"
    echo "  SOURCE=$SOURCE"
    echo "  TARGET=$TARGET"
    echo ""
    echo "$out"
  fi
elif [ "$COMMAND" = "mount" ]; then
  if [ -n "$2" ]; then
    TARGET=$2
  fi
  ensure_dir $TARGET
  TARGET=$(absdir $TARGET)
  load_config

  if [ -n "$1" ]; then
    SOURCE=$1
  fi
  ensure_dir $SOURCE
  SOURCE=$(absdir $SOURCE)

  # check if there is already one
  out=`df -h -t 'tmpfs' $TARGET 2>/dev/null`
  if [ $? -eq 0 ]; then
    echo "A ramdisk at $TARGET has already existed, skip!"
    echo "$out"
    exit 1
  fi

  ensure_sudo

  echo "start to create a ramdisk ($SIZE) at $TARGET for workspace $SOURCE"
  sudo mount -t tmpfs -o size=$SIZE,uid=$(id -u),gid=$(id -g) tmpfs $TARGET
  if [ $? -ne 0 ]; then
    echo "failed"
    exit 1
  else
    echo "done"
    save_config
  fi

  if [ "$SYNC" = "y" ]; then
    echo "start to sync content from $SOURCE to $TARGET"
    echo "wait for a moment..."
    rsync -a $SOURCE/ $TARGET
    echo "done"
  fi
elif [ "$COMMAND" = "umount" ]; then
  if [ -n "$1" ]; then
    TARGET=$1
  fi
  ensure_dir $TARGET
  TARGET=$(absdir $TARGET)
  load_config

  if [ "$SYNC" = "y" ]; then
    echo "start to sync content from $TARGET to $SOURCE"
    echo "wait for a moment..."
    rsync -au $SOURCE/ $TARGET
    echo "done"
  fi

  ensure_sudo

  echo "now close the ramdisk at $TARGET"
  sudo umount $TARGET
  if [ $? -ne 0 ]; then
    echo "failed"
    exit 1
  else
    echo "done"
  fi
else
  echo "unsupported command!"
  usage && exit 1
fi
