commit d13f165b83701dffc14f7151419e0c00c00c0d1b Author: John Darrington Date: Thu Dec 15 21:56:44 2016 +0100 msgfmt: Remove POT-Creation-Date field from the header in the output. This helps reproducible builds. Reported at . * gettext-tools/src/msgl-header.h (message_list_delete_header_field): New declaration. * gettext-tools/src/msgl-header.c (known_fields): New variable, extracted from msgdomain_list_set_header_field. (message_list_delete_header_field): New function. * gettext-tools/src/write-mo.c: Include msgl-header.h. (msgdomain_write_mo): Delete the POT-Creation-Date field. * gettext-tools/src/write-java.c: Include msgl-header.h. (msgdomain_write_java): Delete the POT-Creation-Date field. * gettext-tools/src/write-csharp.c: Include msgl-header.h. (msgdomain_write_csharp): Delete the POT-Creation-Date field. * gettext-tools/src/write-resources.c: Include msgl-header.h. (msgdomain_write_csharp_resources): Delete the POT-Creation-Date field. * gettext-tools/src/write-tcl.c: Include msgl-header.h. (msgdomain_write_tcl): Delete the POT-Creation-Date field. * gettext-tools/src/write-qt.c: Include msgl-header.h. (msgdomain_write_qt): Delete the POT-Creation-Date field. * gettext-tools/src/write-desktop.c: Include msgl-header.h. (msgdomain_write_desktop): Delete the POT-Creation-Date field. * gettext-tools/src/write-xml.c: Include msgl-header.h. (msgdomain_write_xml): Delete the POT-Creation-Date field. * gettext-tools/tests/msgfmt-19: New file, based on gettext-tools/tests/msgfmt-18. * gettext-tools/tests/Makefile.am (TESTS): Add it. diff --git a/gettext-tools/src/msgl-header.c b/gettext-tools/src/msgl-header.c index 987c1c47e..25ae33af3 100644 --- a/gettext-tools/src/msgl-header.c +++ b/gettext-tools/src/msgl-header.c @@ -30,16 +30,12 @@ #define SIZEOF(a) (sizeof(a) / sizeof(a[0])) -void -msgdomain_list_set_header_field (msgdomain_list_ty *mdlp, - const char *field, const char *value) +/* The known fields in their usual order. */ +static const struct { - /* The known fields in their usual order. */ - static const struct - { - const char *name; - size_t len; - } + const char *name; + size_t len; +} known_fields[] = { { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 }, @@ -54,6 +50,11 @@ msgdomain_list_set_header_field (msgdomain_list_ty *mdlp, { "Content-Transfer-Encoding:", sizeof ("Content-Transfer-Encoding:") - 1 } }; + +void +msgdomain_list_set_header_field (msgdomain_list_ty *mdlp, + const char *field, const char *value) +{ size_t field_len; int field_index; size_t k, i; @@ -168,3 +169,71 @@ msgdomain_list_set_header_field (msgdomain_list_ty *mdlp, } } } + + +void +message_list_delete_header_field (message_list_ty *mlp, + const char *field) +{ + size_t j; + int field_index; + size_t k; + + /* Search the field in known_fields[]. */ + field_index = -1; + for (k = 0; k < SIZEOF (known_fields); k++) + if (strcmp (known_fields[k].name, field) == 0) + { + field_index = k; + break; + } + + size_t field_len; + field_len = strlen (field); + + /* Search the header entry. */ + for (j = 0; j < mlp->nitems; j++) + if (is_header (mlp->item[j]) && !mlp->item[j]->obsolete) + { + message_ty *mp = mlp->item[j]; + + /* Modify the header entry. */ + const char *header = mp->msgstr; + char *new_header = + XCALLOC (strlen (header) + 1, + char); + + /* Test whether the field already occurs in the header entry. */ + const char *h; + + for (h = header; *h != '\0'; ) + { + if (strncmp (h, field, field_len) == 0) + break; + h = strchr (h, '\n'); + if (h == NULL) + break; + h++; + } + if (h != NULL && *h != '\0') + { + /* Replace the field. */ + char *p = new_header; + memcpy (p, header, h - header); + p += h - header; + h = strchr (h, '\n'); + if (h != NULL) + { + h++; + stpcpy (p, h); + } + } + else + { + char *p = new_header; + p = stpcpy (p, header); + } + + mp->msgstr = new_header; + } +} diff --git a/gettext-tools/src/msgl-header.h b/gettext-tools/src/msgl-header.h index 968515711..34726e7b0 100644 --- a/gettext-tools/src/msgl-header.h +++ b/gettext-tools/src/msgl-header.h @@ -34,6 +34,9 @@ extern void msgdomain_list_set_header_field (msgdomain_list_ty *mdlp, const char *field, const char *value); +extern void + message_list_delete_header_field (message_list_ty *mlp, const char *field); + #ifdef __cplusplus } diff --git a/gettext-tools/src/write-csharp.c b/gettext-tools/src/write-csharp.c index 5cf573a0f..30e8411cc 100644 --- a/gettext-tools/src/write-csharp.c +++ b/gettext-tools/src/write-csharp.c @@ -78,6 +78,7 @@ #include "message.h" #include "msgfmt.h" #include "msgl-iconv.h" +#include "msgl-header.h" #include "plural-exp.h" #include "po-charset.h" #include "xalloc.h" @@ -645,6 +646,8 @@ msgdomain_write_csharp (message_list_ty *mlp, const char *canon_encoding, /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + /* Create a temporary directory where we can put the C# file. A simple temporary file would also be possible but would require us to define our own variant of mkstemp(): On one hand the functions mktemp(), diff --git a/gettext-tools/src/write-desktop.c b/gettext-tools/src/write-desktop.c index 898ac3024..e568d47fb 100644 --- a/gettext-tools/src/write-desktop.c +++ b/gettext-tools/src/write-desktop.c @@ -29,6 +29,7 @@ #include #include "error.h" #include "msgl-iconv.h" +#include "msgl-header.h" #include "po-charset.h" #include "read-catalog.h" #include "read-po.h" @@ -203,6 +204,8 @@ msgdomain_write_desktop (message_list_ty *mlp, /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + /* Create a single-element operands and run the bulk operation on it. */ operand.language = (char *) locale_name; operand.mlp = mlp; diff --git a/gettext-tools/src/write-java.c b/gettext-tools/src/write-java.c index eef8c79d2..039ed94d9 100644 --- a/gettext-tools/src/write-java.c +++ b/gettext-tools/src/write-java.c @@ -61,6 +61,7 @@ #include "message.h" #include "msgfmt.h" #include "msgl-iconv.h" +#include "msgl-header.h" #include "plural-exp.h" #include "po-charset.h" #include "xalloc.h" @@ -1066,6 +1067,8 @@ msgdomain_write_java (message_list_ty *mlp, const char *canon_encoding, /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + if (output_source) { tmpdir = NULL; diff --git a/gettext-tools/src/write-mo.c b/gettext-tools/src/write-mo.c index b4a789494..b99dece02 100644 --- a/gettext-tools/src/write-mo.c +++ b/gettext-tools/src/write-mo.c @@ -48,6 +48,9 @@ #include "binary-io.h" #include "fwriteerror.h" #include "gettext.h" +#include "read-catalog.h" +#include "read-stringtable.h" +#include "msgl-header.h" #define _(str) gettext (str) @@ -804,6 +807,7 @@ msgdomain_write_mo (message_list_ty *mlp, if (output_file != NULL) { + message_list_delete_header_field (mlp, "POT-Creation-Date:"); write_table (output_file, mlp); /* Make sure nothing went wrong. */ diff --git a/gettext-tools/src/write-qt.c b/gettext-tools/src/write-qt.c index 978bf0938..4a47d241f 100644 --- a/gettext-tools/src/write-qt.c +++ b/gettext-tools/src/write-qt.c @@ -35,6 +35,7 @@ #include "message.h" #include "po-charset.h" #include "msgl-iconv.h" +#include "msgl-header.h" #include "hash-string.h" #include "unistr.h" #include "xalloc.h" @@ -742,6 +743,7 @@ strings, not in the untranslated strings\n"))); if (output_file != NULL) { + message_list_delete_header_field (mlp, "POT-Creation-Date:"); write_qm (output_file, mlp); /* Make sure nothing went wrong. */ diff --git a/gettext-tools/src/write-resources.c b/gettext-tools/src/write-resources.c index e5103c4b0..ec74eadcd 100644 --- a/gettext-tools/src/write-resources.c +++ b/gettext-tools/src/write-resources.c @@ -38,6 +38,7 @@ #include "message.h" #include "msgfmt.h" #include "msgl-iconv.h" +#include "msgl-header.h" #include "po-charset.h" #include "xalloc.h" #include "concat-filename.h" @@ -114,6 +115,8 @@ msgdomain_write_csharp_resources (message_list_ty *mlp, const char *domain_name, const char *file_name) { + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + /* If no entry for this domain don't even create the file. */ if (mlp->nitems != 0) { diff --git a/gettext-tools/src/write-tcl.c b/gettext-tools/src/write-tcl.c index 0dbe3aa88..04b62d9c8 100644 --- a/gettext-tools/src/write-tcl.c +++ b/gettext-tools/src/write-tcl.c @@ -34,6 +34,7 @@ #include "xerror.h" #include "message.h" #include "msgl-iconv.h" +#include "msgl-header.h" #include "po-charset.h" #include "xalloc.h" #include "xmalloca.h" @@ -216,6 +217,7 @@ but the Tcl message catalog format doesn't support plural handling\n"))); return 1; } + message_list_delete_header_field (mlp, "POT-Creation-Date:"); write_msg (output_file, mlp, frobbed_locale_name); /* Make sure nothing went wrong. */ diff --git a/gettext-tools/src/write-xml.c b/gettext-tools/src/write-xml.c index 79b7b5dbc..f6cd6c003 100644 --- a/gettext-tools/src/write-xml.c +++ b/gettext-tools/src/write-xml.c @@ -29,6 +29,7 @@ #include #include "error.h" #include "msgl-iconv.h" +#include "msgl-header.h" #include "po-charset.h" #include "read-catalog.h" #include "read-po.h" @@ -94,6 +95,8 @@ msgdomain_write_xml (message_list_ty *mlp, /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + /* Create a single-element operands and run the bulk operation on it. */ operand.language = (char *) locale_name; operand.mlp = mlp; diff --git a/gettext-tools/tests/Makefile.am b/gettext-tools/tests/Makefile.am index 0dfb4d867..38b47b922 100644 --- a/gettext-tools/tests/Makefile.am +++ b/gettext-tools/tests/Makefile.am @@ -46,7 +46,7 @@ TESTS = gettext-1 gettext-2 gettext-3 gettext-4 gettext-5 gettext-6 gettext-7 \ msgfilter-sr-latin-1 msgfilter-quote-1 \ msgfmt-1 msgfmt-2 msgfmt-3 msgfmt-4 msgfmt-5 msgfmt-6 msgfmt-7 \ msgfmt-8 msgfmt-9 msgfmt-10 msgfmt-11 msgfmt-12 msgfmt-13 msgfmt-14 \ - msgfmt-15 msgfmt-16 msgfmt-17 msgfmt-18 \ + msgfmt-15 msgfmt-16 msgfmt-17 msgfmt-18 msgfmt-19 \ msgfmt-properties-1 \ msgfmt-qt-1 msgfmt-qt-2 \ msgfmt-desktop-1 msgfmt-desktop-2 \ diff --git a/gettext-tools/tests/msgfmt-19 b/gettext-tools/tests/msgfmt-19 new file mode 100755 index 000000000..88574c817 --- /dev/null +++ b/gettext-tools/tests/msgfmt-19 @@ -0,0 +1,66 @@ +#! /bin/sh +. "${srcdir=.}/init.sh"; path_prepend_ . ../src + +# Test accelerators. + +cat <<\EOF > mf-19-1.po +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: GNU bison\n" +"POT-Creation-Date: 2017-04-05 19:47+0200\n" +"PO-Revision-Date: 2017-06-07 09:07+0000\n" +"Last-Translator: ABC DEF \n" +"Language-Team: test \n" +"Language: test\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "pen &File" +msgstr "pen File" + +msgid "how _Help" +msgstr "how Help" +EOF + + +cat <<\EOF > mf-19-2.po +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: GNU bison\n" +"POT-Creation-Date: 2016-03-04 18:46+0100\n" +"PO-Revision-Date: 2017-06-07 09:07+0000\n" +"Last-Translator: ABC DEF \n" +"Language-Team: test \n" +"Language: test\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "pen &File" +msgstr "pen File" + +msgid "how _Help" +msgstr "how Help" +EOF + + +: ${MSGFMT=msgfmt} +${MSGFMT} -o mf-19-1.mo mf-19-1.po 2>/dev/null +test $? = 0 || { Exit 1; } + +: ${MSGFMT=msgfmt} +${MSGFMT} -o mf-19-2.mo mf-19-2.po 2>/dev/null +test $? = 0 || { Exit 1; } + +: ${DIFF=diff} +${DIFF} mf-19-1.mo mf-19-2.mo +test $? = 0 || { Exit 1; } commit dea676293993e16ae50119ce1edfcc18e586c3f7 Author: Bruno Haible Date: Thu Dec 15 22:51:00 2016 +0100 Polish the last commit. diff --git a/gettext-tools/src/msgl-header.c b/gettext-tools/src/msgl-header.c index 25ae33af3..219b412ab 100644 --- a/gettext-tools/src/msgl-header.c +++ b/gettext-tools/src/msgl-header.c @@ -36,20 +36,20 @@ static const struct const char *name; size_t len; } - known_fields[] = - { - { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 }, - { "Report-Msgid-Bugs-To:", sizeof ("Report-Msgid-Bugs-To:") - 1 }, - { "POT-Creation-Date:", sizeof ("POT-Creation-Date:") - 1 }, - { "PO-Revision-Date:", sizeof ("PO-Revision-Date:") - 1 }, - { "Last-Translator:", sizeof ("Last-Translator:") - 1 }, - { "Language-Team:", sizeof ("Language-Team:") - 1 }, - { "Language:", sizeof ("Language:") - 1 }, - { "MIME-Version:", sizeof ("MIME-Version:") - 1 }, - { "Content-Type:", sizeof ("Content-Type:") - 1 }, - { "Content-Transfer-Encoding:", - sizeof ("Content-Transfer-Encoding:") - 1 } - }; +known_fields[] = + { + { "Project-Id-Version:", sizeof ("Project-Id-Version:") - 1 }, + { "Report-Msgid-Bugs-To:", sizeof ("Report-Msgid-Bugs-To:") - 1 }, + { "POT-Creation-Date:", sizeof ("POT-Creation-Date:") - 1 }, + { "PO-Revision-Date:", sizeof ("PO-Revision-Date:") - 1 }, + { "Last-Translator:", sizeof ("Last-Translator:") - 1 }, + { "Language-Team:", sizeof ("Language-Team:") - 1 }, + { "Language:", sizeof ("Language:") - 1 }, + { "MIME-Version:", sizeof ("MIME-Version:") - 1 }, + { "Content-Type:", sizeof ("Content-Type:") - 1 }, + { "Content-Transfer-Encoding:", sizeof ("Content-Transfer-Encoding:") - 1 } + }; + void msgdomain_list_set_header_field (msgdomain_list_ty *mdlp, @@ -175,21 +175,8 @@ void message_list_delete_header_field (message_list_ty *mlp, const char *field) { + size_t field_len = strlen (field); size_t j; - int field_index; - size_t k; - - /* Search the field in known_fields[]. */ - field_index = -1; - for (k = 0; k < SIZEOF (known_fields); k++) - if (strcmp (known_fields[k].name, field) == 0) - { - field_index = k; - break; - } - - size_t field_len; - field_len = strlen (field); /* Search the header entry. */ for (j = 0; j < mlp->nitems; j++) @@ -199,11 +186,8 @@ message_list_delete_header_field (message_list_ty *mlp, /* Modify the header entry. */ const char *header = mp->msgstr; - char *new_header = - XCALLOC (strlen (header) + 1, - char); - /* Test whether the field already occurs in the header entry. */ + /* Test whether the field occurs in the header entry. */ const char *h; for (h = header; *h != '\0'; ) @@ -217,7 +201,9 @@ message_list_delete_header_field (message_list_ty *mlp, } if (h != NULL && *h != '\0') { - /* Replace the field. */ + /* Delete the field. */ + char *new_header = XCALLOC (strlen (header) + 1, char); + char *p = new_header; memcpy (p, header, h - header); p += h - header; @@ -225,15 +211,12 @@ message_list_delete_header_field (message_list_ty *mlp, if (h != NULL) { h++; - stpcpy (p, h); + strcpy (p, h); } + else + *p = '\0'; + + mp->msgstr = new_header; } - else - { - char *p = new_header; - p = stpcpy (p, header); - } - - mp->msgstr = new_header; } } diff --git a/gettext-tools/src/msgl-header.h b/gettext-tools/src/msgl-header.h index 34726e7b0..35524a37f 100644 --- a/gettext-tools/src/msgl-header.h +++ b/gettext-tools/src/msgl-header.h @@ -34,8 +34,11 @@ extern void msgdomain_list_set_header_field (msgdomain_list_ty *mdlp, const char *field, const char *value); +/* Remove the given field from the header. + The FIELD name ends in a colon. */ extern void - message_list_delete_header_field (message_list_ty *mlp, const char *field); + message_list_delete_header_field (message_list_ty *mlp, + const char *field); #ifdef __cplusplus diff --git a/gettext-tools/src/write-csharp.c b/gettext-tools/src/write-csharp.c index 30e8411cc..161cd4f45 100644 --- a/gettext-tools/src/write-csharp.c +++ b/gettext-tools/src/write-csharp.c @@ -646,8 +646,10 @@ msgdomain_write_csharp (message_list_ty *mlp, const char *canon_encoding, /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + /* Support for "reproducible builds": Delete information that may vary + between builds in the same conditions. */ message_list_delete_header_field (mlp, "POT-Creation-Date:"); - + /* Create a temporary directory where we can put the C# file. A simple temporary file would also be possible but would require us to define our own variant of mkstemp(): On one hand the functions mktemp(), diff --git a/gettext-tools/src/write-desktop.c b/gettext-tools/src/write-desktop.c index e568d47fb..657620dcb 100644 --- a/gettext-tools/src/write-desktop.c +++ b/gettext-tools/src/write-desktop.c @@ -204,8 +204,10 @@ msgdomain_write_desktop (message_list_ty *mlp, /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + /* Support for "reproducible builds": Delete information that may vary + between builds in the same conditions. */ message_list_delete_header_field (mlp, "POT-Creation-Date:"); - + /* Create a single-element operands and run the bulk operation on it. */ operand.language = (char *) locale_name; operand.mlp = mlp; diff --git a/gettext-tools/src/write-java.c b/gettext-tools/src/write-java.c index 039ed94d9..9ddfac868 100644 --- a/gettext-tools/src/write-java.c +++ b/gettext-tools/src/write-java.c @@ -1067,6 +1067,8 @@ msgdomain_write_java (message_list_ty *mlp, const char *canon_encoding, /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + /* Support for "reproducible builds": Delete information that may vary + between builds in the same conditions. */ message_list_delete_header_field (mlp, "POT-Creation-Date:"); if (output_source) diff --git a/gettext-tools/src/write-mo.c b/gettext-tools/src/write-mo.c index b99dece02..69196550c 100644 --- a/gettext-tools/src/write-mo.c +++ b/gettext-tools/src/write-mo.c @@ -45,12 +45,10 @@ #include "xsize.h" #include "xalloc.h" #include "xmalloca.h" +#include "msgl-header.h" #include "binary-io.h" #include "fwriteerror.h" #include "gettext.h" -#include "read-catalog.h" -#include "read-stringtable.h" -#include "msgl-header.h" #define _(str) gettext (str) @@ -789,6 +787,10 @@ msgdomain_write_mo (message_list_ty *mlp, /* If no entry for this domain don't even create the file. */ if (mlp->nitems != 0) { + /* Support for "reproducible builds": Delete information that may vary + between builds in the same conditions. */ + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + if (strcmp (domain_name, "-") == 0) { output_file = stdout; @@ -807,7 +809,6 @@ msgdomain_write_mo (message_list_ty *mlp, if (output_file != NULL) { - message_list_delete_header_field (mlp, "POT-Creation-Date:"); write_table (output_file, mlp); /* Make sure nothing went wrong. */ diff --git a/gettext-tools/src/write-qt.c b/gettext-tools/src/write-qt.c index 4a47d241f..b3cca5a8e 100644 --- a/gettext-tools/src/write-qt.c +++ b/gettext-tools/src/write-qt.c @@ -725,6 +725,10 @@ strings, not in the untranslated strings\n"))); } } + /* Support for "reproducible builds": Delete information that may vary + between builds in the same conditions. */ + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + if (strcmp (domain_name, "-") == 0) { output_file = stdout; @@ -743,7 +747,6 @@ strings, not in the untranslated strings\n"))); if (output_file != NULL) { - message_list_delete_header_field (mlp, "POT-Creation-Date:"); write_qm (output_file, mlp); /* Make sure nothing went wrong. */ diff --git a/gettext-tools/src/write-resources.c b/gettext-tools/src/write-resources.c index ec74eadcd..8cc33cc13 100644 --- a/gettext-tools/src/write-resources.c +++ b/gettext-tools/src/write-resources.c @@ -115,8 +115,6 @@ msgdomain_write_csharp_resources (message_list_ty *mlp, const char *domain_name, const char *file_name) { - message_list_delete_header_field (mlp, "POT-Creation-Date:"); - /* If no entry for this domain don't even create the file. */ if (mlp->nitems != 0) { @@ -161,6 +159,10 @@ but the C# .resources format doesn't support plural handling\n"))); /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + /* Support for "reproducible builds": Delete information that may vary + between builds in the same conditions. */ + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + /* Execute the WriteResource program. */ { const char *args[2]; diff --git a/gettext-tools/src/write-tcl.c b/gettext-tools/src/write-tcl.c index 04b62d9c8..b61608e76 100644 --- a/gettext-tools/src/write-tcl.c +++ b/gettext-tools/src/write-tcl.c @@ -185,6 +185,10 @@ but the Tcl message catalog format doesn't support plural handling\n"))); /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + /* Support for "reproducible builds": Delete information that may vary + between builds in the same conditions. */ + message_list_delete_header_field (mlp, "POT-Creation-Date:"); + /* Now create the file. */ { size_t len; @@ -217,7 +221,6 @@ but the Tcl message catalog format doesn't support plural handling\n"))); return 1; } - message_list_delete_header_field (mlp, "POT-Creation-Date:"); write_msg (output_file, mlp, frobbed_locale_name); /* Make sure nothing went wrong. */ diff --git a/gettext-tools/src/write-xml.c b/gettext-tools/src/write-xml.c index f6cd6c003..5c719f92e 100644 --- a/gettext-tools/src/write-xml.c +++ b/gettext-tools/src/write-xml.c @@ -95,8 +95,10 @@ msgdomain_write_xml (message_list_ty *mlp, /* Convert the messages to Unicode. */ iconv_message_list (mlp, canon_encoding, po_charset_utf8, NULL); + /* Support for "reproducible builds": Delete information that may vary + between builds in the same conditions. */ message_list_delete_header_field (mlp, "POT-Creation-Date:"); - + /* Create a single-element operands and run the bulk operation on it. */ operand.language = (char *) locale_name; operand.mlp = mlp; diff --git a/gettext-tools/tests/msgfmt-19 b/gettext-tools/tests/msgfmt-19 index 88574c817..76d4a739d 100755 --- a/gettext-tools/tests/msgfmt-19 +++ b/gettext-tools/tests/msgfmt-19 @@ -1,7 +1,8 @@ #! /bin/sh . "${srcdir=.}/init.sh"; path_prepend_ . ../src -# Test accelerators. +# Test that PO files that differ only in the POT-Creation-Date yield the +# exact same .mo file. cat <<\EOF > mf-19-1.po # SOME DESCRIPTIVE TITLE. @@ -20,14 +21,13 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -msgid "pen &File" -msgstr "pen File" +msgid "Open &File" +msgstr "Open File" -msgid "how _Help" -msgstr "how Help" +msgid "Show _Help" +msgstr "Show Help" EOF - cat <<\EOF > mf-19-2.po # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Free Software Foundation, Inc. @@ -45,14 +45,13 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -msgid "pen &File" -msgstr "pen File" +msgid "Open &File" +msgstr "Open File" -msgid "how _Help" -msgstr "how Help" +msgid "Show _Help" +msgstr "Show Help" EOF - : ${MSGFMT=msgfmt} ${MSGFMT} -o mf-19-1.mo mf-19-1.po 2>/dev/null test $? = 0 || { Exit 1; }