[Reproducible-builds] Bug#825436: gettext: please make xgettext honour SOURCE_DATE_EPOCH

Alexis Bienvenüe pado at passoire.fr
Thu May 26 21:16:00 UTC 2016


Source: gettext
Version: 0.19.7-2
Severity: wishlist
Tags: patch upstream
User: reproducible-builds at lists.alioth.debian.org
Usertags: toolchain
X-Debbugs-Cc: reproducible-builds at lists.alioth.debian.org

Dear Maintainer,

While working on the “reproducible builds” effort [1], we have noticed
that some packages (like gdm3, gnome-session) use xgettext in their
building process, resulting in timestamps in POT files that break
reproducibility.

To solve this kind of issues, it would be nice to have xgettext support
the SOURCE_DATE_EPOCH environment variable [2], so that the
POT-Creation-Date timestamp will be set from the last debian/changelog
entry instead of the (unreproducible) build date.

See the attached patch for a solution to this issue.

Regards,
Alexis Bienvenüe.

[1] https://wiki.debian.org/ReproducibleBuilds
[2] https://reproducible-builds.org/specs/source-date-epoch/


-------------- next part --------------
Description: xgettext honour SOURCE_DATE_EPOCH
 Make xgettext honour the SOURCE_DATE_EPOCH environment variable: is set,
 this variable is used to set POT-Creation-Date.
 See https://reproducible-builds.org/specs/source-date-epoch/
Author: Alexis Bienvenüe <pado at passoire.fr>

Index: gettext-0.19.7/gettext-tools/src/po-time.c
===================================================================
--- gettext-0.19.7.orig/gettext-tools/src/po-time.c
+++ gettext-0.19.7/gettext-tools/src/po-time.c
@@ -52,13 +52,17 @@ difftm (const struct tm *a, const struct
 
 
 char *
-po_strftime (const time_t *tp)
+po_strftime_tz (const time_t *tp, int gmt)
 {
   struct tm local_time;
   char tz_sign;
   long tz_min;
 
-  local_time = *localtime (tp);
+  if (gmt) {
+    local_time = *gmtime (tp);
+  } else {
+    local_time = *localtime (tp);
+  }
   tz_sign = '+';
   tz_min = difftm (&local_time, gmtime (tp)) / 60;
   if (tz_min < 0)
@@ -74,3 +78,9 @@ po_strftime (const time_t *tp)
                     local_time.tm_min,
                     tz_sign, tz_min / 60, tz_min % 60);
 }
+
+char *
+po_strftime (const time_t *tp)
+{
+  return (po_strftime_tz (tp,0));
+}
Index: gettext-0.19.7/gettext-tools/src/po-time.h
===================================================================
--- gettext-0.19.7.orig/gettext-tools/src/po-time.h
+++ gettext-0.19.7/gettext-tools/src/po-time.h
@@ -29,6 +29,7 @@ extern "C" {
 /* Return a freshly allocated string containing the given time in the
    format YYYY-MM-DD HH:MM+TZOFF.  */
 extern char *po_strftime (const time_t *tp);
+extern char *po_strftime_tz (const time_t *tp, int gmt);
 
 
 #ifdef __cplusplus
Index: gettext-0.19.7/gettext-tools/src/xgettext.c
===================================================================
--- gettext-0.19.7.orig/gettext-tools/src/xgettext.c
+++ gettext-0.19.7/gettext-tools/src/xgettext.c
@@ -3723,6 +3723,9 @@ construct_header ()
   message_ty *mp;
   char *msgstr;
   char *comment;
+  char *source_date_epoch;
+  unsigned long long epoch;
+  char *endptr;
   static lex_pos_ty pos = { __FILE__, __LINE__ };
 
   if (package_name != NULL)
@@ -3744,8 +3747,33 @@ the MSGID_BUGS_ADDRESS variable there; o
 specify an --msgid-bugs-address command line option.\n\
 ")));
 
-  time (&now);
-  timestring = po_strftime (&now);
+  source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+  if (source_date_epoch) {
+    errno = 0;
+    epoch = strtoull(source_date_epoch, &endptr, 10);
+    if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
+        || (errno != 0 && epoch == 0)) {
+      fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n", strerror(errno));
+      exit(EXIT_FAILURE);
+    }
+    if (endptr == source_date_epoch) {
+      fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n", endptr);
+      exit(EXIT_FAILURE);
+    }
+    if (*endptr != '\0') {
+      fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n", endptr);
+      exit(EXIT_FAILURE);
+    }
+    if (epoch > ULONG_MAX) {
+      fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to: %lu but was found to be: %llu \n", ULONG_MAX, epoch);
+      exit(EXIT_FAILURE);
+    }
+    now = epoch;
+    timestring = po_strftime_tz (&now,1);
+  } else {
+    time (&now);
+    timestring = po_strftime (&now);
+  }
 
   msgstr = xasprintf ("\
 Project-Id-Version: %s\n\


More information about the Reproducible-builds mailing list