[evolution-data-server] Bug 732717 - Refreshing an IMAP account does not refresh folder list



commit 27116dde047e00c0dd0a0891a13ae9c0bea2d163
Author: Milan Crha <mcrha redhat com>
Date:   Thu Nov 20 17:13:40 2014 +0100

    Bug 732717 - Refreshing an IMAP account does not refresh folder list

 camel/providers/imapx/camel-imapx-mailbox.c |   44 +++++++++++++
 camel/providers/imapx/camel-imapx-mailbox.h |   13 ++++
 camel/providers/imapx/camel-imapx-store.c   |   88 ++++++++++++++++++++++++++-
 3 files changed, 143 insertions(+), 2 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-mailbox.c b/camel/providers/imapx/camel-imapx-mailbox.c
index 7da8b00..6b555d3 100644
--- a/camel/providers/imapx/camel-imapx-mailbox.c
+++ b/camel/providers/imapx/camel-imapx-mailbox.c
@@ -48,6 +48,8 @@ struct _CamelIMAPXMailboxPrivate {
        guint64 highestmodseq;
        guint32 permanentflags;
 
+       CamelIMAPXMailboxState state;
+
        GMutex property_lock;
        GRecMutex update_lock;
 
@@ -126,6 +128,7 @@ camel_imapx_mailbox_init (CamelIMAPXMailbox *mailbox)
        g_rec_mutex_init (&mailbox->priv->update_lock);
        mailbox->priv->message_map = g_sequence_new (NULL);
        mailbox->priv->permanentflags = ~0;
+       mailbox->priv->state = CAMEL_IMAPX_MAILBOX_STATE_CREATED;
 }
 
 /**
@@ -217,6 +220,7 @@ camel_imapx_mailbox_clone (CamelIMAPXMailbox *mailbox,
        clone->priv->uidnext = mailbox->priv->uidnext;
        clone->priv->uidvalidity = mailbox->priv->uidvalidity;
        clone->priv->highestmodseq = mailbox->priv->highestmodseq;
+       clone->priv->state = mailbox->priv->state;
 
        clone->priv->quota_roots = g_strdupv (mailbox->priv->quota_roots);
 
@@ -238,6 +242,46 @@ camel_imapx_mailbox_clone (CamelIMAPXMailbox *mailbox,
 }
 
 /**
+ * camel_imapx_mailbox_get_state:
+ * @mailbox: a #CamelIMAPXMailbox
+ *
+ * Returns current state of the mailbox. This is used for folder
+ * structure updates, to identify newly created, updated, renamed
+ * or removed mailboxes.
+ *
+ * Returns: Current (update) state of the mailbox.
+ *
+ * Since: 3.14
+ **/
+CamelIMAPXMailboxState
+camel_imapx_mailbox_get_state (CamelIMAPXMailbox *mailbox)
+{
+       g_return_val_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox), CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN);
+
+       return mailbox->priv->state;
+}
+
+/**
+ * camel_imapx_mailbox_set_state:
+ * @mailbox: a #CamelIMAPXMailbox
+ * @state: a new #CamelIMAPXMailboxState to set
+ *
+ * Sets current (update) state of the mailbox. This is used for folder
+ * structure updates, to identify newly created, updated, renamed
+ * or removed mailboxes.
+ *
+ * Since: 3.14
+ **/
+void
+camel_imapx_mailbox_set_state (CamelIMAPXMailbox *mailbox,
+                              CamelIMAPXMailboxState state)
+{
+       g_return_if_fail (CAMEL_IS_IMAPX_MAILBOX (mailbox));
+
+       mailbox->priv->state = state;
+}
+
+/**
  * camel_imapx_mailbox_exists:
  * @mailbox: a #CamelIMAPXMailbox
  *
diff --git a/camel/providers/imapx/camel-imapx-mailbox.h b/camel/providers/imapx/camel-imapx-mailbox.h
index 083d2ac..b8de9a9 100644
--- a/camel/providers/imapx/camel-imapx-mailbox.h
+++ b/camel/providers/imapx/camel-imapx-mailbox.h
@@ -47,6 +47,13 @@ typedef struct _CamelIMAPXMailbox CamelIMAPXMailbox;
 typedef struct _CamelIMAPXMailboxClass CamelIMAPXMailboxClass;
 typedef struct _CamelIMAPXMailboxPrivate CamelIMAPXMailboxPrivate;
 
+typedef enum {
+       CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN,
+       CAMEL_IMAPX_MAILBOX_STATE_CREATED,
+       CAMEL_IMAPX_MAILBOX_STATE_UPDATED,
+       CAMEL_IMAPX_MAILBOX_STATE_RENAMED
+} CamelIMAPXMailboxState;
+
 /**
  * CamelIMAPXMailbox:
  *
@@ -73,6 +80,12 @@ CamelIMAPXMailbox *
                camel_imapx_mailbox_clone
                                        (CamelIMAPXMailbox *mailbox,
                                         const gchar *new_mailbox_name);
+CamelIMAPXMailboxState
+               camel_imapx_mailbox_get_state
+                                       (CamelIMAPXMailbox *mailbox);
+void           camel_imapx_mailbox_set_state
+                                       (CamelIMAPXMailbox *mailbox,
+                                        CamelIMAPXMailboxState state);
 gboolean       camel_imapx_mailbox_exists
                                        (CamelIMAPXMailbox *mailbox);
 gint           camel_imapx_mailbox_compare
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 7cd5098..5e5ff3c 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -993,6 +993,7 @@ event:
        camel_store_summary_save (imapx_store->summary);
 
        fi = imapx_store_build_folder_info (imapx_store, folder_path, 0);
+       camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (imapx_store), fi);
        camel_store_folder_deleted (CAMEL_STORE (imapx_store), fi);
        camel_folder_info_free (fi);
 }
@@ -1352,10 +1353,73 @@ exit:
        return success;
 }
 
+static void
+imapx_store_mark_mailbox_unknown_cb (gpointer key,
+                                    gpointer value,
+                                    gpointer user_data)
+{
+       CamelIMAPXMailbox *mailbox = value;
+
+       g_return_if_fail (mailbox != NULL);
+
+       camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN);
+}
+
+static gboolean
+imapx_store_remove_unknown_mailboxes_cb (gpointer key,
+                                        gpointer value,
+                                        gpointer user_data)
+{
+       CamelIMAPXMailbox *mailbox = value;
+       CamelIMAPXStore *imapx_store = user_data;
+       CamelStoreInfo *si;
+
+       g_return_val_if_fail (mailbox != NULL, FALSE);
+       g_return_val_if_fail (CAMEL_IS_IMAPX_STORE (imapx_store), FALSE);
+
+       if (camel_imapx_mailbox_get_state (mailbox) == CAMEL_IMAPX_MAILBOX_STATE_CREATED) {
+               CamelFolderInfo *fi;
+               gchar *folder_path;
+
+               folder_path = camel_imapx_mailbox_dup_folder_path (mailbox);
+               fi = imapx_store_build_folder_info (imapx_store, folder_path,
+                       imapx_store_mailbox_attributes_to_flags (mailbox));
+               camel_store_folder_created (CAMEL_STORE (imapx_store), fi);
+               camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (imapx_store), fi);
+               camel_folder_info_free (fi);
+               g_free (folder_path);
+       }
+
+       if (camel_imapx_mailbox_get_state (mailbox) != CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN) {
+               return FALSE;
+       }
+
+       si = (CamelStoreInfo *) camel_imapx_store_summary_mailbox (imapx_store->summary, 
camel_imapx_mailbox_get_name (mailbox));
+       if (si) {
+               const gchar *si_path;
+               gchar *dup_folder_path;
+
+               si_path = camel_store_info_path (imapx_store->summary, si);
+               dup_folder_path = g_strdup (si_path);
+
+               if (dup_folder_path != NULL) {
+                       imapx_delete_folder_from_cache (imapx_store, dup_folder_path);
+                       g_free (dup_folder_path);
+               } else {
+                       camel_store_summary_remove (imapx_store->summary, si);
+               }
+
+               camel_store_summary_info_unref (imapx_store->summary, si);
+       }
+
+       return TRUE;
+}
+
 static gboolean
 sync_folders (CamelIMAPXStore *imapx_store,
               const gchar *root_folder_path,
               CamelStoreGetFolderInfoFlags flags,
+             gboolean initial_setup,
               GCancellable *cancellable,
               GError **error)
 {
@@ -1380,6 +1444,12 @@ sync_folders (CamelIMAPXStore *imapx_store,
         * in imapx_store_process_mailbox_attributes(). */
        g_atomic_int_inc (&imapx_store->priv->syncing_folders);
 
+       if (!initial_setup && (!root_folder_path || !*root_folder_path)) {
+               g_mutex_lock (&imapx_store->priv->mailboxes_lock);
+               g_hash_table_foreach (imapx_store->priv->mailboxes, imapx_store_mark_mailbox_unknown_cb, 
imapx_store);
+               g_mutex_unlock (&imapx_store->priv->mailboxes_lock);
+       }
+
        if (root_folder_path != NULL && *root_folder_path != '\0') {
                success = fetch_folder_info_from_folder_path (
                        imapx_store, server, root_folder_path, flags,
@@ -1410,6 +1480,12 @@ sync_folders (CamelIMAPXStore *imapx_store,
        if (!success)
                goto exit;
 
+       if (!initial_setup && (!root_folder_path || !*root_folder_path)) {
+               g_mutex_lock (&imapx_store->priv->mailboxes_lock);
+               g_hash_table_foreach_remove (imapx_store->priv->mailboxes, 
imapx_store_remove_unknown_mailboxes_cb, imapx_store);
+               g_mutex_unlock (&imapx_store->priv->mailboxes_lock);
+       }
+
        array = camel_store_summary_array (imapx_store->summary);
 
        for (ii = 0; ii < array->len; ii++) {
@@ -1483,7 +1559,7 @@ imapx_refresh_finfo (CamelSession *session,
                CAMEL_SERVICE (store), cancellable, error))
                goto exit;
 
-       sync_folders (store, NULL, 0, cancellable, error);
+       sync_folders (store, NULL, 0, FALSE, cancellable, error);
 
        camel_store_summary_save (store->summary);
 
@@ -1724,7 +1800,7 @@ imapx_store_get_folder_info_sync (CamelStore *store,
                goto exit;
        }
 
-       if (!sync_folders (imapx_store, top, flags, cancellable, error))
+       if (!sync_folders (imapx_store, top, flags, initial_setup, cancellable, error))
                goto exit;
 
        camel_store_summary_save (imapx_store->summary);
@@ -3193,14 +3269,20 @@ camel_imapx_store_handle_list_response (CamelIMAPXStore *imapx_store,
                mailbox = imapx_store_rename_mailbox_unlocked (
                        imapx_store, old_mailbox_name, mailbox_name);
                emit_mailbox_renamed = (mailbox != NULL);
+               if (mailbox && camel_imapx_mailbox_get_state (mailbox) == CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN)
+                       camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_RENAMED);
        }
        if (mailbox == NULL) {
                mailbox = imapx_store_ref_mailbox_unlocked (imapx_store, mailbox_name);
                emit_mailbox_updated = (mailbox != NULL);
+               if (mailbox && camel_imapx_mailbox_get_state (mailbox) == CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN)
+                       camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_UPDATED);
        }
        if (mailbox == NULL) {
                mailbox = imapx_store_create_mailbox_unlocked (imapx_store, response);
                emit_mailbox_created = (mailbox != NULL);
+               if (mailbox)
+                       camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_CREATED);
        } else {
                camel_imapx_mailbox_handle_list_response (mailbox, response);
        }
@@ -3255,6 +3337,8 @@ camel_imapx_store_handle_lsub_response (CamelIMAPXStore *imapx_store,
        mailbox = imapx_store_ref_mailbox_unlocked (imapx_store, mailbox_name);
        if (mailbox != NULL) {
                camel_imapx_mailbox_handle_lsub_response (mailbox, response);
+               if (camel_imapx_mailbox_get_state (mailbox) == CAMEL_IMAPX_MAILBOX_STATE_UNKNOWN)
+                       camel_imapx_mailbox_set_state (mailbox, CAMEL_IMAPX_MAILBOX_STATE_UPDATED);
                emit_mailbox_updated = TRUE;
        }
        g_mutex_unlock (&imapx_store->priv->mailboxes_lock);


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