automake
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ``install -C'' / unnecessarily updating time stamps


From: Paul Eggert
Subject: Re: ``install -C'' / unnecessarily updating time stamps
Date: Mon, 25 Dec 2006 21:23:15 -0800
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)

Benoit Sigoure <address@hidden> writes:

> http://lists.gnu.org/archive/html/automake-patches/2006-10/msg00070.html

I installed the following to Automake install-sh to implement
"install-sh -C", which is the second part of that patch.

2006-12-25  Paul Eggert  <address@hidden>

        * 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  <address@hidden>

        * 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.

Index: lib/install-sh
===================================================================
RCS file: /cvs/automake/automake/lib/install-sh,v
retrieving revision 1.38
diff -u -p -r1.38 install-sh
--- lib/install-sh      25 Dec 2006 06:30:28 -0000      1.38
+++ lib/install-sh      26 Dec 2006 05:20:50 -0000
@@ -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: tests/defs.in
===================================================================
RCS file: /cvs/automake/automake/tests/defs.in,v
retrieving revision 1.40
diff -u -p -r1.40 defs.in
--- tests/defs.in       25 Dec 2006 06:30:28 -0000      1.40
+++ tests/defs.in       26 Dec 2006 05:20:50 -0000
@@ -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: tests/instsh2.test
===================================================================
RCS file: /cvs/automake/automake/tests/instsh2.test,v
retrieving revision 1.7
diff -u -p -r1.7 instsh2.test
--- tests/instsh2.test  14 May 2005 20:28:55 -0000      1.7
+++ tests/instsh2.test  26 Dec 2006 05:20:50 -0000
@@ -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'




reply via email to

[Prev in Thread] Current Thread [Next in Thread]