[evolution-data-server] Rework camel_imapx_server_list().
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Rework camel_imapx_server_list().
- Date: Sun, 27 Oct 2013 14:54:28 +0000 (UTC)
commit fc43f6f07d61287329dec657769afbe6cc88ba63
Author: Matthew Barnes <mbarnes redhat com>
Date: Wed Aug 7 10:18:06 2013 +0200
Rework camel_imapx_server_list().
Repurpose camel_imapx_server_list() to create/update CamelIMAPXMailbox
instances within CamelIMAPXServer. This function no longer returns an
array of CamelIMAPXListResponses, but simply a success/failure boolean.
Also, this function no longer takes an extension string parameter. If
the server names "LIST-EXTENDED" in its CAPABILITY response, then this
function automatically issues an extended LIST command:
LIST "" $PATTERN RETURN (CHILDREN SUBSCRIBED)
Otherwise it issues a LIST command followed by an LSUB command:
LIST "" $PATTERN
LSUB "" $PATTERN
After camel_imapx_server_list() returns, the caller can then pass the
same $PATTERN string to camel_imapx_server_list_mailboxes() to obtain
an up-to-date list of CamelIMAPXMailbox instances that match $PATTERN.
Also as part of this, we now explicitly only list mailboxes in personal
namespaces. Listing mailboxes in shared or other users namespaces is a
future enhancement since CamelStore does not yet have a suitable API to
support this properly.
camel/camel-imapx-server.c | 141 ++++++++--------
camel/camel-imapx-server.h | 3 +-
camel/camel-imapx-store.c | 418 +++++++++++++++++++-------------------------
3 files changed, 252 insertions(+), 310 deletions(-)
---
diff --git a/camel/camel-imapx-server.c b/camel/camel-imapx-server.c
index 19a98aa..3c8cfa0 100644
--- a/camel/camel-imapx-server.c
+++ b/camel/camel-imapx-server.c
@@ -134,9 +134,6 @@ struct _CopyMessagesData {
struct _ListData {
gchar *pattern;
- CamelStoreGetFolderInfoFlags flags;
- gchar *ext;
- GHashTable *folders;
};
struct _MailboxData {
@@ -324,6 +321,10 @@ struct _CamelIMAPXServerPrivate {
* STATUS $mailbox_name ($status_data_items) */
gchar *status_data_items;
+ /* Return options for extended LIST commands:
+ * LIST "" $pattern RETURN ($list_return_opts) */
+ gchar *list_return_opts;
+
/* Untagged SEARCH data gets deposited here.
* The search command should claim the results
* when finished and reset the pointer to NULL. */
@@ -663,9 +664,6 @@ static void
list_data_free (ListData *data)
{
g_free (data->pattern);
- g_free (data->ext);
-
- g_hash_table_destroy (data->folders);
g_slice_free (ListData, data);
}
@@ -829,6 +827,14 @@ imapx_server_stash_command_arguments (CamelIMAPXServer *is)
g_string_append (buffer, " HIGHESTMODSEQ");
g_free (is->priv->status_data_items);
is->priv->status_data_items = g_string_free (buffer, FALSE);
+
+ g_free (is->priv->list_return_opts);
+ if (CAMEL_IMAPX_HAVE_CAPABILITY (is->cinfo, LIST_EXTENDED)) {
+ buffer = g_string_new ("CHILDREN SUBSCRIBED");
+ is->priv->list_return_opts = g_string_free (buffer, FALSE);
+ } else {
+ is->priv->list_return_opts = NULL;
+ }
}
static void
@@ -2417,8 +2423,6 @@ imapx_untagged_list (CamelIMAPXServer *is,
{
CamelIMAPXListResponse *response;
CamelIMAPXMailbox *mailbox = NULL;
- CamelIMAPXJob *job = NULL;
- ListData *data = NULL;
gboolean emit_mailbox_created = FALSE;
gboolean emit_mailbox_renamed = FALSE;
gboolean emit_mailbox_updated = FALSE;
@@ -2485,30 +2489,7 @@ imapx_untagged_list (CamelIMAPXServer *is,
g_signal_emit (is, signals[MAILBOX_UPDATED], 0, mailbox);
g_clear_object (&mailbox);
-
- job = imapx_match_active_job (is, IMAPX_JOB_LIST, mailbox_name);
-
- data = camel_imapx_job_get_data (job);
- g_return_val_if_fail (data != NULL, FALSE);
-
- // TODO: we want to make sure the names match?
-
- if (data->flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) {
- c (is->tagprefix, "lsub: '%s' (%c)\n", mailbox_name, separator);
- } else {
- c (is->tagprefix, "list: '%s' (%c)\n", mailbox_name, separator);
- }
-
- if (job && !g_hash_table_contains (data->folders, response)) {
- if (is->priv->context->lsub)
- camel_imapx_list_response_add_attribute (
- response, CAMEL_IMAPX_LIST_ATTR_SUBSCRIBED);
- g_hash_table_add (data->folders, g_object_ref (response));
- } else {
- g_warning ("got list response but no current listing job happening?\n");
- }
-
- g_object_unref (response);
+ g_clear_object (&response);
return TRUE;
}
@@ -6533,6 +6514,43 @@ imapx_command_list_done (CamelIMAPXServer *is,
imapx_unregister_job (is, job);
}
+static void
+imapx_command_list_lsub (CamelIMAPXServer *is,
+ CamelIMAPXCommand *ic)
+{
+ CamelIMAPXJob *job;
+ ListData *data;
+ GError *local_error = NULL;
+
+ job = camel_imapx_command_get_job (ic);
+ g_return_if_fail (CAMEL_IS_IMAPX_JOB (job));
+
+ data = camel_imapx_job_get_data (job);
+ g_return_if_fail (data != NULL);
+
+ if (camel_imapx_command_set_error_if_failed (ic, &local_error)) {
+ g_prefix_error (
+ &local_error, "%s: ",
+ _("Error fetching folders"));
+ camel_imapx_job_take_error (job, local_error);
+ imapx_unregister_job (is, job);
+
+ } else {
+ ic = camel_imapx_command_new (
+ is, "LIST", NULL,
+ "LSUB \"\" %s",
+ data->pattern);
+
+ ic->pri = job->pri;
+ camel_imapx_command_set_job (ic, job);
+ ic->complete = imapx_command_list_done;
+
+ imapx_command_queue (is, ic);
+
+ camel_imapx_command_unref (ic);
+ }
+}
+
static gboolean
imapx_job_list_start (CamelIMAPXJob *job,
CamelIMAPXServer *is,
@@ -6545,20 +6563,23 @@ imapx_job_list_start (CamelIMAPXJob *job,
data = camel_imapx_job_get_data (job);
g_return_val_if_fail (data != NULL, FALSE);
- ic = camel_imapx_command_new (
- is, "LIST", NULL,
- "%s \"\" %s",
- (data->flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) ?
- "LSUB" : "LIST",
- data->pattern);
- if (data->ext) {
- /* Hm, we need a way to add atoms _without_ quoting or using literals */
- camel_imapx_command_add (ic, " ");
- camel_imapx_command_add (ic, data->ext);
+ if (is->priv->list_return_opts != NULL) {
+ ic = camel_imapx_command_new (
+ is, "LIST", NULL,
+ "LIST \"\" %s RETURN (%t)",
+ data->pattern,
+ is->priv->list_return_opts);
+ ic->complete = imapx_command_list_done;
+ } else {
+ ic = camel_imapx_command_new (
+ is, "LIST", NULL,
+ "LIST \"\" %s",
+ data->pattern);
+ ic->complete = imapx_command_list_lsub;
}
+
ic->pri = job->pri;
camel_imapx_command_set_job (ic, job);
- ic->complete = imapx_command_list_done;
imapx_command_queue (is, ic);
@@ -7656,6 +7677,7 @@ imapx_server_finalize (GObject *object)
g_mutex_clear (&is->priv->mailboxes_lock);
g_free (is->priv->status_data_items);
+ g_free (is->priv->list_return_opts);
if (is->priv->search_results != NULL)
g_array_unref (is->priv->search_results);
@@ -8866,30 +8888,22 @@ camel_imapx_server_expunge (CamelIMAPXServer *is,
return success;
}
-GPtrArray *
+gboolean
camel_imapx_server_list (CamelIMAPXServer *is,
const gchar *pattern,
CamelStoreGetFolderInfoFlags flags,
- const gchar *ext,
GCancellable *cancellable,
GError **error)
{
CamelIMAPXJob *job;
- GPtrArray *folders = NULL;
ListData *data;
+ gboolean success;
- g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), NULL);
- g_return_val_if_fail (pattern != NULL, NULL);
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (is), FALSE);
+ g_return_val_if_fail (pattern != NULL, FALSE);
data = g_slice_new0 (ListData);
data->pattern = g_strdup (pattern);
- data->flags = flags;
- data->ext = g_strdup (ext);
- data->folders = g_hash_table_new_full (
- (GHashFunc) camel_imapx_list_response_hash,
- (GEqualFunc) camel_imapx_list_response_equal,
- (GDestroyNotify) g_object_unref,
- (GDestroyNotify) NULL);
job = camel_imapx_job_new (cancellable);
job->type = IMAPX_JOB_LIST;
@@ -8904,24 +8918,11 @@ camel_imapx_server_list (CamelIMAPXServer *is,
if (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST)
job->pri += 300;
- if (imapx_submit_job (is, job, error)) {
- GList *list, *link;
-
- /* Transfer LIST responses from a GHashTable
- * to a sorted GPtrArray by way of a GList. */
- folders = g_ptr_array_new_with_free_func (
- (GDestroyNotify) g_object_unref);
- list = g_list_sort (
- g_hash_table_get_keys (data->folders),
- (GCompareFunc) camel_imapx_list_response_compare);
- for (link = list; link != NULL; link = g_list_next (link))
- g_ptr_array_add (folders, g_object_ref (link->data));
- g_list_free (list);
- }
+ success = imapx_submit_job (is, job, error);
camel_imapx_job_unref (job);
- return folders;
+ return success;
}
gboolean
diff --git a/camel/camel-imapx-server.h b/camel/camel-imapx-server.h
index 0bf8e64..d5881fb 100644
--- a/camel/camel-imapx-server.h
+++ b/camel/camel-imapx-server.h
@@ -182,10 +182,9 @@ CamelAuthenticationResult
const gchar *mechanism,
GCancellable *cancellable,
GError **error);
-GPtrArray * camel_imapx_server_list (CamelIMAPXServer *is,
+gboolean camel_imapx_server_list (CamelIMAPXServer *is,
const gchar *pattern,
CamelStoreGetFolderInfoFlags flags,
- const gchar *ext,
GCancellable *cancellable,
GError **error);
CamelFolderChangeInfo *
diff --git a/camel/camel-imapx-store.c b/camel/camel-imapx-store.c
index 81731d0..3cd257b 100644
--- a/camel/camel-imapx-store.c
+++ b/camel/camel-imapx-store.c
@@ -76,6 +76,7 @@ struct _CamelIMAPXStorePrivate {
/* Used for synchronizing get_folder_info_sync(). */
GMutex get_finfo_lock;
time_t last_refresh_time;
+ volatile gint syncing_folders;
};
enum {
@@ -489,6 +490,13 @@ imapx_store_process_mailbox_attributes (CamelIMAPXStore *store,
emit_folder_unsubscribed_deleted = TRUE;
}
+ /* Suppress all signal emissions when synchronizing folders. */
+ if (g_atomic_int_get (&store->priv->syncing_folders) > 0) {
+ emit_folder_created_subscribed = FALSE;
+ emit_folder_unsubscribed_deleted = FALSE;
+ emit_folder_renamed = FALSE;
+ }
+
/* At most one signal emission flag should be set. */
g_warn_if_fail (
(emit_folder_created_subscribed ? 1 : 0) +
@@ -1436,296 +1444,247 @@ get_folder_info_offline (CamelStore *store,
}
static void
-add_mailbox_to_summary (CamelIMAPXStore *imapx_store,
- CamelIMAPXServer *server,
- CamelIMAPXListResponse *response,
- GHashTable *mailboxes,
- gboolean update_for_lsub)
+collect_folder_info_for_list (CamelIMAPXStore *imapx_store,
+ CamelIMAPXMailbox *mailbox,
+ GHashTable *folder_info_results)
{
+ CamelStoreSummary *store_summary;
CamelIMAPXStoreInfo *si;
CamelFolderInfo *fi;
+ const gchar *folder_path;
const gchar *mailbox_name;
- gchar separator;
- CamelStoreInfoFlags flags;
- CamelStoreInfoFlags new_flags;
-
- mailbox_name = camel_imapx_list_response_get_mailbox_name (response);
- separator = camel_imapx_list_response_get_separator (response);
-
- /* XXX The flags type transforms from CamelStoreInfoFlags
- * to CamelFolderInfoFlags about half-way through this.
- * We should really eliminate the confusing redundancy. */
- flags = camel_imapx_list_response_get_summary_flags (response);
-
- if (update_for_lsub) {
- fi = g_hash_table_lookup (mailboxes, mailbox_name);
- if (fi != NULL)
- fi->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
- return;
- }
-
- si = camel_imapx_store_summary_add_from_mailbox (
- imapx_store->summary, mailbox_name, separator);
- if (si == NULL)
- return;
- new_flags =
- (si->info.flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) |
- (flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED);
-
- if (CAMEL_IMAPX_LACK_CAPABILITY (server->cinfo, NAMESPACE))
- imapx_store->dir_sep = separator;
-
- if (si->info.flags != new_flags) {
- si->info.flags = new_flags;
- camel_store_summary_touch (
- (CamelStoreSummary *) imapx_store->summary);
- }
+ store_summary = CAMEL_STORE_SUMMARY (imapx_store->summary);
- fi = camel_folder_info_new ();
- fi->full_name = g_strdup (camel_store_info_path (
- CAMEL_STORE_SUMMARY (imapx_store->summary),
- (CamelStoreInfo *) si));
- if (g_ascii_strcasecmp (fi->full_name, "inbox") == 0) {
- flags |= CAMEL_FOLDER_SYSTEM;
- flags |= CAMEL_FOLDER_TYPE_INBOX;
- fi->display_name = g_strdup (_("Inbox"));
- } else {
- fi->display_name = g_strdup (
- camel_store_info_name (
- CAMEL_STORE_SUMMARY (imapx_store->summary),
- (CamelStoreInfo *) si));
- }
+ mailbox_name = camel_imapx_mailbox_get_name (mailbox);
- fi->flags |= flags;
+ si = camel_imapx_store_summary_mailbox (
+ imapx_store->summary, mailbox_name);
+ g_return_if_fail (si != NULL);
- fi->total = -1;
- fi->unread = -1;
+ folder_path = camel_store_info_path (
+ store_summary, (CamelStoreInfo *) si);
+ fi = imapx_store_build_folder_info (imapx_store, folder_path, 0);
/* Takes ownership of the CamelFolderInfo. */
- g_hash_table_insert (mailboxes, g_strdup (mailbox_name), fi);
+ g_hash_table_insert (folder_info_results, g_strdup (mailbox_name), fi);
}
static gboolean
-fetch_mailboxes_for_pattern (CamelIMAPXStore *imapx_store,
- CamelIMAPXServer *server,
- const gchar *pattern,
- CamelStoreGetFolderInfoFlags flags,
- const gchar *ext,
- GHashTable *mailboxes,
- GCancellable *cancellable,
- GError **error)
+fetch_folder_info_for_pattern (CamelIMAPXServer *server,
+ CamelIMAPXNamespace *namespace,
+ const gchar *pattern,
+ CamelStoreGetFolderInfoFlags flags,
+ GHashTable *folder_info_results,
+ GCancellable *cancellable,
+ GError **error)
{
- GPtrArray *folders;
- gboolean update_for_lsub;
- guint ii;
+ CamelIMAPXStore *imapx_store;
+ GList *list, *link;
+ gboolean success;
- folders = camel_imapx_server_list (
- server, pattern, flags, ext, cancellable, error);
- if (folders == NULL)
+ success = camel_imapx_server_list (
+ server, pattern, flags, cancellable, error);
+ if (!success)
return FALSE;
- /* Indicates we had to issue a separate LSUB command after the
- * LIST command and we're just processing subscription results. */
- if (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)
- update_for_lsub = TRUE;
- else
- update_for_lsub = FALSE;
+ imapx_store = camel_imapx_server_ref_store (server);
+
+ list = camel_imapx_server_list_mailboxes (server, namespace, pattern);
- for (ii = 0; ii < folders->len; ii++) {
- CamelIMAPXListResponse *response;
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ CamelIMAPXMailbox *mailbox;
- response = g_ptr_array_index (folders, ii);
+ mailbox = CAMEL_IMAPX_MAILBOX (link->data);
- add_mailbox_to_summary (
- imapx_store, server, response,
- mailboxes, update_for_lsub);
+ collect_folder_info_for_list (
+ imapx_store, mailbox, folder_info_results);
}
- g_ptr_array_unref (folders);
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
+
+ g_object_unref (imapx_store);
return TRUE;
}
-static GList *
-get_namespaces (CamelIMAPXStore *imapx_store)
+static gboolean
+fetch_folder_info_for_namespace_category (CamelIMAPXServer *server,
+ CamelIMAPXNamespaceCategory category,
+ CamelStoreGetFolderInfoFlags flags,
+ GHashTable *folder_info_results,
+ GCancellable *cancellable,
+ GError **error)
{
- GList *namespaces = NULL;
- CamelIMAPXNamespaceList *nsl = NULL;
+ CamelIMAPXNamespaceResponse *namespace_response;
+ GList *list, *link;
+ gboolean success = TRUE;
- /* Add code to return the namespaces from preference else all of them */
- nsl = imapx_store->summary->namespaces;
- if (nsl->personal != NULL)
- namespaces = g_list_append (namespaces, nsl->personal);
- if (nsl->other != NULL)
- namespaces = g_list_append (namespaces, nsl->other);
- if (nsl->shared != NULL)
- namespaces = g_list_append (namespaces, nsl->shared);
+ namespace_response = camel_imapx_server_ref_namespaces (server);
+ g_return_val_if_fail (namespace_response != NULL, FALSE);
- return namespaces;
-}
+ list = camel_imapx_namespace_response_list (namespace_response);
-static GHashTable *
-fetch_mailboxes_for_namespaces (CamelIMAPXStore *imapx_store,
- const gchar *pattern,
- gboolean sync,
- GCancellable *cancellable,
- GError **error)
-{
- CamelIMAPXServer *server;
- GHashTable *mailboxes = NULL;
- GList *namespaces = NULL, *l;
- const gchar *list_ext = NULL;
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ CamelIMAPXNamespace *namespace;
+ CamelIMAPXNamespaceCategory ns_category;
+ const gchar *ns_prefix;
+ gchar *pattern;
- server = camel_imapx_store_ref_server (imapx_store, error);
+ namespace = CAMEL_IMAPX_NAMESPACE (link->data);
+ ns_category = camel_imapx_namespace_get_category (namespace);
+ ns_prefix = camel_imapx_namespace_get_prefix (namespace);
- if (server == NULL)
- return NULL;
+ if (ns_category != category)
+ continue;
- if (CAMEL_IMAPX_HAVE_CAPABILITY (server->cinfo, LIST_EXTENDED))
- list_ext = "RETURN (SUBSCRIBED)";
+ pattern = g_strdup_printf ("%s*", ns_prefix);
- mailboxes = g_hash_table_new_full (
- (GHashFunc) imapx_name_hash,
- (GEqualFunc) imapx_name_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) camel_folder_info_free);
+ success = fetch_folder_info_for_pattern (
+ server, namespace, pattern, flags,
+ folder_info_results, cancellable, error);
- namespaces = get_namespaces (imapx_store);
+ g_free (pattern);
- for (l = namespaces; l != NULL; l = g_list_next (l)) {
- CamelIMAPXStoreNamespace *ns = l->data;
+ if (!success)
+ break;
+ }
- while (ns != NULL) {
- CamelStoreGetFolderInfoFlags flags = 0;
- gboolean success;
- gchar *pat;
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
- if (pattern != NULL)
- pat = g_strdup_printf ("%s*", pattern);
- else if (*ns->prefix != '\0')
- pat = g_strdup_printf (
- "%s%c*", ns->prefix, ns->sep);
- else
- pat = g_strdup ("*");
-
- if (sync)
- flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST;
-
- success = fetch_mailboxes_for_pattern (
- imapx_store, server, pat, flags, list_ext,
- mailboxes, cancellable, error);
-
- if (success && list_ext == NULL) {
- /* If the server doesn't support LIST-EXTENDED
- * then we have to issue the LSUB command to
- * list the subscribed mailboxes separately. */
- flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
- success = fetch_mailboxes_for_pattern (
- imapx_store, server, pat, flags, NULL,
- mailboxes, cancellable, error);
- }
+ g_object_unref (namespace_response);
- g_free (pat);
+ return success;
+}
- if (!success) {
- g_hash_table_destroy (mailboxes);
- mailboxes = NULL;
- goto exit;
- }
+static gboolean
+fetch_folder_info_from_folder_path (CamelIMAPXServer *server,
+ const gchar *folder_path,
+ CamelStoreGetFolderInfoFlags flags,
+ GHashTable *folder_info_results,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelIMAPXNamespaceResponse *namespace_response;
+ CamelIMAPXNamespace *namespace;
+ gchar *mailbox_name;
+ gchar *utf7_mailbox_name;
+ gchar *pattern;
+ gchar separator;
+ gboolean success = FALSE;
- if (pattern != NULL)
- goto exit;
+ namespace_response = camel_imapx_server_ref_namespaces (server);
+ g_return_val_if_fail (namespace_response != NULL, FALSE);
- ns = ns->next;
- }
+ /* Find a suitable IMAP namespace for the folder path. */
+ namespace = camel_imapx_namespace_response_lookup_for_path (
+ namespace_response, folder_path);
+ if (namespace == NULL) {
+ g_set_error (
+ error, CAMEL_STORE_ERROR,
+ CAMEL_STORE_ERROR_INVALID,
+ _("No IMAP namespace for folder path '%s'"),
+ folder_path);
+ goto exit;
}
+ /* Convert the folder path to a mailbox name. */
+ separator = camel_imapx_namespace_get_separator (namespace);
+ mailbox_name = g_strdelimit (g_strdup (folder_path), "/", separator);
+
+ utf7_mailbox_name = camel_utf8_utf7 (mailbox_name);
+ pattern = g_strdup_printf ("%s*", utf7_mailbox_name);
+
+ success = fetch_folder_info_for_pattern (
+ server, namespace, pattern, flags,
+ folder_info_results, cancellable, error);
+
+ g_free (pattern);
+ g_free (utf7_mailbox_name);
+ g_free (mailbox_name);
+
exit:
- g_list_free (namespaces);
- g_object_unref (server);
+ g_clear_object (&namespace);
+ g_clear_object (&namespace_response);
- return mailboxes;
+ return success;
}
static gboolean
sync_folders (CamelIMAPXStore *imapx_store,
- const gchar *pattern,
- gboolean sync,
+ const gchar *root_folder_path,
+ CamelStoreGetFolderInfoFlags flags,
GCancellable *cancellable,
GError **error)
{
- CamelSettings *settings;
+ CamelIMAPXServer *server;
CamelStoreSummary *store_summary;
- GHashTable *mailboxes;
+ GHashTable *folder_info_results;
GPtrArray *array;
- gboolean notify_all;
guint ii;
+ gboolean success;
+
+ server = camel_imapx_store_ref_server (imapx_store, error);
+ if (server == NULL)
+ return FALSE;
store_summary = CAMEL_STORE_SUMMARY (imapx_store->summary);
- mailboxes = fetch_mailboxes_for_namespaces (
- imapx_store, pattern, sync, cancellable, error);
+ /* mailbox name -> CamelFolderInfo */
+ folder_info_results = g_hash_table_new_full (
+ (GHashFunc) imapx_name_hash,
+ (GEqualFunc) imapx_name_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) camel_folder_info_free);
+
+ /* This suppresses CamelStore signal emissions
+ * in imapx_store_process_mailbox_attributes(). */
+ g_atomic_int_inc (&imapx_store->priv->syncing_folders);
- if (mailboxes == NULL)
- return FALSE;
+ if (root_folder_path != NULL && *root_folder_path != '\0') {
+ success = fetch_folder_info_from_folder_path (
+ server, root_folder_path, flags,
+ folder_info_results, cancellable, error);
+ } else {
+ /* XXX We only fetch personal mailboxes at this time. */
+ success = fetch_folder_info_for_namespace_category (
+ server, CAMEL_IMAPX_NAMESPACE_PERSONAL, flags,
+ folder_info_results, cancellable, error);
+ }
- settings = camel_service_ref_settings (CAMEL_SERVICE (imapx_store));
- notify_all = !camel_imapx_settings_get_use_subscriptions (
- CAMEL_IMAPX_SETTINGS (settings));
- g_object_unref (settings);
+ /* Don't need to test for zero, just decrement atomically. */
+ g_atomic_int_dec_and_test (&imapx_store->priv->syncing_folders);
+
+ if (!success)
+ goto exit;
array = camel_store_summary_array (store_summary);
for (ii = 0; ii < array->len; ii++) {
CamelStoreInfo *si;
CamelFolderInfo *fi;
- CamelIMAPXStoreNamespace *ns;
const gchar *mailbox_name;
+ const gchar *si_path;
gboolean pattern_match;
si = g_ptr_array_index (array, ii);
+ si_path = camel_store_info_path (store_summary, si);
mailbox_name = ((CamelIMAPXStoreInfo *) si)->mailbox_name;
if (mailbox_name == NULL || *mailbox_name == '\0')
continue;
- ns = camel_imapx_store_summary_namespace_find_by_mailbox (
- imapx_store->summary, mailbox_name);
-
pattern_match =
- (pattern == NULL) || (*pattern == '\0') ||
- imapx_match_pattern (ns, pattern, mailbox_name);
+ (root_folder_path == NULL) ||
+ (*root_folder_path == '\0') ||
+ (g_str_has_prefix (si_path, root_folder_path));
if (!pattern_match)
continue;
- fi = g_hash_table_lookup (mailboxes, mailbox_name);
-
- if (fi != NULL) {
- gboolean do_notify = notify_all;
-
- /* Check if the SUBSCRIBED flags in the
- * folder info and store info disagree.
- * The folder info is authoritative. */
- if (((fi->flags ^ si->flags) & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) {
- si->flags &= ~CAMEL_FOLDER_SUBSCRIBED;
- si->flags |= fi->flags & CAMEL_FOLDER_SUBSCRIBED;
- camel_store_summary_touch (store_summary);
- do_notify = TRUE;
- }
-
- if (do_notify) {
- camel_store_folder_created (
- CAMEL_STORE (imapx_store), fi);
- camel_subscribable_folder_subscribed (
- CAMEL_SUBSCRIBABLE (imapx_store), fi);
- }
- } else {
- gchar *dup_folder_path;
- const gchar *si_path;
+ fi = g_hash_table_lookup (folder_info_results, mailbox_name);
- si_path = camel_store_info_path (store_summary, si);
- dup_folder_path = g_strdup (si_path);
+ if (fi == NULL) {
+ gchar *dup_folder_path = g_strdup (si_path);
if (dup_folder_path != NULL) {
imapx_unmark_folder_subscribed (
@@ -1741,9 +1700,12 @@ sync_folders (CamelIMAPXStore *imapx_store,
camel_store_summary_array_free (store_summary, array);
- g_hash_table_destroy (mailboxes);
+exit:
+ g_hash_table_destroy (folder_info_results);
- return TRUE;
+ g_object_unref (server);
+
+ return success;
}
static void
@@ -1769,8 +1731,7 @@ imapx_refresh_finfo (CamelSession *session,
CAMEL_SERVICE (store), cancellable, error))
goto exit;
- /* look in all namespaces */
- sync_folders (store, "", FALSE, cancellable, error);
+ sync_folders (store, NULL, 0, cancellable, error);
camel_store_summary_save (CAMEL_STORE_SUMMARY (store->summary));
@@ -1943,7 +1904,6 @@ imapx_store_get_folder_info_sync (CamelStore *store,
CamelStoreSummary *store_summary;
gboolean initial_setup = FALSE;
gboolean use_subscriptions;
- gchar *pattern = NULL;
service = CAMEL_SERVICE (store);
imapx_store = CAMEL_IMAPX_STORE (store);
@@ -1971,6 +1931,7 @@ imapx_store_get_folder_info_sync (CamelStore *store,
initial_setup = TRUE;
}
+ /* XXX I don't know why the SUBSCRIBED flag matters here. */
if (!initial_setup && flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) {
time_t time_since_last_refresh;
@@ -1992,32 +1953,15 @@ imapx_store_get_folder_info_sync (CamelStore *store,
g_object_unref (session);
}
-
- fi = get_folder_info_offline (store, top, flags, error);
- goto exit;
}
- if (*top && flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST) {
+ /* Avoid server interaction if the FAST flag is set. */
+ if (!initial_setup && flags & CAMEL_STORE_FOLDER_INFO_FAST) {
fi = get_folder_info_offline (store, top, flags, error);
goto exit;
}
- if (*top) {
- gchar *mailbox;
-
- mailbox = camel_imapx_store_summary_mailbox_from_path (
- imapx_store->summary, top);
- if (mailbox == NULL)
- mailbox = camel_imapx_store_summary_path_to_mailbox (
- imapx_store->summary, top,
- imapx_store->dir_sep);
- pattern = camel_utf8_utf7 (mailbox);
- g_free (mailbox);
- } else {
- pattern = g_strdup ("");
- }
-
- if (!sync_folders (imapx_store, pattern, TRUE, cancellable, error))
+ if (!sync_folders (imapx_store, top, flags, cancellable, error))
goto exit;
camel_store_summary_save (store_summary);
@@ -2031,8 +1975,6 @@ imapx_store_get_folder_info_sync (CamelStore *store,
exit:
g_mutex_unlock (&imapx_store->priv->get_finfo_lock);
- g_free (pattern);
-
return fi;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]