Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Refactor pkg install with a cleaner solver.
Baptiste Daroussin committed 13 years ago
commit b373238faa90fe0b353c2603815b3b62cb9ceb9d
parent e84f8ba
4 files changed +358 -313
modified libpkg/pkg_jobs.c
@@ -42,7 +42,10 @@
#include "private/pkg.h"
#include "private/pkgdb.h"

+
static int get_remote_pkg(struct pkg_jobs *j, const char *pattern, match_t m, bool root);
+
static struct pkg * get_local_pkg(struct pkg_jobs *j, const char *origin);
static int pkg_jobs_fetch(struct pkg_jobs *j);
+
static bool newer_than_local_pkg(struct pkg_jobs *j, struct pkg *rp, bool force);

int
pkg_jobs_new(struct pkg_jobs **j, pkg_jobs_t t, struct pkgdb *db)
@@ -97,6 +100,7 @@ int
pkg_jobs_add(struct pkg_jobs *j, match_t match, char **argv, int argc)
{
	struct job_pattern *jp;
+
	int i = 0;

	if (j->solved) {
		pkg_emit_error("The job has already been solved. "
@@ -104,11 +108,13 @@ pkg_jobs_add(struct pkg_jobs *j, match_t match, char **argv, int argc)
		return (EPKG_FATAL);
	}

-
	jp = malloc(sizeof(struct job_pattern));
-
	jp->pattern = argv;
-
	jp->nb = argc;
-
	jp->match = match;
-
	LL_APPEND(j->patterns, jp);
+
	for (i = 0; i < argc; i++) {
+
		jp = malloc(sizeof(struct job_pattern));
+
		jp->pattern = argv + i;
+
		jp->nb = 1;
+
		jp->match = match;
+
		LL_APPEND(j->patterns, jp);
+
	}

	return (EPKG_OK);
}
@@ -229,41 +235,366 @@ jobs_solve_upgrade(struct pkg_jobs *j)
	return (EPKG_OK);
}

+
static void
+
remove_from_deps(struct pkg_jobs *j, const char *origin)
+
{
+
	struct pkg *pkg, *tmp;
+
	struct pkg_dep *d;
+

+
	HASH_ITER(hh, j->bulk, pkg, tmp) {
+
		HASH_FIND_STR(pkg->deps, origin, d);
+
		if (d != NULL) {
+
			HASH_DEL(pkg->deps, d);
+
			pkg_dep_free(d);
+
		}
+
	}
+
}
+

static int
-
jobs_solve_install(struct pkg_jobs *j)
+
order_pool(struct pkg_jobs *j)
{
-
	struct job_pattern *jp = NULL;
-
	struct pkg *pkg = NULL;
+
	struct pkg *pkg, *tmp;
+
	char *origin;
+
	unsigned int nb;
+

+
	nb = HASH_COUNT(j->bulk);
+
	HASH_ITER(hh, j->bulk, pkg, tmp) {
+
		pkg_get(pkg, PKG_ORIGIN, &origin);
+
		if (HASH_COUNT(pkg->deps) == 0) {
+
			HASH_DEL(j->bulk, pkg);
+
			HASH_ADD_KEYPTR(hh, j->jobs, origin, strlen(origin), pkg);
+
			remove_from_deps(j, origin);
+
		}
+
	}
+

+
	if (nb == HASH_COUNT(j->bulk)) {
+
		pkg_emit_error("Error while ordering the jobs, probably a circular dependency");
+
		return (EPKG_FATAL);
+
	}
+

+
	return (EPKG_OK);
+
}
+

+
static int
+
populate_rdeps(struct pkg_jobs *j, struct pkg *p)
+
{
+
	struct pkg *pkg;
+
	struct pkg_dep *d = NULL;
+

+
	while (pkg_rdeps(p, &d) == EPKG_OK) {
+
		HASH_FIND_STR(j->bulk, pkg_dep_get(d, PKG_DEP_ORIGIN), pkg);
+
		if (pkg != NULL)
+
			continue;
+
		HASH_FIND_STR(j->seen, pkg_dep_get(d, PKG_DEP_ORIGIN), pkg);
+
		if (pkg != NULL)
+
			continue;
+
		if (get_remote_pkg(j, pkg_dep_get(d, PKG_DEP_ORIGIN), MATCH_EXACT, true) != EPKG_OK) {
+
			pkg_emit_error("Missing dependency matching '%s'", pkg_dep_get(d, PKG_DEP_ORIGIN));
+
			return (EPKG_FATAL);
+
		}
+
	}
+

+
	return (EPKG_OK);
+
}
+

+
static int
+
populate_deps(struct pkg_jobs *j, struct pkg *p)
+
{
+
	struct pkg *pkg;
+
	struct pkg_dep *d = NULL;
+

+
	while (pkg_deps(p, &d) == EPKG_OK) {
+
		HASH_FIND_STR(j->bulk, pkg_dep_get(d, PKG_DEP_ORIGIN), pkg);
+
		if (pkg != NULL)
+
			continue;
+
		HASH_FIND_STR(j->seen, pkg_dep_get(d, PKG_DEP_ORIGIN), pkg);
+
		if (pkg != NULL)
+
			continue;
+
		if (get_remote_pkg(j, pkg_dep_get(d, PKG_DEP_ORIGIN), MATCH_EXACT, false) != EPKG_OK) {
+
			pkg_emit_error("Missing dependency matching '%s'", pkg_dep_get(d, PKG_DEP_ORIGIN));
+
			return (EPKG_FATAL);
+
		}
+
	}
+

+
	return (EPKG_OK);
+
}
+

+
static bool
+
new_pkg_version(struct pkg_jobs *j)
+
{
+
	struct pkg *p;
+
	const char *origin = "ports-mgmt/pkg";
+

+
	/* determine local pkgng */
+
	p = get_local_pkg(j, origin);
+

+
	if (p == NULL) {
+
		origin = "ports-mgmt/pkg-devel";
+
		p = get_local_pkg(j, origin);
+
	}
+

+
	/* you are using git version skip */
+
	if (p == NULL)
+
		return (false);
+

+
	if (get_remote_pkg(j, origin, MATCH_EXACT, true) == EPKG_OK)
+
		return (true);
+

+
	return (false);
+
}
+

+
static int
+
get_remote_pkg(struct pkg_jobs *j, const char *pattern, match_t m, bool root)
+
{
+
	struct pkg *p = NULL;
+
	struct pkg *p1;
	struct pkgdb_it *it;
	char *origin;
+
	const char *buf1, *buf2;
	bool force = false;
-
	bool recursive = false;
-
	bool pkgversiontest = false;
+
	int rc = EPKG_FATAL;
+
	unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_DEPS|PKG_LOAD_OPTIONS|PKG_LOAD_SHLIBS_REQUIRED;

-
	if ((j->flags & PKG_FLAG_FORCE) != 0)
+
	if (root && (j->flags & PKG_FLAG_FORCE) == PKG_FLAG_FORCE)
		force = true;

-
	if ((j->flags & PKG_FLAG_RECURSIVE) != 0)
-
		recursive = true;
+
	if (root && (j->flags & PKG_FLAG_RECURSIVE) == PKG_FLAG_RECURSIVE)
+
		flags |= PKG_LOAD_RDEPS;
+

+
	if ((it = pkgdb_rquery(j->db, pattern, m, j->reponame)) == NULL)
+
		return (rc);
+

+
	while (pkgdb_it_next(it, &p, flags) == EPKG_OK) {
+
		pkg_get(p, PKG_ORIGIN, &origin);
+
		HASH_FIND_STR(j->bulk, origin, p1);
+
		if (p1 != NULL) {
+
			pkg_get(p1, PKG_VERSION, &buf1);
+
			pkg_get(p, PKG_VERSION, &buf2);
+
			p->direct = root;
+
			if (pkg_version_cmp(buf1, buf2) != 1)
+
				continue;
+
			HASH_DEL(j->bulk, p1);
+
			pkg_free(p1);
+
		}

-
	if ((j->flags & PKG_FLAG_PKG_VERSION_TEST) != 0)
-
		pkgversiontest = true;
+
		if (!newer_than_local_pkg(j, p, force)) {
+
			if (root)
+
				pkg_emit_already_installed(p);
+
			rc = EPKG_OK;
+
			HASH_ADD_KEYPTR(hh, j->seen, origin, strlen(origin), p);
+
			continue;
+
		}
+

+
		rc = EPKG_OK;
+
		p->direct = root;
+
		HASH_ADD_KEYPTR(hh, j->bulk, origin, strlen(origin), p);
+
		if (populate_deps(j, p) == EPKG_FATAL) {
+
			rc = EPKG_FATAL;
+
			break;
+
		}
+

+
		if (populate_rdeps(j, p) == EPKG_FATAL) {
+
			rc = EPKG_FATAL;
+
			break;
+
		}
+
		p = NULL;
+
	}
+

+
	pkgdb_it_free(it);
+

+
	return (rc);
+
}
+

+
static struct pkg *
+
get_local_pkg(struct pkg_jobs *j, const char *origin)
+
{
+
	struct pkg *pkg = NULL;
+
	struct pkgdb_it *it;
+

+
	if ((it = pkgdb_query(j->db, origin, MATCH_EXACT)) == NULL)
+
		return (NULL);
+

+
	if (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS|PKG_LOAD_OPTIONS|PKG_LOAD_SHLIBS_REQUIRED) != EPKG_OK)
+
		pkg = NULL;
+

+
	pkgdb_it_free(it);
+

+
	return (pkg);
+
}
+

+
static bool
+
newer_than_local_pkg(struct pkg_jobs *j, struct pkg *rp, bool force)
+
{
+
	char *origin, *newversion, *oldversion, *oldsize, *newsize;
+
	struct pkg *lp;
+
	struct sbuf *sb1, *sb2;
+
	struct pkg_option *o = NULL;
+
	struct pkg_dep *d = NULL;
+
	struct pkg_shlib *s = NULL;
+
	bool automatic, locked;
+
	int cmp = 0;
+

+
	pkg_get(rp, PKG_ORIGIN, &origin);
+
	lp = get_local_pkg(j, origin);
+

+
	/* obviously yes because local doesn't exists */
+
	if (lp == NULL) {
+
		pkg_set(rp, PKG_AUTOMATIC, (int64_t)true);
+
		return (true);
+
	}
+

+
	pkg_get(lp, PKG_LOCKED, &locked,
+
	    PKG_AUTOMATIC, &automatic,
+
	    PKG_VERSION, &oldversion,
+
	    PKG_FLATSIZE, &oldsize);
+

+
	if (locked) {
+
		pkg_free(lp);
+
		return (false);
+
	}
+

+
	pkg_get(rp, PKG_VERSION, &newversion, PKG_FLATSIZE, &newsize);
+
	pkg_set(rp, PKG_VERSION, oldversion, PKG_NEWVERSION, newversion,
+
	    PKG_NEW_FLATSIZE, newsize, PKG_FLATSIZE, oldsize,
+
	    PKG_AUTOMATIC, (int64_t)automatic);
+

+
	if (force) {
+
		pkg_free(lp);
+
		return (true);
+
	}
+

+
	/* compare versions */
+
	cmp = pkg_version_cmp(newversion, oldversion);
+

+
	if (cmp == 1) {
+
		pkg_free(lp);
+
		return (true);
+
	}
+

+
	if (cmp == 0) {
+
		pkg_free(lp);
+
		return (false);
+
	}
+

+
	/* compare options */
+
	sb1 = sbuf_new_auto();
+
	sb2 = sbuf_new_auto();
+

+
	while (pkg_options(rp, &o) == EPKG_OK)
+
		sbuf_printf(sb1, "%s=%s ", pkg_option_opt(o), pkg_option_value(o));
+

+
	o = NULL;
+
	while (pkg_options(lp, &o) == EPKG_OK)
+
		sbuf_printf(sb2, "%s=%s ", pkg_option_opt(o), pkg_option_value(o));
+

+
	sbuf_finish(sb1);
+
	sbuf_finish(sb2);
+

+
	if (strcmp(sbuf_data(sb1), sbuf_data(sb2)) != 0) {
+
		sbuf_delete(sb1);
+
		sbuf_delete(sb2);
+
		pkg_free(lp);
+
		return (true);
+
	}
+

+
	/* What about the direct deps */
+
	sbuf_reset(sb1);
+
	sbuf_reset(sb2);
+

+
	while (pkg_deps(rp, &d) == EPKG_OK)
+
		sbuf_cat(sb1, pkg_dep_get(d, PKG_DEP_NAME));
+

+
	d = NULL;
+
	while (pkg_deps(lp, &d) == EPKG_OK)
+
		sbuf_cat(sb2, pkg_dep_get(d, PKG_DEP_NAME));
+

+
	sbuf_finish(sb1);
+
	sbuf_finish(sb2);
+

+
	if (strcmp(sbuf_data(sb1), sbuf_data(sb2)) != 0) {
+
		sbuf_delete(sb1);
+
		sbuf_delete(sb2);
+
		pkg_free(lp);
+

+
		return (true);
+
	}
+

+
	/* Finish by the shlibs */
+
	sbuf_reset(sb1);
+
	sbuf_reset(sb2);
+

+
	while (pkg_shlibs_required(rp, &s) == EPKG_OK)
+
		sbuf_cat(sb1, pkg_shlib_name(s));
+

+
	d = NULL;
+
	while (pkg_shlibs_required(lp, &s) == EPKG_OK)
+
		sbuf_cat(sb2, pkg_shlib_name(s));
+

+
	sbuf_finish(sb1);
+
	sbuf_finish(sb2);
+

+
	if (strcmp(sbuf_data(sb1), sbuf_data(sb2)) != 0) {
+
		sbuf_delete(sb1);
+
		sbuf_delete(sb2);
+
		pkg_free(lp);
+

+
		return (true);
+
	}
+

+
	sbuf_delete(sb1);
+
	sbuf_delete(sb2);
+

+
	return (false);
+
}
+

+
static int
+
jobs_solve_install(struct pkg_jobs *j)
+
{
+
	struct job_pattern *jp = NULL;
+
	struct pkg *pkg, *tmp, *p;
+
	struct pkg_dep *d;
+

+
	if ((j->flags & PKG_FLAG_PKG_VERSION_TEST) != PKG_FLAG_PKG_VERSION_TEST)
+
		if (new_pkg_version(j)) {
+
			pkg_emit_newpkgversion();
+
			goto order;
+
		}

	LL_FOREACH(j->patterns, jp) {
-
		if ((it = pkgdb_query_installs(j->db, jp->match, jp->nb,
-
		        jp->pattern, j->reponame, force, recursive,
-
			pkgversiontest)) == NULL)
-
			return (EPKG_FATAL);
+
		if (get_remote_pkg(j, jp->pattern[0], jp->match, true) == EPKG_FATAL)
+
			pkg_emit_error("No packages matching '%s' has been found in the repositories", jp->pattern[0]);
+
	}

-
		while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) {
-
			pkg_get(pkg, PKG_ORIGIN, &origin);
+
	if (HASH_COUNT(j->bulk) == 0)
+
		return (EPKG_OK);
+

+
	/* remove everything seen from deps */
+
	HASH_ITER(hh, j->bulk, pkg, tmp) {
+
		d = NULL;
+
		while (pkg_deps(pkg, &d) == EPKG_OK) {
+
			HASH_FIND_STR(j->seen, pkg_dep_get(d, PKG_DEP_ORIGIN), p);
+
			if (p != NULL) {
+
				HASH_DEL(pkg->deps, d);
+
				pkg_dep_free(d);
+
			}
+
		}
+
		if (pkg->direct) {
			if ((j->flags & PKG_FLAG_AUTOMATIC) == PKG_FLAG_AUTOMATIC)
				pkg_set(pkg, PKG_AUTOMATIC, (int64_t)true);
-
			HASH_ADD_KEYPTR(hh, j->jobs, origin, strlen(origin), pkg);
-
			pkg = NULL;
+
			else
+
				pkg_set(pkg, PKG_AUTOMATIC, (int64_t)false);
		}
-
		pkgdb_it_free(it);
	}
+

+
order:
+
	HASH_FREE(j->seen, pkg, pkg_free);
+

+
	/* now order the pool */
+
	while (HASH_COUNT(j->bulk) > 0) {
+
		if (order_pool(j) != EPKG_OK)
+
			return (EPKG_FATAL);
+
	}
+

	j->solved = true;

	return (EPKG_OK);
modified libpkg/pkgdb.c
@@ -89,7 +89,6 @@ static void populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg);
static int create_temporary_pkgjobs(sqlite3 *);
static void pkgdb_detach_remotes(sqlite3 *);
static bool is_attached(sqlite3 *, const char *);
-
static void report_already_installed(sqlite3 *);
static int sqlcmd_init(sqlite3 *db, __unused const char **err,
    __unused const void *noused);
static int prstmt_initialize(struct pkgdb *db);
@@ -3105,51 +3104,6 @@ is_attached(sqlite3 *s, const char *name)
	return (false);
}

-
static void
-
report_already_installed(sqlite3 *s)
-
{
-
	sqlite3_stmt	*stmt = NULL;
-
	const char	*origin = NULL;
-
	const char	*sql = ""
-
		"SELECT origin FROM pkgjobs "
-
		"WHERE "
-
		    "(SELECT p.origin FROM main.packages AS p "
-
		    "WHERE p.origin = pkgjobs.origin "
-
		    "AND p.version = pkgjobs.version "
-
		    "AND (SELECT GROUP_CONCAT(option) "
-
			"FROM (SELECT option FROM main.options "
-
			"WHERE package_id = p.id "
-
			"AND value = 'on' "
-
			"ORDER BY option))"
-
		    "IS pkgjobs.opts "
-
		    "AND (SELECT GROUP_CONCAT(origin) "
-
			"FROM (SELECT origin from main.deps "
-
			"wHERE package_id = p.id "
-
			"ORDER BY origin))"
-
		    "IS pkgjobs.deps "
-
		    "AND (SELECT GROUP_CONCAT(shlib) "
-
			"FROM (SELECT name as shlib from main.pkg_shlibs_required, main.shlibs as s "
-
			"WHERE package_id = p.id AND shlib_id = s.id "
-
			"ORDER BY name)) "
-
		    "IS pkgjobs.shlibs) "
-
		"IS NOT NULL;";
-

-
	assert(s != NULL);
-

-
	if (sqlite3_prepare_v2(s, sql, -1, &stmt, NULL) != SQLITE_OK) {
-
		ERROR_SQLITE(s);
-
		return;
-
	}
-

-
	while (sqlite3_step(stmt) != SQLITE_DONE) {
-
		origin = sqlite3_column_text(stmt, 0);
-
		pkg_emit_error("%s is already installed and at "
-
		    "the latest version", origin);
-
	}
-

-
	sqlite3_finalize(stmt);
-
}
-

static int
sql_on_all_attached_db(sqlite3 *s, struct sbuf *sql, const char *multireposql,
    const char *compound)
@@ -3416,248 +3370,6 @@ cleanup:
}

struct pkgdb_it *
-
pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs,
-
        const char *repo, bool force, bool recursive, bool pkgversiontest)
-
{
-
	sqlite3_stmt	*stmt = NULL;
-
	struct pkgdb_it	*it;
-
	int		 i = 0, ret;
-
	struct sbuf	*sql = NULL;
-
	const char	*how = NULL;
-
	const char	*reponame = NULL;
-
	bool             pkg_not_found = false;
-

-
	if (pkgversiontest && 
-
	    (it = pkgdb_query_newpkgversion(db, repo)) != NULL) {
-
		pkg_emit_newpkgversion();
-
		return (it);
-
	}
-

-
	const char	 finalsql[] = ""
-
		"SELECT pkgid AS id, origin, name, version, "
-
		"comment, desc, message, arch, maintainer, "
-
		"www, prefix, flatsize, newversion, newflatsize, pkgsize, "
-
		"cksum, repopath, automatic, weight, "
-
		"'%s' AS dbname FROM pkgjobs ORDER BY weight DESC;";
-

-
	const char	 main_sql[] =
-
		"INSERT OR IGNORE INTO pkgjobs ("
-
		"  pkgid, origin, name, version, comment, desc, arch, "
-
		"  maintainer, www, prefix, flatsize, pkgsize, "
-
		"  cksum, repopath, automatic, opts, deps, shlibs"
-
		") "
-
		"SELECT id, origin, name, version, comment, desc, "
-
		"  arch, maintainer, www, prefix, flatsize, pkgsize, "
-
		"  cksum, path, 0, "
-
		"  (SELECT GROUP_CONCAT(option) FROM "
-
		"    (SELECT option FROM '%s'.options "
-
		"		    WHERE package_id=id"
-
		"		    AND value='on' ORDER BY option"
-
		"    )"
-
		"  ), "
-
		"  (SELECT GROUP_CONCAT(origin) FROM "
-
		"    (SELECT origin FROM '%s'.deps "
-
		"		    WHERE package_id=id"
-
		"		    ORDER BY origin"
-
		"    )"
-
		"  ), "
-
		"  (SELECT GROUP_CONCAT(shlib) FROM "
-
		"    (SELECT name as shlib FROM '%s'.pkg_shlibs_required, '%s'.shlibs as s "
-
		"		WHERE package_id = id AND shlib_id = s.id "
-
		"		ORDER BY name"
-
		"    )"
-
		"  ) "
-
		"FROM '%s'.packages WHERE ";
-

-
	const char	deps_sql[] = ""
-
		"INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, "
-
		    "version, comment, desc, arch, maintainer, www, "
-
		    "prefix, flatsize, pkgsize, cksum, repopath, "
-
		    "automatic) "
-
		"SELECT DISTINCT r.id, r.origin, r.name, r.version, "
-
		    "r.comment, r.desc, r.arch, r.maintainer, r.www, "
-
		    "r.prefix, r.flatsize, r.pkgsize, r.cksum, "
-
		    "r.path, 1 "
-
		"FROM '%s'.packages AS r WHERE r.origin IN "
-
		    "(SELECT d.origin FROM '%s'.deps AS d, pkgjobs AS j "
-
		    "WHERE d.package_id = j.pkgid) "
-
		    "AND (SELECT origin FROM main.packages "
-
		    "WHERE origin = r.origin AND version = r.version) "
-
		    "IS NULL";
-

-
	const char	upwards_deps_sql[] = ""
-
		"INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, "
-
		    "version, comment, desc, arch, maintainer, www, "
-
		    "prefix, flatsize, pkgsize, cksum, repopath, automatic) "
-
		"SELECT DISTINCT r.id, r.origin, r.name, r.version, "
-
		    "r.comment, r.desc, r.arch, r.maintainer, r.www, "
-
		    "r.prefix, r.flatsize, r.pkgsize, r.cksum, r.path, "
-
		    "p.automatic "
-
		"FROM '%s'.packages AS r "
-
		"INNER JOIN main.packages p ON (p.origin = r.origin) "
-
		"WHERE r.id IN (SELECT d.package_id FROM '%s'.deps AS d, "
-
		    "pkgjobs AS j WHERE d.origin = j.origin)";
-

-
	const char	weight_sql[] = ""
-
		"UPDATE pkgjobs SET weight=("
-
		"SELECT COUNT(*) FROM '%s'.deps AS d, '%s'.packages AS p, "
-
			"pkgjobs AS j "
-
		"WHERE d.origin = pkgjobs.origin "
-
			"AND d.package_id = p.id "
-
			"AND p.origin = j.origin "
-
		");";
-

-
	assert(db != NULL);
-
	assert(db->type == PKGDB_REMOTE);
-

-
	if ((reponame = pkgdb_get_reponame(db, repo)) == NULL)
-
		return (NULL);
-

-
	sql = sbuf_new_auto();
-
	sbuf_printf(sql, main_sql, reponame, reponame, reponame, reponame, reponame);
-

-
	how = pkgdb_get_match_how(match);
-

-
	create_temporary_pkgjobs(db->sqlite);
-

-
	sbuf_printf(sql, how, "name");
-
	sbuf_cat(sql, " OR ");
-
	sbuf_printf(sql, how, "origin");
-
	sbuf_cat(sql, " OR ");
-
	sbuf_printf(sql, how, "name || \"-\" || version");
-
	sbuf_finish(sql);
-

-
	for (i = 0; i < nbpkgs; i++) {
-
		ret = sqlite3_prepare_v2(db->sqlite, sbuf_get(sql), -1,
-
		    &stmt, NULL);
-
		if (ret != SQLITE_OK) {
-
			ERROR_SQLITE(db->sqlite);
-
			sbuf_delete(sql);
-
			return (NULL);
-
		}
-
		sqlite3_bind_text(stmt, 1, pkgs[i], -1, SQLITE_STATIC);
-
		while (sqlite3_step(stmt) != SQLITE_DONE);
-

-
		/* report if package was not found in the database */
-
		if (sqlite3_changes(db->sqlite) == 0) {
-
			pkg_emit_package_not_found(pkgs[i]);
-
			pkg_not_found = true;
-
		}
-
	}
-

-
	sqlite3_finalize(stmt);
-
	sbuf_clear(sql);
-

-
	if (pkg_not_found) {
-
		sbuf_delete(sql);
-
		return (NULL);
-
	}
-

-
	/*
-
	 * Report and remove packages already installed and at the latest
-
	 * version and without option change
-
	 */
-
	report_already_installed(db->sqlite);
-
	if (!force) {
-
		sql_exec(db->sqlite, "DELETE FROM pkgjobs WHERE "
-
		    "(SELECT p.origin FROM main.packages AS p WHERE "
-
		    "p.origin = pkgjobs.origin "
-
		    "AND PKGGT(p.version, pkgjobs.version))"
-
		    "IS NOT NULL;");
-
		sql_exec(db->sqlite, "DELETE FROM pkgjobs WHERE "
-
		    "(SELECT p.origin FROM main.packages AS p "
-
		    "WHERE p.origin = pkgjobs.origin "
-
			 "AND p.version=pkgjobs.version "
-
			 "AND p.name = pkgjobs.name "
-
			 "AND (SELECT GROUP_CONCAT(option) "
-
			 "FROM (SELECT option FROM main.options "
-
			 "WHERE package_id = p.id AND value = 'on' "
-
			 "ORDER BY option)) IS pkgjobs.opts "
-
			 "AND (SELECT GROUP_CONCAT(origin) "
-
			 "FROM (SELECT origin from main.deps "
-
			 "wHERE package_id = p.id "
-
			 "ORDER BY origin))"
-
			 "IS pkgjobs.deps  "
-
			 "AND (SELECT GROUP_CONCAT(shlib) "
-
			 "FROM (SELECT name as shlib from main.pkg_shlibs_required, main.shlibs as s "
-
			 "WHERE package_id = p.id AND shlib_id = s.id "
-
			 "ORDER BY name))"
-
			 "IS pkgjobs.shlibs "
-
		    ") IS NOT NULL;");
-
	}
-

-
	/* Include all reverse dependencies */
-
	if (recursive) {
-
		do {
-
			sql_exec(db->sqlite, upwards_deps_sql,
-
				 reponame, reponame);
-
		} while (sqlite3_changes(db->sqlite) != 0);
-
	}
-

-
	/* Append missing dependencies */
-
	sbuf_reset(sql);
-
	sbuf_printf(sql, deps_sql, reponame, reponame);
-
	sbuf_finish(sql);
-

-
	do {
-
		sql_exec(db->sqlite, sbuf_get(sql));
-
	} while (sqlite3_changes(db->sqlite) != 0);
-

-
	/* Determine if there is an upgrade needed */
-
	sql_exec(db->sqlite, ""
-
		 "INSERT OR REPLACE INTO pkgjobs (pkgid, origin, name, "
-
		     "version, comment, desc, message, arch, "
-
		     "maintainer, www, prefix, locked, flatsize, "
-
		     "newversion, newflatsize, pkgsize, cksum, repopath, "
-
		     "automatic) "
-
		 "SELECT l.id, l.origin, l.name, l.version, l.comment, "
-
		     "l.desc, l.message, l.arch, l.maintainer, l.www, "
-
		     "l.prefix, l.locked, l.flatsize, "
-
		     "r.version AS newversion, r.flatsize AS newflatsize, "
-
		     "r.pkgsize, r.cksum, r.repopath, l.automatic "
-
		 "FROM main.packages AS l, pkgjobs AS r "
-
		 "WHERE l.origin = r.origin ");
-

-
	sbuf_reset(sql);
-
	sbuf_printf(sql, weight_sql, reponame, reponame);
-
	sbuf_finish(sql);
-

-
	if (!force) {
-

-
		/* Remove all the downgrades in dependencies as well
-
		 * we asked for upgrade :) */
-
		sql_exec(db->sqlite, ""
-
		    "DELETE FROM pkgjobs "
-
		    "WHERE "
-
		       "(SELECT p.origin FROM main.packages AS p "
-
		       "WHERE p.origin = pkgjobs.origin "
-
		       "AND PKGGT(p.version,pkgjobs.version))"
-
		    "IS NOT NULL;");
-
	}
-

-
	sql_exec(db->sqlite, sbuf_get(sql));
-

-
	sql_exec(db->sqlite, "UPDATE pkgjobs SET weight=100000 "
-
		 "WHERE origin REGEXP '^ports-mgmt/pkg(-devel)?$'");
-

-
	sbuf_reset(sql);
-
	sbuf_printf(sql, finalsql, reponame);
-
	sbuf_finish(sql);
-

-
	if (sqlite3_prepare_v2(db->sqlite, sbuf_get(sql), -1, &stmt, NULL)
-
	    != SQLITE_OK) {
-
		ERROR_SQLITE(db->sqlite);
-
		sbuf_delete(sql);
-
		return (NULL);
-
	}
-

-
	sbuf_finish(sql);
-
	sbuf_delete(sql);
-

-
	return (pkgdb_it_new(db, stmt, PKG_REMOTE, PKGDB_IT_FLAG_ONCE));
-
}
-

-
struct pkgdb_it *
pkgdb_query_upgrades(struct pkgdb *db, const char *repo, bool all,
	bool pkgversiontest)
{
modified libpkg/private/pkg.h
@@ -104,6 +104,7 @@ extern int eventpipe;

struct pkg {
	struct sbuf	*fields[PKG_NUM_FIELDS];
+
	bool		 direct;
	bool		 automatic;
	bool		 locked;
	int64_t		 flatsize;
@@ -178,6 +179,8 @@ struct pkg_option {

struct pkg_jobs {
	struct pkg	*jobs;
+
	struct pkg 	*bulk;
+
	struct pkg	*seen;
	struct pkgdb	*db;
	pkg_jobs_t	 type;
	pkg_flags	 flags;
modified libpkg/private/pkgdb.h
@@ -67,7 +67,6 @@ struct pkgdb_it *pkgdb_it_new(struct pkgdb *db, sqlite3_stmt *s, int type, short

struct pkgdb_it *pkgdb_query_delete(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, int recursive);
struct pkgdb_it *pkgdb_query_upgrades(struct pkgdb *db, const char *reponame, bool all, bool pkgversiontest);
-
struct pkgdb_it *pkgdb_query_installs(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, const char *reponame, bool force, bool recursive, bool pkgversiontest);
struct pkgdb_it *pkgdb_query_fetch(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, const char *reponame, unsigned flags);

int pkgdb_obtain_lock(struct pkgdb *db);