Only retry another uid if we had a name clash, otherwise fail.
authorNot Zed <NotZed@HelixCode.com>
Tue, 8 Aug 2000 03:42:47 +0000 (03:42 +0000)
committerMichael Zucci <zucchi@src.gnome.org>
Tue, 8 Aug 2000 03:42:47 +0000 (03:42 +0000)
2000-08-07  Not Zed  <NotZed@HelixCode.com>

        * providers/mh/camel-mh-folder.c (mh_append_message): Only retry
        another uid if we had a name clash, otherwise fail.

2000-08-04  Not Zed  <NotZed@HelixCode.com>

        * camel-url.c (camel_url_set_protocol):
        (camel_url_set_host):
        (camel_url_set_path):
        (camel_url_set_port): Url editing functions.

2000-08-02  Not Zed  <NotZed@HelixCode.com>

        * providers/mh/camel-mh-summary.c (camel_mh_summary_sync): Expunge
        from the end, so the index isn't messed up when you remove a
        message.

        * providers/mh/camel-mh-folder.c (mh_append_message): Fix a bug
        where it would never open an output file/uid.

        * providers/mbox/camel-mbox-store.c (rename_folder):
        Implementation for mbox as well.

        * camel-store.c (camel_store_rename_folder): New method to rename folders.
        (rename_folder): Default implementation.

        * providers/mh/camel-mh-store.c (delete_folder): Implement this.
        (rename_folder): Implement a rename operation.

camel/ChangeLog
camel/camel-store.c
camel/camel-store.h
camel/camel-url.c
camel/camel-url.h
camel/providers/mbox/camel-mbox-store.c
camel/providers/mh/camel-mh-folder.c
camel/providers/mh/camel-mh-store.c
camel/providers/mh/camel-mh-summary.c

index 63ee275..ec58af3 100644 (file)
@@ -1,3 +1,33 @@
+2000-08-07  Not Zed  <NotZed@HelixCode.com>
+
+       * providers/mh/camel-mh-folder.c (mh_append_message): Only retry
+       another uid if we had a name clash, otherwise fail.
+
+2000-08-04  Not Zed  <NotZed@HelixCode.com>
+
+       * camel-url.c (camel_url_set_protocol): 
+       (camel_url_set_host): 
+       (camel_url_set_path): 
+       (camel_url_set_port): Url editing functions.
+
+2000-08-02  Not Zed  <NotZed@HelixCode.com>
+
+       * providers/mh/camel-mh-summary.c (camel_mh_summary_sync): Expunge
+       from the end, so the index isn't messed up when you remove a
+       message.
+
+       * providers/mh/camel-mh-folder.c (mh_append_message): Fix a bug
+       where it would never open an output file/uid.
+
+       * providers/mbox/camel-mbox-store.c (rename_folder):
+       Implementation for mbox as well.
+
+       * camel-store.c (camel_store_rename_folder): New method to rename folders.
+       (rename_folder): Default implementation.
+
+       * providers/mh/camel-mh-store.c (delete_folder): Implement this.
+       (rename_folder): Implement a rename operation.
+
 2000-08-07  Jeffrey Stedfast  <fejj@helixcode.com>
 
        * providers/imap/camel-imap-folder.c
index d729bf1..3be983e 100644 (file)
@@ -38,6 +38,8 @@ static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
                                gboolean create, CamelException *ex);
 static void delete_folder (CamelStore *store, const char *folder_name,
                           CamelException *ex);
+static void rename_folder (CamelStore *store, const char *old_name,
+                          const char *new_name, CamelException *ex);
 
 static char *get_folder_name (CamelStore *store, const char *folder_name,
                              CamelException *ex);
@@ -62,6 +64,7 @@ camel_store_class_init (CamelStoreClass *camel_store_class)
        /* virtual method definition */
        camel_store_class->get_folder = get_folder;
        camel_store_class->delete_folder = delete_folder;
+       camel_store_class->rename_folder = rename_folder;
        camel_store_class->get_folder_name = get_folder_name;
        camel_store_class->get_root_folder_name = get_root_folder_name;
        camel_store_class->get_default_folder_name = get_default_folder_name;
@@ -138,6 +141,16 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
                   gtk_type_name (GTK_OBJECT_TYPE (store)));
 }
 
+static void rename_folder (CamelStore *store, const char *old_name,
+                          const char *new_name, CamelException *ex)
+{
+       g_warning ("CamelStore::rename_folder not implemented for `%s'",
+                  gtk_type_name (GTK_OBJECT_TYPE (store)));
+       camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+                            "rename folder unimplemented for: %s",
+                            gtk_type_name (GTK_OBJECT_TYPE (store)));
+}
+
 
 /* CamelStore::get_folder_name should:
  * a) make sure that the provided name is valid
@@ -287,6 +300,33 @@ camel_store_delete_folder (CamelStore *store, const char *folder_name,
        }
 }
 
+/**
+ * camel_store_rename_folder:
+ * @store: 
+ * @old_name: 
+ * @new_name: 
+ * @ex: 
+ * 
+ * Rename a named folder to a new name.
+ **/
+void             camel_store_rename_folder      (CamelStore *store,
+                                                const char *old_name,
+                                                const char *new_name,
+                                                CamelException *ex)
+{
+       char *old, *new;
+
+       old = CS_CLASS (store)->get_folder_name(store, old_name, ex);
+       if (old) {
+               new = CS_CLASS (store)->get_folder_name(store, new_name, ex);
+               if (new) {
+                       CS_CLASS (store)->rename_folder(store, old, new, ex);
+                       g_free(new);
+               }
+               g_free(old);
+       }
+}
+
 
 /**
  * camel_store_get_root_folder: return the top-level folder
index 6d2d9e5..3fc029d 100644 (file)
@@ -63,7 +63,10 @@ typedef struct {
        void            (*delete_folder)            (CamelStore *store,
                                                     const char *folder_name,
                                                     CamelException *ex);
-
+       void            (*rename_folder)            (CamelStore *store,
+                                                    const char *old_name,
+                                                    const char *new_name,
+                                                    CamelException *ex);
        char *          (*get_folder_name)          (CamelStore *store,
                                                     const char *folder_name,
                                                     CamelException *ex);
@@ -99,6 +102,10 @@ CamelFolder *    camel_store_get_default_folder (CamelStore *store,
 void             camel_store_delete_folder      (CamelStore *store,
                                                 const char *folder_name,
                                                 CamelException *ex);
+void             camel_store_rename_folder      (CamelStore *store,
+                                                const char *old_name,
+                                                const char *new_name,
+                                                CamelException *ex);
 
 #ifdef __cplusplus
 }
index 6038500..e52645c 100644 (file)
@@ -233,6 +233,28 @@ camel_url_free (CamelURL *url)
        g_free (url);
 }
 
+void camel_url_set_protocol(CamelURL *url, const char *p)
+{
+       g_free(url->protocol);
+       url->protocol = g_strdup(p);
+}
+
+void camel_url_set_host(CamelURL *url, const char *h)
+{
+       g_free(url->host);
+       url->host = g_strdup(h);
+}
+
+void camel_url_set_port(CamelURL *url, int port)
+{
+       url->port = port;
+}
+void camel_url_set_path(CamelURL *url, const char *p)
+{
+       g_free(url->path);
+       url->path = g_strdup(p);
+}
+
 
 /**
  * camel_url_encode:
index bea1c43..aba903c 100644 (file)
@@ -53,10 +53,15 @@ CamelURL *camel_url_new (const char *url_string, CamelException *ex);
 char *camel_url_to_string (CamelURL *url, gboolean show_password);
 void camel_url_free (CamelURL *url);
 
-char *camel_url_encode (char *part, gboolean escape_unsafe,
-                       char *escape_extra);
+char *camel_url_encode (char *part, gboolean escape_unsafe, char *escape_extra);
 void camel_url_decode (char *part);
 
+/* for editing url's */
+void camel_url_set_protocol(CamelURL *url, const char *);
+void camel_url_set_host(CamelURL *url, const char *);
+void camel_url_set_port(CamelURL *url, int port);
+void camel_url_set_path(CamelURL *url, const char *);
+
 /* for putting url's into hash tables */
 guint camel_url_hash (const void *v);
 int camel_url_equal(const void *v, const void *v2);
index 19b7c54..e3396a7 100644 (file)
@@ -44,6 +44,7 @@ static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
                                gboolean create, CamelException *ex);
 static void delete_folder (CamelStore *store, const char *folder_name,
                           CamelException *ex);
+static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex);
 static char *get_folder_name (CamelStore *store, const char *folder_name,
                              CamelException *ex);
 
@@ -58,6 +59,7 @@ camel_mbox_store_class_init (CamelMboxStoreClass *camel_mbox_store_class)
 
        camel_store_class->get_folder = get_folder;
        camel_store_class->delete_folder = delete_folder;
+       camel_store_class->rename_folder = rename_folder;
        camel_store_class->get_folder_name = get_folder_name;
 }
 
@@ -169,8 +171,7 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
        struct stat st;
        int status;
 
-       name = g_strdup_printf ("%s%s", CAMEL_SERVICE (store)->url->path,
-                               folder_name);
+       name = g_strdup_printf ("%s%s", CAMEL_SERVICE (store)->url->path, folder_name);
        if (stat (name, &st) == -1) {
                if (errno == ENOENT) {
                        /* file doesn't exist - it's kinda like deleting it ;-) */
@@ -220,6 +221,51 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
        }
 }
 
+static int xrename(char *oldp, char *newp, char *prefix, char *suffix, CamelException *ex)
+{
+       struct stat st;
+       char *old = g_strconcat(prefix, oldp, suffix, 0);
+       char *new = g_strconcat(prefix, newp, suffix, 0);
+       int ret = -1;
+
+       printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix);
+
+       /* FIXME: this has races ... */
+       if (!(stat(new, &st) == -1 && errno==ENOENT)) {
+               camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+                                    "Could not rename folder %s to %s: destination exists",
+                                    old, new);
+       } else if (rename(old, new) == 0 || errno==ENOENT) {
+               ret = 0;
+       } else if (stat(old, &st) == -1 && errno==ENOENT && stat(new, &st) == 0) {
+               /* for nfs, check if the rename worked anyway ... */
+               ret = 0;
+       }
+       printf("success = %d\n", ret);
+
+       g_free(old);
+       g_free(new);
+       return ret;
+}
+
+static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex)
+{
+       char *path = CAMEL_SERVICE (store)->url->path;
+
+       /* try to rollback failures, has obvious races */
+       if (xrename(old, new, path, ".ibex", ex)) {
+               return;
+       }
+       if (xrename(old, new, path, "-ev-summary", ex)) {
+               xrename(new, old, path, ".ibex", ex);
+               return;
+       }
+       if (xrename(old, new, path, "", ex)) {
+               xrename(new, old, path, "-ev-summary", ex);
+               xrename(new, old, path, ".ibex", ex);
+       }
+}
+
 static char *
 get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex)
 {
index 1961c62..6f85fb7 100644 (file)
@@ -268,7 +268,6 @@ static gint mh_get_unread_message_count(CamelFolder * folder)
        return count;
 }
 
-/* FIXME: this may need some tweaking for performance? */
 static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, guint32 flags, CamelException * ex)
 {
        CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(folder);
@@ -285,7 +284,7 @@ static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message,
                uid = camel_folder_summary_next_uid_string((CamelFolderSummary *)mh_folder->summary);
                name = g_strdup_printf("%s/%s", mh_folder->folder_file_path, uid);
                output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT|O_EXCL, 0600);
-       } while (output_stream == NULL || errno != EEXIST);
+       } while (output_stream == NULL && errno == EEXIST);
 
        if (output_stream == NULL)
                goto fail;
index 6ae885a..5ab4bcc 100644 (file)
@@ -43,6 +43,7 @@
 static char *get_name(CamelService * service, gboolean brief);
 static CamelFolder *get_folder(CamelStore * store, const char *folder_name, gboolean create, CamelException * ex);
 static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex);
+static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex);
 static char *get_folder_name(CamelStore * store, const char *folder_name, CamelException * ex);
 
 static void camel_mh_store_class_init(CamelMhStoreClass * camel_mh_store_class)
@@ -55,6 +56,7 @@ static void camel_mh_store_class_init(CamelMhStoreClass * camel_mh_store_class)
 
        camel_store_class->get_folder = get_folder;
        camel_store_class->delete_folder = delete_folder;
+       camel_store_class->rename_folder = rename_folder;
        camel_store_class->get_folder_name = get_folder_name;
 }
 
@@ -107,8 +109,11 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, gboo
 
        name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
 
+       printf("getting folder: %s\n", name);
        if (stat(name, &st) == -1) {
                int fd;
+               
+               printf("doesn't exist ...\n");
 
                if (errno != ENOENT) {
                        camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
@@ -120,12 +125,15 @@ static CamelFolder *get_folder(CamelStore * store, const char *folder_name, gboo
                                             "Folder `%s' does not exist.", folder_name);
                        goto done;
                }
+               printf("creating ...\n");
 
-               if (mkdir (name, 0600) != 0) {
+               if (mkdir(name, 0700) != 0) {
                        camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
                                             "Could not create folder `%s':" "\n%s", folder_name, g_strerror(errno));
                        goto done;
                }
+               printf("created ok?\n");
+
        } else if (!S_ISDIR(st.st_mode)) {
                camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, "`%s' is not a directory.", name);
                goto done;
@@ -142,13 +150,54 @@ done:
 static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex)
 {
        char *name;
+       struct stat st;
+       char *str;
 
        name = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, folder_name);
-       camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
-                            "Could not delete folder `%s':\n%s", folder_name, "not implemented");
+       if (stat(name, &st) == -1) {
+               if (errno != ENOENT)
+                       camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+                                            "Could not delete folder `%s': %s", folder_name, strerror(errno));
+       } else {
+               /* this will 'fail' if there are still messages in the directory -
+                  but only the metadata is lost */
+               str = g_strdup_printf("%s/ev-summary", name);
+               unlink(str);
+               g_free(str);
+               str = g_strdup_printf("%s/ev-index.ibex", name);
+               unlink(str);
+               g_free(str);
+               if (rmdir(name) == -1) {
+                       camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+                                            "Could not delete folder `%s': %s", folder_name, strerror(errno));
+               }
+       }
        g_free(name);
 }
 
+static void rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex)
+{
+       char *old, *new;
+       struct stat st;
+
+       old = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, old_name);
+       new = g_strdup_printf("%s%s", CAMEL_SERVICE(store)->url->path, new_name);
+       if (stat(new, &st) == -1 && errno == ENOENT) {
+               if (stat(old, &st) == 0 && S_ISDIR(st.st_mode)) {
+                       if (rename(old, new) != 0) {
+                               camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+                                                    "Could not rename folder `%s': %s", old_name, strerror(errno));
+                       }
+               } else {
+                       camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+                                            "Could not rename folder `%s': %s", old_name, strerror(errno));
+               }
+       } else {
+               camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+                                    "Could not rename folder `%s': %s exists", old_name, new_name);
+       }
+}
+
 static char *get_folder_name(CamelStore * store, const char *folder_name, CamelException * ex)
 {
        /* For now, we don't allow hieararchy. FIXME. */
index 83f2113..36bfd2f 100644 (file)
@@ -258,15 +258,17 @@ int               camel_mh_summary_sync(CamelMhSummary * mhs, int expunge, CamelException *ex
        CamelMessageInfo *info;
        char *name;
 
+       printf("summary_sync(expunge=%s)\n", expunge?"true":"false");
+
        if (!expunge)
                return 0;
 
        count = camel_folder_summary_count((CamelFolderSummary *)mhs);
-       for (i=0;i<count;i++) {
+       for (i=count-1;i>=0;i--) {
                info = camel_folder_summary_index((CamelFolderSummary *)mhs, i);
                if (info && info->flags & CAMEL_MESSAGE_DELETED) {
                        name = g_strdup_printf("%s/%s", mhs->mh_path, info->uid);
-                       d(printf("deleting %s\n", name));
+                       (printf("deleting %s\n", name));
                        if (unlink(name) == 0 || errno==ENOENT) {
                                camel_folder_summary_remove((CamelFolderSummary *)mhs, info);
                        }