aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog34
-rw-r--r--camel/camel-folder.c69
-rw-r--r--camel/camel-folder.h2
-rw-r--r--camel/camel-store.c100
-rw-r--r--camel/camel-store.h5
-rw-r--r--camel/camel-vee-folder.c15
-rw-r--r--camel/camel-vee-store.c34
-rw-r--r--camel/providers/imap/camel-imap-store.c23
-rw-r--r--camel/providers/local/camel-local-folder.c28
9 files changed, 227 insertions, 83 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 92e89a5c55..6776cb0b34 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,37 @@
+2001-10-27 <NotZed@Ximian.com>
+
+ * providers/imap/camel-imap-store.c (rename_folder): Finished
+ implementation.
+
+ * providers/local/camel-local-folder.c (local_rename): Implement
+ local rename of folder objects.
+
+2001-10-26 <NotZed@Ximian.com>
+
+ * camel-vee-folder.c (camel_vee_folder_class_init): Hook into
+ rename function.
+ (vee_rename): Implement the veefolder rename function.
+ (camel_vee_folder_class_init):
+ (folder_changed_change): Kill a warning with a cast.
+
+ * camel-vee-store.c (vee_rename_folder): Emit a folder_renamed
+ event properly, also call parent to do some rename stuff.
+
+ * camel-store.h: Added a CamelRenameInfo for the rename event.
+
+ * camel-folder.c (camel_folder_rename): New function to rename a
+ folder object.
+ (camel_folder_class_init): Added a renamed event.
+ (folder_rename): Default impl, set full_name, and set name
+ assuming the dir separator is '/'.
+
+ * camel-store.c (camel_store_class_init): Added folder_renamed
+ event.
+ (camel_store_rename_folder): Rename an active folder object if we
+ have one, and update the folder table.
+ (rename_folder): Make a default implementation that handles
+ updating the folder tree.
+
2001-10-26 Jeffrey Stedfast <fejj@ximian.com>
* providers/imap/camel-imap-store.c (delete_folder): Don't bother
diff --git a/camel/camel-folder.c b/camel/camel-folder.c
index f28572f8ba..9bc38df846 100644
--- a/camel/camel-folder.c
+++ b/camel/camel-folder.c
@@ -87,29 +87,21 @@ static GPtrArray *get_summary (CamelFolder *folder);
static void free_summary (CamelFolder *folder,
GPtrArray *array);
-static CamelMimeMessage *get_message (CamelFolder *folder,
- const gchar *uid,
- CamelException *ex);
+static CamelMimeMessage *get_message (CamelFolder *folder, const gchar *uid, CamelException *ex);
-static CamelMessageInfo *get_message_info (CamelFolder *folder, const char *uid);
-static void free_message_info (CamelFolder *folder, CamelMessageInfo *info);
-static void ref_message_info (CamelFolder *folder, CamelMessageInfo *info);
+static CamelMessageInfo *get_message_info (CamelFolder *folder, const char *uid);
+static void free_message_info (CamelFolder *folder, CamelMessageInfo *info);
+static void ref_message_info (CamelFolder *folder, CamelMessageInfo *info);
static GPtrArray *search_by_expression (CamelFolder *folder, const char *exp, CamelException *ex);
static GPtrArray *search_by_uids (CamelFolder *folder, const char *exp, GPtrArray *uids, CamelException *ex);
static void search_free (CamelFolder * folder, GPtrArray *result);
-static void copy_messages_to (CamelFolder *source,
- GPtrArray *uids,
- CamelFolder *dest,
- CamelException *ex);
+static void copy_messages_to (CamelFolder *source, GPtrArray *uids, CamelFolder *dest, CamelException *ex);
+static void move_messages_to (CamelFolder *source, GPtrArray *uids, CamelFolder *dest, CamelException *ex);
-static void move_messages_to (CamelFolder *source,
- GPtrArray *uids,
- CamelFolder *dest,
- CamelException *ex);
-
-static void delete (CamelFolder *folder);
+static void delete (CamelFolder *folder);
+static void folder_rename (CamelFolder *folder, const char *new);
static void freeze (CamelFolder *folder);
static void thaw (CamelFolder *folder);
@@ -159,6 +151,7 @@ camel_folder_class_init (CamelFolderClass *camel_folder_class)
camel_folder_class->copy_messages_to = copy_messages_to;
camel_folder_class->move_messages_to = move_messages_to;
camel_folder_class->delete = delete;
+ camel_folder_class->rename = folder_rename;
camel_folder_class->freeze = freeze;
camel_folder_class->thaw = thaw;
camel_folder_class->is_frozen = is_frozen;
@@ -169,6 +162,7 @@ camel_folder_class_init (CamelFolderClass *camel_folder_class)
camel_object_class_declare_event (camel_object_class,
"message_changed", message_changed);
camel_object_class_declare_event (camel_object_class, "deleted", NULL);
+ camel_object_class_declare_event (camel_object_class, "renamed", NULL);
}
static void
@@ -1324,7 +1318,7 @@ delete (CamelFolder *folder)
* camel_folder_delete:
* @folder: folder
*
- * Marks a folder as deleted and performs any required cleanup.
+ * Marks a folder object as deleted and performs any required cleanup.
**/
void
camel_folder_delete (CamelFolder *folder)
@@ -1340,13 +1334,50 @@ camel_folder_delete (CamelFolder *folder)
folder->folder_flags |= CAMEL_FOLDER_HAS_BEEN_DELETED;
CF_CLASS (folder)->delete (folder);
-
+
CAMEL_FOLDER_UNLOCK (folder, lock);
-
+
camel_object_trigger_event (CAMEL_OBJECT (folder), "deleted", NULL);
}
static void
+folder_rename (CamelFolder *folder, const char *new)
+{
+ char *tmp;
+
+ printf("CamelFolder:rename('%s')\n", new);
+
+ g_free(folder->full_name);
+ folder->full_name = g_strdup(new);
+ g_free(folder->name);
+ tmp = strrchr(new, '/');
+ folder->name = g_strdup(tmp?tmp+1:new);
+}
+
+/**
+ * camel_folder_rename:
+ * @folder:
+ * @new:
+ *
+ * Mark an active folder object as renamed.
+ *
+ * NOTE: This is an internal function used by camel stores, no locking
+ * is performed on the folder.
+ **/
+void
+camel_folder_rename(CamelFolder *folder, const char *new)
+{
+ char *old;
+
+ old = g_strdup(folder->full_name);
+
+ CF_CLASS (folder)->rename(folder, new);
+
+ camel_object_trigger_event (CAMEL_OBJECT (folder), "renamed", old);
+ g_free(old);
+}
+
+static void
freeze (CamelFolder *folder)
{
CAMEL_FOLDER_LOCK(folder, change_lock);
diff --git a/camel/camel-folder.h b/camel/camel-folder.h
index 22398b6436..4ba36e9d03 100644
--- a/camel/camel-folder.h
+++ b/camel/camel-folder.h
@@ -156,6 +156,7 @@ typedef struct {
CamelException *ex);
void (*delete) (CamelFolder *folder);
+ void (*rename) (CamelFolder *folder, const char *newname);
void (*freeze) (CamelFolder *folder);
void (*thaw) (CamelFolder *folder);
@@ -273,6 +274,7 @@ void camel_folder_move_messages_to (CamelFolder *source,
CamelException *ex);
void camel_folder_delete (CamelFolder *folder);
+void camel_folder_rename (CamelFolder *folder, const char *new);
/* stop/restart getting events */
void camel_folder_freeze (CamelFolder *folder);
diff --git a/camel/camel-store.c b/camel/camel-store.c
index 85f618be5b..f4b15a045c 100644
--- a/camel/camel-store.c
+++ b/camel/camel-store.c
@@ -104,6 +104,7 @@ camel_store_class_init (CamelStoreClass *camel_store_class)
camel_object_class_declare_event(camel_object_class, "folder_created", NULL);
camel_object_class_declare_event(camel_object_class, "folder_deleted", NULL);
+ camel_object_class_declare_event(camel_object_class, "folder_renamed", NULL);
camel_object_class_declare_event(camel_object_class, "folder_subscribed", NULL);
camel_object_class_declare_event(camel_object_class, "folder_unsubscribed", NULL);
}
@@ -267,7 +268,6 @@ camel_store_get_folder (CamelStore *store, const char *folder_name, guint32 flag
return folder;
}
-
static CamelFolderInfo *
create_folder (CamelStore *store, const char *parent_name,
const char *folder_name, CamelException *ex)
@@ -365,15 +365,32 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name, CamelExce
CAMEL_STORE_UNLOCK(store, folder_lock);
}
-
static void
-rename_folder (CamelStore *store, const char *old_name,
- const char *new_name, CamelException *ex)
+rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex)
{
w(g_warning ("CamelStore::rename_folder not implemented for `%s'",
camel_type_to_name (CAMEL_OBJECT_GET_TYPE (store))));
}
+struct _get_info {
+ CamelStore *store;
+ GPtrArray *folders;
+ const char *old;
+ const char *new;
+};
+
+static void
+get_subfolders(char *key, CamelFolder *folder, struct _get_info *info)
+{
+ /* If this is a subfolder of the one to be renamed, we need to get it, AND lock it */
+ if (strncmp(folder->full_name, info->old, strlen(info->old)) == 0) {
+ d(printf("Found subfolder of '%s' == '%s'\n", info->old, folder->full_name));
+ camel_object_ref((CamelObject *)folder);
+ g_ptr_array_add(info->folders, folder);
+ CAMEL_FOLDER_LOCK(folder, lock);
+ }
+}
+
/**
* camel_store_rename_folder:
* @store: a CamelStore
@@ -387,32 +404,79 @@ void
camel_store_rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex)
{
char *key;
- CamelFolder *folder;
+ CamelFolder *folder, *oldfolder;
+ struct _get_info info = { store, NULL, old_name, new_name };
+ int i;
+
+ printf("store rename folder '%s' '%s'\n", old_name, new_name);
if (strcmp(old_name, new_name) == 0)
return;
+ info.folders = g_ptr_array_new();
+
CAMEL_STORE_LOCK(store, folder_lock);
+
+ /* If the folder is open (or any subfolders of the open folder)
+ We need to rename them atomically with renaming the actual folder path */
+ if (store->folders) {
+ CAMEL_STORE_LOCK(store, cache_lock);
+ /* Get all subfolders that are about to have their name changed */
+ g_hash_table_foreach(store->folders, (GHFunc)get_subfolders, &info);
+ CAMEL_STORE_UNLOCK(store, cache_lock);
+ }
+
+ /* Now try the real rename (will emit renamed event) */
CS_CLASS (store)->rename_folder (store, old_name, new_name, ex);
-
- /* remove the old name from the cache if it is there */
- CAMEL_STORE_LOCK(store, cache_lock);
- if (g_hash_table_lookup_extended(store->folders, old_name, (void **)&key, (void **)&folder)) {
- g_hash_table_remove(store->folders, key);
- g_free(key);
-
- camel_object_ref (CAMEL_OBJECT (folder));
+
+ /* If it worked, update all open folders/unlock them */
+ if (!camel_exception_is_set(ex)) {
+ guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
+ CamelRenameInfo reninfo;
+
+ /* Emit changed signal */
+ if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
+ flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
+ reninfo.old_base = (char *)old_name;
+ reninfo.new = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder_info(store, new_name, flags, ex);
+ if (info.new != NULL) {
+ camel_object_trigger_event(CAMEL_OBJECT(store), "folder_renamed", &reninfo);
+ ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->free_folder_info(store, reninfo.new);
+ }
+
+ CAMEL_STORE_LOCK(store, cache_lock);
+ for (i=0;i<info.folders->len;i++) {
+ char *new;
+
+ folder = info.folders->pdata[i];
+
+ new = g_strdup_printf("%s%s", new_name, folder->full_name+strlen(old_name));
+
+ if (g_hash_table_lookup_extended(store->folders, folder->full_name, (void **)&key, (void **)&oldfolder)) {
+ g_hash_table_remove(store->folders, key);
+ g_free(key);
+ g_hash_table_insert(store->folders, new, oldfolder);
+ }
+
+ camel_folder_rename(folder, new);
+
+ CAMEL_FOLDER_UNLOCK(folder, lock);
+ camel_object_unref((CamelObject *)folder);
+ }
CAMEL_STORE_UNLOCK(store, cache_lock);
-
- if (store->vtrash)
- camel_vee_folder_remove_folder (CAMEL_VEE_FOLDER (store->vtrash), folder);
- camel_object_unref (CAMEL_OBJECT (folder));
} else {
- CAMEL_STORE_UNLOCK(store, cache_lock);
+ /* Failed, just unlock our folders for re-use */
+ for (i=0;i<info.folders->len;i++) {
+ folder = info.folders->pdata[i];
+ CAMEL_FOLDER_UNLOCK(folder, lock);
+ camel_object_unref((CamelObject *)folder);
+ }
}
CAMEL_STORE_UNLOCK(store, folder_lock);
+
+ g_ptr_array_free(info.folders, TRUE);
}
diff --git a/camel/camel-store.h b/camel/camel-store.h
index df69505e62..157bc196a0 100644
--- a/camel/camel-store.h
+++ b/camel/camel-store.h
@@ -51,6 +51,11 @@ typedef struct _CamelFolderInfo {
int unread_message_count;
} CamelFolderInfo;
+/* Structure of rename event's event_data */
+typedef struct _CamelRenameInfo {
+ char *old_base;
+ struct _CamelFolderInfo *new;
+} CamelRenameInfo;
#define CAMEL_STORE_TYPE (camel_store_get_type ())
#define CAMEL_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_STORE_TYPE, CamelStore))
diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c
index 7e31e94cb9..dccc76c369 100644
--- a/camel/camel-vee-folder.c
+++ b/camel/camel-vee-folder.c
@@ -62,6 +62,7 @@ static GPtrArray *vee_search_by_uids(CamelFolder *folder, const char *expression
static void vee_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set);
static void vee_set_message_user_flag (CamelFolder *folder, const char *uid, const char *name, gboolean value);
+static void vee_rename(CamelFolder *folder, const char *new);
static void camel_vee_folder_class_init (CamelVeeFolderClass *klass);
static void camel_vee_folder_init (CamelVeeFolder *obj);
@@ -130,6 +131,8 @@ camel_vee_folder_class_init (CamelVeeFolderClass *klass)
folder_class->set_message_flags = vee_set_message_flags;
folder_class->set_message_user_flag = vee_set_message_user_flag;
+
+ folder_class->rename = vee_rename;
}
static void
@@ -749,6 +752,16 @@ vee_move_messages_to (CamelFolder *folder, GPtrArray *uids, CamelFolder *dest, C
}
}
+static void vee_rename(CamelFolder *folder, const char *new)
+{
+ CamelVeeFolder *vf = (CamelVeeFolder *)folder;
+
+ g_free(vf->vname);
+ vf->vname = g_strdup(new);
+
+ ((CamelFolderClass *)camel_vee_folder_parent)->rename(folder, new);
+}
+
/* ********************************************************************** *
utility functions */
@@ -1320,7 +1333,7 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg)
strcpy(vuid+8, uid);
vinfo = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, vuid);
if (vinfo == NULL)
- g_ptr_array_add(newchanged, uid);
+ g_ptr_array_add(newchanged, (char *)uid);
else
camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo);
}
diff --git a/camel/camel-vee-store.c b/camel/camel-vee-store.c
index 4530c34ee2..1d9a5c61d4 100644
--- a/camel/camel-vee-store.c
+++ b/camel/camel-vee-store.c
@@ -27,6 +27,8 @@
#include <string.h>
+#define d(x)
+
static CamelFolder *vee_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex);
static void vee_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex);
static void vee_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex);
@@ -290,7 +292,8 @@ static void
vee_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex)
{
CamelFolder *folder;
- char *key, *oldname, *full_oldname;
+
+ d(printf("vee rename folder '%s' '%s'\n", old, new));
if (strcmp(old, CAMEL_UNMATCHED_NAME) == 0) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
@@ -298,31 +301,12 @@ vee_rename_folder(CamelStore *store, const char *old, const char *new, CamelExce
return;
}
+ /* See if it exists, for vfolders, all folders are in the folders hash */
CAMEL_STORE_LOCK(store, cache_lock);
- if (g_hash_table_lookup_extended(store->folders, old, (void **)&key, (void **)&folder)) {
- g_hash_table_remove(store->folders, key);
- g_free(key);
-
- /* this should really be atomic */
- oldname = folder->name;
- full_oldname = folder->full_name;
- key = folder->name;
- folder->full_name = g_strdup(new);
- key = strrchr(new, '/');
- key = key?key+1:(char *)new;
- folder->name = g_strdup(key);
- g_hash_table_insert(store->folders, g_strdup(new), folder);
-
- g_free(oldname);
- g_free(full_oldname);
- CAMEL_STORE_UNLOCK(store, cache_lock);
-
-
- } else {
- CAMEL_STORE_UNLOCK(store, cache_lock);
-
+ if ((folder = g_hash_table_lookup(store->folders, old)) == NULL) {
camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
- _("Cannot rename folder: %s: No such folder"), new);
+ _("Cannot rename folder: %s: No such folder"), old);
}
-}
+ CAMEL_STORE_UNLOCK(store, cache_lock);
+}
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 32899b20e5..1fea5a27b9 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -1103,18 +1103,11 @@ static void
rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex)
{
CamelImapStore *imap_store = CAMEL_IMAP_STORE (store);
- CamelFolderInfo *old_fi, *new_fi;
CamelImapResponse *response;
-
+
if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
return;
- old_fi = get_folder_info_online (store, old_name, CAMEL_STORE_FOLDER_INFO_FAST |
- CAMEL_STORE_FOLDER_INFO_RECURSIVE, ex);
-
- if (old_fi == NULL)
- return;
-
/* make sure this folder isn't currently SELECTed - it's
actually possible to rename INBOX but if you do another
INBOX will immediately be created by the server */
@@ -1129,20 +1122,10 @@ rename_folder (CamelStore *store, const char *old_name, const char *new_name, Ca
} else
return;
- response = camel_imap_command (imap_store, NULL, ex, "RENAME %F %F",
- old_name, new_name);
+ response = camel_imap_command(imap_store, NULL, ex, "RENAME %F %F", old_name, new_name);
- if (response) {
+ if (response)
camel_imap_response_free (imap_store, response);
-
- new_fi = get_folder_info_online (store, new_name, CAMEL_STORE_FOLDER_INFO_FAST |
- CAMEL_STORE_FOLDER_INFO_RECURSIVE, ex);
-
- if (new_fi == NULL)
- return;
-
- /* emit the renamed event */
- }
}
static CamelFolderInfo *
diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c
index cc4a703006..985081a266 100644
--- a/camel/providers/local/camel-local-folder.c
+++ b/camel/providers/local/camel-local-folder.c
@@ -65,6 +65,8 @@ static GPtrArray *local_search_by_expression(CamelFolder *folder, const char *ex
static GPtrArray *local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex);
static void local_search_free(CamelFolder *folder, GPtrArray * result);
+static void local_rename(CamelFolder *folder, const char *newname);
+
static void local_finalize(CamelObject * object);
static void
@@ -84,6 +86,8 @@ camel_local_folder_class_init(CamelLocalFolderClass * camel_local_folder_class)
camel_folder_class->search_by_uids = local_search_by_uids;
camel_folder_class->search_free = local_search_free;
+ camel_folder_class->rename = local_rename;
+
camel_local_folder_class->lock = local_lock;
camel_local_folder_class->unlock = local_unlock;
}
@@ -308,6 +312,30 @@ local_expunge(CamelFolder *folder, CamelException *ex)
CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, TRUE, ex);
}
+static void
+local_rename(CamelFolder *folder, const char *newname)
+{
+ CamelLocalFolder *lf = (CamelLocalFolder *)folder;
+
+ d(printf("renaming local folder paths to '%s'\n", newname));
+
+ /* Sync? */
+
+ g_free(lf->folder_path);
+ g_free(lf->summary_path);
+ g_free(lf->index_path);
+ lf->folder_path = g_strdup_printf("%s/%s", lf->base_path, newname);
+ lf->summary_path = g_strdup_printf("%s/%s.ev-summary", lf->base_path, newname);
+ lf->index_path = g_strdup_printf("%s/%s.ibex", lf->base_path, newname);
+
+ /* FIXME: Poke some internals, sigh */
+ camel_folder_summary_set_filename(folder->summary, lf->summary_path);
+ g_free(((CamelLocalSummary *)folder->summary)->folder_path);
+ ((CamelLocalSummary *)folder->summary)->folder_path = g_strdup(lf->folder_path);
+
+ parent_class->rename(folder, newname);
+}
+
static GPtrArray *
local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex)
{