Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge pull request #1214 from vstakhov/master
Vsevolod Stakhov committed 11 years ago
commit 9e146776a8b034362e02ee9d57fd20ba46591ce6
parent 82c2469
6 files changed +205 -197
modified libpkg/pkg_jobs_universe.c
@@ -59,7 +59,7 @@ pkg_jobs_universe_get_local(struct pkg_jobs_universe *universe,
	if (flag == 0) {
		if (!IS_DELETE(universe->j))
			flag = PKG_LOAD_BASIC|PKG_LOAD_DEPS|PKG_LOAD_RDEPS|PKG_LOAD_OPTIONS|
-
				PKG_LOAD_REQUIRES|
+
				PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
				PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_ANNOTATIONS|
				PKG_LOAD_CONFLICTS;
		else
@@ -340,110 +340,134 @@ pkg_jobs_universe_process_conflicts(struct pkg_jobs_universe *universe,
}

static int
-
pkg_jobs_universe_process_shlibs(struct pkg_jobs_universe *universe,
-
	struct pkg *pkg)
+
pkg_jobs_universe_handle_provide(struct pkg_jobs_universe *universe,
+
		struct pkgdb_it *it, const char *name, bool is_shlib)
{
-
	struct pkg_shlib *shlib = NULL;
	struct pkg_job_universe_item *unit;
	struct pkg_job_provide *pr, *prhead;
-
	struct pkgdb_it *it;
	struct pkg *npkg, *rpkg;
	unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
				PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
				PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
				PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;

-
	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
-
		HASH_FIND_STR(universe->provides, shlib->name, pr);
-
		if (pr != NULL)
-
			continue;
+
	rpkg = NULL;
+
	prhead = NULL;
+
	while (pkgdb_it_next(it, &rpkg, flags) == EPKG_OK) {
+
		/* Check for local packages */
+
		HASH_FIND_STR(universe->items, rpkg->uid, unit);
+
		if (unit != NULL) {
+
			if (pkg_jobs_need_upgrade (rpkg, unit->pkg)) {
+
				/* Remote provide is newer, so we can add it */
+
				if (pkg_jobs_universe_process_item(universe, rpkg,
+
						&unit) != EPKG_OK)
+
					continue;

-
		/* Not found, search in the repos */
-
		it = pkgdb_repo_shlib_provide(universe->j->db,
-
			shlib->name, universe->j->reponame);
-
		if (it != NULL) {
-
			rpkg = NULL;
-
			prhead = NULL;
-
			while (pkgdb_it_next(it, &rpkg, flags) == EPKG_OK) {
-
				/* Check for local packages */
-
				HASH_FIND_STR(universe->items, rpkg->uid, unit);
-
				if (unit != NULL) {
-
					if (pkg_jobs_need_upgrade (rpkg, unit->pkg)) {
-
						/* Remote provide is newer, so we can add it */
-
						if (pkg_jobs_universe_process_item(universe, rpkg,
+
				rpkg = NULL;
+
			}
+
		}
+
		else {
+
			/* Maybe local package has just been not added */
+
			npkg = pkg_jobs_universe_get_local(universe, rpkg->uid, 0);
+
			if (npkg != NULL) {
+
				if (pkg_jobs_universe_process_item(universe, npkg,
+
						&unit) != EPKG_OK) {
+
					return (EPKG_FATAL);
+
				}
+
				if (pkg_jobs_need_upgrade (rpkg, npkg)) {
+
					/* Remote provide is newer, so we can add it */
+
					if (pkg_jobs_universe_process_item(universe, rpkg,
							&unit) != EPKG_OK)
-
							continue;
-

-
						rpkg = NULL;
-
					}
+
						continue;
				}
-
				else {
-
					/* Maybe local package has just been not added */
-
					npkg = pkg_jobs_universe_get_local(universe, rpkg->uid, 0);
-
					if (npkg != NULL) {
-
						if (pkg_jobs_universe_process_item(universe, npkg,
-
							&unit) != EPKG_OK) {
-
							return (EPKG_FATAL);
-
						}
-
						if (pkg_jobs_need_upgrade (rpkg, npkg)) {
-
							/* Remote provide is newer, so we can add it */
-
							if (pkg_jobs_universe_process_item(universe, rpkg,
-
								&unit) != EPKG_OK)
-
								continue;
-
						}
-
					}
+
			}
+
		}
+

+
		/* Skip seen packages */
+
		if (unit == NULL) {
+
			struct pkg_job_seen *seen;
+

+
			if (rpkg->digest == NULL) {
+
				pkg_debug(3, "no digest found for package %s", rpkg->uid);
+
				if (pkg_checksum_calculate(rpkg, universe->j->db) != EPKG_OK) {
+
					return (EPKG_FATAL);
				}
+
			}
+
			HASH_FIND_STR(universe->seen, rpkg->digest, seen);
+
			if (seen == NULL) {
+
				pkg_jobs_universe_process_item(universe, rpkg,
+
						&unit);

-
				/* Skip seen packages */
-
				if (unit == NULL) {
-
					struct pkg_job_seen *seen;
+
				/* Reset package to avoid freeing */
+
				rpkg = NULL;
+
			}
+
			else {
+
				unit = seen->un;
+
			}
+
		}

-
					if (rpkg->digest == NULL) {
-
						pkg_debug(3, "no digest found for package %s", rpkg->uid);
-
						if (pkg_checksum_calculate(pkg, universe->j->db) != EPKG_OK) {
-
							return (EPKG_FATAL);
-
						}
-
					}
-
					HASH_FIND_STR(universe->seen, rpkg->digest, seen);
-
					if (seen == NULL) {
-
						pkg_jobs_universe_process_item(universe, rpkg,
-
							&unit);
+
		pr = calloc (1, sizeof (*pr));
+
		if (pr == NULL) {
+
			pkg_emit_errno("pkg_jobs_add_universe", "calloc: "
+
					"struct pkg_job_provide");
+
			return (EPKG_FATAL);
+
		}

-
						/* Reset package to avoid freeing */
-
						rpkg = NULL;
-
					}
-
					else {
-
						unit = seen->un;
-
					}
-
				}
+
		pr->un = unit;
+
		pr->provide = name;
+
		pr->is_shlib = is_shlib;

-
				pr = calloc (1, sizeof (*pr));
-
				if (pr == NULL) {
-
					pkg_emit_errno("pkg_jobs_add_universe", "calloc: "
-
						"struct pkg_job_provide");
-
					return (EPKG_FATAL);
-
				}
+
		if (prhead == NULL) {
+
			DL_APPEND(prhead, pr);
+
			HASH_ADD_KEYPTR(hh, universe->provides, pr->provide,
+
					strlen(pr->provide), prhead);
+
		}
+
		else {
+
			DL_APPEND(prhead, pr);
+
		}
+
	}

-
				pr->un = unit;
-
				pr->provide = shlib->name;
+
	return (EPKG_OK);
+
}

-
				if (prhead == NULL) {
-
					DL_APPEND(prhead, pr);
-
					HASH_ADD_KEYPTR(hh, universe->provides, pr->provide,
-
						strlen(pr->provide), prhead);
-
				}
-
				else {
-
					DL_APPEND(prhead, pr);
-
				}
+
static int
+
pkg_jobs_universe_process_shlibs(struct pkg_jobs_universe *universe,
+
	struct pkg *pkg)
+
{
+
	struct pkg_shlib *shlib = NULL;
+
	struct pkg_job_provide *pr;
+
	struct pkgdb_it *it;
+
	int rc;
+

+
	while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
+
		HASH_FIND_STR(universe->provides, shlib->name, pr);
+
		if (pr != NULL)
+
			continue;
+

+
		/* Check for local provides */
+
		it = pkgdb_query_shlib_provide(universe->j->db, shlib->name);
+
		if (it != NULL) {
+
			rc = pkg_jobs_universe_handle_provide(universe, it, shlib->name, true);
+
			pkgdb_it_free(it);
+

+
			if (rc != EPKG_OK) {
+
				pkg_debug(1, "cannot find local packages that provide library %s "
+
						"required for %s",
+
						shlib->name, pkg->name);
			}
+
		}
+
		/* Not found, search in the repos */
+
		it = pkgdb_repo_shlib_provide(universe->j->db,
+
			shlib->name, universe->j->reponame);
+

+
		if (it != NULL) {
+
			rc = pkg_jobs_universe_handle_provide(universe, it, shlib->name, true);
			pkgdb_it_free(it);
-
			if (prhead == NULL) {
-
				pkg_debug(1, "cannot find packages that provide %s required for %s",
+

+
			if (rc != EPKG_OK) {
+
				pkg_debug(1, "cannot find remote packages that provide library %s "
+
						"required for %s",
				    shlib->name, pkg->name);
-
				/*
-
				 * XXX: this is not normal but it is very common for the existing
-
				 * repos, hence we just ignore this stale dependency
-
				 */
			}
		}
	}
@@ -456,106 +480,41 @@ pkg_jobs_universe_process_provides_requires(struct pkg_jobs_universe *universe,
	struct pkg *pkg)
{
	struct pkg_provide *p = NULL;
-
	struct pkg_job_universe_item *unit;
-
	struct pkg_job_provide *pr, *prhead;
+
	struct pkg_job_provide *pr;
	struct pkgdb_it *it;
-
	struct pkg *npkg, *rpkg;
-
	unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
-
				PKG_LOAD_REQUIRES|PKG_LOAD_PROVIDES|
-
				PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_SHLIBS_PROVIDED|
-
				PKG_LOAD_PROVIDES|
-
				PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
+
	int rc;

	while (pkg_requires(pkg, &p) == EPKG_OK) {
		HASH_FIND_STR(universe->provides, p->provide, pr);
		if (pr != NULL)
			continue;

-
		/* Not found, search in the repos */
-
		it = pkgdb_repo_provide(universe->j->db,
-
			p->provide, universe->j->reponame);
+
		/* Check for local provides */
+
		it = pkgdb_query_provide(universe->j->db, p->provide);
		if (it != NULL) {
-
			rpkg = NULL;
-
			prhead = NULL;
-
			while (pkgdb_it_next(it, &rpkg, flags) == EPKG_OK) {
-
				/* Check for local packages */
-
				HASH_FIND_STR(universe->items, rpkg->uid, unit);
-
				if (unit != NULL) {
-
					if (pkg_jobs_need_upgrade (rpkg, unit->pkg)) {
-
						/* Remote provide is newer, so we can add it */
-
						if (pkg_jobs_universe_process_item(universe, rpkg,
-
							&unit) != EPKG_OK)
-
							continue;
-

-
						rpkg = NULL;
-
					}
-
				}
-
				else {
-
					/* Maybe local package has just been not added */
-
					npkg = pkg_jobs_universe_get_local(universe, rpkg->uid, 0);
-
					if (npkg != NULL) {
-
						if (pkg_jobs_universe_process_item(universe, npkg,
-
							&unit) != EPKG_OK)
-
							return (EPKG_FATAL);
-
						if (pkg_jobs_need_upgrade (rpkg, npkg)) {
-
							/* Remote provide is newer, so we can add it */
-
							if (pkg_jobs_universe_process_item(universe, rpkg,
-
								&unit) != EPKG_OK)
-
								continue;
-
						}
-
					}
-
				}
-

-
				/* Skip seen packages */
-
				if (unit == NULL) {
-
					struct pkg_job_seen *seen;
-

-
					if (rpkg->digest == NULL) {
-
						pkg_debug(3, "no digest found for package %s", rpkg->uid);
-
						if (pkg_checksum_calculate(pkg, universe->j->db) != EPKG_OK) {
-
							return (EPKG_FATAL);
-
						}
-
					}
-
					HASH_FIND_STR(universe->seen, rpkg->digest, seen);
-
					if (seen == NULL) {
-
						pkg_jobs_universe_process_item(universe, rpkg,
-
							&unit);
-

-
						/* Reset package to avoid freeing */
-
						rpkg = NULL;
-
					}
-
					else {
-
						unit = seen->un;
-
					}
-
				}
+
			rc = pkg_jobs_universe_handle_provide(universe, it, p->provide, false);
+
			pkgdb_it_free(it);

-
				pr = calloc (1, sizeof (*pr));
-
				if (pr == NULL) {
-
					pkg_emit_errno("pkg_jobs_add_universe", "calloc: "
-
						"struct pkg_job_provide");
-
					return (EPKG_FATAL);
-
				}
+
			if (rc != EPKG_OK) {
+
				pkg_debug(1, "cannot find local packages that provide %s "
+
						"required for %s",
+
						p->provide, pkg->name);
+
			}
+
		}

-
				pr->un = unit;
-
				pr->provide = p->provide;
+
		/* Not found, search in the repos */
+
		it = pkgdb_repo_provide(universe->j->db,
+
			p->provide, universe->j->reponame);

-
				if (prhead == NULL) {
-
					DL_APPEND(prhead, pr);
-
					HASH_ADD_KEYPTR(hh, universe->provides, pr->provide,
-
						strlen(pr->provide), prhead);
-
				}
-
				else {
-
					DL_APPEND(prhead, pr);
-
				}
-
			}
+
		if (it != NULL) {
+
			rc = pkg_jobs_universe_handle_provide(universe, it, p->provide, false);
			pkgdb_it_free(it);
-
			if (prhead == NULL) {
-
				pkg_debug(1, "cannot find packages that provide %s required for %s",
+

+
			if (rc != EPKG_OK) {
+
				pkg_debug(1, "cannot find remote packages that provide %s "
+
						"required for %s",
				    p->provide, pkg->name);
-
				/*
-
				 * XXX: this is not normal but it is very common for the existing
-
				 * repos, hence we just ignore this stale dependency
-
				 */
+
				return (rc);
			}
		}
	}
@@ -619,15 +578,13 @@ pkg_jobs_universe_process_item(struct pkg_jobs_universe *universe, struct pkg *p
		rc = pkg_jobs_universe_process_conflicts(universe, pkg);
		if (rc != EPKG_OK)
			return (rc);
-
		/* For remote packages we should also handle shlib deps */
-
		if (pkg->type != PKG_INSTALLED) {
-
			rc = pkg_jobs_universe_process_shlibs(universe, pkg);
-
			if (rc != EPKG_OK)
-
				return (rc);
-
			rc = pkg_jobs_universe_process_provides_requires(universe, pkg);
-
			if (rc != EPKG_OK)
-
				return (rc);
-
		}
+
		/* Provides/requires */
+
		rc = pkg_jobs_universe_process_shlibs(universe, pkg);
+
		if (rc != EPKG_OK)
+
			return (rc);
+
		rc = pkg_jobs_universe_process_provides_requires(universe, pkg);
+
		if (rc != EPKG_OK)
+
			return (rc);
		break;
	case PKG_JOBS_AUTOREMOVE:
		/* XXX */
modified libpkg/pkg_solve.c
@@ -296,6 +296,9 @@ pkg_solve_handle_provide (struct pkg_solve_problem *problem,
	struct pkg_solve_item *it = NULL;
	struct pkg_solve_variable *var, *curvar;
	struct pkg_job_universe_item *un;
+
	struct pkg_shlib *shlp;
+
	struct pkg_provide *np;
+
	struct pkg *pkg;

	/* Find the first package in the universe list */
	un = pr->un;
@@ -307,7 +310,28 @@ pkg_solve_handle_provide (struct pkg_solve_problem *problem,
	HASH_FIND_STR(problem->variables_by_uid, un->pkg->uid, var);

	LL_FOREACH(var, curvar) {
-
		/* For each provide */
+
		/*
+
		 * For each provide we need to check whether this package
+
		 * actually provides this require
+
		 */
+
		shlp = NULL;
+
		np = NULL;
+
		pkg = curvar->unit->pkg;
+

+
		if (pr->is_shlib) {
+
			HASH_FIND_STR(pkg->shlibs_provided, pr->provide, shlp);
+
		}
+
		else {
+
			HASH_FIND_STR(pkg->provides, pr->provide, np);
+
		}
+

+
		if (np == NULL && shlp == NULL) {
+
			pkg_debug(4, "%s provide is not satisfied by %s-%s(%c)", pr->provide,
+
					pkg->name, pkg->version, pkg->type == PKG_INSTALLED ?
+
							'l' : 'r');
+
			continue;
+
		}
+

		it = pkg_solve_item_new(curvar);
		if (it == NULL)
			return (EPKG_FATAL);
@@ -685,19 +709,16 @@ pkg_solve_process_universe_variable(struct pkg_solve_problem *problem,

		/* Shlibs */
		shlib = NULL;
-
		if (pkg->type != PKG_INSTALLED) {
-
			while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
-
				if (pkg_solve_add_require_rule(problem, cur_var,
-
				    shlib->name) != EPKG_OK)
-
					continue;
-
			}
+
		while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) {
+
			if (pkg_solve_add_require_rule(problem, cur_var,
+
					shlib->name) != EPKG_OK)
+
				continue;
		}
-
		if (pkg->type != PKG_INSTALLED) {
-
			while (pkg_requires(pkg, &p) == EPKG_OK) {
-
				if (pkg_solve_add_require_rule(problem, cur_var,
-
				    p->provide) != EPKG_OK)
-
					continue;
-
			}
+
		p = NULL;
+
		while (pkg_requires(pkg, &p) == EPKG_OK) {
+
			if (pkg_solve_add_require_rule(problem, cur_var,
+
					p->provide) != EPKG_OK)
+
				continue;
		}

		/* Request */
@@ -852,7 +873,14 @@ pkg_solve_sat_problem(struct pkg_solve_problem *problem)
			picosat_set_more_important_lit(problem->sat, i + 1);
		}
		else {
-
			picosat_set_default_phase_lit(problem->sat, i + 1, -1);
+
			if (!var->next && var->prev == var) {
+
				/* Prefer not to install if have no local version */
+
				picosat_set_default_phase_lit(problem->sat, i + 1, -1);
+
			}
+
			else {
+
				/* Prefer to upgrade if possible */
+
				picosat_set_default_phase_lit(problem->sat, i + 1, 1);
+
			}
			picosat_set_less_important_lit(problem->sat, i + 1);
		}
	}
modified libpkg/pkgdb.c
@@ -1892,6 +1892,8 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forced)
	 */
	if (pkgdb_update_provides(pkg, package_id, s) != EPKG_OK)
		goto cleanup;
+
	if (pkgdb_update_requires(pkg, package_id, s) != EPKG_OK)
+
		goto cleanup;

	retcode = EPKG_OK;

@@ -1977,6 +1979,25 @@ pkgdb_update_shlibs_provided(struct pkg *pkg, int64_t package_id, sqlite3 *s)
}

int
+
pkgdb_update_requires(struct pkg *pkg, int64_t package_id, sqlite3 *s)
+
{
+
	struct pkg_provide	*provide = NULL;
+

+
	while (pkg_requires(pkg, &provide) == EPKG_OK) {
+
		if (run_prstmt(REQUIRE, provide->provide)
+
		    != SQLITE_DONE
+
		    ||
+
		    run_prstmt(PKG_REQUIRE, package_id, provide->provide)
+
		    != SQLITE_DONE) {
+
			ERROR_SQLITE(s, SQL(PKG_REQUIRE));
+
			return (EPKG_FATAL);
+
		}
+
	}
+

+
	return (EPKG_OK);
+
}
+

+
int
pkgdb_update_provides(struct pkg *pkg, int64_t package_id, sqlite3 *s)
{
	struct pkg_provide	*provide = NULL;
modified libpkg/pkgdb_query.c
@@ -265,10 +265,10 @@ pkgdb_query_require(struct pkgdb *db, const char *req)
			"p.version, p.comment, p.desc, "
			"p.message, p.arch, p.maintainer, p.www, "
			"p.prefix, p.flatsize, p.time "
-
			"FROM packages AS p, pkg_requires AS ps, require AS s "
+
			"FROM packages AS p, pkg_requires AS ps, requires AS s "
			"WHERE p.id = ps.package_id "
				"AND ps.require_id = s.id "
-
				"AND s.name = ?1;";
+
				"AND s.require = ?1;";

	assert(db != NULL);

@@ -292,10 +292,10 @@ pkgdb_query_provide(struct pkgdb *db, const char *req)
			"p.version, p.comment, p.desc, "
			"p.message, p.arch, p.maintainer, p.www, "
			"p.prefix, p.flatsize, p.time "
-
			"FROM packages AS p, pkg_provides AS ps, provide AS s "
+
			"FROM packages AS p, pkg_provides AS ps, provides AS s "
			"WHERE p.id = ps.package_id "
				"AND ps.provide_id = s.id "
-
				"AND s.name = ?1;";
+
				"AND s.provide = ?1;";

	assert(db != NULL);

modified libpkg/private/pkg.h
@@ -604,6 +604,7 @@ int pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forc
int pkgdb_update_shlibs_required(struct pkg *pkg, int64_t package_id, sqlite3 *s);
int pkgdb_update_shlibs_provided(struct pkg *pkg, int64_t package_id, sqlite3 *s);
int pkgdb_update_provides(struct pkg *pkg, int64_t package_id, sqlite3 *s);
+
int pkgdb_update_requires(struct pkg *pkg, int64_t package_id, sqlite3 *s);
int pkgdb_insert_annotations(struct pkg *pkg, int64_t package_id, sqlite3 *s);
int pkgdb_register_finale(struct pkgdb *db, int retcode);
int pkgdb_set_pkg_digest(struct pkgdb *db, struct pkg *pkg);
modified libpkg/private/pkg_jobs.h
@@ -78,6 +78,7 @@ struct pkg_job_seen {
struct pkg_job_provide {
	struct pkg_job_universe_item *un;
	const char *provide;
+
	bool is_shlib;
	struct pkg_job_provide *next, *prev;
	UT_hash_handle hh;
};