diff options
18 files changed, 1037 insertions, 1671 deletions
@@ -1,3 +1,135 @@ +2001-02-08 Eskil Heyn Olsen <eskil@eazel.com> + + reviewed by: Robey Pointer <robey@eazel.com> + + This commit fixed bugs: + 5723 ei2: check that install_failed_signal was not called + 5752 ei2: port the uninstall stuff to the new ei2 + 5753 ei2: port the revert stuff to ei2 + 5757 fix leaks in EazelProblemHander + 5957 eazel-install cli tool no longer uninstalls nicely + 6100 RPM4: don't handle dependencies called "rpmlib(.*)" + 6173 ei2: finish conflict and feature breakage + 6191 make revert work (ei2: resurrect transaction stuff) + + * components/rpmview/nautilus-rpm-view-install.c: + (get_detailed_errors_foreach): + Updated for the CANCELLED status. + * components/services/install/command-line/eazel-alt-install-corba. + c: (eazel_preflight_check_signal): + Fixed an output string. + + * components/services/install/idl/trilobite-eazel-install.idl: + Added the CANCELLED status. + uninstall_progress now has same signature as install_progress. + + * components/services/install/lib/eazel-install-corba-callback.h: + * components/services/install/lib/eazel-install-corba-callback.c: + (impl_uninstall_progress), + (eazel_install_callback_class_initialize): + uninstall_progress now has same signature as install_progress. + + * components/services/install/lib/eazel-install-corba-types.c: + (corba_packagedatastruct_fill_from_packagedata), + (traverse_packagetree_md5), (corba_packagedatastruct_fill_deps), + (packagedata_from_corba_packagedatastruct), + (packagedata_tree_from_corba_packagedatastructlist), + (categorydata_list_from_corba_categorystructlist): + Added the CANCELLED status. + Commented out sending ->provides in signals. + Added some g_asserts to find a bug. + categorydata_list_from_corba_categorystructlist uses + packagedata_list_from_corba_packagedatastructlist. + + * components/services/install/lib/eazel-install-logic.h: + * components/services/install/lib/eazel-install-logic.c: + (eazel_install_start_transaction), (dump_one_package), + (compare_break_to_package_by_name), + (eazel_uninstall_upward_traverse), + (eazel_uninstall_downward_traverse): + Threw out most of the old code. Keeping logic.c untill 6190 is + closed. + + * components/services/install/lib/eazel-install-logic2.c: + (dump_tree_helper), (check_md5_on_files), (is_satisfied), + (check_tree_helper), (execute), (set_toplevel), + (get_packages_with_mod_flag), (check_uninst_vs_downgrade), + (debug_revert), (compare_break_to_package_by_name), + (eazel_uninstall_upward_traverse), + (eazel_uninstall_check_for_install), (eazel_uninstall_globber), + (install_packages), (uninstall_packages), (revert_transaction): + Moved revert and uninstall into logic2.c and updated them + appropriately. + Added paranoia check in case bad xml dependency has a version but + an senseless sense. + When reviving, set parent->topleve to TRUE, not revived package. + Revived the transaction stuff (for revert). + Don't allow a package to depend on a package of the same name, + this is often a problem during softcat updates. + + * components/services/install/lib/eazel-install-public.h: + * components/services/install/lib/eazel-install-private.h: + * components/services/install/lib/eazel-install-object.c: + (eazel_install_finalize), (eazel_install_start_signal), + (eazel_install_end_signal), (eazel_install_progress_signal), + (eazel_install_failed_signal), (eazel_install_class_initialize), + (eazel_install_initialize), (eazel_install_install_packages), + (eazel_install_uninstall_packages), + (eazel_install_revert_transaction_from_xmlstring), + (eazel_install_do_transaction_save_report_helper), + (eazel_install_save_transaction_report), + (eazel_install_init_transaction), + (eazel_install_emit_uninstall_progress), + (eazel_install_emit_uninstall_progress_default), + (eazel_install_emit_download_progress): + uninstall_progress now has same signature as install_progress. + Fixed some dumb bugs in install/uninstall progress emission. + Added some lists to check on install status. + Moved some of the transaction stuff from logic.c here. + + * components/services/install/lib/eazel-install-problem.c: + (get_detailed_messages_foreach), + (get_detailed_uninstall_messages_foreach), + (get_detailed_cases_foreach), + (get_detailed_uninstall_cases_foreach), + (eazel_install_problem_tree_to_case), + (eazel_install_problem_tree_to_string), + (build_categories_from_problem_list): + Updated again for the new PackageBreaks objects. + Fixed so cli uninstall works nice again. + Added the CANCELLED status. + The problem handler is deteriorating, either we use it or we scrap + it. + + * components/services/install/lib/eazel-package-system-rpm3.c: + (rpmmonitorpiggybag_new), + (eazel_package_system_rpm3_set_mod_status), + (monitor_rpm_process_pipe_percent_output), + (eazel_package_system_rpm3_packagedata_fill_from_header), + (eazel_package_system_rpm3_set_state), + (eazel_package_system_rpm3_execute), (check_if_all_packages_seen), + (eazel_package_system_rpm3_install_uninstall): + Don't spam about the locales decimal seperator. + Set modification status after handling a package, so transaction + logs make sense. + Don't accept requirements of type "rpmlib(.*". + Ability to set all packages to CANCELLED if root helper failed + login. + If TEST is set, fake success all the time. + + * components/services/install/lib/eazel-package-system-types.h: + * components/services/install/lib/eazel-package-system-types.c: + (categorydata_new), (categorydata_destroy_foreach), + (packagedata_status_enum_to_str), + (packagedata_status_str_to_enum): + Added the CANCELLED status. + Improved the debug strings for alloc/dealloc of category data + structures. + + * components/services/install/lib/eazel-package-system.c: + (eazel_package_system_install): + If TEST, disable FORCE. + 2001-02-08 John Harper <jsh@eazel.com> Fixed bug 6044 (Druid should be clearer on what the right diff --git a/components/rpmview/nautilus-rpm-view-install.c b/components/rpmview/nautilus-rpm-view-install.c index 69528fad9..18b2e7409 100644 --- a/components/rpmview/nautilus-rpm-view-install.c +++ b/components/rpmview/nautilus-rpm-view-install.c @@ -96,7 +96,7 @@ get_detailed_errors_foreach (const PackageData *pack, GString *message) { switch (pack->status) { case PACKAGE_UNKNOWN_STATUS: - break; + case PACKAGE_CANCELLED: case PACKAGE_SOURCE_NOT_SUPPORTED: break; case PACKAGE_FILE_CONFLICT: diff --git a/components/services/install/command-line/eazel-alt-install-corba.c b/components/services/install/command-line/eazel-alt-install-corba.c index faff124a0..e2394002d 100644 --- a/components/services/install/command-line/eazel-alt-install-corba.c +++ b/components/services/install/command-line/eazel-alt-install-corba.c @@ -556,7 +556,7 @@ eazel_preflight_check_signal (EazelInstallCallback *service, if (cases) return FALSE; fprintf (stdout, "About to %s a total of %d packages, %dKb\n", - arg_erase ? "uninstall" : "install", + arg_erase ? "uninstall" : arg_revert ? "revert" : "install", total_packages, total_bytes/1024); for (iterator = packages; iterator; iterator = iterator->next) { PackageData *pack = (PackageData*)iterator->data; diff --git a/components/services/install/idl/trilobite-eazel-install.idl b/components/services/install/idl/trilobite-eazel-install.idl index 76c8ee13f..ff10e20b7 100644 --- a/components/services/install/idl/trilobite-eazel-install.idl +++ b/components/services/install/idl/trilobite-eazel-install.idl @@ -17,6 +17,7 @@ module Trilobite { enum PackageStatusEnum { UNKNOWN_STATUS, + CANCELLED, /* medium: Package cancelled, eg wrong password or such */ SOURCE_NOT_SUPPORTED, /* bad: we don't install source packages */ DEPENDENCY_FAIL, /* bad: a dependency failed in next level */ FILE_CONFLICT, /* bad: this file owns a file that the @@ -181,11 +182,19 @@ module Trilobite { /* Called during (un)installation of a package */ oneway void install_progress (in PackageDataStruct package, - in long package_num, in long num_packages, - in long package_size_completed, in long package_size_total, - in long total_size_completed, in long total_size); + in long package_num, + in long num_packages, + in long package_size_completed, + in long package_size_total, + in long total_size_completed, + in long total_size); oneway void uninstall_progress (in PackageDataStruct package, - in long amount, in long total); + in long package_num, + in long num_packages, + in long package_size_completed, + in long package_size_total, + in long total_size_completed, + in long total_size); /* Called whenever a package (un)install fails */ diff --git a/components/services/install/lib/eazel-install-corba-callback.c b/components/services/install/lib/eazel-install-corba-callback.c index 5fa53fee8..d0d743504 100644 --- a/components/services/install/lib/eazel-install-corba-callback.c +++ b/components/services/install/lib/eazel-install-corba-callback.c @@ -191,13 +191,18 @@ impl_install_progress (impl_POA_GNOME_Trilobite_Eazel_InstallCallback *servant, static void impl_uninstall_progress (impl_POA_GNOME_Trilobite_Eazel_InstallCallback *servant, const GNOME_Trilobite_Eazel_PackageDataStruct *corbapack, - const CORBA_long amount, - const CORBA_long total, - CORBA_Environment * ev) + const CORBA_long package_num, const CORBA_long num_packages, + const CORBA_long package_size_completed, const CORBA_long package_size_total, + const CORBA_long total_size_completed, const CORBA_long total_size, + CORBA_Environment * ev) { PackageData *pack; pack = packagedata_from_corba_packagedatastruct (corbapack); - gtk_signal_emit (GTK_OBJECT (servant->object), signals[UNINSTALL_PROGRESS], pack, amount, total); + gtk_signal_emit (GTK_OBJECT (servant->object), signals[UNINSTALL_PROGRESS], + pack, + package_num, num_packages, + package_size_completed, package_size_total, + total_size_completed, total_size); gtk_object_unref (GTK_OBJECT (pack)); } @@ -429,8 +434,10 @@ eazel_install_callback_class_initialize (EazelInstallCallbackClass *klass) GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallCallbackClass, uninstall_progress), - gtk_marshal_NONE__POINTER_INT_INT, - GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT); + eazel_install_gtk_marshal_NONE__POINTER_INT_INT_INT_INT_INT_INT, + GTK_TYPE_NONE, 7, + GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT, + GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT); signals[DOWNLOAD_FAILED] = gtk_signal_new ("download_failed", GTK_RUN_LAST, diff --git a/components/services/install/lib/eazel-install-corba-callback.h b/components/services/install/lib/eazel-install-corba-callback.h index 65bec6982..56ed93a36 100644 --- a/components/services/install/lib/eazel-install-corba-callback.h +++ b/components/services/install/lib/eazel-install-corba-callback.h @@ -63,7 +63,11 @@ struct _EazelInstallCallbackClass int package_size_completed, int package_size_total, int total_size_completed, int total_size); /* Called during uninstall of a package */ - void (*uninstall_progress) (EazelInstallCallback *service, const PackageData *pack, int amount, int total); + void (*uninstall_progress) (EazelInstallCallback *service, + const PackageData *pack, + int package_num, int num_packages, + int package_size_completed, int package_size_total, + int total_size_completed, int total_size); /* Called when a package is undergoing the different checks */ void (*file_conflict_check)(EazelInstallCallback *service, const PackageData *package); diff --git a/components/services/install/lib/eazel-install-corba-types.c b/components/services/install/lib/eazel-install-corba-types.c index 1eb0291d4..ad6d4040b 100644 --- a/components/services/install/lib/eazel-install-corba-types.c +++ b/components/services/install/lib/eazel-install-corba-types.c @@ -117,17 +117,22 @@ corba_packagedatastruct_fill_from_packagedata (GNOME_Trilobite_Eazel_PackageData case PACKAGE_ALREADY_INSTALLED: corbapack->status = GNOME_Trilobite_Eazel_ALREADY_INSTALLED; break; + case PACKAGE_CANCELLED: + corbapack->status = GNOME_Trilobite_Eazel_CANCELLED; + break; case PACKAGE_CIRCULAR_DEPENDENCY: corbapack->status = GNOME_Trilobite_Eazel_CIRCULAR_DEPENDENCY; break; } +/* None of the callback signals wants this.... if (pack->provides) { g_list_to_corba_string_sequence (&(corbapack->provides), pack->provides); } else { corbapack->provides._length = 0; corbapack->provides._buffer = NULL; } +*/ /* depends will be filled in further up, if they're required -- * many times, this function is called to create a single corba package with no other package pointers */ @@ -204,6 +209,7 @@ traverse_packagetree_md5 (const PackageData *pack, GHashTable *md5_table) g_hash_table_insert (md5_table, pack->md5, (void *)pack); for (iter = g_list_first (pack->depends); iter != NULL; iter = g_list_next (iter)) { dep = (PackageDependency *)(iter->data); + g_assert (dep); traverse_packagetree_md5 (dep->package, md5_table); } for (iter = g_list_first (pack->breaks); iter != NULL; iter = g_list_next (iter)) { @@ -244,6 +250,7 @@ corba_packagedatastruct_fill_deps (GNOME_Trilobite_Eazel_PackageDataStruct *corb dep = (PackageDependency *)(iter->data); /* set up a PackageDependencyStruct for it */ + g_assert (dep); corbadep = &(corbapack->depends._buffer[i]); sense_str = eazel_softcat_sense_flags_to_string (dep->sense); corbadep->sense = CORBA_string_dup (sense_str); @@ -251,6 +258,7 @@ corba_packagedatastruct_fill_deps (GNOME_Trilobite_Eazel_PackageDataStruct *corb corbadep->package_md5 = CORBA_string_dup (dep->package->md5); g_free (sense_str); } + g_assert (i!=0); } if (pack->breaks != NULL) { @@ -393,6 +401,9 @@ packagedata_from_corba_packagedatastruct (const GNOME_Trilobite_Eazel_PackageDat case GNOME_Trilobite_Eazel_ALREADY_INSTALLED: pack->status = PACKAGE_ALREADY_INSTALLED; break; + case GNOME_Trilobite_Eazel_CANCELLED: + pack->status = PACKAGE_CANCELLED; + break; case GNOME_Trilobite_Eazel_CIRCULAR_DEPENDENCY: pack->status = PACKAGE_CIRCULAR_DEPENDENCY; break; @@ -481,6 +492,7 @@ packagedata_tree_from_corba_packagedatastructlist (const GNOME_Trilobite_Eazel_P pack->depends = g_list_prepend (pack->depends, dep); } } + pack->depends = g_list_reverse (pack->depends); for (j = 0; j < corbapack->breaks._length; j++) { @@ -568,7 +580,7 @@ GList* categorydata_list_from_corba_categorystructlist (const GNOME_Trilobite_Eazel_CategoryStructList *corbacategories) { GList *categories; - guint i,j; + guint i; categories = NULL; @@ -582,17 +594,9 @@ categorydata_list_from_corba_categorystructlist (const GNOME_Trilobite_Eazel_Cat corbacategory = &(corbacategories->_buffer[i]); packagelist = &(corbacategory->packages); - for (j = 0; j < packagelist->_length; j++) { - PackageData *pack; - GNOME_Trilobite_Eazel_PackageDataStruct *corbapack; - - corbapack = &(packagelist->_buffer[j]); - pack = packagedata_from_corba_packagedatastruct (corbapack); - packages = g_list_prepend (packages, pack); - } category = categorydata_new (); category->name = (strlen (corbacategory->name) > 0) ? g_strdup (corbacategory->name) : NULL; - category->packages = packages; + category->packages = packagedata_list_from_corba_packagedatastructlist (packagelist); categories = g_list_prepend (categories, category); } diff --git a/components/services/install/lib/eazel-install-logic.c b/components/services/install/lib/eazel-install-logic.c index 38dbc9922..9f8083c04 100644 --- a/components/services/install/lib/eazel-install-logic.c +++ b/components/services/install/lib/eazel-install-logic.c @@ -20,6 +20,9 @@ * Authors: Eskil Heyn Olsen <eskil@eazel.com> */ +/* CVS version 1.41 contains the big chunks of old logic code + that got evicted in the last phases of logic2 work */ + #include "eazel-install-logic.h" #include "eazel-install-xml-package-list.h" #include "eazel-install-public.h" @@ -53,748 +56,9 @@ #include <sys/wait.h> #endif -static gboolean eazel_install_do_install_packages (EazelInstall *service, - GList* packages); - -static int eazel_install_start_transaction (EazelInstall *service, - GList* packages); - -static gboolean eazel_install_ensure_deps (EazelInstall *service, - GList **filenames, - GList **fails); - -static void eazel_uninstall_globber (EazelInstall *service, - GList **packages, - GList **failed); - -static gboolean eazel_install_download_packages (EazelInstall *service, - gboolean toplevel, - GList **packages, - GList **failed_packages); -#if 0 -static gboolean eazel_install_check_for_file_conflicts (EazelInstall *service, - PackageData *pack, - GList **breaks, - GList **requires); -#endif -static void eazel_install_prune_packages (EazelInstall *service, - PackageData *pack, - ...); -/* - Checks for pre-existance of all the packages - */ -static void -eazel_install_pre_install_packages (EazelInstall *service, - GList **packages) -{ - GList *iterator; - GList *failed_packages = NULL; - - for (iterator = *packages; iterator; iterator = g_list_next (iterator)) { - PackageData *pack = (PackageData*)iterator->data; - EazelInstallStatus inst_status; - gboolean skip = FALSE; - - inst_status = eazel_install_check_existing_packages (service, pack); - - /* If in force mode, install it under all circumstances. - if not, only install if not already installed in same - version or up/downgrade is set */ - if (eazel_install_get_force (service) || - (eazel_install_get_downgrade (service) && inst_status == EAZEL_INSTALL_STATUS_DOWNGRADES) || - (eazel_install_get_update (service) && inst_status == EAZEL_INSTALL_STATUS_UPGRADES) || - inst_status == EAZEL_INSTALL_STATUS_NEW_PACKAGE) { - skip = FALSE; - } else { - skip = TRUE; - } - - if (skip) { - trilobite_debug ("Skipping %s...", pack->name); -#if 0 - /* Nuke the modifies list again, since we don't want to see them */ - g_list_foreach (pack->modifies, - (GFunc)packagedata_destroy, - GINT_TO_POINTER (TRUE)); - g_list_free (pack->modifies); - pack->modifies = NULL; -#endif - - /* Add it to the list of packages to nuke at the end - of this function */ - failed_packages = g_list_prepend (failed_packages, pack); - } - } - - for (iterator = failed_packages; iterator; iterator=g_list_next (iterator)) { - eazel_install_prune_packages (service, - (PackageData*)iterator->data, - packages, NULL); - } - g_list_free (failed_packages); -} - -EazelInstallStatus -ei_install_packages (EazelInstall *service, GList *categories) { - EazelInstallStatus result; - - if (categories == NULL) { - trilobite_debug (_("Reading the install package list %s"), eazel_install_get_package_list (service)); - categories = parse_local_xml_package_list (eazel_install_get_package_list (service), NULL, NULL); - } - - result = EAZEL_INSTALL_NOTHING; - if (categories != NULL) { - /* First, collect all packages in one list */ - GList *packages = categorylist_flatten_to_packagelist (categories); - - /* Now download all the packages */ - if (eazel_install_download_packages (service, TRUE, &packages, NULL)) { - - /* check for packages that are already installed */ - eazel_install_pre_install_packages (service, &packages); - - /* Files downloaded, now install */ - if (eazel_install_do_install_packages (service, packages)) { - result |= EAZEL_INSTALL_INSTALL_OK; - } - } - } - - return result; -} /* end install_new_packages */ - -/* - Download all the packages and keep doing that by recursively - calling eazel_install_download_packages with package->soft_depends - */ -static gboolean -eazel_install_download_packages (EazelInstall *service, - gboolean toplevel, - GList **packages, - GList **failed_packages) -{ - g_assert_not_reached (); - return TRUE; -#if 0 - GList *iterator; - gboolean result = TRUE; - GList *remove_list = NULL; - - g_assert (packages); - g_assert (*packages); - - for (iterator = *packages; (iterator != NULL) && result; iterator = g_list_next (iterator)) { - PackageData* package = (PackageData*)iterator->data; - gboolean fetch_package; - - fetch_package = TRUE; - - trilobite_debug ("init for %s (%s/%s)", package->name, package->version ? package->version : "NO VERSION", - toplevel?"TRUE":"FALSE"); - /* if filename in the package is set, but the file - does not exist, get it anyway */ - if (package->filename) { - trilobite_debug ("Filename set, and file exists = %d", - g_file_test (package->filename, G_FILE_TEST_ISFILE)); - if (g_file_test (package->filename, G_FILE_TEST_ISFILE)) { - /* Don't fetch, but load rpm header and return - ok */ - fetch_package = FALSE; - result = TRUE; - package = eazel_package_system_load_package (service->private->package_system, - package, - package->filename, - PACKAGE_FILL_NO_DIRS_IN_PROVIDES); - } else { - /* The file didn't exist, remove the - leading path and set the filename, plus - toggle the fetch_package to TRUE */ - g_free (package->filename); - package->filename = g_strdup (g_basename (package->filename)); - } - } else if (!eazel_install_get_force (service) && package->version) { - /* If the package has a version set, check that we don't already have - the same or newer installed. This is almost the same check as - in eazel_install_pre_install_package. The reason for two checks is - - first check before download (if possible) - - after download, when we for sure have access to the version, check again - - we do this before do_dependency_check to avoid downloaded soft_deps. - */ - EazelInstallStatus inst_status; - - inst_status = eazel_install_check_existing_packages (service, package); - if (eazel_install_get_downgrade (service) && inst_status == EAZEL_INSTALL_STATUS_DOWNGRADES) { - trilobite_debug (_("Will download %s"), package->name); - /* must download... */ - } else if (inst_status == EAZEL_INSTALL_STATUS_QUO || - inst_status == EAZEL_INSTALL_STATUS_DOWNGRADES) { - /* Nuke the modifies list again, since we don't want to see them */ - g_list_foreach (package->modifies, - (GFunc)packagedata_destroy, - GINT_TO_POINTER (TRUE)); - g_list_free (package->modifies); - package->modifies = NULL; - /* don't fecth the package */ - fetch_package = FALSE; - /* Add it to the list of packages to nuke at the end - of this function */ - remove_list = g_list_prepend (remove_list, package); - trilobite_debug (_("%s already installed"), package->name); - } - } - - if (fetch_package) { - result = eazel_install_fetch_package (service, package); - - if (!result) { - package->status = PACKAGE_CANNOT_OPEN; - remove_list = g_list_prepend (remove_list, package); - } else { -#if 0 - /* If downloaded package has soft_deps, - fetch them by a recursive call */ - if (package->soft_depends) { - result = eazel_install_download_packages (service, - FALSE, - &package->soft_depends, - NULL); - } -#endif - } - } - - if (result) { - package->toplevel = toplevel; - if (package->source_package) { - package->status = PACKAGE_SOURCE_NOT_SUPPORTED; - remove_list = g_list_prepend (remove_list, package); - } - if (strlen ("debug")) { - char *tmp = packagedata_dump (package, TRUE); - fprintf (stderr, "%s", tmp); - g_free (tmp); - } - } - } - - for (iterator = remove_list; iterator; iterator = g_list_next (iterator)) { - PackageData *package = (PackageData*)(iterator->data); - eazel_install_prune_packages (service, package, packages, NULL); - } - - if (failed_packages) { - (*failed_packages) = remove_list; - } - - return result; -#endif -} -#if 0 -/* - This function checks all files in pack->provides, and - checks if another already installed package owns this file. - returns FALSE is there are no conflicts, and TRUE if there - are. - - If there are conflicts because of a related package, - this package is added to *requires. - */ -static gboolean -eazel_install_check_for_file_conflicts (EazelInstall *service, - PackageData *pack, - GList **breaks, - GList **requires) -{ - GList *owners; - GList *iterator; - /* Set optimism to high */ - gboolean result = FALSE; - - g_assert (service); - g_assert (pack); - g_assert (requires); - g_assert (*requires == NULL); - - trilobite_debug ("Checking file conflicts for %s", pack->name); - - for (iterator = pack->provides; iterator; glist_step (iterator)) { - char *filename = (char*)iterator->data; - - /* many packages will supply some dirs, eg /usr/share/locale/../LC_MESSAGES - dirs, so don't check those - - eazel-install-types - (packagedata_fill_from_rpm_header) now does not add - these. This is more safe, as checking the file - could still cause a conflict, if the file was not - on the system but two dirs had the same dir - - if (g_file_test (filename, G_FILE_TEST_ISDIR)) { - continue; - } */ - - owners = eazel_package_system_query (service->private->package_system, - service->private->cur_root, - filename, - EAZEL_PACKAGE_SYSTEM_QUERY_OWNS, - PACKAGE_FILL_NO_DIRS_IN_PROVIDES); - packagedata_list_prune (&owners, pack->modifies, TRUE, TRUE); - - if (g_list_length (owners) > 1) { - GList *pit; - /* FIXME bugzilla.eazel.com 3511: - More than one packages owns this file, - this cannot happen (or should not at least) - */ - trilobite_debug ("***************************************************"); - trilobite_debug ("More than one package owns the file %s", filename); - trilobite_debug ("This is filed as bug 2959"); - trilobite_debug ("Try rpm --rebuilddb"); - for (pit = owners; pit; pit = g_list_next (pit)) { - char *tmp; - PackageData *owner = (PackageData*)(pit->data); - tmp = packagedata_get_readable_name (owner); - trilobite_debug ("a owner is %s", tmp); - g_free (tmp); - } - trilobite_debug ("halting..."); - g_assert_not_reached (); - } else if (g_list_length (owners) == 1) { - PackageData *owner = (PackageData*)owners->data; - - /* If the package owner is already in the breaks list for the package, - or in the *requires, continue */ - if (g_list_find_custom (*breaks, owner->name, - (GCompareFunc)eazel_install_package_name_compare) || - g_list_find_custom (*requires, owner->name, - (GCompareFunc)eazel_install_package_name_compare)) { - /* trilobite_debug ("already breaking %s", owner->name); */ - gtk_object_unref (GTK_OBJECT (owner)); - owner = NULL; - continue; - } - - if (strcmp (pack->name, owner->name)) { - trilobite_debug ("file %s from package %s conflicts with file from package %s", - filename, pack->name, owner->name); - - result = TRUE; - if (eazel_install_check_if_related_package (service, pack, owner)) { - trilobite_debug ("Package %s may be related to %s", - owner->name, pack->name); - g_free (owner->version); - owner->version = g_strdup (pack->version); - (*requires) = g_list_prepend (*requires, owner); - } else { - owner->status = PACKAGE_FILE_CONFLICT; - (*breaks) = g_list_prepend (*breaks, owner); - } - - } else { - /* else it's the same package and it's okay */ - /* so FREE IT YOU SICK MONKEY! */ - gtk_object_unref (GTK_OBJECT (owner)); - } - } - /* free the _simple_query result list */ - g_list_free (owners); - -#ifdef EAZEL_INSTALL_SLIM - /* In the slim, we need to enter the g_main_loop during file check */ - g_main_iteration (FALSE); -#endif - - } - return result; -} -#endif - -static gboolean -eazel_install_do_install_packages (EazelInstall *service, - GList* packages) -{ - gboolean rv = TRUE; - GList* failedfiles = NULL; - - if (packages) { - rv = FALSE; - eazel_install_ensure_deps (service, &packages, &failedfiles); - if (g_list_length (packages)) { - if (eazel_install_start_transaction (service, packages) == 0) { - rv = TRUE; - } - g_list_free (packages); - } - } - - return rv; -} /* end install_packages */ - -static EazelInstallStatus -uninstall_all_packages (EazelInstall *service, - GList *categories) -{ - EazelInstallStatus result = EAZEL_INSTALL_UNINSTALL_OK; - - while (categories) { - CategoryData* cat = categories->data; - GList *failed; - - trilobite_debug (_("Category = %s"), cat->name); - - failed = NULL; - eazel_uninstall_globber (service, &cat->packages, &failed); - - if (eazel_install_start_transaction (service, cat->packages) != 0) { - result = EAZEL_INSTALL_NOTHING; - } - - categories = g_list_next (categories); - } - return result; -} - -EazelInstallStatus -ei_uninstall_packages (EazelInstall *service, - GList* categories) -{ - EazelInstallStatus result = EAZEL_INSTALL_NOTHING; - - result |= uninstall_all_packages (service, categories); - - return result; - -} /* end install_new_packages */ - - -static GList * -ei_get_packages_with_mod_flag (GList *packages, - PackageModification mod) -{ - GList *it; - GList *res; - - res = NULL; - for (it = packages; it; it = g_list_next (it)) { - PackageData *pack; - pack = (PackageData*)it->data; - if (pack->modify_status == mod) { - res = g_list_prepend (res, pack); - } - if (pack->soft_depends) { - res = g_list_concat (res, - ei_get_packages_with_mod_flag (pack->soft_depends, mod)); - } - if (pack->modifies) { - res = g_list_concat (res, - ei_get_packages_with_mod_flag (pack->modifies, mod)); - } - } - return res; -} - -/* Function to prune the uninstall list for elements marked as downgrade */ -static void -ei_check_uninst_vs_downgrade (GList **inst, - GList **down) -{ - GList *it; - GList *remove; - - remove = NULL; - for (it = *inst; it; it = g_list_next (it)) { - GList *entry; - PackageData *pack; - - pack = (PackageData*)it->data; - entry = g_list_find_custom (*down, pack->name, (GCompareFunc)eazel_install_package_name_compare); - if (entry != NULL) { - remove = g_list_prepend (remove, it->data); - } - } - - for (it = remove; it; it = g_list_next (it)) { - (*inst) = g_list_remove (*inst, it->data); - } -} - -static void hest (PackageData *pack, char *str) { - trilobite_debug ("Must %s %s", str, pack->name); -} - -EazelInstallStatus -ei_revert_transaction (EazelInstall *service, - GList *packages) -{ - GList *uninst, *inst, *upgrade, *downgrade; - CategoryData *cat; - GList *categories; - EazelInstallStatus result = EAZEL_INSTALL_NOTHING; - - uninst = ei_get_packages_with_mod_flag (packages, PACKAGE_MOD_INSTALLED); - inst = ei_get_packages_with_mod_flag (packages, PACKAGE_MOD_UNINSTALLED); - upgrade = ei_get_packages_with_mod_flag (packages, PACKAGE_MOD_DOWNGRADED); - downgrade = ei_get_packages_with_mod_flag (packages, PACKAGE_MOD_UPGRADED); - - ei_check_uninst_vs_downgrade (&uninst, &downgrade); - - g_list_foreach (uninst, (GFunc)hest, "uninstall"); - g_list_foreach (inst, (GFunc)hest, "install"); - g_list_foreach (downgrade, (GFunc)hest, "downgrade"); - g_list_foreach (upgrade, (GFunc)hest, "upgrade"); - - cat = categorydata_new (); - categories = g_list_prepend (NULL, cat); - - if (uninst) { - eazel_install_set_uninstall (service, TRUE); - eazel_install_set_downgrade (service, FALSE); - eazel_install_set_update (service, FALSE); - cat->packages = uninst; - result |= ei_uninstall_packages (service, categories); - } - if (inst) { - eazel_install_set_uninstall (service, FALSE); - eazel_install_set_downgrade (service, FALSE); - eazel_install_set_update (service, FALSE); - cat->packages = inst; - result |= ei_install_packages (service, categories); - } - if (downgrade) { - eazel_install_set_uninstall (service, FALSE); - eazel_install_set_downgrade (service, TRUE); - eazel_install_set_update (service, FALSE); - cat->packages = downgrade; - result |= ei_install_packages (service, categories); - } - if (upgrade) { - eazel_install_set_uninstall (service, FALSE); - eazel_install_set_downgrade (service, TRUE); - eazel_install_set_update (service, TRUE); - cat->packages = upgrade; - result |= ei_install_packages (service, categories); - g_list_foreach (upgrade, (GFunc)gtk_object_unref, NULL); - } - - return result; -} - - -void -eazel_install_do_transaction_add_to_transaction (EazelInstall *service, - PackageData *pack) -{ - service->private->transaction = g_list_prepend (service->private->transaction, - pack); -} - -static void -eazel_install_do_transaction_save_report_helper (xmlNodePtr node, - GList *packages) -{ - GList *iterator; - - for (iterator = packages; iterator; iterator = g_list_next (iterator)) { - PackageData *pack; - char *tmp; - pack = (PackageData*)iterator->data; - switch (pack->modify_status) { - case PACKAGE_MOD_INSTALLED: - tmp = g_strdup_printf ("Installed %s", pack->name); - xmlNewChild (node, NULL, "DESCRIPTION", tmp); - g_free (tmp); - break; - case PACKAGE_MOD_UNINSTALLED: - tmp = g_strdup_printf ("Uninstalled %s", pack->name); - xmlNewChild (node, NULL, "DESCRIPTION", tmp); - g_free (tmp); - break; - default: - break; - } - if (pack->modifies) { - eazel_install_do_transaction_save_report_helper (node, pack->modifies); - } - } -} - -static void -eazel_install_do_transaction_save_report (EazelInstall *service) -{ - FILE *outfile; - xmlDocPtr doc; - xmlNodePtr node, root; - char *name = NULL; - - if (eazel_install_get_transaction_dir (service) == NULL) { - g_warning ("Transaction directory not set, not storing transaction report"); - } - - /* Ensure the transaction dir is present */ - if (! g_file_test (eazel_install_get_transaction_dir (service), G_FILE_TEST_ISDIR)) { - int retval; - retval = mkdir (eazel_install_get_transaction_dir (service), 0755); - if (retval < 0) { - if (errno != EEXIST) { - g_warning (_("Could not create transaction directory (%s)! ***\n"), - eazel_install_get_transaction_dir (service)); - return; - } - } - } - - /* Create xml */ - doc = xmlNewDoc ("1.0"); - root = node = xmlNewNode (NULL, "TRANSACTION"); - xmlDocSetRootElement (doc, node); - - /* Make a unique name */ - name = g_strdup_printf ("%s/transaction.%lu", eazel_install_get_transaction_dir (service), - (unsigned long) time (NULL)); - while (g_file_test (name, G_FILE_TEST_ISFILE)) { - g_free (name); - sleep (1); - name = g_strdup_printf ("%s/transaction.%lu", - eazel_install_get_transaction_dir (service), - (unsigned long) time (NULL)); - } - - trilobite_debug (_("Writing transaction to %s"), name); - - /* Open and save */ - outfile = fopen (name, "w"); - xmlAddChild (root, eazel_install_packagelist_to_xml (service->private->transaction, FALSE)); - node = xmlAddChild (node, xmlNewNode (NULL, "DESCRIPTIONS")); - - { - char *tmp; - tmp = g_strdup_printf ("%lu", (unsigned long) time (NULL)); - xmlNewChild (node, NULL, "DATE", tmp); - g_free (tmp); - } - - eazel_install_do_transaction_save_report_helper (node, service->private->transaction); - - xmlDocDump (outfile, doc); - - fclose (outfile); - g_free (name); -} - -/* - This checks, that for a given set of packages, no two packages - contains the same file. - This is done by filling a hashtable with the files from - package->provides (which have full pathname) and link to the - owning package. Before adding a file to the hashtable, lookup the - file first. If result is non-null, problem... - - Did I mention that this function leaks memory like a russian submarine? -robey - */ -static gboolean -eazel_install_do_transaction_all_files_check (EazelInstall *service, - GList **packages) -{ - g_assert_not_reached (); - return FALSE; -#if 0 - gboolean result = TRUE; - GList *iterator; - GList *conflicts = NULL; /* PackageRequirements. ->package is the first found package - that providing a file, ->required is the second file that - has the same file */ - GHashTable *file_to_pack; /* maps from a filename to a packagedata struct */ - - if (eazel_install_get_force (service) || - eazel_install_get_ignore_file_conflicts (service) || - (g_list_length (*packages) == 1 )) { - trilobite_debug ("not performing file conflict check"); - return result; - } - - file_to_pack = g_hash_table_new (g_str_hash, g_str_equal); - - /* Check all the packages */ - for (iterator = *packages; iterator; glist_step (iterator)) { - PackageData *pack = (PackageData*)iterator->data; - GList *file_iterator; - int reported_yet = FALSE; - int other_conflicts = 0; - - /* Check all files provided */ - for (file_iterator = pack->provides; file_iterator; glist_step (file_iterator)) { - char *fname = (char*)file_iterator->data; - /* Lookup and check what happens... */ - PackageData *previous_pack = g_hash_table_lookup (file_to_pack, - fname); - if (previous_pack) { - /* Dang, fname is owned by previous_pack but pack also adds it */ - /* The use of reported_yet && other_conflicts is purely for - debug nicety. It ensures that only one fileconflicts pr - package is printed, whereas the alternative is eg. 200 */ - if (! reported_yet) { - trilobite_debug ("conflict, file %s from package %s is also in %s", - fname, - pack->name, - previous_pack->name); - reported_yet = TRUE; - } else { - other_conflicts++; - } - if (!g_list_find_custom (conflicts, - pack, - (GCompareFunc)eazel_install_requirement_dep_compare)) { - PackageRequirement *req; - - req = packagerequirement_new (previous_pack, pack); - conflicts = g_list_prepend (conflicts, req); - } - } else { - /* File is ok */ - g_hash_table_insert (file_to_pack, - fname, - pack); - } - } - if (other_conflicts) { - trilobite_debug ("(%d other conflicts from the same package... *sigh*)", other_conflicts); - } - } - - for (iterator = conflicts; iterator; glist_step (iterator)) { - PackageRequirement *req = (PackageRequirement*)iterator->data; - - result = FALSE; - /* Need to fail the package here to fully fix bug - FIXME bugzilla.eazel.com 3374: */ - trilobite_debug ("Conflict between %s and %s", req->package->name, req->required->name); - req->package->status = PACKAGE_FILE_CONFLICT; - req->required->status = PACKAGE_FILE_CONFLICT; - Xpackagedata_add_pack_to_breaks (req->package, req->required); - eazel_install_prune_packages (service, req->package, packages, NULL); - } - - return result; -#endif -} - - -static unsigned long -get_total_size_of_packages (const GList *packages) -{ - const GList *iterator; - unsigned long result = 0; - for (iterator = packages; iterator; iterator = g_list_next (iterator)) { - PackageData *pack = (PackageData*)iterator->data; - result += pack->bytesize; - } - return result; -} - /* A GHRFunc to clean out the name_to_package hash table -*/ + static gboolean eazel_install_clean_name_to_package_hash (char *key, PackageData *pack, @@ -803,12 +67,14 @@ eazel_install_clean_name_to_package_hash (char *key, g_free (key); return TRUE; } +*/ /* This begins the package transaction. Return value is number of failed packages */ -int +#if 0 +static int eazel_install_start_transaction (EazelInstall *service, GList* packages) { @@ -856,7 +122,7 @@ eazel_install_start_transaction (EazelInstall *service, service->private->infoblock [2] = 0; service->private->infoblock [3] = g_list_length (packages); service->private->infoblock [4] = 0; - service->private->infoblock [5] = get_total_size_of_packages (packages); + service->private->infoblock [5] = 0; if (eazel_install_emit_preflight_check (service, packages)) { /* this makes the primary packages appear before their dependencies. very useful for installs @@ -876,7 +142,7 @@ eazel_install_start_transaction (EazelInstall *service, flag); } - eazel_install_do_transaction_save_report (service); + eazel_install_save_transaction_report (service); } g_list_free (service->private->transaction); @@ -888,166 +154,7 @@ eazel_install_start_transaction (EazelInstall *service, return res; } /* end start_transaction */ - - -/* Checks if pack depends on dep, by doing a deep tree search */ -static gboolean -eazel_install_check_if_depends_on (PackageData *pack, - PackageData *dep) -{ - gboolean result = FALSE; - GList *iterator; - - for (iterator = pack->soft_depends; !result && iterator; glist_step (iterator)) { - PackageData *nisse = (PackageData*)iterator->data; - if (nisse == dep) { - result = TRUE; - } else if (eazel_install_check_if_depends_on (nisse, dep)) { - /* trilobite_debug ("nope, recursing"); */ - result = TRUE; - } - } - - return result; -} - -/* - The helper for eazel_install_prune_packages. - If the package is in "pruned", it has already been marked - for pruning. - Otherwise, prune first it's softdepends, then all - packages that depend on it. - */ -static void -eazel_install_prune_packages_helper (EazelInstall *service, - GList **packages, - GList **pruned, - PackageData *pack) -{ - GList *iterator; - char *tmp; - - g_return_if_fail (pack!=NULL); - /* If already pruned, abort */ - if (g_list_find (*pruned, pack) || pack->name==NULL) { - return; - } - tmp = packagedata_get_readable_name (pack); - trilobite_debug (_("Removing package %s (0x%p) %s"), - tmp, - pack, - pack->toplevel ? "(emit fail)" :"()"); - g_free (tmp); - if (pack->toplevel) { - /* We only emit signal for the toplevel packages, - and only delete them. They _destroy function destroys - the entire dep tree */ - eazel_install_emit_install_failed (service, pack); - } - /* Add to list of pruned packages */ - (*pruned) = g_list_prepend (*pruned, pack); - - /* Prune all it's soft_deps */ - for (iterator = pack->soft_depends; iterator; iterator = g_list_next (iterator)) { - PackageData *sub; - sub = (PackageData*)iterator->data; - eazel_install_prune_packages_helper (service, packages, pruned, sub); - } - - /* For all packages in "packages", check if they depend on this */ - for (iterator = *packages; iterator; iterator = g_list_next (iterator)) { - PackageData *super; - - super = (PackageData*)iterator->data; - /* FIXME bugzilla.eazel.com 3542: - This is the cause of 3542. - In this specific case, gnome-print is removed from the toplevel and from - 1st sublevel of soft_deps. - The problem is, that this g_list_find only looks down one level, and does'nt - search the entire tree, duh. - I need a find_custom call that does this the right way */ - if (eazel_install_check_if_depends_on (super, pack)) { - eazel_install_prune_packages_helper (service, packages, pruned, super); - } - } -} - -/* - Used to remove a package "pack" and all - packages in "packages" that depends - on "pack". - - To do this, we need the _helper, which gathers - the stripped files into "pruned". That way, we - can safely traverse without altering - the lists during the for loops (as g_list_remove - will fuck up the for loop). - - This may end in a recursive loop if - the ->soft_depends points to something - upwards in the dep tree (circular dependency) - - First it calls prune_helper for all the given packages, - at each iteration it removes the pruned (from list "pruned") - packages. - - Finally it deallocates all the pruned packages. - -*/ - -static void -eazel_install_prune_packages (EazelInstall *service, - PackageData *pack, - ...) -{ - va_list ap; - GList *pruned; - GList *iterator; - GList **packages; - - g_return_if_fail (pack!=NULL); - - va_start (ap, pack); - - pruned = NULL; - while ( (packages = va_arg (ap, GList **)) != NULL) { - eazel_install_prune_packages_helper (service, - packages, - &pruned, - pack); - for (iterator = pruned; iterator; iterator = g_list_next (iterator)) { - PackageData *pack = (PackageData*)iterator->data; - /* trilobite_debug ("%s pruned", pack->name); */ - (*packages) = g_list_remove (*packages, pack); - }; - } - - /* Note, don't destroy, all packages are destroyed when the - categories are destroyed - for (iterator = pruned; iterator; iterator = g_list_next (iterator)) { - PackageData *pack; - pack = (PackageData*)iterator->data; - gtk_object_unref (GTK_OBJECT (pack)); - }; - */ - - g_list_free (pruned); - - va_end (ap); -} -#if 0 -static void -eazel_install_add_to_extras_foreach (char *key, GList *list, GList **extrapackages) -{ - GList *iterator; - PackageData *dep; - for (iterator = list; iterator; iterator = g_list_next (iterator)) { - dep = (PackageData*)iterator->data; - (*extrapackages) = g_list_prepend (*extrapackages, dep); - } - g_list_free (list); -} -#endif +#endif /* This function tests wheter "package" and "dep" @@ -1128,252 +235,22 @@ eazel_install_check_if_related_package (EazelInstall *service, return result; } -static gboolean -eazel_install_fetch_dependencies (EazelInstall *service, - GList **packages, - GList **extrapackages, - GList **failedpackages, - GList *requirements) -{ - g_assert_not_reached (); - return FALSE; -#if 0 - GList *iterator; - /* Contains the packages downloaded when handling the list of requirements */ - GList *extras_in_this_batch = NULL; - GHashTable *extras; - gboolean fetch_result; - - extras = g_hash_table_new (g_str_hash, g_str_equal); - fetch_result = FALSE; - - trilobite_debug ("%d requirements to be fetched/resolved", g_list_length (requirements)); - for (iterator = requirements; iterator; glist_step (iterator)) { - PackageRequirement *req = (PackageRequirement*)iterator->data; - PackageData *pack = req->package; - PackageData *dep = req->required; - - /* Check to see if the package system happened to file a requirement - for a package that was also failed... */ - if (g_list_find_custom (*failedpackages, - pack, - (GCompareFunc)eazel_install_package_compare)) { - char *tmp; - tmp = packagedata_get_readable_name (pack); - trilobite_debug ("%s already failed, will not download it's requirements", tmp); - g_free (tmp); - gtk_object_unref (GTK_OBJECT (dep)); - continue; - } - - /* We use the unknown status later, to see if - we should set it or not */ - dep->status = PACKAGE_UNKNOWN_STATUS; - - /* Emit the signal here, since then we won't have to make that - call in for every package system (when I say every, we know - I mean "both"...) */ - eazel_install_emit_dependency_check_pre_ei2 (service, pack, dep); - packagedata_add_pack_to_soft_depends (pack, dep); - - fetch_result = eazel_install_fetch_package (service, dep); - - if (fetch_result) { - if (dep->source_package) { - dep->status = PACKAGE_SOURCE_NOT_SUPPORTED; - fetch_result = FALSE; - } - } - - if (fetch_result) { - /* If the package we just downloaded was already in packages, - but we just had a dependency conflict, we're in the funky case, - were pacakge foo is not installed. But the dependecy stuff has caused - it to be downloaded in version x.y, and later in v.w. This means that - the first conflict (causing x.y to be downloaded) now happens again. - */ - if (g_list_find_custom (*packages, - dep->name, - (GCompareFunc)eazel_install_package_name_compare)) { - GList *pack_entry; - - pack_entry = g_list_find_custom (*packages, - dep, - (GCompareFunc)eazel_install_package_other_version_compare); - trilobite_debug ("Circular dependency %s-%s-%s at 0x%p", - dep->name, dep->version, dep->minor, dep); - - if (pack_entry) { - PackageData *evil_package = packagedata_copy ((PackageData*)(pack_entry->data), FALSE); - Xpackagedata_add_pack_to_breaks (dep, evil_package); - trilobite_debug ("Circular dependency caused by %s-%s-%s at 0x%p", - evil_package->name, - evil_package->version, - evil_package->minor, - evil_package); - evil_package->status = PACKAGE_CIRCULAR_DEPENDENCY; - } else { - trilobite_debug ("This is Bad: I cannot set the funky break list"); - } - dep->status = PACKAGE_CIRCULAR_DEPENDENCY; - fetch_result = FALSE; - } - } - - if (fetch_result) { - EazelInstallStatus inst_status; - /* This sets the dep->modifies and checks for a funky case. - This case is sort of like the one above. - If the call returns 0, the following must have happened ; - We had a dependency saying that foo required bar-x.y. - So we download bar and now discover that bar is already installed - in the exact same version (x.y). So that means, another - dependency solving caused us to up/downgrade bar to another - version, and the following dep check then caused a - conflict indicating that we should *not* do this up/downgrade. - - Solution: fail the downgraded package - - I assume the packages have the same name... - */ - inst_status = eazel_install_check_existing_packages (service, dep); - if (inst_status == EAZEL_INSTALL_STATUS_QUO) { - GList *pack_entry; - - trilobite_debug ("package %s required %s", pack->name, dep->name); - trilobite_debug ("This is because some other package was downloaded"); - trilobite_debug ("and crushed this, since %s is already installed", dep->name); - - /* Use name compare here, as we expect the package to have the same name */ - pack_entry = g_list_find_custom (*packages, - dep->name, - (GCompareFunc)eazel_install_package_name_compare); - if (pack_entry) { - /* FIXME bugzilla.eazel.com - I suspect that adding this to adding evil_package to pack's breaks - might yield a more pleasant tree */ - PackageData *evil_package = (PackageData*)pack_entry->data; - Xpackagedata_add_pack_to_breaks (evil_package, dep); - evil_package->status = PACKAGE_BREAKS_DEPENDENCY; - } else { - trilobite_debug ("This is also Bad: I cannot set the funky break list"); - } - dep->status = PACKAGE_CIRCULAR_DEPENDENCY; - fetch_result = FALSE; - } else if (eazel_install_get_downgrade (service)==FALSE && - inst_status == EAZEL_INSTALL_STATUS_DOWNGRADES) { - /* Bad, we're downgrading but not allowed to downgrade */ - fetch_result = FALSE; - } else if (eazel_install_get_update (service)==FALSE && - inst_status == EAZEL_INSTALL_STATUS_UPGRADES) { - /* Bad, we're upgrading but not allowed to upgrade */ - fetch_result = FALSE; - } - - } - - if (fetch_result) { - /* if it succeeds, add to a list of extras for this package - We cannot just put it into extrapackages, as a later dep - might fail, and than we have to fail the package */ - GList *extralist; - - /* Check if a previous requirement download solved this - Note, we don't check till after download, since only a download - will reveal the packagename in case we need to download - using fetch_package using the pack->provides. - This is a paranoia check in addition to a check done - in do_dependency_check, since a dep check might say - that we require two files that are provided by the same - package, and we only want to get the package once. - Eg. nautilus requires libgconf-gtk-1.so and libgconf-1.so, - both provided by gconf, so we fetch gconf twice */ - if (g_list_find_custom (extras_in_this_batch, - dep, - (GCompareFunc)eazel_install_package_compare)) { - trilobite_debug ("already handled %s", dep->name); - packagedata_remove_soft_dep (dep, pack); - dep = NULL; - continue; - } - - /* This maintains a list of extra packages for - a package. So when a requirement D for package A fails, - and we've already downloaded B & C for A, - we can easily find B & D and remove them */ - extralist = g_hash_table_lookup (extras, pack->name); - extralist = g_list_append (extralist, dep); - g_hash_table_insert (extras, pack->name, extralist); - - /* This list contains all the packages added in this call - to fetch_rpm_dependencies. It's used in the initial check, - to avoid that multiple requests for a file results in - multiple downloads */ - extras_in_this_batch = g_list_prepend (extras_in_this_batch, dep); - - pack->status = PACKAGE_PARTLY_RESOLVED; - } else { - /* - If it fails - 1) remove it from the extras hashtable for the package, - thereby ensuring the fetched packages before the fail aren't added - 2) add the package to the list of stuff to remove (deleting it - immediately from packages will cause - eazel_install_match_package_data_from_rpm_conflict - to return zero. This is fine if we then just do a continue, but - this way, we get all the missing deps into pack->soft_depends - 3) add to list of failed packages - */ - GList *extralist; - - pack->status = PACKAGE_DEPENDENCY_FAIL; - if (dep->status == PACKAGE_UNKNOWN_STATUS) { - dep->status = PACKAGE_CANNOT_OPEN; - } - - trilobite_debug ("Fetching %s failed, status %s/%s", - packagedata_get_readable_name (dep), - packagedata_status_enum_to_str (dep->status), - packagedata_modstatus_enum_to_str (dep->modify_status)); - - if (!eazel_install_get_force (service)) { - /* Remove the extra packages for this package */ - extralist = g_hash_table_lookup (extras, pack->name); - /* Remove all the extras from the soft_deps (is this what we want ?) */ - g_list_foreach (extralist, (GFunc)packagedata_remove_soft_dep, pack); - g_list_free (extralist); - g_hash_table_remove (extras, pack->name); - - /* Don't add it to failedpackages more than once */ - if (g_list_find (*failedpackages, pack) == NULL) { - (*failedpackages) = g_list_prepend (*failedpackages, pack); - } - (*packages) = g_list_remove (*packages, pack); - - /* Don't process anymore */ - break; - } - } - } - - /* iterate over all the lists in extras and add to extrapackages */ - g_hash_table_foreach (extras, (GHFunc)eazel_install_add_to_extras_foreach, extrapackages); - g_hash_table_destroy (extras); - g_list_free (extras_in_this_batch); - - if (*failedpackages) { - return FALSE; - } else { - return TRUE; - } -#endif -} - static void -dump_one_package (PackageData *pack, char *prefix) +dump_one_package (GtkObject *foo, char *prefix) { char *softprefix, *modprefix, *breakprefix; char *packname; + PackageData *pack = NULL; + + if (IS_PACKAGEDATA (foo)) { + pack = PACKAGEDATA (foo); + } else if (IS_PACKAGEBREAKS (foo)) { + pack = packagebreaks_get_package (PACKAGEBREAKS (foo)); + } else if (IS_PACKAGEDEPENDENCY (foo)) { + pack = PACKAGEDEPENDENCY (foo)->package; + } else { + g_assert_not_reached (); + } if (pack->name == NULL) { if (pack->provides && pack->provides->data) { @@ -1382,20 +259,20 @@ dump_one_package (PackageData *pack, char *prefix) packname = g_strdup ("[mystery package]"); } } else { - packname = g_strdup_printf ("%s-%s-%s", pack->name, pack->version, pack->minor); + packname = packagedata_get_readable_name (pack); } - trilobite_debug ("%s%s (stat %s/%s), 0x%08X", + trilobite_debug ("%s%s (stat %s/%s), %p", prefix, packname, packagedata_status_enum_to_str (pack->status), packagedata_modstatus_enum_to_str (pack->modify_status), - (unsigned int)pack); + pack); g_free (packname); softprefix = g_strdup_printf ("%s (s) ", prefix); breakprefix = g_strdup_printf ("%s (b) ", prefix); modprefix = g_strdup_printf ("%s (m) ", prefix); - g_list_foreach (pack->soft_depends, (GFunc)dump_one_package, softprefix); + g_list_foreach (pack->depends, (GFunc)dump_one_package, softprefix); g_list_foreach (pack->modifies, (GFunc)dump_one_package, modprefix); g_list_foreach (pack->breaks, (GFunc)dump_one_package, breakprefix); g_free (softprefix); @@ -1404,22 +281,6 @@ dump_one_package (PackageData *pack, char *prefix) } static void -dump_packages_foreach (PackageData *pack, gpointer unused) -{ - if (pack->toplevel) { - dump_one_package (pack, ""); - } -} - -void -dump_packages (GList *packages) -{ - trilobite_debug ("##### PACKAGE TREE #####"); - g_list_foreach (packages, (GFunc)dump_packages_foreach, NULL); - trilobite_debug ("----- end -----"); -} - -static void print_package_list (char *str, GList *packages, gboolean show_deps) { GList *iterator; @@ -1469,245 +330,12 @@ print_package_list (char *str, GList *packages, gboolean show_deps) } } -/* - Helperfunction to create PackageRequirements for fileconflicts. Should be - used for packagesystems that don't do this (eg. RPM) */ -static void -eazel_install_do_file_conflict_check (EazelInstall *service, - GList **packages, - GList **failedpackages, - GList **requirements) +static int +compare_break_to_package_by_name (PackageBreaks *breakage, PackageData *pack) { - g_assert_not_reached (); -#if 0 - GList *iterator; - GList *tmp_failed = NULL; - - if (eazel_install_get_ignore_file_conflicts (service) || - eazel_install_get_force (service)) { - trilobite_debug ("not performing file conflict check"); - } - - /* Now do file conflicts on all packages */ - for (iterator = *packages; iterator; glist_step (iterator)) { - PackageData *pack = (PackageData*)iterator->data; - GList *required = NULL; + PackageData *broken_package = packagebreaks_get_package (breakage); - /* If we haven't tested conflicts yet */ - if (pack->conflicts_checked == FALSE) { - GList *breaks = NULL; - pack->conflicts_checked = TRUE; - if (eazel_install_check_for_file_conflicts (service, pack, &breaks, &required)) { - if (required) { - /* Create PackageRequirements for all the requirements */ - GList *reqiterator; - for (reqiterator = required;reqiterator;glist_step (reqiterator)) { - PackageData *required_pack = (PackageData*)reqiterator->data; - if (g_list_find_custom (*packages, - required_pack->name, - (GCompareFunc)eazel_install_package_name_compare)) { - trilobite_debug ("but we'e updating it (requirement)"); - /* gtk_object_unref (GTK_OBJECT (broken_package)); */ - } else { - PackageRequirement *req; - req = packagerequirement_new (pack, required_pack); - (*requirements) = g_list_prepend (*requirements, req); - } - } - } - if (breaks) { - GList *break_iterator; - gboolean fail_it = FALSE; - for (break_iterator = breaks; break_iterator; glist_step (break_iterator)) { - PackageData *broken_package = (PackageData*)break_iterator->data; - trilobite_debug ("breaking %s", broken_package->name); - if (g_list_find_custom (*packages, - broken_package->name, - (GCompareFunc)eazel_install_package_name_compare)) { - trilobite_debug ("but we're updating it"); - /* gtk_object_unref (GTK_OBJECT (broken_package)); */ - } else { - fail_it = TRUE; - Xpackagedata_add_pack_to_breaks (pack, broken_package); - } - } - if (fail_it) { - tmp_failed = g_list_prepend (tmp_failed, pack); - } - } - } else { - /* No file conflicts */ - } - } - } - - /* Now clean up */ - for (iterator = tmp_failed; iterator; glist_step (iterator)) { - PackageData *cpack = (PackageData*)(iterator->data); - (*failedpackages) = g_list_prepend (*failedpackages, cpack); - (*packages) = g_list_remove (*packages, cpack); - } -#endif -} - -/* - Use package system to do the dependency check - */ -static void -eazel_install_do_dependency_check (EazelInstall *service, - GList **packages, - GList **failedpackages, - GList **requirements) -{ - eazel_install_do_rpm_dependency_check (service, - packages, - failedpackages, - requirements); - /* RPM's depCheck doens't do fileconflicts, so we do - them ourselves */ - eazel_install_do_file_conflict_check (service, - packages, - failedpackages, - requirements); -} - -/* - Given a glist of PackageData's, ensure_deps_are_fetched checks deps - for them all, if deps fail, fetch the depency and add to packages. - Returns FALSE if outfiles was set, TRUE is all dependencies were satisfied. - If a dep could not be found, that name is added to fails) - */ -static gboolean -eazel_install_ensure_deps (EazelInstall *service, - GList **packages, - GList **failedpackages) -{ - GList *extrapackages = NULL; /* This list contains packages that were added to "packages" */ - gboolean result; - GList *requirements = NULL; /* This list contains the PackageRequirements for the dependecy failures */ - - g_return_val_if_fail (packages != NULL, TRUE); - g_return_val_if_fail (*packages != NULL, TRUE); - - g_return_val_if_fail (g_list_length (*packages)>=1, FALSE); - result = TRUE; - - trilobite_debug ("Into eazel_install_ensure_deps"); - - /* First we load headers and prepare them. - The datastructures depend on the packagesystem, - and are places in service->private->packsys. - */ - - eazel_install_do_dependency_check (service, - packages, - failedpackages, - &requirements); - - if (requirements != NULL) { - GList *iterator; - - extrapackages = NULL; - - /* For all the packages, set state to partly_resolved. */ - for (iterator=*packages; iterator; iterator = g_list_next (iterator)) { - PackageData *pack; - pack = (PackageData*)iterator->data; - pack->status = PACKAGE_PARTLY_RESOLVED; - } - - trilobite_debug ("%d dependency failure(s)", g_list_length (requirements)); - - /* Fetch the needed stuff. - "extrapackages" gets the new packages added, - packages in "failedpackages" are packages moved from - "packages" that could not be resolved. */ - eazel_install_fetch_dependencies (service, - packages, - &extrapackages, - failedpackages, - requirements); - - /* Delete the PackageRequirements. - Note, that we just need to free the structure, both elements - are kept, req->package in extrapackages or failedpackages and - req->required will be in req->package's breaks/soft_depends. - */ - g_list_foreach (requirements, (GFunc)g_free, NULL); - g_list_free (requirements); - - /* Some debug printing */ - dump_packages (*packages); - print_package_list ("Packages that were fetched", extrapackages, FALSE); - print_package_list ("Packages that failed", *failedpackages, TRUE); - } else { - GList *iterator; - - /* Deps are fine, set all packages to resolved */ - for (iterator=*packages; iterator; iterator = g_list_next (iterator)) { - PackageData *pack; - pack = (PackageData*)iterator->data; - pack->status = PACKAGE_RESOLVED; - } - trilobite_debug (_("Dependencies appear ok")); - - if (!eazel_install_do_transaction_all_files_check (service, packages)) { - trilobite_debug (_("But there are file conflicts")); - /* Now recurse into eazel_install_ensure_deps with - the new "packages" list */ - eazel_install_ensure_deps (service, packages, failedpackages); - } else { - trilobite_debug ("Dependencies still appear ok"); - } - - } - - /* If there was failedpackages, prune them from the tree - and the "extrapackages". - We need to strip from "extrapackages" as well, since : - while installing A & B, C was added for A, D was - added for B but B also needs E (but not found). Therefore - we strip D from "extrapackages" and B is stripped - from "packages". Keeping D around would - install a non-needed package - */ - if (*failedpackages) { - GList *iterator; - - for (iterator = *failedpackages; iterator; iterator = g_list_next (iterator)) { - PackageData *pack; - pack = (PackageData*)iterator->data; - trilobite_debug ("calling prune on %s", pack->name); - eazel_install_prune_packages (service, pack, packages, - &extrapackages, NULL); - } - } - /* If there were conflicts, we'll have called fetch_dependencies and might - have downloaded extra packages. So we have to recurse and process these */ - if (extrapackages) { - GList *iterator; - - /* Add to "packages" */ - for (iterator = extrapackages; iterator; iterator = g_list_next (iterator)) { - (*packages) = g_list_append (*packages, iterator->data); - } - g_list_free (extrapackages); - - /* Now recurse into eazel_install_ensure_deps with - the new "packages" list */ - eazel_install_ensure_deps (service, packages, failedpackages); - - /* Now remove the packages that failed from "packages" - and copy them into "failedpackages". */ - for (iterator = *failedpackages; iterator; iterator = g_list_next (iterator)) { - PackageData *pack; - pack = (PackageData*)iterator->data; - (*packages) = g_list_remove (*packages, pack); - } - } - dump_packages (*packages); - - return result; + return eazel_install_package_compare (broken_package, pack); } /* This traverses upwards in the deptree from the initial list, and adds @@ -1742,43 +370,48 @@ eazel_uninstall_upward_traverse (EazelInstall *service, GList *matches = NULL; GList *match_iterator; GList *tmp_breaks = NULL; - GList *break_iterator = NULL; - - trilobite_debug ("checking reqs by %s", rpmname_from_packagedata (pack)); + GList *b_iterator = NULL; + + /* Get the packages required by pack */ + trilobite_debug ("checking reqs by %p %s", pack, rpmname_from_packagedata (pack)); matches = eazel_package_system_query (service->private->package_system, service->private->cur_root, pack, EAZEL_PACKAGE_SYSTEM_QUERY_REQUIRES, - PACKAGE_FILL_NO_DIRS_IN_PROVIDES); - packagedata_list_prune (&matches, *packages, TRUE, TRUE); + PACKAGE_FILL_NO_DIRS_IN_PROVIDES | PACKAGE_FILL_NO_DEPENDENCIES); + /* For all of them, mark as a break conflict */ for (match_iterator = matches; match_iterator; match_iterator = g_list_next (match_iterator)) { PackageData *requiredby = (PackageData*)match_iterator->data;; requiredby->status = PACKAGE_DEPENDENCY_FAIL; pack->status = PACKAGE_BREAKS_DEPENDENCY; - trilobite_debug ("logic.c: %s requires %s", requiredby->name, pack->name); + trilobite_debug ("logic.c: %p %s requires %p %s", + requiredby, requiredby->name, + pack, pack->name); - /* If we're already marked it as breaking, go on - if (g_list_find_custom (*breaks, (gpointer)requiredby->name, - (GCompareFunc)eazel_install_package_name_compare)) { - trilobite_debug ("skip %s", requiredby->name); - gtk_object_unref (GTK_OBJECT (requiredby)); - requiredby = NULL; + /* If the broken package is in packages, just continue */ + if (g_list_find_custom (*packages, requiredby, + (GCompareFunc)eazel_install_package_compare)) { + trilobite_debug ("skip %p %s", requiredby, requiredby->name); continue; } - */ - /* Guess not, mark it as breaking (and that pack is the offender */ + /* only add to breaks if it's a new breakage */ + if (g_list_find_custom (*breaks, (gpointer)requiredby, + (GCompareFunc)compare_break_to_package_by_name)) { + (*breaks) = g_list_prepend ((*breaks), requiredby); + } + + /* Create a FeatureMissing breakage */ { PackageFeatureMissing *breakage = packagefeaturemissing_new (); packagebreaks_set_package (PACKAGEBREAKS (breakage), requiredby); packagedata_add_to_breaks (pack, PACKAGEBREAKS (breakage)); - gtk_object_unref (GTK_OBJECT (requiredby)); + gtk_object_unref (GTK_OBJECT (breakage)); } - (*breaks) = g_list_prepend ((*breaks), requiredby); - /* If the package has not been failed yet (and is a toplevel), + /* If the pac has not been failed yet (and is a toplevel), fail it */ if (!g_list_find_custom (*failed, (gpointer)pack->name, (GCompareFunc)eazel_install_package_name_compare) && @@ -1786,18 +419,22 @@ eazel_uninstall_upward_traverse (EazelInstall *service, (*failed) = g_list_prepend (*failed, pack); } } - /* fre the list structure from _simple_query */ + g_list_foreach (matches, (GFunc)gtk_object_unref, NULL); g_list_free (matches); - + + /* Now check the packages that broke, this is where eg. uninstalling + glib begins to take forever */ if (*breaks) { eazel_uninstall_upward_traverse (service, breaks, failed, &tmp_breaks); } - for (break_iterator = tmp_breaks; break_iterator; break_iterator = g_list_next (break_iterator)) { - (*breaks) = g_list_prepend ((*breaks), break_iterator->data); + /* Add the result from the recursion */ + for (b_iterator = tmp_breaks; b_iterator; b_iterator = g_list_next (b_iterator)) { + (*breaks) = g_list_prepend ((*breaks), b_iterator->data); } } + /* Remove the failed packages */ for (iterator = *failed; iterator; iterator = g_list_next (iterator)) { (*packages) = g_list_remove (*packages, iterator->data); } @@ -1965,126 +602,3 @@ eazel_uninstall_downward_traverse (EazelInstall *service, trilobite_debug ("out eazel_uninstall_downward_traverse"); } - -static void -eazel_uninstall_check_for_install (EazelInstall *service, - GList **packages, - GList **failed) -{ - GList *iterator; - GList *remove = NULL; - GList *result = NULL; - - trilobite_debug ("in eazel_uninstall_check_for_install"); - g_assert (packages); - trilobite_debug ("g_list_length (*packages) = %d", g_list_length (*packages)); - for (iterator = *packages; iterator; iterator = g_list_next (iterator)) { - PackageData *pack = (PackageData*)iterator->data; - GList *matches; - - matches = eazel_package_system_query (service->private->package_system, - service->private->cur_root, - pack->name, - EAZEL_PACKAGE_SYSTEM_QUERY_MATCHES, - PACKAGE_FILL_NO_TEXT | PACKAGE_FILL_NO_DEPENDENCIES | PACKAGE_FILL_NO_DIRS_IN_PROVIDES); - /* If it's installed, continue */ - if (matches) { - GList *match_it; - gboolean any = FALSE; - for (match_it = matches; match_it; match_it = g_list_next (match_it)) { - PackageData *matched = (PackageData*)match_it->data; - if (eazel_install_package_matches_versioning (matched, - pack->version, - pack->minor, - EAZEL_SOFTCAT_SENSE_EQ)) { - matched->toplevel = TRUE; - /* mark that at least one matched */ - any = TRUE; - result = g_list_prepend (result, matched); - } else { - gtk_object_unref (GTK_OBJECT (matched)); - } - - } - if (!any) { - pack->status = PACKAGE_CANNOT_OPEN; - remove = g_list_prepend (remove, pack); - } - g_list_free (matches); - continue; - } else { - pack->status = PACKAGE_CANNOT_OPEN; - remove = g_list_prepend (remove, pack); - } - } - - for (iterator = remove; iterator; iterator=g_list_next (iterator)) { - (*packages) = g_list_remove (*packages, iterator->data); - (*failed) = g_list_prepend (*failed, iterator->data); - } - g_list_free (remove); - remove = NULL; - - trilobite_debug ("g_list_length (*packages) = %d", g_list_length (*packages)); - trilobite_debug ("g_list_length (result) = %d", g_list_length (result)); - - g_list_foreach (*packages, (GFunc)gtk_object_unref, NULL); - g_list_free (*packages); - (*packages) = result; - - trilobite_debug ("out eazel_uninstall_check_for_install"); -} - -/* Calls the upward and downward traversal */ -static void -eazel_uninstall_globber (EazelInstall *service, - GList **packages, - GList **failed) -{ - GList *iterator; - GList *tmp; - - /* - call upward with packages - call downward with packages and &tmp - add all from &tmp to packages - */ - - trilobite_debug ("in eazel_uninstall_globber"); - - tmp = NULL; - - eazel_uninstall_check_for_install (service, packages, failed); - for (iterator = *failed; iterator; iterator = g_list_next (iterator)) { - trilobite_debug ("not installed %s", ((PackageData*)iterator->data)->name); - eazel_install_emit_uninstall_failed (service, (PackageData*)iterator->data); - } - - /* If there are still packages and we're not forcing, - do upwards traversel */ - if (*packages && !eazel_install_get_force (service)) { - eazel_uninstall_upward_traverse (service, packages, failed, &tmp); - print_package_list ("FAILED", *failed, TRUE); - for (iterator = *failed; iterator; iterator = g_list_next (iterator)) { - PackageData *pack = (PackageData*)iterator->data; - trilobite_debug ("failed %s", pack->name); - dump_one_package (pack, ""); - eazel_install_emit_uninstall_failed (service, pack); - } - g_list_free (tmp); - } - -/* - I've disabled downwards traverse untill it's done. - - tmp = NULL; - eazel_uninstall_downward_traverse (service, packages, failed, &tmp); - for (iterator = tmp; iterator; iterator = g_list_next (iterator)) { - g_message ("also doing %s", ((PackageData*)iterator->data)->name); - (*packages) = g_list_prepend (*packages, iterator->data); - } - g_list_free (tmp); -*/ - - trilobite_debug ("out eazel_uninstall_glob"); -} diff --git a/components/services/install/lib/eazel-install-logic.h b/components/services/install/lib/eazel-install-logic.h index 597f24fdf..4255c9a51 100644 --- a/components/services/install/lib/eazel-install-logic.h +++ b/components/services/install/lib/eazel-install-logic.h @@ -33,17 +33,6 @@ #include "eazel-install-public.h" #include <eazel-package-system.h> -EazelInstallOperationStatus ei_install_packages (EazelInstall *service, GList *categories); -EazelInstallOperationStatus ei_uninstall_packages (EazelInstall *service, GList *categories); -EazelInstallOperationStatus ei_revert_transaction (EazelInstall *service, GList *packages); - -gboolean eazel_install_prepare_package_system (EazelInstall *service); -gboolean eazel_install_free_package_system (EazelInstall *service); - -unsigned long eazel_install_get_total_size_of_packages (EazelInstall *service, - const GList *packages); -void eazel_install_do_transaction_add_to_transaction (EazelInstall *service, - PackageData *pack); gboolean eazel_install_check_if_related_package (EazelInstall *service, PackageData *package, PackageData *dep); diff --git a/components/services/install/lib/eazel-install-logic2.c b/components/services/install/lib/eazel-install-logic2.c index 7616e99b5..d01e554e9 100644 --- a/components/services/install/lib/eazel-install-logic2.c +++ b/components/services/install/lib/eazel-install-logic2.c @@ -21,6 +21,7 @@ * Robey Pointer <robey@eazel.com> */ +#include "eazel-install-logic.h" #include "eazel-install-logic2.h" #include "eazel-install-public.h" #include "eazel-install-private.h" @@ -84,7 +85,7 @@ dump_tree_helper (GList *packages, char *indent, GList *path) pack->eazel_id, (pack->fillflag & MUST_HAVE) ? "filled" : "not filled", (pack->status == PACKAGE_CANNOT_OPEN) ? " but failed" : "", - pack->md5); + pack->toplevel ? "TOP":""); tmp = g_strdup_printf ("%s ", indent); if (g_list_find (path, pack)) { trilobite_debug ("%s... %p %s recurses ..", indent, pack, pack->name); @@ -155,7 +156,9 @@ check_md5_on_files (EazelInstall *service, trilobite_debug ("No MD5 available for %s", pack->name); } } + g_list_free (flat_packages); + eazel_install_unlock_tmp_dir (service); return result; } @@ -685,6 +688,16 @@ is_satisfied (EazelInstall *service, return FALSE; } + /* If the dependency has a version, but no sense, something is terribly + wrong with the xml */ +#if EI2_DEBUG & 0x4 + if (dep->version && dep->sense == 0) { + trilobite_debug ("I'm going to die now, because softcat is making no sense"); + trilobite_debug ("Or rather, the xml returned a invalid dependency sense"); + } +#endif + if (dep->version) { g_assert (dep->sense!=0); } + sense_str = eazel_softcat_sense_flags_to_string (dep->sense); #if EI2_DEBUG & 0x4 trilobite_debug ("is_satisfied? %p %s %s %s", @@ -856,10 +869,27 @@ check_dependencies_foreach (PackageData *package, for (iterator = package->depends; iterator; iterator = g_list_next (iterator)) { PackageDependency *dep = PACKAGEDEPENDENCY (iterator->data); - if (is_satisfied (service, dep)) { + + if (dep->package->name && strcmp (dep->package->name, package->name)==0) { + char *name_a, *name_b; + + name_a = packagedata_get_readable_name (package); + name_b = packagedata_get_readable_name (dep->package); + + g_warning ("Possible inconsistency!"); + g_warning ("%s depends on %s", name_a, name_b); + + g_free (name_a); + g_free (name_b); + + package->status = PACKAGE_INVALID; remove = g_list_prepend (remove, dep); } else { - eazel_install_emit_dependency_check (service, package, dep); + if (is_satisfied (service, dep)) { + remove = g_list_prepend (remove, dep); + } else { + eazel_install_emit_dependency_check (service, package, dep); + } } } @@ -975,6 +1005,7 @@ check_tree_helper (EazelInstall *service, pack_update->status = PACKAGE_PARTLY_RESOLVED; remove = g_list_prepend (remove, breakage); pack->status = PACKAGE_PARTLY_RESOLVED; + pack_update->toplevel = TRUE; } else { #if EI2_DEBUG & 0x4 trilobite_debug ("%s still has conflict", pack_update->name); @@ -1584,7 +1615,7 @@ eazel_install_get_total_size_of_packages (EazelInstall *service, return result; } -static void +static gboolean execute (EazelInstall *service, GList *packages, EazelPackageSystemOperation op, @@ -1592,6 +1623,7 @@ execute (EazelInstall *service, { TrilobiteRootHelper *root_helper; GList *flat_packages; + gboolean result = FALSE; flat_packages = flatten_packagedata_dependency_tree (packages); @@ -1603,6 +1635,8 @@ execute (EazelInstall *service, flags |= EAZEL_PACKAGE_SYSTEM_OPERATION_TEST; } + eazel_install_init_transaction (service); + /* Init the hack var to emit the old style progress signals */ service->private->infoblock [0] = 0; service->private->infoblock [1] = 0; @@ -1632,13 +1666,15 @@ execute (EazelInstall *service, break; } + if (service->private->failed_packages == NULL) { + eazel_install_save_transaction_report (service); + result = TRUE; + } g_list_free (flat_packages); + + return result; } -/***********************************************************************************/ - -/* These are the methods exposed to the the rest of the service object */ - static void install_packages_helper (EazelInstall *service, GList **packages, @@ -1667,6 +1703,13 @@ install_packages_helper (EazelInstall *service, } static void +set_toplevel (PackageData *package, + EazelInstall *service) +{ + package->toplevel = TRUE; +} + +static void expand_package_suites (EazelInstall *service, GList **packages) { GList *iter, *newlist, *sublist; @@ -1696,13 +1739,287 @@ expand_package_suites (EazelInstall *service, GList **packages) *packages = newlist; } +/***********************************************************************************/ +/* This is the revert majick */ + +static GList * +get_packages_with_mod_flag (GList *packages, + PackageModification mod) +{ + GList *it; + GList *res; + + res = NULL; + for (it = packages; it; it = g_list_next (it)) { + PackageData *pack; + pack = (PackageData*)it->data; + if (pack->modify_status == mod) { + res = g_list_prepend (res, pack); + } + if (pack->soft_depends) { + res = g_list_concat (res, + get_packages_with_mod_flag (pack->soft_depends, mod)); + } + if (pack->modifies) { + res = g_list_concat (res, + get_packages_with_mod_flag (pack->modifies, mod)); + } + } + return res; +} + +/* Function to prune the uninstall list for elements marked as downgrade */ static void -set_toplevel (PackageData *package, - EazelInstall *service) +check_uninst_vs_downgrade (GList **inst, + GList **down) { - package->toplevel = TRUE; + GList *it; + GList *remove; + + remove = NULL; + for (it = *inst; it; it = g_list_next (it)) { + GList *entry; + PackageData *pack; + + pack = (PackageData*)it->data; + entry = g_list_find_custom (*down, pack->name, (GCompareFunc)eazel_install_package_name_compare); + if (entry != NULL) { + remove = g_list_prepend (remove, it->data); + } + } + + for (it = remove; it; it = g_list_next (it)) { + (*inst) = g_list_remove (*inst, it->data); + } +} + +static void +debug_revert (PackageData *pack, char *str) +{ + char *name = packagedata_get_readable_name (pack); + g_message ("will %s %s", str, name); + g_free (name); +} + +/***********************************************************************************/ +/* This is the uninstall dep check majick */ + +static int +compare_break_to_package_by_name (PackageBreaks *breakage, PackageData *pack) +{ + PackageData *broken_package = packagebreaks_get_package (breakage); + + return eazel_install_package_compare (broken_package, pack); } +/* This traverses upwards in the deptree from the initial list, and adds + all packages that will break to "breaks" */ +static void +eazel_uninstall_upward_traverse (EazelInstall *service, + GList **packages, + GList **failed, + GList **breaks) +{ + GList *iterator; + /* + Create set + add all packs from packages to set + dep check + for all break, add to packages and recurse + */ + + trilobite_debug ("in eazel_uninstall_upward_traverse"); + + g_assert (packages!=NULL); + g_assert (*packages!=NULL); + g_assert (breaks!=NULL); + g_assert (*breaks==NULL); + + /* Open the package system */ + + /* Add all packages to the set */ + + for (iterator = *packages; iterator; iterator = g_list_next (iterator)) { + PackageData *pack = (PackageData*)iterator->data; + GList *matches = NULL; + GList *match_iterator; + GList *tmp_breaks = NULL; + GList *b_iterator = NULL; + + /* Get the packages required by pack */ + trilobite_debug ("checking reqs by %p %s", pack, rpmname_from_packagedata (pack)); + matches = eazel_package_system_query (service->private->package_system, + service->private->cur_root, + pack, + EAZEL_PACKAGE_SYSTEM_QUERY_REQUIRES, + PACKAGE_FILL_NO_DIRS_IN_PROVIDES | PACKAGE_FILL_NO_DEPENDENCIES); + + /* For all of them, mark as a break conflict */ + for (match_iterator = matches; match_iterator; match_iterator = g_list_next (match_iterator)) { + PackageData *requiredby = (PackageData*)match_iterator->data;; + + requiredby->status = PACKAGE_DEPENDENCY_FAIL; + pack->status = PACKAGE_BREAKS_DEPENDENCY; + trilobite_debug ("logic.c: %p %s requires %p %s", + requiredby, requiredby->name, + pack, pack->name); + + /* If the broken package is in packages, just continue */ + if (g_list_find_custom (*packages, requiredby, + (GCompareFunc)eazel_install_package_compare)) { + trilobite_debug ("skip %p %s", requiredby, requiredby->name); + continue; + } + + /* only add to breaks if it's a new breakage */ + if (g_list_find_custom (*breaks, (gpointer)requiredby, + (GCompareFunc)compare_break_to_package_by_name)) { + (*breaks) = g_list_prepend ((*breaks), requiredby); + } + + /* Create a FeatureMissing breakage */ + { + PackageFeatureMissing *breakage = packagefeaturemissing_new (); + packagebreaks_set_package (PACKAGEBREAKS (breakage), requiredby); + packagedata_add_to_breaks (pack, PACKAGEBREAKS (breakage)); + gtk_object_unref (GTK_OBJECT (breakage)); + } + + /* If the pac has not been failed yet (and is a toplevel), + fail it */ + if (!g_list_find_custom (*failed, (gpointer)pack->name, + (GCompareFunc)eazel_install_package_name_compare) && + pack->toplevel) { + (*failed) = g_list_prepend (*failed, pack); + } + } + g_list_foreach (matches, (GFunc)gtk_object_unref, NULL); + g_list_free (matches); + + /* Now check the packages that broke, this is where eg. uninstalling + glib begins to take forever */ + if (*breaks) { + eazel_uninstall_upward_traverse (service, breaks, failed, &tmp_breaks); + } + + /* Add the result from the recursion */ + for (b_iterator = tmp_breaks; b_iterator; b_iterator = g_list_next (b_iterator)) { + (*breaks) = g_list_prepend ((*breaks), b_iterator->data); + } + } + + /* Remove the failed packages */ + for (iterator = *failed; iterator; iterator = g_list_next (iterator)) { + (*packages) = g_list_remove (*packages, iterator->data); + } + + trilobite_debug ("out eazel_uninstall_upward_traverse"); +} + +static void +eazel_uninstall_check_for_install (EazelInstall *service, + GList **packages, + GList **failed) +{ + GList *iterator; + GList *remove = NULL; + GList *result = NULL; + + trilobite_debug ("in eazel_uninstall_check_for_install"); + g_assert (packages); + trilobite_debug ("g_list_length (*packages) = %d", g_list_length (*packages)); + for (iterator = *packages; iterator; iterator = g_list_next (iterator)) { + PackageData *pack = (PackageData*)iterator->data; + + if (eazel_package_system_is_installed (service->private->package_system, + service->private->cur_root, + pack->name, + pack->version, + pack->minor, + EAZEL_SOFTCAT_SENSE_EQ)) { + + pack->toplevel = TRUE; + result = g_list_prepend (result, pack); + } else { + pack->status = PACKAGE_CANNOT_OPEN; + remove = g_list_prepend (remove, pack); + } + } + + for (iterator = remove; iterator; iterator=g_list_next (iterator)) { + (*packages) = g_list_remove (*packages, iterator->data); + (*failed) = g_list_prepend (*failed, iterator->data); + } + g_list_free (remove); + remove = NULL; + + trilobite_debug ("g_list_length (*packages) = %d", g_list_length (*packages)); + trilobite_debug ("g_list_length (result) = %d", g_list_length (result)); + + g_list_free (*packages); + (*packages) = result; + + trilobite_debug ("out eazel_uninstall_check_for_install"); +} + +/* Calls the upward and downward traversal */ +static void +eazel_uninstall_globber (EazelInstall *service, + GList **packages, + GList **failed) +{ + GList *iterator; + GList *tmp; + + /* + call upward with packages + call downward with packages and &tmp + add all from &tmp to packages + */ + + trilobite_debug ("in eazel_uninstall_globber"); + + tmp = NULL; + + eazel_uninstall_check_for_install (service, packages, failed); + for (iterator = *failed; iterator; iterator = g_list_next (iterator)) { + trilobite_debug ("not installed %p %s", + (PackageData*)iterator->data, ((PackageData*)iterator->data)->name); + eazel_install_emit_uninstall_failed (service, (PackageData*)iterator->data); + } + g_list_foreach (*failed, (GFunc)gtk_object_unref, NULL); + g_list_free (*failed); + + /* If there are still packages and we're not forcing, + do upwards traversel */ + if (*packages && !eazel_install_get_force (service)) { + eazel_uninstall_upward_traverse (service, packages, failed, &tmp); + +#if EI2_DEBUG & 0x4 + if (*failed) { + trilobite_debug ("FAILED"); + dump_tree (*failed); + } +#endif + for (iterator = *failed; iterator; iterator = g_list_next (iterator)) { + PackageData *pack = (PackageData*)iterator->data; + trilobite_debug ("failed %p %s", pack, pack->name); + //dump_one_package (GTK_OBJECT (pack), ""); + eazel_install_emit_uninstall_failed (service, pack); + } + g_list_foreach (*failed, (GFunc)gtk_object_unref, NULL); + g_list_free (*failed); + g_list_free (tmp); + } + + trilobite_debug ("out eazel_uninstall_glob"); +} + + +/***********************************************************************************/ + +/* These are the methods exposed to the the rest of the service object */ + EazelInstallOperationStatus install_packages (EazelInstall *service, GList *categories) { @@ -1726,7 +2043,7 @@ install_packages (EazelInstall *service, GList *categories) #endif if (packages) { if (eazel_install_emit_preflight_check (service, packages)) { - int flags = EAZEL_PACKAGE_SYSTEM_OPERATION_UPGRADE | EAZEL_PACKAGE_SYSTEM_OPERATION_FORCE; + int flags = EAZEL_PACKAGE_SYSTEM_OPERATION_UPGRADE | EAZEL_PACKAGE_SYSTEM_OPERATION_DOWNGRADE | EAZEL_PACKAGE_SYSTEM_OPERATION_FORCE; gboolean go_ahead = TRUE; /* FIXME: bugzilla.eazel.com 5722 @@ -1739,10 +2056,10 @@ install_packages (EazelInstall *service, GList *categories) } } if (go_ahead) { - execute (service, packages, EAZEL_PACKAGE_SYSTEM_OPERATION_INSTALL, flags); - /* FIXME: bugzilla.eazel.com 5723 - we need to detect if install_failed_signal was called */ - result = EAZEL_INSTALL_INSTALL_OK; + /* Execute the operation */ + if (execute (service, packages, EAZEL_PACKAGE_SYSTEM_OPERATION_INSTALL, flags)) { + result = EAZEL_INSTALL_INSTALL_OK; + } } } } @@ -1761,13 +2078,98 @@ install_packages (EazelInstall *service, GList *categories) EazelInstallOperationStatus uninstall_packages (EazelInstall *service, GList *categories) { - EazelInstallOperationStatus result = EAZEL_INSTALL_NOTHING; + EazelInstallStatus result = EAZEL_INSTALL_NOTHING; + GList *packages = NULL; + GList *failed = NULL; + + trilobite_debug (" --> uninstall_all_packages"); + packages = packagedata_list_copy (categorylist_flatten_to_packagelist (categories), TRUE); + eazel_uninstall_globber (service, &packages, &failed); + + if (packages) { + if (eazel_install_emit_preflight_check (service, packages)) { + int flags = EAZEL_PACKAGE_SYSTEM_OPERATION_FORCE; + if (execute (service, packages, EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL, flags)) { + result = EAZEL_INSTALL_UNINSTALL_OK; + } + } + } + + g_list_foreach (packages, (GFunc)gtk_object_unref, NULL); + g_list_free (packages); + + trilobite_debug ("uninstall returns returning %s", + result == EAZEL_INSTALL_UNINSTALL_OK ? "OK" : "FAILED"); + trilobite_debug (" <-- uninstall_all_packages"); return result; } -EazelInstallOperationStatus -revert_transaction (EazelInstall *service, GList *packages) +EazelInstallStatus +revert_transaction (EazelInstall *service, + GList *packages) { - EazelInstallOperationStatus result = EAZEL_INSTALL_NOTHING; + GList *uninst, *inst, *upgrade, *downgrade; + CategoryData *cat; + GList *categories; + EazelInstallStatus result = EAZEL_INSTALL_NOTHING; + + uninst = get_packages_with_mod_flag (packages, PACKAGE_MOD_INSTALLED); + inst = get_packages_with_mod_flag (packages, PACKAGE_MOD_UNINSTALLED); + upgrade = get_packages_with_mod_flag (packages, PACKAGE_MOD_DOWNGRADED); + downgrade = get_packages_with_mod_flag (packages, PACKAGE_MOD_UPGRADED); + + check_uninst_vs_downgrade (&uninst, &downgrade); + + g_list_foreach (uninst, (GFunc)debug_revert, "uninstall"); + g_list_foreach (inst, (GFunc)debug_revert, "install"); + g_list_foreach (downgrade, (GFunc)debug_revert, "downgrade"); + g_list_foreach (upgrade, (GFunc)debug_revert, "upgrade"); + + cat = categorydata_new (); + categories = g_list_prepend (NULL, cat); + + if (uninst) { + eazel_install_set_uninstall (service, TRUE); + eazel_install_set_downgrade (service, FALSE); + eazel_install_set_update (service, FALSE); + cat->packages = uninst; + if (uninstall_packages (service, categories) == EAZEL_INSTALL_UNINSTALL_OK) { + result = EAZEL_INSTALL_REVERSION_OK; + } + } + if (inst) { + eazel_install_set_uninstall (service, FALSE); + eazel_install_set_downgrade (service, FALSE); + eazel_install_set_update (service, FALSE); + cat->packages = inst; + if (install_packages (service, categories) == EAZEL_INSTALL_UNINSTALL_OK) { + result = EAZEL_INSTALL_REVERSION_OK; + } + } + if (downgrade) { + eazel_install_set_uninstall (service, FALSE); + eazel_install_set_downgrade (service, TRUE); + eazel_install_set_update (service, FALSE); + cat->packages = downgrade; + if (install_packages (service, categories) == EAZEL_INSTALL_UNINSTALL_OK) { + result = EAZEL_INSTALL_REVERSION_OK; + } + } + if (upgrade) { + eazel_install_set_uninstall (service, FALSE); + eazel_install_set_downgrade (service, TRUE); + eazel_install_set_update (service, TRUE); + cat->packages = upgrade; + if (install_packages (service, categories) == EAZEL_INSTALL_UNINSTALL_OK) { + result = EAZEL_INSTALL_REVERSION_OK; + } + } + + + categorydata_destroy (cat); + g_list_free (categories); + return result; } + + diff --git a/components/services/install/lib/eazel-install-object.c b/components/services/install/lib/eazel-install-object.c index c914de236..f5d874bd4 100644 --- a/components/services/install/lib/eazel-install-object.c +++ b/components/services/install/lib/eazel-install-object.c @@ -64,6 +64,7 @@ enum { DOWNLOAD_PROGRESS, PREFLIGHT_CHECK, INSTALL_PROGRESS, + UNINSTALL_PROGRESS, DOWNLOAD_FAILED, MD5_CHECK_FAILED, INSTALL_FAILED, @@ -123,6 +124,9 @@ void eazel_install_emit_feature_consistency_check_default (EazelInstall *service void eazel_install_emit_install_progress_default (EazelInstall *service, const PackageData *pack, int, int, int, int, int, int); +void eazel_install_emit_uninstall_progress_default (EazelInstall *service, + const PackageData *pack, + int, int, int, int, int, int); void eazel_install_emit_download_progress_default (EazelInstall *service, const PackageData *package, int amount, @@ -200,6 +204,7 @@ eazel_install_finalize (GtkObject *object) g_list_free (service->private->root_dirs); g_list_free (service->private->transaction); + g_list_free (service->private->failed_packages); g_free (service->private->transaction_dir); g_free (service->private->cur_root); @@ -235,13 +240,19 @@ eazel_install_start_signal (EazelPackageSystem *system, service->private->infoblock[2]++; switch (op) { case EAZEL_PACKAGE_SYSTEM_OPERATION_INSTALL: - case EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL: eazel_install_emit_install_progress (service, pack, service->private->infoblock[2], service->private->infoblock[3], 0, pack->bytesize, service->private->infoblock[4], service->private->infoblock[5]); break; + case EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL: + eazel_install_emit_uninstall_progress (service, + pack, + service->private->infoblock[2], service->private->infoblock[3], + 0, pack->bytesize, + service->private->infoblock[4], service->private->infoblock[5]); + break; default: break; } @@ -256,16 +267,29 @@ eazel_install_end_signal (EazelPackageSystem *system, { switch (op) { case EAZEL_PACKAGE_SYSTEM_OPERATION_INSTALL: - case EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL: eazel_install_emit_install_progress (service, pack, service->private->infoblock[2], service->private->infoblock[3], pack->bytesize, pack->bytesize, service->private->infoblock[4], service->private->infoblock[5]); break; + case EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL: + eazel_install_emit_uninstall_progress (service, + pack, + service->private->infoblock[2], service->private->infoblock[3], + pack->bytesize, pack->bytesize, + service->private->infoblock[4], service->private->infoblock[5]); + break; default: break; } + if (pack->toplevel) { + if (g_list_find (service->private->failed_packages, (PackageData*)pack) == NULL) { + g_message ("Adding %s to transaction", pack->name); + service->private->transaction = g_list_prepend (service->private->transaction, + (PackageData*)pack); + } + } return TRUE; } @@ -280,13 +304,19 @@ eazel_install_progress_signal (EazelPackageSystem *system, if ((info[0] != 0) && (info[0] != info[1])) { switch (op) { case EAZEL_PACKAGE_SYSTEM_OPERATION_INSTALL: - case EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL: eazel_install_emit_install_progress (service, pack, service->private->infoblock[2], service->private->infoblock[3], info[0], pack->bytesize, info[4], info[5]); break; + case EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL: + eazel_install_emit_uninstall_progress (service, + pack, + service->private->infoblock[2], service->private->infoblock[3], + info[0], pack->bytesize, + info[4], info[5]); + break; default: break; } @@ -301,6 +331,10 @@ eazel_install_failed_signal (EazelPackageSystem *system, EazelInstall *service) { trilobite_debug ("*** %s failed", pack->name); + + service->private->failed_packages = g_list_prepend (service->private->failed_packages, + (PackageData*)pack); + if (pack->toplevel) { trilobite_debug ("emiting failed for %s", pack->name); if (op==EAZEL_PACKAGE_SYSTEM_OPERATION_INSTALL) { @@ -461,6 +495,15 @@ eazel_install_class_initialize (EazelInstallClass *klass) GTK_TYPE_NONE, 7, GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT); + signals[UNINSTALL_PROGRESS] = + gtk_signal_new ("uninstall_progress", + GTK_RUN_LAST, + object_class->type, + GTK_SIGNAL_OFFSET (EazelInstallClass, uninstall_progress), + eazel_install_gtk_marshal_NONE__POINTER_INT_INT_INT_INT_INT_INT, + GTK_TYPE_NONE, 7, GTK_TYPE_POINTER, + GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, + GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT); signals[DOWNLOAD_FAILED] = gtk_signal_new ("download_failed", GTK_RUN_LAST, @@ -510,6 +553,7 @@ eazel_install_class_initialize (EazelInstallClass *klass) klass->file_uniqueness_check = NULL; klass->feature_consistency_check = NULL; klass->install_progress = NULL; + klass->uninstall_progress = NULL; klass->download_progress = NULL; klass->download_failed = NULL; klass->md5_check_failed = NULL; @@ -522,6 +566,7 @@ eazel_install_class_initialize (EazelInstallClass *klass) klass->file_uniqueness_check = eazel_install_emit_file_uniqueness_check_default; klass->feature_consistency_check = eazel_install_emit_feature_consistency_check_default; klass->install_progress = eazel_install_emit_install_progress_default; + klass->uninstall_progress = eazel_install_emit_uninstall_progress_default; klass->download_progress = eazel_install_emit_download_progress_default; klass->download_failed = eazel_install_emit_download_failed_default; klass->md5_check_failed = eazel_install_emit_md5_check_failed_default; @@ -666,6 +711,7 @@ eazel_install_initialize (EazelInstall *service) { (GCompareFunc)g_str_equal); service->private->downloaded_files = NULL; service->private->transaction = NULL; + service->private->failed_packages = NULL; service->private->revert = FALSE; service->private->ssl_rename = FALSE; service->private->ignore_file_conflicts = FALSE; @@ -687,7 +733,7 @@ eazel_install_initialize (EazelInstall *service) { char *tmp = NULL; #ifndef EAZEL_INSTALL_SLIM - tmp = g_strdup_printf ("%s/.nautilus/rpmdb/", g_get_home_dir ()); + tmp = g_strdup_printf ("%s/.nautilus/packagedb/", g_get_home_dir ()); list = g_list_prepend (list, g_strdup (g_get_home_dir ())); list = g_list_prepend (list, tmp); #else @@ -1158,7 +1204,6 @@ eazel_install_install_packages (EazelInstall *service, g_warning (_("Install failed")); } - eazel_install_unlock_tmp_dir (service); trilobite_debug ("service->private->downloaded_files = 0x%p", (unsigned int)service->private->downloaded_files); @@ -1199,15 +1244,7 @@ eazel_install_uninstall_packages (EazelInstall *service, GList *categories, cons eazel_install_fetch_remote_package_list (service); } -/* - FIXME: bugzilla.eazel.com 5752 - if (eazel_install_get_ei2 (service)) { - result = uninstall_packages (service, categories); - } else { - result = ei_uninstall_packages (service, categories); - } -*/ - result = ei_uninstall_packages (service, categories); + result = uninstall_packages (service, categories); if (result == EAZEL_INSTALL_NOTHING) { g_warning (_("Uninstall failed")); @@ -1232,17 +1269,7 @@ eazel_install_revert_transaction_from_xmlstring (EazelInstall *service, service->private->revert = TRUE; if (create_temporary_directory (service)) { - -/* - FIXME: bugzilla.eazel.com 5753 - if (eazel_install_get_ei2 (service)) { - result = revert_transaction (service, packages); - } else { - result = ei_revert_transaction (service, packages); - } -*/ - result = ei_revert_transaction (service, packages); - eazel_install_unlock_tmp_dir (service); + result = revert_transaction (service, packages); } else { result = EAZEL_INSTALL_NOTHING; } @@ -1293,6 +1320,110 @@ eazel_install_add_repository (EazelInstall *service, const char *dir) service->private->local_repositories = g_list_prepend (service->private->local_repositories, g_strdup (dir)); } +static void +eazel_install_do_transaction_save_report_helper (xmlNodePtr node, + GList *packages) +{ + GList *iterator; + + for (iterator = packages; iterator; iterator = g_list_next (iterator)) { + PackageData *pack; + char *tmp; + pack = (PackageData*)iterator->data; + switch (pack->modify_status) { + case PACKAGE_MOD_INSTALLED: + tmp = g_strdup_printf ("Installed %s", pack->name); + xmlNewChild (node, NULL, "DESCRIPTION", tmp); + g_free (tmp); + break; + case PACKAGE_MOD_UNINSTALLED: + tmp = g_strdup_printf ("Uninstalled %s", pack->name); + xmlNewChild (node, NULL, "DESCRIPTION", tmp); + g_free (tmp); + break; + default: + break; + } + if (pack->modifies) { + eazel_install_do_transaction_save_report_helper (node, pack->modifies); + } + } +} + +void +eazel_install_save_transaction_report (EazelInstall *service) +{ + FILE *outfile; + xmlDocPtr doc; + xmlNodePtr node, root; + char *name = NULL; + + if (eazel_install_get_transaction_dir (service) == NULL) { + g_warning ("Transaction directory not set, not storing transaction report"); + } + + /* Ensure the transaction dir is present */ + if (! g_file_test (eazel_install_get_transaction_dir (service), G_FILE_TEST_ISDIR)) { + int retval; + retval = mkdir (eazel_install_get_transaction_dir (service), 0755); + if (retval < 0) { + if (errno != EEXIST) { + g_warning (_("Could not create transaction directory (%s)! ***\n"), + eazel_install_get_transaction_dir (service)); + return; + } + } + } + + /* Create xml */ + doc = xmlNewDoc ("1.0"); + root = node = xmlNewNode (NULL, "TRANSACTION"); + xmlDocSetRootElement (doc, node); + + /* Make a unique name */ + name = g_strdup_printf ("%s/transaction.%lu", eazel_install_get_transaction_dir (service), + (unsigned long) time (NULL)); + while (g_file_test (name, G_FILE_TEST_ISFILE)) { + g_free (name); + sleep (1); + name = g_strdup_printf ("%s/transaction.%lu", + eazel_install_get_transaction_dir (service), + (unsigned long) time (NULL)); + } + + trilobite_debug (_("Writing transaction to %s"), name); + + /* Open and save */ + outfile = fopen (name, "w"); + xmlAddChild (root, eazel_install_packagelist_to_xml (service->private->transaction, FALSE)); + node = xmlAddChild (node, xmlNewNode (NULL, "DESCRIPTIONS")); + + { + char *tmp; + tmp = g_strdup_printf ("%lu", (unsigned long) time (NULL)); + xmlNewChild (node, NULL, "DATE", tmp); + g_free (tmp); + } + + eazel_install_do_transaction_save_report_helper (node, service->private->transaction); + + xmlDocDump (outfile, doc); + + fclose (outfile); + g_free (name); +} + +void +eazel_install_init_transaction (EazelInstall *service) +{ + /* Null the list of files met in the transaction */ + g_list_free (service->private->transaction); + service->private->transaction = NULL; + + /* Null the list of files met in the transaction */ + g_list_free (service->private->transaction); + service->private->transaction = NULL; +} /************************************************ Signal emitters and default handlers. @@ -1428,13 +1559,56 @@ eazel_install_emit_install_progress_default (EazelInstall *service, } void +eazel_install_emit_uninstall_progress (EazelInstall *service, + const PackageData *pack, + int package_num, int num_packages, + int package_size_completed, int package_size_total, + int total_size_completed, int total_size) +{ + EAZEL_INSTALL_SANITY(service); + gtk_signal_emit (GTK_OBJECT (service), signals[UNINSTALL_PROGRESS], + pack, + package_num, num_packages, + package_size_completed, package_size_total, + total_size_completed, total_size); + +} + +void +eazel_install_emit_uninstall_progress_default (EazelInstall *service, + const PackageData *pack, + int package_num, int num_packages, + int package_size_completed, int package_size_total, + int total_size_completed, int total_size) +{ +#ifndef EAZEL_INSTALL_NO_CORBA + CORBA_Environment ev; + CORBA_exception_init (&ev); + EAZEL_INSTALL_SANITY(service); + + if (service->callback != CORBA_OBJECT_NIL) { + GNOME_Trilobite_Eazel_PackageDataStruct *package; + package = corba_packagedatastruct_from_packagedata (pack); + GNOME_Trilobite_Eazel_InstallCallback_uninstall_progress (service->callback, + package, + package_num, num_packages, + package_size_completed, package_size_total, + total_size_completed, total_size, + &ev); + CORBA_free (package); + } + CORBA_exception_free (&ev); +#endif /* EAZEL_INSTALL_NO_CORBA */ +} + +void eazel_install_emit_download_progress (EazelInstall *service, const PackageData *pack, int amount, int total) { EAZEL_INSTALL_SANITY(service); - gtk_signal_emit (GTK_OBJECT (service), signals[DOWNLOAD_PROGRESS], pack, amount, total); + //gtk_signal_emit (GTK_OBJECT (service), signals[DOWNLOAD_PROGRESS], pack, amount, total); } void diff --git a/components/services/install/lib/eazel-install-private.h b/components/services/install/lib/eazel-install-private.h index 087242717..f2900eea7 100644 --- a/components/services/install/lib/eazel-install-private.h +++ b/components/services/install/lib/eazel-install-private.h @@ -74,12 +74,12 @@ struct _EazelInstallPrivate { but not erased. */ GHashTable *name_to_package_hash; - /* This holds the toplevel packages requested for - install/upgrade/uninstall. - Entries are added in eazel-install-rpm-glue.c, as - stuff is done. - It's cleaned up in the end of eazel_install_start_transaction */ + /* During an operation, this logs the toplevel packages + that were installed */ GList *transaction; + + /* During an operation, this logs all packages that failed */ + GList *failed_packages; /* The logfile used for the object */ FILE *logfile; diff --git a/components/services/install/lib/eazel-install-problem.c b/components/services/install/lib/eazel-install-problem.c index 59588e54b..21fac31cf 100644 --- a/components/services/install/lib/eazel-install-problem.c +++ b/components/services/install/lib/eazel-install-problem.c @@ -101,7 +101,7 @@ get_detailed_messages_breaks_foreach (PackageBreaks *breakage, GetErrorsForEachD } static void -get_detailed_messages_foreach (PackageData *pack, GetErrorsForEachData *data) +get_detailed_messages_foreach (GtkObject *foo, GetErrorsForEachData *data) { char *message = NULL; char *required = NULL; @@ -110,6 +110,17 @@ get_detailed_messages_foreach (PackageData *pack, GetErrorsForEachData *data) GList **errors = &(data->errors); PackageData *previous_pack = NULL; PackageData *top_pack = NULL; + PackageData *pack = NULL; + + if (IS_PACKAGEDATA (foo)) { + pack = PACKAGEDATA (foo); + } else if (IS_PACKAGEBREAKS (foo)) { + pack = packagebreaks_get_package (PACKAGEBREAKS (foo)); + } else if (IS_PACKAGEDEPENDENCY (foo)) { + pack = PACKAGEDEPENDENCY (foo)->package; + } else { + g_assert_not_reached (); + } if (data->path) { previous_pack = (PackageData*)(data->path->data); @@ -124,6 +135,7 @@ get_detailed_messages_foreach (PackageData *pack, GetErrorsForEachData *data) switch (pack->status) { case PACKAGE_UNKNOWN_STATUS: + case PACKAGE_CANCELLED: break; case PACKAGE_SOURCE_NOT_SUPPORTED: message = g_strdup_printf (_("%s is a source package, which is not yet supported"), @@ -141,7 +153,7 @@ get_detailed_messages_foreach (PackageData *pack, GetErrorsForEachData *data) } break; case PACKAGE_DEPENDENCY_FAIL: - if (pack->soft_depends) { + if (pack->depends) { } else { if (previous_pack && previous_pack->status == PACKAGE_BREAKS_DEPENDENCY) { @@ -231,7 +243,7 @@ get_detailed_messages_foreach (PackageData *pack, GetErrorsForEachData *data) /* Create the path list */ data->path = g_list_prepend (data->path, pack); - g_list_foreach (pack->soft_depends, (GFunc)get_detailed_messages_foreach, data); + g_list_foreach (pack->depends, (GFunc)get_detailed_messages_foreach, data); g_list_foreach (pack->modifies, (GFunc)get_detailed_messages_foreach, data); g_list_foreach (pack->breaks, (GFunc)get_detailed_messages_breaks_foreach, data); @@ -240,7 +252,7 @@ get_detailed_messages_foreach (PackageData *pack, GetErrorsForEachData *data) } static void -get_detailed_uninstall_messages_foreach (PackageData *pack, +get_detailed_uninstall_messages_foreach (GtkObject *foo, GetErrorsForEachData *data) { char *message = NULL; @@ -250,6 +262,17 @@ get_detailed_uninstall_messages_foreach (PackageData *pack, GList **errors = &(data->errors); PackageData *previous_pack = NULL; PackageData *top_pack = NULL; + PackageData *pack = NULL; + + if (IS_PACKAGEDATA (foo)) { + pack = PACKAGEDATA (foo); + } else if (IS_PACKAGEBREAKS (foo)) { + pack = packagebreaks_get_package (PACKAGEBREAKS (foo)); + } else if (IS_PACKAGEDEPENDENCY (foo)) { + pack = PACKAGEDEPENDENCY (foo)->package; + } else { + g_assert_not_reached (); + } if (data->path) { previous_pack = (PackageData*)(data->path->data); @@ -264,6 +287,7 @@ get_detailed_uninstall_messages_foreach (PackageData *pack, switch (pack->status) { case PACKAGE_UNKNOWN_STATUS: + case PACKAGE_CANCELLED: break; case PACKAGE_SOURCE_NOT_SUPPORTED: message = g_strdup_printf (_("%s is a source package, which is not yet supported"), @@ -310,7 +334,7 @@ get_detailed_uninstall_messages_foreach (PackageData *pack, /* Create the path list */ data->path = g_list_prepend (data->path, pack); - g_list_foreach (pack->soft_depends, (GFunc)get_detailed_uninstall_messages_foreach, data); + g_list_foreach (pack->depends, (GFunc)get_detailed_uninstall_messages_foreach, data); g_list_foreach (pack->modifies, (GFunc)get_detailed_uninstall_messages_foreach, data); g_list_foreach (pack->breaks, (GFunc)get_detailed_uninstall_messages_foreach, data); @@ -613,10 +637,22 @@ get_detailed_cases_breaks_foreach (PackageBreaks *breakage, GetErrorsForEachData - package status looks ok, check modification_status */ static void -get_detailed_cases_foreach (PackageData *pack, GetErrorsForEachData *data) +get_detailed_cases_foreach (GtkObject *foo, + GetErrorsForEachData *data) { /* GList **errors = &(data->errors); */ PackageData *previous_pack = NULL; + PackageData *pack = NULL; + + if (IS_PACKAGEDATA (foo)) { + pack = PACKAGEDATA (foo); + } else if (IS_PACKAGEBREAKS (foo)) { + pack = packagebreaks_get_package (PACKAGEBREAKS (foo)); + } else if (IS_PACKAGEDEPENDENCY (foo)) { + pack = PACKAGEDEPENDENCY (foo)->package; + } else { + g_assert_not_reached (); + } #ifdef EIP_DEBUG g_message ("get_detailed_cases_foreach (%p)", pack); @@ -633,13 +669,14 @@ get_detailed_cases_foreach (PackageData *pack, GetErrorsForEachData *data) switch (pack->status) { case PACKAGE_UNKNOWN_STATUS: + case PACKAGE_CANCELLED: break; case PACKAGE_SOURCE_NOT_SUPPORTED: break; case PACKAGE_FILE_CONFLICT: break; case PACKAGE_DEPENDENCY_FAIL: - if (pack->soft_depends) { + if (pack->depends) { } else { if (previous_pack && previous_pack->status == PACKAGE_BREAKS_DEPENDENCY) { add_update_case (data->problem, pack, FALSE, &(data->errors)); @@ -672,7 +709,7 @@ get_detailed_cases_foreach (PackageData *pack, GetErrorsForEachData *data) /* Create the path list */ data->path = g_list_prepend (data->path, pack); - g_list_foreach (pack->soft_depends, (GFunc)get_detailed_cases_foreach, data); + g_list_foreach (pack->depends, (GFunc)get_detailed_cases_foreach, data); g_list_foreach (pack->modifies, (GFunc)get_detailed_cases_foreach, data); g_list_foreach (pack->breaks, (GFunc)get_detailed_cases_breaks_foreach, data); @@ -686,9 +723,20 @@ get_detailed_cases_foreach (PackageData *pack, GetErrorsForEachData *data) - package status looks ok, check modification_status */ static void -get_detailed_uninstall_cases_foreach (PackageData *pack, GetErrorsForEachData *data) +get_detailed_uninstall_cases_foreach (GtkObject *foo, GetErrorsForEachData *data) { PackageData *previous_pack = NULL; + PackageData *pack = NULL; + + if (IS_PACKAGEDATA (foo)) { + pack = PACKAGEDATA (foo); + } else if (IS_PACKAGEBREAKS (foo)) { + pack = packagebreaks_get_package (PACKAGEBREAKS (foo)); + } else if (IS_PACKAGEDEPENDENCY (foo)) { + pack = PACKAGEDEPENDENCY (foo)->package; + } else { + g_assert_not_reached (); + } #ifdef EIP_DEBUG g_message ("get_detailed_uninstall_cases_foreach (data->path = %p)", data->path); @@ -706,6 +754,7 @@ get_detailed_uninstall_cases_foreach (PackageData *pack, GetErrorsForEachData *d switch (pack->status) { case PACKAGE_UNKNOWN_STATUS: + case PACKAGE_CANCELLED: break; case PACKAGE_SOURCE_NOT_SUPPORTED: break; @@ -733,7 +782,7 @@ get_detailed_uninstall_cases_foreach (PackageData *pack, GetErrorsForEachData *d /* Create the path list */ data->path = g_list_prepend (data->path, pack); - g_list_foreach (pack->soft_depends, (GFunc)get_detailed_uninstall_cases_foreach, data); + g_list_foreach (pack->depends, (GFunc)get_detailed_uninstall_cases_foreach, data); g_list_foreach (pack->modifies, (GFunc)get_detailed_uninstall_cases_foreach, data); g_list_foreach (pack->breaks, (GFunc)get_detailed_uninstall_cases_foreach, data); @@ -744,7 +793,7 @@ get_detailed_uninstall_cases_foreach (PackageData *pack, GetErrorsForEachData *d data->path = NULL; } - if (pack->toplevel) { + if (pack->toplevel && pack->status == PACKAGE_BREAKS_DEPENDENCY) { /* This is just to make sure the toplevel is first */ data->packs = g_list_reverse (data->packs); add_cascade_remove (data->problem, &(data->packs), FALSE, &(data->errors)); @@ -1105,9 +1154,9 @@ eazel_install_problem_tree_to_case (EazelInstallProblem *problem, problem->in_step_problem_mode = FALSE; if (uninstall) { - get_detailed_uninstall_cases_foreach (pack_copy, &data); + get_detailed_uninstall_cases_foreach (GTK_OBJECT (pack_copy), &data); } else { - get_detailed_cases_foreach (pack_copy, &data); + get_detailed_cases_foreach (GTK_OBJECT (pack_copy), &data); } gtk_object_unref (GTK_OBJECT (pack_copy)); @@ -1133,9 +1182,9 @@ eazel_install_problem_tree_to_string (EazelInstallProblem *problem, pack_copy = packagedata_copy (pack, TRUE); if (uninstall) { - get_detailed_uninstall_messages_foreach (pack_copy, &data); + get_detailed_uninstall_messages_foreach (GTK_OBJECT (pack_copy), &data); } else { - get_detailed_messages_foreach (pack_copy, &data); + get_detailed_messages_foreach (GTK_OBJECT (pack_copy), &data); } gtk_object_unref (GTK_OBJECT (pack_copy)); @@ -1267,7 +1316,6 @@ build_categories_from_problem_list (EazelInstallProblem *problem, break; case EI_PROBLEM_CASCADE_REMOVE: { GList *iterator; - g_message ("%s:%d cascade", __FILE__, __LINE__); for (iterator = pcase->u.cascade.packages; iterator; iterator = g_list_next (iterator)) { packages = g_list_prepend (packages, iterator->data); } diff --git a/components/services/install/lib/eazel-install-public.h b/components/services/install/lib/eazel-install-public.h index 0e455d629..a23ea793a 100644 --- a/components/services/install/lib/eazel-install-public.h +++ b/components/services/install/lib/eazel-install-public.h @@ -49,10 +49,10 @@ extern "C" { #define EAZEL_IS_INSTALL_CLASS(klass)(GTK_CHECK_CLASS_TYPE ((klass), TYPE_EAZEL_INSTALL)) typedef enum { - EAZEL_INSTALL_NOTHING = 0, - EAZEL_INSTALL_INSTALL_OK = 1<<0, - EAZEL_INSTALL_UNINSTALL_OK = 1<<1, - EAZEL_INSTALL_REVERSION_OK = 1<<2 + EAZEL_INSTALL_NOTHING = 0x0, + EAZEL_INSTALL_INSTALL_OK = 0x1, + EAZEL_INSTALL_UNINSTALL_OK = 0x2, + EAZEL_INSTALL_REVERSION_OK = 0x4 } EazelInstallOperationStatus; typedef enum { @@ -88,6 +88,11 @@ struct _EazelInstallClass int package_num, int num_packages, int package_size_completed, int package_size_total, int total_size_completed, int total_size); + void (*uninstall_progress) (EazelInstall *service, + const PackageData *pack, + int package_num, int num_packages, + int package_size_completed, int package_size_total, + int total_size_completed, int total_size); void (*dependency_check) (EazelInstall *service, const PackageData *pack, const PackageData *needed); /* if the set URLType is PROTOCOL_HTTP, info is a HTTPError struc @@ -159,6 +164,11 @@ void eazel_install_emit_install_progress (EazelInstall *service, int package_num, int num_packages, int package_size_completed, int package_size_total, int total_size_completed, int total_size); +void eazel_install_emit_uninstall_progress (EazelInstall *service, + const PackageData *pack, + int package_num, int num_packages, + int package_size_completed, int package_size_total, + int total_size_completed, int total_size); void eazel_install_emit_download_progress (EazelInstall *service, const PackageData *package, int amount, @@ -211,6 +221,8 @@ void eazel_install_revert_transaction_from_file (EazelInstall *service, void eazel_install_delete_downloads (EazelInstall *service); +void eazel_install_init_transaction (EazelInstall *service); +void eazel_install_save_transaction_report (EazelInstall *service); /******************************************************************************/ /* Beware, from hereonafter, it's #def madness, to make the get/set functions */ diff --git a/components/services/install/lib/eazel-package-system-rpm3.c b/components/services/install/lib/eazel-package-system-rpm3.c index dd026473b..d6fd69bd7 100644 --- a/components/services/install/lib/eazel-package-system-rpm3.c +++ b/components/services/install/lib/eazel-package-system-rpm3.c @@ -123,7 +123,7 @@ rpmmonitorpiggybag_new (EazelPackageSystemRpm3 *system, #ifdef USE_PERCENT lc = localeconv (); pig.separator = *(lc->decimal_point); - trilobite_debug ("I am in in a %c country", pig.separator); + info (system, "I am in in a %c country", pig.separator); pig.state = 1; pig.bytes_read_in_line = 0; pig.line[0] = '\0'; @@ -284,6 +284,25 @@ get_total_size_of_packages (const GList *packages) return result; } +static void +eazel_package_system_rpm3_set_mod_status (EazelPackageSystemRpm3 *system, + EazelPackageSystemOperation op, + PackageData *pack) +{ + if (pack->modify_status == PACKAGE_MOD_UNTOUCHED) { + switch (op) { + case EAZEL_PACKAGE_SYSTEM_OPERATION_INSTALL: + pack->modify_status = PACKAGE_MOD_INSTALLED; + break; + case EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL: + pack->modify_status = PACKAGE_MOD_UNINSTALLED; + break; + default: + break; + } + } +} + #ifdef USE_PERCENT /* This monitors an rpm process pipe and emits signals during execution */ @@ -414,6 +433,11 @@ monitor_rpm_process_pipe_percent_output (GIOChannel *source, pig->bytes_installed += pig->pack->bytesize; pig->packages_seen = g_list_prepend (pig->packages_seen, pig->pack); + + eazel_package_system_rpm3_set_mod_status (pig->system, + pig->op, + pig->pack); + eazel_package_system_emit_end (EAZEL_PACKAGE_SYSTEM (pig->system), pig->op, pig->pack); @@ -863,16 +887,16 @@ eazel_package_system_rpm3_packagedata_fill_from_header (EazelPackageSystemRpm3 * PackageData *package = packagedata_new (); PackageDependency *pack_dep = packagedependency_new (); - /* If it's a lib*.so* or a /yadayada, add to provides */ - if ((strncmp (requires_name[index], "lib", 3)==0 && - strstr (requires_name[index], ".so")) || + /* If it's a lib*.so* or a /yadayada, but not ld-linux.so + or rpmlib( add to provides */ + if (((strncmp (requires_name[index], "lib", 3)==0 && strstr (requires_name[index], ".so")) || (strncmp (requires_name[index], "ld-linux.so", 11) == 0) || - (*requires_name[index]=='/')) { - /* Unless it has a ( in the name */ - if (strchr (requires_name[index], '(')==NULL) { - package->features = g_list_prepend (package->features, - g_strdup (requires_name[index])); - } + (*requires_name[index]=='/')) && + (strncmp (requires_name[index], "rpmlib(", 7) != 0)) { + + + package->features = g_list_prepend (package->features, + g_strdup (requires_name[index])); } else { /* Otherwise, add as a package name */ package->name = g_strdup (requires_name[index]); @@ -881,7 +905,7 @@ eazel_package_system_rpm3_packagedata_fill_from_header (EazelPackageSystemRpm3 * NULL : g_strdup (requires_version[index]); } /* If anything set, add dep */ - if (package->name || package->provides) { + if (package->name || package->features) { pack_dep->sense = rpm_sense_to_softcat_sense (system, requires_flag[index]); package->archtype = trilobite_get_distribution_arch (); @@ -1273,6 +1297,18 @@ monitor_subcommand_pipe (EazelPackageSystemRpm3 *system, info (system, "ending monitor on %d", fd); } +static void +eazel_package_system_rpm3_set_state (EazelPackageSystemRpm3 *system, + GList *packages, + PackageSystemStatus status) { + GList *iterator; + for (iterator = packages; iterator; iterator = g_list_next (iterator)) { + PackageData *pack = PACKAGEDATA (iterator->data); + pack->status = status; + } +} + + /* returns TRUE on success */ static gboolean manual_rpm_command (GList *args, int *fd) @@ -1352,6 +1388,7 @@ eazel_package_system_rpm3_execute (EazelPackageSystemRpm3 *system, monitor_subcommand_pipe (system, fd, (GIOFunc)monitor_rpm_process_pipe, pig); #endif } else { + eazel_package_system_rpm3_set_state (system, pig->packages_to_expect, PACKAGE_CANCELLED); /* FIXME: fail all the packages in pig */ } } @@ -1362,6 +1399,7 @@ static void check_if_all_packages_seen (EazelPackageSystemRpm3 *system, const char *dbpath, EazelPackageSystemOperation op, + int flags, GList *packages, GList *seen) { @@ -1372,6 +1410,20 @@ check_if_all_packages_seen (EazelPackageSystemRpm3 *system, for (iterator = packages; iterator; iterator = g_list_next (iterator)) { PackageData *pack = (PackageData*)iterator->data; + + if (flags & EAZEL_PACKAGE_SYSTEM_OPERATION_TEST) { + eazel_package_system_emit_start (EAZEL_PACKAGE_SYSTEM (system), + op, + pack); + eazel_package_system_rpm3_set_mod_status (system, + op, + pack); + eazel_package_system_emit_end (EAZEL_PACKAGE_SYSTEM (system), + op, + pack); + continue; + } + /* HACK: that fixes bugzilla.eazel.com 4914 */ if (op==EAZEL_PACKAGE_SYSTEM_OPERATION_UNINSTALL) { if (eazel_package_system_is_installed (EAZEL_PACKAGE_SYSTEM (system), @@ -1386,6 +1438,9 @@ check_if_all_packages_seen (EazelPackageSystemRpm3 *system, eazel_package_system_emit_start (EAZEL_PACKAGE_SYSTEM (system), op, pack); + eazel_package_system_rpm3_set_mod_status (system, + op, + pack); eazel_package_system_emit_end (EAZEL_PACKAGE_SYSTEM (system), op, pack); @@ -1395,7 +1450,8 @@ check_if_all_packages_seen (EazelPackageSystemRpm3 *system, pack, (GCompareFunc)eazel_install_package_compare)) { fail (system, "did not see %s", pack->name); - eazel_package_system_emit_failed (EAZEL_PACKAGE_SYSTEM (system), op, pack); + eazel_package_system_emit_failed (EAZEL_PACKAGE_SYSTEM (system), + op, pack); } } } @@ -1427,7 +1483,7 @@ eazel_package_system_rpm3_install_uninstall (EazelPackageSystemRpm3 *system, eazel_package_system_rpm3_execute (system, &pig, args); destroy_string_list (args); - check_if_all_packages_seen (system, dbpath, op, packages, pig.packages_seen); + check_if_all_packages_seen (system, dbpath, op, flags, packages, pig.packages_seen); g_list_free (pig.packages_seen); g_hash_table_foreach_remove (pig.name_to_package, (GHRFunc)clear_name_to_package, NULL); diff --git a/components/services/install/lib/eazel-package-system-types.c b/components/services/install/lib/eazel-package-system-types.c index 6c7d70d92..918e29d13 100644 --- a/components/services/install/lib/eazel-package-system-types.c +++ b/components/services/install/lib/eazel-package-system-types.c @@ -38,10 +38,11 @@ #include <libtrilobite/trilobite-core-utils.h> -#define DEBUG_PACKAGE_ALLOCS +#undef DEBUG_PACKAGE_ALLOCS #ifdef DEBUG_PACKAGE_ALLOCS static int report_all = 0; + static int package_total_allocs = 0, package_max = 0; static int package_allocs = 0; GList *packages_allocated = NULL; @@ -106,7 +107,7 @@ categorydata_new (void) result = g_new0 (CategoryData, 1); #ifdef DEBUG_PACKAGE_ALLOCS category_allocs ++; - if (report_all) trilobite_debug ("category_allocs inced to %d (%p)", category_allocs, result); + if (report_all) trilobite_debug ("category_allocs increased to %d (%p)", category_allocs, result); #endif /* DEBUG_PACKAGE_ALLOCS */ result->name = NULL; result->description = NULL; @@ -157,13 +158,13 @@ categorydata_destroy_foreach (CategoryData *cd, gpointer ununsed) { #ifdef DEBUG_PACKAGE_ALLOCS category_allocs --; - if (report_all) trilobite_debug ("category_allocs = %d (%p) %s", category_allocs, cd, cd ? cd->name: "?"); + if (report_all) trilobite_debug ("category_allocs decreased to %d (%p) %s", category_allocs, cd, cd ? cd->name: "?"); #endif /* DEBUG_PACKAGE_ALLOCS */ g_return_if_fail (cd != NULL); - if (g_list_length (cd->packages)) { + if (cd->packages) { g_list_foreach (cd->packages, (GFunc)gtk_object_unref, NULL); - } + } else trilobite_debug ("EMPTY"); g_list_free (cd->packages); cd->packages = NULL; if (g_list_length (cd->depends)) { @@ -771,6 +772,9 @@ packagedata_status_enum_to_str (PackageSystemStatus st) case PACKAGE_RESOLVED: result = g_strdup ("RESOLVED"); break; + case PACKAGE_CANCELLED: + result = g_strdup ("CANCELLED"); + break; case PACKAGE_ALREADY_INSTALLED: result = g_strdup ("ALREADY_INSTALLED"); break; @@ -799,6 +803,7 @@ packagedata_status_str_to_enum (const char *st) else if (strcmp (st, "CANNOT_OPEN")==0) { result = PACKAGE_CANNOT_OPEN; } else if (strcmp (st, "PARTLY_RESOLVED")==0) { result = PACKAGE_PARTLY_RESOLVED; } else if (strcmp (st, "RESOLVED")==0) { result = PACKAGE_RESOLVED; } + else if (strcmp (st, "CANCELLED")==0) { result = PACKAGE_CANCELLED; } else if (strcmp (st, "ALREADY_INSTALLED")==0) { result = PACKAGE_ALREADY_INSTALLED; } else if (strcmp (st, "CIRCULAR_DEPENDENCY")==0) { result = PACKAGE_CIRCULAR_DEPENDENCY; } else { g_assert_not_reached (); result = PACKAGE_UNKNOWN_STATUS; }; diff --git a/components/services/install/lib/eazel-package-system-types.h b/components/services/install/lib/eazel-package-system-types.h index 32c405802..680e79b1e 100644 --- a/components/services/install/lib/eazel-package-system-types.h +++ b/components/services/install/lib/eazel-package-system-types.h @@ -70,7 +70,8 @@ enum _PackageSystemStatus { PACKAGE_PARTLY_RESOLVED, PACKAGE_ALREADY_INSTALLED, PACKAGE_CIRCULAR_DEPENDENCY, - PACKAGE_RESOLVED + PACKAGE_RESOLVED, + PACKAGE_CANCELLED }; /* Methods to convert enum to/from char* val. The returned char* must not be freed */ @@ -109,6 +110,7 @@ enum _PackageFillFlags { PACKAGE_FILL_NO_PROVIDES = 0x02, PACKAGE_FILL_NO_DEPENDENCIES = 0x04, PACKAGE_FILL_NO_DIRS_IN_PROVIDES = 0x8, /* only used if PACKAGE_FILL_NO_PROVIDES is not set */ + PACAKGE_FILL_NO_FEATURES = 0x10, PACKAGE_FILL_MINIMAL = 0x7fff, PACKAGE_FILL_INVALID = 0x8000 }; diff --git a/components/services/install/lib/eazel-package-system.c b/components/services/install/lib/eazel-package-system.c index 41b58e3e6..ffd77b432 100644 --- a/components/services/install/lib/eazel-package-system.c +++ b/components/services/install/lib/eazel-package-system.c @@ -263,7 +263,15 @@ eazel_package_system_install (EazelPackageSystem *system, { EPS_SANE (system); g_assert (system->private->install); - (*system->private->install) (system, root, packages, flags); + + /* If we're in test mode, disable FORCE just to trigger + any potiental errors */ + if (flags & EAZEL_PACKAGE_SYSTEM_OPERATION_TEST) { + (*system->private->install) (system, root, packages, + flags & ~EAZEL_PACKAGE_SYSTEM_OPERATION_FORCE); + } else { + (*system->private->install) (system, root, packages, flags); + } } void |