#!/bin/bash

# basic usage, error and help function
usage() {
  [[ -n $1 ]] && echo -e "\n  $1"
  echo -e "\n  Usage:  ${0##*/} [-u, -w] [-l, -s (branchname)] \n"
  echo -e "    ${0##*/} (options) [(branchname)] will write commands to stdout needed to create"
  echo -e "    tarballs from your local TDE GIT tree (default - no options/arguments). When called"
  echo -e "    with the '-w' argument, the script will create tarballs from from your local GIT"
  echo -e "    tree in the directory specified by 'tgzpath' within the script. When called with"
  echo -e "    the '-u' option, it will update the current GIT tree.\n"
  echo -e "    The '-l' and '-s branchname' options will (-l) list the current branch for each module"
  echo -e "    in the git tree and (-s branchname) will switch each module in the GIT tree to"
  echo -e "    the given GIT branch if it is available for that module. In addition a 'git pull'"
  echo -e "    and 'git submodule update' are called on each module switched.\n"
  echo -e "    NOTE:: You MUST set the variables 'tdepath' and 'tgzpath' (and 'gituser') in the"
  echo -e "    script for the script to work. tdepath is the path to your local GIT tree and"
  echo -e "    tgzpath is where you want the completed tarballs placed. gituser (optional) is"
  echo -e "    just your username for the TDE GIT tree. Enjoy.\n"
  exit 1
}

# respond to help
[[ "$@" =~ -h ]] && usage

# array for tde modules to make individual packages
tdeapps=('applications'
	'dependencies'
	'libraries')

# array for tde modules to create single package from module
tdemods=('common'
	'tdeaccessibility'
	'tdeaddons'
	'tdeadmin'
	'tdeartwork'
	'tdebase'
	'tdebindings'
	'tdeedu'
	'tdegames'
	'tdegraphics'
	'tdelibs'
	'tdemultimedia'
	'tdenetwork'
	'tdepim'
	'tdesdk'
	'tdetoys'
	'tdeutils'
	'tdevelop'
	'tdewebdev')

tdepath="/mnt/pv/home/david/tde13/tde"
tgzpath="/mnt/pv/home/david/tde13/tgz"
branch="v3.5.13-sru"
gituser=drankin
declare -a remba                                      # remote branches available array
dtcode="$(date +%Y%m%d-%H%M%S)"                       # date tag to use with script
srulist="/tmp/v3.5.13-sru_modules-${dtcode}.txt"
:> $srulist

## function - reset current module to HEAD and update
gitresetHEAD() {

  ## normal reset to head, discard local edits and update
  git reset --hard HEAD
  git clean -dxf
  git pull
  git reset --hard HEAD
  git clean -dxf
  sed -i "s/system@/${gituser}@/g" .gitmodules
  git submodule init
  git submodule update --recursive
  git submodule foreach --recursive "git checkout master"
  git submodule foreach --recursive "git pull"
  git checkout -- .gitmodules

}

## function - pull and submodule update on module
gitpullsmupdt() {
  git pull
  git submodule update
}

## function - get remote branches available and parse for branch name
gitremotebranches() {
  oifs="$IFS"                # save current internal field separator
  IFS=$'\n'                  # set IFS to only break on newline
  let ct=0
  remba=( $(git branch -r) )
  for i in ${remba[@]}; do
    brname=${i// ->*}
    remba[$ct]=${brname##*/}
    ((ct++))
  done
  IFS="$oifs"                # restore original IFS ( IFS=$' \t\n' )
}

## check tde path or show usage
[[ -r "$tdepath" ]] || usage "ERROR: local copy of tde not found in '$tdepath'" >&2

## save present working dir and change to tdepath/main
mydir="$PWD"
cd "${tdepath}/main" || usage "Error: unable to change to tde directory '${tdepath}/main'" >&2

## switch local GIT repository to $branch before creating tarballs if -s|--switch given
if [[ "$@" =~ '-s' ]]; then

  ## loop through GIT modules in main and checkout v3.5.13-sru if available
  for j in ${tdemods[@]}; do

    cd "${tdepath}/main/${j}" || { echo "Warning: unable to change to '${j}' skipping..." >&2; continue; }

    ## get current local branch
    clb="$(git branch -l)"
    clb="${clb##* }"

    ## get remote branches available and parse for branch name
    gitremotebranches

    ## formatted output to $srulist file
    printf "module: %-32s  branch: %-13s  available: " $j $clb >> $srulist
    echo "${remba[@]}" >> $srulist

    ## test local branch against target branch, if on correct branch, update and then continue
    if test "$clb" == "$branch"; then
      echo "Module: '$j' - current local branch is already '$branch'"
      ## update the local branch
      gitpullsmupdt
      continue
    else
      ## test that branch is available branch and switch to branch
      if [[ "${remba[@]}" =~ "$branch" ]]; then
        echo "changing module '$j' to branch '$branch' (git checkout $branch)"
        ## test good checkout
        if git checkout $branch; then
	  gitpullsmupdt
	else
	  ## issue fail warning and attempt to reset to HEAD and try again
	  echo "Warning: failed to checkout '$branch' for module '$j'" >&2
	  echo "attempting to reset to HEAD and then switch to $branch" >&2
	  gitresetHEAD
	  if git checkout $branch; then
	    gitpullsmupdt
	  else
	    echo "ERROR: switch of module '$j' to '$branch' -- FAILED" >&2
	  fi
        fi
      else
	echo "Warning: '$branch' is not available for module '$j'" >&2
      fi
    fi

  done

  ## loop through GIT modules in applications, dependencies and libraries
  for i in ${tdeapps[@]}; do
    ## restore directory to "${tdepath}/main"
    cd "${tdepath}/main" || usage "Error: unable to change to tde directory '${tdepath}/main'" >&2
    for j in $(find ${i} -maxdepth 1 -type d | sort); do
      [[ ${j##*/} == $i ]] ||  [[ ${j##*/} == admin ]] ||  [[ ${j##*/} == cmake ]] &&  continue

      ## change to module directory and checkout v3.5.13-sru
      cd "${tdepath}/main/${j}" || { echo "Warning: unable to change to '${j}' skipping..." >&2; continue; }

      ## get current local branch
      clb="$(git branch -l)"
      clb="${clb##* }"

      ## get remote branches available and parse for branch name
      gitremotebranches

      ## formatted output to $srulist file
      printf "module: %-32s  branch: %-13s  available: " $j $clb >> $srulist
      echo "${remba[@]}" >> $srulist

      ## test local branch against target branch, if on correct branch, update and then continue
      if test "$clb" == "$branch"; then
	echo "Module: '$j' - current local branch is already '$branch'"
	## update the local branch
	gitpullsmupdt
	continue
      else
	## test that branch is available branch and switch to branch
	if [[ "${remba[@]}" =~ "$branch" ]]; then
	  echo "changing module '$j' to branch '$branch' (git checkout $branch)"
	  ## test good checkout
          if git checkout $branch; then
	    gitpullsmupdt
	  else
	    ## issue fail warning and attempt to reset to HEAD and try again
	    echo "Warning: failed to checkout '$branch' for module '$j'" >&2
	    echo "attempting to reset to HEAD and then switch to $branch" >&2
	    gitresetHEAD
	    if git checkout $branch; then
	      gitpullsmupdt
	    else
	      echo "ERROR: switch of module '$j' to '$branch' -- FAILED" >&2
	    fi
          fi
	else
	  echo "Warning: '$branch' is not available for module '$j'" >&2
	fi
      fi

    done
  done

  ## restore directory to "${tdepath}/main"
  cd "${tdepath}/main" || usage "Error: unable to change to tde directory '${tdepath}/main'" >&2

fi

## if called with -l | --list, then just list the current and available branches for each module
if [[ "$@" =~ '-l' ]]; then

  for j in ${tdemods[@]}; do

    cd "${tdepath}/main/${j}" || { echo "Warning: unable to change to '${j}' skipping..." >&2; continue; }

    ## get current local branch
    clb="$(git branch -l)"
    clb="${clb##* }"

    ## get remote branches available and parse for branch name
    gitremotebranches

    ## formatted output to $srulist file
    printf "module: %-32s  branch: %-13s  available: " $j $clb | tee -a $srulist
    echo "${remba[@]}" | tee -a $srulist

  done

  for i in ${tdeapps[@]}; do
    cd "${tdepath}/main" || usage "Error: unable to change to tde directory '${tdepath}/main'" >&2
    for j in $(find ${i} -maxdepth 1 -type d | sort); do
      [[ ${j##*/} == $i ]] ||  [[ ${j##*/} == admin ]] ||  [[ ${j##*/} == cmake ]] &&  continue

      ## change to module directory and checkout v3.5.13-sru
      cd "${tdepath}/main/${j}" || { echo "Warning: unable to change to '${j}' skipping..." >&2; continue; }

      ## get current local branch
      clb="$(git branch -l)"
      clb="${clb##* }"

      ## get remote branches available and parse for branch name
      gitremotebranches

      ## formatted output to $srulist file
      printf "module: %-32s  branch: %-13s  available: " $j $clb | tee -a $srulist
      echo "${remba[@]}" | tee -a $srulist
    done
  done

fi


## update local GIT repository before creating tarballs if -u|--update given
if [[ "$@" =~ '-u' ]]; then

  ## loop through GIT modules in main and checkout v3.5.13-sru
  for j in ${tdemods[@]}; do

    cd "${tdepath}/main/${j}" || { echo "Warning: unable to change to '${j}' skipping..." >&2; continue; }
    gitpullsmupdt

  done

  ## loop through GIT modules in applications, dependencies and libraries
  ## and switch to v3.5.13-sru if branch is available
  for i in ${tdeapps[@]}; do
    cd "${tdepath}/main"
    for j in $(find ${i} -maxdepth 1 -type d | sort); do
      [[ ${j##*/} == $i ]] ||  [[ ${j##*/} == admin ]] ||  [[ ${j##*/} == cmake ]] &&  continue

	## change to module directory and checkout v3.5.13-sru
	cd "${tdepath}/main/${j}" || { echo "Warning: unable to change to '${j}' skipping..." >&2; continue; }
	gitpullsmupdt
    done
  done

  ## restore directory to "${tdepath}/main"
  cd "${tdepath}/main" || usage "Error: unable to change to tde directory '${tdepath}/main'" >&2

fi

## move existing tarballs to tgz-old
[[ -d "$tgzpath" ]] && [[ "$@" =~ -w ]] && {

  echo "moving existing $tgzpath -> $tgzpath-$dtcode"
  mkdir -p "${tgzpath}-$dtcode" || usage "ERROR: unable to create save directory '$tgzpath-$dtcode' for old .tar.gz files, exiting." >&2
  mv -f "${tgzpath}"/* "${tgzpath}-$dtcode"

}

## create output path for tarballs
mkdir -p "$tgzpath" || usage "ERROR: unable to create output directory '$tgzpath' for .tar.gz files, exiting." >&2

## create your tarballs for individual apps
for i in ${tdeapps[@]}; do
  for j in $(find ${i} -maxdepth 1 -type d | sort); do
    [[ ${j##*/} == $i ]] ||  [[ ${j##*/} == admin ]] ||  [[ ${j##*/} == cmake ]] &&  continue

    pkgname="${i}-${j##*/}.tar.gz"

    if [[ "$@" =~ -w ]]; then
      echo -n "Compressing:  ${pkgname}"
      if tar --exclude='.git*' -C "${tdepath}/main/${i}" -czf "${tgzpath}/${pkgname}" "${j##*/}"; then
	echo "  ..... Done"
      else
	echo "  ..... Failed"
      fi
    else
      echo "tar --exclude='.git*' -C ${tdepath}/main/${i} -czf ${tgzpath}/${pkgname} ${j##*/}"
    fi
  done
done

## create tarballs for those conatining complete modules
for i in ${tdemods[@]}; do

  pkgname="${i}.tar.gz"
  if [[ "$@" =~ -w ]]; then
    echo -n "Compressing:  ${pkgname}"
    if tar --exclude='.git*' -C "${tdepath}/main" -czf "${tgzpath}/${pkgname}" "${i}"; then
      echo "  ..... Done"
    else
      echo "  ..... Failed"
    fi
  else
    echo "tar --exclude='.git*' -C ${tdepath}/main -czf ${tgzpath}/${pkgname} ${i}"
  fi

done


## clean up
cd "$mydir"

exit 0
