Browse Source

Improve reproducibility recipe

* doc/tar.texi (Reproducibility): Improve index.
Improve and add comments to recipe.  In the recipe,
don’t worry about file names beginning with ‘-’ for simplicity;
don’t use touch -c as it exits with status 0 even when it
does not work; and set directory timestamps too.
Paul Eggert 1 year ago
parent
commit
68636f0bcb
1 changed files with 20 additions and 8 deletions
  1. 20 8
      doc/tar.texi

+ 20 - 8
doc/tar.texi

@@ -10307,6 +10307,7 @@ This option is meaningless with @option{--list} (@option{-t}).
 @node Portability
 @node Portability
 @section Making @command{tar} Archives More Portable
 @section Making @command{tar} Archives More Portable
 
 
+@cindex portable archives
 Creating a @command{tar} archive on a particular system that is meant to be
 Creating a @command{tar} archive on a particular system that is meant to be
 useful later on many other machines and with other versions of @command{tar}
 useful later on many other machines and with other versions of @command{tar}
 is more challenging than you might think.  @command{tar} archive formats
 is more challenging than you might think.  @command{tar} archive formats
@@ -11182,6 +11183,7 @@ Done
 @node Reproducibility
 @node Reproducibility
 @section Making @command{tar} Archives More Reproducible
 @section Making @command{tar} Archives More Reproducible
 
 
+@cindex reproducible archives
 Sometimes it is important for an archive to be @dfn{reproducible},
 Sometimes it is important for an archive to be @dfn{reproducible},
 so that one can be easily verify it to have been derived solely from
 so that one can be easily verify it to have been derived solely from
 its input.  We call an archive reproducible, if an archive
 its input.  We call an archive reproducible, if an archive
@@ -11256,11 +11258,23 @@ function get_commit_time() @{
     --date=format:%Y-%m-%dT%H:%M:%SZ \
     --date=format:%Y-%m-%dT%H:%M:%SZ \
     "$@@"
     "$@@"
 @}
 @}
-SOURCE_EPOCH=$(get_commit_time)
+#
+# Set each source file timestamp to that of its latest commit.
 git ls-files | while read -r file; do
 git ls-files | while read -r file; do
-  commit_time=$(get_commit_time -- "$file") &&
-  touch -cmd $commit_time -- "$file"
+  commit_time=$(get_commit_time "$file") &&
+  touch -md $commit_time "$file"
 done
 done
+#
+# Set timestamp of each directory under $FILES
+# to the latest timestamp of any descendant.
+find $FILES -depth -type d -exec sh -c \
+  'touch -r "$0/$(ls -At "$0" | head -n 1)" "$0"' \
+  @{@} ';'
+#
+# Create $ARCHIVE.tgz from $FILES, pretending that
+# the modification time for each newer file
+# is that of the most recent commit of any source file.
+SOURCE_EPOCH=$(get_commit_time)
 TARFLAGS="
 TARFLAGS="
   --sort=name --format=posix
   --sort=name --format=posix
   --pax-option=exthdr.name=%d/PaxHeaders/%f
   --pax-option=exthdr.name=%d/PaxHeaders/%f
@@ -11269,11 +11283,9 @@ TARFLAGS="
   --numeric-owner --owner=0 --group=0
   --numeric-owner --owner=0 --group=0
   --mode=go+u,go-w
   --mode=go+u,go-w
 "
 "
-GZIPFLAGS="
-  --no-name --best
-"
-LC_ALL=C tar $TARFLAGS -cf - FILES |
-  gzip $GZIPFLAGS > ARCHIVE.tgz
+GZIPFLAGS="--no-name --best"
+LC_ALL=C tar $TARFLAGS -cf - $FILES |
+  gzip $GZIPFLAGS > $ARCHIVE.tgz
 @end example
 @end example
 
 
 @node cpio
 @node cpio