]> git.ipfire.org Git - thirdparty/automake.git/commitdiff
Reliable multi-file install for man pages.
authorRalf Wildenhues <Ralf.Wildenhues@gmx.de>
Sun, 7 Sep 2008 07:59:52 +0000 (09:59 +0200)
committerRalf Wildenhues <Ralf.Wildenhues@gmx.de>
Sun, 7 Sep 2008 08:13:35 +0000 (10:13 +0200)
* lib/am/mans.am: Include inst-vars.am.
(install-man%SECTION%): Gather lists of man pages to install,
and install up to 40 of those that do not have to be renamed
at once.  Fail if installation of any file fails.
(uninstall-man%SECTION%): Rewrite to use fewer sed invocations.
* doc/automake.texi (Man pages): Hint the user to the fast path.
Indentation fix.
* tests/instmany-mans.test: New test.
* tests/Makefile.am: Update.

Signed-off-by: Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
ChangeLog
doc/automake.texi
lib/am/mans.am
tests/Makefile.am
tests/Makefile.in
tests/instmany-mans.test [new file with mode: 0755]

index 4266e4dc66bf9010c349edd85e80bf1af4e94349..e5b4eb652604943f270dad6b3e36d0d8f1884266 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-09-07  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
+           Jim Meyering <jim@meyering.net>
+
+       Reliable multi-file install for man pages.
+       * lib/am/mans.am: Include inst-vars.am.
+       (install-man%SECTION%): Gather lists of man pages to install,
+       and install up to 40 of those that do not have to be renamed
+       at once.  Fail if installation of any file fails.
+       (uninstall-man%SECTION%): Rewrite to use fewer sed invocations.
+       * doc/automake.texi (Man pages): Hint the user to the fast path.
+       Indentation fix.
+       * tests/instmany-mans.test: New test.
+       * tests/Makefile.am: Update.
+
 2008-09-07  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
        Faster `make uninstall'; fast install for JAVA.
index 0ea578097052218fb8cb739483ee53f895f0d09d..263d1b638d65554938a98dc3d6c7b75bc8602854 100644 (file)
@@ -7644,6 +7644,7 @@ For instance, consider this example:
 man1_MANS = rename.man thesame.1 alsothesame.1c
 @end example
 
+@noindent
 In this case, @file{rename.man} will be renamed to @file{rename.1} when
 installed, but the other files will keep their names.
 
@@ -7661,6 +7662,10 @@ not expend effort to keep the man pages up to date.  In these cases, the
 installed by default.  The user can still explicitly install them via
 @samp{make install-man}.
 
+For fast installation, with many files it is preferable to use
+@samp{man@var{SECTION}_MANS} over @samp{man_MANS} as well as files that
+do not need to be renamed.
+
 Man pages are not currently considered to be source, because it is not
 uncommon for man pages to be automatically generated.  Therefore they
 are not automatically included in the distribution.  However, this can
index 338b43c512d1b4dedd1a3472836fa8b6a8ab2ba0..803a89227f70b90052cdfe4c017a10a878bf7db7 100644 (file)
@@ -15,6 +15,7 @@
 ## You should have received a copy of the GNU General Public License
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+include inst-vars.am
 man%SECTION%dir = $(mandir)/man%SECTION%
 
 ## ------------ ##
@@ -34,62 +35,69 @@ install-man%SECTION%: %DEPS%
 if %?NOTRANS_MANS%
 ## Handle MANS with notrans_ prefix
        @list='%NOTRANS_SECT_LIST%'; \
+       { for i in $$list; do echo "$$i"; done;  \
 ## Extract all items from notrans_man_MANS that should go in this section.
 ## This must be done dynamically to support conditionals.
-?HAVE_NOTRANS? l2='%NOTRANS_LIST%'; \
-?HAVE_NOTRANS? for i in $$l2; do \
-?HAVE_NOTRANS?   case "$$i" in \
-## Have to accept files like `foo.1c'.
-?HAVE_NOTRANS?     *.%SECTION%*) list="$$list $$i" ;; \
-?HAVE_NOTRANS?   esac; \
+?HAVE_NOTRANS? l2='%NOTRANS_LIST%'; for i in $$l2; do \
+## Accept files like `foo.1c'.
+?HAVE_NOTRANS?   case $$i in *.%SECTION%*) echo "$$i";; esac; \
 ?HAVE_NOTRANS? done; \
-       for i in $$list; do \
+## Extract basename of manpage, change the extension if needed.
+       } | while read p; do \
 ## Find the file.
-         if test -f $$i; then file=$$i; \
-         else file=$(srcdir)/$$i; fi; \
-## Change the extension if needed.
-         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
-         case "$$ext" in \
-           %SECTION%*) ;; \
-           *) ext='%SECTION%' ;; \
-         esac; \
-## Extract basename of man page and append extension.
-         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
-         inst=`echo $$inst | sed -e 's/^.*\///'`.$$ext; \
-         echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \
-         $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man%SECTION%dir)/$$inst"; \
-       done
+         if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; echo "$$p"; \
+       done | \
+## Extract the basename of the man page and change the extension if needed.
+       sed 'n;s,.*/,,;p;s,\.[^%SECTION%][0-9a-z]*$$,.%SECTION%,' | \
+       sed 'N;N;s,\n, ,g' | { \
+## We now have a list "sourcefile basename installed-name".
+       list=; while read file base inst; do \
+         if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+           echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \
+           $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man%SECTION%dir)/$$inst" || exit $$?; \
+         fi; \
+       done; \
+       for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+       while read files; do \
+         test -z "$$files" || { \
+           echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man%SECTION%dir)'"; \
+           $(INSTALL_DATA) $$files "$(DESTDIR)$(man%SECTION%dir)" || exit $$?; }; \
+       done; }
 endif %?NOTRANS_MANS%
 if %?TRANS_MANS%
 ## Handle MANS without notrans_ prefix
        @list='%TRANS_SECT_LIST%'; \
-## Extract all items from man_MANS that should go in this section.
+       { for i in $$list; do echo "$$i"; done; \
+## Extract all items from notrans_man_MANS that should go in this section.
 ## This must be done dynamically to support conditionals.
-?HAVE_TRANS?   l2='%TRANS_LIST%'; \
-?HAVE_TRANS?   for i in $$l2; do \
-?HAVE_TRANS?     case "$$i" in \
-## Have to accept files like `foo.1c'.
-?HAVE_TRANS?       *.%SECTION%*) list="$$list $$i" ;; \
-?HAVE_TRANS?     esac; \
+?HAVE_TRANS?   l2='%TRANS_LIST%'; for i in $$l2; do \
+## Accept files like `foo.1c'.
+?HAVE_TRANS?     case $$i in *.%SECTION%*) echo "$$i";; esac; \
 ?HAVE_TRANS?   done; \
-       for i in $$list; do \
+## Extract basename of manpage, change the extension if needed.
+       } | while read p; do \
 ## Find the file.
-         if test -f $$i; then file=$$i; \
-         else file=$(srcdir)/$$i; fi; \
-## Change the extension if needed.
-         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
-         case "$$ext" in \
-           %SECTION%*) ;; \
-           *) ext='%SECTION%' ;; \
-         esac; \
-## Extract basename of man page and run it through the program rename
-## transform.
-         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
-         inst=`echo $$inst | sed -e 's/^.*\///'`; \
-         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
-         echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \
-         $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man%SECTION%dir)/$$inst"; \
-       done
+         if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; echo "$$p"; \
+       done | \
+## Extract the basename of the man page and change the extension if needed.
+       sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^%SECTION%][0-9a-z]*$$,%SECTION%,;x' \
+             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+       sed 'N;N;s,\n, ,g' | { \
+## We now have a list "sourcefile basename installed-name".
+       list=; while read file base inst; do \
+         if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+           echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \
+           $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man%SECTION%dir)/$$inst" || exit $$?; \
+         fi; \
+       done; \
+       for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+       while read files; do \
+         test -z "$$files" || { \
+           echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man%SECTION%dir)'"; \
+           $(INSTALL_DATA) $$files "$(DESTDIR)$(man%SECTION%dir)" || exit $$?; }; \
+       done; }
 endif %?TRANS_MANS%
 
 
@@ -97,7 +105,6 @@ endif %?TRANS_MANS%
 ## Uninstalling.  ##
 ## -------------- ##
 
-## This is just completely gross.
 .PHONY: uninstall-man
 ?INSTALL-MAN?uninstall-am: uninstall-man
 .PHONY uninstall-man: uninstall-man%SECTION%
@@ -106,54 +113,34 @@ uninstall-man%SECTION%:
 if %?NOTRANS_MANS%
 ## Handle MANS with notrans_ prefix
        @list='%NOTRANS_SECT_LIST%'; \
+       files=`{ for i in $$list; do echo "$$i"; done; \
 ## Extract all items from notrans_man_MANS that should go in this section.
 ## This must be done dynamically to support conditionals.
-?HAVE_NOTRANS? l2='%NOTRANS_LIST%'; \
-?HAVE_NOTRANS? for i in $$l2; do \
-?HAVE_NOTRANS?   case "$$i" in \
-## Have to accept files like `foo.1c'.
-?HAVE_NOTRANS?     *.%SECTION%*) list="$$list $$i" ;; \
-?HAVE_NOTRANS?   esac; \
+?HAVE_NOTRANS? l2='%NOTRANS_LIST%'; for i in $$l2; do \
+## Accept files like `foo.1c'.
+?HAVE_NOTRANS?   case $$i in *.%SECTION%*) echo "$$i";; esac; \
 ?HAVE_NOTRANS? done; \
-       for i in $$list; do \
-## Change the extension if needed.
-         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
-         case "$$ext" in \
-           %SECTION%*) ;; \
-           *) ext='%SECTION%' ;; \
-         esac; \
-## Extract basename of man page and append extension.
-         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
-         inst=`echo $$inst | sed -e 's/^.*\///'`.$$ext; \
-         echo " rm -f '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \
-         rm -f "$(DESTDIR)$(man%SECTION%dir)/$$inst"; \
-       done
+## Extract basename of manpage, change the extension if needed.
+       } | sed 's,.*/,,;s,\.[^%SECTION%][0-9a-z]*$$,.%SECTION%,'`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(man%SECTION%dir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(man%SECTION%dir)" && rm -f $$files
 endif %?NOTRANS_MANS%
 if %?TRANS_MANS%
 ## Handle MANS without notrans_ prefix
        @list='%TRANS_SECT_LIST%'; \
+       files=`{ for i in $$list; do echo "$$i"; done; \
 ## Extract all items from man_MANS that should go in this section.
 ## This must be done dynamically to support conditionals.
-?HAVE_TRANS?   l2='%TRANS_LIST%'; \
-?HAVE_TRANS?   for i in $$l2; do \
-?HAVE_TRANS?     case "$$i" in \
-## Have to accept files like `foo.1c'.
-?HAVE_TRANS?       *.%SECTION%*) list="$$list $$i" ;; \
-?HAVE_TRANS?     esac; \
+?HAVE_TRANS?   l2='%TRANS_LIST%'; for i in $$l2; do \
+## Accept files like `foo.1c'.
+?HAVE_TRANS?     case $$i in *.%SECTION%*) echo "$$i";; esac; \
 ?HAVE_TRANS?   done; \
-       for i in $$list; do \
-## Change the extension if needed.
-         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
-         case "$$ext" in \
-           %SECTION%*) ;; \
-           *) ext='%SECTION%' ;; \
-         esac; \
-## Extract basename of man page and run it through the program rename
-## transform.
-         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
-         inst=`echo $$inst | sed -e 's/^.*\///'`; \
-         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
-         echo " rm -f '$(DESTDIR)$(man%SECTION%dir)/$$inst'"; \
-         rm -f "$(DESTDIR)$(man%SECTION%dir)/$$inst"; \
-       done
+## Extract basename of manpage, run it through the program rename
+## transform, and change the extension if needed.
+       } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^%SECTION%][0-9a-z]*$$,%SECTION%,;x' \
+             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(man%SECTION%dir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(man%SECTION%dir)" && rm -f $$files
 endif %?TRANS_MANS%
index 7a6b2865a3bfc2f7ac1066e67eb438ca432f88f6..a9e995eb8bed8b7d50eb7e80d06ecc2587c9e153 100644 (file)
@@ -311,6 +311,7 @@ insthook.test \
 instman.test \
 instman2.test \
 instmany.test \
+instmany-mans.test \
 instmany-python.test \
 instspc.test \
 interp.test \
index 914ebf84f678ab9d475fdfca1af3d68ad3fa7a34..d5559b646bbbe3c96a55a5ed1c02667a916da604 100644 (file)
@@ -462,6 +462,7 @@ insthook.test \
 instman.test \
 instman2.test \
 instmany.test \
+instmany-mans.test \
 instmany-python.test \
 instspc.test \
 interp.test \
diff --git a/tests/instmany-mans.test b/tests/instmany-mans.test
new file mode 100755 (executable)
index 0000000..3f331a6
--- /dev/null
@@ -0,0 +1,147 @@
+#! /bin/sh
+# Copyright (C) 2008  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, 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/>.
+
+# Installing many files should not exceed the command line length limit.
+
+# This is the mans sister test of instmany.test, see there for details.
+
+required=non-root    # hope to catch 'chmod a-r'-challenged file systems.
+. ./defs || Exit 1
+
+set -e
+
+# In order to have a useful test on modern systems (which have a high
+# limit, if any), use a fake install program that errors out for more
+# than 2K characters in a command line.  The POSIX limit is 4096, but
+# that may include space taken up by the environment.
+
+limit=2500
+subdir=long_subdir_name_with_many_characters
+nfiles=81
+
+# Let's use `seq' if available, it's faster than the loop.
+list=`(seq 1 $nfiles) 2>/dev/null || {
+  i=1
+  while test $i -le $nfiles; do
+    echo $i
+    i=\`expr $i + 1\`
+  done; }`
+
+sed "s|@limit@|$limit|g" >myinstall.in <<'END'
+#! /bin/sh
+# Fake install script.  This doesn't really install
+# (the INSTALL path below would be wrong outside this directory).
+limit=@limit@
+INSTALL='@INSTALL@'
+len=`expr "$INSTALL $*" : ".*" 2>/dev/null || echo $limit`
+if test $len -ge $limit; then
+  echo "$0: safe command line limit of $limit characters exceeded" >&2
+  exit 1
+fi
+exit 0
+END
+
+# Creative quoting in the next line to please maintainer-check.
+sed "s|@limit@|$limit|g" >'rm' <<'END'
+#! /bin/sh
+limit=@limit@
+PATH=$save_PATH
+export PATH
+RM='rm -f'
+len=`expr "$RM $*" : ".*" 2>/dev/null || echo $limit`
+if test $len -ge $limit; then
+  echo "$0: safe command line limit of $limit characters exceeded" >&2
+  exit 1
+fi
+exec $RM "$@"
+exit 1
+END
+
+chmod +x rm
+
+cat >>configure.in <<END
+AC_CONFIG_FILES([myinstall], [chmod +x ./myinstall])
+AC_CONFIG_FILES([$subdir/Makefile])
+AC_OUTPUT
+END
+
+cat >Makefile.am <<END
+SUBDIRS = $subdir
+END
+
+mkdir $subdir
+cd $subdir
+
+cat >Makefile.am <<'END'
+man_MANS =
+man3_MANS =
+notrans_man_MANS =
+notrans_man3_MANS =
+END
+
+for n in $list; do
+  cat >>Makefile.am <<END
+man_MANS += page$n.1
+man3_MANS += page$n.man
+notrans_man_MANS += npage$n.1
+notrans_man3_MANS += npage$n.man
+END
+  echo >page$n.1
+  echo >page$n.man
+  echo >npage$n.1
+  echo >npage$n.man
+done
+
+cd ..
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE --add-missing
+
+instdir=`pwd`/inst
+mkdir build
+cd build
+../configure --prefix="$instdir"
+$MAKE
+# Try whether native install (or install-sh) works.
+$MAKE install
+$MAKE uninstall
+test `find "$instdir" -type f -print | wc -l` = 0
+
+# Try whether we don't exceed the low limit.
+INSTALL='$(SHELL) $(top_builddir)/myinstall' $MAKE -e install
+env save_PATH="$PATH" PATH="`pwd`/..:$PATH" $MAKE uninstall
+
+cd $subdir
+srcdir=../../$subdir
+
+# Ensure 'make install' fails when 'install' fails.
+
+# We cheat here, for efficiency, knowing the internal rule names.
+# For correctness, one should `$MAKE install' here always, or at
+# least use install-exec or install-data.
+
+for file in page3.1 page$nfiles.1 npage3.1 npage$nfiles.1; do
+  chmod a-r $srcdir/$file
+  $MAKE install-man1 && Exit 1
+  chmod u+r $srcdir/$file
+done
+
+for file in page3.man page$nfiles.man npage3.man npage$nfiles.man; do
+  chmod a-r $srcdir/$file
+  $MAKE install-man3 && Exit 1
+  chmod u+r $srcdir/$file
+done
+: