#!/bin/bash

## Take an existing, tar-based CiviCRM directory and convert it to a git working directory

#### Helpers ####

###########################################
## usage: do_gitify <repo-url> <existing-dir> [git-checkout-options]
function do_gitify() {
  REPO="$1"
  TGT="$2"
  TMP="${TGT}.tmp"
  shift 2

  if [ -d "$TGT/.git" ]; then
    echo "[[Already checked out git repo ($TGT) -- skip $REPO]]"
    return
  fi
  [ -d $TGT ] || mkdir -p "$TGT"
  [ -d $TMP ] && rm -rf "$TMP"
  echo "[[Checkout $REPO ($TMP)]]"
  echo "[git clone "$@" "$REPO" "$TMP"]"
  git clone "$@" "$REPO" "$TMP"

  echo "[[Swap metadata]]"
  mv "$TMP/.git" "$TGT/.git"

  echo "[[Remove local modifications]]"
  pushd "$TGT" > /dev/null
  git checkout -- .
  popd > /dev/null

  rm -rf "$TMP"
}

###########################################
## add hook shims to a repo
## usage: do_hookify <canonical-repo-name> <repo-path> <relative-hook-path>
function do_hookify() {
  GIT_CANONICAL_REPO_NAME="$1"
  TGT="$2"
  HOOK_DIR="$3"
  if [ -n "$CIVICRM_GIT_HOOKS" ]; then
    echo "[[Install recommended hooks ($TGT)]]"
    for HOOK in commit-msg post-checkout post-merge pre-commit prepare-commit-msg post-commit pre-rebase post-rewrite ;do
          cat << TMPL > "$TGT/.git/hooks/$HOOK"
#!/bin/bash
if [ -f "\$GIT_DIR/${HOOK_DIR}/${HOOK}" ]; then
  ## Note: GIT_CANONICAL_REPO_NAME was not provided by early hook-stubs
  export GIT_CANONICAL_REPO_NAME="$GIT_CANONICAL_REPO_NAME"
  source "\$GIT_DIR/${HOOK_DIR}/${HOOK}"
fi
TMPL
      chmod +x "$TGT/.git/hooks/$HOOK"
    done
  else
    echo "[[Skip hook installation ($TGT) -- use \"--hooks\" to enable]]"
  fi
}

###########################################
## Create or update the URL of a git remote
## usage: git_set_remote <local-repo-path> <remote-name> <remote-url>
function git_set_remote() {
  REPODIR="$1"
  REMOTE_NAME="$2"
  REMOTE_URL="$3"
  echo "[[Set remote ($REMOTE_NAME => $REMOTE_URL within $REPODIR)]]"

  pushd "$REPODIR" >> /dev/null
    git remote set-url "$REMOTE_NAME"  "$REMOTE_URL" >/dev/null 2>&1 || git remote add "$REMOTE_NAME"  "$REMOTE_URL"
  popd >> /dev/null
}

###########################################
## usage: do_targzify <targz-url> <file-name> <existing-dir>
## Fetches a tar.gz archive and unpacks it in the current directory
function do_targzify() {
  TARGZURL="$1"
  TARFILE="$2"
  TGT="$3"
  shift 3

  if [ -d "$TGT" ]; then
    echo "[[Already have a copy of the archive ($TGT) -- skip $TARGZURL]]"
    return
  fi

  TMP=`mktemp -d`

  echo "[[Downloading $TARGZURL ($TMP)]]"
  echo "[wget \"$TARGZURL\" -O \"$TMP/$TARFILE\"]"

  pushd "$CIVICRM_ROOT" > /dev/null
  wget -q "$TARGZURL" -O "$TMP/$TARFILE"
  tar zxfv "$TMP/$TARFILE"
  popd

  rm "$TMP/$TARFILE"
  rmdir "$TMP"
}

###########################################
## usage: do_gencode <civicrm-path>
function do_gencode() {
  pushd "$1/xml" > /dev/null
    if [ -f "GenCode.php" ]; then
      echo "[[Generate files]]"
      php GenCode.php
    else
      echo "[[Skip \"Generate files\"]]"
    fi
  popd > /dev/null
}

## usage: do_setupconf <civicrm-path>
function do_setupconf() {
  pushd "$1" >> /dev/null
    echo "[[Initialize bin/setup.conf]]"
    if [ ! -f "bin/setup.conf" ]; then
      pwd
      echo       cp "bin/setup.conf.txt" "bin/setup.conf"
      cp "bin/setup.conf.txt" "bin/setup.conf"
    fi
    echo "[[chmod 600 bin/setup.conf]]"
    chmod 600 bin/setup.conf
    echo ""
    echo "====================[ Next steps (for Civi v4.6+) ]===================="
    echo "  * Edit the following file and fill in credentials for the CiviCRM DB."
    echo "    $1/bin/setup.conf"
    echo "  * Perform one of these steps:"
    echo "    + Run 'bin/setup.sh -Dg' to download and generate missing code."
    echo "    + Run 'bin/setup.sh' to download code and reset the CiviCRM DB"
    echo "      with the latest schema."
    echo "  * If this is a network-accessible server (eg staging/production), then"
    echo "    setup.conf may present a security issue. The permissions have been"
    echo "    preset to restrict access in most servers - but this may not work"
    echo "    in all environments. Please:"
    echo "    + Check whether the file is web-accessible."
    echo "    + Optionally, change the permissions."
    echo "    + Optionally, delete the file."
  popd > /dev/null
}

###########################################
## config_repo <repo-name> <local-path> <default-branch> <git-scripts-path>
##                  1            2              3               4
function config_repo() {
  do_gitify "${UPSTREAM_GIT_BASE_URL}/${1}.git" "$2" -b "$3"
  do_hookify "$1" "$2" "$4"
  ## doesn't work with http -- git ls-remote "git://github.com/civicrm/civicrm-drupalz.git" HEAD --exit-code &>- ; echo $?
  if [ -n "$FORK_GIT_BASE_URL" ]; then
    git_set_remote "$2" upstream "${UPSTREAM_GIT_BASE_URL}/${1}.git"
    git_set_remote "$2" origin "${FORK_GIT_BASE_URL}/${1}.git"
  else
    git_set_remote "$2" origin "${UPSTREAM_GIT_BASE_URL}/${1}.git"
  fi
}

function check_dep() {
  if [ -z "`which git`" ]; then
    echo "command not found: git"
    exit 3
  fi
  if [ -z `which php` ]; then
    echo "command not found: php"
  fi
}

###########################################
#### Main: Parse arguments

set -e

CIVICRM_CMS=""
CIVICRM_ROOT=""
CIVICRM_L10N=""
CIVICRM_GIT_HOOKS=""
CIVICRM_BRANCH="master"
FORK_GIT_BASE_URL=""
UPSTREAM_GIT_BASE_URL="https://github.com/civicrm"
SKIP_GENCODE=

while [ -n "$1" ]; do
  if [ "$1" == "--l10n" ]; then
    CIVICRM_L10N="$1"
  elif [ "$1" == "--hooks" ]; then
    CIVICRM_GIT_HOOKS="$1"
  elif [ "$1" == "--upstream" ]; then
    shift
    UPSTREAM_GIT_BASE_URL="$1"
  elif [ "$1" == "--fork" ]; then
    shift
    FORK_GIT_BASE_URL="$1"
  elif [ "$1" == "--skip-gencode" ]; then
    SKIP_GENCODE=1
  elif [ "$1" == "--branch" ]; then
    shift
    CIVICRM_BRANCH="$1"
  elif [ -z "$CIVICRM_CMS" ]; then
    ## First arg
    CIVICRM_CMS="$1"
  elif [ -z "$CIVICRM_ROOT" ]; then
    ## Third arg
    CIVICRM_ROOT="$1"
  else
    echo "unrecognized argument: $1"
    exit 2
  fi
  shift
done

if [ -z "$CIVICRM_ROOT" -o ! -d "$CIVICRM_ROOT" -o -z "$UPSTREAM_GIT_BASE_URL" -o -z "$CIVICRM_CMS" ]; then
  echo "Convert a directory into a set of CiviCRM git clones"
  echo "usage: $0 <Drupal|Drupal6|Joomla|WordPress|all> <existing-civicrm-root> [--fork <base-url>] [--upstream <base-url>] [--l10n] [--hooks] [--branch <branch>]"
  echo "  <cms-name>: one of: Drupal|Drupal6|Joomla|WordPress|all"
  echo "  <git-base-url>: a base URL shared by the desiried git repos (e.g. git://github.com/civicrm)"
  echo "  <existing-civicrm-root>: the main directory containing CiviCRM"
  echo "  --upstream <base-url>: specify the base URL for upstream repositories"
  echo "  --fork <base-url>: specify the base URL for your personal fork repositories"
  echo "  --l10n: optionally fetch localization data"
  echo "  --hooks: optionally install recommended git hooks; the hooks are mostly"
  echo "           tested with git CLI under Linux and OSX; they haven't been"
  echo "           tested with git GUIs or Windows"
  echo "  --branch <branch>: specy the base branch name to checkout (ex: 'master', '4.4')"
  echo "           For some repos, this name is adapted (ex: Drupal's '7.x-master' or '6.x-master'"
  echo "  --skip-gencode: optionally disable gencode execution"
  echo ""
  echo "Note: If pointing to a pre-existing directory, your local changes may be replaced by"
  echo "the pristine code from git. If you've made changes, then make sure there's a backup!"
  echo ""
  echo "example: $0 Drupal /var/www/drupal7/sites/all/modules/civicrm"
  echo "  (checkout core code plus Drupal 7.x integration code)"
  echo ""
  echo "example: $0 Drupal6 /var/www/drupal6/sites/all/modules/civicrm"
  echo "  (checkout core code plus Drupal 6.x integration code)"
  echo ""
  echo "example: $0 all ~/src/civicrm --upstream git@github.com:civicrm --l10n"
  echo "  (checkout core code plus Drupal 7.x, Joomla, and WordPress integration code and l10n using SSH)"
  exit 1
fi

###########################################
#### Main: Update git repo metadata ####
check_dep

## config_repo <repo-name>         <local-path>                <default-branch>      <git-scripts-path>
config_repo     civicrm-core       "$CIVICRM_ROOT"            "$CIVICRM_BRANCH"      "../tools/scripts/git"
config_repo     civicrm-packages   "$CIVICRM_ROOT/packages"   "$CIVICRM_BRANCH"      "../../tools/scripts/git"
case "$CIVICRM_CMS" in
  Drupal)
    config_repo civicrm-drupal     "$CIVICRM_ROOT/drupal"     "7.x-$CIVICRM_BRANCH"  "../../tools/scripts/git"
    ;;
  Drupal6)
    config_repo civicrm-drupal     "$CIVICRM_ROOT/drupal"     "6.x-$CIVICRM_BRANCH"  "../../tools/scripts/git"
    ;;
  Joomla)
    config_repo civicrm-joomla     "$CIVICRM_ROOT/joomla"     "$CIVICRM_BRANCH"      "../../tools/scripts/git"
    ;;
  WordPress)
    config_repo civicrm-wordpress  "$CIVICRM_ROOT/WordPress"  "$CIVICRM_BRANCH"      "../../tools/scripts/git"
    ;;
  all)
    config_repo civicrm-drupal     "$CIVICRM_ROOT/drupal"     "7.x-$CIVICRM_BRANCH"  "../../tools/scripts/git"
    config_repo civicrm-joomla     "$CIVICRM_ROOT/joomla"     "$CIVICRM_BRANCH"      "../../tools/scripts/git"
    config_repo civicrm-wordpress  "$CIVICRM_ROOT/WordPress"  "$CIVICRM_BRANCH"      "../../tools/scripts/git"
    ;;
  none)
    ;;
  *)
    echo "Unrecognized CMS: $CIVICRM_CMS"
esac

if [ "$CIVICRM_L10N" == "--l10n" ]; then
  do_targzify "https://download.civicrm.org/civicrm-l10n-core/archives/civicrm-l10n-daily.tar.gz" "civicrm-l10n-daily.tar.gz" "$CIVICRM_ROOT/l10n"
fi

if [ -f "$CIVICRM_ROOT/composer.json" ]; then
  ## Civi v4.6+
  do_setupconf "$CIVICRM_ROOT"
elif [ -z "$SKIP_GENCODE" ]; then
  do_gencode "$CIVICRM_ROOT"
fi
