pkg_t *pkg_hash_fetch_best_installation_candidate_by_name(ipkg_conf_t *conf, const char *name) { hash_table_t *hash = &conf->pkg_hash; abstract_pkg_t *apkg = NULL; if (!(apkg = abstract_pkg_fetch_by_name(hash, name))) return NULL; return pkg_hash_fetch_best_installation_candidate(conf, apkg, pkg_name_constraint_fcn, apkg->name, 0); }
/* returns ndependencies or negative error value */ int pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied, char ***unresolved) { pkg_t *satisfier_entry_pkg; int i, j; unsigned int k; int count, found; char **the_lost; abstract_pkg_t *ab_pkg; /* * this is a setup to check for redundant/cyclic dependency checks, * which are marked at the abstract_pkg level */ ab_pkg = pkg->parent; if (!ab_pkg) { opkg_msg(ERROR, "Internal error, with pkg %s.\n", pkg->name); *unresolved = NULL; return 0; } if (ab_pkg->dependencies_checked) { /* avoid duplicate or cyclic checks */ opkg_msg(DEBUG2, "Already checked dependencies for '%s'.\n", ab_pkg->name); *unresolved = NULL; return 0; } else { opkg_msg(DEBUG2, "Checking dependencies for '%s'.\n", ab_pkg->name); ab_pkg->dependencies_checked = 1; /* mark it for subsequent visits */ } count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count; if (!count) { *unresolved = NULL; return 0; } the_lost = NULL; /* foreach dependency */ for (i = 0; i < count; i++) { compound_depend_t *compound_depend = &pkg->depends[i]; depend_t **possible_satisfiers = compound_depend->possibilities;; found = 0; satisfier_entry_pkg = NULL; if (compound_depend->type == GREEDY_DEPEND) { /* foreach possible satisfier */ for (j = 0; j < compound_depend->possibility_count; j++) { /* foreach provided_by, which includes the abstract_pkg itself */ abstract_pkg_t *abpkg = possible_satisfiers[j]->pkg; abstract_pkg_vec_t *ab_provider_vec = abpkg->provided_by; int nposs = ab_provider_vec->len; abstract_pkg_t **ab_providers = ab_provider_vec->pkgs; int l; for (l = 0; l < nposs; l++) { pkg_vec_t *test_vec = ab_providers[l]->pkgs; /* if no depends on this one, try the first package that * Provides this one */ if (!test_vec) { /* no pkg_vec hooked up to the abstract_pkg! (need another feed?) */ continue; } /* cruise this possiblity's pkg_vec looking for an installed version */ for (k = 0; k < test_vec->len; k++) { pkg_t *pkg_scout = test_vec->pkgs[k]; /* not installed, and not already known about? */ int wanted = (pkg_scout->state_want != SW_INSTALL) && !pkg_scout->parent->dependencies_checked && !is_pkg_in_pkg_vec(unsatisfied, pkg_scout); if (wanted) { char **newstuff = NULL; int rc; pkg_vec_t *tmp_vec = pkg_vec_alloc(); /* check for not-already-installed dependencies */ rc = pkg_hash_fetch_unsatisfied_dependencies(pkg_scout, tmp_vec, &newstuff); if (newstuff == NULL) { int m; int ok = 1; for (m = 0; m < rc; m++) { pkg_t *p = tmp_vec->pkgs[m]; if (p->state_want == SW_INSTALL) continue; opkg_msg(DEBUG, "Not installing %s due" " to requirement for %s.\n", pkg_scout->name, p->name); ok = 0; break; } pkg_vec_free(tmp_vec); if (ok) { /* mark this one for installation */ opkg_msg(NOTICE, "Adding satisfier for greedy" " dependence %s.\n", pkg_scout->name); pkg_vec_insert(unsatisfied, pkg_scout); } } else { opkg_msg(DEBUG, "Not installing %s due to " "broken depends.\n", pkg_scout->name); free(newstuff); } } } } } continue; } /* foreach possible satisfier, look for installed package */ for (j = 0; j < compound_depend->possibility_count; j++) { /* foreach provided_by, which includes the abstract_pkg itself */ depend_t *dependence_to_satisfy = possible_satisfiers[j]; abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg; pkg_t *satisfying_pkg = pkg_hash_fetch_best_installation_candidate( satisfying_apkg, pkg_installed_and_constraint_satisfied, dependence_to_satisfy, 1); opkg_msg(DEBUG, "satisfying_pkg=%p\n", satisfying_pkg); if (satisfying_pkg != NULL) { found = 1; break; } } /* if nothing installed matches, then look for uninstalled satisfier */ if (!found) { /* foreach possible satisfier, look for installed package */ for (j = 0; j < compound_depend->possibility_count; j++) { /* foreach provided_by, which includes the abstract_pkg itself */ depend_t *dependence_to_satisfy = possible_satisfiers[j]; abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg; pkg_t *satisfying_pkg = pkg_hash_fetch_best_installation_candidate( satisfying_apkg, pkg_constraint_satisfied, dependence_to_satisfy, 1); opkg_msg(DEBUG, "satisfying_pkg=%p\n", satisfying_pkg); if (!satisfying_pkg) continue; /* user request overrides package recommendation */ int ignore = (compound_depend->type == RECOMMEND || compound_depend->type == SUGGEST) && (satisfying_pkg->state_want == SW_DEINSTALL || satisfying_pkg->state_want == SW_PURGE || opkg_config->no_install_recommends); if (ignore) { opkg_msg(NOTICE, "%s: ignoring recommendation for " "%s at user request\n", pkg->name, satisfying_pkg->name); continue; } /* Check for excluded packages */ int exclude = str_list_contains(&opkg_config->exclude_list, satisfying_pkg->name); if (exclude) { opkg_msg(NOTICE, "%s: exclude required package %s at users request\n", pkg->name, satisfying_pkg->name); continue; } satisfier_entry_pkg = satisfying_pkg; break; } } /* we didn't find one, add something to the unsatisfied vector */ if (!found) { if (!satisfier_entry_pkg) { /* failure to meet recommendations is not an error */ int required = compound_depend->type != RECOMMEND && compound_depend->type != SUGGEST; if (required) the_lost = add_unresolved_dep(pkg, the_lost, i); else opkg_msg(NOTICE, "%s: unsatisfied recommendation for %s\n", pkg->name, compound_depend->possibilities[0]->pkg->name); } else { if (compound_depend->type == SUGGEST) { /* just mention it politely */ opkg_msg(NOTICE, "package %s suggests installing %s\n", pkg->name, satisfier_entry_pkg->name); } else { char **newstuff = NULL; int not_seen_before = satisfier_entry_pkg != pkg && !is_pkg_in_pkg_vec(unsatisfied, satisfier_entry_pkg); if (not_seen_before) { pkg_vec_insert(unsatisfied, satisfier_entry_pkg); pkg_hash_fetch_unsatisfied_dependencies(satisfier_entry_pkg, unsatisfied, &newstuff); the_lost = merge_unresolved(the_lost, newstuff); if (newstuff) free(newstuff); } } } } } *unresolved = the_lost; return unsatisfied->len; }
pkg_vec_t *pkg_hash_fetch_satisfied_dependencies(pkg_t * pkg) { pkg_vec_t *satisfiers; int i, j; unsigned int k; int count; abstract_pkg_t *ab_pkg; satisfiers = pkg_vec_alloc(); /* * this is a setup to check for redundant/cyclic dependency checks, * which are marked at the abstract_pkg level */ ab_pkg = pkg->parent; if (!ab_pkg) { opkg_msg(ERROR, "Internal error, with pkg %s.\n", pkg->name); return satisfiers; } count = pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count; if (!count) return satisfiers; /* foreach dependency */ for (i = 0; i < count; i++) { compound_depend_t *compound_depend = &pkg->depends[i]; depend_t **possible_satisfiers = compound_depend->possibilities;; int not_required = compound_depend->type == RECOMMEND || compound_depend->type == SUGGEST; if (not_required) continue; if (compound_depend->type == GREEDY_DEPEND) { /* foreach possible satisfier */ for (j = 0; j < compound_depend->possibility_count; j++) { /* foreach provided_by, which includes the abstract_pkg itself */ abstract_pkg_t *abpkg = possible_satisfiers[j]->pkg; abstract_pkg_vec_t *ab_provider_vec = abpkg->provided_by; int nposs = ab_provider_vec->len; abstract_pkg_t **ab_providers = ab_provider_vec->pkgs; int l; for (l = 0; l < nposs; l++) { pkg_vec_t *test_vec = ab_providers[l]->pkgs; /* if no depends on this one, try the first package that * Provides this one */ if (!test_vec) { /* no pkg_vec hooked up to the abstract_pkg! (need another feed?) */ continue; } /* cruise this possiblity's pkg_vec looking for an installed version */ for (k = 0; k < test_vec->len; k++) { pkg_t *pkg_scout = test_vec->pkgs[k]; /* not installed, and not already known about? */ int not_seen_before = pkg_scout != pkg && pkg_scout->state_want == SW_INSTALL; if (not_seen_before) pkg_vec_insert(satisfiers, pkg_scout); } } } continue; } /* foreach possible satisfier, look for installed package */ for (j = 0; j < compound_depend->possibility_count; j++) { /* foreach provided_by, which includes the abstract_pkg itself */ depend_t *dependence_to_satisfy = possible_satisfiers[j]; abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg; pkg_t *satisfying_pkg = pkg_hash_fetch_best_installation_candidate(satisfying_apkg, pkg_constraint_satisfied, dependence_to_satisfy, 0); int need_to_insert = satisfying_pkg != NULL && satisfying_pkg != pkg && (satisfying_pkg->state_want == SW_INSTALL || satisfying_pkg->state_want == SW_UNKNOWN); if (need_to_insert) pkg_vec_insert(satisfiers, satisfying_pkg); } } return satisfiers; }