#! /bin/bash -e

# NOTE: should be invoked as either:
#    ./msys-build-diffutils diffutils-VER.tar.bz2
#    which will unpack the "pristine" source distribution, patch it, 
#    and begin the build,
# OR, as
#    ../msys-build-diffutils
#    where the current working directory is the unpacked and patched
#    source distribution.
#
# NOTE2: The first patch is extremely large, because it represents
# importing GNULIB sources into the (bare) CVS tree, using the following
# command:
#    gnulib-tool --import --dir=. --local-dir=gl --lib=libdiffutils \
#       --source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux \
#       --no-libtool --macro-prefix=gl c-stack config-h diffseq dirname \
#       dup2 error exclude exit exitfail extensions fcntl fdl file-type \
#       fnmatch-gnu getopt gettext gettime hard-locale inttostr inttypes \
#       mkstemp regex sh-quote stat-macros stat-time strcase strftime \
#       strtoumax unistd unlocked-io verify version-etc version-etc-fsf \
#       xalloc xstrtoumax
# and fixing up what's left:
#     mv lib/Makefile.am lib/gnulib.mk
#     mv lib/Makefile.am~ lib/Makefile.am
#     rm -f lib/getopt.h

### hardcode PKG and patches diffutilsball
export PKG=diffutils
export VER=2.8.7.20071206cvs
export BLD=3
export SYS=msys
_sysver=$(uname -r)
export SYSVER=${_sysver%%\(*}
FULLPKG=${PKG}-${VER}-${BLD}-${SYS} # not sysver
SRCDIR_=${PKG}
RELDOCDIR=share/doc/${PKG}/${VER}
BINPKG=${PKG}-${VER}-${BLD}-${SYS}-${SYSVER}-bin.tar.lzma
LANGPKG=${PKG}-${VER}-${BLD}-${SYS}-${SYSVER}-lang.tar.lzma
LICPKG=${PKG}-${VER}-${BLD}-${SYS}-${SYSVER}-lic.tar.lzma
DOCPKG=${PKG}-${VER}-${BLD}-${SYS}-${SYSVER}-doc.tar.lzma
SRCPKG=${PKG}-${VER}-${BLD}-${SYS}-${SYSVER}-src.tar.lzma
BIN_CONTENTS='bin'
LANG_CONTENTS='share/locale'
LIC_CONTENTS="${RELDOCDIR}/COPYING"
DOC_CONTENTS="--exclude ${RELDOCDIR}/COPYING \
	share/doc share/info share/man"

# displays error message and exits
error() {
        case $? in
                0) local errorcode=1 ;;
                *) local errorcode=$? ;;
        esac

        echo -e "\e[1;31m*** ERROR:\e[0;0m ${1:-no error message provided}";
        exit ${errorcode};
}

# displays information message
inform() {
        echo -e "\e[1;32m*** Info:\e[0;0m ${1}";
}

# displays warning message only
warning() {
        echo -e "\e[1;33m*** Warning:\e[0;0m ${1}";
}

# query
query() {
	while true
	do
          echo -e "\e[1;35m*** Query:\e[0;0m ${1}";
	  if read -e answer
	  then
	    query_result=$answer
	    return 0
	  else
	    # user did a ^D
	    echo -e "Quitting.\n"
	    exit 1
	  fi
	done
}

# displays command to stdout before execution
verbose() {
        echo "${@}"
        "${@}"
        return $?
}
export -f verbose warning inform error

cmparg=
set_cmparg() {
        case "$1" in
        *tar.bz2       ) cmparg="j" ;;
        *tar.lzma      ) cmparg=" --lzma" ;;
        *tar.xz        ) cmparg=" --use-compress-program=xz" ;;
        *tar.gz | *tgz ) cmparg="z" ;;
        *              ) cmparg="" ;;
        esac
}

specific_patchlevel=
do_patch() {
  #local patchfile_name;
  #local patchfile_path;
  #local patchlevel;
  if [ -n "$specific_patchlevel" ]
  then
    starting_patchlevel=$specific_patchlevel
    stopping_patchlevel=$specific_patchlevel
  else
    starting_patchlevel=0
    stopping_patchlevel=3
  fi
  specific_patchlevel=

  for patchfile_path
  do
    patchfile_name="${patchfile_path##*/}"

    if [ ! -e ${patchfile_path} ]
    then
      warning "patch ${patchfile_name} not found";
      continue;
    fi

    patchlevel=$starting_patchlevel

    while test $patchlevel -le $stopping_patchlevel
    do
      if patch -N -s --dry-run -p${patchlevel} -i ${patchfile_path} &> /dev/null
      then
        echo "*** applying patch ${patchfile_name}:";
        patch -N -p${patchlevel} -i ${patchfile_path} || error "patch ${patchfile_name} failed"
        break;
      elif patch -N -s --binary --dry-run -p${patchlevel} -i ${patchfile_path} &> /dev/null
      then
        echo "*** applying patch ${patchfile_name}:";
        patch -N --binary -p${patchlevel} -i ${patchfile_path} || error "patch ${patchfile_name} failed"
        break;
      elif patch -R -s --dry-run -p${patchlevel} -i ${patchfile_path} &> /dev/null
      then
        warning "patch ${patchfile_name} already applied; skipping";
        break;
      else
        if (( patchlevel == 3 ))
        then
          error patch "patch ${patchfile_name} will not apply";
        else
          patchlevel=`expr $patchlevel + 1`;
          continue;
        fi
      fi
    done
  done
}
export -f do_patch


if [ "x" != "x$1" ]; then
  if [ -d "$1" ]; then
    savedir="$PWD"
    cd "$1"
    srcdir="$PWD"
  elif [ -f "$1" ]; then
    case "$1" in
    *.tar.bz2 ) srcdir=`echo $1 | sed -e 's/\.tar\.bz2$//'`
                unpack=tbz
                savedir="$PWD" ;;
    *.tar.gz  ) srcdir=`echo $1 | sed -e 's/\.tar\.gz$//'`
                unpack=tgz
                savedir="$PWD" ;;
    *.zip     ) srcdir=`echo $1 | sed -e 's/\.zip$//'`
                unpack=zip
                savedir="$PWD" ;;
    *.tar.lzma ) srcdir=`echo $1 | sed -e 's/\.tar\.lzma$//'`
                unpack=tlz
                savedir="$PWD" ;;
    *.tar.xz )  srcdir=`echo $1 | sed -e 's/\.tar\.xz$//'`
                unpack=txz
                savedir="$PWD" ;;
    * ) error "Bad src directory specified: $1" ;;
    esac
  else
    error "Bad src directory specified: $1"
  fi
else
  savedir="$PWD"
  srcdir="$PWD"
fi

if [ "$MSYSTEM" != "MSYS" ]
then
  echo "You must be in an MSYS shell to use this script"
  exit 1
fi

if [ -n "$unpack" ] ; then
  case "$unpack" in
  tbz ) inform "unpacking $1" ; tar xjf $1 ;;
  tgz ) inform "unpacking $1" ; tar xzf $1 ;;
  zip ) inform "unpacking $1" ; unzip -q $1 ;;
  tlz ) inform "unpacking $1" ; tar --lzma -xf $1 ;;
  txz ) inform "unpacking $1" ; tar --use-compress-program=xz -xf $1 ;;
  * ) error "unknown pack format" ;;
  esac
  if [ -n "${SRCDIR_}" ]; then
    if [ ! -d "${SRCDIR_}" ]; then
      echo "src package $1 does not unpack into assumed srcdir $SRCDIR_"
      exit 1
    fi
    srcdir=`cd ${SRCDIR_} && pwd`
  fi
  if [ ! -d "$srcdir" ]; then
    echo "src package $1 does not unpack into assumed srcdir $srcdir"
    exit 1
  fi


  cd ${srcdir}
  chmod -R u+w *
  chmod -R u+w *
  specific_patchlevel=2 && do_patch ${savedir}/01-diffutils-2.8.7-3-gnulib.patch
  do_patch ${savedir}/02-diffutils-2.8.7-3-msys.patch
  cd ${savedir}
  srcdir=`cd $srcdir; pwd`
fi


abovedir=`cd ${srcdir}/..; pwd`
PREFIX=/usr
opt_flags="-O3 -fno-unit-at-a-time -s -march=i386 -mtune=i686"
export CFLAGS=${CFLAGS:-"${opt_flags}"}
# note: defining towlower this way breaks mbscasecmp, which in turn breaks
# diffutils's casefolding, for files whose contents are encoded using
# multibyte. But, for msys, we really have no alternative; not even GNULIB
# has completely implemented a replacement towlower.
export CPPFLAGS="${CPPFLAGS} -D__CYGWIN__ -DWEOF='((wint_t)-1)' -DEILSEQ=138 -Dtowlower=tolower"
export CXXFLAGS=${CXXFLAGS:-"${opt_flags}"}
export F77FLAGS=${F77FLAGS:-"${opt_flags}"}
export GCJFLAGS=${GCJFLAGS:-"${opt_flags}"}
export LDFLAGS="${LDFLAGS} -Wl,--enable-auto-import"

# NO SPACES!!
export PATH=`pwd`:/bin:/usr/local/bin:/mingw/bin:/c/WINDOWS/system32:/c/WINDOWS

mkdir -p ${abovedir}/_build
builddir=${abovedir}/_build
mkdir -p ${abovedir}/_inst
instdir=${abovedir}/_inst
cd ${builddir}


msys_conf_prep() {
  inform "Preparing ${PKG}"
  cd ${srcdir}
  autoreconf -fvi
  verbose mv po/Makevars.template po/Makevars
  # have to do this AFTER autoreconf, because Makefile.in.in
  # doesn't exist until autopoint is executed.  But there's a
  # bug in the gettext-0.17 version of this file, which happens
  # to be tickled by diffutils
  patch -p2 <<'EOF'
--- old/diffutils/po/Makefile.in.in.orig	2009-08-13 11:59:55.025000000 -0400
+++ new/diffutils/po/Makefile.in.in	2009-08-13 12:00:18.050000000 -0400
@@ -20,6 +20,7 @@
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
 VPATH = @srcdir@
 
 prefix = @prefix@
EOF
  # ditto for LINGUAS
  echo "en en_US" > po/LINGUAS

  # gnulib macros are newer; restore them and re-run autotools
  for f in codeset.m4 gettext.m4 glibc2.m4 glibc21.m4 \
	iconv.m4 intdiv0.m4 intldir.m4 intlmacosx.m4 \
	intmax.m4 inttypes-pri.m4 inttypes_h.m4 lcmessage.m4 \
	lib-ld.m4 lib-link.m4 lib-prefix.m4 lock.m4 \
	longlong.m4 nls.m4 po.m4 printf-posix.m4 \
	progtest.m4 size_max.m4 stdint_h.m4 uintmax_t.m4 \
	visibility.m4 wchar_t.m4 wint_t.m4 xsize.m4
  do
    mv m4/${f}~ m4/${f}
  done
  verbose aclocal --force -I m4
  verbose autoconf --force
  verbose autoheader --force
  verbose automake --add-missing --copy --force-missing
  cd ${builddir}
}

msys_conf () {
  confargs="--prefix=${PREFIX} \
	--datarootdir=\${prefix}/share --docdir=\${prefix}/${RELDOCDIR} \
	--with-libintl-prefix=/usr --with-libiconv-prefix=/usr"

  ${srcdir}/configure --srcdir=${srcdir} ${confargs} \
	CFLAGS="${CFLAGS}" \
	CPPFLAGS="${CPPFLAGS}" \
	CXXFLAGS="${CXXFLAGS}" \
	LDFLAGS="${LDFLAGS}"

  for f in `find . -name "Makefile"`
  do
    cat "$f" | sed -e 's:/libintl\.a:/libintl.dll.a:g' \
      -e 's:/libiconv\.a:/libiconv.dll.a:g' \
      > "${f}.new" && \
    mv "${f}.new" "${f}" 
  done
}

msys_build () {
  inform "Building ${PKG}"
  make V=0
}

msys_check () {
  :
}

msys_install () {
  inform "Installing ${PKG}"
  make install DESTDIR=${instdir}

  verbose rm -f ${instdir}${PREFIX}/share/info/dir
  verbose rm -f ${instdir}${PREFIX}/lib/charset.alias
  verbose rmdir ${instdir}${PREFIX}/lib || /bin/true

  verbose mkdir -p ${instdir}${PREFIX}/${RELDOCDIR}
  verbose cp -p ${srcdir}/ChangeLog* \
	${srcdir}/AUTHORS \
	${srcdir}/COPYING \
	${srcdir}/NEWS \
	${srcdir}/README \
	${srcdir}/THANKS \
	${srcdir}/TODO  ${instdir}${PREFIX}/${RELDOCDIR}

  verbose /usr/bin/install -d -m 755 ${instdir}${PREFIX}/share/doc/MSYS
  verbose /usr/bin/install -m 644 ${abovedir}/msys-diffutils.RELEASE_NOTES \
          ${instdir}${PREFIX}/share/doc/MSYS/${PKG}-${VER}-${BLD}-${SYS}.RELEASE_NOTES.txt
}

msys_package () {
  inform "Packaging ${PKG}"
  cd ${instdir}${PREFIX}

  set_cmparg "${BINPKG}"
  tar cv${cmparg} --hard-dereference -f ${abovedir}/${BINPKG} ${BIN_CONTENTS}

  set_cmparg "${LANGPKG}"
  tar cv${cmparg} --hard-dereference -f ${abovedir}/${LANGPKG} ${LANG_CONTENTS}

  set_cmparg "${LICPKG}"
  tar cv${cmparg} --hard-dereference -f ${abovedir}/${LICPKG} ${LIC_CONTENTS}

  set_cmparg "${DOCPKG}"
  tar cv${cmparg} --hard-dereference -f ${abovedir}/${DOCPKG} ${DOC_CONTENTS}


  cd ${abovedir}
  set_cmparg "${SRCPKG}"
  tar cv${cmparg} -f ./${SRCPKG} \
    ${PKG}-${VER}.tar.bz2 \
    01-diffutils-2.8.7-3-gnulib.patch \
    02-diffutils-2.8.7-3-msys.patch \
    msys-diffutils.RELEASE_NOTES \
    msys-build-diffutils
}

msys_conf_prep
msys_conf
msys_build
msys_check
msys_install
msys_package

cd "$savedir"

