#!/bin/bash
#
# miktex_update
#
# synchronize the local MiKTeX repository (optional),
# update installed packages and install new packages
# (tested with MiKTeX 2.8) v1.4 (30.10.2009)
# (C) Josef Kleber 2008-2009  License: LPPL
# See http://miktexupdate.josef-kleber.de/index.htm or
#     http://miktexupdate.josef-kleber.de/en_index.htm
# for more information
#
VERSION="v1.4 (30.10.2009)"
REPO=C:/MiKTeXRepRsync
REPOSUBDIR=/packages 
# don't change REPOSUBDIR!!
HTTPURL="http://www.ctan.org/systems/win32/miktex/tm/packages"
HTTPSEARCHURL="http://www.ctan.org/cgi-bin/filenameSearch.py?filename=miktex-zzdb&Search=Search"
MIKTEXFILENAME1="miktex"
MIKTEXFILENAME2="zzdb"
MIKTEXFILENAMEEND=""
MIKTEXVERSION=""
TEMPDIR=""
TEMPENV=""
RSYNCURL1=rsync://tug.ctan.org/CTAN/
# RSYNCURL1=rsync://rsync.tex.ac.uk/CTAN/
# RSYNCURL1=rsync://dante.ctan.org/CTAN/
# see http://www.ctan.org/tex-archive/CTAN.sites for other "rsync" servers
RSYNCURL2=systems/win32/miktex/tm/packages 
RSYNCURL="${RSYNCURL1}${RSYNCURL2}"
RSYNCOPT1="-av --delete"
RSYNCOPT2="--progress --partial"
ODIR=$(pwd)
ODIR2=""
ODIR3=""
UPDATEMODE="default"
ARGREPO="default"
VERBOSE=""
UPDLIST="update.txt"
INSTLIST="install.txt"
ERRORDIR="$HOME"
ERROR="miktex_update_error.txt"
ERRORFILE="${ERRORDIR}/${ERROR}"
ERRORFILESIZE=""
UPDATE="true"
INSTALL="true"
NOLIST="false"
INTERACTIVE="default"
SEARCHONLY="false"
ADMIN=""
typeset -i STEP=0
#
function printHelp()
{
  echo -e \
          "`basename $0` [options] [--local | --online [--repository <URL/DIR Repository>]]\n"\
          " updates your MiKTeX installation and installs new packages\n\n"\
          " Options:\n\n"\
          " -h, --help  will print this help statement\n\n"\
          " -V, --version  will print the version number of `basename $0`\n\n"\
          " -a, --admin  run mpm in administrative mode (MiKTeX v2.8+)\n\n"\
          " -b, --broadband  will optimize the text output in LOCAL mode for broadband\n"\
          "                  download. Support for partial package download will be\n"\
          "                  switched off!\n\n"\
          " -v, --verbose  will lead to a more verbose text output in the process of\n"\
          "                updating and installing new packages\n\n"\
          " -n, --nolist  will not print the list of updatable and/or installable\n"\
          "               packages\n\n"\
          " -I, --interactive  the script will ask, if you want to update and/or install\n"\
          "                    packages (-n.--nolist will be switched off)\n\n"\
          " -s, --searchonly  will only list packages, but not update or install them\n\n"\
          " -u, --update  will only update already installed packages\n\n"\
          " -i, --install  will only install new respectively uninstalled packages\n\n"\
          " -l, --local  will set the update mode to LOCAL and syncronize the local\n"\
          "              repository (default or specified with option -r) with CTAN\n\n"\
          " -o, --online  will set the update mode to ONLINE. You can specify an online\n"\
          "               repository with option -r. Without doing so, a repository\n"\
          "               from the MiKTeX server network will be picked by random\n\n"\
          " -r, --repository  specifies the local or online repository for updating\n"\
          "                   and installing new packages\n\n"\
          " -R, --rsync  specifies the rsync server, if you don't want to use the\n"\
          "              default server (rsync://tug.ctan.org/CTAN/)\n\n"\
          " See http://miktexupdate.josef-kleber.de/index.htm or\n"\
          "     http://miktexupdate.josef-kleber.de/en_index.htm\n"\
          " for more information"
  exit 0;
}
function printVersion()
{
  echo "This is version $VERSION of `basename $0`"
  exit 0;
}
#
if [ $# -eq 0 ]
then
  echo -e "`basename $0`: Could not find command line arguments.\nUse the '--help' option for explanation."
  exit 1
fi
#
LONGOPTS="help,admin,broadband,verbose,version,nolist,local,online,update,install,interactive,searchonly,repository:,rsync:"
SHORTOPTS="habVvnlouiIsr:R:"
ARGS=$(getopt -l "$LONGOPTS" "$SHORTOPTS" "$@" 2>$ERRORFILE)
if [ $? -ne 0 ]
then
  echo -e "`basename $0`: Could not process command line arguments.\nUse the '--help' option for explanation."
  echo -e "ERROR:\n`cat $ERRORFILE`"
  exit 1
fi
#
eval set -- "$ARGS"
#
while [ $# -gt 0 ]; do
  ARG=$1
  case "$ARG" in
      --help|-h)         shift; printHelp;;
      --broadband|-b)    shift; RSYNCOPT2="";;
      --admin|-a)        shift; ADMIN="--admin";;
      --verbose|-v)      shift; VERBOSE="--verbose";;
      --version|-V)      shift; printVersion;;
      --nolist|-n)       shift; NOLIST="true";;
      --local|-l)        shift; UPDATEMODE="LOCAL";;
      --online|-o)       shift; UPDATEMODE="ONLINE";;
      --update|-u)       shift; INSTALL="false";;
      --install|-i)      shift; UPDATE="false";;
      --interactive|-I)  shift; INTERACTIVE="interactive";;
      --searchonly|-s)   shift; SEARCHONLY="true";;
      --repository|-r)   shift; ARGREPO="$1"; shift;;
      --rsync|-R)        shift; RSYNCURL="$1${RSYNCURL2}"; shift;;
      --)                shift; break;;
      *)                 break;;
  esac
done
#
if [ $INTERACTIVE = "interactive" ]
then
  NOLIST="false"
fi
if [ $SEARCHONLY = "true" ]
then
  NOLIST="false"
  INTERACTIVE="default"
fi
#
TEMPENV=$(cygpath -w $TEMP)
TEMPDIR="${TEMPENV}\miktex_update"
echo
echo
echo " MiKTeX Update"
echo "---------------"
echo
if [ $UPDATEMODE = "LOCAL" ]
then
  if [ $ARGREPO != "default" ]
  then
    REPO=${ARGREPO}${REPOSUBDIR}
  else
    REPO=${REPO}${REPOSUBDIR}
  fi
  if [ $SEARCHONLY = "true" ]
  then
    ((STEP++))
    echo "$STEP) Download latest MiKTeX repository information"
    echo
    ODIR2=$(pwd)
    mkdir -p $TEMPDIR 2>>$ERRORFILE
    cd $TEMPDIR
    rm -f *.* 2>>$ERRORFILE
    MIKTEXVERSION=$(mpm --version | head -1 | cut -f4 -d ' ' | cut -c1-3 2>>$ERRORFILE)
    wget -q $HTTPSEARCHURL -O url.htm 2>>$ERRORFILE
    MIKTEXFILENAMEEND=$(cat url.htm | grep $MIKTEXFILENAME1 | grep $MIKTEXVERSION | head -1 | cut -f3-4 -d '.' | cut -f1 -d '<' 2>>$ERRORFILE)
    URL="${HTTPURL}/${MIKTEXFILENAME1}-${MIKTEXFILENAME2}1-${MIKTEXVERSION}.${MIKTEXFILENAMEEND}"
    wget -q $URL 2>>$ERRORFILE
    URL="${HTTPURL}/${MIKTEXFILENAME1}-${MIKTEXFILENAME2}2-${MIKTEXVERSION}.${MIKTEXFILENAMEEND}"
    wget -q $URL 2>>$ERRORFILE
    REPO=$TEMPDIR
    cd $ODIR2
  else
    ((STEP++))
    echo "$STEP) Synchronize local repository with CTAN"
    echo
    if [ ! -d $REPO ]
    then
      mkdir -p $REPO 2>>$ERRORFILE
    fi
    cd $REPO
    cd ..
    if [ -a $ERRORFILE ]
    then
      rm $ERRORFILE 2>>$ERRORFILE
    fi
    RSYNCOPT="$RSYNCOPT1 $RSYNCOPT2"
    rsync $RSYNCOPT $RSYNCURL . 2>>$ERRORFILE
    if [ $? -eq 0 ]
    then
      echo
    fi
  fi
  REPO=$(cygpath -w $REPO)
elif [ $UPDATEMODE = "ONLINE" ]
then
  if [ $ARGREPO = "default" ]
  then
    REPO=$(mpm --pick-repository-url | sed -e "s/\r//")
  else
    REPO=$ARGREPO
  fi
  ((STEP++))
  echo "$STEP) Set online repository: $REPO"
  echo
else
  echo -e "`basename $0`: You did not specify an UPDATE MODE.\nUse the '--help' option for explanation."
  exit 1
fi
mpm --set-repository=$REPO $ADMIN 2>>$ERRORFILE
((STEP++))
echo "$STEP) Update DB"
echo
mpm --update-db $ADMIN 2>>$ERRORFILE;
if [ $UPDATE = "true" ]
then
  mpm --find-updates $ADMIN >$UPDLIST 2>>$ERRORFILE
  if [ $NOLIST = "false" ]
  then
    ((STEP++))
    echo "$STEP) List of updatable packages:"
    echo
    if [ "`cat $UPDLIST | head -1 | cut -c1-5`" = "There" ]
    then
      echo "   There are currently no updates available."
      echo
    else
      cat $UPDLIST
      echo
      if [ $INTERACTIVE = "interactive" ]
      then
        echo -e "Do you want to update these packages (y/n): \c"
        read ANSWER
        if [ $ANSWER = "y" -o $ANSWER = "Y" ]
        then
          UPDATE="true"
        else
          UPDATE="false"
        fi
        echo
      fi
    fi
  fi
  if [ $UPDATE = "true" -a $SEARCHONLY = "false" ]
  then
    ((STEP++))
    echo "$STEP) Update installed packages"
    echo
    if [ "`cat $UPDLIST | head -1 | cut -c1-5`" = "There" ]
    then
      echo "   There are currently no updates available."
      echo
    else    
      mpm --update $ADMIN $VERBOSE 2>>$ERRORFILE
    echo
    fi
  fi
fi
if [ $INSTALL = "true" ]
then
  mpm --list $ADMIN | grep -e '- ' | cut -c22- >$INSTLIST 2>>$ERRORFILE
  if [ $NOLIST = "false" ]
  then
    ((STEP++))
    echo "$STEP) List of installable packages:"
    echo
    if [ -s $INSTLIST ]
    then
      cat $INSTLIST
    echo
    if [ $INTERACTIVE = "interactive" ]
    then
      echo -e "Do you want to install these packages (y/n): \c"
      read ANSWER
      if [ $ANSWER = "y" -o $ANSWER = "Y" ]
      then
        INSTALL="true"
      else
        INSTALL="false"
      fi
      echo
    fi
    else
      echo "   There are currently no new packages available."
      echo
    fi
  fi
  if [ $INSTALL = "true" -a $SEARCHONLY = "false" ]
  then
    ((STEP++))
    echo "$STEP) Install new packages"
    echo
    if [ -s $INSTLIST ]
    then
      mpm --install-some=$INSTLIST $ADMIN $VERBOSE 2>>$ERRORFILE
    echo
    else
      echo "   There are currently no new packages available."
      echo
    fi
  fi
fi
if [ $UPDATE = "true" ]
then
  rm $UPDLIST
fi
if [ $INSTALL = "true" ]
then
  rm $INSTLIST
fi
if [ $UPDATEMODE = "LOCAL" -a $SEARCHONLY = "true" ]
then
  cd $TEMPDIR
  rm -f miktex* 2>>$ERRORFILE
  rm -f url.htm 2>>$ERRORFILE
  cd $ODIR2
  rmdir -p --ignore-fail-on-non-empty $TEMPDIR 2>>$ERRORFILE
fi 
ODIR3=$(pwd)
cd $ERRORDIR
ERRORFILESIZE=$(ls -al | grep $ERROR | tr -s ' ' | cut -f5 -d ' ' 2>>$ERRORFILE)
cd $ODIR3
echo
if [ $ERRORFILESIZE = "0" ]
then
  rm $ERRORFILE 2>>$ERRORFILE
  cd $ODIR
else
  echo "ERROR list:"
  echo
  cat $ERRORFILE
  cd $ODIR
  exit 1
fi
echo
exit 0