-pkg_t *pkg_hash_fetch_best_installation_candidate(opkg_conf_t *conf, abstract_pkg_t *apkg,
- int (*constraint_fcn)(pkg_t *pkg, void *cdata), void *cdata, int quiet)
-{
- int i;
- int nprovides = 0;
- int nmatching = 0;
- pkg_vec_t *matching_pkgs = pkg_vec_alloc();
- abstract_pkg_vec_t *matching_apkgs = abstract_pkg_vec_alloc();
- abstract_pkg_vec_t *provided_apkg_vec;
- abstract_pkg_t **provided_apkgs;
- abstract_pkg_vec_t *providers = abstract_pkg_vec_alloc();
- pkg_t *latest_installed_parent = NULL;
- pkg_t *latest_matching = NULL;
- pkg_t *held_pkg = NULL;
- pkg_t *good_pkg_by_name = NULL;
-
- if (matching_apkgs == NULL || providers == NULL ||
- apkg == NULL || apkg->provided_by == NULL || (apkg->provided_by->len == 0))
- return NULL;
-
- opkg_message(conf, OPKG_DEBUG, "best installation candidate for %s\n", apkg->name);
-
- provided_apkg_vec = apkg->provided_by;
- nprovides = provided_apkg_vec->len;
- provided_apkgs = provided_apkg_vec->pkgs;
- if (nprovides > 1)
- opkg_message(conf, OPKG_DEBUG, " apkg=%s nprovides=%d\n", apkg->name, nprovides);
-
- /* accumulate all the providers */
- for (i = 0; i < nprovides; i++) {
- abstract_pkg_t *provider_apkg = provided_apkgs[i];
- opkg_message(conf, OPKG_DEBUG, " adding %s to providers\n", provider_apkg->name);
- abstract_pkg_vec_insert(providers, provider_apkg);
- }
- nprovides = providers->len;
-
- for (i = 0; i < nprovides; i++) {
- abstract_pkg_t *provider_apkg = abstract_pkg_vec_get(providers, i);
- abstract_pkg_t *replacement_apkg = NULL;
- pkg_vec_t *vec;
-
- if (provider_apkg->replaced_by && provider_apkg->replaced_by->len) {
- replacement_apkg = provider_apkg->replaced_by->pkgs[0];
- if (provider_apkg->replaced_by->len > 1) {
- opkg_message(conf, OPKG_NOTICE, "Multiple replacers for %s, using first one (%s)\n",
- provider_apkg->name, replacement_apkg->name);
- }
- }
-
- if (replacement_apkg)
- opkg_message(conf, OPKG_DEBUG, " replacement_apkg=%s for provider_apkg=%s\n",
- replacement_apkg->name, provider_apkg->name);
-
- if (replacement_apkg && (replacement_apkg != provider_apkg)) {
- if (abstract_pkg_vec_contains(providers, replacement_apkg))
- continue;
- else
- provider_apkg = replacement_apkg;
- }
-
- if (!(vec = provider_apkg->pkgs)) {
- opkg_message(conf, OPKG_DEBUG, " no pkgs for provider_apkg %s\n", provider_apkg->name);
- continue;
- }
-
-
- /* now check for supported architecture */
- {
- int max_count = 0;
- int i;
-
- /* count packages matching max arch priority and keep track of last one */
- for (i = 0; i < vec->len; i++) {
- pkg_t *maybe = vec->pkgs[i];
- opkg_message(conf, OPKG_DEBUG, " %s arch=%s arch_priority=%d version=%s \n",
- maybe->name, maybe->architecture, maybe->arch_priority, maybe->version);
- if (maybe->arch_priority > 0) {
- max_count++;
- abstract_pkg_vec_insert(matching_apkgs, maybe->parent);
- pkg_vec_insert(matching_pkgs, maybe);
- }
- }
- }
- }
-
- if (matching_pkgs->len > 1)
- pkg_vec_sort(matching_pkgs, pkg_name_version_and_architecture_compare);
- if (matching_apkgs->len > 1)
- abstract_pkg_vec_sort(matching_pkgs, abstract_pkg_name_compare);
-
-/* Here it is usefull, if ( matching_apkgs->len > 1 ), to test if one of this matching packages has the same name of the
- needed package. In this case, I would return it for install, otherwise I will continue with the procedure */
-/* The problem is what to do when there are more than a mathing package, with the same name and several version ?
- Until now I always got the latest, but that breaks the downgrade option.
- If I stop at the first one, I would probably miss the new ones
- Maybe the way is to have some kind of flag somewhere, to see if the package been asked to install is from a file,
- or from a Packages feed.
- It it is from a file it always need to be checked whatever version I have in feeds or everywhere, according to force-down or whatever options*/
-/*Pigi*/
-
- for (i = 0; i < matching_pkgs->len; i++) {
- pkg_t *matching = matching_pkgs->pkgs[i];
- if (constraint_fcn(matching, cdata)) { /* We found it */
- opkg_message(conf, OPKG_DEBUG, " Found a valid candidate for the install: %s %s \n", matching->name, matching->version) ;
- good_pkg_by_name = matching;
- if ( matching->provided_by_hand == 1 ) /* It has been provided by hand, so it is what user want */
- break;
- }
- }
-
-
- for (i = 0; i < matching_pkgs->len; i++) {
- pkg_t *matching = matching_pkgs->pkgs[i];
- latest_matching = matching;
- if (matching->parent->state_status == SS_INSTALLED || matching->parent->state_status == SS_UNPACKED)
- latest_installed_parent = matching;
- if (matching->state_flag & (SF_HOLD|SF_PREFER)) {
- if (held_pkg)
- opkg_message(conf, OPKG_ERROR, "Multiple packages (%s and %s) providing same name marked HOLD or PREFER. Using latest.\n",
- held_pkg->name, matching->name);
- held_pkg = matching;
- }
- }
-
- if (!good_pkg_by_name && !held_pkg && !latest_installed_parent && matching_apkgs->len > 1 && !quiet) {
- opkg_message(conf, OPKG_ERROR, "Package=%s, %d matching providers\n",
- apkg->name, matching_apkgs->len);
- for (i = 0; i < matching_apkgs->len; i++) {
- abstract_pkg_t *matching = matching_apkgs->pkgs[i];
- opkg_message(conf, OPKG_ERROR, " %s\n", matching->name);
- }
- opkg_message(conf, OPKG_ERROR, "Please select one with opkg install or opkg flag prefer\n");
- }
-
- if (matching_apkgs->len > 1 && conf->verbosity > 1) {
- opkg_message(conf, OPKG_NOTICE, "%s: for apkg=%s, %d matching pkgs\n",
- __FUNCTION__, apkg->name, matching_pkgs->len);
- for (i = 0; i < matching_pkgs->len; i++) {
- pkg_t *matching = matching_pkgs->pkgs[i];
- opkg_message(conf, OPKG_INFO, " %s %s %s\n",
- matching->name, matching->version, matching->architecture);
- }
- }
-
- nmatching = matching_apkgs->len;
-
- pkg_vec_free(matching_pkgs);
- abstract_pkg_vec_free(matching_apkgs);
- abstract_pkg_vec_free(providers);
-
- if (good_pkg_by_name) { /* We found a good candidate, we will install it */
- return good_pkg_by_name;
- }
- if (held_pkg) {
- opkg_message(conf, OPKG_INFO, " using held package %s\n", held_pkg->name);
- return held_pkg;
- }
- if (latest_installed_parent) {
- opkg_message(conf, OPKG_INFO, " using latest version of installed package %s\n", latest_installed_parent->name);
- return latest_installed_parent;
- }
- if (nmatching > 1) {
- opkg_message(conf, OPKG_INFO, " no matching pkg out of matching_apkgs=%d\n", nmatching);
- return NULL;
- }
- if (latest_matching) {
- opkg_message(conf, OPKG_INFO, " using latest matching %s %s %s\n",
- latest_matching->name, latest_matching->version, latest_matching->architecture);
- return latest_matching;
- }
- return NULL;