diff options
-rw-r--r-- | mail/e-mail-migrate.c | 325 | ||||
-rw-r--r-- | shell/Makefile.am | 3 | ||||
-rw-r--r-- | shell/e-convert-local-mail.c | 315 | ||||
-rw-r--r-- | shell/main.c | 15 |
4 files changed, 332 insertions, 326 deletions
diff --git a/mail/e-mail-migrate.c b/mail/e-mail-migrate.c index e2968c1d9f..c642df91db 100644 --- a/mail/e-mail-migrate.c +++ b/mail/e-mail-migrate.c @@ -65,50 +65,6 @@ /* 1.4 upgrade functions */ -#define EM_TYPE_MIGRATE_SESSION \ - (em_migrate_session_get_type ()) - -typedef struct _EMMigrateSession { - CamelSession parent_object; - - CamelStore *store; /* new folder tree store */ - gchar *srcdir; /* old folder tree path */ -} EMMigrateSession; - -typedef struct _EMMigrateSessionClass { - CamelSessionClass parent_class; - -} EMMigrateSessionClass; - -GType em_migrate_session_get_type (void); - -G_DEFINE_TYPE (EMMigrateSession, em_migrate_session, CAMEL_TYPE_SESSION) - -static void -em_migrate_session_class_init (EMMigrateSessionClass *class) -{ -} - -static void -em_migrate_session_init (EMMigrateSession *session) -{ -} - -static EMMigrateSession * -em_migrate_session_new (const gchar *user_data_dir) -{ - const gchar *user_cache_dir; - - /* FIXME Really need to kill this function and - * get the cache dir from EShellBackend. */ - user_cache_dir = mail_session_get_cache_dir (); - - return g_object_new ( - EM_TYPE_MIGRATE_SESSION, - "user-data-dir", user_data_dir, - "user-cache-dir", user_cache_dir, NULL); -} - static GtkProgressBar *progress; static void @@ -275,284 +231,6 @@ emm_setup_initial (const gchar *data_dir) return TRUE; } -static gboolean -mbox_to_maildir_migration_needed (EShellBackend *shell_backend) -{ - gchar *local_store; - gchar *local_outbox; - const gchar *data_dir; - gboolean migration_needed = FALSE; - - data_dir = e_shell_backend_get_data_dir (shell_backend); - - local_store = g_build_filename (data_dir, "local", NULL); - local_outbox = g_build_filename (local_store, ".Outbox", NULL); - - /* If this is a fresh install (no local store exists yet) - * then obviously there's nothing to migrate to Maildir. */ - if (!g_file_test (local_store, G_FILE_TEST_IS_DIR)) - migration_needed = FALSE; - - /* Look for a Maildir Outbox folder. */ - else if (!g_file_test (local_outbox, G_FILE_TEST_IS_DIR)) - migration_needed = TRUE; - - g_free (local_store); - g_free (local_outbox); - - return migration_needed; -} - -/* Folder names with '.' are converted to '_' */ -static gchar * -sanitize_maildir_folder_name (gchar *folder_name) -{ - gchar *maildir_folder_name; - - maildir_folder_name = g_strdup (folder_name); - g_strdelimit (maildir_folder_name, ".", '_'); - - return maildir_folder_name; -} - -static void -copy_folder (CamelStore *mbox_store, - CamelStore *maildir_store, - const gchar *mbox_fname, - const gchar *maildir_fname) -{ - CamelFolder *fromfolder, *tofolder; - GPtrArray *uids; - - fromfolder = camel_store_get_folder_sync ( - mbox_store, mbox_fname, 0, NULL, NULL); - if (fromfolder == NULL) { - g_warning ("Cannot find mbox folder %s \n", mbox_fname); - return; - } - - tofolder = camel_store_get_folder_sync ( - maildir_store, maildir_fname, - CAMEL_STORE_FOLDER_CREATE, - NULL, NULL); - if (tofolder == NULL) { - g_warning ("Cannot create maildir folder %s \n", maildir_fname); - g_object_unref (fromfolder); - return; - } - - uids = camel_folder_get_uids (fromfolder); - camel_folder_transfer_messages_to_sync ( - fromfolder, uids, tofolder, - FALSE, NULL, - NULL, NULL); - camel_folder_free_uids (fromfolder, uids); - - g_object_unref (fromfolder); - g_object_unref (tofolder); -} - -static void -copy_folders (CamelStore *mbox_store, - CamelStore *maildir_store, - CamelFolderInfo *fi, - EMMigrateSession *session) -{ - if (fi) { - if (!g_str_has_prefix (fi->full_name, ".#evolution")) { - gchar *maildir_folder_name; - - /* sanitize folder names and copy folders */ - maildir_folder_name = sanitize_maildir_folder_name (fi->full_name); - copy_folder ( - mbox_store, maildir_store, - fi->full_name, maildir_folder_name); - g_free (maildir_folder_name); - } - - if (fi->child) - copy_folders (mbox_store, maildir_store, fi->child, session); - - copy_folders (mbox_store, maildir_store, fi->next, session); - } -} - -struct MigrateStore { - EMMigrateSession *session; - CamelStore *mbox_store; - CamelStore *maildir_store; - gboolean complete; -}; - -static void -migrate_stores (struct MigrateStore *ms) -{ - CamelFolderInfo *mbox_fi; - CamelStore *mbox_store = ms->mbox_store; - CamelStore *maildir_store = ms->maildir_store; - - mbox_fi = camel_store_get_folder_info_sync ( - mbox_store, NULL, - CAMEL_STORE_FOLDER_INFO_RECURSIVE | - CAMEL_STORE_FOLDER_INFO_FAST | - CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, - NULL, NULL); - - /* FIXME progres dialog */ - copy_folders (mbox_store, maildir_store, mbox_fi, ms->session); - ms->complete = TRUE; - - return; -} - -static gboolean -migrate_mbox_to_maildir (EShellBackend *shell_backend, - EMMigrateSession *session) -{ - EShell *shell; - ESource *source; - ESourceRegistry *registry; - ESourceExtension *extension; - const gchar *extension_name; - CamelService *mbox_service; - CamelService *maildir_service; - CamelStore *mbox_store; - CamelStore *maildir_store; - CamelSettings *settings; - const gchar *data_dir; - const gchar *uid; - gchar *path; - struct MigrateStore ms; - GError *error = NULL; - - data_dir = e_shell_backend_get_data_dir (shell_backend); - shell = e_shell_backend_get_shell (shell_backend); - registry = e_shell_get_registry (shell); - - source = e_source_new (NULL, NULL, NULL); - e_source_set_display_name (source, "local_mbox"); - - uid = e_source_get_uid (source); - - extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; - extension = e_source_get_extension (source, extension_name); - - e_source_backend_set_backend_name ( - E_SOURCE_BACKEND (extension), "mbox"); - - extension_name = e_source_camel_get_extension_name ("mbox"); - extension = e_source_get_extension (source, extension_name); - settings = e_source_camel_get_settings (E_SOURCE_CAMEL (extension)); - - path = g_build_filename (data_dir, "local_mbox", NULL); - g_object_set (settings, "path", path, NULL); - g_free (path); - - e_source_registry_commit_source_sync ( - registry, source, NULL, &error); - - if (error == NULL) - mbox_service = camel_session_add_service ( - CAMEL_SESSION (session), uid, "mbox", - CAMEL_PROVIDER_STORE, &error); - - if (error == NULL) - maildir_service = camel_session_add_service ( - CAMEL_SESSION (session), "local", "maildir", - CAMEL_PROVIDER_STORE, &error); - - if (error != NULL) { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_object_unref (source); - g_error_free (error); - return FALSE; - } - - camel_service_set_settings (mbox_service, settings); - - g_object_unref (source); - - settings = camel_service_get_settings (maildir_service); - path = g_build_filename (data_dir, "local", NULL); - g_object_set (settings, "path", path, NULL); - g_mkdir (path, 0700); - g_free (path); - - mbox_store = CAMEL_STORE (mbox_service); - maildir_store = CAMEL_STORE (maildir_service); - - ms.mbox_store = mbox_store; - ms.maildir_store = maildir_store; - ms.session = session; - ms.complete = FALSE; - - g_thread_create ((GThreadFunc) migrate_stores, &ms, TRUE, NULL); - while (!ms.complete) - g_main_context_iteration (NULL, TRUE); - - return TRUE; -} - -static void -rename_mbox_dir (EShellBackend *shell_backend) -{ - gchar *local_mbox_path, *new_mbox_path; - const gchar *data_dir; - - data_dir = e_shell_backend_get_data_dir (shell_backend); - local_mbox_path = g_build_filename (data_dir, "local", NULL); - new_mbox_path = g_build_filename (data_dir, "local_mbox", NULL); - - if (!g_file_test (local_mbox_path, G_FILE_TEST_EXISTS)) - goto exit; - - if (g_file_test (new_mbox_path, G_FILE_TEST_EXISTS)) - goto exit; - - g_rename (local_mbox_path, new_mbox_path); - -exit: - g_free (local_mbox_path); - g_free (new_mbox_path); -} - -static gboolean -migrate_local_store (EShellBackend *shell_backend) -{ - EMMigrateSession *session; - const gchar *data_dir; - gchar *local_store; - gint response; - - if (!mbox_to_maildir_migration_needed (shell_backend)) - return TRUE; - - response = e_alert_run_dialog_for_args ( - e_shell_get_active_window (NULL), - "mail:ask-migrate-store", NULL); - - if (response == GTK_RESPONSE_CANCEL) - exit (EXIT_SUCCESS); - - rename_mbox_dir (shell_backend); - data_dir = e_shell_backend_get_data_dir (shell_backend); - local_store = g_build_filename (data_dir, "local", NULL); - - if (!g_file_test (local_store, G_FILE_TEST_EXISTS)) - g_mkdir_with_parents (local_store, 0700); - - session = em_migrate_session_new (data_dir); - camel_session_set_online (CAMEL_SESSION (session), FALSE); - - migrate_mbox_to_maildir (shell_backend, session); - - g_object_unref (session); - - g_free (local_store); - - return TRUE; -} - static void em_rename_view_in_folder (gpointer data, gpointer user_data) @@ -660,9 +338,6 @@ e_mail_migrate (EShellBackend *shell_backend, if (major == 0) return emm_setup_initial (data_dir); - if (!migrate_local_store (shell_backend)) - return FALSE; - if (major <= 2 || (major == 3 && minor < 4)) em_rename_folder_views (shell_backend); diff --git a/shell/Makefile.am b/shell/Makefile.am index b460d08d43..a01dc7771c 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -143,7 +143,8 @@ evolution_CPPFLAGS = \ $(CLUTTER_CFLAGS) evolution_SOURCES = \ - main.c + main.c \ + e-convert-local-mail.c evolution_LDADD = \ libeshell.la \ diff --git a/shell/e-convert-local-mail.c b/shell/e-convert-local-mail.c new file mode 100644 index 0000000000..c36a036749 --- /dev/null +++ b/shell/e-convert-local-mail.c @@ -0,0 +1,315 @@ +/* + * e-convert-local-mail.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + */ + +#include <config.h> + +#include <glib/gstdio.h> +#include <camel/camel.h> + +#include <shell/e-shell.h> +#include <libevolution-utils/e-alert-dialog.h> + +/* Forward Declarations */ +void e_convert_local_mail (EShell *shell); + +static gboolean +mail_to_maildir_migration_needed (const gchar *mail_data_dir) +{ + gchar *local_store; + gchar *local_outbox; + gboolean migration_needed = FALSE; + + local_store = g_build_filename (mail_data_dir, "local", NULL); + local_outbox = g_build_filename (local_store, ".Outbox", NULL); + + /* If this is a fresh install (no local store exists yet) + * then obviously there's nothing to migrate to Maildir. */ + if (!g_file_test (local_store, G_FILE_TEST_IS_DIR)) + migration_needed = FALSE; + + /* Look for a Maildir Outbox folder. */ + else if (!g_file_test (local_outbox, G_FILE_TEST_IS_DIR)) + migration_needed = TRUE; + + g_free (local_store); + g_free (local_outbox); + + return migration_needed; +} + +/* Folder names with '.' are converted to '_' */ +static gchar * +sanitize_maildir_folder_name (gchar *folder_name) +{ + gchar *maildir_folder_name; + + maildir_folder_name = g_strdup (folder_name); + g_strdelimit (maildir_folder_name, ".", '_'); + + return maildir_folder_name; +} + +static void +copy_folder (CamelStore *mail_store, + CamelStore *maildir_store, + const gchar *mail_fname, + const gchar *maildir_fname) +{ + CamelFolder *fromfolder, *tofolder; + GPtrArray *uids; + + fromfolder = camel_store_get_folder_sync ( + mail_store, mail_fname, 0, NULL, NULL); + if (fromfolder == NULL) { + g_warning ("Cannot find mail folder %s \n", mail_fname); + return; + } + + tofolder = camel_store_get_folder_sync ( + maildir_store, maildir_fname, + CAMEL_STORE_FOLDER_CREATE, NULL, NULL); + if (tofolder == NULL) { + g_warning ("Cannot create maildir folder %s \n", maildir_fname); + g_object_unref (fromfolder); + return; + } + + uids = camel_folder_get_uids (fromfolder); + camel_folder_transfer_messages_to_sync ( + fromfolder, uids, tofolder, FALSE, NULL, NULL, NULL); + camel_folder_free_uids (fromfolder, uids); + + g_object_unref (fromfolder); + g_object_unref (tofolder); +} + +static void +copy_folders (CamelStore *mail_store, + CamelStore *maildir_store, + CamelFolderInfo *fi, + CamelSession *session) +{ + if (fi) { + if (!g_str_has_prefix (fi->full_name, ".#evolution")) { + gchar *maildir_folder_name; + + /* sanitize folder names and copy folders */ + maildir_folder_name = sanitize_maildir_folder_name (fi->full_name); + copy_folder ( + mail_store, maildir_store, + fi->full_name, maildir_folder_name); + g_free (maildir_folder_name); + } + + if (fi->child) + copy_folders (mail_store, maildir_store, fi->child, session); + + copy_folders (mail_store, maildir_store, fi->next, session); + } +} + +struct MigrateStore { + CamelSession *session; + CamelStore *mail_store; + CamelStore *maildir_store; + gboolean complete; +}; + +static void +migrate_stores (struct MigrateStore *ms) +{ + CamelFolderInfo *mail_fi; + CamelStore *mail_store = ms->mail_store; + CamelStore *maildir_store = ms->maildir_store; + + mail_fi = camel_store_get_folder_info_sync ( + mail_store, NULL, + CAMEL_STORE_FOLDER_INFO_RECURSIVE | + CAMEL_STORE_FOLDER_INFO_FAST | + CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, + NULL, NULL); + + /* FIXME progres dialog */ + copy_folders (mail_store, maildir_store, mail_fi, ms->session); + ms->complete = TRUE; +} + +static void +rename_mail_dir (ESource *mbox_source, + const gchar *mail_data_dir) +{ + gchar *old_mail_dir; + gchar *new_mail_dir; + gboolean need_rename; + const gchar *mbox_uid; + + mbox_uid = e_source_get_uid (mbox_source); + + old_mail_dir = g_build_filename (mail_data_dir, "local", NULL); + new_mail_dir = g_build_filename (mail_data_dir, mbox_uid, NULL); + + /* Rename if old directory exists and new directory does not. */ + need_rename = + g_file_test (old_mail_dir, G_FILE_TEST_EXISTS) && + !g_file_test (new_mail_dir, G_FILE_TEST_EXISTS); + + if (need_rename) + g_rename (old_mail_dir, new_mail_dir); + + g_free (old_mail_dir); + g_free (new_mail_dir); +} + +static gboolean +migrate_mail_to_maildir (EShell *shell, + CamelSession *session, + ESource *mbox_source) +{ + ESourceRegistry *registry; + ESourceExtension *extension; + const gchar *extension_name; + CamelService *mail_service; + CamelService *maildir_service; + CamelStore *mail_store; + CamelStore *maildir_store; + CamelSettings *settings; + const gchar *data_dir; + const gchar *mbox_uid; + gchar *path; + struct MigrateStore ms; + GError *error = NULL; + + registry = e_shell_get_registry (shell); + + data_dir = camel_session_get_user_data_dir (session); + + mbox_uid = e_source_get_uid (mbox_source); + e_source_set_display_name (mbox_source, "local_mbox"); + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + extension = e_source_get_extension (mbox_source, extension_name); + + e_source_backend_set_backend_name ( + E_SOURCE_BACKEND (extension), "mbox"); + + extension_name = e_source_camel_get_extension_name ("mbox"); + extension = e_source_get_extension (mbox_source, extension_name); + settings = e_source_camel_get_settings (E_SOURCE_CAMEL (extension)); + + path = g_build_filename (data_dir, mbox_uid, NULL); + g_object_set (settings, "path", path, NULL); + g_free (path); + + e_source_registry_commit_source_sync ( + registry, mbox_source, NULL, &error); + + if (error == NULL) + mail_service = camel_session_add_service ( + session, mbox_uid, "mbox", + CAMEL_PROVIDER_STORE, &error); + + if (error == NULL) + maildir_service = camel_session_add_service ( + session, "local", "maildir", + CAMEL_PROVIDER_STORE, &error); + + if (error != NULL) { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_error_free (error); + return FALSE; + } + + camel_service_set_settings (mail_service, settings); + + settings = camel_service_get_settings (maildir_service); + path = g_build_filename (data_dir, "local", NULL); + g_object_set (settings, "path", path, NULL); + g_mkdir (path, 0700); + g_free (path); + + mail_store = CAMEL_STORE (mail_service); + maildir_store = CAMEL_STORE (maildir_service); + + ms.mail_store = mail_store; + ms.maildir_store = maildir_store; + ms.session = session; + ms.complete = FALSE; + + g_thread_create ((GThreadFunc) migrate_stores, &ms, TRUE, NULL); + while (!ms.complete) + g_main_context_iteration (NULL, TRUE); + + return TRUE; +} + +void +e_convert_local_mail (EShell *shell) +{ + CamelSession *session; + ESource *mbox_source; + const gchar *user_data_dir; + const gchar *user_cache_dir; + gchar *mail_data_dir; + gchar *mail_cache_dir; + gchar *local_store; + gint response; + + user_data_dir = e_get_user_data_dir (); + user_cache_dir = e_get_user_cache_dir (); + + mail_data_dir = g_build_filename (user_data_dir, "mail", NULL); + mail_cache_dir = g_build_filename (user_cache_dir, "mail", NULL); + + if (!mail_to_maildir_migration_needed (mail_data_dir)) + goto exit; + + response = e_alert_run_dialog_for_args ( + e_shell_get_active_window (NULL), + "mail:ask-migrate-store", NULL); + + if (response == GTK_RESPONSE_CANCEL) + exit (EXIT_SUCCESS); + + mbox_source = e_source_new (NULL, NULL, NULL); + + rename_mail_dir (mbox_source, mail_data_dir); + + local_store = g_build_filename (mail_data_dir, "local", NULL); + + if (!g_file_test (local_store, G_FILE_TEST_EXISTS)) + g_mkdir_with_parents (local_store, 0700); + + g_free (local_store); + + session = g_object_new ( + CAMEL_TYPE_SESSION, + "online", FALSE, + "user-data-dir", mail_data_dir, + "user-cache-dir", mail_cache_dir, + NULL); + + migrate_mail_to_maildir (shell, session, mbox_source); + + g_object_unref (session); + + g_object_unref (mbox_source); + +exit: + g_free (mail_data_dir); + g_free (mail_cache_dir); +} diff --git a/shell/main.c b/shell/main.c index d6de1499e4..a19614d76c 100644 --- a/shell/main.c +++ b/shell/main.c @@ -114,6 +114,9 @@ static gchar *geometry = NULL; static gchar *requested_view = NULL; static gchar **remaining_args; +/* Forward declarations */ +void e_convert_local_mail (EShell *shell); + static void categories_icon_theme_hack (void) { @@ -644,6 +647,18 @@ main (gint argc, goto exit; } + /* This routine converts the local mail store from mbox format to + * Maildir format as needed. The reason the code is here and not + * in the mail module is because we inform the user at startup of + * the impending mail conversion by displaying a popup dialog and + * waiting for confirmation before proceeding. + * + * This has to be done before we load modules because some of the + * EShellBackends immediately add GMainContext sources that would + * otherwise get dispatched during gtk_dialog_run(), and we don't + * want them dispatched until after the conversion is complete. */ + e_convert_local_mail (shell); + e_shell_load_modules (shell); if (!disable_eplugin) { |