#! /bin/sh
#
# Copyright (C) 2002-2007 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

# This file is meant for authors, maintainers, co-maintainers or installers
# of packages which are internationalized with the help of GNU gettext.  For
# further information how to use it consult the GNU gettext manual.

progname=$0
package=gettext-tools
version=0.17

# Set variables
# - gettext_dir     directory where the sources are stored.
prefix="/usr/local"
datarootdir="${prefix}/share"
gettext_dir="${datarootdir}/gettext"

# func_tmpdir
# creates a temporary directory.
# Sets variable
# - tmp             pathname of freshly created temporary directory
func_tmpdir ()
{
  # Use the environment variable TMPDIR, falling back to /tmp. This allows
  # users to specify a different temporary directory, for example, if their
  # /tmp is filled up or too small.
  : ${TMPDIR=/tmp}
  {
    # Use the mktemp program if available. If not available, hide the error
    # message.
    tmp=`(umask 077 && mktemp -d "$TMPDIR/gtXXXXXX") 2>/dev/null` &&
    test -n "$tmp" && test -d "$tmp"
  } ||
  {
    # Use a simple mkdir command. It is guaranteed to fail if the directory
    # already exists.  $RANDOM is bash specific and expands to empty in shells
    # other than bash, ksh and zsh.  Its use does not increase security;
    # rather, it minimizes the probability of failure in a very cluttered /tmp
    # directory.
    tmp=$TMPDIR/gt$$-$RANDOM
    (umask 077 && mkdir "$tmp")
  } ||
  {
    echo "$0: cannot create a temporary directory in $TMPDIR" >&2
    { (exit 1); exit 1; }
  }
}

# Support for relocatability.
func_find_curr_installdir ()
{
  # Determine curr_installdir, even taking into account symlinks.
  curr_executable="$0"
  case "$curr_executable" in
    */* | *\\*) ;;
    *) # Need to look in the PATH.
      if test "${PATH_SEPARATOR+set}" != set; then
        func_tmpdir
        { echo "#! /bin/sh"; echo "exit 0"; } > "$tmp"/conf.sh
        chmod +x "$tmp"/conf.sh
        if (PATH="/nonexistent;$tmp"; conf.sh) >/dev/null 2>&1; then
          PATH_SEPARATOR=';'
        else
          PATH_SEPARATOR=:
        fi
        rm -rf "$tmp"
      fi
      save_IFS="$IFS"; IFS="$PATH_SEPARATOR"
      for dir in $PATH; do
        IFS="$save_IFS"
        test -z "$dir" && dir=.
        for exec_ext in ''; do
          if test -f "$dir/$curr_executable$exec_ext"; then
            curr_executable="$dir/$curr_executable$exec_ext"
            break 2
          fi
        done
      done
      IFS="$save_IFS"
      ;;
  esac
  # Make absolute.
  case "$curr_executable" in
    /* | ?:/* | ?:\\*) ;;
    *) curr_executable=`pwd`/"$curr_executable" ;;
  esac
  # Resolve symlinks.
  sed_dirname='s,/[^/]*$,,'
  sed_linkdest='s,^.* -> \(.*\),\1,p'
  while : ; do
    lsline=`LC_ALL=C ls -l "$curr_executable"`
    case "$lsline" in
      *" -> "*)
        linkdest=`echo "$lsline" | sed -n -e "$sed_linkdest"`
        case "$linkdest" in
          /* | ?:/* | ?:\\*) curr_executable="$linkdest" ;;
          *) curr_executable=`echo "$curr_executable" | sed -e "$sed_dirname"`/"$linkdest" ;;
        esac ;;
      *) break ;;
    esac
  done
  curr_installdir=`echo "$curr_executable" | sed -e 's,/[^/]*$,,'`
  # Canonicalize.
  curr_installdir=`cd "$curr_installdir" && pwd`
}
func_find_prefixes ()
{
  # Compute the original/current installation prefixes by stripping the
  # trailing directories off the original/current installation directories.
  orig_installprefix="$orig_installdir"
  curr_installprefix="$curr_installdir"
  while true; do
    orig_last=`echo "$orig_installprefix" | sed -n -e 's,^.*/\([^/]*\)$,\1,p'`
    curr_last=`echo "$curr_installprefix" | sed -n -e 's,^.*/\([^/]*\)$,\1,p'`
    if test -z "$orig_last" || test -z "$curr_last"; then
      break
    fi
    if test "$orig_last" != "$curr_last"; then
      break
    fi
    orig_installprefix=`echo "$orig_installprefix" | sed -e 's,/[^/]*$,,'`
    curr_installprefix=`echo "$curr_installprefix" | sed -e 's,/[^/]*$,,'`
  done
}
if test "no" = yes; then
  exec_prefix="${prefix}"
  bindir="${exec_prefix}/bin"
  orig_installdir="$bindir" # see Makefile.am's *_SCRIPTS variables
  func_find_curr_installdir # determine curr_installdir
  func_find_prefixes
  # Relocate the directory variables that we use.
  gettext_dir=`echo "$gettext_dir/" | sed -e "s%^${orig_installprefix}/%${curr_installprefix}/%" | sed -e 's,/$,,'`
fi

# func_usage
# outputs to stdout the --help usage message.
func_usage ()
{
  echo "\
Usage: autopoint [OPTION]...

Copies standard gettext infrastructure files into a source package.

Options:
      --help           print this help and exit
      --version        print version information and exit
  -f, --force          force overwriting of files that already exist
  -n, --dry-run        print modifications but don't perform them"
#  echo "\
#  -V version           copy the infrastructure of the specified gettext version
#                         (dangerous)"
  echo "
Report bugs to <bug-gnu-gettext@gnu.org>."
}

# func_version
# outputs to stdout the --version message.
func_version ()
{
  echo "$progname (GNU $package) $version"
  echo "Copyright (C) 2002-2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law."
  echo "Written by" "Bruno Haible"
}

# func_fatal_error message
# outputs to stderr a fatal error message, and terminates the program.
func_fatal_error ()
{
  echo "autopoint: *** $1" 1>&2
  echo "autopoint: *** Stop." 1>&2
  exit 1
}

# Command-line option processing.
# Removes the OPTIONS from the arguments. Sets the variables:
# - force           yes if --force was given, empty otherwise
# - ver             gettext version if -V was given, empty otherwise
# - doit            false if --dry-run was given, : otherwise
{
  force=
  ver=
  doit=:

  while test $# -gt 0; do
    case "$1" in
      -n | --dry-run | --dry-ru | --dry-r | --dry- | --dry | --dr | --d )
        shift
        doit=false ;;
      -f | --force | --forc | --for | --fo | --f )
        shift
        force=yes ;;
      --help | --hel | --he | --h )
        func_usage; exit 0 ;;
#      -V ) # Some people put a space between -V and the version number.
#        shift
#        if test $# = 0; then
#          func_usage 1>&2
#          exit 1
#        fi
#        ver=$1;
#        shift ;;
#      -V*) # Some people omit the space between -V and the version number.
#        ver=`echo "X$1" | sed -e 's/^X-V//'`
#        shift ;;
      --version | --versio | --versi | --vers | --ver | --ve | --v )
        func_version
        exit 0 ;;
      -- ) # Stop option prcessing
        shift; break ;;
      -* )
        echo "autopoint: unknown option $1" 1>&2
        echo "Try 'autopoint --help' for more information." 1>&2
        exit 1 ;;
      * )
        break ;;
    esac
  done
}

# Command-line argument processing.
# Analyzes the remaining arguments.
{
  if test $# -gt 0; then
    func_usage 1>&2
    exit 1
  fi
}

srcdir=`pwd`
# The current directory is now $srcdir.

# Check integrity of package: A configure.in/ac must be present. Sets variable
# - configure_in    name of configure.in/ac file.
if test -f configure.in; then
  configure_in=configure.in
else
  if test -f configure.ac; then
    configure_in=configure.ac
  else
    # KDE specific convention: configure.in.in
    if test -f configure.in.in; then
      configure_in=configure.in.in
    else
      func_fatal_error "Missing configure.in or configure.ac, please cd to your package first."
    fi
  fi
fi

# Check whether the -V option and the version number in configure.in match.
# At least one of the two must be given. If both are given, they must agree.
xver=`cat "$configure_in" | grep '^AM_GNU_GETTEXT_VERSION(' | sed -e 's/^AM_GNU_GETTEXT_VERSION(\([^()]*\))/\1/p' | sed -e 's/^\[\(.*\)\]$/\1/' | sed -e 1q`
if test -z "$xver" && test -f intl/VERSION; then
  xver=`cat intl/VERSION | LC_ALL=C sed -n -e 's/^.*gettext-\([-+_.0-9A-Za-z]*\).*$/\1/p'`
fi
if test -n "$xver"; then
  if test -n "$ver"; then
    if test "X$ver" != "X$xver"; then
      func_fatal_error "Version mismatch: specified -V $ver but the package uses gettext version $xver"
    fi
  else
    ver="$xver"
  fi
else
  if test -z "$ver"; then
    func_fatal_error "Missing version: please specify in $configure_in through a line 'AM_GNU_GETTEXT_VERSION(x.yy.zz)' the gettext version the package is using"
  fi
fi

# Check whether the version number is supported.
case "$ver" in
  0.10.35 | 0.10.36 | 0.10.37 | 0.10.38 | 0.10.39 | 0.10.40 | \
  0.11 | 0.11.1 | 0.11.2 | 0.11.3 | 0.11.4 | 0.11.5 | \
  0.12 | 0.12.1 | \
  0.13 | 0.13.1 | \
  0.14 | 0.14.1 | 0.14.2 | 0.14.3 | 0.14.4 | 0.14.5 | 0.14.6 | \
  0.15 | \
  0.16 | 0.16.1 | \
  0.17 )
    ;;
  *)
    func_fatal_error "The AM_GNU_GETTEXT_VERSION declaration in your $configure_in\
               file requires the infrastructure from gettext-$ver but this version\
               is older. Please upgrade to gettext-$ver or newer."
    ;;
esac

# We distribute the many different versions of the files in a CVS repository.
# This guarantees a good compression rate:
#
#   Including version    size in KB of
#                       "du autopoint-files/archive"
#      0.10.35                  240
#      0.10.36                  428
#      0.10.37                  436
#      0.10.38                  488
#      0.10.39                  500
#      0.10.40                  528
#      0.11                     720
#      0.11.1                   740
#      0.11.2                   748
#      0.11.3                   804
#      0.11.4                   864
#      0.11.5                   880
#      0.12                    1032
#      0.12.1                  1032
#      0.13                    1220
#      0.13.1                  1236
#      0.14                    1296
#      0.14.1                  1300
#      0.14.2                  1420
#      0.14.3                  1428
#      0.14.4                  1464
#      0.14.5                  1508
#      0.14.6                  1580
#      0.15                    1760
#      0.16                    1808
#      0.16.1                  1812
#      0.17                    2128
#
# The requirement that the user must have the CVS program available is not
# a severe restrictions, because most of the people who use autopoint are
# users of CVS.
#
# Check availability of the CVS program.
(cvs -v) >/dev/null 2>/dev/null || func_fatal_error "cvs program not found"

# Check in which directory config.rpath, mkinstalldirs etc. belong.
auxdir=`cat "$configure_in" | grep '^AC_CONFIG_AUX_DIR' | sed -n -e 's/AC_CONFIG_AUX_DIR(\([^()]*\))/\1/p' | sed -e 's/^\[\(.*\)\]$/\1/' | sed -e 1q`
if test -n "$auxdir"; then
  auxdir="$auxdir/"
fi

# Check in which directory the *.m4 macros belong.
m4dir=m4
if test -f Makefile.am; then
  # A package using automake.
  # Extract the macro directory name from Makefile.am.
  aclocal_amflags=`grep '^ACLOCAL_AMFLAGS[ 	]*=' Makefile.am | sed -e 's/^ACLOCAL_AMFLAGS[ 	]*=\(.*\)$/\1/'`
  m4dir_is_next=
  for arg in $aclocal_amflags; do
    if test -n "$m4dir_is_next"; then
      m4dir="$arg"
      break
    else
      if test "X$arg" = "X-I"; then
        m4dir_is_next=yes
      else
        m4dir_is_next=
      fi
    fi
  done
fi

# Check whether to omit the intl/ directory.
omitintl=`cat "$configure_in" | grep '^AM_GNU_GETTEXT' | sed -n -e 's/^AM_GNU_GETTEXT(\([^(),]*\).*$/\1/p' | sed -e 's/^\[\(.*\)\]$/\1/' | sed -e 1q`
omitintl=`if test 'external' = "$omitintl"; then echo yes; fi`

# Set up a temporary CVS repository and a temporary checkout directory.
# We need the temporary CVS repository because any checkout needs write
# access to the CVSROOT/history file, so it cannot be under $gettext_dir.
# We need the temporary checkout directory because when --force was not
# given, we need to compare the existing files with the checked out ones.
# Set variables
# - cvs_dir         directory containing the temporary repository
# - work_dir        directory containing the temporary checkout
cvs_dir=tmpcvs$$
work_dir=tmpwrk$$
# Use an umask of 077, to avoid attacks that work by overwriting files in the
# "$CVSROOT"/CVSROOT directory.
(umask 077 && mkdir "$cvs_dir") || {
  if test -d "$cvs_dir"; then
    func_fatal_error "directory $cvs_dir already exists"
  else
    func_fatal_error "cannot create directory $cvs_dir"
  fi
}
mkdir "$work_dir" || {
  if test -d "$work_dir"; then
    func_fatal_error "directory $work_dir already exists"
  else
    func_fatal_error "cannot create directory $work_dir"
  fi
}
CVSROOT="$srcdir/$cvs_dir"
export CVSROOT
unset CVS_CLIENT_LOG
unset CVS_CLIENT_PORT
unset CVS_IGNORE_REMOTE_ROOT
unset CVS_PASSFILE
unset CVS_PASSWORD
unset CVS_RCMD_PORT
unset CVS_RSH
unset CVS_SERVER
unset CVS_SERVER_SLEEP
unset CVSIGNORE
unset CVSREAD
unset CVSUMASK
unset CVSWRAPPERS

# Need to pass -d "$CVSROOT", because there may be a CVS directory in the
# current directory.
cvs -d "$CVSROOT" init
gzip -d -c < "$gettext_dir/archive.tar.gz" | (cd "$cvs_dir" && tar xf -)

cd "$work_dir"
cvsver=gettext-`echo "$ver" | sed -e 's/\./_/g'`
(cvs checkout -r"$cvsver" archive > /dev/null) 2>&1 | grep -v '^cvs checkout: Updating'
find archive -name CVS -type d -print | xargs rm -rf
if test `find archive -type f -print | wc -l` = 0; then
  cd ..
  rm -rf "$cvs_dir" "$work_dir"
  func_fatal_error "infrastructure files for version $ver not found; this is autopoint from GNU $package $version"
fi
cd ..

# func_destfile file
# determines the destination file, relative to the package's top level
# directory, for a given file name, relative to archive.
# Sets variables
# - destfile        relative destination file name, or
#                   empty if the file shall be omitted
# - sharedowner     yes if the file is not only owned by GNU gettext but may
#                   be installed by automake or other tools, otherwise empty
func_destfile ()
{
  # There are five categories of files:
  # ABOUT_NLS -> top level directory
  # config.rpath mkinstalldirs -> $auxdir
  # m4/* -> $m4dir/
  # intl/* -> intl/
  # po/* -> po/
  sharedowner=
  case `echo "$1" | sed -e 's,[^/]*$,,'` in
    "" )
      case "$1" in
        config.rpath ) destfile="$auxdir$1" ;;
        mkinstalldirs ) destfile="$auxdir$1" sharedowner=yes ;;
        * ) destfile="$1" ;;
      esac
      ;;
    m4/ ) destfile=`echo "$1" | sed -e "s,^m4/,$m4dir/,"` ;;
    intl/ ) if test -n "$omitintl"; then destfile=""; else destfile="$1"; fi ;;
    * ) destfile="$1" ;;
  esac
}

# If some files have been locally modified and we have not been requested
# to overwrite them, then bail out. This is better than leaving a source
# package around where half of the files are locally modified and half are
# original - too great risk of version mismatch.
if test -z "$force"; then
  mismatch=
  func_tmpdir
  mismatchfile="$tmp"/autopoint.diff
  for file in `find "$work_dir/archive" -type f -print | sed -e "s,^$work_dir/archive/,," | LC_ALL=C sort`; do
    func_destfile "$file"
    if test -n "$destfile"; then
      if test -f "$destfile"; then
        if cmp -s "$work_dir/archive/$file" "$destfile"; then
          :
        else
          if test -n "$sharedowner"; then
            echo "autopoint: warning: File $destfile has been locally modified." 1>&2
          else
            echo "autopoint: File $destfile has been locally modified." 1>&2
            mismatch=yes
            diff -c "$work_dir/archive/$file" "$destfile" | sed -e "1s,$work_dir/archive/,," >> "$mismatchfile"
          fi
        fi
      fi
    fi
  done
  if test -n "$mismatch"; then
    rm -rf "$cvs_dir" "$work_dir"
    func_fatal_error "Some files have been locally modified. Not overwriting them because --force has not been specified. For your convenience, you find the local modifications in the file '$mismatchfile'."
  fi
  rm -rf "$tmp"
fi

# func_mkdir_for to
# ensures the directory that would the given file exists.
# 'to' is a relative pathname, relative to the current directory.
func_mkdir_for ()
{
  base=`echo "$1" | sed -e 's,/[^/]*$,,'`
  if test "X$base" != "X$1" && test -n "$base"; then
    func_mkdir_for "$base"
    # Recompute base. It was clobbered by the recursive call.
    base=`echo "$1" | sed -e 's,/[^/]*$,,'`
    test -d "$base" || { echo "Creating directory $base"; mkdir "$base"; }
  fi
}

# func_copy from to
# copies a file.
# 'from' is a relative pathname, relative to the current directory.
# 'to' is a relative pathname, relative to the current directory.
func_copy ()
{
  if $doit; then
    func_mkdir_for "$2"
    rm -f "$2"
    echo "Copying file $2"
    cp "$1" "$2"
  else
    echo "Copy file $2"
  fi
}

# func_backup to
# makes a backup of a file that is about to be overwritten or replaced.
# 'to' is a relative pathname, relative to the current directory.
func_backup ()
{
  if $doit; then
    if test -f "$1"; then
      rm -f "$1~"
      cp -p "$1" "$1~"
    fi
  fi
}

# Now copy the files.
for file in `find "$work_dir/archive" -type f -print | sed -e "s,^$work_dir/archive/,," | LC_ALL=C sort`; do
  func_destfile "$file"
  mustcopy=
  if test -n "$destfile"; then
    if test -f "$destfile"; then
      if cmp -s "$work_dir/archive/$file" "$destfile"; then
        :
      else
        if test -n "$force"; then
          # Overwrite locally modified file.
          mustcopy=yes
        fi
        # If --force is not specified, don't overwrite locally modified files
        # for which GNU gettext is a shared owner.
      fi
    else
      mustcopy=yes
    fi
  fi
  if test -n "$mustcopy"; then
    func_backup "$destfile"
    func_copy "$work_dir/archive/$file" "$destfile"
  fi
done

# That's it.
rm -rf "$cvs_dir" "$work_dir"
exit 0
