]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Support alternative to the cvs-compression of the archive.
authorBruno Haible <bruno@clisp.org>
Sun, 27 Sep 2009 20:56:39 +0000 (22:56 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 27 Sep 2009 20:56:39 +0000 (22:56 +0200)
ChangeLog
DEPENDENCIES
NEWS
PACKAGING
gettext-tools/ChangeLog
gettext-tools/configure.ac
gettext-tools/misc/ChangeLog
gettext-tools/misc/Makefile.am
gettext-tools/misc/autopoint.in
gettext-tools/misc/convert-archive.in [new file with mode: 0644]

index bacfd366c0a9683014809d8a27aec58dc8daf225..a5db476f76eeb6ee7284e5c66d363b96a7d5a5b2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-09-27  Bruno Haible  <bruno@clisp.org>
+
+       * NEWS: Mention configure options --without-cvs and --with-git.
+       * PACKAGING: Mention archive.*.tar.gz instead of archive.tar.gz.
+       * DEPENDENCIES: Mention also git.
+
 2009-09-01  Bruno Haible  <bruno@clisp.org>
 
        * README.woe32: Put the -mno-cygwin option into CC and CXX.
index c29f2c75c3305817bf3c6c30d832c8d8dcf0c4ed..e1506e837d23b640d40b2c0c7ba19682f778dc37 100644 (file)
@@ -100,9 +100,18 @@ The following packages should be installed when GNU gettext is installed:
 
 * CVS 1.11 or newer
   + Recommended.
-    Needed by the 'autopoint' program.
+    Needed by the 'autopoint' program, if not configured with --without-cvs
+    or --with-git.
   + Homepage:
     http://ximbiot.com/cvs/wiki/index.php?title=Main_Page
     http://www.nongnu.org/cvs/
   + Download:
     http://ftp.gnu.org/non-gnu/cvs/
+
+* git 1.6 or newer
+  + Recommended.
+    Needed by the 'autopoint' program, if configured with --with-git.
+  + Homepage:
+    http://git-scm.com/
+  + Download:
+    http://www.kernel.org/pub/software/scm/git/
diff --git a/NEWS b/NEWS
index 02b6964022ee112f4d9bf58b416a19baada8b20f..6635376c778c183918282dd10bf0a7cff5ba5f4a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,14 @@ Version 0.18 - January 2008
 
 * Updated the meaning of 'gcc-internal-format' to match GCC 4.3.
 
+* Installation options:
+  The configure options --without-cvs and --with-git can be used to specify
+  whether 'autopoint' will use the 'cvs' program, or the 'git' program, or
+  none at all. These options allow to trade dependencies against installed
+  package size: If --without-cvs is specified and --with-git is not specified,
+  'autopoint' will not rely on 'cvs' or 'git', but will instead rely on a
+  locally installed a 3 MB large archive.
+
 * Portability:
   The msgfilter program now also works on native Woe32 platforms.
 \f
index b9657e24764981e2903bca2683a4ef60f6d72ff5..3e7772b615a1ed1313ad0189d2421e3cdfbf3e70 100644 (file)
--- a/PACKAGING
+++ b/PACKAGING
@@ -113,7 +113,9 @@ following file list.
       $prefix/share/gettext/gettext.h
       $prefix/share/gettext/gettext.jar   (only installed if gcj is not present)
       $prefix/share/gettext/msgunfmt.tcl
-      $prefix/share/gettext/archive.tar.gz
+      $prefix/share/gettext/archive.cvs.tar.gz
+      $prefix/share/gettext/archive.git.tar.gz   (only installed if --with-git specified)
+      $prefix/share/gettext/archive.dir.tar.gz   (only installed if --without-cvs specified)
       $prefix/share/aclocal/codeset.m4
       $prefix/share/aclocal/gettext.m4
       $prefix/share/aclocal/glibc2.m4
index 4249ddde3b28836b055f3a2d1f290e4cbd18d5b7..2ac988c26d3f688ac716d649e8713db912fdc792 100644 (file)
@@ -1,3 +1,9 @@
+2009-09-27  Bruno Haible  <bruno@clisp.org>
+
+       * configure.ac: Accept --without-cvs, --with-git options. Substitute
+       ARCHIVE_FORMAT.
+       (AC_CONFIG_FILES): Add misc/convert-archive.
+
 2009-08-10  Bruno Haible  <bruno@clisp.org>
 
        * woe32dll/gettextsrc-exports.c: Export formatstring_gfc_internal,
index 1451ec3a7f538cff2c9b10fd6ca239bd59e465dd..711c7d47ee46245c007dda228337e92cf0ec99ae 100644 (file)
@@ -305,6 +305,36 @@ fi
 aclocaldir='${datadir}/aclocal'
 AC_SUBST([aclocaldir])
 
+dnl Check how to install the set of previous versions, for autopoint.
+AC_ARG_WITH([cvs],
+  [  --without-cvs           don't use cvs to compress the infrastructure archive],
+  [gt_use_cvs=$withval],
+  [gt_use_cvs=maybe])
+AC_ARG_WITH([git],
+  [  --with-git              use git to compress the infrastructure archive],
+  [gt_use_git=$withval],
+  [gt_use_git=no])
+if test "$gt_use_cvs" != no && test "$gt_use_cvs" != maybe; then
+  # --with-cvs is specified. Even if --with-git is also specified, we use the
+  # cvs format, because it yields smaller archives than the git format.
+  ARCHIVE_FORMAT=cvs
+else
+  if test "$gt_use_git" != no; then
+    # --with-git is specified.
+    ARCHIVE_FORMAT=git
+  else
+    # Neither --with-cvs not --with-git is specified.
+    if test "$gt_use_cvs" != no; then
+      # --without-cvs is not specified. Use cvs format.
+      ARCHIVE_FORMAT=cvs
+    else
+      # --without-cvs is specified.
+      ARCHIVE_FORMAT=dir
+    fi
+  fi
+fi
+AC_SUBST([ARCHIVE_FORMAT])
+
 dnl Check for tools needed for formatting the documentation.
 ac_aux_dir_abs=`cd $ac_aux_dir && pwd`
 AC_PATH_PROG([DVIPS], [dvips], [$ac_aux_dir_abs/missing dvips])
@@ -386,6 +416,7 @@ AC_CONFIG_FILES([styles/Makefile])
 AC_CONFIG_FILES([misc/Makefile])
 AC_CONFIG_FILES([misc/gettextize], [chmod a+x misc/gettextize])
 AC_CONFIG_FILES([misc/autopoint], [chmod a+x misc/autopoint])
+AC_CONFIG_FILES([misc/convert-archive], [chmod a+x misc/convert-archive])
 
 AC_CONFIG_FILES([man/Makefile],
                 [FIX_MAKEFILE_DISTRIB])
index afdfe90853e1d2ff80e4857c19db5f7753f5c6f2..0f766b81dc4451a90dacb207efd2f653b0ec3828 100644 (file)
@@ -1,3 +1,16 @@
+2009-09-27  Bruno Haible  <bruno@clisp.org>
+
+       Support alternative to the cvs-compression of the archive.
+       * convert-archive.in: New file.
+       * autopoint.in (func_version): Show the archive format.
+       Support archive formats dir, cvs, git, instead of only cvs.
+       * Makefile.am (DISTCLEANFILES): Add convert-archive.
+       (CLEANFILES): Add archive.dir.tar.gz, archive.git.tar.gz.
+       (gettextsrc_DATA): Depend on @ARCHIVE_FORMAT@.
+       (archive.dir.tar.gz, archive.git.tar.gz): New rules.
+       Reported by Arkadiusz Miskiewicz in
+       <https://savannah.gnu.org/bugs/?27281>.
+
 2009-09-27  Bruno Haible  <bruno@clisp.org>
 
        * add-to-archive: Use archive.cvs.tar.gz instead of archive.tar.gz.
index 589eb21cadd8cdc223ae90233ae4479c05ff2d2f..1668782fb363294b0211ab5b5a9a13aa8da3d9ba 100644 (file)
@@ -18,6 +18,7 @@
 
 AUTOMAKE_OPTIONS = 1.2 gnits
 EXTRA_DIST =
+CLEANFILES =
 DISTCLEANFILES =
 
 
@@ -25,12 +26,14 @@ DISTCLEANFILES =
 
 bin_SCRIPTS = gettextize autopoint
 
-DISTCLEANFILES += gettextize autopoint
+DISTCLEANFILES += gettextize autopoint convert-archive
+
+CLEANFILES += archive.dir.tar.gz archive.git.tar.gz
 
 EXTRA_DIST += add-to-archive cvsuser.c archive.cvs.tar.gz
 
 gettextsrcdir = $(datadir)/gettext
-gettextsrc_DATA = archive.cvs.tar.gz
+gettextsrc_DATA = archive.@ARCHIVE_FORMAT@.tar.gz
 
 # The archive.cvs.tar.gz is not in the CVS. Alpha-testers must use the one from
 # an already installed release.
@@ -42,6 +45,24 @@ archive.cvs.tar.gz:
          exit 1; \
        fi
 
+# The archive.dir.tar.gz is generated from archive.cvs.tar.gz.
+archive.dir.tar.gz: archive.cvs.tar.gz
+       if test -f archive.cvs.tar.gz; then \
+         inputfile=archive.cvs.tar.gz; \
+       else \
+         inputfile='$(srcdir)'/archive.cvs.tar.gz; \
+       fi; \
+       ./convert-archive cvs dir "$$inputfile" $@
+
+# The archive.git.tar.gz is generated from archive.cvs.tar.gz.
+archive.git.tar.gz: archive.cvs.tar.gz
+       if test -f archive.cvs.tar.gz; then \
+         inputfile=archive.cvs.tar.gz; \
+       else \
+         inputfile='$(srcdir)'/archive.cvs.tar.gz; \
+       fi; \
+       ./convert-archive cvs git "$$inputfile" $@
+
 # Emacs Lisp code.
 
 lisp_LISP = start-po.el po-mode.el po-compat.el
index 15a8f0b4cb2db07b49a53c79f460ecf74f9a37a0..ec6059d1ff39a79735ccfeb19e7158298ace0dfa 100644 (file)
@@ -173,6 +173,7 @@ Report bugs to <bug-gnu-gettext@gnu.org>."
 func_version ()
 {
   echo "$progname (GNU $package) $version"
+  echo "Uses a versions archive in @ARCHIVE_FORMAT@ format."
   echo "Copyright (C) 2002-2008 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.
@@ -304,46 +305,6 @@ case "$ver" in
     ;;
 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
@@ -403,25 +364,10 @@ if test -z "$podirs"; then
   podirs="po"
 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 up a temporary checkout directory.
 # 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"
@@ -429,44 +375,136 @@ mkdir "$work_dir" || {
     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.cvs.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
-# Check that really all CVS directories are gone, otherwise we would overwrite
-# the contents of the user's CVS directories.
-if test `find archive -name CVS -type d -print | wc -l` != 0; then
-  cd ..
-  rm -rf "$cvs_dir" "$work_dir"
-  func_fatal_error "failed to remove all CVS subdirectories"
-fi
-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 ..
+
+# We support three archive formats.
+#
+# Format | Size (KiB) for gettext-0.17 | Extra tools needed |
+# -------+-----------------------------+--------------------+
+#  dir   |            3000             |         --         |
+#  cvs   |             356             |         cvs        |
+#  git   |             484             |         git        |
+# -------+-----------------------------+--------------------+
+
+case "@ARCHIVE_FORMAT@" in
+  dir)
+    # The archive of different versions is very large, but using it does not
+    # require special tools.
+    gzip -d -c < "$gettext_dir/archive.dir.tar.gz" | (cd "$work_dir" && tar xf - "gettext-$ver")
+    if test `find "$work_dir" -type f -print | wc -l` = 0; then
+      rm -rf "$work_dir"
+      func_fatal_error "infrastructure files for version $ver not found; this is autopoint from GNU $package $version"
+    fi
+    mv "$work_dir/gettext-$ver" "$work_dir/archive"
+    ;;
+
+  cvs)
+    # 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"
+
+    # Set up a temporary CVS repository.
+    # 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
+    cvs_dir=tmpcvs$$
+    # 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
+    }
+    CVSROOT="$srcdir/$cvs_dir"
+    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.cvs.tar.gz" | (cd "$cvs_dir" && tar xf -)
+
+    cd "$work_dir"
+    cvsver=gettext-`echo "$ver" | sed -e 's/\./_/g'`
+    (cvs -d "$CVSROOT" checkout -r"$cvsver" archive > /dev/null) 2>&1 | grep -v '^cvs checkout: Updating'
+    find archive -name CVS -type d -print | xargs rm -rf
+    cd ..
+    rm -rf "$cvs_dir"
+    # Check that really all CVS directories are gone, otherwise we would overwrite
+    # the contents of the user's CVS directories.
+    if test `find $work_dir/archive -name CVS -type d -print | wc -l` != 0; then
+      rm -rf "$work_dir"
+      func_fatal_error "failed to remove all CVS subdirectories"
+    fi
+    if test `find $work_dir/archive -type f -print | wc -l` = 0; then
+      rm -rf "$work_dir"
+      func_fatal_error "infrastructure files for version $ver not found; this is autopoint from GNU $package $version"
+    fi
+    ;;
+
+  git)
+    # Check availability of the git program.
+    (git --version) >/dev/null 2>/dev/null || func_fatal_error "git program not found"
+    mkdir "$work_dir/archive"
+    gzip -d -c < "$gettext_dir/archive.git.tar.gz" | (cd "$work_dir/archive" && tar xf -)
+    (cd "$work_dir/archive" && git checkout -q "gettext-$ver") || {
+      rm -rf "$work_dir"
+      func_fatal_error "infrastructure files for version $ver not found; this is autopoint from GNU $package $version"
+    }
+    (cd "$work_dir/archive" && rm -rf .git .gitignore)
+    ;;
+esac
 
 # func_destfile file
 # determines the destination file, relative to the package's top level
@@ -572,7 +610,7 @@ if test -z "$force"; then
     fi
   done
   if test -n "$mismatch"; then
-    rm -rf "$cvs_dir" "$work_dir"
+    rm -rf "$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"
@@ -657,5 +695,5 @@ for file in `find "$work_dir/archive" -type f -print | sed -e "s,^$work_dir/arch
 done
 
 # That's it.
-rm -rf "$cvs_dir" "$work_dir"
+rm -rf "$work_dir"
 exit 0
diff --git a/gettext-tools/misc/convert-archive.in b/gettext-tools/misc/convert-archive.in
new file mode 100644 (file)
index 0000000..e4c0b33
--- /dev/null
@@ -0,0 +1,294 @@
+#! /bin/sh
+#
+# Copyright (C) 2009 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/>.
+#
+
+# Usage: convert-archive FROM TO [FROMFILE [TOFILE]]
+# where FROM is dir or cvs or git
+# and   TO   is dir or cvs or git
+# This will read FROMFILE (default: archive.$FROM.tar.gz)
+# and produce TOFILE (default: archive.$TO.tar.gz).
+
+progname=$0
+package=@PACKAGE@
+version=@VERSION@
+
+# func_usage
+# outputs to stdout the --help usage message.
+func_usage ()
+{
+  echo "\
+Usage: convert-archive FROM TO [FROMFILE [TOFILE]]
+
+Converts the archive of gettext infrastructure from the FROM format
+to the TO format.
+FROMFILE is the original file, defaulting to archive.\$FROM.tar.gz.
+TOFILE is the destination file, defaulting to archive.\$TO.tar.gz.
+
+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) 2009 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 "convert-archive: *** $1" 1>&2
+  echo "convert-archive: *** Stop." 1>&2
+  exit 1
+}
+
+# Command-line option processing.
+
+if ! { { test $# = 2 || test $# = 3 || test $# = 4; } \
+       && case "$1" in dir | cvs | git ) true;; *) false;; esac \
+       && case "$2" in dir | cvs | git ) true;; *) false;; esac; }; then
+  echo "Usage: convert-archive {dir|cvs|git} {dir|cvs|git} [fromfile [tofile]]"
+  exit 1
+fi
+
+from="$1"
+to="$2"
+fromfile="$3"
+test -n "$fromfile" || fromfile=`pwd`/archive.$from.tar.gz
+tofile="$4"
+test -n "$tofile" || tofile=`pwd`/archive.$to.tar.gz
+
+unpacked=`pwd`/unpacked-files
+mkdir "$unpacked" || {
+  if test -d "$unpacked"; then
+    func_fatal_error "directory $unpacked already exists"
+  else
+    func_fatal_error "cannot create directory $unpacked"
+  fi
+}
+
+# Unpack the original archive.
+case "$from" in
+  dir)
+    gzip -d -c < "$fromfile" | (cd "$unpacked" && tar xf -)
+    ;;
+
+  cvs)
+    # Set variables
+    # - work_dir        directory containing the temporary checkout
+    work_dir=tmpwrk$$
+    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
+    }
+
+    # Set variables
+    # - cvs_dir         directory containing the temporary repository
+    cvs_dir=tmpcvs$$
+    # 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
+    }
+    CVSROOT=`pwd`/"$cvs_dir"
+    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 < "$fromfile" | (cd "$cvs_dir" && tar xf -)
+
+    # A witness that contains all versions.
+    # Can be e.g. ABOUT-NLS, intl/ChangeLog, m4/gettext.m4.
+    witness='ABOUT-NLS'
+
+    # Get list of tags or versions.
+    sed_extract_tags_from_log1='/^symbolic names:/{
+:a
+/^     /p
+n
+ba
+}
+/^keyword substitution:/q'
+    sed_extract_tags_from_log2='s/^    \([^:]*\):.*/\1/'
+    tags=`
+      LC_ALL=C rlog "$cvs_dir"/archive/$witness,v | \
+      sed -n -e "$sed_extract_tags_from_log1" | \
+      sed -e "$sed_extract_tags_from_log2"`
+    sed_tag_to_version='s/_/./g'
+    for tag in $tags; do
+      if test $tag != release; then
+        version=`echo "$tag" | sed -e "$sed_tag_to_version"`
+        (cd "$work_dir"
+         (cvs -d "$CVSROOT" checkout -r"$tag" archive > /dev/null) 2>&1 | grep -v '^cvs checkout: Updating'
+         find archive -name CVS -type d -print | xargs rm -rf
+         rm -rf CVS
+        )
+        mv "$work_dir"/archive "$unpacked/$version"
+      fi
+    done
+    rm -rf "$cvs_dir"
+    rm -rf "$work_dir"
+    ;;
+
+  git)
+    # Set variables
+    # - work_dir        directory containing the temporary checkout
+    work_dir=tmpwrk$$
+    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
+    }
+
+    mkdir "$work_dir/master"
+    gzip -d -c < "$fromfile" | (cd "$work_dir/master" && tar xf -)
+    cd "$work_dir"
+    for tag in `cd master && git tag`; do
+      if test $tag != empty; then
+        version=$tag
+        (cd master && git checkout -q $tag)
+        rm -f master/.gitignore
+        mv master/.git .git
+        mkdir "$unpacked/$version"
+        (cd master && tar cf - .) | (cd "$unpacked/$version" && tar xf -)
+        mv .git master/.git
+      fi
+    done
+    cd ..
+    rm -rf "$work_dir"
+    ;;
+esac
+
+# Create the target archive.
+case "$to" in
+  dir)
+    (cd "$unpacked" && tar cf - --owner=root --group=root *) | gzip -c -9 > "$tofile"
+    ;;
+
+  cvs)
+    # Set variables
+    # - cvs_dir         directory containing the temporary repository
+    cvs_dir=autopoint-files
+    # 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
+    }
+    CVSROOT=`pwd`/"$cvs_dir"
+    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
+
+    # Set a nonstandard variable, for a good-looking cvs history.
+    cvsuser=bruno
+    gcc -shared -fPIC -O cvsuser.c -o cvsuser.so
+    cvsuser_hack=`pwd`/cvsuser.so
+
+    # Need to pass -d "$CVSROOT", because there may be a CVS directory in the
+    # current directory.
+    cvs -d "$CVSROOT" init
+
+    # Add the contents of the unpacked directory to the repository.
+    (cd "$unpacked"
+     for version in *; do
+       cvsver=`echo "$version" | sed -e 's/\./_/g'`
+       (cd $version
+        CVSUSER=$cvsuser LD_PRELOAD=$cvsuser_hack \
+        cvs -d "$CVSROOT" import -m "Import $version" archive release "$cvsver"
+       )
+     done
+    )
+    (cd "$cvs_dir" && tar cf - --owner=root --group=root archive) | gzip -c -9 > "$tofile"
+    rm -rf "$cvs_dir" cvsuser.so
+    ;;
+
+  git)
+    git_dir=`pwd`/tmpgit$$
+    mkdir "$git_dir"
+    (cd "$git_dir" && {
+      git init -q
+      touch .gitignore
+      git add .
+      git commit --author="Bruno Haible <bruno@clisp.org>" --message="Empty directory" 2>&1 | grep -v '^ '
+      git tag empty
+    })
+    sed_remove_leading_dot='s,^\./,,'
+    sed_remove_git_infrastructure='/^\.git/d'
+    (cd "$unpacked"
+     for version in *; do
+       (cd $version && tar cf - .) | \
+       (cd "$git_dir" && {
+         prev_files=`find . -type f | sed -e "$sed_remove_leading_dot" -e "$sed_remove_git_infrastructure"`
+         if test -n "$prev_files"; then
+           git rm -q $prev_files
+         fi
+         tar xf -
+         git add .
+         git commit --author="Bruno Haible <bruno@clisp.org>" --message="Import $version" 2>&1 | grep -v '^ '
+         git tag "$version"
+       })
+     done
+    )
+    (cd "$git_dir" && git reset -q --hard empty && git repack -a -d -q)
+    (cd "$git_dir" && tar cf - --owner=root --group=root .git) | gzip -c -9 > "$tofile"
+    rm -rf "$git_dir"
+    ;;
+esac
+
+rm -rf "$unpacked"