* lib/install-sh (initialize_posix_glob): New var.
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 26 Dec 2006 05:20:52 +0000 (05:20 +0000)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 26 Dec 2006 05:20:52 +0000 (05:20 +0000)
Use it instead of setting posix_glob inline.
(posix_glob): Use '?'/''/: instead of ''/yes/no, for convenience.
(cmpprog, CMPPROG): New vars, since we use cmp rather than the diff
of Akim's patch.
Use LC_ALL before invoking 'ls' when we depend on its output format.
Don't use awk; just use the shell's builtin features.
Clean up $dsttmp -C detects no installation is needed.
* tests/defs.in (is_newest): Renamed from is_younger; the new
name is more accurate.  All uses changed.
(old_timestamp): New var.
* tests/instsh2.test: Rewrite to avoid the need for sleeping.

2006-12-25  Akim Demaille  <akim@epita.fr>

* lib/install-sh: Implement install-sh -C.
(This patch is the remaining part of the patch proposed in
<http://lists.gnu.org/archive/html/automake-patches/2006-10/msg00077.html>.)
(usage): Document it.
(copy_on_change): New var.
* tests/defs.in (is_younger): New function.
* tests/instsh2.test: Check install-sh -C.

ChangeLog
lib/install-sh
tests/defs.in
tests/instsh2.test

index 93999239cb7d96e1993f21999adfec1cbf084b04..a59ab147c0e896d66c03bb2db9b89e1e13cb3e8c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2006-12-25  Paul Eggert  <eggert@cs.ucla.edu>
+
+       * lib/install-sh (initialize_posix_glob): New var.
+       Use it instead of setting posix_glob inline.
+       (posix_glob): Use '?'/''/: instead of ''/yes/no, for convenience.
+       (cmpprog, CMPPROG): New vars, since we use cmp rather than the diff
+       of Akim's patch.
+       Use LC_ALL before invoking 'ls' when we depend on its output format.
+       Don't use awk; just use the shell's builtin features.
+       Clean up $dsttmp -C detects no installation is needed.
+       * tests/defs.in (is_newest): Renamed from is_younger; the new
+       name is more accurate.  All uses changed.
+       (old_timestamp): New var.
+       * tests/instsh2.test: Rewrite to avoid the need for sleeping.
+
+2006-12-25  Akim Demaille  <akim@epita.fr>
+
+       * lib/install-sh: Implement install-sh -C.
+       (This patch is the remaining part of the patch proposed in
+       <http://lists.gnu.org/archive/html/automake-patches/2006-10/msg00077.html>.)
+       (usage): Document it.
+       (copy_on_change): New var.
+       * tests/defs.in (is_younger): New function.
+       * tests/instsh2.test: Check install-sh -C.
+
 2006-12-24  Paul Eggert  <eggert@cs.ucla.edu>
 
        * lib/install-sh: Fix typo in previous patch for handling --.
index 3386cf14b257f076689ae1d54bb03b17ef2ee88a..a5897de6ea7f74f83fd793474bb4738d32884719 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2006-12-24.16
+scriptversion=2006-12-25.00
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -61,13 +61,24 @@ fi
 chgrpprog=${CHGRPPROG-chgrp}
 chmodprog=${CHMODPROG-chmod}
 chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
 cpprog=${CPPROG-cp}
 mkdirprog=${MKDIRPROG-mkdir}
 mvprog=${MVPROG-mv}
 rmprog=${RMPROG-rm}
 stripprog=${STRIPPROG-strip}
 
-posix_glob=
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
 posix_mkdir=
 
 # Desired mode of installed file.
@@ -85,6 +96,7 @@ dst=
 dir_arg=
 dst_arg=
 
+copy_on_change=false
 no_target_directory=
 
 usage="\
@@ -102,6 +114,7 @@ Options:
      --version  display version info and exit.
 
   -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
   -d            create directories instead of installing files.
   -g GROUP      $chgrpprog installed files to GROUP.
   -m MODE       $chmodprog installed files to MODE.
@@ -111,13 +124,16 @@ Options:
   -T            report an error if DSTFILE is a directory.
 
 Environment variables override the default commands:
-  CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
 "
 
 while test $# -ne 0; do
   case $1 in
     -c) ;;
 
+    -C) copy_on_change=true;;
+
     -d) dir_arg=true;;
 
     -g) chgrpcmd="$chgrpprog $2"
@@ -373,21 +389,14 @@ do
        *)  prefix='';;
       esac
 
-      case $posix_glob in
-       '')
-         if (set -f) 2>/dev/null; then
-           posix_glob=true
-         else
-           posix_glob=false
-         fi;;
-      esac
+      eval "$initialize_posix_glob"
 
       oIFS=$IFS
       IFS=/
-      $posix_glob && set -f
+      $posix_glob set -f
       set fnord $dstdir
       shift
-      $posix_glob && set +f
+      $posix_glob set +f
       IFS=$oIFS
 
       prefixes=
@@ -454,32 +463,49 @@ do
     { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
     { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
 
-    # Now rename the file to the real destination.
-    { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || {
-          # The rename failed, perhaps because mv can't rename something else
-          # to itself, or perhaps because mv is so ancient that it does not
-          # support -f.
-
-          # Now remove or move aside any old file at destination location.
-          # We try this two ways since rm can't unlink itself on some
-          # systems and the destination file might be busy for other
-          # reasons.  In this case, the final cleanup might fail but the new
-          # file should still install successfully.
-          {
-            test ! -f "$dst" ||
-            $doit $rmcmd -f "$dst" 2>/dev/null ||
-            { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
-              { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
-            } ||
-            { echo "$0: cannot unlink or rename $dst" >&2
-              (exit 1); exit 1
-            }
-          } &&
-
-          # Now rename the file to the real destination.
-          $doit $mvcmd "$dsttmp" "$dst"
-        }
-    } || exit 1
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"    2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+       # Now remove or move aside any old file at destination location.
+       # We try this two ways since rm can't unlink itself on some
+       # systems and the destination file might be busy for other
+       # reasons.  In this case, the final cleanup might fail but the new
+       # file should still install successfully.
+       {
+         test ! -f "$dst" ||
+         $doit $rmcmd -f "$dst" 2>/dev/null ||
+         { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+           { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+         } ||
+         { echo "$0: cannot unlink or rename $dst" >&2
+           (exit 1); exit 1
+         }
+       } &&
+
+       # Now rename the file to the real destination.
+       $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
 
     trap '' 0
   fi
index a6d075316059e72ca87733c2173aeac1387ec09a..b2c31c7c8a21c16b9d1e532cd9335dc4c4ee9df7 100644 (file)
@@ -316,6 +316,22 @@ sleep='sleep @MODIFICATION_DELAY@'
 testsrcdir=$srcdir
 unset srcdir
 
+# An old timestamp that can be given to a file, in "touch -t" format.
+# The time stamp should be portable to all file systems of interest.
+# Just for fun, choose the exact time of the announcement of the GNU project
+# in UTC; see <http://www.gnu.org/gnu/initial-announcement.html>.
+old_timestamp=198309271735.59
+
+# is_newest FILE FILES
+# --------------------
+# Return false if any file in FILES is newer than FILE.
+# Resolve ties in favor of FILE.
+is_newest ()
+{
+  test x`find "$@" -newer "$1"` = x
+}
+
+
 # AUTOMAKE_run status [options...]
 # --------------------------------
 # Run Automake with OPTIONS, and fail if automake
index 8e463db6673da062ea4dcf8f05cf5dca8628531c..88f19855e08d760ec32918cb627f0b011e6cbd20 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# Copyright (C) 2002, 2004  Free Software Foundation, Inc.
+# Copyright (C) 2002, 2004, 2006  Free Software Foundation, Inc.
 #
 # This file is part of GNU Automake.
 #
@@ -21,7 +21,6 @@
 # Various install-sh checks
 
 . ./defs || exit 1
-
 set -e
 
 # Basic errors
@@ -82,6 +81,20 @@ test -f d3/y
 ./install-sh -T x d3 && exit 1
 ./install-sh -T x d4// && exit 1
 
+# Do not change the timestamps when using -C.
+echo foo >file
+./install-sh -C file d1
+TZ=UTC0 touch -t $old_timestamp d1/file
+./install-sh -C file d1
+is_newest file d1/file
+echo foo1 >file
+./install-sh -C file d1
+diff file d1/file
+# Rights must be updated.
+./install-sh -C -m 444 file d1
+test -r d1/file
+test ! -w d1/file
+
 # Ensure that install-sh works with names that include spaces
 touch 'a  b'
 mkdir 'x  y'