#!/bin/sh

set -o errexit
REVISION="$VENDORPULL_REVISION"
set -o nounset

# @params [string] Error message
vendorpull_fail() {
  echo "ERROR: $1" 1>&2
  exit 1
}

# @params [string] File path
# @params [string] Error message
vendorpull_assert_defined() {
  if [ -z "$1" ]
  then
    vendorpull_fail "$2"
  fi
}

# @params [string] Command
vendorpull_assert_command() {
  if ! command -v "$1" > /dev/null
  then
    vendorpull_fail "You must install $1 in order to use this tool"
  fi
}

# @params [string] File path
vendorpull_assert_file() {
  if [ ! -f "$1" ]
  then
    vendorpull_fail "No such file: $1"
  fi
}
# @params [string] Dependency definition
vendorpull_dependencies_name() {
  RESULT="$(echo "$1" | cut -d ' ' -f 1)"
  vendorpull_assert_defined "$RESULT" "Missing dependency name"
  echo "$RESULT"
}

# @params [string] Dependency definition
vendorpull_dependencies_repository() {
  RESULT="$(echo "$1" | cut -d ' ' -f 2)"
  vendorpull_assert_defined "$RESULT" "Missing dependency url"
  echo "$RESULT"
}

# @params [string] Dependency definition
vendorpull_dependencies_revision() {
  RESULT="$(echo "$1" | cut -d ' ' -f 3)"
  vendorpull_assert_defined "$RESULT" "Missing dependency revision"
  echo "$RESULT"
}

# @params [string] Path to DEPENDENCIES file
# @params [string] Pattern
vendorpull_dependencies_find() {
  if [ ! -f "$1" ]
  then
    echo ""
  else
    grep "^$2" < "$1" | head -n 1
  fi
}

# @params [string] Path to DEPENDENCIES file
# @params [string] Pattern
vendorpull_dependencies_safe_find() {
  DEFINITION="$(vendorpull_dependencies_find "$1" "$2")"
  vendorpull_assert_defined "$DEFINITION" "Could not find a dependency $2 in $1"
  echo "$DEFINITION"
}

# @params [string] Path to DEPENDENCIES file
# @params [string] Dependency name
vendorpull_dependencies_find_exact() {
  if [ ! -f "$1" ]
  then
    echo ""
  else
    grep "^$2 " < "$1" | head -n 1
  fi
}

# @params [string] Path to DEPENDENCIES file
# @params [string] Dependency name
# @params [string] Dependency url
# @params [string] Dependency revision
vendorpull_dependency_set() {
  DEPENDENCY="$(vendorpull_dependencies_find_exact "$1" "$2")"
  if [ -z "$DEPENDENCY" ]
  then
    echo "$2 $3 $4" >> "$1"
  else
    # Use a delimiter other than the slash
    # in case the dependency name contains one
    if [ "$(uname)" = "Darwin" ]
    then
      sed -i .bak "s|^$2 .*|$2 $3 $4|" "$1"
      rm "$1.bak"
    else
      sed -i "s|^$2 .*|$2 $3 $4|" "$1"
    fi
  fi
}
# Clone a git repository
# @params [string] Git URL
# @params [string] Clone location
# @params [string] Revision
vendorpull_clone_git() {
  git clone --recurse-submodules --jobs 8 "$1" "$2"
  if [ "$3" != "HEAD" ]
  then
    git -C "$2" reset --hard "$3"
  fi
}

# Un-git the repository and its dependencies (if any)
# @params [string] Repository directory
vendorpull_clean_git() {
  GIT_FILES=".git .gitignore .github .gitmodules"
  git -C "$1" submodule foreach "rm -rf $GIT_FILES"
  for file in $GIT_FILES
  do
    rm -rf "$1/${file:?}"
  done
}

# @params [string] Repository directory
# @params [string] Patch file
vendorpull_patch_git() {
  git -C "$1" apply --3way "$2"
}

vendorpull_assert_command 'git'

# Get the root directory of the current git repository
INSTALLATION_DIRECTORY="$(git rev-parse --show-toplevel)"

DEPENDENCIES_FILE="$INSTALLATION_DIRECTORY/DEPENDENCIES"

# The repository to install from.
# TODO: We should find a way to make this resistant to repository renames, etc.
VENDORPULL_REPOSITORY="https://github.com/jviotti/vendorpull"

TEMPORARY_DIRECTORY="$(mktemp -d -t vendorpull-clone-XXXXX)"
echo "Setting up temporary directory at $TEMPORARY_DIRECTORY..."
temporary_directory_clean() {
  rm -rf "$TEMPORARY_DIRECTORY"
}
trap temporary_directory_clean EXIT

# Clone the latest available version of vendorpull to perform
# the initial dependencies installation
echo "Cloning vendorpull..."
vendorpull_clone_git "$VENDORPULL_REPOSITORY" "$TEMPORARY_DIRECTORY" HEAD

if [ -n "$REVISION" ]
then
  # We use this for testing purposes, as otherwise we cannot
  # send a pull-request and have the changes to the program
  # be taken into account by the bootstrap script.
  echo "Using input revision $REVISION"
  HASH="$REVISION"
else
  HASH="$(git -C "$TEMPORARY_DIRECTORY" rev-parse HEAD)"
fi

# Make sure we use the same vendorpull version that we are about
# to install in order to not cause unpredictable results.
git -C "$TEMPORARY_DIRECTORY" checkout "$HASH"

echo "Creating DEPENDENCIES files..."
vendorpull_dependency_set "$DEPENDENCIES_FILE" vendorpull "$VENDORPULL_REPOSITORY" "$HASH"

# After vendorpull has been declared in the repo, run a full update
echo "Pulling dependencies ..."
cd "$INSTALLATION_DIRECTORY"
"$TEMPORARY_DIRECTORY/pull"

echo "Done!"
