#include "hash_table.h"
#include "pkg.h"
#include "opkg_message.h"
+#include "pkg_depends.h"
#include "pkg_vec.h"
#include "pkg_hash.h"
#include "parse_util.h"
#include "pkg_parse.h"
#include "opkg_utils.h"
+#include "opkg_cmd.h"
#include "sprintf_alloc.h"
#include "file_util.h"
#include "libbb/libbb.h"
hash_table_deinit(&conf->pkg_hash);
}
-int dist_hash_add_from_file(const char *lists_dir, pkg_src_t * dist)
-{
- nv_pair_list_elt_t *l;
- char *list_file, *subname;
-
- list_for_each_entry(l, &conf->arch_list.head, node) {
- nv_pair_t *nv = (nv_pair_t *) l->data;
- sprintf_alloc(&subname, "%s-%s", dist->name, nv->name);
- sprintf_alloc(&list_file, "%s/%s", lists_dir, subname);
-
- if (file_exists(list_file)) {
- if (pkg_hash_add_from_file(list_file, dist, NULL, 0, 0)) {
- free(list_file);
- return -1;
- }
- pkg_src_list_append(&conf->pkg_src_list, subname,
- dist->value, "__dummy__", 0);
- }
-
- free(list_file);
- }
-
- return 0;
-}
-
int
pkg_hash_add_from_file(const char *file_name,
- pkg_src_t * src, pkg_dest_t * dest, int is_status_file, int state_flags)
+ pkg_src_t * src, pkg_dest_t * dest, int is_status_file, int state_flags,
+ void (*cb)(pkg_t *, void *), void *priv)
{
pkg_t *pkg;
FILE *fp;
continue;
}
+ if (!(pkg->state_flag & SF_NEED_DETAIL)) {
+ //opkg_msg(DEBUG, "Package %s is unrelated, ignoring.\n", pkg->name);
+ pkg_deinit(pkg);
+ free(pkg);
+ continue;
+ }
+
if (!pkg_get_architecture(pkg) || !pkg_get_arch_priority(pkg)) {
char *version_str = pkg_version_str_alloc(pkg);
opkg_msg(NOTICE, "Package %s version %s has no "
continue;
}
- hash_insert_pkg(pkg, is_status_file);
+ if (cb)
+ cb(pkg, priv);
+ else
+ hash_insert_pkg(pkg, is_status_file);
} while (!feof(fp));
/*
* Load in feed files from the cached "src" and/or "src/gz" locations.
*/
-int pkg_hash_load_feeds(void)
+int pkg_hash_load_feeds(int state_flags, void (*cb)(pkg_t *, void *), void *priv)
{
pkg_src_list_elt_t *iter;
- pkg_src_t *src, *subdist;
+ pkg_src_t *src;
char *list_file, *lists_dir;
opkg_msg(INFO, "\n");
sprintf_alloc(&list_file, "%s/%s", lists_dir, src->name);
if (file_exists(list_file)) {
- if (pkg_hash_add_from_file(list_file, src, NULL, 0, 0)) {
+ if (pkg_hash_add_from_file(list_file, src, NULL, 0, state_flags, cb, priv)) {
free(list_file);
return -1;
}
/*
* Load in status files from the configured "dest"s.
*/
-int pkg_hash_load_status_files(void)
+int pkg_hash_load_status_files(void (*cb)(pkg_t *, void *), void *priv)
{
pkg_dest_list_elt_t *iter;
pkg_dest_t *dest;
if (file_exists(dest->status_file_name)) {
if (pkg_hash_add_from_file
- (dest->status_file_name, NULL, dest, 1, SF_NEED_DETAIL))
+ (dest->status_file_name, NULL, dest, 1, SF_NEED_DETAIL, cb, priv))
return -1;
}
}
return 0;
}
+static void
+pkg_hash_load_package_details_helper(const char *pkg_name, void *entry, void *data)
+{
+ int *count = data;
+ abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry;
+
+ if (ab_pkg->state_flag & SF_NEED_DETAIL) {
+ if (ab_pkg->state_flag & SF_MARKED) {
+ opkg_msg(DEBUG, "skipping already seen flagged abpkg %s\n",
+ ab_pkg->name);
+ return;
+ }
+
+ opkg_msg(DEBUG, "found yet incomplete flagged abpkg %s\n",
+ ab_pkg->name);
+
+ (*count)++;
+ ab_pkg->state_flag |= SF_MARKED;
+ }
+}
+
+int pkg_hash_load_package_details(void)
+{
+ int n_need_detail;
+
+ while (1) {
+ pkg_hash_load_feeds(0, NULL, NULL);
+
+ n_need_detail = 0;
+ hash_table_foreach(&conf->pkg_hash, pkg_hash_load_package_details_helper, &n_need_detail);
+
+ if (n_need_detail > 0)
+ opkg_msg(DEBUG, "Found %d packages requiring details, reloading feeds\n", n_need_detail);
+ else
+ break;
+ }
+
+ return 0;
+}
+
+static int
+pkg_hash_check_unresolved(pkg_t *maybe)
+{
+ char **unresolved = NULL;
+ char **tmp;
+ pkg_vec_t *depends;
+ int res = 0;
+
+ depends = pkg_vec_alloc();
+ pkg_hash_fetch_unsatisfied_dependencies(maybe, depends, &unresolved, 1);
+
+ if (unresolved) {
+ res = 1;
+ tmp = unresolved;
+ while (*tmp) {
+ opkg_msg(ERROR, "cannot find dependency %s for %s\n", *tmp, maybe->name);
+ free(*(tmp++));
+ }
+ free(unresolved);
+ }
+ pkg_vec_free(depends);
+
+ return res;
+}
+
pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg,
int (*constraint_fcn) (pkg_t *
pkg,
int nmatching = 0;
int wrong_arch_found = 0;
int arch_priority;
+ int good_pkg_score = 0;
pkg_vec_t *matching_pkgs;
abstract_pkg_vec_t *matching_apkgs;
abstract_pkg_vec_t *provided_apkg_vec;
if ((arch_priority > 0)
&&
(!pkg_vec_contains(matching_pkgs, maybe))) {
- max_count++;
- abstract_pkg_vec_insert(matching_apkgs,
- maybe->parent);
- pkg_vec_insert(matching_pkgs, maybe);
+ if (!pkg_hash_check_unresolved(maybe)) {
+ max_count++;
+ abstract_pkg_vec_insert(matching_apkgs,
+ maybe->parent);
+ pkg_vec_insert(matching_pkgs, maybe);
+ }
}
}
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);
+ abstract_pkg_vec_sort(matching_apkgs, abstract_pkg_name_compare);
for (i = 0; i < matching_pkgs->len; i++) {
pkg_t *matching = matching_pkgs->pkgs[i];
if (constraint_fcn(matching, cdata)) {
- opkg_msg(DEBUG, "Candidate: %s %s.\n",
- matching->name, pkg_get_string(matching, PKG_VERSION));
+ int score = 1;
+ if (strcmp(matching->name, apkg->name) == 0)
+ score++;
+
+ for (j = 0; j < opkg_cli_argc; ++j) {
+ if (!strcmp(matching->name, opkg_cli_argv[j])) {
+ score++;
+ break;
+ }
+ }
+
+ opkg_msg(DEBUG, "Candidate: %s %s (score %d).\n",
+ matching->name, pkg_get_string(matching, PKG_VERSION),
+ score);
+ if (score < good_pkg_score)
+ continue;
+
good_pkg_by_name = matching;
+ good_pkg_score = score;
/* It has been provided by hand, so it is what user want */
if (matching->provided_by_hand == 1)
break;