Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Implement provide/require rules in solver.
Vsevolod Stakhov committed 12 years ago
commit 2d62b3ed5be40c3d86658e0bb8921f965a636dcb
parent 299b67e
2 files changed +81 -2
modified libpkg/pkg_jobs.c
@@ -587,11 +587,15 @@ pkg_jobs_add_universe(struct pkg_jobs *j, struct pkg *pkg,
	struct pkg_dep *d = NULL;
	struct pkg_conflict *c = NULL;
	struct pkg *npkg, *rpkg;
-
	int ret;
	struct pkg_job_universe_item *unit;
	struct pkg_shlib *shlib = NULL;
	struct pkgdb_it *it;
	struct pkg_job_provide *pr, *prhead;
+
	int ret;
+
	const char *origin;
+
	unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
+
			PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
+
			PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;

	if (!deps_only) {
		/* Add the requested package itself */
@@ -702,11 +706,15 @@ pkg_jobs_add_universe(struct pkg_jobs *j, struct pkg *pkg,
	/* For remote packages we should also handle shlib deps */
	if (pkg->type != PKG_INSTALLED) {
		while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
+
			HASH_FIND_STR(j->provides, pkg_shlib_name(shlib), pr);
+
			if (pr != NULL)
+
				continue;
+
			/* Not found, search in the repos */
			it = pkgdb_find_shlib_provide(j->db, pkg_shlib_name(shlib), j->reponame);
			if (it != NULL) {
				npkg = NULL;
				prhead = NULL;
-
				while (pkgdb_it_next(it, &npkg, PKG_LOAD_BASIC) == EPKG_OK) {
+
				while (pkgdb_it_next(it, &npkg, flags) == EPKG_OK) {
					if (pkg_jobs_add_universe(j, npkg, recursive, false, &unit) != EPKG_OK)
						return (EPKG_FATAL);
					pr = calloc (1, sizeof (*pr));
@@ -727,6 +735,12 @@ pkg_jobs_add_universe(struct pkg_jobs *j, struct pkg *pkg,
					npkg = NULL;
				}
				pkgdb_it_free(it);
+
				if (prhead == NULL) {
+
					pkg_get(pkg, PKG_ORIGIN, &origin);
+
					pkg_emit_error("cannot find packages that provide %s required for %s",
+
							pkg_shlib_name(shlib), origin);
+
					return (EPKG_FATAL);
+
				}
			}
		}
	}
modified libpkg/pkg_solve.c
@@ -579,6 +579,8 @@ pkg_solve_add_pkg_rule(struct pkg_jobs *j, struct pkg_solve_problem *problem,
	struct pkg_solve_rule *rule;
	struct pkg_solve_item *it = NULL;
	struct pkg_solve_variable *var, *tvar, *cur_var;
+
	struct pkg_shlib *shlib = NULL;
+
	struct pkg_job_provide *pr, *prhead;
	int cnt;

	const char *origin;
@@ -689,6 +691,69 @@ pkg_solve_add_pkg_rule(struct pkg_jobs *j, struct pkg_solve_problem *problem,
			}
		}

+
		/* Check required shlibs */
+
		shlib = NULL;
+
		if (pkg->type != PKG_INSTALLED) {
+
			while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
+
				rule = NULL;
+
				it = NULL;
+
				var = NULL;
+
				HASH_FIND_STR(j->provides, pkg_shlib_name(shlib), prhead);
+
				if (prhead != NULL) {
+
					/* Require rule !A | P1 | P2 | P3 ... */
+
					rule = pkg_solve_rule_new();
+
					if (rule == NULL)
+
						goto err;
+
					/* !A */
+
					it = pkg_solve_item_new(cur_var);
+
					if (it == NULL)
+
						goto err;
+

+
					it->inverse = true;
+
					RULE_ITEM_PREPEND(rule, it);
+
					/* B1 | B2 | ... */
+
					cnt = 1;
+
					LL_FOREACH(prhead, pr) {
+
						/* For each provide */
+
						pkg_get(pr->un->pkg, PKG_ORIGIN, &origin);
+
						HASH_FIND(ho, problem->variables_by_origin, origin,
+
								strlen(origin), var);
+
						if (var == NULL) {
+
							if (pkg_solve_add_universe_variable(j, problem, origin, &var)
+
									!= EPKG_OK)
+
								continue;
+
						}
+
						/* XXX: select all its versions? */
+
						LL_FOREACH(var, tvar) {
+
							if (var->unit->pkg->type == PKG_INSTALLED)
+
								continue;
+
							it = pkg_solve_item_new(tvar);
+
							if (it == NULL)
+
								goto err;
+

+
							it->inverse = false;
+
							RULE_ITEM_PREPEND(rule, it);
+
							cnt ++;
+
						}
+
					}
+

+
					pkg_solve_add_var_rules (var, rule->items, cnt, true, "provide");
+
					pkg_solve_add_var_rules (cur_var, rule->items, cnt, false, "provide");
+

+
					LL_PREPEND(problem->rules, rule);
+
					problem->rules_count ++;
+
				}
+
#if 0
+
				/* XXX: not working */
+
				else {
+
					pkg_emit_error("solver: cannot find provide for required shlib %s",
+
							pkg_shlib_name(shlib));
+
					goto err;
+
				}
+
#endif
+
			}
+
		}
+

		if (conflicting) {
			/*
			 * If this var chain contains mutually conflicting vars