[PATCH] sort when saving (v2)

Jim Radford radford at blackbean.org
Mon May 4 13:19:36 EDT 2009


On Sat, May 02, 2009 at 12:18:25PM -0700, Jim Radford wrote:
> The attached patches sort the slots, lots, book accounts, bill
> terms, customers, employees, entries, invoices, jobs, orders, tax
> tables and vendors before saving them to the gnucash XML file.

> This is an attempt to make saves more idempotent thereby facilitating
> the use of a revision control system on the gnucash XML files.

A few testers pointed out that recursive slots and the backends
themselves were not being sorted.  The attached patch should fix that.

Also, you can this patch to the latest svn (as opposed a recent
release) after running the following on it.

   sed -e s@/lib/@/src/@g -e s@/file/@/xml/@g

-Jim
-------------- next part --------------
--- gnucash-2.2.8/lib/libqof/qof/qofutil.h.orig	2009-05-02 12:53:20.000000000 -0700
+++ gnucash-2.2.8/lib/libqof/qof/qofutil.h	2009-05-02 13:12:10.000000000 -0700
@@ -166,6 +166,12 @@
 
 /* **** Prototypes *********************************************/
 
+/** Calls the given function for each of the key/value pairs in the
+ *  GHashTable in an order determined by the GCompareFunc applied to
+ *  the keys. The function is passed the key and value of each pair,
+ *  and the given user_data parameter. */
+void g_hash_table_foreach_sorted(GHashTable *hash_table, GHFunc func, gpointer user_data, GCompareFunc compare_func);
+
 /** Search for an occurence of the substring needle in the string
  * haystack, ignoring case. Return TRUE if one is found or FALSE
  * otherwise. */
--- gnucash-2.2.8/lib/libqof/qof/qofutil.c.orig	2009-05-02 12:53:37.000000000 -0700
+++ gnucash-2.2.8/lib/libqof/qof/qofutil.c	2009-05-02 13:05:13.000000000 -0700
@@ -36,6 +36,15 @@
 
 static QofLogModule log_module = QOF_MOD_UTIL;
 
+void
+g_hash_table_foreach_sorted(GHashTable *hash_table, GHFunc func, gpointer user_data, GCompareFunc compare_func)
+{
+    GList *i, *keys = g_list_sort(g_hash_table_get_keys(hash_table), compare_func);
+    for (i = keys; i; i = i->next)
+        func(i->data, g_hash_table_lookup(hash_table, i->data), user_data);
+    g_list_free(keys);
+}
+
 gboolean
 qof_utf8_substr_nocase (const gchar *haystack, const gchar *needle)
 {
--- gnucash-2.2.8/lib/libqof/qof/qofobject.h.orig	2009-04-23 21:33:54.000000000 -0700
+++ gnucash-2.2.8/lib/libqof/qof/qofobject.h	2009-04-23 21:33:17.000000000 -0700
@@ -162,6 +162,10 @@
 void qof_object_foreach (QofIdTypeConst type_name, QofBook *book, 
                          QofInstanceForeachCB cb, gpointer user_data);
 
+/** Invoke callback 'cb' on each instance in guid orted order */
+void qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book,
+                                QofInstanceForeachCB cb, gpointer user_data);
+
 /** Register and lookup backend-specific data for this particular object */
 gboolean qof_object_register_backend (QofIdTypeConst type_name,
                                       const char *backend_name,
--- gnucash-2.2.8/lib/libqof/qof/qofobject.c.orig	2009-04-23 21:28:13.000000000 -0700
+++ gnucash-2.2.8/lib/libqof/qof/qofobject.c	2009-04-23 21:30:42.000000000 -0700
@@ -137,6 +137,29 @@
   }
 }
 
+static void
+do_append (QofInstance *qof_p, gpointer list_p)
+{
+  GList **list = list_p;
+  *list = g_list_append(*list, qof_p);
+}
+
+void
+qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
+{
+  GList *list = NULL, *n, *l;
+
+  qof_object_foreach(type_name, book, do_append, &list);
+
+  list = g_list_sort(list, qof_instance_guid_compare);
+
+  for (l = list; l; l = l->next)
+    cb(l->data, user_data);
+
+  g_list_free(list);
+}
+
+
 gboolean 
 qof_object_compliance (QofIdTypeConst type_name, gboolean warn)
 {
--- gnucash-2.2.8/lib/libqof/qof/qofobject.c.orig	2009-04-23 21:28:13.000000000 -0700
+++ gnucash-2.2.8/lib/libqof/qof/qofobject.c	2009-05-02 13:14:38.000000000 -0700
@@ -356,7 +379,7 @@
   cb_data.cb = cb;
   cb_data.user_data = user_data;
 
-  g_hash_table_foreach (ht, foreach_backend, &cb_data);
+  g_hash_table_foreach_sorted (ht, foreach_backend, &cb_data, strcmp);
 }
 
 /* ========================= END OF FILE =================== */
--- gnucash-2.2.8/src/backend/file/sixtp-dom-generators.c.orig	2009-05-01 16:41:27.000000000 -0700
+++ gnucash-2.2.8/src/backend/file/sixtp-dom-generators.c	2009-05-02 22:06:42.000000000 -0700
@@ -314,14 +314,15 @@
     break;
     case KVP_TYPE_GLIST:
     {
-        GList *cursor;
+        GList *cursor, *sorted = g_list_sort(g_list_copy(kvp_value_get_glist(val)), (GCompareFunc)strcmp);
         
         xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "list");
-        for(cursor = kvp_value_get_glist(val); cursor; cursor = cursor->next)
+        for(cursor = sorted; cursor; cursor = cursor->next)
         {
             kvp_value *val = (kvp_value*)cursor->data;
             add_kvp_value_node(val_node, "slot:value", val);
         }
+        g_list_free(sorted);
     }
     
     break;
@@ -335,8 +336,8 @@
         if (!frame || !kvp_frame_get_hash (frame))
           break;
 
-        g_hash_table_foreach(kvp_frame_get_hash(frame),
-                             add_kvp_slot, val_node);
+        g_hash_table_foreach_sorted(kvp_frame_get_hash(frame),
+                                    add_kvp_slot, val_node, strcmp);
     }
     break;
 
@@ -380,7 +380,7 @@
     
     ret = xmlNewNode(NULL, BAD_CAST tag);
     
-    g_hash_table_foreach(kvp_frame_get_hash(frame), add_kvp_slot, ret);
+    g_hash_table_foreach_sorted(kvp_frame_get_hash(frame), add_kvp_slot, ret, strcmp);
     
     return ret;
 }
--- gnucash-2.2.8/src/backend/file/gnc-book-xml-v2.c~	2008-01-07 17:05:37.000000000 -0800
+++ gnucash-2.2.8/src/backend/file/gnc-book-xml-v2.c	2009-04-13 14:40:28.000000000 -0700
@@ -69,6 +69,7 @@
     GList *children, *node;
 
     children = gnc_account_get_children(account);
+    children = g_list_sort(children, qof_instance_guid_compare);
     for (node = children; node; node = node->next) 
     {
         xmlNodePtr accnode;
--- gnucash-2.2.8/src/business/business-core/file/gnc-bill-term-xml-v2.c.orig	2009-04-23 21:44:09.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-bill-term-xml-v2.c	2009-04-23 21:44:18.000000000 -0700
@@ -512,7 +512,7 @@
 static void
 billterm_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_billterm, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_billterm, (gpointer) out);
 }
 
 static gboolean
--- gnucash-2.2.8/src/business/business-core/file/gnc-customer-xml-v2.c.orig	2009-04-23 21:40:51.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-customer-xml-v2.c	2009-04-23 21:41:00.000000000 -0700
@@ -504,7 +504,7 @@
 static void
 customer_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_customer, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_customer, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-employee-xml-v2.c.orig	2009-04-23 21:41:20.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-employee-xml-v2.c	2009-04-23 21:41:30.000000000 -0700
@@ -423,7 +423,7 @@
 static void
 employee_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_employee, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_employee, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-entry-xml-v2.c.orig	2008-01-07 17:05:59.000000000 -0800
+++ gnucash-2.2.8/src/business/business-core/file/gnc-entry-xml-v2.c	2009-04-23 21:42:06.000000000 -0700
@@ -816,7 +816,7 @@
 static void
 entry_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_entry, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_entry, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-invoice-xml-v2.c.orig	2009-04-23 21:36:01.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-invoice-xml-v2.c	2009-04-23 21:36:33.000000000 -0700
@@ -535,7 +535,7 @@
 static void
 invoice_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_invoice, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_invoice, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-job-xml-v2.c.orig	2009-04-23 21:42:29.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-job-xml-v2.c	2009-04-23 21:42:40.000000000 -0700
@@ -322,7 +322,7 @@
 static void
 job_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_job, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_job, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-order-xml-v2.c.orig	2009-04-23 21:42:56.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-order-xml-v2.c	2009-04-23 21:43:02.000000000 -0700
@@ -365,7 +365,7 @@
 static void
 order_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_order, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_order, (gpointer) out);
 }
 
 static void
--- gnucash-2.2.8/src/business/business-core/file/gnc-tax-table-xml-v2.c.orig	2009-04-23 21:43:17.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-tax-table-xml-v2.c	2009-04-23 21:43:24.000000000 -0700
@@ -475,7 +475,7 @@
 static void
 taxtable_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_taxtable, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_taxtable, (gpointer) out);
 }
 
 
--- gnucash-2.2.8/src/business/business-core/file/gnc-vendor-xml-v2.c.orig	2009-04-23 21:43:45.000000000 -0700
+++ gnucash-2.2.8/src/business/business-core/file/gnc-vendor-xml-v2.c	2009-04-23 21:43:50.000000000 -0700
@@ -441,7 +441,7 @@
 static void
 vendor_write (FILE *out, QofBook *book)
 {
-  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_vendor, (gpointer) out);
+  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_vendor, (gpointer) out);
 }
 
 static void
diff -u gnucash-2.2.4/src/backend/file/gnc-account-xml-v2.c gnucash-2.2.4-sorted/src/backend/file/gnc-account-xml-v2.c
--- gnucash-2.2.4/src/backend/file/gnc-account-xml-v2.c	2008-03-02 05:24:27.000000000 -0800
+++ gnucash-2.2.4-sorted/src/backend/file/gnc-account-xml-v2.c	2008-04-23 15:06:13.000000000 -0700
@@ -139,6 +139,8 @@
     {
        xmlNodePtr toaddto = xmlNewChild(ret, NULL, BAD_CAST act_lots_string, NULL);
 
+       lots = g_list_sort(lots, qof_instance_guid_compare);
+
        for (n = lots; n; n=n->next)
        {
           GNCLot * lot = n->data;


More information about the gnucash-devel mailing list