#! /usr/bin/env bash
set -e

abs_dirname()  {
  local path="$1"
  local cwd
  cwd="$(pwd)"

  while [ -n "$path" ]; do
    cd "${path%/*}" 2> /dev/null
    local name="${path##*/}"
    path="$(resolve_link "$name" || true)"
  done

  pwd
  cd "$cwd"
}

abs_path()  {
  local path="$1"
  echo "$(cd "$(abs_dirname "$path")" && pwd)/$(basename "$path")"
}

resolve_link()  {
  $(type -p greadlink readlink | head -1) "$1"
}

resolve_archive() {
  local archive="$1"

  archive="$(abs_path "$archive")"

  if [ ! -f "$archive" ]; then
    echo "ERROR: \"${archive}\" is not a file." 1>&2
    exit 1
  fi

  echo "$archive"
}

resolve_volname()  {
  local archive="$1"
  local file
  local dir

  file="$(basename "$archive")"
  dir="$(dirname "$archive")"

  docker run --rm \
    --volume "${dir}:/source" \
    alpine:latest \
    sh -c "tar --exclude=\"*/*/*\" -tzf \"/source/${file}\" \
               | grep -v '^[^/]\+/[^/]\+$' | sed s'/.$//'" 2> /dev/null
}

help()  {
  echo "usage: docker-volume-restore <archive> [<volume-name>]"
  echo ""
  echo "Restores contents from a *.tar.gz archive to a Docker volume."
  echo ""
  echo "Arguments:"
  echo "   <archive>      - Filename to restore data from. Must be a .tar.gz"
  echo "                    archive with a single root directory."
  echo "   <volume-name>  - Optional argument to specify the volume name to"
  echo "                    restore to. If not specified, will use name of"
  echo "                    top-level directory in the archive."
}

main()  {
  local archive="$1"
  local volname="$2"
  local archive_volname
  local archive_file
  local archive_dir

  if [ -z "$archive" ]; then
    help 1>&2
    exit 1
  fi

  archive="$(resolve_archive "$archive")"
  archive_file="$(basename "$archive")"
  archive_dir="$(dirname "$archive")"
  archive_volname="$(resolve_volname "$archive")"

  if [ "$(echo "$archive_volname" | wc -l)" -gt 1 ]; then
    echo "ERROR: \"$archive_file\" has more than one root directory." 1>&2
    exit 1
  fi

  if [ -z "$volname" ]; then
    volname="$archive_volname"
  fi

  if docker volume inspect "$volname" &> /dev/null; then
    echo "ERROR: Volume \"${volname}\" already exists." 1>&2
    exit 1
  fi

  echo "Restoring volume ${volname} from: ${archive_file}"
  docker volume create "${volname}"
  docker run --rm \
    --volume "${volname}:/target" \
    --volume "${archive_dir}:/source" \
    alpine:latest \
    sh -c "cd /target && tar --strip-components=1 \
                             -xvzf \"/source/${archive_file}\""

  echo "Volume \"${volname}\" was restored from: ${archive_file}"
}

main "$@"
