#!/bin/bash -e
#Assists sparse checkouts of an ICEDUST package / project
#set -x

##############################################################################
# Pre-setup
##############################################################################
case `uname` in
  Darwin) ECHO=echo ;;
  *) ECHO="echo -e" ;;
esac

usage () {
  $ECHO "git icedust-add [options] SubSystem/Package"
  $ECHO "git icedust-add [options] -f FILE"
  $ECHO
  $ECHO "Options:"
  $ECHO "-h, --help         \tthis help message"
  $ECHO
  $ECHO "-t, --thorough     \tSwitch off speed-increasing measures that may cause packages to be improperly checked out"
  $ECHO "-D, --depend       \tcheck for dependencies and check them out too"
  $ECHO "-d, --debug        \tenable debug output"
  $ECHO "-f, --file FILE    \tread the list of packages to be checkoed out from FILE"
  $ECHO "-q, --quiet, -z    \tdo not print out progress"
  $ECHO "--skip-setup       \tdon't run git icedust-setup, useful when used in other scripts"
  exit $1
}

VERBOSE=1
VERBOSE_STREAM=/dev/stderr
DEBUG_STREAM=/dev/null

RED='\033[31m'
NORMAL='\033[0m'

verbose () {
  if [ "X$VERBOSE" = X1 ]; then
    $ECHO "$@"
  fi
}

case `git --version` in
  git\ version\ 1.7*)
    # git 1.7.x does not support a leading slash in .gitignore and .git/info/sparse-checkout
    LEADING_SLASH= ;;
  *)
    LEADING_SLASH=/ ;;
esac

##############################################################################
# Parse options
##############################################################################
ReadFile(){
  InFile="$1"
  PACKAGES=( `grep -ve '^\s*#' "$InFile" | tr '\r\n' ' ' ` "${PACKAGES[@]}"  )
}

INITOPTIONS=""
PACKAGES=( )
CHECK_DEPS=false
BeThorough=false
while [ "$#" != 0 ]; do
  case "$1" in
    -h | --help )
      usage 0;;
    -t | --thorough )
      INITOPTIONS="$INITOPTIONS $1"
      shift; BeThorough=true;;
    -d | --debug )
      INITOPTIONS="$INITOPTIONS $1"
      shift; set -x; DEBUG_STREAM=/dev/stderr ;;
    -D | --depend )
      CHECK_DEPS=true; shift;;
    -f | --file )
      OPTION=$1; shift
      INPUT_FILE="$1"; shift
      if [ ! "$INPUT_FILE" ]; then
        $ECHO "git icedust-add: option $OPTION requires an argument"
        $ECHO
        usage 1
      elif [ ! -r "$INPUT_FILE" ]; then
        $ECHO "git : file $INPUT_FILE does not exist or is not readable"
        $ECHO
        usage 1
      fi
      ReadFile "$INPUT_FILE"
      unset OPTION
      ;;
    -q | --quiet | -z )
      INITOPTIONS="$INITOPTIONS $1"
      shift; set +x; VERBOSE=0; VERBOSE_STREAM=/dev/null ;;
    --skip-init)
      SKIP_INIT=true; shift;;
    -*)
      $ECHO Unknown option $1 ; usage 1 ;;
    *)
      PACKAGES=( "$1" "${PACKAGES[@]}" )
      shift
    ;;
  esac
done


if [ "${#PACKAGES[@]}" -lt 1 ] ; then
  $ECHO "Error: You need to specify at least one package or input file." 
  usage 1
fi

##############################################################################
# Check we're setup properly
##############################################################################
export ICEDUST_HOME
export ICEDUST_PROJECT
if [ -z "$INTERNAL_CALL_CHECKDEPS" ];then
  tmp="`git icedust-home "$ICEDUST_HOME" "$ICEDUST_PROJECT"||true`"
  # Check if there was an issue getting the variables
  if grep 'Error' <<< "$tmp" &> "$DEBUG_STREAM" ;then
          $ECHO $tmp
          $ECHO "icedust-add: Error: Problem with ICEDUST_HOME and ICEDUST_PROJECT variables (see above messge)."
          $ECHO "Current values: "
          $ECHO "   ICEDUST_HOME=$ICEDUST_HOME"
          $ECHO "   ICEDUST_PROJECT=$ICEDUST_PROJECT"
          exit 1
  fi
  ICEDUST_HOME=`sed 's!^.*ICEDUST_HOME=\([^;]\+\);.*!\1!' <<<$tmp`
  ICEDUST_PROJECT=`sed 's!^.*ICEDUST_PROJECT=\([^;]\+\);.*!\1!' <<<$tmp`
  unset tmp
fi 

PackageDirectory="$ICEDUST_HOME/$ICEDUST_PROJECT/packages"
ExternalDirectory="$PackageDirectory/EXTERNALS"
if [ -z "$INTERNAL_CALL_CHECKDEPS" ];then
  ProjectCmtDirectory="$ICEDUST_HOME/$ICEDUST_PROJECT/cmt"
  for dir in "$PackageDirectory"/.git "$ExternalDirectory"/.git "$ProjectCmtDirectory";do
  if ! [ -d "$dir" ]; then
          $ECHO "Error: Please run git icedust-setup first"
          exit 1
  fi
  done
fi 
  
echo ICEDUST_HOME=$ICEDUST_HOME >$DEBUG_STREAM
echo ICEDUST_PROJECT=$ICEDUST_PROJECT >$DEBUG_STREAM

cd "$PackageDirectory"

##############################################################################
# Are the local, staged changes
##############################################################################
if [ -z "$INTERNAL_CALL_CHECKDEPS" ];then
  if [ "$(git status --porcelain --untracked=no | grep '^[ACDMRU]')" ]; then
    $ECHO "${RED}Error:${NORMAL} there are staged but not committed changes on your working tree, please commit or stash them."
    exit 1
  fi
fi

##############################################################################
# Check out the packages
##############################################################################
verbose "Checking out package(s) ${PACKAGES[@]}"

# copy the file so we can prepare the new version based on the original
cp -f "$PackageDirectory/.git/info/sparse-checkout" "$PackageDirectory/.git/info/sparse-checkout-new"
cp -f "$ExternalDirectory/.git/info/sparse-checkout" "$ExternalDirectory/.git/info/sparse-checkout-new"

RequirementsFile="$ICEDUST_HOME/$ICEDUST_PROJECT/cmt/requirements"

for Package in "${PACKAGES[@]}";do
  # Do we already have this package? 
  if ! $BeThorough && ( [ -d "$PackageDirectory/$Package" ] || [ -d "$ExternalDirectory/$Package" ] ) ; then continue ;fi 
  # prepare the line to go into the file
  Line="`$ECHO "$Package" | sed -e "s|[/]*$|/|;s|^/*|${LEADING_SLASH}|"`"
  IsGood=true
  if   [ -n "`cd "$PackageDirectory" && git ls-files "$Package" `" ];then
     $ECHO $Line>> "$PackageDirectory/.git/info/sparse-checkout-new"
  elif [ -n "`cd "$ExternalDirectory" && git ls-files "$Package" `" ];then
     $ECHO $Line>> "$ExternalDirectory/.git/info/sparse-checkout-new"
  else
     $ECHO "icedust-add: Error: Unknown package: $Package"
     IsGood=false
  fi
  #If this script was invoked by the user, prepare the Project's requirements file
  if [ -z "$INTERNAL_CALL_CHECKDEPS" ] && $IsGood && \
          ! grep '^\s*use\s*'$Package "$RequirementsFile" > $DEBUG_STREAM ;then
      $ECHO "use $Package" >> "$RequirementsFile"
  fi
done


# Remove duplicate entries as we update the old spare-checkout file
for dir in "$PackageDirectory" "$ExternalDirectory";do
        (
    cd "$dir"
    cat .git/info/sparse-checkout-new | sort -u > .git/info/sparse-checkout
    # Tidy up
    rm -f .git/info/sparse-checkout-new

    # Actually tidy up the working index
    git read-tree -m -u HEAD
    )
done

CURRENT_BRANCH=`basename $(git symbolic-ref -q HEAD)`

cd "$PackageDirectory"
# Check that we really got all packages
for Package in "${PACKAGES[@]}";do
  if [ ! -d "$PackageDirectory/$Package" ]; then
    if [ ! -d "$ExternalDirectory/$Package" ]; then
      $ECHO "package $Package does not exist in branch $CURRENT_BRANCH"
    fi
  fi
done 

##############################################################################
# Check all dependencies
##############################################################################
if $CHECK_DEPS;then
export INTERNAL_CALL_CHECKDEPS="YES"
  git icedust-check $INITOPTIONS --skip-init -H "$ICEDUST_HOME"
fi