r15787 - gnucash/trunk/src - Play nicer with recent releases of glib that have tightened what's

David Hampton hampton at cvs.gnucash.org
Tue Apr 3 23:40:16 EDT 2007


Author: hampton
Date: 2007-04-03 23:40:14 -0400 (Tue, 03 Apr 2007)
New Revision: 15787
Trac: http://svn.gnucash.org/trac/changeset/15787

Modified:
   gnucash/trunk/src/app-utils/file-utils.c
   gnucash/trunk/src/app-utils/file-utils.h
   gnucash/trunk/src/app-utils/gnc-exp-parser.c
   gnucash/trunk/src/business/business-gnome/dialog-invoice.c
   gnucash/trunk/src/core-utils/gnc-gkeyfile-utils.c
   gnucash/trunk/src/core-utils/gnc-gkeyfile-utils.h
   gnucash/trunk/src/gnome-utils/gnc-main-window.c
   gnucash/trunk/src/gnome-utils/gnc-plugin-file-history.c
   gnucash/trunk/src/gnome-utils/gnc-tree-view-account.c
   gnucash/trunk/src/gnome/dialog-print-check.c
   gnucash/trunk/src/gnome/gnc-plugin-page-register.c
   gnucash/trunk/src/report/report-gnome/gnc-plugin-page-report.c
Log:
Play nicer with recent releases of glib that have tightened what's
considered a valid key in a key/value file. This change will cause
gnucash to rewrite any opened state file into a new version where all
key names fit the new glib requirements.

This code was originally committed to trunk as #15458 on 1/28/07, and
then backed out with #15461 on 1/29/07.  Backward compatibility
support for this code was committed to the 2.0 branch in #15460 and
was released as part of 2.0.5.  Now that 2.0.5 has now been out for
six weeks, this commit puts the original changes back into trunk.


Modified: gnucash/trunk/src/app-utils/file-utils.c
===================================================================
--- gnucash/trunk/src/app-utils/file-utils.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/app-utils/file-utils.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -23,6 +23,9 @@
 
 #include <glib.h>
 #include <glib/gstdio.h>
+#ifndef HAVE_GLIB_2_8
+#include <gfileutils-2.8.h>
+#endif
 #include <libguile.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -167,6 +170,63 @@
 }
 
 
+/* Update one state file file to fit the new constraints introduced by
+ * glib 2.12.5.  Supposedly its always been illegal to use spaces in
+ * key names, but it was never a problem with earlier releases of
+ * glib. Glib 2.12.5 added hard enforcement of this rule, completely
+ * ignoring any key/value pair where the key name contained an
+ * "illegal" character.  Glib 2.12.7 relented and changed the hard
+ * failure to a warning, but the point has been made.  Spaces in key
+ * names must go.
+ */
+static gboolean
+gnc_update_state_file_keys(const gchar *filename)
+{
+  const gchar *eol;
+  gchar *contents, **lines, *line, **kv, **parts, *part, *newkey;
+  GError *error = NULL;
+  int i, j;
+
+  if (!g_file_get_contents(filename, &contents, NULL, &error)) {
+    DEBUG("Error reading state file: %s", error->message);
+    g_error_free(error);
+    return FALSE;
+  }
+
+  lines = g_strsplit(contents, "\n", -1);
+  g_free(contents);
+
+  /* Strip spaces from non-comment lines, and rewrite the new text
+   * over top of the old text.  The new line is guaranteed to be at
+   * most the same number of characters as the old. */
+  for (i = 0, line = lines[i++]; line; line = lines[i++]) {
+    if ((*line == '\0') || (*line == '#') || (*line == '[')) {
+      continue;
+    } else {
+      kv = g_strsplit(line, "=", 2);
+      parts = g_strsplit(kv[0], " ", -1);
+      for (j = 0, part = parts[j++]; part; part = parts[j++])
+	part[0] = g_ascii_toupper(part[0]);
+      newkey = g_strjoinv("", parts);
+      g_sprintf(line, "%s=%s", newkey, kv[1]);
+      g_free(newkey);
+      g_strfreev(parts);
+      g_strfreev(kv);
+    }
+  }
+
+  contents = g_strjoinv("\n", lines);
+  if (!g_file_set_contents(filename, contents, -1, &error)) {
+    DEBUG("Error writing state file: %s", error->message);
+    g_error_free(error);
+    g_free(contents);
+    return FALSE;
+  }
+
+  g_free(contents);
+  return TRUE;
+}
+
 /*  Find the state file that corresponds to this URL and guid.  The
  *  URL is used to compute the base name of the file (which will be in
  *  ~/.gnucash/books) and the guid is used to differentiate when the
@@ -179,6 +239,7 @@
   gchar *basename, *original = NULL, *filename, *tmp, *file_guid;
   GKeyFile *key_file = NULL;
   GError *error = NULL;
+  gboolean do_increment;
   gint i;
 
   ENTER("url %s, guid %s", url, guid);
@@ -199,9 +260,24 @@
     else
       filename = g_strdup_printf("%s_%d", original, i);
     DEBUG("Trying %s", filename);
-    key_file = gnc_key_file_load_from_file(filename, FALSE, FALSE);
+    key_file = gnc_key_file_load_from_file(filename, FALSE, FALSE, &error);
     DEBUG("Result %p", key_file);
 
+    if (error &&
+	(error->domain == G_KEY_FILE_ERROR) && 
+	(error->code == G_KEY_FILE_ERROR_PARSE)) {
+      /* Handle the case where glib was updated first, and is refusing
+       * to read old state files. */
+      if (gnc_update_state_file_keys(filename)) {
+	DEBUG("Trying %s again", filename);
+	key_file = gnc_key_file_load_from_file(filename, FALSE, FALSE, NULL);
+	DEBUG("Result %p", key_file);
+      }
+    }
+    if (error) {
+      g_error_free(error);
+      error = NULL;
+    }
     if (!key_file) {
       DEBUG("No key file by that name");
       break;
@@ -209,7 +285,7 @@
 
     file_guid = g_key_file_get_string(key_file,
 				      STATE_FILE_TOP, STATE_FILE_BOOK_GUID,
-				      &error);
+				      NULL);
     DEBUG("File GUID is %s", file_guid);
     if (safe_strcmp(guid, file_guid) == 0) {
       DEBUG("Matched !!!");
@@ -217,11 +293,26 @@
       break;
     }
 
+    /* Handle the case where gnucash was updated first, and is trying
+     * to find new key names in an old state files. */
+    file_guid = g_key_file_get_string(key_file,
+				      STATE_FILE_TOP, STATE_FILE_BOOK_GUID_OLD,
+				      NULL);
+    DEBUG("%s is %s", STATE_FILE_BOOK_GUID,
+	  file_guid ? file_guid : "<not found>");
+    if (safe_strcmp(guid, file_guid) == 0) {
+      DEBUG("Matched !!!");
+      do_increment = !gnc_update_state_file_keys(filename);
+    } else {
+      do_increment = TRUE;
+    }
+
     DEBUG("Clean up this pass");
     g_free(file_guid);
     g_key_file_free(key_file);
     g_free(filename);
-    i++;
+    if (do_increment)
+      i++;
   }
 
   DEBUG("Clean up");

Modified: gnucash/trunk/src/app-utils/file-utils.h
===================================================================
--- gnucash/trunk/src/app-utils/file-utils.h	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/app-utils/file-utils.h	2007-04-04 03:40:14 UTC (rev 15787)
@@ -60,8 +60,9 @@
 
 
 /* Definitions shared by file-utils.c and gnc-main-window.c */
-#define STATE_FILE_TOP		"Top"
-#define STATE_FILE_BOOK_GUID	"Book Guid"
+#define STATE_FILE_TOP           "Top"
+#define STATE_FILE_BOOK_GUID     "BookGuid"
+#define STATE_FILE_BOOK_GUID_OLD "Book Guid"
 
 /** Find the state file that corresponds to this URL and guid.  The
  *  URL is used to compute the base name of the file (which will be in

Modified: gnucash/trunk/src/app-utils/gnc-exp-parser.c
===================================================================
--- gnucash/trunk/src/app-utils/gnc-exp-parser.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/app-utils/gnc-exp-parser.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -86,7 +86,7 @@
 
   if ( addPredefined ) {
     filename = gnc_exp_parser_filname();
-    key_file = gnc_key_file_load_from_file(filename, TRUE, FALSE);
+    key_file = gnc_key_file_load_from_file(filename, TRUE, FALSE, NULL);
     if (key_file) {
       keys = g_key_file_get_keys(key_file, GROUP_NAME, NULL, NULL);
       for (key = keys; key && *key; key++) {

Modified: gnucash/trunk/src/business/business-gnome/dialog-invoice.c
===================================================================
--- gnucash/trunk/src/business/business-gnome/dialog-invoice.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/business/business-gnome/dialog-invoice.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -1676,10 +1676,10 @@
   return iw;
 }
 
-#define KEY_INVOICE_TYPE	"Invoice Type"
-#define KEY_INVOICE_GUID	"Invoice GUID"
-#define KEY_OWNER_TYPE		"Owner Type"
-#define KEY_OWNER_GUID		"Owner GUID"
+#define KEY_INVOICE_TYPE        "InvoiceType"
+#define KEY_INVOICE_GUID        "InvoiceGUID"
+#define KEY_OWNER_TYPE          "OwnerType"
+#define KEY_OWNER_GUID          "OwnerGUID"
 
 GncPluginPage *
 gnc_invoice_recreate_page (GKeyFile *key_file,

Modified: gnucash/trunk/src/core-utils/gnc-gkeyfile-utils.c
===================================================================
--- gnucash/trunk/src/core-utils/gnc-gkeyfile-utils.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/core-utils/gnc-gkeyfile-utils.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -265,7 +265,8 @@
 GKeyFile *
 gnc_key_file_load_from_file (const gchar *filename,
 			     gboolean ignore_error,
-			     gboolean return_empty_struct)
+			     gboolean return_empty_struct,
+			     GError **caller_error)
 {
   GKeyFile *key_file;
   GError *error = NULL;
@@ -290,7 +291,7 @@
 
   if (!ignore_error)
     g_warning("Unable to read file %s: %s\n", filename, error->message);
-  g_error_free(error);
+  g_propagate_error(caller_error, error);
   return key_file;
 }
 

Modified: gnucash/trunk/src/core-utils/gnc-gkeyfile-utils.h
===================================================================
--- gnucash/trunk/src/core-utils/gnc-gkeyfile-utils.h	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/core-utils/gnc-gkeyfile-utils.h	2007-04-04 03:40:14 UTC (rev 15787)
@@ -71,7 +71,8 @@
  */
 GKeyFile *gnc_key_file_load_from_file (const gchar *file,
 				       gboolean ignore_error,
-				       gboolean return_empty_struct);
+				       gboolean return_empty_struct,
+				       GError **caller_error);
 
 
 /** Write a key/value file from memory to disk.  If there is no data

Modified: gnucash/trunk/src/gnome/dialog-print-check.c
===================================================================
--- gnucash/trunk/src/gnome/dialog-print-check.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/gnome/dialog-print-check.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -1004,7 +1004,7 @@
     check_format_t *format;
 
     pathname = g_build_filename(dirname, file, (char *)NULL);
-    key_file = gnc_key_file_load_from_file(pathname, FALSE, FALSE);
+    key_file = gnc_key_file_load_from_file(pathname, FALSE, FALSE, NULL);
     g_free(pathname);
     if (!key_file) {
         g_warning("Check file %s, cannot load file", file);

Modified: gnucash/trunk/src/gnome/gnc-plugin-page-register.c
===================================================================
--- gnucash/trunk/src/gnome/gnc-plugin-page-register.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/gnome/gnc-plugin-page-register.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -831,10 +831,10 @@
   NULL
 };
 
-#define KEY_REGISTER_TYPE	"Register Type"
-#define KEY_ACCOUNT_NAME	"Account Name"
-#define KEY_REGISTER_STYLE	"Register Style"
-#define KEY_DOUBLE_LINE		"Double Line Mode"
+#define KEY_REGISTER_TYPE       "RegisterType"
+#define KEY_ACCOUNT_NAME        "AccountName"
+#define KEY_REGISTER_STYLE      "RegisterStyle"
+#define KEY_DOUBLE_LINE         "DoubleLineMode"
 
 #define LABEL_ACCOUNT		"Account"
 #define LABEL_SUBACCOUNT	"SubAccount"

Modified: gnucash/trunk/src/gnome-utils/gnc-main-window.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-main-window.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/gnome-utils/gnc-main-window.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -402,20 +402,20 @@
 /************************************************************
  *                                                          *
  ************************************************************/
-#define WINDOW_COUNT		"Window Count"
-#define WINDOW_STRING		"Window %d"
-#define WINDOW_GEOMETRY		"Window Geometry"
-#define WINDOW_POSITION		"Window Position"
-#define WINDOW_MAXIMIZED	"Window Maximized"
-#define TOOLBAR_VISIBLE		"Toolbar Visible"
-#define STATUSBAR_VISIBLE	"Statusbar Visible"
-#define SUMMARYBAR_VISIBLE	"Summarybar Visible"
-#define WINDOW_FIRSTPAGE	"First Page"
-#define WINDOW_PAGECOUNT	"Page Count"
-#define WINDOW_PAGEORDER	"Page Order"
-#define PAGE_TYPE		"Page Type"
-#define PAGE_NAME		"Page Name"
-#define PAGE_STRING		"Page %d"
+#define WINDOW_COUNT            "WindowCount"
+#define WINDOW_STRING           "Window %d"
+#define WINDOW_GEOMETRY         "WindowGeometry"
+#define WINDOW_POSITION         "WindowPosition"
+#define WINDOW_MAXIMIZED        "WindowMaximized"
+#define TOOLBAR_VISIBLE         "ToolbarVisible"
+#define STATUSBAR_VISIBLE       "StatusbarVisible"
+#define SUMMARYBAR_VISIBLE      "SummarybarVisible"
+#define WINDOW_FIRSTPAGE        "FirstPage"
+#define WINDOW_PAGECOUNT        "PageCount"
+#define WINDOW_PAGEORDER        "PageOrder"
+#define PAGE_TYPE               "PageType"
+#define PAGE_NAME               "PageName"
+#define PAGE_STRING             "Page %d"
 
 typedef struct {
   GKeyFile *key_file;

Modified: gnucash/trunk/src/gnome-utils/gnc-plugin-file-history.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-plugin-file-history.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/gnome-utils/gnc-plugin-file-history.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -435,7 +435,7 @@
   /* Copy the old values from the gnucash 1.x/gnome1 settings file to
    * the gnucash 2.x/gconf settings area.  */
   mdi_file = g_build_filename(home, ".gnome", "GnuCash", (gchar *)NULL);
-  keyfile = gnc_key_file_load_from_file (mdi_file, FALSE, FALSE);
+  keyfile = gnc_key_file_load_from_file (mdi_file, FALSE, FALSE, NULL);
   if (keyfile) {
     keys = g_key_file_get_keys(keyfile, GNOME1_HISTORY, NULL, NULL);
     if (keys) {

Modified: gnucash/trunk/src/gnome-utils/gnc-tree-view-account.c
===================================================================
--- gnucash/trunk/src/gnome-utils/gnc-tree-view-account.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/gnome-utils/gnc-tree-view-account.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -1853,12 +1853,12 @@
   LEAVE(" ");
 }
 
-#define ACCT_COUNT    "Number of Open Accounts"
-#define ACCT_OPEN     "Open Account %d"
-#define ACCT_SELECTED "Selected Account"
-#define SHOW_HIDDEN   "Show Hidden"
-#define SHOW_ZERO     "Show Zero Total"
-#define ACCT_TYPES    "Account Types"
+#define ACCT_COUNT    "NumberOfOpenAccounts"
+#define ACCT_OPEN     "OpenAccount%d"
+#define ACCT_SELECTED "SelectedAccount"
+#define SHOW_HIDDEN   "ShowHidden"
+#define SHOW_ZERO     "ShowZeroTotal"
+#define ACCT_TYPES    "AccountTypes"
 
 typedef struct foo {
   GKeyFile *key_file;

Modified: gnucash/trunk/src/report/report-gnome/gnc-plugin-page-report.c
===================================================================
--- gnucash/trunk/src/report/report-gnome/gnc-plugin-page-report.c	2007-04-04 02:22:28 UTC (rev 15786)
+++ gnucash/trunk/src/report/report-gnome/gnc-plugin-page-report.c	2007-04-04 03:40:14 UTC (rev 15787)
@@ -649,8 +649,8 @@
 
 /** The key name used it the state file for storing the report
  *  options. */
-#define SCHEME_OPTIONS   "Scheme Options"
-#define SCHEME_OPTIONS_N "Scheme Options %d"
+#define SCHEME_OPTIONS   "SchemeOptions"
+#define SCHEME_OPTIONS_N "SchemeOptions%d"
 
 
 /** Save enough information about this report page that it can be



More information about the gnucash-changes mailing list