A new folder-copy implementation
- From: Philip Van Hoof <spam pvanhoof be>
- To: tinymail-devel-list gnome org
- Subject: A new folder-copy implementation
- Date: Tue, 15 May 2007 17:47:27 +0200
--
Philip Van Hoof, software developer
home: me at pvanhoof dot be
gnome: pvanhoof at gnome dot org
http://www.pvanhoof.be/blog
Index: libtinymail-camel/tny-camel-folder.c
===================================================================
--- libtinymail-camel/tny-camel-folder.c (revision 1954)
+++ libtinymail-camel/tny-camel-folder.c (working copy)
@@ -1512,266 +1512,368 @@
return TNY_CAMEL_FOLDER_GET_CLASS (self)->copy_func (self, into, new_name, del, err);
}
-static TnyFolder*
-tny_camel_folder_copy_default (TnyFolder *self, TnyFolderStore *into, const gchar *new_name, gboolean del, GError **err)
+typedef struct {
+ GList *rems;
+ GList *adds;
+ TnyFolder *created;
+} CpyRecRet;
+
+typedef struct {
+ TnyFolderStore *str;
+ TnyFolder *fol;
+} CpyEvent;
+
+static CpyEvent*
+cpy_event_new (TnyFolderStore *str, TnyFolder *fol)
{
- TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
- guint32 flags = CAMEL_STORE_FOLDER_INFO_FAST |
- CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
- GList *pending = NULL, *deleting = NULL, *l; GString *fromname=NULL, *toname=NULL;
- CamelFolderInfo *fi; const char *tmp; int fromlen;
- CamelException ex = CAMEL_EXCEPTION_INITIALISER;
- CamelStore *fromstore; const gchar *frombase;
- CamelStore *tostore; const gchar *tobase;
- GStaticRecMutex *tolock=NULL, *fromlock=NULL;
+ CpyEvent *e = g_slice_new (CpyEvent);
+ e->str = (TnyFolderStore *) g_object_ref (str);
+ e->fol = (TnyFolder *) g_object_ref (fol);
+ return e;
+}
+
+static void
+cpy_event_free (CpyEvent *e)
+{
+ g_object_unref (e->str);
+ g_object_unref (e->fol);
+ g_slice_free (CpyEvent, e);
+}
+
+static CpyRecRet*
+recurse_copy (TnyFolder *folder, TnyFolderStore *into, const gchar *new_name, gboolean del, GError **err, GList *rems, GList *adds)
+{
+ CpyRecRet *cpyr = g_slice_new0 (CpyRecRet);
+
TnyFolder *retval = NULL;
- TnyCamelFolderPriv *fpriv;
- CamelFolderInfo *iter;
- gchar *final_name;
- TnyFolderStoreChange *change;
- TnyFolderStore *old_parent;
+ TnyStoreAccount *acc_to, *acc_from;
+ TnyCamelFolderPriv *fpriv = TNY_CAMEL_FOLDER_GET_PRIVATE (folder);
+ TnyCamelFolderPriv *tpriv = TNY_CAMEL_FOLDER_GET_PRIVATE (into);
+ TnyList *headers;
- if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), err,
- TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_COPY))
- return NULL;
+ GError *nerr = NULL;
- g_assert (TNY_IS_CAMEL_FOLDER (into) || TNY_IS_CAMEL_STORE_ACCOUNT (into));
- g_assert (new_name != NULL && strlen (new_name) > 0);
+ g_static_rec_mutex_lock (fpriv->folder_lock);
+ g_static_rec_mutex_lock (tpriv->folder_lock);
- fromstore = priv->store;
- camel_object_ref (CAMEL_OBJECT (fromstore));
- frombase = priv->folder_name;
- fromlock = priv->folder_lock;
+ load_folder_no_lock (fpriv);
+ load_folder_no_lock (tpriv);
- g_assert (frombase != NULL && strlen (frombase) > 0);
+ retval = tny_folder_store_create_folder (into, new_name, &nerr);
+ if (nerr != NULL) {
+ if (retval)
+ g_object_unref (retval);
+ goto exception;
+ }
- if (TNY_IS_CAMEL_FOLDER (into))
- {
- TnyCamelFolderPriv *topriv = TNY_CAMEL_FOLDER_GET_PRIVATE (into);
- tostore = topriv->store;
- camel_object_ref (CAMEL_OBJECT (tostore));
- tobase = topriv->folder_name;
- tolock = topriv->folder_lock;
+ adds = g_list_append (adds, cpy_event_new (TNY_FOLDER_STORE (into), retval));
- } else
+ if (TNY_IS_FOLDER_STORE (folder))
{
- TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (into);
+ TnyList *folders = tny_simple_list_new ();
+ TnyIterator *iter;
- tobase = "/";
- tostore = camel_session_get_store ((CamelSession*) apriv->session,
- apriv->url_string, &ex);
+ tny_folder_store_get_folders (TNY_FOLDER_STORE (folder), folders, NULL, &nerr);
- /* TODO: a tolock */
+ if (nerr != NULL)
+ {
+ g_object_unref (folders);
+ g_object_unref (retval);
+ goto exception;
+ }
- if (camel_exception_is_set (&ex))
+ iter = tny_list_create_iterator (folders);
+ while (!tny_iterator_is_done (iter))
{
- g_set_error (err, TNY_FOLDER_ERROR,
- TNY_FOLDER_ERROR_COPY,
- camel_exception_get_description (&ex));
- camel_exception_clear (&ex);
+ TnyFolder *cur = TNY_FOLDER (tny_iterator_get_current (iter));
+ TnyFolder *mnew;
- if (tostore && CAMEL_IS_OBJECT (tostore))
- camel_object_unref (CAMEL_OBJECT (tostore));
- _tny_session_stop_operation (TNY_FOLDER_PRIV_GET_SESSION (priv));
- return NULL;
+ CpyRecRet *rt = recurse_copy (cur, TNY_FOLDER_STORE (retval),
+ tny_folder_get_name (cur), del, &nerr, rems, adds);
+
+ mnew = rt->created;
+ rems = rt->rems;
+ adds = rt->adds;
+
+ g_slice_free (CpyRecRet, rt);
+
+ if (nerr != NULL)
+ {
+ if (mnew) g_object_unref (mnew);
+ g_object_unref (cur);
+ g_object_unref (iter);
+ g_object_unref (folders);
+ g_object_unref (retval);
+ goto exception;
+ }
+
+ g_object_unref (mnew);
+ g_object_unref (cur);
+ tny_iterator_next (iter);
}
+ g_object_unref (iter);
+ g_object_unref (folders);
}
- g_assert (tobase != NULL && strlen (tobase) > 0);
+ acc_from = TNY_STORE_ACCOUNT (tny_folder_get_account (folder));
+ rems = g_list_append (rems, cpy_event_new (TNY_FOLDER_STORE (acc_from), folder));
+ g_object_unref (acc_from);
- g_static_rec_mutex_lock (fromlock);
- if (tolock)
- g_static_rec_mutex_lock (tolock);
+ headers = tny_simple_list_new ();
+ tny_folder_get_headers (folder, headers, TRUE, &nerr);
+ if (nerr != NULL) {
+ g_object_unref (headers);
+ g_object_unref (retval);
+ retval = NULL;
+ goto exception;
+ }
- if (!(fi = camel_store_get_folder_info (fromstore, frombase, flags, &ex)))
+printf ("Transfer %s to %s\n", tny_folder_get_name (folder), tny_folder_get_name (retval));
+
+ tny_folder_transfer_msgs (folder, headers, retval, del, &nerr);
+
+ if (nerr != NULL) {
+ g_object_unref (headers);
+ g_object_unref (retval);
+ retval = NULL;
goto exception;
-
- pending = g_list_append (pending, fi);
-
- toname = g_string_new ("");
- fromname = g_string_new ("");
-
- tmp = strrchr (frombase, '/');
- if (tmp == NULL)
- fromlen = 0;
+ }
+
+ acc_to = TNY_STORE_ACCOUNT (tny_folder_get_account (retval));
+ if (tny_folder_is_subscribed (folder))
+ tny_store_account_subscribe (acc_to, retval);
+ g_object_unref (acc_to);
+
+
+exception:
+
+ if (nerr != NULL)
+ g_propagate_error (err, nerr);
+
+ g_static_rec_mutex_unlock (tpriv->folder_lock);
+ g_static_rec_mutex_unlock (fpriv->folder_lock);
+
+ cpyr->created = retval;
+ cpyr->adds = adds;
+ cpyr->rems = rems;
+
+ return cpyr;
+}
+
+typedef GList * (*lstmodfunc) (GList *list, gpointer data);
+
+static GList*
+recurse_evt (TnyFolder *folder, TnyFolderStore *into, GList *list, lstmodfunc func, gboolean rem)
+{
+ TnyList *folders = tny_simple_list_new ();
+ TnyIterator *iter;
+ TnyStoreAccount *acc;
+
+ acc = TNY_STORE_ACCOUNT (tny_folder_get_account (folder));
+
+ if (rem)
+ tny_store_account_unsubscribe (acc, folder);
else
- fromlen = tmp - frombase + 1;
-
- while (pending)
{
- CamelFolderInfo *info = pending->data;
-
- pending = g_list_remove_link (pending, pending);
- while (info)
- {
- CamelFolder *fromfolder, *tofolder;
- GPtrArray *uids;
- int deleted = 0;
-
- if (info->child)
- pending = g_list_append (pending, info->child);
-
- if (tobase[0])
- g_string_printf (toname, "%s/%s", tobase, info->full_name + fromlen);
- else
- g_string_printf (toname, "%s", info->full_name + fromlen);
-
- if ((info->flags & CAMEL_FOLDER_NOSELECT) == 0)
- {
- if (tostore == fromstore && del) {
- camel_store_rename_folder (fromstore, info->full_name, toname->str, &ex);
- if (camel_exception_is_set (&ex))
- goto exception;
-
- if (camel_store_supports_subscriptions (fromstore))
- camel_store_unsubscribe_folder (fromstore, info->full_name, NULL);
-
- deleted = 1;
- } else {
- if (!(fromfolder = camel_store_get_folder (fromstore, info->full_name, 0, &ex)))
- goto exception;
-
- if (!(tofolder = camel_store_get_folder (tostore, toname->str, CAMEL_STORE_FOLDER_CREATE, &ex))) {
- camel_object_unref (fromfolder);
- goto exception;
- }
-
- uids = camel_folder_get_uids (fromfolder);
- camel_folder_transfer_messages_to (fromfolder, uids, tofolder, NULL, del, &ex);
- camel_folder_free_uids (fromfolder, uids);
-
- if (del)
- camel_folder_sync(fromfolder, TRUE, NULL);
-
- camel_object_unref (fromfolder);
- camel_object_unref (tofolder);
- }
- }
-
- if (camel_exception_is_set (&ex))
- goto exception;
- else if (del && !deleted)
- deleting = g_list_prepend (deleting, info);
-
- if (camel_store_supports_subscriptions (tostore)
- && !camel_store_folder_subscribed (tostore, toname->str))
- camel_store_subscribe_folder (tostore, toname->str, NULL);
-
- info = info->next;
- }
+ if (tny_folder_is_subscribed (folder))
+ tny_store_account_subscribe (acc, folder);
}
- l = deleting;
- while (l)
+ g_object_unref (acc);
+
+ list = func (list, cpy_event_new (TNY_FOLDER_STORE (into), folder));
+
+
+ tny_folder_store_get_folders (TNY_FOLDER_STORE (folder), folders, NULL, NULL);
+
+ iter = tny_list_create_iterator (folders);
+ while (!tny_iterator_is_done (iter))
{
- CamelFolderInfo *info = l->data;
-
- if (camel_store_supports_subscriptions (fromstore))
- camel_store_unsubscribe_folder (fromstore, info->full_name, NULL);
-
- camel_store_delete_folder (fromstore, info->full_name, NULL);
- l = l->next;
+ TnyFolder *cur = TNY_FOLDER (tny_iterator_get_current (iter));
+
+ recurse_evt (cur, TNY_FOLDER_STORE (folder), list, func, rem);
+
+ g_object_unref (cur);
+ tny_iterator_next (iter);
}
+ g_object_unref (iter);
+ g_object_unref (folders);
- final_name = g_strdup_printf ("%s/%s", tobase, new_name);
- iter = camel_store_get_folder_info (tostore, final_name,
- CAMEL_STORE_FOLDER_INFO_FAST|CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL,&ex);
- g_free (final_name);
+ return list;
+}
- if (camel_exception_is_set (&ex))
+
+static void
+notify_folder_store_observers_about_for_store_acc (TnyFolderStore *self, TnyFolderStoreChange *change)
+{
+ TnyCamelStoreAccountPriv *priv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self);
+ TnyIterator *iter;
+
+ if (!priv->sobservers)
+ return;
+
+ iter = tny_list_create_iterator (priv->sobservers);
+ while (!tny_iterator_is_done (iter))
{
- if (iter && CAMEL_IS_STORE (tostore))
- camel_store_free_folder_info (tostore, iter);
-
- goto exception;
+ TnyFolderStoreObserver *observer = TNY_FOLDER_STORE_OBSERVER (tny_iterator_get_current (iter));
+ tny_folder_store_observer_update (observer, change);
+ g_object_unref (G_OBJECT (observer));
+ tny_iterator_next (iter);
}
+ g_object_unref (G_OBJECT (iter));
+}
- old_parent = tny_folder_get_folder_store (self);
+static void
+notify_folder_observers_about_copy (GList *adds, GList *rems, gboolean del)
+{
+ while (rems)
+ {
+ CpyEvent *evt = rems->data;
- if (tostore == fromstore && del) {
- retval = self;
- /* No need to notify the folder if there was not an
- * actual change in the short (visual) name */
+ if (del) {
+ TnyFolderStoreChange *change = tny_folder_store_change_new (evt->str);
+ tny_folder_store_change_add_removed_folder (change, evt->fol);
- if (strcmp (tny_folder_get_name (self), new_name)) {
- TnyFolderChange *change;
-
- change = tny_folder_change_new (self);
- tny_folder_change_set_rename (change, new_name);
- notify_folder_observers_about (self, change);
+ if (TNY_IS_CAMEL_STORE_ACCOUNT (evt->str))
+ notify_folder_store_observers_about_for_store_acc (evt->str, change);
+ else
+ notify_folder_store_observers_about (evt->str, change);
+
g_object_unref (G_OBJECT (change));
}
- } else {
- retval = _tny_camel_folder_new ();
-
- fpriv = TNY_CAMEL_FOLDER_GET_PRIVATE (retval);
- camel_object_ref (CAMEL_OBJECT (tostore));
- fpriv->store = tostore;
+
+ g_print ("R: %s\n",
+ tny_folder_get_name (evt->fol));
+
+ cpy_event_free (evt);
+ rems = g_list_next (rems);
}
- /* Notify the deletion before the addition because otherwise
- * we could delete the recently created folder instead of the
- * old one. */
+ g_list_free (rems);
- if (del) {
- TnyFolderStoreChange *change = tny_folder_store_change_new (old_parent);
- tny_folder_store_change_add_removed_folder (change, self);
- notify_folder_store_observers_about (old_parent, change);
+ while (adds)
+ {
+ TnyFolderStoreChange *change;
+ CpyEvent *evt = adds->data;
+
+ change = tny_folder_store_change_new (evt->str);
+ tny_folder_store_change_add_created_folder (change, evt->fol);
+
+ if (TNY_IS_CAMEL_STORE_ACCOUNT (evt->str))
+ notify_folder_store_observers_about_for_store_acc (evt->str, change);
+ else
+ notify_folder_store_observers_about (evt->str, change);
+
g_object_unref (G_OBJECT (change));
+
+ g_print ("A: %s\n",
+ tny_folder_get_name (evt->fol));
+
+ cpy_event_free (evt);
+ adds = g_list_next (adds);
}
- _tny_camel_folder_set_folder_info (into, TNY_CAMEL_FOLDER (retval), iter);
+ g_list_free (adds);
+}
- /* Notify addition */
- change = tny_folder_store_change_new (into);
- tny_folder_store_change_add_created_folder (change, retval);
- notify_folder_store_observers_about (into, change);
- g_object_unref (G_OBJECT (change));
+static TnyFolder*
+tny_camel_folder_copy_default (TnyFolder *self, TnyFolderStore *into, const gchar *new_name, gboolean del, GError **err)
+{
+ TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+ TnyFolder *retval;
+ gboolean succeeded = FALSE;
+ TnyAccount *a, *b;
+ GError *nerr = NULL;
- g_object_unref (G_OBJECT (old_parent));
- camel_object_unref (CAMEL_OBJECT (tostore));
- camel_object_unref (CAMEL_OBJECT (fromstore));
+ GList *rems=NULL, *adds=NULL;
- goto noexception;
+ if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), err,
+ TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_COPY))
+ return NULL;
-exception:
- if (camel_exception_is_set (&ex))
+ g_static_rec_mutex_lock (priv->folder_lock);
+
+ if (TNY_IS_CAMEL_FOLDER (into) || TNY_IS_CAMEL_STORE_ACCOUNT (into))
{
- g_set_error (err, TNY_FOLDER_ERROR,
- TNY_FOLDER_ERROR_COPY,
- camel_exception_get_description (&ex));
- camel_exception_clear (&ex);
+ a = tny_folder_get_account (self);
+
+ if (TNY_IS_FOLDER (into))
+ b = tny_folder_get_account (TNY_FOLDER (into));
+ else
+ b = g_object_ref (into);
- if (fromstore && CAMEL_IS_OBJECT (fromstore))
- camel_object_unref (CAMEL_OBJECT (fromstore));
+ if (del && (a == b))
+ {
+ TnyCamelFolderPriv *rpriv;
+ TnyCamelFolderPriv *tpriv = TNY_CAMEL_FOLDER_GET_PRIVATE (into);
+ TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (a);
+ CamelException ex = CAMEL_EXCEPTION_INITIALISER;
+ gchar *from, *to;
- if (tostore && CAMEL_IS_OBJECT (tostore))
- camel_object_unref (CAMEL_OBJECT (tostore));
+ load_folder_no_lock (priv);
+ load_folder_no_lock (tpriv);
+
+ from = priv->folder_name;
+
+ if (TNY_IS_CAMEL_STORE_ACCOUNT (into))
+ to = g_strdup (new_name);
+ else
+ to = g_strdup_printf ("%s/%s", tpriv->folder_name, new_name);
+
+printf ("Rename %s to %s\n", from, to);
+
+ camel_store_rename_folder (CAMEL_STORE (apriv->service), from, to, &ex);
+
+ if (!camel_exception_is_set (&ex))
+ {
+ rems = recurse_evt (self, TNY_FOLDER_STORE (a),
+ rems, g_list_prepend, TRUE);
+
+ adds = recurse_evt (self, TNY_FOLDER_STORE (into),
+ adds, g_list_append, FALSE);
+
+ retval = g_object_ref (self);
+ rpriv = TNY_CAMEL_FOLDER_GET_PRIVATE (retval);
+ g_free (rpriv->folder_name);
+ rpriv->folder_name = g_strdup (to);
+ succeeded = TRUE;
+ }
+ g_free (to);
+ }
+ g_object_unref (a);
+ g_object_unref (b);
}
-noexception:
+ if (!succeeded)
+ {
+ CpyRecRet *cpyr = recurse_copy (self, into, new_name, del, &nerr, adds, rems);
+ retval = cpyr->created;
+ adds = cpyr->adds;
+ rems = cpyr->rems;
+ g_slice_free (CpyRecRet, cpyr);
+ }
- camel_store_free_folder_info (fromstore, fi);
- g_list_free (deleting);
+ if (nerr != NULL)
+ g_propagate_error (err, nerr);
+ else
+ notify_folder_observers_about_copy (adds, rems, del);
- if (toname)
- g_string_free (toname, TRUE);
- if (fromname)
- g_string_free (fromname, TRUE);
+ g_static_rec_mutex_unlock (priv->folder_lock);
- if (tolock)
- g_static_rec_mutex_unlock (tolock);
- g_static_rec_mutex_unlock (fromlock);
-
_tny_session_stop_operation (TNY_FOLDER_PRIV_GET_SESSION (priv));
return retval;
}
+
+
+
+
typedef struct
{
TnyFolder *self;
+ TnyFolderStore *from;
TnyFolderStore *into;
gchar *new_name;
gboolean delete_originals;
@@ -1780,21 +1882,86 @@
guint depth;
TnyCopyFolderCallback callback;
TnyStatusCallback status_callback;
+ TnyFolder *new_folder;
TnySessionCamel *session;
TnyIdleStopper *stopper;
gboolean cancelled;
} CopyFolderInfo;
+static void
+inform_observers_about_folder_copy (TnyFolder *self, TnyFolderStore *from, TnyFolderStore *to, gboolean del_orig, const gchar *new_name, TnyFolder *new_folder)
+{
+ TnyFolderStoreChange *tochange = tny_folder_store_change_new (to);
+ TnyFolderStoreChange *fromchange = tny_folder_store_change_new (from);
+ TnyFolderChange *origchange = tny_folder_change_new (self);
+/* TnyList *folders = tny_simple_list_new (); */
+/* TnyIterator *iter; */
+
+ /* Notify change name (if neccesary) */
+ if (to == from && del_orig) {
+ if (strcmp (tny_folder_get_name (self), new_name)) {
+ tny_folder_change_set_rename (origchange, new_name);
+ notify_folder_observers_about (self, origchange);
+ }
+ }
+
+ /* Notify deletion (if neccesary) */
+ if (del_orig) {
+ tny_folder_store_change_add_removed_folder (fromchange, self);
+ notify_folder_store_observers_about (from, fromchange);
+ }
+
+ /* Notify addition */
+ tny_folder_store_change_add_created_folder (tochange, new_folder);
+ notify_folder_store_observers_about (to, tochange);
+
+ /* Notify subfolders addition */
+/* tny_folder_store_get_folders (TNY_FOLDER_STORE(self), folders, NULL, NULL); */
+/* iter = tny_list_create_iterator (folders); */
+/* while (!tny_iterator_is_done (iter)) { */
+
+/* TnyFolder *folder = (TnyFolder*) tny_iterator_get_current (iter); */
+/* TnyFolderStoreChange *change = tny_folder_store_change_new (TNY_FOLDER_STORE(self)); */
+/* tny_folder_store_change_add_created_folder (change, folder); */
+/* notify_folder_store_observers_about (TNY_FOLDER_STORE(self), change); */
+
+/* tny_iterator_next (iter); */
+
+/* g_object_unref (G_OBJECT (folder)); */
+/* g_object_unref (G_OBJECT (change)); */
+/* } */
+
+ /* Free */
+/* g_object_unref (G_OBJECT (iter)); */
+/* g_object_unref (G_OBJECT (folders)); */
+ g_object_unref (G_OBJECT (tochange));
+ g_object_unref (G_OBJECT (fromchange));
+ g_object_unref (G_OBJECT (origchange));
+}
+
static void
tny_camel_folder_copy_async_destroyer (gpointer thr_user_data)
{
CopyFolderInfo *info = (CopyFolderInfo *) thr_user_data;
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
+ TnyCamelFolderPriv *priv_from = TNY_CAMEL_FOLDER_GET_PRIVATE (info->from);
+ TnyCamelFolderPriv *priv_to = TNY_CAMEL_FOLDER_GET_PRIVATE (info->into);
+ inform_observers_about_folder_copy (info->self,
+ info->from,
+ info->into,
+ info->delete_originals,
+ info->new_name,
+ info->new_folder);
+
/* thread reference */
_tny_camel_folder_unreason (priv);
g_object_unref (G_OBJECT (info->self));
+ _tny_camel_folder_unreason (priv_to);
+ g_object_unref (G_OBJECT (info->into));
+ _tny_camel_folder_unreason (priv_from);
+ g_object_unref (G_OBJECT (info->from));
if (info->err)
g_error_free (info->err);
@@ -1853,13 +2020,28 @@
{
CopyFolderInfo *info = thr_user_data;
TnyFolder *self = info->self;
+ TnyFolder *new_folder = NULL;
+ TnyFolderStore *into = info->into;
+ TnyFolderStore *from = info->from;
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+ TnyCamelFolderPriv *priv_dst = TNY_CAMEL_FOLDER_GET_PRIVATE (into);
+ TnyCamelFolderPriv *priv_from = TNY_CAMEL_FOLDER_GET_PRIVATE (from);
TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv->account);
CamelException ex = CAMEL_EXCEPTION_INITIALISER;
GError *err = NULL;
g_static_rec_mutex_lock (priv->folder_lock);
+ /* Load oldparent foler */
+ if (!load_folder_no_lock (priv_from))
+ {
+ tny_camel_folder_copy_async_destroyer (info);
+ g_static_rec_mutex_unlock (priv->folder_lock);
+ g_thread_exit (NULL);
+ return NULL;
+ }
+
+ /* Load directory to move */
if (!load_folder_no_lock (priv))
{
tny_camel_folder_copy_async_destroyer (info);
@@ -1868,6 +2050,15 @@
return NULL;
}
+ /* Load new_parent foler */
+ if (!load_folder_no_lock (priv_dst))
+ {
+ tny_camel_folder_copy_async_destroyer (info);
+ g_static_rec_mutex_unlock (priv->folder_lock);
+ g_thread_exit (NULL);
+ return NULL;
+ }
+
info->cancelled = FALSE;
/* start camel operations */
@@ -1876,17 +2067,16 @@
"Fetching summary information for new messages in folder");
/* Do work */
- tny_camel_folder_copy (self, info->into, info->new_name, info->delete_originals, &info->err);
+ new_folder = tny_camel_folder_copy (self, info->into, info->new_name, info->delete_originals, &info->err);
- /* Check cancellation and fill data */
+ /* Check cancelation and stop operation */
info->cancelled = camel_operation_cancel_check (apriv->cancel);
- priv->cached_length = camel_folder_get_message_count (priv->folder);
+ _tny_camel_account_stop_camel_operation (TNY_CAMEL_ACCOUNT (priv->account));
- if (G_LIKELY (priv->folder) && CAMEL_IS_FOLDER (priv->folder) && G_LIKELY (priv->has_summary_cap))
- priv->unread_length = (guint)camel_folder_get_unread_message_count (priv->folder);
+ /* Get data */
+ info->new_folder = new_folder;
/* Stop operation and check errors */
- _tny_camel_account_stop_camel_operation (TNY_CAMEL_ACCOUNT (priv->account));
info->err = NULL;
if (camel_exception_is_set (&ex))
{
@@ -1915,6 +2105,10 @@
} else { /* Thread reference */
g_object_unref (G_OBJECT (self));
_tny_camel_folder_unreason (priv);
+ g_object_unref (G_OBJECT (into));
+ _tny_camel_folder_unreason (priv_dst);
+ g_object_unref (G_OBJECT (from));
+ _tny_camel_folder_unreason (priv_from);
}
g_thread_exit (NULL);
@@ -1934,7 +2128,10 @@
CopyFolderInfo *info = NULL;
GThread *thread = NULL;
GError *err = NULL;
+ TnyFolderStore *from = NULL;
TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+ TnyCamelFolderPriv *priv_to = TNY_CAMEL_FOLDER_GET_PRIVATE (into);
+ TnyCamelFolderPriv *priv_from = NULL;
if (!_tny_session_check_operation (TNY_FOLDER_PRIV_GET_SESSION(priv), &err,
TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_REFRESH))
@@ -1945,9 +2142,12 @@
return;
}
+ from = tny_folder_get_folder_store (self);
+ priv_from = TNY_CAMEL_FOLDER_GET_PRIVATE (from);
+
/* Idle info for the status callback: */
-
info = g_slice_new (CopyFolderInfo);
+ info->from = from;
info->into = into;
info->new_name = g_strdup(new_name);
info->delete_originals = del;
@@ -1966,8 +2166,11 @@
info->stopper = tny_idle_stopper_new();
/* thread reference */
- g_object_ref (G_OBJECT (self));
+ g_object_ref (G_OBJECT (info->self));
_tny_camel_folder_reason (priv);
+ g_object_ref (G_OBJECT (info->into));
+ _tny_camel_folder_reason (priv_to);
+ _tny_camel_folder_reason (priv_from);
/* This will cause the idle status callback to be called,
* via _tny_camel_account_start_camel_operation,
@@ -2000,6 +2203,7 @@
gboolean cancelled;
} TransferMsgsInfo;
+
static void
inform_observers_about_transfer (TnyFolder *from, TnyFolder *to, gboolean del_orig, TnyList *headers, gint from_all, gint to_all, gint from_unread, gint to_unread)
{
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c (revision 1954)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c (working copy)
@@ -2594,12 +2594,73 @@
}
}
+static int
+make_path (char *path, int nmode, int parent_mode)
+{
+ int oumask;
+ struct stat sb;
+ char *p, *npath;
+
+ if (stat (path, &sb) == 0)
+ {
+ if (S_ISDIR (sb.st_mode) == 0)
+ return 1;
+ if (chmod (path, nmode))
+ return 1;
+ return 0;
+ }
+
+ oumask = umask (0);
+ npath = g_strdup (path); /* So we can write to it. */
+
+ /* Check whether or not we need to do anything with intermediate dirs. */
+
+ /* Skip leading slashes. */
+ p = npath;
+ while (*p == '/')
+ p++;
+
+ while (p = strchr (p, '/'))
+ {
+ *p = '\0';
+ if (stat (npath, &sb) != 0)
+ {
+ if (mkdir (npath, parent_mode))
+ {
+ free (npath);
+ return 1;
+ }
+ }
+ else if (S_ISDIR (sb.st_mode) == 0)
+ {
+ free (npath);
+ return 1;
+ }
+
+ *p++ = '/'; /* restore slash */
+ while (*p == '/')
+ p++;
+ }
+
+ /* Create the final directory component. */
+ if (stat (npath, &sb) && mkdir (npath, nmode))
+ {
+ free (npath);
+ return 1;
+ }
+
+ free (npath);
+ return 0;
+}
+
+
static void
rename_folder (CamelStore *store, const char *old_name, const char *new_name_in, CamelException *ex)
{
CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
CamelImapResponse *response;
char *oldpath, *newpath, *storage_path;
+ char *tpath, *lslash;
CAMEL_SERVICE_REC_LOCK (imap_store, connect_lock);
@@ -2644,6 +2705,15 @@
g_free(storage_path);
/* So do we care if this didn't work? Its just a cache? */
+ tpath = g_strdup (newpath);
+ /* TNY TODO: Win32 portage needed */
+ lslash = strrchr (tpath, '/');
+ if (lslash) {
+ lslash = '\0';
+ make_path (tpath, S_IRWXU, S_IRWXU);
+ }
+ g_free (tpath);
+
if (g_rename (oldpath, newpath) == -1) {
g_warning ("Could not rename message cache '%s' to '%s': %s: cache reset",
oldpath, newpath, strerror (errno));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]