plover-gtk/transactionhelper.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Apr 18 14:55:22 2016 +0100 (2016-04-18)
changeset 35 c264564e4c89
child 38 a29623b68ca2
permissions -rw-r--r--
Support EL6's expat21 compatibility package
ali@24
     1
/*
ali@24
     2
 * Copyright (C) 2014  J. Ali Harlow <ali@juiblex.co.uk>
ali@24
     3
 *
ali@24
     4
 * This program is free software; you can redistribute it and/or modify
ali@24
     5
 * it under the terms of the GNU General Public License as published by
ali@24
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@24
     7
 * (at your option) any later version.
ali@24
     8
 *
ali@24
     9
 * This program is distributed in the hope that it will be useful,
ali@24
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@24
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@24
    12
 * GNU General Public License for more details.
ali@24
    13
 *
ali@24
    14
 * You should have received a copy of the GNU General Public License along
ali@24
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@24
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@24
    17
 */
ali@24
    18
ali@24
    19
#include "config.h"
ali@24
    20
#include <stdlib.h>
ali@24
    21
#include <errno.h>
ali@24
    22
#include <gtk/gtk.h>
ali@24
    23
#include <plover/plover.h>
ali@24
    24
#include <plover/transaction.h>
ali@24
    25
#include <plover-gtk/transactionhelper.h>
ali@24
    26
ali@24
    27
/*
ali@24
    28
 * A PloverTransactionHelper uses a GtkAssistant to help a user run a
ali@24
    29
 * transaction.
ali@24
    30
 */
ali@24
    31
ali@24
    32
G_DEFINE_TYPE(PloverTransactionHelper,plover_transaction_helper,G_TYPE_OBJECT)
ali@24
    33
ali@24
    34
enum {
ali@24
    35
    CLOSE=0,
ali@24
    36
    N_SIGNALS
ali@24
    37
};
ali@24
    38
ali@24
    39
static guint signals[N_SIGNALS];
ali@24
    40
ali@24
    41
static void plover_transaction_helper_finalize(PloverTransactionHelper *helper)
ali@24
    42
{
ali@24
    43
    g_free(helper->error_primary_text);
ali@24
    44
    g_free(helper->base);
ali@24
    45
    g_free(helper->unsatisfied);
ali@24
    46
    if (helper->comps)
ali@24
    47
	plover_comps_free(helper->comps);
ali@24
    48
    plover_vector_free(helper->report_adding);
ali@24
    49
    plover_vector_free(helper->report_removing);
ali@24
    50
}
ali@24
    51
ali@24
    52
static void plover_transaction_helper_dispose(PloverTransactionHelper *helper)
ali@24
    53
{
ali@24
    54
    g_clear_error(&helper->error);
ali@24
    55
    if (helper->error_dialog)
ali@24
    56
    {
ali@24
    57
	g_signal_handlers_disconnect_by_data(helper->error_dialog,helper);
ali@24
    58
	gtk_widget_destroy(helper->error_dialog);
ali@24
    59
	helper->error_dialog=NULL;
ali@24
    60
    }
ali@24
    61
    if (helper->assistant)
ali@24
    62
    {
ali@24
    63
	g_signal_handlers_disconnect_by_data(helper->assistant,helper);
ali@24
    64
	g_clear_object(&helper->assistant);
ali@24
    65
    }
ali@24
    66
    g_clear_object(&helper->ui);
ali@24
    67
    g_slist_foreach(helper->transactions,(GFunc)g_object_unref,NULL);
ali@24
    68
    g_slist_free(helper->transactions);
ali@24
    69
    helper->transactions=NULL;
ali@24
    70
    g_clear_object(&helper->installed);
ali@24
    71
    g_clear_object(&helper->upstream);
ali@24
    72
    g_clear_object(&helper->relocated_upstream);
ali@24
    73
}
ali@24
    74
ali@24
    75
static void
ali@24
    76
  plover_transaction_helper_class_init(PloverTransactionHelperClass *klass)
ali@24
    77
{
ali@24
    78
    GObjectClass *gobject_class=G_OBJECT_CLASS(klass);
ali@24
    79
    gobject_class->finalize=
ali@24
    80
      (void (*)(GObject *))plover_transaction_helper_finalize;
ali@24
    81
    gobject_class->dispose=
ali@24
    82
      (void (*)(GObject *))plover_transaction_helper_dispose;
ali@24
    83
    signals[CLOSE]=g_signal_newv("close",
ali@24
    84
      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
ali@24
    85
      g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
ali@24
    86
}
ali@24
    87
ali@24
    88
static void plover_transaction_helper_init(PloverTransactionHelper *helper)
ali@24
    89
{
ali@24
    90
    helper->report_adding=plover_vector_new();
ali@24
    91
    helper->report_removing=plover_vector_new();
ali@24
    92
}
ali@24
    93
ali@24
    94
static void plover_transaction_helper_assistant_cancel(GtkAssistant *assistant,
ali@24
    95
  PloverTransactionHelper *helper)
ali@24
    96
{
ali@24
    97
    gtk_widget_hide(GTK_WIDGET(helper->assistant));
ali@24
    98
    gtk_assistant_set_current_page(helper->assistant,0);
ali@24
    99
    g_signal_emit(helper,signals[CLOSE],0);
ali@24
   100
}
ali@24
   101
ali@24
   102
static void plover_transaction_helper_assistant_close(GtkAssistant *assistant,
ali@24
   103
  PloverTransactionHelper *helper)
ali@24
   104
{
ali@24
   105
    gtk_widget_hide(GTK_WIDGET(helper->assistant));
ali@24
   106
    gtk_assistant_set_current_page(helper->assistant,0);
ali@24
   107
    g_signal_emit(helper,signals[CLOSE],0);
ali@24
   108
}
ali@24
   109
ali@24
   110
static void
ali@24
   111
  plover_transaction_helper_prepare_confirm(PloverTransactionHelper *helper)
ali@24
   112
{
ali@24
   113
    gchar *package_list,*add,*remove,*s;
ali@24
   114
    GtkLabel *label;
ali@24
   115
    struct plover_vector *report;
ali@24
   116
    if (helper->report_adding->len)
ali@24
   117
    {
ali@24
   118
	plover_vector_sort(helper->report_adding);
ali@24
   119
	if (helper->report_adding_dependencies)
ali@24
   120
	{
ali@24
   121
	    report=plover_vector_dup(helper->report_adding);
ali@24
   122
	    if (helper->report_adding->len==1)
ali@24
   123
		plover_vector_append(report,"its dependencies");
ali@24
   124
	    else
ali@24
   125
		plover_vector_append(report,"their dependencies");
ali@24
   126
	    package_list=plover_vector_format_for_display(report);
ali@24
   127
	    plover_vector_free(report);
ali@24
   128
	}
ali@24
   129
	else
ali@24
   130
	    package_list=
ali@24
   131
	      plover_vector_format_for_display(helper->report_adding);
ali@24
   132
	add=g_strconcat("Packages to be installed or updated: ",package_list,
ali@24
   133
	  ".",NULL);
ali@24
   134
	g_free(package_list);
ali@24
   135
    }
ali@24
   136
    else
ali@24
   137
	add=NULL;
ali@24
   138
    if (helper->report_removing->len)
ali@24
   139
    {
ali@24
   140
	plover_vector_sort(helper->report_removing);
ali@24
   141
	if (helper->report_removing_dependants)
ali@24
   142
	{
ali@24
   143
	    report=plover_vector_dup(helper->report_removing);
ali@24
   144
	    if (helper->report_adding->len==1)
ali@24
   145
		plover_vector_append(report,"its dependants");
ali@24
   146
	    else
ali@24
   147
		plover_vector_append(report,"their dependants");
ali@24
   148
	    package_list=plover_vector_format_for_display(report);
ali@24
   149
	    plover_vector_free(report);
ali@24
   150
	}
ali@24
   151
	else
ali@24
   152
	    package_list=
ali@24
   153
	      plover_vector_format_for_display(helper->report_removing);
ali@24
   154
	remove=g_strconcat("Packages to be removed: ",package_list,".",NULL);
ali@24
   155
	g_free(package_list);
ali@24
   156
    }
ali@24
   157
    else
ali@24
   158
	remove=NULL;
ali@24
   159
    label=GTK_LABEL(gtk_builder_get_object(helper->ui,"SISummaryOfWork"));
ali@24
   160
    if (add && remove)
ali@24
   161
	s=g_strconcat("<b>Installation Summary</b>\n\n",remove,"\n\n",add,NULL);
ali@24
   162
    else if (add || remove)
ali@24
   163
	s=g_strconcat("<b>Installation Summary</b>\n\n",add?add:remove,NULL);
ali@24
   164
    else
ali@24
   165
	s=g_strdup("<b>Installation Summary</b>\n\nNo changes scheduled");
ali@24
   166
    gtk_label_set_markup(label,s);
ali@24
   167
    g_free(s);
ali@24
   168
    g_free(add);
ali@24
   169
    g_free(remove);
ali@24
   170
}
ali@24
   171
ali@24
   172
static void plover_transaction_helper_run(PloverTransactionHelper *helper);
ali@24
   173
ali@24
   174
static void plover_transaction_helper_callback(GObject *source,
ali@24
   175
  GAsyncResult *result,gpointer user_data)
ali@24
   176
{
ali@24
   177
    GError *error=NULL;
ali@24
   178
    PloverTransactionHelper *helper=user_data;
ali@24
   179
    PloverTransaction *transaction=PLOVER_TRANSACTION(source);
ali@24
   180
    if (!plover_transaction_commit_finish(transaction,result,&error))
ali@24
   181
    {
ali@24
   182
	plover_transaction_helper_set_error(helper,error,
ali@24
   183
	  "Software installation failed");
ali@24
   184
	g_error_free(error);
ali@24
   185
    }
ali@24
   186
    else
ali@24
   187
	plover_transaction_helper_run(helper);
ali@24
   188
    g_signal_handlers_disconnect_by_data(transaction,helper);
ali@24
   189
    g_object_unref(transaction);
ali@24
   190
}
ali@24
   191
ali@24
   192
static void plover_transaction_helper_transaction_status_changed(
ali@24
   193
  PloverTransaction *transaction,const char *status,
ali@24
   194
  PloverTransactionHelper *helper)
ali@24
   195
{
ali@24
   196
    GtkProgressBar *bar;
ali@24
   197
    bar=GTK_PROGRESS_BAR(gtk_builder_get_object(helper->ui,"SIProgressBar"));
ali@24
   198
    gtk_progress_bar_set_text(bar,status);
ali@24
   199
}
ali@24
   200
ali@24
   201
static void plover_transaction_helper_run(PloverTransactionHelper *helper)
ali@24
   202
{
ali@24
   203
    PloverTransaction *transaction;
ali@24
   204
    GtkWidget *page;
ali@24
   205
    page=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress"));
ali@24
   206
    if (helper->transactions)
ali@24
   207
    {
ali@24
   208
	if (helper->assistant)
ali@24
   209
	    gtk_assistant_set_page_complete(helper->assistant,page,FALSE);
ali@24
   210
	transaction=helper->transactions->data;
ali@24
   211
	helper->transactions=g_slist_delete_link(helper->transactions,
ali@24
   212
	  helper->transactions);
ali@24
   213
	g_signal_connect(transaction,"status-changed",
ali@24
   214
	  G_CALLBACK(plover_transaction_helper_transaction_status_changed),
ali@24
   215
	  helper);
ali@24
   216
	plover_transaction_commit_async(transaction,NULL,
ali@24
   217
	  plover_transaction_helper_callback,helper);
ali@24
   218
    }
ali@24
   219
    else if (helper->assistant)
ali@24
   220
	gtk_assistant_set_page_complete(helper->assistant,page,TRUE);
ali@24
   221
}
ali@24
   222
ali@24
   223
static gboolean plover_transaction_helper_pulse(gpointer user_data)
ali@24
   224
{
ali@24
   225
    PloverTransactionHelper *helper=user_data;
ali@24
   226
    GtkWidget *w;
ali@24
   227
    GtkProgressBar *bar;
ali@24
   228
    if (!helper->assistant)
ali@24
   229
	return FALSE;
ali@24
   230
    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress"));
ali@24
   231
    bar=GTK_PROGRESS_BAR(gtk_builder_get_object(helper->ui,"SIProgressBar"));
ali@24
   232
    if (gtk_assistant_get_page_complete(helper->assistant,w))
ali@24
   233
    {
ali@24
   234
	gtk_progress_bar_set_fraction(bar,1.0);
ali@24
   235
	helper->pulse_handler=0;
ali@24
   236
	return FALSE;
ali@24
   237
    }
ali@24
   238
    else
ali@24
   239
    {
ali@24
   240
	gtk_progress_bar_pulse(bar);
ali@24
   241
	return TRUE;
ali@24
   242
    }
ali@24
   243
}
ali@24
   244
ali@24
   245
static void
ali@24
   246
  plover_transaction_helper_prepare_progress(PloverTransactionHelper *helper)
ali@24
   247
{
ali@24
   248
    GError *error=NULL;
ali@24
   249
    GtkToggleButton *button;
ali@24
   250
    PloverTransaction *transaction;
ali@24
   251
    button=GTK_TOGGLE_BUTTON(gtk_builder_get_object(helper->ui,
ali@24
   252
      "SIRemoveExisting"));
ali@24
   253
    if (gtk_toggle_button_get_active(button))
ali@24
   254
    {
ali@24
   255
	transaction=plover_transaction_new_remove(NULL,&error);
ali@24
   256
	if (!transaction)
ali@24
   257
	{
ali@24
   258
	    if (g_error_matches(error,PLOVER_POSIX_ERROR,ENOENT))
ali@24
   259
		g_clear_error(&error);
ali@24
   260
	    if (error)
ali@24
   261
	    {
ali@24
   262
		plover_transaction_helper_set_error(helper,error,
ali@24
   263
		  "Software installation failed");
ali@24
   264
		g_error_free(error);
ali@24
   265
		return;
ali@24
   266
	    }
ali@24
   267
	}
ali@24
   268
	else
ali@24
   269
	    helper->transactions=
ali@24
   270
	      g_slist_prepend(helper->transactions,transaction);
ali@24
   271
    }
ali@24
   272
    /*
ali@24
   273
     * Note that PloverTransaction does support cancelling a transaction, but
ali@24
   274
     * there are a number of challenges with using it:
ali@24
   275
     *	- cancellation is only supported during the file phase if razor
ali@24
   276
     *	  has atomic rollback,
ali@24
   277
     *  - cancellation is not supported during post-transaction scripts at all
ali@24
   278
     *    (since by the time the first script is started the atomic has already
ali@24
   279
     *    been committed) and these can take quite some time,
ali@24
   280
     *  - where a transaction has an embedded COMMIT, any rollback won't
ali@24
   281
     *    go back beyond this point.
ali@24
   282
     * To support user-cancel, then, we would need some mechanism to:
ali@24
   283
     *  - Comunicate that the operation is being cancelled and this may take
ali@24
   284
     *    some time,
ali@24
   285
     *  - Not allow cancellation at all after the last post-transaction script
ali@24
   286
     *    phase is started,
ali@24
   287
     *  - Report the partially completed transaction where cancellation
ali@24
   288
     *    occurred after a COMMIT point.
ali@24
   289
     * At present, this doesn't appear worth the effort.
ali@24
   290
     */
ali@24
   291
    if (helper->assistant)
ali@24
   292
	gtk_assistant_commit(helper->assistant);
ali@24
   293
    plover_transaction_helper_run(helper);
ali@24
   294
    helper->pulse_handler=g_timeout_add(100,plover_transaction_helper_pulse,
ali@24
   295
      helper);
ali@24
   296
}
ali@24
   297
ali@24
   298
static void plover_transaction_helper_assistant_prepare(GtkAssistant *assistant,
ali@24
   299
  GtkWidget *page,PloverTransactionHelper *helper)
ali@24
   300
{
ali@24
   301
    if (page==GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm")))
ali@24
   302
	plover_transaction_helper_prepare_confirm(helper);
ali@24
   303
    else if (page==GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress")))
ali@24
   304
	plover_transaction_helper_prepare_progress(helper);
ali@24
   305
}
ali@24
   306
ali@24
   307
static void
ali@24
   308
  plover_transaction_helper_remove_existing_toggled(GtkToggleButton *button,
ali@24
   309
  PloverTransactionHelper *helper)
ali@24
   310
{
ali@24
   311
    GtkWidget *w;
ali@24
   312
    if (helper->assistant)
ali@24
   313
    {
ali@24
   314
	w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm"));
ali@24
   315
	gtk_assistant_set_page_complete(helper->assistant,w,
ali@24
   316
	  gtk_toggle_button_get_active(button));
ali@24
   317
    }
ali@24
   318
}
ali@24
   319
ali@24
   320
PloverTransactionHelper *plover_transaction_helper_new(GtkBuilder *ui)
ali@24
   321
{
ali@24
   322
    gsize len;
ali@24
   323
    gchar *s,*directory,*contents;
ali@24
   324
    GError *error=NULL;
ali@24
   325
    GtkWidget *w;
ali@24
   326
    PloverTransactionHelper *helper;
ali@24
   327
    g_return_val_if_fail(ui == NULL || GTK_IS_BUILDER(ui),NULL);
ali@24
   328
    helper=PLOVER_TRANSACTION_HELPER(
ali@24
   329
      g_object_new(PLOVER_TYPE_TRANSACTION_HELPER,NULL));
ali@24
   330
    if (ui)
ali@24
   331
	helper->ui=g_object_ref(ui);
ali@24
   332
    else
ali@24
   333
	helper->ui=gtk_builder_new();
ali@24
   334
    helper->assistant=
ali@24
   335
      GTK_ASSISTANT(gtk_builder_get_object(helper->ui,"SoftwareInstallation"));
ali@24
   336
    if (!helper->assistant)
ali@24
   337
    {
ali@24
   338
	directory=g_strdup(g_getenv("PLOVER_DATADIR"));
ali@24
   339
	if (!directory)
ali@24
   340
	{
ali@24
   341
#ifdef WIN32
ali@24
   342
	    s=g_win32_get_package_installation_directory_of_module(NULL);
ali@24
   343
	    directory=g_build_filename(s,"share","plover",NULL);
ali@24
   344
	    g_free(s);
ali@24
   345
#else
ali@24
   346
	    directory=g_strdup(PLOVER_DATADIR);
ali@24
   347
#endif
ali@24
   348
	}
ali@24
   349
	s=g_build_filename(directory,"software-installation.ui",NULL);
ali@24
   350
	g_free(directory);
ali@24
   351
	(void)g_file_get_contents(s,&contents,&len,&error);
ali@24
   352
	g_free(s);
ali@24
   353
	if (!error)
ali@24
   354
	{
ali@24
   355
	    (void)gtk_builder_add_from_string(helper->ui,contents,len,&error);
ali@24
   356
	    g_free(contents);
ali@24
   357
	}
ali@24
   358
	if (error)
ali@24
   359
	{
ali@24
   360
	    g_critical("software-installation.ui: %s",error->message);
ali@24
   361
	    g_clear_error(&error);
ali@24
   362
	    g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
ali@24
   363
	      "Internal error (no user interface)");
ali@24
   364
	    plover_transaction_helper_set_error(helper,error,
ali@24
   365
	      "Can't start installer");
ali@24
   366
	    return helper;
ali@24
   367
	}
ali@24
   368
	helper->assistant=GTK_ASSISTANT(gtk_builder_get_object(helper->ui,
ali@24
   369
	  "SoftwareInstallation"));
ali@24
   370
    }
ali@24
   371
    if (!helper->assistant)
ali@24
   372
    {
ali@24
   373
	g_critical("\"SoftwareInstallation\" object not found");
ali@24
   374
	g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
ali@24
   375
	  "Internal error (missing wizard)");
ali@24
   376
	plover_transaction_helper_set_error(helper,error,
ali@24
   377
	  "Can't start installer");
ali@24
   378
	g_error_free(error);
ali@24
   379
	return helper;
ali@24
   380
    }
ali@24
   381
    else
ali@24
   382
	g_object_ref(helper->assistant);
ali@24
   383
    if (!GTK_IS_ASSISTANT(helper->assistant))
ali@24
   384
    {
ali@24
   385
	g_critical("\"SoftwareInstallation\" is not a GtkAssistant");
ali@24
   386
	g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
ali@24
   387
	  "Internal error (unexpected wizard type)");
ali@24
   388
	plover_transaction_helper_set_error(helper,error,
ali@24
   389
	  "Can't start installer");
ali@24
   390
	g_error_free(error);
ali@24
   391
	return helper;
ali@24
   392
    }
ali@24
   393
    g_signal_connect(helper->assistant,"cancel",
ali@24
   394
      G_CALLBACK(plover_transaction_helper_assistant_cancel),helper);
ali@24
   395
    g_signal_connect(helper->assistant,"close",
ali@24
   396
      G_CALLBACK(plover_transaction_helper_assistant_close),helper);
ali@24
   397
    g_signal_connect(helper->assistant,"prepare",
ali@24
   398
      G_CALLBACK(plover_transaction_helper_assistant_prepare),helper);
ali@24
   399
    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIRemoveExisting"));
ali@24
   400
    if (w)
ali@24
   401
	g_signal_connect(w,"toggled",
ali@24
   402
	  G_CALLBACK(plover_transaction_helper_remove_existing_toggled),helper);
ali@24
   403
    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIIntroduction"));
ali@24
   404
    if (w)
ali@24
   405
	gtk_assistant_set_page_complete(helper->assistant,w,TRUE);
ali@24
   406
    return helper;
ali@24
   407
}
ali@24
   408
ali@24
   409
PloverPackageSet *
ali@24
   410
  plover_transaction_helper_get_installed(PloverTransactionHelper *helper)
ali@24
   411
{
ali@24
   412
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   413
    return helper->installed;
ali@24
   414
}
ali@24
   415
ali@24
   416
void plover_transaction_helper_set_installed(PloverTransactionHelper *helper,
ali@24
   417
  PloverPackageSet *installed)
ali@24
   418
{
ali@24
   419
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   420
    g_return_if_fail(PLOVER_IS_PACKAGE_SET(installed));
ali@24
   421
    g_return_if_fail(helper->installed == NULL);
ali@24
   422
    helper->installed=g_object_ref(installed);
ali@24
   423
}
ali@24
   424
ali@24
   425
PloverRepository *
ali@24
   426
  plover_transaction_helper_get_upstream(PloverTransactionHelper *helper,
ali@24
   427
  GError **error)
ali@24
   428
{
ali@24
   429
    const char *base;
ali@24
   430
#if 0
ali@24
   431
    const char *prefix;
ali@24
   432
    struct razor_relocations *relocations=NULL;
ali@24
   433
#endif
ali@24
   434
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   435
    if (!helper->upstream)
ali@24
   436
    {
ali@24
   437
#if 0
ali@24
   438
	prefix=plover_transaction_helper_get_prefix(helper,error);
ali@24
   439
	if (!prefix)
ali@24
   440
	    return NULL;
ali@24
   441
#endif
ali@24
   442
	base=plover_transaction_helper_get_base(helper);
ali@24
   443
#if 0
ali@24
   444
	if (prefix)
ali@24
   445
	{
ali@24
   446
	    relocations=razor_relocations_create();
ali@24
   447
	    razor_relocations_add(relocations,"/usr",prefix);
ali@24
   448
	}
ali@24
   449
#endif
ali@24
   450
	helper->upstream=plover_repository_new_from_yum(base,error);
ali@24
   451
#if 0
ali@24
   452
	if (relocations)
ali@24
   453
	    razor_relocations_destroy(relocations);
ali@24
   454
#endif
ali@24
   455
    }
ali@24
   456
    return helper->upstream;
ali@24
   457
}
ali@24
   458
ali@24
   459
static PloverPackageSet *plover_transaction_helper_get_relocated_upstream(
ali@24
   460
  PloverTransactionHelper *helper,GError **error)
ali@24
   461
{
ali@24
   462
    const char *prefix;
ali@24
   463
    struct razor_relocations *relocations=NULL;
ali@24
   464
    GError *tmp_error=NULL;
ali@24
   465
    PloverRepository *upstream;
ali@24
   466
    PloverPackageSet *set;
ali@24
   467
    if (!helper->relocated_upstream)
ali@24
   468
    {
ali@24
   469
	upstream=plover_transaction_helper_get_upstream(helper,error);
ali@24
   470
	if (!upstream)
ali@24
   471
	    return NULL;
ali@24
   472
	prefix=plover_transaction_helper_get_prefix(helper,&tmp_error);
ali@24
   473
	if (tmp_error)
ali@24
   474
	{
ali@24
   475
	    g_propagate_error(error,tmp_error);
ali@24
   476
	    return NULL;
ali@24
   477
	}
ali@24
   478
	set=plover_repository_get_package_set(upstream);
ali@24
   479
	if (prefix)
ali@24
   480
	{
ali@24
   481
	    relocations=razor_relocations_create();
ali@24
   482
	    razor_relocations_add(relocations,"/usr",prefix);
ali@24
   483
	    helper->relocated_upstream=
ali@24
   484
	      plover_package_set_new_from_repository(upstream,relocations,
ali@24
   485
	      error);
ali@24
   486
	    if (relocations)
ali@24
   487
		razor_relocations_destroy(relocations);
ali@24
   488
	}
ali@24
   489
	else
ali@24
   490
	    helper->relocated_upstream=g_object_ref(set);
ali@24
   491
    }
ali@24
   492
    return helper->relocated_upstream;
ali@24
   493
}
ali@24
   494
ali@24
   495
void plover_transaction_helper_set_upstream(PloverTransactionHelper *helper,
ali@24
   496
  PloverRepository *upstream)
ali@24
   497
{
ali@24
   498
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   499
    g_return_if_fail(PLOVER_IS_REPOSITORY(upstream));
ali@24
   500
    g_return_if_fail(helper->upstream == NULL);
ali@24
   501
    helper->upstream=g_object_ref(upstream);
ali@24
   502
}
ali@24
   503
ali@24
   504
const char *plover_transaction_helper_get_base(PloverTransactionHelper *helper)
ali@24
   505
{
ali@24
   506
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   507
    return helper->base;
ali@24
   508
}
ali@24
   509
ali@24
   510
void plover_transaction_helper_set_base(PloverTransactionHelper *helper,
ali@24
   511
  const char *base)
ali@24
   512
{
ali@24
   513
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   514
    g_return_if_fail(helper->transactions == NULL);
ali@24
   515
    g_free(helper->base);
ali@24
   516
    helper->base=g_strdup(base);
ali@24
   517
}
ali@24
   518
ali@24
   519
struct comps *
ali@24
   520
  plover_transaction_helper_get_comps(PloverTransactionHelper *helper,
ali@24
   521
  GError **error)
ali@24
   522
{
ali@24
   523
    gchar *s;
ali@24
   524
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   525
    g_return_val_if_fail(helper->base != NULL,NULL);
ali@24
   526
    if (!helper->comps)
ali@24
   527
    {
ali@24
   528
	s=g_strconcat(helper->base,"/repodata/comps.xml",NULL);
ali@24
   529
	helper->comps=plover_comps_new_from_file(s);
ali@24
   530
	if (!helper->comps)
ali@24
   531
	    g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
   532
	      PLOVER_GENERAL_ERROR_FAILED,"%s: %s",s,g_strerror(errno));
ali@24
   533
	g_free(s);
ali@24
   534
    }
ali@24
   535
    return helper->comps;
ali@24
   536
}
ali@24
   537
ali@24
   538
const char *
ali@24
   539
  plover_transaction_helper_get_prefix(PloverTransactionHelper *helper,
ali@24
   540
  GError **error)
ali@24
   541
{
ali@24
   542
    const char *prefix;
ali@24
   543
    struct comps *comps;
ali@24
   544
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   545
    g_return_val_if_fail(helper->base != NULL || helper->installed != NULL,NULL);
ali@24
   546
    if (helper->base)
ali@24
   547
    {
ali@24
   548
	comps=plover_transaction_helper_get_comps(helper,error);
ali@24
   549
	if (!comps)
ali@24
   550
	    return NULL;
ali@24
   551
	return plover_default_prefix_for_vendor(comps->vendor);
ali@24
   552
    }
ali@24
   553
    prefix=plover_package_set_guess_prefix(helper->installed,error);
ali@24
   554
    return prefix;
ali@24
   555
}
ali@24
   556
ali@24
   557
static int plover_transaction_helper_package_count(void)
ali@24
   558
{
ali@24
   559
    int count=0;
ali@24
   560
    char *install_root;
ali@24
   561
    struct razor_set *set;
ali@24
   562
    struct razor_package *package;
ali@24
   563
    struct razor_package_iterator *pi;
ali@24
   564
    install_root=getenv("RAZOR_ROOT");
ali@24
   565
    if (!install_root)
ali@24
   566
	install_root="";
ali@24
   567
    set=razor_root_open_read_only(install_root,NULL);
ali@24
   568
    if (set)
ali@24
   569
    {
ali@24
   570
	pi=razor_package_iterator_create(set);
ali@24
   571
	while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_LAST))
ali@24
   572
	    count++;
ali@24
   573
	razor_package_iterator_destroy(pi);
ali@24
   574
	razor_set_unref(set);
ali@24
   575
    }
ali@24
   576
    return count;
ali@24
   577
}
ali@24
   578
ali@24
   579
static gboolean
ali@24
   580
  plover_transaction_helper_check_vendor(PloverTransactionHelper *helper,
ali@24
   581
  GError **error)
ali@24
   582
{
ali@24
   583
    int i;
ali@24
   584
    gchar *prefix=NULL,*s;
ali@24
   585
    struct comps *comps=NULL;
ali@24
   586
    GtkWidget *container,*page;
ali@24
   587
    GtkButton *button;
ali@24
   588
    GtkLabel *label;
ali@24
   589
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   590
    if (helper->check_vendor)
ali@24
   591
    {
ali@24
   592
	comps=plover_transaction_helper_get_comps(helper,error);
ali@24
   593
	if (!comps)
ali@24
   594
	    return FALSE;
ali@24
   595
	prefix=plover_default_prefix_for_vendor(comps->vendor);
ali@24
   596
    }
ali@24
   597
    button=GTK_BUTTON(gtk_builder_get_object(helper->ui,"SIRemoveExisting"));
ali@24
   598
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),FALSE);
ali@24
   599
    container=GTK_WIDGET(gtk_builder_get_object(helper->ui,
ali@24
   600
      "SIIncompatibleInstallation"));
ali@24
   601
    page=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm"));
ali@24
   602
    if (helper->check_vendor && prefix &&
ali@24
   603
      !plover_installed_files_match_prefix(prefix))
ali@24
   604
    {
ali@24
   605
	label=GTK_LABEL(gtk_builder_get_object(helper->ui,
ali@24
   606
	  "SIIncompatibleInstallationLabel"));
ali@24
   607
	s=g_strdup_printf("<b>Incompatible Installation</b>\n\n"
ali@24
   608
	  "The existing installation is not from %s.\n"
ali@24
   609
	  "In order to continue, all the existing packages must be removed.",
ali@24
   610
	  comps->vendor);
ali@24
   611
	gtk_label_set_markup(label,s);
ali@24
   612
	g_free(s);
ali@24
   613
	i=plover_transaction_helper_package_count();
ali@24
   614
	s=g_strdup_printf("Remove %d existing package%s",i,i==1?"":"s");
ali@24
   615
	gtk_button_set_label(button,s);
ali@24
   616
	g_free(s);
ali@24
   617
	gtk_widget_show(container);
ali@24
   618
	if (helper->assistant)
ali@24
   619
	    gtk_assistant_set_page_complete(helper->assistant,page,FALSE);
ali@24
   620
    }
ali@24
   621
    else
ali@24
   622
    {
ali@24
   623
	gtk_widget_hide(container);
ali@24
   624
	if (helper->assistant)
ali@24
   625
	    gtk_assistant_set_page_complete(helper->assistant,page,TRUE);
ali@24
   626
    }
ali@24
   627
    return TRUE;
ali@24
   628
}
ali@24
   629
ali@24
   630
void plover_transaction_helper_set_check_vendor(PloverTransactionHelper *helper,
ali@24
   631
  gboolean check_vendor)
ali@24
   632
{
ali@24
   633
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   634
    if (helper->check_vendor!=check_vendor)
ali@24
   635
    {
ali@24
   636
	helper->check_vendor=check_vendor;
ali@24
   637
	if (helper->transactions)
ali@24
   638
	    plover_transaction_helper_check_vendor(helper,NULL);
ali@24
   639
    }
ali@24
   640
}
ali@24
   641
ali@24
   642
/*
ali@24
   643
 * If plover_transaction_helper_add_transaction() failes with an error
ali@24
   644
 * of PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET
ali@24
   645
 * then plover_transaction_helper_get_unsatisfied() can be used to
ali@24
   646
 * retrieve a textual description of the problem.
ali@24
   647
 */
ali@24
   648
ali@24
   649
const char *
ali@24
   650
  plover_transaction_helper_get_unsatisfied(PloverTransactionHelper *helper)
ali@24
   651
{
ali@24
   652
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   653
    return helper->unsatisfied;
ali@24
   654
}
ali@24
   655
ali@24
   656
gboolean
ali@24
   657
  plover_transaction_helper_add_transaction(PloverTransactionHelper *helper,
ali@24
   658
  PloverTransaction *transaction,struct plover_vector *report_packages,
ali@24
   659
  enum razor_install_action report_action,GError **error)
ali@24
   660
{
ali@24
   661
    int i,count;
ali@24
   662
    gboolean other_packages;
ali@24
   663
    const char *s,*name;
ali@24
   664
    enum razor_install_action action;
ali@24
   665
    struct razor_install_iterator *ii;
ali@24
   666
    struct razor_set *next;
ali@24
   667
    struct razor_package *package;
ali@24
   668
    struct plover_vector *tasked_packages;
ali@24
   669
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   670
    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
ali@24
   671
    g_return_val_if_fail(report_action==RAZOR_INSTALL_ACTION_ADD || report_action==RAZOR_INSTALL_ACTION_REMOVE,FALSE);
ali@24
   672
    g_free(helper->unsatisfied);
ali@24
   673
    helper->unsatisfied=NULL;
ali@24
   674
    if (!plover_transaction_resolve(transaction,error))
ali@24
   675
    {
ali@24
   676
	s=plover_transaction_get_unsatisfied(transaction);
ali@24
   677
	helper->unsatisfied=g_strdup(s);
ali@24
   678
	return FALSE;
ali@24
   679
    }
ali@24
   680
    ii=plover_transaction_get_install_iterator(transaction,error);
ali@24
   681
    if (!ii)
ali@24
   682
	return FALSE;
ali@24
   683
    next=plover_transaction_get_next_set(transaction,error);
ali@24
   684
    if (!next)
ali@24
   685
	return FALSE;
ali@24
   686
    tasked_packages=plover_vector_new();
ali@24
   687
    other_packages=FALSE;
ali@24
   688
    while (razor_install_iterator_next(ii,&package,&action,&count))
ali@24
   689
    {
ali@24
   690
	if (action==report_action)
ali@24
   691
	{
ali@24
   692
	    razor_package_get_details(next,package,RAZOR_DETAIL_NAME,&name,
ali@24
   693
	      RAZOR_DETAIL_LAST);
ali@24
   694
	    if (!report_packages ||
ali@24
   695
	      plover_vector_contains(report_packages,name))
ali@24
   696
		plover_vector_append(tasked_packages,name);
ali@24
   697
	    else
ali@24
   698
		other_packages=TRUE;
ali@24
   699
	}
ali@24
   700
    }
ali@24
   701
    if (!tasked_packages->len)
ali@24
   702
    {
ali@24
   703
	/*
ali@24
   704
	 * If there are no reportable packages tasked for action there
ali@24
   705
	 * shouldn't by any packages at all, but let's be paranoid.
ali@24
   706
	 */
ali@24
   707
	other_packages=FALSE;
ali@24
   708
	razor_install_iterator_rewind(ii);
ali@24
   709
	while (razor_install_iterator_next(ii,&package,&action,&count))
ali@24
   710
	{
ali@24
   711
	    if (action==report_action)
ali@24
   712
	    {
ali@24
   713
		razor_package_get_details(next,package,RAZOR_DETAIL_NAME,&name,
ali@24
   714
		  RAZOR_DETAIL_LAST);
ali@24
   715
		plover_vector_append(tasked_packages,name);
ali@24
   716
	    }
ali@24
   717
	}
ali@24
   718
    }
ali@24
   719
    if (!tasked_packages->len)
ali@24
   720
    {
ali@24
   721
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
   722
	  PLOVER_GENERAL_ERROR_NO_WORK,"Transaction includes no %s actions",
ali@24
   723
	  report_action==RAZOR_INSTALL_ACTION_ADD?"add":"remove");
ali@24
   724
	plover_vector_free(tasked_packages);
ali@24
   725
	return FALSE;
ali@24
   726
    }
ali@24
   727
    if (!helper->transactions)
ali@24
   728
	plover_transaction_helper_check_vendor(helper,error);
ali@24
   729
    g_object_ref(transaction);
ali@24
   730
    helper->transactions=g_slist_append(helper->transactions,transaction);
ali@24
   731
    if (report_action==RAZOR_INSTALL_ACTION_ADD)
ali@24
   732
    {
ali@24
   733
	for(i=0;i<tasked_packages->len;i++)
ali@24
   734
	{
ali@24
   735
	    s=tasked_packages->strings[i];
ali@24
   736
	    if (!plover_vector_contains(helper->report_adding,s))
ali@24
   737
		plover_vector_append(helper->report_adding,s);
ali@24
   738
	}
ali@24
   739
	helper->report_adding_dependencies|=other_packages;
ali@24
   740
    }
ali@24
   741
    else
ali@24
   742
    {
ali@24
   743
	for(i=0;i<tasked_packages->len;i++)
ali@24
   744
	{
ali@24
   745
	    s=tasked_packages->strings[i];
ali@24
   746
	    if (!plover_vector_contains(helper->report_removing,s))
ali@24
   747
		plover_vector_append(helper->report_removing,s);
ali@24
   748
	}
ali@24
   749
	helper->report_removing_dependants|=other_packages;
ali@24
   750
    }
ali@24
   751
    plover_vector_free(tasked_packages);
ali@24
   752
    return TRUE;
ali@24
   753
}
ali@24
   754
ali@24
   755
static PloverTransaction *
ali@24
   756
  plover_transaction_helper_new_transaction(PloverTransactionHelper *helper,
ali@24
   757
  GError **error)
ali@24
   758
{
ali@24
   759
    gboolean ok;
ali@24
   760
    const char *base,*prefix;
ali@24
   761
    GError *tmp_error=NULL;
ali@24
   762
    PloverTransaction *transaction;
ali@24
   763
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   764
    prefix=plover_transaction_helper_get_prefix(helper,&tmp_error);
ali@24
   765
    if (tmp_error)
ali@24
   766
    {
ali@24
   767
	g_propagate_error(error,tmp_error);
ali@24
   768
	return NULL;
ali@24
   769
    }
ali@24
   770
    transaction=plover_transaction_new();
ali@24
   771
    plover_transaction_set_prefix(transaction,prefix);
ali@24
   772
    plover_transaction_set_installed(transaction,helper->installed);
ali@24
   773
    if (helper->upstream)
ali@24
   774
	ok=plover_transaction_set_upstream(transaction,helper->upstream,error);
ali@24
   775
    else
ali@24
   776
    {
ali@24
   777
	base=plover_transaction_helper_get_base(helper);
ali@24
   778
	ok=plover_transaction_set_upstream_from_yum(transaction,base,error);
ali@24
   779
    }
ali@24
   780
    if (!ok)
ali@24
   781
    {
ali@24
   782
	g_object_unref(transaction);
ali@24
   783
	transaction=NULL;
ali@24
   784
    }
ali@24
   785
    return transaction;
ali@24
   786
}
ali@24
   787
ali@24
   788
struct plover_vector *plover_transaction_helper_group_get_default_packages(
ali@24
   789
  PloverTransactionHelper *helper,const char *group,GError **error)
ali@24
   790
{
ali@24
   791
    gboolean changed;
ali@24
   792
    struct comps *comps;
ali@24
   793
    struct comps_group *grp;
ali@24
   794
    struct comps_requirement *pkg;
ali@24
   795
    struct plover_vector *default_packages;
ali@24
   796
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   797
    comps=plover_transaction_helper_get_comps(helper,error);
ali@24
   798
    if (!comps)
ali@24
   799
	return NULL;
ali@24
   800
    grp=plover_comps_lookup_group(comps,group);
ali@24
   801
    if (!grp)
ali@24
   802
    {
ali@24
   803
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
   804
	  PLOVER_GENERAL_ERROR_FAILED,"%s: group not found",group);
ali@24
   805
	return NULL;
ali@24
   806
    }
ali@24
   807
    default_packages=plover_vector_new();
ali@24
   808
    do
ali@24
   809
    {
ali@24
   810
	changed=FALSE;
ali@24
   811
	for(pkg=grp->packages;pkg;pkg=pkg->next)
ali@24
   812
	{
ali@24
   813
	    if (plover_vector_contains(default_packages,pkg->name))
ali@24
   814
		continue;
ali@24
   815
	    if (pkg->type==COMPS_REQUIREMENT_DEFAULT ||
ali@24
   816
	      pkg->type==COMPS_REQUIREMENT_MANDATORY ||
ali@24
   817
	      pkg->type==COMPS_REQUIREMENT_CONDITIONAL &&
ali@24
   818
	      plover_vector_contains(default_packages,pkg->requires))
ali@24
   819
	    {
ali@24
   820
		changed=TRUE;
ali@24
   821
		plover_vector_append(default_packages,pkg->name);
ali@24
   822
	    }
ali@24
   823
	}
ali@24
   824
    } while(changed);
ali@24
   825
    return default_packages;
ali@24
   826
}
ali@24
   827
ali@24
   828
/*
ali@24
   829
 * Returns TRUE if there is work to be done or FALSE if the packages are
ali@24
   830
 * already installed or on error.
ali@24
   831
 */
ali@24
   832
gboolean
ali@24
   833
  plover_transaction_helper_install_packages(PloverTransactionHelper *helper,
ali@24
   834
  struct plover_vector *packages,GError **error)
ali@24
   835
{
ali@24
   836
    gboolean retval;
ali@24
   837
    PloverTransaction *transaction;
ali@24
   838
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   839
    g_return_val_if_fail(packages != NULL,FALSE);
ali@24
   840
    if (!packages->len)
ali@24
   841
    {
ali@24
   842
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
   843
	  PLOVER_GENERAL_ERROR_NO_WORK,"No packages listed to be installed");
ali@24
   844
	return FALSE;
ali@24
   845
    }
ali@24
   846
    transaction=plover_transaction_helper_new_transaction(helper,error);
ali@24
   847
    if (!transaction)
ali@24
   848
	return FALSE;
ali@24
   849
    if (!plover_transaction_install(transaction,packages->strings,error))
ali@24
   850
    {
ali@24
   851
	g_object_unref(transaction);
ali@24
   852
	return FALSE;
ali@24
   853
    }
ali@24
   854
    retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@24
   855
      packages,RAZOR_INSTALL_ACTION_ADD,error);
ali@24
   856
    g_object_unref(transaction);
ali@24
   857
    return retval;
ali@24
   858
}
ali@24
   859
ali@24
   860
/*
ali@24
   861
 * Returns TRUE if there is work to be done or FALSE if the group is
ali@24
   862
 * already installed or on error.
ali@24
   863
 */
ali@24
   864
gboolean
ali@24
   865
  plover_transaction_helper_install_group(PloverTransactionHelper *helper,
ali@24
   866
  const char *group,GError **error)
ali@24
   867
{
ali@24
   868
    gboolean retval;
ali@24
   869
    struct plover_vector *selected_packages;
ali@24
   870
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   871
    selected_packages=plover_transaction_helper_group_get_default_packages(
ali@24
   872
      helper,group,error);
ali@24
   873
    if (!selected_packages)
ali@24
   874
	return FALSE;
ali@24
   875
    if (!selected_packages->len)
ali@24
   876
    {
ali@24
   877
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
   878
	  PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
ali@24
   879
	plover_vector_free(selected_packages);
ali@24
   880
	return FALSE;
ali@24
   881
    }
ali@24
   882
    retval=plover_transaction_helper_install_packages(helper,selected_packages,
ali@24
   883
      error);
ali@24
   884
    plover_vector_free(selected_packages);
ali@24
   885
    return retval;
ali@24
   886
}
ali@24
   887
ali@24
   888
/*
ali@24
   889
 * Returns TRUE if there is work to be done or FALSE if the group is
ali@24
   890
 * not installed or on error.
ali@24
   891
 */
ali@24
   892
gboolean plover_transaction_helper_remove_group(PloverTransactionHelper *helper,
ali@24
   893
  const char *group,GError **error)
ali@24
   894
{
ali@24
   895
    gboolean retval;
ali@24
   896
    struct plover_vector *selected_packages;
ali@24
   897
    PloverTransaction *transaction;
ali@24
   898
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   899
    selected_packages=plover_transaction_helper_group_get_default_packages(
ali@24
   900
      helper,group,error);
ali@24
   901
    if (!selected_packages)
ali@24
   902
	return FALSE;
ali@24
   903
    if (!selected_packages->len)
ali@24
   904
    {
ali@24
   905
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
   906
	  PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
ali@24
   907
	plover_vector_free(selected_packages);
ali@24
   908
	return FALSE;
ali@24
   909
    }
ali@24
   910
    transaction=plover_transaction_new();
ali@24
   911
    plover_transaction_set_installed(transaction,helper->installed);
ali@24
   912
    if (!plover_transaction_remove(transaction,selected_packages->strings,
ali@24
   913
      error))
ali@24
   914
    {
ali@24
   915
	plover_vector_free(selected_packages);
ali@24
   916
	g_object_unref(transaction);
ali@24
   917
	return FALSE;
ali@24
   918
    }
ali@24
   919
    retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@24
   920
      NULL,RAZOR_INSTALL_ACTION_REMOVE,error);
ali@24
   921
    g_object_unref(transaction);
ali@24
   922
    plover_vector_free(selected_packages);
ali@24
   923
    return retval;
ali@24
   924
}
ali@24
   925
ali@24
   926
/*
ali@24
   927
 * Returns TRUE if there is work to be done or FALSE if all updates have
ali@24
   928
 * already been applied or on error.
ali@24
   929
 */
ali@24
   930
gboolean plover_transaction_helper_update(PloverTransactionHelper *helper,
ali@24
   931
  GError **error)
ali@24
   932
{
ali@24
   933
    gboolean retval;
ali@24
   934
    PloverTransaction *transaction;
ali@24
   935
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   936
    transaction=plover_transaction_helper_new_transaction(helper,error);
ali@24
   937
    if (!transaction)
ali@24
   938
	return FALSE;
ali@24
   939
    if (!plover_transaction_update(transaction,NULL,error))
ali@24
   940
    {
ali@24
   941
	g_object_unref(transaction);
ali@24
   942
	return FALSE;
ali@24
   943
    }
ali@24
   944
    retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@24
   945
      NULL,RAZOR_INSTALL_ACTION_ADD,error);
ali@24
   946
    g_object_unref(transaction);
ali@24
   947
    return retval;
ali@24
   948
}
ali@24
   949
ali@24
   950
gboolean plover_transaction_helper_get_visible(PloverTransactionHelper *helper)
ali@24
   951
{
ali@24
   952
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   953
    if (helper->error_dialog)
ali@24
   954
	return TRUE;
ali@24
   955
    else if (!helper->assistant)
ali@24
   956
	return FALSE;
ali@24
   957
    else
ali@24
   958
	return gtk_widget_get_visible(GTK_WIDGET(helper->assistant));
ali@24
   959
}
ali@24
   960
ali@24
   961
void plover_transaction_helper_present(PloverTransactionHelper *helper)
ali@24
   962
{
ali@24
   963
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   964
    if (helper->error_dialog)
ali@24
   965
	gtk_window_present(GTK_WINDOW(helper->error_dialog));
ali@24
   966
    else if (helper->assistant)
ali@24
   967
	gtk_window_present(GTK_WINDOW(helper->assistant));
ali@24
   968
}
ali@24
   969
ali@24
   970
static void
ali@24
   971
  plover_transaction_helper_error_dialog_response(GtkDialog *error_dialog,
ali@24
   972
  int response_id,PloverTransactionHelper *helper)
ali@24
   973
{
ali@24
   974
    g_signal_handlers_disconnect_by_data(error_dialog,helper);
ali@24
   975
    if ((GtkWidget *)error_dialog==helper->error_dialog)
ali@24
   976
    {
ali@24
   977
	gtk_widget_destroy(helper->error_dialog);
ali@24
   978
	helper->error_dialog=NULL;
ali@24
   979
	if (helper->assistant)
ali@24
   980
	{
ali@24
   981
	    gtk_widget_hide(GTK_WIDGET(helper->assistant));
ali@24
   982
	    gtk_assistant_set_current_page(helper->assistant,0);
ali@24
   983
	}
ali@24
   984
	g_signal_emit(helper,signals[CLOSE],0);
ali@24
   985
    }
ali@24
   986
}
ali@24
   987
ali@24
   988
const char *plover_transaction_helper_get_error(PloverTransactionHelper *helper,
ali@24
   989
  const GError **error)
ali@24
   990
{
ali@24
   991
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   992
    if (!helper->error_dialog)
ali@24
   993
	return NULL;
ali@24
   994
    if (error)
ali@24
   995
	*error=helper->error;
ali@24
   996
    return helper->error_primary_text;
ali@24
   997
}
ali@24
   998
ali@24
   999
void plover_transaction_helper_set_error(PloverTransactionHelper *helper,
ali@24
  1000
  const GError *error,const char *primary_text)
ali@24
  1001
{
ali@24
  1002
    GtkMessageType type;
ali@24
  1003
    GtkWindow *window;
ali@24
  1004
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
  1005
    g_return_if_fail(error != NULL);
ali@24
  1006
    g_return_if_fail(primary_text != NULL);
ali@24
  1007
    if (helper->pulse_handler)
ali@24
  1008
    {
ali@24
  1009
	g_source_remove(helper->pulse_handler);
ali@24
  1010
	helper->pulse_handler=0;
ali@24
  1011
    }
ali@24
  1012
    if (helper->error_dialog)
ali@24
  1013
    {
ali@24
  1014
	gtk_widget_destroy(helper->error_dialog);
ali@24
  1015
	helper->error_dialog=NULL;
ali@24
  1016
    }
ali@24
  1017
    g_free(helper->error_primary_text);
ali@24
  1018
    helper->error_primary_text=g_strdup(primary_text);
ali@24
  1019
    g_clear_error(&helper->error);
ali@24
  1020
    helper->error=g_error_copy(error);
ali@24
  1021
    if (g_error_matches(error,PLOVER_GENERAL_ERROR,
ali@24
  1022
      PLOVER_GENERAL_ERROR_NO_WORK))
ali@24
  1023
	type=GTK_MESSAGE_INFO;
ali@24
  1024
    else
ali@24
  1025
	type=GTK_MESSAGE_ERROR;
ali@24
  1026
    if (helper->assistant)
ali@24
  1027
	window=GTK_WINDOW(helper->assistant);
ali@24
  1028
    else
ali@24
  1029
    	window=NULL;
ali@24
  1030
    helper->error_dialog=gtk_message_dialog_new(window,
ali@24
  1031
      GTK_DIALOG_DESTROY_WITH_PARENT,type,GTK_BUTTONS_CLOSE,primary_text);
ali@24
  1032
    gtk_message_dialog_format_secondary_text(
ali@24
  1033
      GTK_MESSAGE_DIALOG(helper->error_dialog),error->message);
ali@24
  1034
    gtk_widget_show(helper->error_dialog);
ali@24
  1035
    g_signal_connect(helper->error_dialog,"response",
ali@24
  1036
      G_CALLBACK(plover_transaction_helper_error_dialog_response),helper);
ali@24
  1037
}