2 * Copyright (C) 2014 J. Ali Harlow <ali@juiblex.co.uk>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <plover/plover.h>
24 #include <plover/transaction.h>
25 #include <plover-gtk/transactionhelper.h>
28 * A PloverTransactionHelper uses a GtkAssistant to help a user run a
32 G_DEFINE_TYPE(PloverTransactionHelper,plover_transaction_helper,G_TYPE_OBJECT)
39 static guint signals[N_SIGNALS];
41 static void plover_transaction_helper_finalize(PloverTransactionHelper *helper)
43 g_free(helper->error_primary_text);
45 g_free(helper->unsatisfied);
47 plover_comps_free(helper->comps);
48 plover_vector_free(helper->report_adding);
49 plover_vector_free(helper->report_removing);
52 static void plover_transaction_helper_dispose(PloverTransactionHelper *helper)
54 g_clear_error(&helper->error);
55 if (helper->error_dialog)
57 g_signal_handlers_disconnect_by_data(helper->error_dialog,helper);
58 gtk_widget_destroy(helper->error_dialog);
59 helper->error_dialog=NULL;
61 if (helper->assistant)
63 g_signal_handlers_disconnect_by_data(helper->assistant,helper);
64 g_clear_object(&helper->assistant);
66 g_clear_object(&helper->ui);
67 g_slist_foreach(helper->transactions,(GFunc)g_object_unref,NULL);
68 g_slist_free(helper->transactions);
69 helper->transactions=NULL;
70 g_clear_object(&helper->installed);
71 g_clear_object(&helper->upstream);
72 g_clear_object(&helper->relocated_upstream);
76 plover_transaction_helper_class_init(PloverTransactionHelperClass *klass)
78 GObjectClass *gobject_class=G_OBJECT_CLASS(klass);
79 gobject_class->finalize=
80 (void (*)(GObject *))plover_transaction_helper_finalize;
81 gobject_class->dispose=
82 (void (*)(GObject *))plover_transaction_helper_dispose;
83 signals[CLOSE]=g_signal_newv("close",
84 G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
85 g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
88 static void plover_transaction_helper_init(PloverTransactionHelper *helper)
90 helper->report_adding=plover_vector_new();
91 helper->report_removing=plover_vector_new();
94 static void plover_transaction_helper_assistant_cancel(GtkAssistant *assistant,
95 PloverTransactionHelper *helper)
97 gtk_widget_hide(GTK_WIDGET(helper->assistant));
98 gtk_assistant_set_current_page(helper->assistant,0);
99 g_signal_emit(helper,signals[CLOSE],0);
102 static void plover_transaction_helper_assistant_close(GtkAssistant *assistant,
103 PloverTransactionHelper *helper)
105 gtk_widget_hide(GTK_WIDGET(helper->assistant));
106 gtk_assistant_set_current_page(helper->assistant,0);
107 g_signal_emit(helper,signals[CLOSE],0);
111 plover_transaction_helper_prepare_confirm(PloverTransactionHelper *helper)
113 gchar *package_list,*add,*remove,*s;
115 struct plover_vector *report;
116 if (helper->report_adding->len)
118 plover_vector_sort(helper->report_adding);
119 if (helper->report_adding_dependencies)
121 report=plover_vector_dup(helper->report_adding);
122 if (helper->report_adding->len==1)
123 plover_vector_append(report,"its dependencies");
125 plover_vector_append(report,"their dependencies");
126 package_list=plover_vector_format_for_display(report);
127 plover_vector_free(report);
131 plover_vector_format_for_display(helper->report_adding);
132 add=g_strconcat("Packages to be installed or updated: ",package_list,
134 g_free(package_list);
138 if (helper->report_removing->len)
140 plover_vector_sort(helper->report_removing);
141 if (helper->report_removing_dependants)
143 report=plover_vector_dup(helper->report_removing);
144 if (helper->report_adding->len==1)
145 plover_vector_append(report,"its dependants");
147 plover_vector_append(report,"their dependants");
148 package_list=plover_vector_format_for_display(report);
149 plover_vector_free(report);
153 plover_vector_format_for_display(helper->report_removing);
154 remove=g_strconcat("Packages to be removed: ",package_list,".",NULL);
155 g_free(package_list);
159 label=GTK_LABEL(gtk_builder_get_object(helper->ui,"SISummaryOfWork"));
161 s=g_strconcat("<b>Installation Summary</b>\n\n",remove,"\n\n",add,NULL);
162 else if (add || remove)
163 s=g_strconcat("<b>Installation Summary</b>\n\n",add?add:remove,NULL);
165 s=g_strdup("<b>Installation Summary</b>\n\nNo changes scheduled");
166 gtk_label_set_markup(label,s);
172 static void plover_transaction_helper_run(PloverTransactionHelper *helper);
174 static void plover_transaction_helper_callback(GObject *source,
175 GAsyncResult *result,gpointer user_data)
178 PloverTransactionHelper *helper=user_data;
179 PloverTransaction *transaction=PLOVER_TRANSACTION(source);
180 if (!plover_transaction_commit_finish(transaction,result,&error))
182 plover_transaction_helper_set_error(helper,error,
183 "Software installation failed");
187 plover_transaction_helper_run(helper);
188 g_signal_handlers_disconnect_by_data(transaction,helper);
189 g_object_unref(transaction);
192 static void plover_transaction_helper_transaction_status_changed(
193 PloverTransaction *transaction,const char *status,
194 PloverTransactionHelper *helper)
197 bar=GTK_PROGRESS_BAR(gtk_builder_get_object(helper->ui,"SIProgressBar"));
198 gtk_progress_bar_set_text(bar,status);
201 static void plover_transaction_helper_run(PloverTransactionHelper *helper)
203 PloverTransaction *transaction;
205 page=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress"));
206 if (helper->transactions)
208 if (helper->assistant)
209 gtk_assistant_set_page_complete(helper->assistant,page,FALSE);
210 transaction=helper->transactions->data;
211 helper->transactions=g_slist_delete_link(helper->transactions,
212 helper->transactions);
213 g_signal_connect(transaction,"status-changed",
214 G_CALLBACK(plover_transaction_helper_transaction_status_changed),
216 plover_transaction_commit_async(transaction,NULL,
217 plover_transaction_helper_callback,helper);
219 else if (helper->assistant)
220 gtk_assistant_set_page_complete(helper->assistant,page,TRUE);
223 static gboolean plover_transaction_helper_pulse(gpointer user_data)
225 PloverTransactionHelper *helper=user_data;
228 if (!helper->assistant)
230 w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress"));
231 bar=GTK_PROGRESS_BAR(gtk_builder_get_object(helper->ui,"SIProgressBar"));
232 if (gtk_assistant_get_page_complete(helper->assistant,w))
234 gtk_progress_bar_set_fraction(bar,1.0);
235 helper->pulse_handler=0;
240 gtk_progress_bar_pulse(bar);
246 plover_transaction_helper_prepare_progress(PloverTransactionHelper *helper)
249 GtkToggleButton *button;
250 PloverTransaction *transaction;
251 button=GTK_TOGGLE_BUTTON(gtk_builder_get_object(helper->ui,
252 "SIRemoveExisting"));
253 if (gtk_toggle_button_get_active(button))
255 transaction=plover_transaction_new_remove(NULL,&error);
258 if (g_error_matches(error,PLOVER_POSIX_ERROR,ENOENT))
259 g_clear_error(&error);
262 plover_transaction_helper_set_error(helper,error,
263 "Software installation failed");
269 helper->transactions=
270 g_slist_prepend(helper->transactions,transaction);
273 * Note that PloverTransaction does support cancelling a transaction, but
274 * there are a number of challenges with using it:
275 * - cancellation is only supported during the file phase if razor
276 * has atomic rollback,
277 * - cancellation is not supported during post-transaction scripts at all
278 * (since by the time the first script is started the atomic has already
279 * been committed) and these can take quite some time,
280 * - where a transaction has an embedded COMMIT, any rollback won't
281 * go back beyond this point.
282 * To support user-cancel, then, we would need some mechanism to:
283 * - Comunicate that the operation is being cancelled and this may take
285 * - Not allow cancellation at all after the last post-transaction script
287 * - Report the partially completed transaction where cancellation
288 * occurred after a COMMIT point.
289 * At present, this doesn't appear worth the effort.
291 if (helper->assistant)
292 gtk_assistant_commit(helper->assistant);
293 plover_transaction_helper_run(helper);
294 helper->pulse_handler=g_timeout_add(100,plover_transaction_helper_pulse,
298 static void plover_transaction_helper_assistant_prepare(GtkAssistant *assistant,
299 GtkWidget *page,PloverTransactionHelper *helper)
301 if (page==GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm")))
302 plover_transaction_helper_prepare_confirm(helper);
303 else if (page==GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress")))
304 plover_transaction_helper_prepare_progress(helper);
308 plover_transaction_helper_remove_existing_toggled(GtkToggleButton *button,
309 PloverTransactionHelper *helper)
312 if (helper->assistant)
314 w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm"));
315 gtk_assistant_set_page_complete(helper->assistant,w,
316 gtk_toggle_button_get_active(button));
320 PloverTransactionHelper *plover_transaction_helper_new(GtkBuilder *ui)
323 gchar *s,*directory,*contents;
326 PloverTransactionHelper *helper;
327 g_return_val_if_fail(ui == NULL || GTK_IS_BUILDER(ui),NULL);
328 helper=PLOVER_TRANSACTION_HELPER(
329 g_object_new(PLOVER_TYPE_TRANSACTION_HELPER,NULL));
331 helper->ui=g_object_ref(ui);
333 helper->ui=gtk_builder_new();
335 GTK_ASSISTANT(gtk_builder_get_object(helper->ui,"SoftwareInstallation"));
336 if (!helper->assistant)
338 directory=g_strdup(g_getenv("PLOVER_DATADIR"));
342 s=g_win32_get_package_installation_directory_of_module(NULL);
343 directory=g_build_filename(s,"share","plover",NULL);
346 directory=g_strdup(PLOVER_DATADIR);
349 s=g_build_filename(directory,"software-installation.ui",NULL);
351 (void)g_file_get_contents(s,&contents,&len,&error);
355 (void)gtk_builder_add_from_string(helper->ui,contents,len,&error);
360 g_critical("software-installation.ui: %s",error->message);
361 g_clear_error(&error);
362 g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
363 "Internal error (no user interface)");
364 plover_transaction_helper_set_error(helper,error,
365 "Can't start installer");
368 helper->assistant=GTK_ASSISTANT(gtk_builder_get_object(helper->ui,
369 "SoftwareInstallation"));
371 if (!helper->assistant)
373 g_critical("\"SoftwareInstallation\" object not found");
374 g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
375 "Internal error (missing wizard)");
376 plover_transaction_helper_set_error(helper,error,
377 "Can't start installer");
382 g_object_ref(helper->assistant);
383 if (!GTK_IS_ASSISTANT(helper->assistant))
385 g_critical("\"SoftwareInstallation\" is not a GtkAssistant");
386 g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
387 "Internal error (unexpected wizard type)");
388 plover_transaction_helper_set_error(helper,error,
389 "Can't start installer");
393 g_signal_connect(helper->assistant,"cancel",
394 G_CALLBACK(plover_transaction_helper_assistant_cancel),helper);
395 g_signal_connect(helper->assistant,"close",
396 G_CALLBACK(plover_transaction_helper_assistant_close),helper);
397 g_signal_connect(helper->assistant,"prepare",
398 G_CALLBACK(plover_transaction_helper_assistant_prepare),helper);
399 w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIRemoveExisting"));
401 g_signal_connect(w,"toggled",
402 G_CALLBACK(plover_transaction_helper_remove_existing_toggled),helper);
403 w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIIntroduction"));
405 gtk_assistant_set_page_complete(helper->assistant,w,TRUE);
410 plover_transaction_helper_get_installed(PloverTransactionHelper *helper)
412 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
413 return helper->installed;
416 void plover_transaction_helper_set_installed(PloverTransactionHelper *helper,
417 PloverPackageSet *installed)
419 g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
420 g_return_if_fail(PLOVER_IS_PACKAGE_SET(installed));
421 g_return_if_fail(helper->installed == NULL);
422 helper->installed=g_object_ref(installed);
426 plover_transaction_helper_get_upstream(PloverTransactionHelper *helper,
432 struct razor_relocations *relocations=NULL;
434 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
435 if (!helper->upstream)
438 prefix=plover_transaction_helper_get_prefix(helper,error);
442 base=plover_transaction_helper_get_base(helper);
446 relocations=razor_relocations_create();
447 razor_relocations_add(relocations,"/usr",prefix);
450 helper->upstream=plover_repository_new_from_yum(base,error);
453 razor_relocations_destroy(relocations);
456 return helper->upstream;
459 static PloverPackageSet *plover_transaction_helper_get_relocated_upstream(
460 PloverTransactionHelper *helper,GError **error)
463 struct razor_relocations *relocations=NULL;
464 GError *tmp_error=NULL;
465 PloverRepository *upstream;
466 PloverPackageSet *set;
467 if (!helper->relocated_upstream)
469 upstream=plover_transaction_helper_get_upstream(helper,error);
472 prefix=plover_transaction_helper_get_prefix(helper,&tmp_error);
475 g_propagate_error(error,tmp_error);
478 set=plover_repository_get_package_set(upstream);
481 relocations=razor_relocations_create();
482 razor_relocations_add(relocations,"/usr",prefix);
483 helper->relocated_upstream=
484 plover_package_set_new_from_repository(upstream,relocations,
487 razor_relocations_destroy(relocations);
490 helper->relocated_upstream=g_object_ref(set);
492 return helper->relocated_upstream;
495 void plover_transaction_helper_set_upstream(PloverTransactionHelper *helper,
496 PloverRepository *upstream)
498 g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
499 g_return_if_fail(PLOVER_IS_REPOSITORY(upstream));
500 g_return_if_fail(helper->upstream == NULL);
501 helper->upstream=g_object_ref(upstream);
504 const char *plover_transaction_helper_get_base(PloverTransactionHelper *helper)
506 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
510 void plover_transaction_helper_set_base(PloverTransactionHelper *helper,
513 g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
514 g_return_if_fail(helper->transactions == NULL);
515 g_free(helper->base);
516 helper->base=g_strdup(base);
520 plover_transaction_helper_get_comps(PloverTransactionHelper *helper,
524 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
525 g_return_val_if_fail(helper->base != NULL,NULL);
528 s=g_strconcat(helper->base,"/repodata/comps.xml",NULL);
529 helper->comps=plover_comps_new_from_file(s);
531 g_set_error(error,PLOVER_GENERAL_ERROR,
532 PLOVER_GENERAL_ERROR_FAILED,"%s: %s",s,g_strerror(errno));
535 return helper->comps;
539 plover_transaction_helper_get_prefix(PloverTransactionHelper *helper,
544 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
545 g_return_val_if_fail(helper->base != NULL || helper->installed != NULL,NULL);
548 comps=plover_transaction_helper_get_comps(helper,error);
551 return plover_default_prefix_for_vendor(comps->vendor);
553 prefix=plover_package_set_guess_prefix(helper->installed,error);
557 static int plover_transaction_helper_package_count(void)
561 struct razor_set *set;
562 struct razor_package *package;
563 struct razor_package_iterator *pi;
564 install_root=getenv("RAZOR_ROOT");
567 set=razor_root_open_read_only(install_root,NULL);
570 pi=razor_package_iterator_create(set);
571 while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_LAST))
573 razor_package_iterator_destroy(pi);
574 razor_set_unref(set);
580 plover_transaction_helper_check_vendor(PloverTransactionHelper *helper,
584 gchar *prefix=NULL,*s;
585 struct comps *comps=NULL;
586 GtkWidget *container,*page;
589 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
590 if (helper->check_vendor)
592 comps=plover_transaction_helper_get_comps(helper,error);
595 prefix=plover_default_prefix_for_vendor(comps->vendor);
597 button=GTK_BUTTON(gtk_builder_get_object(helper->ui,"SIRemoveExisting"));
598 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),FALSE);
599 container=GTK_WIDGET(gtk_builder_get_object(helper->ui,
600 "SIIncompatibleInstallation"));
601 page=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm"));
602 if (helper->check_vendor && prefix &&
603 !plover_installed_files_match_prefix(prefix))
605 label=GTK_LABEL(gtk_builder_get_object(helper->ui,
606 "SIIncompatibleInstallationLabel"));
607 s=g_strdup_printf("<b>Incompatible Installation</b>\n\n"
608 "The existing installation is not from %s.\n"
609 "In order to continue, all the existing packages must be removed.",
611 gtk_label_set_markup(label,s);
613 i=plover_transaction_helper_package_count();
614 s=g_strdup_printf("Remove %d existing package%s",i,i==1?"":"s");
615 gtk_button_set_label(button,s);
617 gtk_widget_show(container);
618 if (helper->assistant)
619 gtk_assistant_set_page_complete(helper->assistant,page,FALSE);
623 gtk_widget_hide(container);
624 if (helper->assistant)
625 gtk_assistant_set_page_complete(helper->assistant,page,TRUE);
630 void plover_transaction_helper_set_check_vendor(PloverTransactionHelper *helper,
631 gboolean check_vendor)
633 g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
634 if (helper->check_vendor!=check_vendor)
636 helper->check_vendor=check_vendor;
637 if (helper->transactions)
638 plover_transaction_helper_check_vendor(helper,NULL);
643 * If plover_transaction_helper_add_transaction() failes with an error
644 * of PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET
645 * then plover_transaction_helper_get_unsatisfied() can be used to
646 * retrieve a textual description of the problem.
650 plover_transaction_helper_get_unsatisfied(PloverTransactionHelper *helper)
652 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
653 return helper->unsatisfied;
657 plover_transaction_helper_add_transaction(PloverTransactionHelper *helper,
658 PloverTransaction *transaction,struct plover_vector *report_packages,
659 enum razor_install_action report_action,GError **error)
662 gboolean other_packages;
664 enum razor_install_action action;
665 struct razor_install_iterator *ii;
666 struct razor_set *next;
667 struct razor_package *package;
668 struct plover_vector *tasked_packages;
669 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
670 g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
671 g_return_val_if_fail(report_action==RAZOR_INSTALL_ACTION_ADD || report_action==RAZOR_INSTALL_ACTION_REMOVE,FALSE);
672 g_free(helper->unsatisfied);
673 helper->unsatisfied=NULL;
674 if (!plover_transaction_resolve(transaction,error))
676 s=plover_transaction_get_unsatisfied(transaction);
677 helper->unsatisfied=g_strdup(s);
680 ii=plover_transaction_get_install_iterator(transaction,error);
683 next=plover_transaction_get_next_set(transaction,error);
686 tasked_packages=plover_vector_new();
687 other_packages=FALSE;
688 while (razor_install_iterator_next(ii,&package,&action,&count))
690 if (action==report_action)
692 razor_package_get_details(next,package,RAZOR_DETAIL_NAME,&name,
694 if (!report_packages ||
695 plover_vector_contains(report_packages,name))
696 plover_vector_append(tasked_packages,name);
701 if (!tasked_packages->len)
704 * If there are no reportable packages tasked for action there
705 * shouldn't by any packages at all, but let's be paranoid.
707 other_packages=FALSE;
708 razor_install_iterator_rewind(ii);
709 while (razor_install_iterator_next(ii,&package,&action,&count))
711 if (action==report_action)
713 razor_package_get_details(next,package,RAZOR_DETAIL_NAME,&name,
715 plover_vector_append(tasked_packages,name);
719 if (!tasked_packages->len)
721 g_set_error(error,PLOVER_GENERAL_ERROR,
722 PLOVER_GENERAL_ERROR_NO_WORK,"Transaction includes no %s actions",
723 report_action==RAZOR_INSTALL_ACTION_ADD?"add":"remove");
724 plover_vector_free(tasked_packages);
727 if (!helper->transactions)
728 plover_transaction_helper_check_vendor(helper,error);
729 g_object_ref(transaction);
730 helper->transactions=g_slist_append(helper->transactions,transaction);
731 if (report_action==RAZOR_INSTALL_ACTION_ADD)
733 for(i=0;i<tasked_packages->len;i++)
735 s=tasked_packages->strings[i];
736 if (!plover_vector_contains(helper->report_adding,s))
737 plover_vector_append(helper->report_adding,s);
739 helper->report_adding_dependencies|=other_packages;
743 for(i=0;i<tasked_packages->len;i++)
745 s=tasked_packages->strings[i];
746 if (!plover_vector_contains(helper->report_removing,s))
747 plover_vector_append(helper->report_removing,s);
749 helper->report_removing_dependants|=other_packages;
751 plover_vector_free(tasked_packages);
755 static PloverTransaction *
756 plover_transaction_helper_new_transaction(PloverTransactionHelper *helper,
760 const char *base,*prefix;
761 GError *tmp_error=NULL;
762 PloverTransaction *transaction;
763 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
764 prefix=plover_transaction_helper_get_prefix(helper,&tmp_error);
767 g_propagate_error(error,tmp_error);
770 transaction=plover_transaction_new();
771 plover_transaction_set_prefix(transaction,prefix);
772 plover_transaction_set_installed(transaction,helper->installed);
773 if (helper->upstream)
774 ok=plover_transaction_set_upstream(transaction,helper->upstream,error);
777 base=plover_transaction_helper_get_base(helper);
778 ok=plover_transaction_set_upstream_from_yum(transaction,base,error);
782 g_object_unref(transaction);
788 struct plover_vector *plover_transaction_helper_group_get_default_packages(
789 PloverTransactionHelper *helper,const char *group,GError **error)
793 struct comps_group *grp;
794 struct comps_requirement *pkg;
795 struct plover_vector *default_packages;
796 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
797 comps=plover_transaction_helper_get_comps(helper,error);
800 grp=plover_comps_lookup_group(comps,group);
803 g_set_error(error,PLOVER_GENERAL_ERROR,
804 PLOVER_GENERAL_ERROR_FAILED,"%s: group not found",group);
807 default_packages=plover_vector_new();
811 for(pkg=grp->packages;pkg;pkg=pkg->next)
813 if (plover_vector_contains(default_packages,pkg->name))
815 if (pkg->type==COMPS_REQUIREMENT_DEFAULT ||
816 pkg->type==COMPS_REQUIREMENT_MANDATORY ||
817 pkg->type==COMPS_REQUIREMENT_CONDITIONAL &&
818 plover_vector_contains(default_packages,pkg->requires))
821 plover_vector_append(default_packages,pkg->name);
825 return default_packages;
829 * Returns TRUE if there is work to be done or FALSE if the packages are
830 * already installed or on error.
833 plover_transaction_helper_install_packages(PloverTransactionHelper *helper,
834 struct plover_vector *packages,GError **error)
837 PloverTransaction *transaction;
838 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
839 g_return_val_if_fail(packages != NULL,FALSE);
842 g_set_error(error,PLOVER_GENERAL_ERROR,
843 PLOVER_GENERAL_ERROR_NO_WORK,"No packages listed to be installed");
846 transaction=plover_transaction_helper_new_transaction(helper,error);
849 if (!plover_transaction_install(transaction,packages->strings,error))
851 g_object_unref(transaction);
854 retval=plover_transaction_helper_add_transaction(helper,transaction,
855 packages,RAZOR_INSTALL_ACTION_ADD,error);
856 g_object_unref(transaction);
861 * Returns TRUE if there is work to be done or FALSE if the group is
862 * already installed or on error.
865 plover_transaction_helper_install_group(PloverTransactionHelper *helper,
866 const char *group,GError **error)
869 struct plover_vector *selected_packages;
870 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
871 selected_packages=plover_transaction_helper_group_get_default_packages(
873 if (!selected_packages)
875 if (!selected_packages->len)
877 g_set_error(error,PLOVER_GENERAL_ERROR,
878 PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
879 plover_vector_free(selected_packages);
882 retval=plover_transaction_helper_install_packages(helper,selected_packages,
884 plover_vector_free(selected_packages);
889 * Returns TRUE if there is work to be done or FALSE if the group is
890 * not installed or on error.
892 gboolean plover_transaction_helper_remove_group(PloverTransactionHelper *helper,
893 const char *group,GError **error)
896 struct plover_vector *selected_packages;
897 PloverTransaction *transaction;
898 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
899 selected_packages=plover_transaction_helper_group_get_default_packages(
901 if (!selected_packages)
903 if (!selected_packages->len)
905 g_set_error(error,PLOVER_GENERAL_ERROR,
906 PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
907 plover_vector_free(selected_packages);
910 transaction=plover_transaction_new();
911 plover_transaction_set_installed(transaction,helper->installed);
912 if (!plover_transaction_remove(transaction,selected_packages->strings,
915 plover_vector_free(selected_packages);
916 g_object_unref(transaction);
919 retval=plover_transaction_helper_add_transaction(helper,transaction,
920 NULL,RAZOR_INSTALL_ACTION_REMOVE,error);
921 g_object_unref(transaction);
922 plover_vector_free(selected_packages);
927 * Returns TRUE if there is work to be done or FALSE if all updates have
928 * already been applied or on error.
930 gboolean plover_transaction_helper_update(PloverTransactionHelper *helper,
934 PloverTransaction *transaction;
935 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
936 transaction=plover_transaction_helper_new_transaction(helper,error);
939 if (!plover_transaction_update(transaction,NULL,error))
941 g_object_unref(transaction);
944 retval=plover_transaction_helper_add_transaction(helper,transaction,
945 NULL,RAZOR_INSTALL_ACTION_ADD,error);
946 g_object_unref(transaction);
950 gboolean plover_transaction_helper_get_visible(PloverTransactionHelper *helper)
952 g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
953 if (helper->error_dialog)
955 else if (!helper->assistant)
958 return gtk_widget_get_visible(GTK_WIDGET(helper->assistant));
961 void plover_transaction_helper_present(PloverTransactionHelper *helper)
963 g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
964 if (helper->error_dialog)
965 gtk_window_present(GTK_WINDOW(helper->error_dialog));
966 else if (helper->assistant)
967 gtk_window_present(GTK_WINDOW(helper->assistant));
971 plover_transaction_helper_error_dialog_response(GtkDialog *error_dialog,
972 int response_id,PloverTransactionHelper *helper)
974 g_signal_handlers_disconnect_by_data(error_dialog,helper);
975 if ((GtkWidget *)error_dialog==helper->error_dialog)
977 gtk_widget_destroy(helper->error_dialog);
978 helper->error_dialog=NULL;
979 if (helper->assistant)
981 gtk_widget_hide(GTK_WIDGET(helper->assistant));
982 gtk_assistant_set_current_page(helper->assistant,0);
984 g_signal_emit(helper,signals[CLOSE],0);
988 const char *plover_transaction_helper_get_error(PloverTransactionHelper *helper,
989 const GError **error)
991 g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
992 if (!helper->error_dialog)
995 *error=helper->error;
996 return helper->error_primary_text;
999 void plover_transaction_helper_set_error(PloverTransactionHelper *helper,
1000 const GError *error,const char *primary_text)
1002 GtkMessageType type;
1004 g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
1005 g_return_if_fail(error != NULL);
1006 g_return_if_fail(primary_text != NULL);
1007 if (helper->pulse_handler)
1009 g_source_remove(helper->pulse_handler);
1010 helper->pulse_handler=0;
1012 if (helper->error_dialog)
1014 gtk_widget_destroy(helper->error_dialog);
1015 helper->error_dialog=NULL;
1017 g_free(helper->error_primary_text);
1018 helper->error_primary_text=g_strdup(primary_text);
1019 g_clear_error(&helper->error);
1020 helper->error=g_error_copy(error);
1021 if (g_error_matches(error,PLOVER_GENERAL_ERROR,
1022 PLOVER_GENERAL_ERROR_NO_WORK))
1023 type=GTK_MESSAGE_INFO;
1025 type=GTK_MESSAGE_ERROR;
1026 if (helper->assistant)
1027 window=GTK_WINDOW(helper->assistant);
1030 helper->error_dialog=gtk_message_dialog_new(window,
1031 GTK_DIALOG_DESTROY_WITH_PARENT,type,GTK_BUTTONS_CLOSE,primary_text);
1032 gtk_message_dialog_format_secondary_text(
1033 GTK_MESSAGE_DIALOG(helper->error_dialog),error->message);
1034 gtk_widget_show(helper->error_dialog);
1035 g_signal_connect(helper->error_dialog,"response",
1036 G_CALLBACK(plover_transaction_helper_error_dialog_response),helper);