Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Use sqlite memory table for install/upgrade solver
Baptiste Daroussin committed 14 years ago
commit dd6db15e6e0a5709a982343cc082c7222411142a
parent 1e89c60
8 files changed +218 -159
modified libpkg/Makefile
@@ -19,7 +19,6 @@ SRCS= pkg.c \
		pkg_ports.c \
		pkg_repo.c \
		pkg_util.c \
-
		pkg_upgrade.c \
		pkg_version.c \
		pkgdb.c \
		backup.c \
modified libpkg/pkg.c
@@ -15,21 +15,21 @@ static struct _fields {
	int type;
	int optional;
} fields[] = {
-
	[PKG_ORIGIN] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_NAME] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_VERSION] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_COMMENT] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_DESC] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_MTREE] = {PKG_FILE|PKG_INSTALLED|PKG_UPGRADE, 1},
-
	[PKG_MESSAGE] = {PKG_FILE|PKG_INSTALLED|PKG_UPGRADE, 1},
-
	[PKG_ARCH] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_OSVERSION] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_MAINTAINER] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_WWW] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 1},
-
	[PKG_PREFIX] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
-
	[PKG_REPOPATH] = {PKG_REMOTE|PKG_UPGRADE, 0},
-
	[PKG_CKSUM] = {PKG_REMOTE|PKG_UPGRADE, 0},
-
	[PKG_NEWVERSION] = {PKG_UPGRADE, 0},
+
	[PKG_ORIGIN] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_NAME] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_VERSION] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_COMMENT] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_DESC] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_MTREE] = {PKG_FILE|PKG_INSTALLED, 1},
+
	[PKG_MESSAGE] = {PKG_FILE|PKG_INSTALLED, 1},
+
	[PKG_ARCH] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_OSVERSION] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_MAINTAINER] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_WWW] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 1},
+
	[PKG_PREFIX] = {PKG_FILE|PKG_REMOTE|PKG_INSTALLED, 0},
+
	[PKG_REPOPATH] = {PKG_REMOTE, 0},
+
	[PKG_CKSUM] = {PKG_REMOTE, 0},
+
	[PKG_NEWVERSION] = {PKG_REMOTE, 1},
};

int
modified libpkg/pkg.h
@@ -104,10 +104,6 @@ typedef enum {
	 * The pkg refers to a localy installed package.
	 */
	PKG_INSTALLED = 1 << 2,
-
	/**
-
	 * A package to be upgraded.
-
	 */
-
	PKG_UPGRADE = 1 << 3,
} pkg_t;

/**
@@ -244,12 +240,12 @@ const char *pkg_get(struct pkg const * const , const pkg_attr);
int64_t pkg_flatsize(struct pkg *);

/**
-
 * @return the size of the uncompressed new package (PKG_UPGRADE).
+
 * @return the size of the uncompressed new package (PKG_REMOTE).
 */
int64_t pkg_new_flatsize(struct pkg *);

/**
-
 * @return the size of the compressed new package (PKG_UPGRADE).
+
 * @return the size of the compressed new package (PKG_REMOTE).
 */
int64_t pkg_new_pkgsize(struct pkg *);

@@ -587,6 +583,7 @@ struct pkgdb_it * pkgdb_rquery(struct pkgdb *db, const char *pattern,
/**
 * 
 */
+
struct pkgdb_it *pkgdb_query_installs(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs);
struct pkgdb_it *pkgdb_query_upgrades(struct pkgdb *db);
struct pkgdb_it *pkgdb_query_downgrades(struct pkgdb *db);
struct pkgdb_it *pkgdb_query_autoremove(struct pkgdb *db);
@@ -716,8 +713,6 @@ int pkg_create_fakeroot(const char *, pkg_formats, const char *, const char *);
int pkg_delete(struct pkg *pkg, struct pkgdb *db, int force);
int pkg_delete2(struct pkg *pkg, struct pkgdb *db, int force, int upgrade);

-
int pkg_upgrade(struct pkgdb *db, struct pkg *pkg, const char *path);
-

int pkg_repo_fetch(struct pkg *pkg);
int pkg_repo_verify(const char *path, unsigned char *sig, unsigned int sig_len);

modified libpkg/pkg_jobs.c
@@ -103,55 +103,17 @@ pkg_jobs_install(struct pkg_jobs *j)
		snprintf(path, sizeof(path), "%s/%s", cachedir,
				 pkg_get(p, PKG_REPOPATH));

-
		if (pkg_add2(j->db, path, 0, pkg_isautomatic(p)) != EPKG_OK) {
-
			return (EPKG_FATAL);
+
		if (pkg_get(p, PKG_NEWVERSION) != NULL) {
+
			p->type = PKG_INSTALLED;
+
			if (pkg_delete2(p, j->db, 1, 0) != EPKG_OK)
+
				return (EPKG_FATAL);
		}
-
	}
-

-
	return (EPKG_OK);
-
}
-

-
static int
-
pkg_jobs_upgrade(struct pkg_jobs *j)
-
{
-
	struct pkg *p = NULL;
-
	struct pkg *oldpkg = NULL;
-
	struct pkgdb_it *it;
-
	const char *cachedir;
-
	char path[MAXPATHLEN + 1];
-
	int retcode = EPKG_FATAL;;

-
	/* Fetch */
-
	while (pkg_jobs(j, &p) == EPKG_OK) {
-
		if (pkg_repo_fetch(p) != EPKG_OK)
+
		if (pkg_add2(j->db, path, 0, pkg_isautomatic(p)) != EPKG_OK)
			return (EPKG_FATAL);
	}

-
	cachedir = pkg_config("PKG_CACHEDIR");
-
	p = NULL;
-
	while (pkg_jobs(j, &p) == EPKG_OK) {
-
		snprintf(path, sizeof(path), "%s/%s", cachedir,
-
			 pkg_get(p, PKG_REPOPATH));
-

-
		/* get the installed pkg if any */
-
		it = pkgdb_query(j->db, pkg_get(p, PKG_ORIGIN), MATCH_EXACT);
-
		if (pkgdb_it_next(it, &oldpkg, PKG_LOAD_BASIC) == EPKG_OK) {
-
			retcode = pkg_upgrade(j->db, oldpkg, path);
-
		} else {
-
			retcode = pkg_upgrade(j->db, NULL, path);
-
		}
-

-
		pkgdb_it_free(it);
-

-
		if (retcode != EPKG_OK)
-
			goto cleanup;
-
	}
-

-
	retcode = EPKG_OK;
-

-
	cleanup:
-
	pkg_free(oldpkg);
-
	return (retcode);
+
	return (EPKG_OK);
}

static int
@@ -176,8 +138,6 @@ pkg_jobs_apply(struct pkg_jobs *j, int force)
		return (pkg_jobs_install(j));
	if (j->type == PKG_JOBS_DEINSTALL)
		return (pkg_jobs_deinstall(j, force));
-
	if (j->type == PKG_JOBS_UPGRADE)
-
		return (pkg_jobs_upgrade(j));

	pkg_emit_error("bad jobs argument");
	return (EPKG_FATAL);
@@ -228,34 +188,6 @@ add_parent(struct pkg_jobs_node *n, struct pkg_jobs_node *p)
}

static void
-
add_dep(struct pkg_jobs *j, struct pkg_jobs_node *n)
-
{
-
	struct pkg_dep *dep = NULL;
-
	struct pkg_jobs_node *ndep;
-
	struct pkgdb_it *it = NULL;
-

-
	while (pkg_deps(n->pkg, &dep) != EPKG_END) {
-
		ndep = get_node(j, pkg_dep_origin(dep), 1);
-
		if (ndep->pkg == NULL) {
-
			/* get it from remote */
-
			if ((it = pkgdb_rquery(j->db, pkg_dep_origin(dep), MATCH_EXACT, FIELD_ORIGIN)) == NULL) {
-
				pkg_emit_missing_dep(n->pkg, dep);
-
			} else {
-
				if (pkgdb_it_next(it, &ndep->pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) {
-
					pkg_setautomatic(ndep->pkg);
-
					add_dep(j, ndep);
-
				} else {
-
					pkg_emit_missing_dep(n->pkg, dep);
-
				}
-
			}
-

-
			pkgdb_it_free(it);
-
		}
-
		add_parent(ndep, n);
-
	}
-
}
-

-
static void
add_rdep(struct pkg_jobs *j, struct pkg_jobs_node *n)
{
	struct pkg_jobs_node *nrdep;
@@ -294,8 +226,7 @@ int
pkg_jobs_resolv(struct pkg_jobs *j)
{
	struct pkg_jobs_node *n, *tmp;
-
	struct pkg *p, *ptemp, *localp;
-
	struct pkgdb_it *it = NULL;
+
	struct pkg *p;

	assert(j != NULL);

@@ -317,10 +248,6 @@ pkg_jobs_resolv(struct pkg_jobs *j)

	/* Add dependencies into nodes */
	LIST_FOREACH(n, &j->nodes, entries) {
-
		if (j->type == PKG_JOBS_UPGRADE)
-
			add_dep(j, n);
-
		if (j->type == PKG_JOBS_INSTALL)
-
			add_dep(j, n);
		if (j->type == PKG_JOBS_DEINSTALL)
			add_rdep(j, n);
	}
@@ -335,25 +262,5 @@ pkg_jobs_resolv(struct pkg_jobs *j)

	j->resolved = 1;

-
	if (j->type == PKG_JOBS_DEINSTALL)
-
		return (EPKG_OK);
-

-
	/* Now remove packages that are already installed */
-
	STAILQ_FOREACH_SAFE(p, &j->jobs, next, ptemp) {
-
		localp = NULL;
-
		it = NULL;
-
		if ((it = pkgdb_query(j->db, pkg_get(p, PKG_ORIGIN), MATCH_EXACT)) == NULL)
-
			continue;
-
		if (pkgdb_it_next(it, &localp, PKG_LOAD_BASIC) == EPKG_OK)
-
			if (!strcmp(pkg_get(localp, PKG_NAME), pkg_get(p, PKG_NAME)) &&
-
					!strcmp(pkg_get(localp, PKG_VERSION), pkg_get(p, p->type == PKG_UPGRADE ? PKG_NEWVERSION : PKG_VERSION))) {
-
				STAILQ_REMOVE(&j->jobs, p, pkg, next);
-
				pkg_free(p);
-
			}
-

-
		pkg_free(localp);
-
		pkgdb_it_free(it);
-
	}
-

	return (EPKG_OK);
}
modified libpkg/pkg_repo.c
@@ -30,8 +30,7 @@ pkg_repo_fetch(struct pkg *pkg)
	const char *packagesite = NULL;
	int retcode = EPKG_OK;

-
	assert((pkg->type & PKG_REMOTE) == PKG_REMOTE ||
-
		(pkg->type & PKG_UPGRADE) == PKG_UPGRADE);
+
	assert((pkg->type & PKG_REMOTE) == PKG_REMOTE);

	if ((packagesite = pkg_config("PACKAGESITE")) == NULL) {
		pkg_emit_error("pkg_repo_fetch(): %s", "PACKAGESITE is not defined");
modified libpkg/pkgdb.c
@@ -31,6 +31,7 @@ static int get_pragma(sqlite3 *, const char *, int64_t *);
static int sql_exec(sqlite3 *, const char *);
static int pkgdb_upgrade(sqlite3 *);
static void populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg);
+
static int create_temporary_pkgjobs(sqlite3 *);

static struct column_text_mapping {
	const char * const name;
@@ -124,6 +125,11 @@ populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg) {
						break;
					}
				}
+
				if (strcmp(colname, "automatic") == 0) {
+
					if (sqlite3_column_int64(stmt, icol) == 1)
+
						pkg_setautomatic(pkg);
+
					break;
+
				}
				if (columns_int[i].name == NULL)
					pkg_emit_error("Unknown column %s", colname);
				break;
@@ -619,7 +625,8 @@ void
pkgdb_it_free(struct pkgdb_it *it)
{

-
	sql_exec(it->db->sqlite, "DROP TABLE IF EXISTS autoremove; ");
+
	sql_exec(it->db->sqlite, "DROP TABLE IF EXISTS autoremove; "
+
			"DROP TABLE IF EXISTS pkgjobs");

	if (it != NULL) {
		sqlite3_finalize(it->stmt);
@@ -757,7 +764,7 @@ pkgdb_loaddeps(struct pkgdb *db, struct pkg *pkg)

	assert(db != NULL && pkg != NULL);

-
	if (pkg->type == PKG_UPGRADE || pkg->type == PKG_REMOTE) {
+
	if (pkg->type == PKG_REMOTE) {
		sql = ""
			"SELECT d.name, d.origin, d.version "
			"FROM remote.deps AS d "
@@ -921,7 +928,7 @@ pkgdb_loadlicense(struct pkgdb *db, struct pkg *pkg)

	assert(db != NULL && pkg != NULL);

-
	if (pkg->type == PKG_UPGRADE || pkg->type == PKG_REMOTE) {
+
	if (pkg->type == PKG_REMOTE) {
		sql = ""
			"SELECT name "
			"FROM remote.pkg_licenses, remote.licenses AS l "
@@ -947,7 +954,7 @@ pkgdb_loadcategory(struct pkgdb *db, struct pkg *pkg)

	assert(db != NULL && pkg != NULL);

-
	if (pkg->type == PKG_UPGRADE || pkg->type == PKG_REMOTE) {
+
	if (pkg->type == PKG_REMOTE) {
		sql = ""
			"SELECT name "
			"FROM remote.pkg_categories, remote.categories AS c "
@@ -1057,7 +1064,7 @@ pkgdb_loadoptions(struct pkgdb *db, struct pkg *pkg)

	assert(db != NULL && pkg != NULL);

-
	if (pkg->type == PKG_UPGRADE || pkg->type == PKG_REMOTE) {
+
	if (pkg->type == PKG_REMOTE) {
		sql = ""
		"SELECT option, value "
		"FROM remote.options "
@@ -1720,6 +1727,117 @@ pkgdb_compact(struct pkgdb *db)
	return (sql_exec(db->sqlite, "VACUUM;"));
}

+
static int
+
create_temporary_pkgjobs(sqlite3 *s)
+
{
+
	int ret;
+

+
	ret = sql_exec(s, "DROP TABLE IF EXISTS pkgjobs;"
+
			"CREATE TEMPORARY TABLE IF NOT EXISTS pkgjobs (pkgid INTEGER, "
+
			"origin TEXT UNIQUE NOT NULL, name TEXT, version TEXT, "
+
			"comment TEXT, desc TEXT, message TEXT, "
+
			"arch TEXT, osversion TEXT, maintainer TEXT, "
+
			"www TEXT, prefix TEXT, flatsize INTEGER, newversion TEXT, "
+
			"newflatsize INTEGER, pkgsize INTEGER, cksum TEXT, repopath TEXT, automatic INTEGER);");
+

+
	return (ret);
+
}
+

+
struct pkgdb_it *
+
pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs)
+
{
+
	sqlite3_stmt *stmt = NULL;;
+
	int i = 0;
+
	struct sbuf *sql = sbuf_new_auto();
+
	const char *how = NULL;
+

+
	const char finalsql[] = "select pkgid as rowid, origin, name, version, "
+
		"comment, desc, message, arch, osversion, maintainer, "
+
		"www, prefix, flatsize, newversion, newflatsize, pkgsize, "
+
		"cksum, repopath, automatic FROM pkgjobs;";
+

+
	if (db->type != PKGDB_REMOTE) {
+
		pkg_emit_error("remote database not attached (misuse)");
+
		return (NULL);
+
	}
+

+
	sbuf_cat(sql, "INSERT OR IGNORE INTO pkgjobs (pkgid, origin, name, version, comment, desc, arch, "
+
			"osversion, maintainer, www, prefix, flatsize, pkgsize, "
+
			"cksum, repopath, automatic) "
+
			"SELECT id, origin, name, version, comment, desc, "
+
			"arch, osversion, maintainer, www, prefix, flatsize, pkgsize, "
+
			"cksum, path, 0 FROM remote.packages WHERE ");
+

+
	switch (match) {
+
		case MATCH_ALL:
+
			how = NULL;
+
			break;
+
		case MATCH_EXACT:
+
			how = "%s = ?1";
+
			break;
+
		case MATCH_GLOB:
+
			how = "%s GLOB ?1";
+
			break;
+
		case MATCH_REGEX:
+
			how = "%s REGEXP ?1";
+
			break;
+
		case MATCH_EREGEX:
+
			how = "EREGEXP(?1, %s)";
+
			break;
+
	}
+

+
	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");
+

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

+
	sqlite3_finalize(stmt);
+
	sbuf_clear(sql);
+

+
	/* Append dependencies */
+
	do {
+
		sql_exec(db->sqlite, "INSERT INTO pkgjobs (pkgid, origin, name, version, comment, desc, arch, "
+
				"osversion, 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.osversion, r.maintainer, r.www, r.prefix, r.flatsize, r.pkgsize, "
+
				"r.cksum, r.path, 1 FROM remote.packages AS r, main.packages AS l, pkgjobs AS j, "
+
				"remote.deps AS d WHERE r.origin = d.origin AND d.package_id = j.pkgid AND "
+
				"((l.origin = r.origin AND l.version != r.version) OR (r.origin NOT IN (select origin from main.packages)));");
+
	} while (sqlite3_changes(db->sqlite) != 0);
+

+
	sbuf_delete(sql);
+

+
	/* Determine if there is an upgrade needed */
+
	sql_exec(db->sqlite, "INSERT OR REPLACE INTO pkgjobs (pkgid, origin, name, version, comment, desc, message, arch, "
+
			"osversion, maintainer, www, prefix, 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.osversion, l.maintainer, l.www, l.prefix, l.flatsize, r.version AS newversion, "
+
			"r.flatsize AS newflatsize, r.pkgsize, r.cksum, r.repopath, r.automatic "
+
			"FROM main.packages AS l, pkgjobs AS r WHERE l.origin = r.origin "
+
			"AND (PKGLT(l.version, r.version) OR (l.name != r.name))");
+

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

+
	return (pkgdb_it_new(db, stmt, PKG_REMOTE));
+
}
+

struct pkgdb_it *
pkgdb_query_upgrades(struct pkgdb *db)
{
@@ -1730,22 +1848,43 @@ pkgdb_query_upgrades(struct pkgdb *db)
		return (NULL);
	}

-
	const char sql[] = ""
-
		"SELECT l.id AS rowid, l.origin AS origin, l.name AS name, l.version AS version, l.comment AS comment, l.desc AS desc, "
-
		"l.message AS message, l.arch AS arch, l.osversion AS osversion, l.maintainer AS maintainer, "
-
		"l.www AS www, l.prefix AS prefix, l.flatsize AS flatsize, r.version AS newversion, r.flatsize AS newflatsize, "
-
		"r.pkgsize AS pkgsize, r.cksum AS cksum, r.path AS repopath "
-
		"FROM main.packages AS l, "
-
		"remote.packages AS r "
-
		"WHERE l.origin = r.origin "
-
		"AND (PKGLT(l.version, r.version) OR (l.name != r.name))";
+
	const char sql[] = "select pkgid as rowid, origin, name, version, "
+
		"comment, desc, message, arch, osversion, maintainer, "
+
		"www, prefix, flatsize, newversion, newflatsize, pkgsize, "
+
		"cksum, repopath, automatic FROM pkgjobs;";
+

+
	create_temporary_pkgjobs(db->sqlite);
+

+
	sql_exec(db->sqlite, "INSERT INTO pkgjobs (pkgid, origin, name, version, comment, desc, message, arch, "
+
			"osversion, maintainer, www, prefix, 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.osversion, l.maintainer, "
+
			"l.www, l.prefix, l.flatsize, r.version AS newversion, r.flatsize AS newflatsize, "
+
			"r.pkgsize, r.cksum, r.path AS repopath, l.automatic "
+
			"FROM main.packages AS l, "
+
			"remote.packages AS r "
+
			"WHERE l.origin = r.origin "
+
			"AND (PKGLT(l.version, r.version) OR (l.name != r.name))");
+

+
	do {
+
		sql_exec(db->sqlite, "INSERT INTO pkgjobs (pkgid, origin, name, version, comment, desc, arch, "
+
			"osversion, maintainer, www, prefix, flatsize, pkgsize, "
+
			"cksum, repopath, automatic)"
+
			"SELECT DISTINCT id, origin, name, version, comment, desc, arch, osversion, maintainer, www, prefix, flatsize, "
+
			"pkgsize, cksum, path as repopath, 1 FROM remote.packages WHERE origin IN ("
+
			"SELECT DISTINCT deps.origin FROM remote.deps as deps, pkgjobs WHERE deps.package_id = pkgjobs.pkgid and "
+
			"deps.origin NOT IN (SELECT DISTINCT origin from pkgjobs) AND deps.origin NOT IN (SELECT DISTINCT origin from main.packages)"
+
			");");
+
	} while (sqlite3_changes(db->sqlite) != 0);
+


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

-
	return (pkgdb_it_new(db, stmt, PKG_UPGRADE));
+
	return (pkgdb_it_new(db, stmt, PKG_REMOTE));
}

struct pkgdb_it *
@@ -1773,7 +1912,7 @@ pkgdb_query_downgrades(struct pkgdb *db)
		return (NULL);
	}

-
	return (pkgdb_it_new(db, stmt, PKG_UPGRADE));
+
	return (pkgdb_it_new(db, stmt, PKG_REMOTE));
}

struct pkgdb_it *
modified pkg/install.c
@@ -7,6 +7,7 @@
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
+
#include <libutil.h>

#include <pkg.h>

@@ -28,7 +29,10 @@ exec_install(int argc, char **argv)
	struct pkgdb *db = NULL;
	struct pkg_jobs *jobs = NULL;
	int retcode = 1;
-
	int i, ch, yes = 0;
+
	int ch, yes = 0;
+
	int64_t dlsize = 0;
+
	int64_t oldsize = 0, newsize = 0;
+
	char size[7];
	match_t match = MATCH_EXACT;

	while ((ch = getopt(argc, argv, "ygxX")) != -1) {
@@ -71,17 +75,12 @@ exec_install(int argc, char **argv)
		goto cleanup;
	}

-
	for (i = 0; i < argc; i++) {
-
		if ((it = pkgdb_rquery(db, argv[i], match, FIELD_NAME)) == NULL) {
-
			goto cleanup;
-
		}
+
	if ((it = pkgdb_query_installs(db, match, argc, argv)) == NULL)
+
		goto cleanup;

-
		while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) {
-
			pkg_jobs_add(jobs, pkg);
-
			pkg = NULL;
-
		}
-
		
-
		pkgdb_it_free(it);
+
	while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_DEPS) == EPKG_OK) {
+
		pkg_jobs_add(jobs, pkg);
+
		pkg = NULL;
	}

	if (pkg_jobs_isempty(jobs))
@@ -91,8 +90,27 @@ exec_install(int argc, char **argv)
	pkg = NULL;
	printf("The following packages will be installed:\n");
	while (pkg_jobs(jobs, &pkg) == EPKG_OK) {
-
		printf("\t%s-%s\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
+
		dlsize += pkg_new_pkgsize(pkg);
+
		if (pkg_get(pkg, PKG_NEWVERSION) != NULL) {
+
			printf("\tUpgrading %s: %s -> %s\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_get(pkg,PKG_NEWVERSION));
+
			oldsize += pkg_flatsize(pkg);
+
			newsize += pkg_new_flatsize(pkg);
+
		} else {
+
			newsize += pkg_flatsize(pkg);
+
			printf("\tInstalling %s: %s\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
+
		}
+
	}
+

+
	if (oldsize > newsize) {
+
		newsize *= -1;
+
		humanize_number(size, sizeof(size), oldsize - newsize, "B", HN_AUTOSCALE, 0);
+
		printf("\nthe installation will save %s\n", size);
+
	} else {
+
		humanize_number(size, sizeof(size), newsize - oldsize, "B", HN_AUTOSCALE, 0);
+
		printf("\nthe installation will require %s more space\n", size);
	}
+
	humanize_number(size, sizeof(size), dlsize, "B", HN_AUTOSCALE, 0);
+
	printf("%s to be downloaded\n", size);
 
	if (yes == 0)
		yes = query_yesno("\nProceed with installing packages [y/N]: ");
modified pkg/upgrade.c
@@ -61,7 +61,7 @@ exec_upgrade(int argc, char **argv)
		return (EX_IOERR);
	}

-
	if (pkg_jobs_new(&jobs, PKG_JOBS_UPGRADE, db) != EPKG_OK) {
+
	if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK) {
		goto cleanup;
	}

@@ -82,13 +82,15 @@ exec_upgrade(int argc, char **argv)
	printf("The following packages will be upgraded: \n");
	pkg = NULL;
	while (pkg_jobs(jobs, &pkg) == EPKG_OK) {
-
		oldsize += pkg_flatsize(pkg);
-
		newsize += pkg_new_flatsize(pkg);
		dlsize += pkg_new_pkgsize(pkg);
-
		if (pkg_type(pkg) == PKG_UPGRADE)
+
		if (pkg_get(pkg, PKG_NEWVERSION) != NULL) {
			printf("\tUpgrading %s: %s -> %s\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_get(pkg,PKG_NEWVERSION));
-
		else
+
			oldsize += pkg_flatsize(pkg);
+
			newsize += pkg_new_flatsize(pkg);
+
		} else {
+
			newsize += pkg_flatsize(pkg);
			printf("\tInstalling %s: %s\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
+
		}
	}

	if (oldsize > newsize) {