Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Search for upgrade candidates first prior to upgrade.
Vsevolod Stakhov committed 12 years ago
commit c1633240fbca76121afdfc99268505f15ef4480b
parent 65f3d62ee0a8581351d507265fafd094ac09e3b0
2 files changed +100 -12
modified libpkg/pkg_jobs.c
@@ -1851,17 +1851,94 @@ jobs_solve_autoremove(struct pkg_jobs *j)
	return (EPKG_OK);
}

+
struct pkg_jobs_install_candidate {
+
	int64_t id;
+
	struct pkg_jobs_install_candidate *next;
+
};
+

+
static struct pkg_jobs_install_candidate *
+
pkg_jobs_new_candidate(struct pkg *pkg)
+
{
+
	struct pkg_jobs_install_candidate *n;
+
	int64_t id;
+

+
	pkg_get(pkg, PKG_ROWID, &id);
+
	n = malloc(sizeof(*n));
+
	if (n == NULL) {
+
		pkg_emit_errno("malloc", "pkg_jobs_install_candidate");
+
		return (NULL);
+
	}
+
	n->id = id;
+
	return (n);
+
}
+

+
static bool
+
pkg_jobs_check_remote_candidate(struct pkg_jobs *j, struct pkg *pkg)
+
{
+
	const char *digest;
+
	char sqlbuf[256];
+
	struct pkgdb_it *it;
+
	struct pkg *p = NULL;
+

+
	pkg_get(pkg, PKG_DIGEST, &digest);
+
	/* If we have no digest, we need to check this package */
+
	if (digest == NULL || digest[0] == '\0')
+
		return (true);
+

+
	sqlite3_snprintf(sizeof(sqlbuf), sqlbuf, " WHERE manifestdigest=%Q", digest);
+

+
	it = pkgdb_rquery(j->db, sqlbuf, MATCH_CONDITION, j->reponame);
+
	if (it != NULL) {
+
		/*
+
		 * If we have the same package in a remote repo, it is not an
+
		 * installation candidate
+
		 */
+
		if (pkgdb_it_next(it, &p, PKG_LOAD_BASIC) == EPKG_OK) {
+
			pkg_free(p);
+
			pkgdb_it_free(it);
+
			return (false);
+
		}
+
		pkgdb_it_free(it);
+
	}
+

+
	return (true);
+
}
+

+
static struct pkg_jobs_install_candidate *
+
pkg_jobs_find_install_candidates(struct pkg_jobs *j)
+
{
+
	struct pkg *pkg = NULL;
+
	struct pkgdb_it *it;
+
	struct pkg_jobs_install_candidate *candidates = NULL, *c;
+

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

+
	while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
+
		if (pkg_jobs_check_remote_candidate(j, pkg)) {
+
			c = pkg_jobs_new_candidate(pkg);
+
			LL_PREPEND(candidates, c);
+
		}
+
	}
+
	pkg_free(pkg);
+
	pkgdb_it_free(it);
+

+
	return (candidates);
+
}
+

static int
jobs_solve_install_upgrade(struct pkg_jobs *j)
{
	struct pkg *pkg = NULL;
	struct pkgdb_it *it;
	char *uid;
+
	char sqlbuf[256];
	bool automatic, got_local;
	struct job_pattern *jp, *jtmp;
	struct pkg_job_request *req, *rtmp;
	unsigned flags = PKG_LOAD_BASIC|PKG_LOAD_OPTIONS|PKG_LOAD_DEPS|
			PKG_LOAD_SHLIBS_REQUIRED|PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
+
	struct pkg_jobs_install_candidate *candidates, *c;

	if ((j->flags & PKG_FLAG_PKG_VERSION_TEST) == PKG_FLAG_PKG_VERSION_TEST)
		if (new_pkg_version(j)) {
@@ -1876,18 +1953,26 @@ jobs_solve_install_upgrade(struct pkg_jobs *j)

	if (j->solved == 0) {
		if (j->patterns == NULL) {
-
			if ((it = pkgdb_query(j->db, NULL, MATCH_ALL)) == NULL)
-
				return (EPKG_FATAL);
+
			candidates = pkg_jobs_find_install_candidates(j);

-
			while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
-
				/* TODO: use repository priority here */
-
				pkg_jobs_add_universe(j, pkg, true, false, NULL);
-
				pkg_get(pkg, PKG_UNIQUEID, &uid, PKG_AUTOMATIC, &automatic);
-
				/* Do not test we ignore what doesn't exists remotely */
-
				pkg_jobs_find_remote_pkg(j, uid, MATCH_EXACT, !automatic, true, !automatic);
-
				pkg = NULL;
+
			LL_FOREACH(candidates, c) {
+
				sqlite3_snprintf(sizeof(sqlbuf), sqlbuf, " WHERE id=%" PRId64,
+
						c->id);
+
				if ((it = pkgdb_query(j->db, sqlbuf, MATCH_CONDITION)) == NULL)
+
					return (EPKG_FATAL);
+

+
				while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
+
					/* TODO: use repository priority here */
+
					pkg_jobs_add_universe(j, pkg, true, false, NULL);
+
					pkg_get(pkg, PKG_UNIQUEID, &uid, PKG_AUTOMATIC, &automatic);
+
					/* Do not test we ignore what doesn't exists remotely */
+
					pkg_jobs_find_remote_pkg(j, uid, MATCH_EXACT, !automatic,
+
							true, !automatic);
+
					pkg = NULL;
+
				}
+
				pkgdb_it_free(it);
			}
-
			pkgdb_it_free(it);
+
			LL_FREE(candidates, free);
		}
		else {
			HASH_ITER(hh, j->patterns, jp, jtmp) {
modified libpkg/private/repodb.h
@@ -178,8 +178,9 @@ static const char initsql[] = ""
	"CREATE INDEX packages_name ON packages(name COLLATE NOCASE);"
	"CREATE INDEX packages_uid_nocase ON packages(name COLLATE NOCASE, origin COLLATE NOCASE);"
	"CREATE INDEX packages_version_nocase ON packages(name COLLATE NOCASE, version);"
-
	"CREATE INDEX packages_uid ON packages(name, origin COLLATE NOCASE);"
+
	"CREATE INDEX packages_uid ON packages(name, origin);"
	"CREATE INDEX packages_version ON packages(name, version);"
+
	"CREATE UNIQUE INDEX packages_digest ON packages(manifestdigest);"
	/* FTS search table */
	"CREATE VIRTUAL TABLE pkg_search USING fts4(id, name, origin);"

@@ -349,8 +350,9 @@ static const struct repo_changes repo_upgrades[] = {

	 "CREATE INDEX IF NOT EXISTS %Q.packages_uid_nocase ON packages(name COLLATE NOCASE, origin COLLATE NOCASE);"
	 "CREATE INDEX IF NOT EXISTS %Q.packages_version_nocase ON packages(name COLLATE NOCASE, version);"
-
	 "CREATE INDEX IF NOT EXISTS %Q.packages_uid ON packages(name, origin COLLATE NOCASE);"
+
	 "CREATE INDEX IF NOT EXISTS %Q.packages_uid ON packages(name, origin);"
	 "CREATE INDEX IF NOT EXISTS %Q.packages_version ON packages(name, version);"
+
	 "CREATE UNIQUE INDEX IF NOT EXISTS %Q.packages_digest ON packages(manifestdigest);"
	},
	/* Mark the end of the array */
	{ -1, -1, NULL, NULL, }
@@ -368,6 +370,7 @@ static const struct repo_changes repo_downgrades[] = {
	 "DROP INDEX %Q.packages_version_nocase;"
	 "DROP INDEX %Q.packages_uid;"
	 "DROP INDEX %Q.packages_version;"
+
	 "DROP INDEX %Q.packages_digest;"
	},
	{2008,
	 2007,