From 53b2a174cf4dbbb7a5404a861f0c2ec2f529d0e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miguel=20=C3=81ngel=20Arruga=20Vivas?=
 <rosen644835@gmail.com>
Date: Tue, 15 Dec 2020 00:05:55 +0100
Subject: [PATCH v3] xgettext, msginit: Honor SOURCE_DATE_EPOCH for timestamps.

* autogen.sh (GNULIB_MODULES_TOOLS_FOR_SRC): Add source-date-epoch.
* gettext-tools/src/msginit.c: Include source-date-epoch.h after
define REPLACE_TIME_WITH_SOURCE_DATE_EPOCH.
* gettext-tools/src/xgettext.c: Likewise.
* gettext-tools/tests/Makefile.am (TESTS): Add new tests.
* gettext-tools/tests/msginit-5: New test case.
* gettext-tools/tests/xgettext-17: Likewise.
* gettext-tools/tests/xgettext-3: Test a fixed POT-Creation-Date
instead of removing it from the generated file.
---
 autogen.sh                      |   1 +
 gettext-tools/src/msginit.c     |   3 +
 gettext-tools/src/xgettext.c    |   2 +
 gettext-tools/tests/Makefile.am |   4 +-
 gettext-tools/tests/msginit-5   | 118 ++++++++++++++++++++++++++++++++
 gettext-tools/tests/xgettext-17 |  59 ++++++++++++++++
 gettext-tools/tests/xgettext-3  |   8 ++-
 7 files changed, 190 insertions(+), 5 deletions(-)
 create mode 100644 gettext-tools/tests/msginit-5
 create mode 100755 gettext-tools/tests/xgettext-17

diff --git a/autogen.sh b/autogen.sh
index 30f5e41dd..869add16c 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -188,6 +188,7 @@ if ! $skip_gnulib; then
     sh-quote
     sigpipe
     sigprocmask
+    source-date-epoch
     spawn-pipe
     stdbool
     stdio
diff --git a/gettext-tools/src/msginit.c b/gettext-tools/src/msginit.c
index 8ca9a3b77..74a2cb3b6 100644
--- a/gettext-tools/src/msginit.c
+++ b/gettext-tools/src/msginit.c
@@ -92,6 +92,9 @@
 #include "propername.h"
 #include "gettext.h"
 
+#define REPLACE_TIME_WITH_SOURCE_DATE_EPOCH 1
+#include "source-date-epoch.h"
+
 #define _(str) gettext (str)
 #define N_(str) (str)
 
diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c
index 1dce01efb..ec28dff77 100644
--- a/gettext-tools/src/xgettext.c
+++ b/gettext-tools/src/xgettext.c
@@ -117,6 +117,8 @@
 #include "x-gsettings.h"
 #include "x-appdata.h"
 
+#define REPLACE_TIME_WITH_SOURCE_DATE_EPOCH 1
+#include "source-date-epoch.h"
 
 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
 #define ENDOF(a) ((a) + SIZEOF(a))
diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am
index 5e1377594..79bad69fa 100644
--- a/gettext-tools/tests/Makefile.am
+++ b/gettext-tools/tests/Makefile.am
@@ -56,7 +56,7 @@ TESTS = gettext-1 gettext-2 \
 	msgfmt-xml-1 msgfmt-xml-2 \
 	msggrep-1 msggrep-2 msggrep-3 msggrep-4 msggrep-5 msggrep-6 msggrep-7 \
 	msggrep-8 msggrep-9 msggrep-10 msggrep-11 \
-	msginit-1 msginit-2 msginit-3 msginit-4 \
+	msginit-1 msginit-2 msginit-3 msginit-4 msginit-5 \
 	msgmerge-1 msgmerge-2 msgmerge-3 msgmerge-4 msgmerge-5 msgmerge-6 \
 	msgmerge-7 msgmerge-8 msgmerge-9 msgmerge-10 msgmerge-11 msgmerge-12 \
 	msgmerge-13 msgmerge-14 msgmerge-15 msgmerge-16 msgmerge-17 \
@@ -77,7 +77,7 @@ TESTS = gettext-1 gettext-2 \
 	recode-sr-latin-1 recode-sr-latin-2 \
 	xgettext-2 xgettext-3 xgettext-4 xgettext-5 xgettext-6 \
 	xgettext-7 xgettext-8 xgettext-9 xgettext-10 xgettext-11 xgettext-12 \
-	xgettext-13 xgettext-14 xgettext-15 xgettext-16 \
+	xgettext-13 xgettext-14 xgettext-15 xgettext-16 xgettext-17 \
 	xgettext-appdata-1 \
 	xgettext-awk-1 xgettext-awk-2 \
 	xgettext-c-2 xgettext-c-3 xgettext-c-4 xgettext-c-5 xgettext-c-6 \
diff --git a/gettext-tools/tests/msginit-5 b/gettext-tools/tests/msginit-5
new file mode 100644
index 000000000..24943e1aa
--- /dev/null
+++ b/gettext-tools/tests/msginit-5
@@ -0,0 +1,118 @@
+#! /bin/sh
+. "${srcdir=.}/init.sh"; path_prepend_ . ../src
+
+# Test reproducible PO file generation with msginit.
+
+# This test fails on mingw, because it relies on the 'project-id' script,
+# which is a shell script (for maintainability) and there is no simple way
+# to execute shell scripts in a native Windows environment.
+# People who need this functionality should use a Cygwin environment, not
+# a native Windows environment.
+
+# This test may fail on Cygwin before 'make install', because the PATH set in
+# msginit.c considers the installation directory, not the build directory.
+
+cat <<\EOF > mi-test5.pot
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 1970-01-01 00:00+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Test msgid"
+msgstr ""
+EOF
+
+: ${MSGINIT=msginit}
+GETTEXTLIBDIR_SRCDIR="$wabs_top_srcdir"/src \
+SOURCE_DATE_EPOCH=1 \
+${MSGINIT} -l ga_IE --no-translator -o mi-test5a.tmp 2>mi-test5a.err
+test $? = 0 || { cat mi-test5a.err 1>&2; Exit 1; }
+
+grep "Project-Id-Version: gt-msginit " mi-test5a.tmp 2>&1 >/dev/null || Exit 1
+
+# The charset stored in the header entry is the locale encoding of the ga_IE
+# locale, which is system dependent, or ASCII if the locale does not exist.
+#
+# Project-Id-Version contains version constructed from a temporary
+# directory name
+sed -e 's/ISO-8859-1/ASCII/g' -e 's/CP1252/ASCII/g' -e 's/UTF-8/ASCII/g' < mi-test5a.tmp | grep -v Project-Id-Version | LC_ALL=C tr -d '\r' > mi-test5a.out || Exit 1
+cat <<\EOF > mi-test5a.ok
+# Irish translations for gt-msginit package.
+# Copyright (C) 1970 THE gt-msginit'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the gt-msginit package.
+# Automatically generated, 1970.
+#
+msgid ""
+msgstr ""
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 1970-01-01 00:00+0000\n"
+"PO-Revision-Date: 1970-01-01 00:00+0000\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ga\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n"
+
+msgid "Test msgid"
+msgstr ""
+EOF
+
+: ${DIFF=diff}
+${DIFF} mi-test5a.ok mi-test5a.out || Exit 1
+
+GETTEXTLIBDIR_SRCDIR="$wabs_top_srcdir"/src \
+SOURCE_DATE_EPOCH=31536000 \
+${MSGINIT} -l ga_IE --no-translator -o mi-test5b.tmp 2>mi-test5b.err
+test $? = 0 || { cat mi-test5b.err 1>&2; Exit 1; }
+
+grep "Project-Id-Version: gt-msginit " mi-test5b.tmp 2>&1 >/dev/null || Exit 1
+
+# The charset stored in the header entry is the locale encoding of the ga_IE
+# locale, which is system dependent, or ASCII if the locale does not exist.
+#
+# Project-Id-Version contains version constructed from a temporary
+# directory name
+sed -e 's/ISO-8859-1/ASCII/g' -e 's/CP1252/ASCII/g' -e 's/UTF-8/ASCII/g' < mi-test5b.tmp | grep -v Project-Id-Version | LC_ALL=C tr -d '\r' > mi-test5b.out || Exit 1
+cat <<\EOF > mi-test5b.ok
+# Irish translations for gt-msginit package.
+# Copyright (C) 1971 THE gt-msginit'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the gt-msginit package.
+# Automatically generated, 1971.
+#
+msgid ""
+msgstr ""
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 1970-01-01 00:00+0000\n"
+"PO-Revision-Date: 1970-01-01 00:00+0000\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: ga\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ASCII\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;\n"
+
+msgid "Test msgid"
+msgstr ""
+EOF
+
+${DIFF} mi-test5b.ok mi-test5b.out
+result=$?
+
+exit $result
diff --git a/gettext-tools/tests/xgettext-17 b/gettext-tools/tests/xgettext-17
new file mode 100755
index 000000000..806dac568
--- /dev/null
+++ b/gettext-tools/tests/xgettext-17
@@ -0,0 +1,59 @@
+#! /bin/sh
+. "${srcdir=.}/init.sh"; path_prepend_ . ../src
+
+# Test reproducible POT generation.
+
+cat <<\EOF > xg-t-17.c
+gettext ("Test msgid");
+EOF
+
+: ${DIFF=diff}
+: ${XGETTEXT=xgettext}
+LC_ALL=C SOURCE_DATE_EPOCH=1 TZ=GMT0 \
+${XGETTEXT} -d xg-t-17 -o xg-t-17-1.pot xg-t-17.c || Exit 1
+
+if ! grep POT-Creation-Date xg-t-17-1.pot > /dev/null; then
+  # xgettext does not output POT-Creation-Date to the header.
+  Exit 77
+fi
+
+# Use the current time to generate this one.
+(
+  unset SOURCE_DATE_EPOCH;
+  time=`date +%s`
+  if test "$time" -gt 60; then
+    LC_ALL=C TZ=GMT0 ${XGETTEXT} -d xg-t-17 -o xg-t-17-2.pot xg-t-17.c
+  else
+    # The system clock provides an unreasonable value, skip this test
+    # case.
+    echo "The system clock provides an unreasonable value: $time" 1>&2
+    echo "This is always different" > xg-t-17-2.pot
+  fi
+) || Exit 1
+
+# Ensure that the wall time is used when SOURCE_DATE_EPOCH is not
+# defined.
+if ${DIFF} xg-t-17-1.pot xg-t-17-2.pot > /dev/null; then
+  Exit 1
+fi
+
+# Call with the same SOURCE_DATE_EPOCH again.
+LC_ALL=C SOURCE_DATE_EPOCH=1 TZ=GMT0 \
+${XGETTEXT} -d xg-t-17 -o xg-t-17-3.pot xg-t-17.c || Exit 1
+
+# Ensure that calls with the same SOURCE_DATE_EPOCH and input generate
+# the same output data.
+${DIFF} xg-t-17-1.pot xg-t-17-3.pot || Exit 1
+
+# Ensure that the output depends on the value provided; this adds a
+# full year to the epoch (60 * 60 * 24 * 365).
+LC_ALL=C SOURCE_DATE_EPOCH=31536000 TZ=GMT0 \
+${XGETTEXT} -d xg-t-17 -o xg-t-17-4.pot xg-t-17.c || Exit 1
+
+# Ensure that two calls with different SOURCE_DATE_EPOCH generate
+# different output files.
+if ${DIFF} xg-t-17-1.pot xg-t-17-4.pot > /dev/null; then
+  Exit 1
+fi
+
+Exit 0
diff --git a/gettext-tools/tests/xgettext-3 b/gettext-tools/tests/xgettext-3
index f5e9f902c..c9bc16b42 100755
--- a/gettext-tools/tests/xgettext-3
+++ b/gettext-tools/tests/xgettext-3
@@ -22,9 +22,10 @@ _("")
 EOF
 
 : ${XGETTEXT=xgettext}
-# delete POT-Creation-Date: line because the date depends on local time.
-${XGETTEXT} --output xg-test3.tmp --no-location -k_ xg-test3.in.c 2>/dev/null || Exit 1
-sed -e '/\"POT-Creation-Date:.*/d' < xg-test3.tmp | LC_ALL=C tr -d '\r' > xg-test3.po
+# Use a fixed timestamp for POT-Creation-Date.
+SOURCE_DATE_EPOCH=1 TZ=GMT0 ${XGETTEXT} --output xg-test3.tmp --no-location \
+  -k_ xg-test3.in.c 2>/dev/null || Exit 1
+LC_ALL=C tr -d '\r' < xg-test3.tmp > xg-test3.po
 
 cat <<EOF > xg-test3.ok
 # SOME DESCRIPTIVE TITLE.
@@ -37,6 +38,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 1970-01-01 00:00+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"

base-commit: d9395be843defd8dff9ef312c048e86d140454da
-- 
2.29.2

