Evolution 1.5.3 has a bug for migration of addressbooks during startup, that causes a crash in Evo. It's been fixed, and this is the patch for it from HEAD. Stuff takes a while to compile on my poor old machine. Please tell me if evo 1.5.3 still crashes at startup after applying this patch. Thanks -- PGP ID:6FFEFD7F FreeBSD 5.2-CURRENT i386 4:58pm up 3:11, 5 users, load averages: 2.61, 2.37, 1.64
--- addressbook/gui/component/addressbook-migrate.c Mon Jan 26 23:55:13 2004 +++ /home/kaeru/cvs/gnome/evolution/addressbook/gui/component/addressbook-migrate.c Fri Jan 30 03:07:34 2004 @@ -33,76 +33,88 @@ #include <gtk/gtkprogressbar.h> #include <e-util/e-folder-map.h> -static GtkWidget *window; -static GtkLabel *label; -static GtkProgressBar *progress; +typedef struct { + /* this hash table maps old folder uris to new uids. It's + build in migrate_contact_folder and it's used in + migrate_completion_folders. */ + GHashTable *folder_uid_map; + + ESourceList *source_list; + + AddressbookComponent *component; + + GtkWidget *window; + GtkLabel *label; + GtkProgressBar *progress; +} MigrationContext; static void -setup_progress_dialog (void) +setup_progress_dialog (MigrationContext *context) { GtkWidget *vbox, *hbox, *w; - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title ((GtkWindow *) window, _("Migrating...")); - gtk_window_set_modal ((GtkWindow *) window, TRUE); - gtk_container_set_border_width ((GtkContainer *) window, 6); + + context->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (context->window), _("Migrating...")); + gtk_window_set_modal (GTK_WINDOW (context->window), TRUE); + gtk_container_set_border_width (GTK_CONTAINER (context->window), 6); vbox = gtk_vbox_new (FALSE, 6); gtk_widget_show (vbox); - gtk_container_add ((GtkContainer *) window, vbox); + gtk_container_add (GTK_CONTAINER (context->window), vbox); w = gtk_label_new (_("The location and hierarchy of the Evolution contact " "folders has changed since Evolution 1.x.\n\nPlease be " "patient while Evolution migrates your folders...")); - gtk_label_set_line_wrap ((GtkLabel *) w, TRUE); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); gtk_widget_show (w); - gtk_box_pack_start_defaults ((GtkBox *) vbox, w); + gtk_box_pack_start_defaults (GTK_BOX (vbox), w); hbox = gtk_hbox_new (FALSE, 6); gtk_widget_show (hbox); - gtk_box_pack_start_defaults ((GtkBox *) vbox, hbox); + gtk_box_pack_start_defaults (GTK_BOX (vbox), hbox); - label = (GtkLabel *) gtk_label_new (""); - gtk_widget_show ((GtkWidget *) label); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) label); + context->label = GTK_LABEL (gtk_label_new ("")); + gtk_widget_show (GTK_WIDGET (context->label)); + gtk_box_pack_start_defaults (GTK_BOX (hbox), GTK_WIDGET (context->label)); - progress = (GtkProgressBar *) gtk_progress_bar_new (); - gtk_widget_show ((GtkWidget *) progress); - gtk_box_pack_start_defaults ((GtkBox *) hbox, (GtkWidget *) progress); + context->progress = GTK_PROGRESS_BAR (gtk_progress_bar_new ()); + gtk_widget_show (GTK_WIDGET (context->progress)); + gtk_box_pack_start_defaults (GTK_BOX (hbox), GTK_WIDGET (context->progress)); - gtk_widget_show (window); + gtk_widget_show (context->window); + } static void -dialog_close (void) +dialog_close (MigrationContext *context) { - gtk_widget_destroy ((GtkWidget *) window); + gtk_widget_destroy (context->window); } static void -dialog_set_folder_name (const char *folder_name) +dialog_set_folder_name (MigrationContext *context, const char *folder_name) { char *text; text = g_strdup_printf (_("Migrating `%s':"), folder_name); - gtk_label_set_text (label, text); + gtk_label_set_text (context->label, text); g_free (text); - gtk_progress_bar_set_fraction (progress, 0.0); + gtk_progress_bar_set_fraction (context->progress, 0.0); while (gtk_events_pending ()) gtk_main_iteration (); } static void -dialog_set_progress (double percent) +dialog_set_progress (MigrationContext *context, double percent) { char text[5]; snprintf (text, sizeof (text), "%d%%", (int) (percent * 100.0f)); - gtk_progress_bar_set_fraction (progress, percent); - gtk_progress_bar_set_text (progress, text); + gtk_progress_bar_set_fraction (context->progress, percent); + gtk_progress_bar_set_text (context->progress, text); while (gtk_events_pending ()) gtk_main_iteration (); @@ -170,7 +182,7 @@ } static void -migrate_contacts (EBook *old_book, EBook *new_book) +migrate_contacts (MigrationContext *context, EBook *old_book, EBook *new_book) { EBookQuery *query = e_book_query_any_field_contains (""); GList *l, *contacts; @@ -277,29 +289,25 @@ num_added ++; - dialog_set_progress ((double)num_added / num_contacts); + dialog_set_progress (context, (double)num_added / num_contacts); } } static void -migrate_contact_folder (char *old_path, ESourceGroup *dest_group, char *source_name) +migrate_contact_folder_to_source (MigrationContext *context, char *old_path, ESource *new_source) { char *old_uri = g_strdup_printf ("file://%s", old_path); GError *e = NULL; EBook *old_book = NULL, *new_book = NULL; ESource *old_source; - ESource *new_source; ESourceGroup *group; group = e_source_group_new ("", old_uri); old_source = e_source_new ("", ""); - e_source_set_group (old_source, group); - - new_source = e_source_new (source_name, source_name); - e_source_set_group (new_source, dest_group); + e_source_group_add_source (group, old_source, -1); - dialog_set_folder_name (source_name); + dialog_set_folder_name (context, e_source_peek_name (new_source)); old_book = e_book_new (); if (!e_book_load_source (old_book, old_source, TRUE, &e)) { @@ -313,12 +321,10 @@ goto finish; } - migrate_contacts (old_book, new_book); + migrate_contacts (context, old_book, new_book); finish: - g_object_unref (new_source); g_object_unref (old_source); - g_object_unref (dest_group); g_object_unref (group); if (old_book) g_object_unref (old_book); @@ -327,30 +333,46 @@ g_free (old_uri); } +static void +migrate_contact_folder (MigrationContext *context, char *old_path, ESourceGroup *dest_group, char *source_name) +{ + ESource *new_source; + + new_source = e_source_new (source_name, source_name); + e_source_set_relative_uri (new_source, e_source_peek_uid (new_source)); + e_source_group_add_source (dest_group, new_source, -1); + + g_hash_table_insert (context->folder_uid_map, g_strdup (old_path), g_strdup (e_source_peek_uid (new_source))); + + migrate_contact_folder_to_source (context, old_path, new_source); + + g_object_unref (new_source); +} + #define LDAP_BASE_URI "ldap://" -#define PERSONAL_RELATIVE_URI "Personal" +#define PERSONAL_RELATIVE_URI "system" static void -create_groups (AddressbookComponent *component, - ESourceList *source_list, +create_groups (MigrationContext *context, ESourceGroup **on_this_computer, - ESourceGroup **on_ldap_servers) + ESourceGroup **on_ldap_servers, + ESource **personal_source) { GSList *groups; ESourceGroup *group; - ESource *personal_source = NULL; - char *base_uri, *base_uri_proto, *new_dir; + ESource *source = NULL; + char *base_uri, *base_uri_proto; *on_this_computer = NULL; *on_ldap_servers = NULL; - base_uri = g_build_filename (addressbook_component_peek_base_directory (component), - "/addressbook/local/OnThisComputer/", + base_uri = g_build_filename (addressbook_component_peek_base_directory (context->component), + "/addressbook/local/", NULL); base_uri_proto = g_strconcat ("file://", base_uri, NULL); - groups = e_source_list_peek_groups (source_list); + groups = e_source_list_peek_groups (context->source_list); if (groups) { /* groups are already there, we need to search for things... */ GSList *g; @@ -359,10 +381,10 @@ group = E_SOURCE_GROUP (g->data); - if (!strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) - *on_this_computer = group; - else if (!strcmp (LDAP_BASE_URI, e_source_group_peek_base_uri (group))) - *on_ldap_servers = group; + if (!*on_this_computer && !strcmp (base_uri_proto, e_source_group_peek_base_uri (group))) + *on_this_computer = g_object_ref (group); + else if (!*on_ldap_servers && !strcmp (LDAP_BASE_URI, e_source_group_peek_base_uri (group))) + *on_ldap_servers = g_object_ref (group); } } @@ -374,7 +396,7 @@ for (s = sources; s; s = s->next) { ESource *source = E_SOURCE (s->data); if (!strcmp (PERSONAL_RELATIVE_URI, e_source_peek_relative_uri (source))) { - personal_source = source; + *personal_source = g_object_ref (source); break; } } @@ -382,25 +404,23 @@ else { /* create the local source group */ group = e_source_group_new (_("On This Computer"), base_uri_proto); - e_source_list_add_group (source_list, group, -1); + e_source_list_add_group (context->source_list, group, -1); *on_this_computer = group; } - if (!personal_source) { + if (!source) { /* Create the default Person addressbook */ - new_dir = g_build_filename (base_uri, "Personal/", NULL); - if (!e_mkdir_hier (new_dir, 0700)) { - personal_source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); - e_source_group_add_source (*on_this_computer, personal_source, -1); - } - g_free (new_dir); + source = e_source_new (_("Personal"), PERSONAL_RELATIVE_URI); + e_source_group_add_source (*on_this_computer, source, -1); + + *personal_source = source; } if (!*on_ldap_servers) { /* Create the LDAP source group */ group = e_source_group_new (_("On LDAP Servers"), LDAP_BASE_URI); - e_source_list_add_group (source_list, group, -1); + e_source_list_add_group (context->source_list, group, -1); *on_ldap_servers = group; } @@ -410,31 +430,33 @@ } static gboolean -migrate_local_folders (AddressbookComponent *component, ESourceGroup *on_this_computer) +migrate_local_folders (MigrationContext *context, ESourceGroup *on_this_computer, ESource *personal_source) { char *old_path = NULL; - char *local_contact_folder = NULL; - char *source_name = NULL; GSList *dirs, *l; + char *local_contact_folder = NULL; old_path = g_strdup_printf ("%s/evolution/local", g_get_home_dir ()); dirs = e_folder_map_local_folders (old_path, "contacts"); - /* migrate the local addressbook first, to OnThisComputer/Personal */ + /* migrate the local addressbook first, to local/system */ local_contact_folder = g_build_filename (g_get_home_dir (), "/evolution/local/Contacts", NULL); - source_name = _("Personal"); - migrate_contact_folder (local_contact_folder, on_this_computer, source_name); + if (personal_source) + for (l = dirs; l; l = l->next) { - /* skip the local contact folder, since we handle that - specifically, mapping it to Personal */ - if (!strcmp ((char*)l->data, local_contact_folder)) + char *source_name; + /* we handle the system folder differently */ + if (personal_source && !strcmp ((char*)l->data, local_contact_folder)) { + g_hash_table_insert (context->folder_uid_map, g_strdup (l->data), g_strdup (e_source_peek_uid (personal_source))); + migrate_contact_folder_to_source (context, local_contact_folder, personal_source); continue; + } source_name = get_source_name (on_this_computer, (char*)l->data); - migrate_contact_folder (l->data, on_this_computer, source_name); + migrate_contact_folder (context, l->data, on_this_computer, source_name); g_free (source_name); } @@ -494,7 +516,7 @@ } static gboolean -migrate_ldap_servers (AddressbookComponent *component, ESourceGroup *on_ldap_servers) +migrate_ldap_servers (MigrationContext *context, ESourceGroup *on_ldap_servers) { char *sources_xml = g_strdup_printf ("%s/evolution/addressbook-sources.xml", g_get_home_dir ()); @@ -526,7 +548,7 @@ } printf ("found %d contact servers to migrate\n", num_contactservers); - dialog_set_folder_name (_("LDAP Servers")); + dialog_set_folder_name (context, _("LDAP Servers")); servernum = 0; for (child = root->children; child; child = child->next) { @@ -581,7 +603,7 @@ g_free (description); servernum++; - dialog_set_progress ((double)servernum/num_contactservers); + dialog_set_progress (context, (double)servernum/num_contactservers); } } @@ -630,9 +652,9 @@ } static gboolean -migrate_completion_folders (AddressbookComponent *component, ESourceList *source_list) +migrate_completion_folders (MigrationContext *context) { - char *uris_xml = gconf_client_get_string (addressbook_component_peek_gconf_client (component), + char *uris_xml = gconf_client_get_string (addressbook_component_peek_gconf_client (context->component), "/apps/evolution/addressbook/completion/uris", NULL); @@ -646,7 +668,7 @@ if (!doc) return FALSE; - dialog_set_folder_name (_("Autocompletion Settings")); + dialog_set_folder_name (context, _("Autocompletion Settings")); root = xmlDocGetRootElement (doc); if (root == NULL || strcmp (root->name, "EvolutionFolderList") != 0) { @@ -657,13 +679,13 @@ for (child = root->children; child; child = child->next) { if (!strcmp (child->name, "folder")) { char *physical_uri = e_xml_get_string_prop_by_name (child, "physical-uri"); - char *uri; - ESource *source; + ESource *source = NULL; - /* if the physical uri is - file://... we need to convert the - path to the new directory - structure. + /* if the physical uri is file://... + we look it up in our folder_uid_map + hashtable. If it's a folder we + converted over, we should get back + a uid we can search for. if the physical_uri is anything else, we strip off the args @@ -671,45 +693,25 @@ for the uri. */ if (!strncmp (physical_uri, "file://", 7)) { - char *local_path = g_build_filename (g_get_home_dir (), - "/evolution/local/", - NULL); - - if (!strncmp (physical_uri + 7, local_path, strlen (local_path))) { - char *path_extra; - char *path; - - if (!strcmp (physical_uri + 7 + strlen (local_path), "Contacts")) - /* special case the ~/evolution/local/Contacts folder */ - path_extra = "Personal"; - else - path_extra = physical_uri + 7 + strlen (local_path); - - path = g_build_filename (g_get_home_dir (), - "/.evolution/addressbook/local/OnThisComputer", - path_extra, - NULL); - uri = g_strdup_printf ("file://%s", path); - g_free (path); - } - else { - /* if they somehow created a folder that lies - outside the evolution folder tree, just pass - the uri straight on */ - uri = g_strdup (physical_uri); - } + char *uid = g_hash_table_lookup (context->folder_uid_map, + physical_uri + 7); - g_free (local_path); + if (uid) + source = e_source_list_peek_source_by_uid (context->source_list, uid); } else { + char *uri; char *semi = strchr (physical_uri, ';'); if (semi) uri = g_strndup (physical_uri, semi - physical_uri); else uri = g_strdup (physical_uri); + + source = get_source_by_uri (context->source_list, uri); + + g_free (uri); } - source = get_source_by_uri (source_list, uri); if (source) { e_source_set_property (source, "completion", "true"); } @@ -719,7 +721,6 @@ } g_free (physical_uri); - g_free (uri); } } @@ -732,19 +733,47 @@ return TRUE; } +static MigrationContext* +migration_context_new (AddressbookComponent *component) +{ + MigrationContext *context = g_new (MigrationContext, 1); + + /* set up the mapping from old uris to new uids */ + context->folder_uid_map = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_free); + + context->source_list = addressbook_component_peek_source_list (component); + + /* initialize our dialog */ + setup_progress_dialog (context); + + context->component = component; + + return context; +} + +static void +migration_context_free (MigrationContext *context) +{ + e_source_list_sync (context->source_list, NULL); + + g_hash_table_destroy (context->folder_uid_map); + g_free (context); +} + int addressbook_migrate (AddressbookComponent *component, int major, int minor, int revision) { - ESourceList *source_list = addressbook_component_peek_source_list (component); ESourceGroup *on_this_computer; ESourceGroup *on_ldap_servers; + ESource *personal_source; + MigrationContext *context = migration_context_new (component); printf ("addressbook_migrate (%d.%d.%d)\n", major, minor, revision); /* we call this unconditionally now - create_groups either creates the groups/sources or it finds the necessary groups/sources. */ - create_groups (component, source_list, &on_this_computer, &on_ldap_servers); + create_groups (context, &on_this_computer, &on_ldap_servers, &personal_source); if (major <= 1) { @@ -756,19 +785,24 @@ /* we're 0.x */ (major == 0)) { - setup_progress_dialog (); - if (on_this_computer) - migrate_local_folders (component, on_this_computer); - if (on_ldap_servers) - migrate_ldap_servers (component, on_ldap_servers); + if (on_this_computer) { + migrate_local_folders (context, on_this_computer, personal_source); + g_object_unref (on_this_computer); + } + if (on_ldap_servers) { + migrate_ldap_servers (context, on_ldap_servers); + g_object_unref (on_ldap_servers); + } + if (personal_source) + g_object_unref (personal_source); - migrate_completion_folders (component, source_list); + migrate_completion_folders (context); - dialog_close (); + dialog_close (context); } } - e_source_list_sync (source_list, NULL); + migration_context_free (context); return TRUE; }
Attachment:
pgpzj5p2QSmhI.pgp
Description: PGP signature