[evolution-data-server] I#49 - [CardDAV] Local cache made broken after update



commit 66966a2f6a73b77556e907774e5a41bd369c47c1
Author: Milan Crha <mcrha redhat com>
Date:   Tue Oct 23 11:57:34 2018 +0200

    I#49 - [CardDAV] Local cache made broken after update
    
    Closes https://gitlab.gnome.org/GNOME/evolution-data-server/issues/49

 .../backends/carddav/e-book-backend-carddav.c      |  3 ++
 src/addressbook/libedata-book/e-book-cache.c       |  1 +
 .../backends/caldav/e-cal-backend-caldav.c         |  3 ++
 src/libebackend/e-cache.c                          | 58 +++++++++++++++++++++-
 src/libebackend/e-cache.h                          |  6 +++
 5 files changed, 69 insertions(+), 2 deletions(-)
---
diff --git a/src/addressbook/backends/carddav/e-book-backend-carddav.c 
b/src/addressbook/backends/carddav/e-book-backend-carddav.c
index b2afae39a..60a824b74 100644
--- a/src/addressbook/backends/carddav/e-book-backend-carddav.c
+++ b/src/addressbook/backends/carddav/e-book-backend-carddav.c
@@ -1142,6 +1142,9 @@ ebb_carddav_save_contact_sync (EBookMetaBackend *meta_backend,
                }
 
                g_free (new_etag);
+       } else if (uid && vcard_string) {
+               success = FALSE;
+               g_propagate_error (error, EDB_ERROR_EX (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Missing 
information about vCard URL, local cache is possibly incomplete or broken. Remove it, please.")));
        } else {
                success = FALSE;
                g_propagate_error (error, EDB_ERROR_EX (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Object to save is 
not a valid vCard")));
diff --git a/src/addressbook/libedata-book/e-book-cache.c b/src/addressbook/libedata-book/e-book-cache.c
index 1401d8f40..515d990a1 100644
--- a/src/addressbook/libedata-book/e-book-cache.c
+++ b/src/addressbook/libedata-book/e-book-cache.c
@@ -4260,6 +4260,7 @@ e_book_cache_fill_pgp_cert_column (ECache *cache,
        e_cache_column_values_take_value (*out_other_columns, e_contact_field_name (E_CONTACT_PGP_CERT), 
g_strdup_printf ("%d", cert ? 1 : 0));
 
        e_contact_cert_free (cert);
+       g_object_unref (contact);
 
        return TRUE;
 }
diff --git a/src/calendar/backends/caldav/e-cal-backend-caldav.c 
b/src/calendar/backends/caldav/e-cal-backend-caldav.c
index ca80748a9..24c9dd560 100644
--- a/src/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/src/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -1315,6 +1315,9 @@ ecb_caldav_save_component_sync (ECalMetaBackend *meta_backend,
                }
 
                g_free (new_etag);
+       } else if (uid && ical_string) {
+               success = FALSE;
+               g_propagate_error (error, EDC_ERROR_EX (InvalidObject, _("Missing information about component 
URL, local cache is possibly incomplete or broken. Remove it, please.")));
        } else {
                success = FALSE;
                g_propagate_error (error, EDC_ERROR (InvalidObject));
diff --git a/src/libebackend/e-cache.c b/src/libebackend/e-cache.c
index 0b2edd584..cfc13b0ec 100644
--- a/src/libebackend/e-cache.c
+++ b/src/libebackend/e-cache.c
@@ -2111,7 +2111,7 @@ e_cache_foreach_update_cb (ECache *cache,
        rd->revision = g_strdup (column_values[fu->revision_index]);
        rd->object = g_strdup (column_values[fu->object_index]);
        rd->offline_state = offline_state;
-       rd->ncols = ncols;
+       rd->ncols = cvalues->len;
        rd->column_values = cvalues;
 
        if (cnames)
@@ -2119,7 +2119,7 @@ e_cache_foreach_update_cb (ECache *cache,
 
        fu->rows = g_slist_prepend (fu->rows, rd);
 
-       g_return_val_if_fail (fu->column_names && (gint) fu->column_names->len != ncols, FALSE);
+       g_return_val_if_fail (fu->column_names && (gint) fu->column_names->len == rd->ncols, FALSE);
 
        return TRUE;
 }
@@ -2140,6 +2140,10 @@ e_cache_foreach_update_cb (ECache *cache,
  * was successful, not whether there are any changes to be saved. If anything
  * fails during the call then the all changes are reverted.
  *
+ * When there are requested any changes by the @func, this function also
+ * calls e_cache_copy_missing_to_column_values() to ensure no descendant
+ * column data is lost.
+ *
  * Returns: Whether succeeded.
  *
  * Since: 3.26
@@ -2235,6 +2239,14 @@ e_cache_foreach_update (ECache *cache,
                                            (new_object && g_strcmp0 (new_object, fr->object) != 0) ||
                                            (new_offline_state != fr->offline_state) ||
                                            (new_other_columns && e_cache_column_values_get_size 
(new_other_columns) > 0))) {
+                                               if (!new_other_columns)
+                                                       new_other_columns = e_cache_column_values_new ();
+
+                                               e_cache_copy_missing_to_column_values (cache, fr->ncols,
+                                                       (const gchar **) fu.column_names->pdata,
+                                                       (const gchar **) fr->column_values->pdata,
+                                                       new_other_columns);
+
                                                success = e_cache_put_locked (cache,
                                                        fr->uid,
                                                        new_revision ? new_revision : fr->revision,
@@ -2269,6 +2281,48 @@ e_cache_foreach_update (ECache *cache,
        return success;
 }
 
+/**
+ * e_cache_copy_missing_to_column_values:
+ * @cache: an #ECache
+ * @ncols: count of columns, items in column_names and column_values
+ * @column_names: column names
+ * @column_values: column values
+ * @other_columns: (in out): an #ECacheColumnValues to fill
+ *
+ * Adds every column value which is not part of the @other_columns to it,
+ * except of E_CACHE_COLUMN_UID, E_CACHE_COLUMN_REVISION, E_CACHE_COLUMN_OBJECT
+ * and E_CACHE_COLUMN_STATE columns.
+ *
+ * This can be used within the callback of e_cache_foreach_update().
+ *
+ * Since: 3.32
+ **/
+void
+e_cache_copy_missing_to_column_values (ECache *cache,
+                                      gint ncols,
+                                      const gchar *column_names[],
+                                      const gchar *column_values[],
+                                      ECacheColumnValues *other_columns)
+{
+       gint ii;
+
+       g_return_if_fail (E_IS_CACHE (cache));
+       g_return_if_fail (column_names != NULL);
+       g_return_if_fail (column_values != NULL);
+       g_return_if_fail (other_columns != NULL);
+
+       for (ii = 0; ii < ncols; ii++) {
+               if (column_names[ii] && column_values[ii] &&
+                   !e_cache_column_values_contains (other_columns, column_names[ii]) &&
+                   g_ascii_strcasecmp (column_names[ii], E_CACHE_COLUMN_UID) != 0 &&
+                   g_ascii_strcasecmp (column_names[ii], E_CACHE_COLUMN_REVISION) != 0 &&
+                   g_ascii_strcasecmp (column_names[ii], E_CACHE_COLUMN_OBJECT) != 0 &&
+                   g_ascii_strcasecmp (column_names[ii], E_CACHE_COLUMN_STATE) != 0) {
+                       e_cache_column_values_put (other_columns, column_names[ii], column_values[ii]);
+               }
+       }
+}
+
 /**
  * e_cache_get_offline_state:
  * @cache: an #ECache
diff --git a/src/libebackend/e-cache.h b/src/libebackend/e-cache.h
index 3ff428a72..3230cdec5 100644
--- a/src/libebackend/e-cache.h
+++ b/src/libebackend/e-cache.h
@@ -462,6 +462,12 @@ gboolean   e_cache_foreach_update          (ECache *cache,
                                                 gpointer user_data,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           e_cache_copy_missing_to_column_values
+                                               (ECache *cache,
+                                                gint ncols,
+                                                const gchar *column_names[],
+                                                const gchar *column_values[],
+                                                ECacheColumnValues *other_columns);
 
 /* Offline support */
 EOfflineState  e_cache_get_offline_state       (ECache *cache,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]