Bug 650223 - evolution-backup does not terminate without --gui

Use g_io_scheduler_push_job() instead of g_thread_create().  When the
operation is finished, call gtk_main_quit() from the main thread using
g_io_scheduler_job_send_to_mainloop().

Also, check for cancellation with a GCancellable instead of a boolean.

Note: We really should be using GLib's process spawning API
      instead of system(), but that's a job for another day.
This commit is contained in:
Matthew Barnes
2011-05-16 16:53:03 -04:00
parent 1f65cd64d3
commit 41337195f3

View File

@ -72,7 +72,6 @@ static gint result = 0;
static GtkWidget *progress_dialog;
static GtkWidget *pbar;
static gchar *txt = NULL;
static gboolean complete = FALSE;
static GOptionEntry options[] = {
{ "backup", '\0', 0, G_OPTION_ARG_NONE, &backup_op,
@ -93,7 +92,6 @@ static GOptionEntry options[] = {
#define d(x)
#define print_and_run(x) G_STMT_START { g_message ("%s", x); system (x); } G_STMT_END
#define CANCEL(x) if (x) return;
static gboolean check (const gchar *filename, gboolean *is_new_format);
@ -277,7 +275,8 @@ write_dir_file (void)
}
static void
backup (const gchar *filename)
backup (const gchar *filename,
GCancellable *cancellable)
{
gchar *command;
gchar *quotedfname;
@ -285,14 +284,18 @@ backup (const gchar *filename)
g_return_if_fail (filename && *filename);
quotedfname = g_shell_quote (filename);
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Shutting down Evolution");
/* FIXME Will the versioned setting always work? */
run_cmd (EVOLUTION " --quit");
run_cmd ("rm $DATADIR/.running");
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Backing Evolution accounts and settings");
run_cmd ("gconftool-2 --dump " GCONF_DIR " > " EVOLUTION_DIR GCONF_DUMP_FILE);
@ -300,7 +303,9 @@ backup (const gchar *filename)
write_dir_file ();
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Backing Evolution data (Mails, Contacts, Calendar, Tasks, Memos)");
/* FIXME stay on this file system ,other options?" */
@ -318,10 +323,10 @@ backup (const gchar *filename)
if (restart_arg) {
CANCEL (complete);
txt = _("Restarting Evolution");
complete=TRUE;
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Restarting Evolution");
run_cmd (EVOLUTION);
}
@ -379,7 +384,8 @@ get_dir_level (const gchar *dir)
}
static void
restore (const gchar *filename)
restore (const gchar *filename,
GCancellable *cancellable)
{
gchar *command;
gchar *quotedfname;
@ -394,18 +400,24 @@ restore (const gchar *filename)
quotedfname = g_shell_quote (filename);
if (g_cancellable_is_cancelled (cancellable))
return;
/* FIXME Will the versioned setting always work? */
CANCEL (complete);
txt = _("Shutting down Evolution");
run_cmd (EVOLUTION " --quit");
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Back up current Evolution data");
run_cmd ("mv $DATADIR $DATADIR_old");
run_cmd ("mv $CONFIGDIR $CONFIGDIR_old");
run_cmd ("mv $HOME/.camel_certs $HOME/.camel_certs_old");
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Extracting files from back up");
if (is_new_format) {
@ -462,7 +474,9 @@ restore (const gchar *filename)
g_free (quotedfname);
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Loading Evolution settings");
if (is_new_format) {
@ -477,7 +491,9 @@ restore (const gchar *filename)
run_cmd ("rm " "$HOME/.evolution/" GCONF_DUMP_FILE);
}
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Removing temporary back up files");
run_cmd ("rm -rf $DATADIR_old");
run_cmd ("rm -rf $CONFIGDIR_old");
@ -487,14 +503,17 @@ restore (const gchar *filename)
if (!is_new_format)
run_cmd ("rm -rf $HOME/.evolution_old");
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Ensuring local sources");
end:
if (restart_arg) {
CANCEL (complete);
if (g_cancellable_is_cancelled (cancellable))
return;
txt = _("Restarting Evolution");
complete=TRUE;
run_cmd (EVOLUTION);
}
}
@ -557,52 +576,48 @@ check (const gchar *filename, gboolean *is_new_format)
}
static gboolean
pbar_update (gpointer data)
pbar_update (GCancellable *cancellable)
{
if (!complete) {
gtk_progress_bar_pulse ((GtkProgressBar *) pbar);
gtk_progress_bar_set_text ((GtkProgressBar *) pbar, txt);
return TRUE;
}
gtk_progress_bar_pulse ((GtkProgressBar *) pbar);
gtk_progress_bar_set_text ((GtkProgressBar *) pbar, txt);
gtk_main_quit ();
return FALSE;
}
static gpointer
thread_start (gpointer data)
{
if (backup_op)
backup (bk_file);
else if (restore_op)
restore (res_file);
else if (check_op)
check (chk_file, NULL);
complete = TRUE;
return GINT_TO_POINTER (result);
/* Return TRUE to reschedule the timeout. */
return !g_cancellable_is_cancelled (cancellable);
}
static gboolean
idle_cb (gpointer data)
finish_job (gpointer user_data)
{
if (gui_arg) {
/* Show progress dialog */
gtk_progress_bar_pulse ((GtkProgressBar *) pbar);
g_timeout_add (50, pbar_update, NULL);
}
gtk_main_quit ();
g_thread_create (thread_start, NULL, FALSE, NULL);
return FALSE;
}
static gboolean
start_job (GIOSchedulerJob *job,
GCancellable *cancellable,
gpointer user_data)
{
if (backup_op)
backup (bk_file, cancellable);
else if (restore_op)
restore (res_file, cancellable);
else if (check_op)
check (chk_file, NULL); /* not cancellable */
g_io_scheduler_job_send_to_mainloop_async (
job, finish_job, NULL, (GDestroyNotify) NULL);
return FALSE;
}
static void
dlg_response (GtkWidget *dlg, gint response, gpointer data)
dlg_response (GtkWidget *dlg,
gint response,
GCancellable *cancellable)
{
/* We will cancel only backup/restore operations and not the check operation */
complete = TRUE;
g_cancellable_cancel (cancellable);
/* If the response is not of delete_event then destroy the event */
if (response != GTK_RESPONSE_NONE)
@ -632,6 +647,7 @@ dlg_response (GtkWidget *dlg, gint response, gpointer data)
gint
main (gint argc, gchar **argv)
{
GCancellable *cancellable;
gchar *file = NULL, *oper = NULL;
gint i;
GError *error = NULL;
@ -691,6 +707,8 @@ main (gint argc, gchar **argv)
}
}
cancellable = g_cancellable_new ();
if (gui_arg && !check_op) {
GtkWidget *widget, *container;
GtkWidget *action_area;
@ -789,7 +807,9 @@ main (gint argc, gchar **argv)
gtk_table_attach (GTK_TABLE (container), pbar, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
gtk_window_set_default_size ((GtkWindow *) progress_dialog, 450, 120);
g_signal_connect (progress_dialog, "response", G_CALLBACK(dlg_response), NULL);
g_signal_connect (
progress_dialog, "response",
G_CALLBACK (dlg_response), cancellable);
gtk_widget_show_all (progress_dialog);
} else if (check_op) {
/* For sanity we don't need gui */
@ -797,8 +817,21 @@ main (gint argc, gchar **argv)
exit (result == 0 ? 0 : 1);
}
g_idle_add (idle_cb, NULL);
if (gui_arg)
g_timeout_add_full (
G_PRIORITY_DEFAULT, 50,
(GSourceFunc) pbar_update,
g_object_ref (cancellable),
(GDestroyNotify) g_object_unref);
g_io_scheduler_push_job (
start_job, NULL,
(GDestroyNotify) NULL,
G_PRIORITY_DEFAULT, cancellable);
gtk_main ();
g_object_unref (cancellable);
return result;
}