]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Avoid modifying PO files if the POT file is the same except for a different
authorBruno Haible <bruno@clisp.org>
Fri, 4 Oct 2002 11:36:54 +0000 (11:36 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:08:46 +0000 (12:08 +0200)
POT-Creation-Date.

po/ChangeLog
po/Makefile.in.in
src/ChangeLog
src/msgl-equal.c
src/msgl-equal.h
src/msgmerge.c

index bb663f50f3d66cf57b587bb7f8061d620950f188..5b3a75e6b9d7f21c520b216f39958310b231f870 100644 (file)
@@ -1,3 +1,13 @@
+2002-10-03  Bruno Haible  <bruno@clisp.org>
+
+       Avoid modifying PO files if the POT file is the same except for a
+       different POT-Creation-Date.
+       * Makefile.in.in (DISTFILES): Add stamp-po.
+       (all-yes): Depend on stamp-po, not directly on CATALOGS.
+       (stamp-po): New rule.
+       (mostlyclean): Also remove stamp-poT.
+       (maintainer-clean): Also remove stamp-po.
+
 2002-09-19  Bruno Haible  <bruno@clisp.org>
 
        * be.po: Update from Ales Nyakhaychyk <i18n@infonet.by>.
index b8eab2b846229b05b408dba3f7a1c82bd2adc9c5..165e8966f2b8404d76e38ef2a2c6968e31514f6a 100644 (file)
@@ -44,7 +44,7 @@ UPDATEPOFILES = @UPDATEPOFILES@
 DUMMYPOFILES = @DUMMYPOFILES@
 DISTFILES.common = Makefile.in.in Makevars remove-potcdate.sin \
 $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
-DISTFILES = $(DISTFILES.common) POTFILES.in $(DOMAIN).pot \
+DISTFILES = $(DISTFILES.common) POTFILES.in $(DOMAIN).pot stamp-po \
 $(POFILES) $(GMOFILES) \
 $(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
 
@@ -74,13 +74,29 @@ CATALOGS = @CATALOGS@
 
 all: all-@USE_NLS@
 
-all-yes: $(CATALOGS)
+all-yes: stamp-po
 all-no:
 
+# stamp-po is a timestamp denoting the last time at which the CATALOGS have
+# been loosely updated. Its purpose is that when a developer or translator
+# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS,
+# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent
+# invocations of "make" will do nothing. This timestamp would not be necessary
+# if updating the $(CATALOGS) would always touch them; however, the rule for
+# $(POFILES) has been designed to not touch files that don't need to be
+# changed.
+stamp-po: $(srcdir)/$(DOMAIN).pot
+       $(MAKE) $(CATALOGS)
+       @echo "touch stamp-po"
+       @echo timestamp > stamp-poT
+       @mv stamp-poT stamp-po
+
 # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
 # otherwise packages like GCC can not be built if only parts of the source
 # have been downloaded.
 
+# This target rebuilds $(DOMAIN).pot; it is an expensive operation.
+# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed.
 $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
        $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
          --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \
@@ -101,9 +117,14 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
          fi; \
        }
 
+# This rule has no dependencies: we don't need to update $(DOMAIN).pot at
+# every "make" invocation, only create it when it is missing.
+# Only "make $(DOMAIN).pot-update" or "make dist" will force an update.
 $(srcdir)/$(DOMAIN).pot:
        $(MAKE) $(DOMAIN).pot-update
 
+# This target rebuilds a PO file if $(DOMAIN).pot has changed.
+# Note that a PO file is not touched if it doesn't need to be changed.
 $(POFILES): $(srcdir)/$(DOMAIN).pot
        @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
        test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
@@ -239,6 +260,7 @@ dvi info tags TAGS ID:
 
 mostlyclean:
        rm -f remove-potcdate.sed
+       rm -f stamp-poT
        rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
        rm -fr *.o
 
@@ -250,7 +272,7 @@ distclean: clean
 maintainer-clean: distclean
        @echo "This command is intended for maintainers to use;"
        @echo "it deletes files that may require special tools to rebuild."
-       rm -f $(GMOFILES)
+       rm -f stamp-po $(GMOFILES)
 
 distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
 dist distdir:
index d5a0d8ead5764837f5cad8742dcb42310f4b84af..9ec1210581f6a1cdcaf6d10d62a1499902303bf2 100644 (file)
@@ -1,3 +1,14 @@
+2002-10-03  Bruno Haible  <bruno@clisp.org>
+
+       * msgl-equal.h (message_equal, message_list_equal,
+       msgdomain_list_equal): Add 'ignore_potcdate' argument.
+       * msgl-equal-c (msgstr_equal, msgstr_equal_ignoring_potcdate): New
+       functions.
+       (message_equal, message_list_equal, msgdomain_equal,
+       msgdomain_list_equal): Add 'ignore_potcdate' argument.
+       * msgmerge.c (main): Call msgdomain_list_equal with ignore_potcdate =
+       true.
+
 2002-09-09  Bruno Haible  <bruno@clisp.org>
 
        * x-smalltalk.h: New file.
index 0c9763092405df53597aa0428e04a0e6c75bc822..1252af9e57dc67d72f193dcd5a6ead17d062420e 100644 (file)
@@ -1,5 +1,5 @@
 /* Message list test for equality.
-   Copyright (C) 2001 Free Software Foundation, Inc.
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
 
    This program is free software; you can redistribute it and/or modify
 /* Specification.  */
 #include "msgl-equal.h"
 
+#include <stddef.h>
 #include <string.h>
 
 
 /* Prototypes for local functions.  Needed to ensure compiler checking of
    function argument counts despite of K&R C function definition syntax.  */
+static inline bool msgstr_equal PARAMS ((const char *msgstr1,
+                                        size_t msgstr1_len,
+                                        const char *msgstr2,
+                                        size_t msgstr2_len));
+static inline bool msgstr_equal_ignoring_potcdate PARAMS ((const char *msgstr1,
+                                                          size_t msgstr1_len,
+                                                          const char *msgstr2,
+                                                          size_t msgstr2_len));
 static inline bool pos_equal PARAMS ((const lex_pos_ty *pos1,
                                      const lex_pos_ty *pos2));
 static inline bool msgdomain_equal PARAMS ((const msgdomain_ty *mdp1,
-                                           const msgdomain_ty *mdp2));
+                                           const msgdomain_ty *mdp2,
+                                           bool ignore_potcdate));
 
 
+static inline bool
+msgstr_equal (msgstr1, msgstr1_len, msgstr2, msgstr2_len)
+     const char *msgstr1;
+     size_t msgstr1_len;
+     const char *msgstr2;
+     size_t msgstr2_len;
+{
+  return (msgstr1_len == msgstr2_len
+         && memcmp (msgstr1, msgstr2, msgstr1_len) == 0);
+}
+
+static bool
+msgstr_equal_ignoring_potcdate (msgstr1, msgstr1_len, msgstr2, msgstr2_len)
+     const char *msgstr1;
+     size_t msgstr1_len;
+     const char *msgstr2;
+     size_t msgstr2_len;
+{
+  const char *msgstr1_end = msgstr1 + msgstr1_len;
+  const char *msgstr2_end = msgstr2 + msgstr2_len;
+  const char *ptr1;
+  const char *ptr2;
+  const char *const field = "POT-Creation-Date:";
+  const ptrdiff_t fieldlen = sizeof ("POT-Creation-Date:") - 1;
+
+  /* Search for the occurrence of field in msgstr1.  */
+  for (ptr1 = msgstr1;;)
+    {
+      if (msgstr1_end - ptr1 < fieldlen)
+       {
+         ptr1 = NULL;
+         break;
+       }
+      if (memcmp (ptr1, field, fieldlen) == 0)
+       break;
+      ptr1 = memchr (ptr1, '\n', msgstr1_end - ptr1);
+      if (ptr1 == NULL)
+       break;
+      ptr1++;
+    }
+
+  /* Search for the occurrence of field in msgstr2.  */
+  for (ptr2 = msgstr2;;)
+    {
+      if (msgstr2_end - ptr2 < fieldlen)
+       {
+         ptr2 = NULL;
+         break;
+       }
+      if (memcmp (ptr2, field, fieldlen) == 0)
+       break;
+      ptr2 = memchr (ptr2, '\n', msgstr2_end - ptr2);
+      if (ptr2 == NULL)
+       break;
+      ptr2++;
+    }
+
+  if (ptr1 == NULL)
+    {
+      if (ptr2 == NULL)
+       return msgstr_equal (msgstr1, msgstr1_len, msgstr2, msgstr2_len);
+    }
+  else
+    {
+      if (ptr2 != NULL)
+       {
+         /* Compare, ignoring the lines starting at ptr1 and ptr2.  */
+         if (msgstr_equal (msgstr1, ptr1 - msgstr1, msgstr2, ptr2 - msgstr2))
+           {
+             ptr1 = memchr (ptr1, '\n', msgstr1_end - ptr1);
+             if (ptr1 == NULL)
+               ptr1 = msgstr1_end;
+
+             ptr2 = memchr (ptr2, '\n', msgstr2_end - ptr2);
+             if (ptr2 == NULL)
+               ptr2 = msgstr2_end;
+
+             return msgstr_equal (ptr1, msgstr1_end - ptr1,
+                                  ptr2, msgstr2_end - ptr2);
+           }
+       }
+    }
+  return false;
+}
+
 static inline bool
 pos_equal (pos1, pos2)
      const lex_pos_ty *pos1;
@@ -63,9 +158,10 @@ string_list_equal (slp1, slp2)
 }
 
 bool
-message_equal (mp1, mp2)
+message_equal (mp1, mp2, ignore_potcdate)
      const message_ty *mp1;
      const message_ty *mp2;
+     bool ignore_potcdate;
 {
   size_t i, i1, i2;
 
@@ -78,9 +174,11 @@ message_equal (mp1, mp2)
        : mp2->msgid_plural == NULL))
     return false;
 
-  if (mp1->msgstr_len != mp2->msgstr_len)
-    return false;
-  if (memcmp (mp1->msgstr, mp2->msgstr, mp1->msgstr_len) != 0)
+  if (mp1->msgid[0] == '\0' && ignore_potcdate
+      ? !msgstr_equal_ignoring_potcdate (mp1->msgstr, mp1->msgstr_len,
+                                        mp2->msgstr, mp2->msgstr_len)
+      : !msgstr_equal (mp1->msgstr, mp1->msgstr_len,
+                      mp2->msgstr, mp2->msgstr_len))
     return false;
 
   if (!pos_equal (&mp1->pos, &mp2->pos))
@@ -114,9 +212,10 @@ message_equal (mp1, mp2)
 }
 
 bool
-message_list_equal (mlp1, mlp2)
+message_list_equal (mlp1, mlp2, ignore_potcdate)
      const message_list_ty *mlp1;
      const message_list_ty *mlp2;
+     bool ignore_potcdate;
 {
   size_t i, i1, i2;
 
@@ -125,24 +224,27 @@ message_list_equal (mlp1, mlp2)
   if (i1 != i2)
     return false;
   for (i = 0; i < i1; i++)
-    if (!message_equal (mlp1->item[i], mlp2->item[i]))
+    if (!message_equal (mlp1->item[i], mlp2->item[i], ignore_potcdate))
       return false;
   return true;
 }
 
 static inline bool
-msgdomain_equal (mdp1, mdp2)
+msgdomain_equal (mdp1, mdp2, ignore_potcdate)
      const msgdomain_ty *mdp1;
      const msgdomain_ty *mdp2;
+     bool ignore_potcdate;
 {
   return (strcmp (mdp1->domain, mdp2->domain) == 0
-         && message_list_equal (mdp1->messages, mdp2->messages));
+         && message_list_equal (mdp1->messages, mdp2->messages,
+                                ignore_potcdate));
 }
 
 bool
-msgdomain_list_equal (mdlp1, mdlp2)
+msgdomain_list_equal (mdlp1, mdlp2, ignore_potcdate)
      const msgdomain_list_ty *mdlp1;
      const msgdomain_list_ty *mdlp2;
+     bool ignore_potcdate;
 {
   size_t i, i1, i2;
 
@@ -151,7 +253,7 @@ msgdomain_list_equal (mdlp1, mdlp2)
   if (i1 != i2)
     return false;
   for (i = 0; i < i1; i++)
-    if (!msgdomain_equal (mdlp1->item[i], mdlp2->item[i]))
+    if (!msgdomain_equal (mdlp1->item[i], mdlp2->item[i], ignore_potcdate))
       return false;
   return true;
 }
index c707289c0858c93f0c7bd82638170c5fcdc466a7..c131b2ded4dbf75afcc4520c171278d79ccb384f 100644 (file)
@@ -1,5 +1,5 @@
 /* Message list test for equality.
-   Copyright (C) 2001 Free Software Foundation, Inc.
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
 
    This program is free software; you can redistribute it and/or modify
@@ -31,12 +31,15 @@ extern bool
    would be the same.  */
 
 extern bool
-       message_equal PARAMS ((const message_ty *mp1, const message_ty *mp2));
+       message_equal PARAMS ((const message_ty *mp1, const message_ty *mp2,
+                             bool ignore_potcdate));
 extern bool
        message_list_equal PARAMS ((const message_list_ty *mlp1,
-                                  const message_list_ty *mlp2));
+                                  const message_list_ty *mlp2,
+                                  bool ignore_potcdate));
 extern bool
        msgdomain_list_equal PARAMS ((const msgdomain_list_ty *mdlp1,
-                                    const msgdomain_list_ty *mdlp2));
+                                    const msgdomain_list_ty *mdlp2,
+                                    bool ignore_potcdate));
 
 #endif /* _MSGL_EQUAL_H */
index bf45a2b2cc7194274825afcf3bb07fffacdf1aaa..dc71eb33bf0b5ac7a295990888a5913b967086e1 100644 (file)
@@ -336,8 +336,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 
   if (update_mode)
     {
-      /* Do nothing if the original file and the result are equal.  */
-      if (!msgdomain_list_equal (def, result))
+      /* Do nothing if the original file and the result are equal.  Also do
+        nothing if the original file and the result differ only by the
+        POT-Creation-Date in the header entry; this is needed for projects
+        which don't put the .pot file under CVS.  */
+      if (!msgdomain_list_equal (def, result, true))
        {
          /* Back up def.po.  */
          enum backup_type backup_type;