Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
delete ordering is done in sql
Baptiste Daroussin committed 14 years ago
commit dd6fd75f77174c1d3de425dba3c142eb18d72040
parent 3e6c589
4 files changed +122 -33
modified libpkg/pkg.h
@@ -585,6 +585,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_delete(struct pkgdb *db, match_t type, int nbpkgs, char **pkgs, int recursive);
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);
modified libpkg/pkg_jobs.c
@@ -272,6 +272,11 @@ pkg_jobs_resolv(struct pkg_jobs *j)
	if (j->resolved == 1)
		return (EPKG_OK);

+
	if (j->type == PKG_JOBS_DEINSTALL) {
+
		j->resolved = 1;
+
		return (EPKG_OK);
+
	}
+

	/* Create nodes and remove jobs form the queue */
	while (!STAILQ_EMPTY(&j->jobs)) {
		p = STAILQ_FIRST(&j->jobs);
modified libpkg/pkgdb.c
@@ -64,6 +64,7 @@ static struct column_int_mapping {
	{ "pkgsize", pkg_set_newpkgsize },
	{ "licenselogic", pkg_set_licenselogic},
	{ "rowid", pkg_set_rowid},
+
	{ "weight", NULL },
	{ NULL, NULL}
};

@@ -125,7 +126,8 @@ populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg) {
			case SQLITE_INTEGER:
				for (i = 0; columns_int[i].name != NULL; i++ ) {
					if (!strcmp(columns_int[i].name, colname)) {
-
						columns_int[i].set_int(pkg, sqlite3_column_int64(stmt, icol));
+
						if (columns_int[i].set_int != NULL)
+
							columns_int[i].set_int(pkg, sqlite3_column_int64(stmt, icol));
						break;
					}
				}
@@ -1984,24 +1986,26 @@ struct pkgdb_it *
pkgdb_query_autoremove(struct pkgdb *db)
{
	sqlite3_stmt *stmt = NULL;
+
	int weight = 0;

	assert(db != NULL);

	const char sql[] = ""
-
		"SELECT id AS rowid, origin, name, version, comment, desc, "
+
		"SELECT id AS rowid, p.origin, name, version, comment, desc, "
		"message, arch, osversion, maintainer, www, prefix, "
-
		"flatsize FROM packages WHERE id IN (SELECT pkgid FROM autoremove);";
+
		"flatsize FROM packages as p, autoremove where id = pkgid ORDER BY weight ASC;";

	sql_exec(db->sqlite, "DROP TABLE IF EXISTS autoremove; "
			"CREATE TEMPORARY TABLE IF NOT EXISTS autoremove ("
-
			"origin TEXT UNIQUE NOT NULL, pkgid INTEGER);");
+
			"origin TEXT UNIQUE NOT NULL, pkgid INTEGER, weight INTEGER);");

	do {
-
		sql_exec(db->sqlite, "INSERT OR IGNORE into autoremove(origin, pkgid)"
-
				"SELECT distinct origin, id FROM packages WHERE automatic=1 AND "
+
		sql_exec(db->sqlite, "INSERT OR IGNORE into autoremove(origin, pkgid, weight) "
+
				"SELECT distinct origin, id, %d FROM packages WHERE automatic=1 AND "
				"origin NOT IN (SELECT DISTINCT deps.origin FROM deps WHERE "
				"deps.package_id not in (select pkgid from  autoremove) and deps.origin = packages.origin);"
-
			);
+
				, weight);
+
		weight++;
	} while (sqlite3_changes(db->sqlite) != 0);

	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
@@ -2013,6 +2017,83 @@ pkgdb_query_autoremove(struct pkgdb *db)
}

struct pkgdb_it *
+
pkgdb_query_delete(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs, int recursive)
+
{
+
	sqlite3_stmt *stmt;
+

+
	struct sbuf *sql = sbuf_new_auto();
+
	const char *how = NULL;
+
	int i = 0;
+

+
	assert(db != NULL);
+

+
	const char sqlsel[] = ""
+
		"SELECT id AS rowid, p.origin, name, version, comment, desc, "
+
		"message, arch, osversion, maintainer, www, prefix, "
+
		"flatsize, (select count(*) from deps AS d where d.origin=del.origin) as weight FROM packages as p, delete_job as del where id = pkgid "
+
		"ORDER BY weight ASC;";
+

+
	sbuf_cat(sql, "INSERT OR IGNORE INTO delete_job (origin, pkgid) "
+
			"SELECT p.origin, p.id FROM packages as p, deps as d WHERE p.origin = d.origin AND ");
+

+
	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;
+
	}
+

+
	sql_exec(db->sqlite, "DROP TABLE IF EXISTS delete_job; "
+
			"CREATE TEMPORARY TABLE IF NOT EXISTS delete_job ("
+
			"origin TEXT UNIQUE NOT NULL, pkgid INTEGER);"
+
			);
+

+
	sbuf_printf(sql, how, "p.name");
+
	sbuf_cat(sql, " OR ");
+
	sbuf_printf(sql, how, "p.origin" );
+
	sbuf_cat(sql, " OR ");
+
	sbuf_printf(sql, how, "p.name || \"-\" || p.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);
+

+
	if (recursive) {
+
		do {
+
			sql_exec(db->sqlite, "INSERT OR IGNORE INTO delete_job(origin, pkgid) "
+
					"SELECT p.origin, p.id FROM deps AS d, packages AS p, delete_job AS del WHERE "
+
					"d.origin=del.origin AND p.id = d.package_id");
+
		} while (sqlite3_changes(db->sqlite) != 0);
+
	}
+

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

+

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

+
struct pkgdb_it *
pkgdb_rquery(struct pkgdb *db, const char *pattern, match_t match, pkgdb_field field)
{
	sqlite3_stmt *stmt = NULL;
modified pkg/delete.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <sysexits.h>
#include <unistd.h>
+
#include <libutil.h>

#include <pkg.h>

@@ -13,7 +14,7 @@
void
usage_delete(void)
{
-
	fprintf(stderr, "usage: pkg delete [-ygxXf] <pkg-name> <...>\n");
+
	fprintf(stderr, "usage: pkg delete [-ygxXfr] <pkg-name> <...>\n");
	fprintf(stderr, "       pkg delete [-y] -a\n\n");
	fprintf(stderr, "For more information see 'pkg help delete'.\n");
}
@@ -26,13 +27,16 @@ exec_delete(int argc, char **argv)
	struct pkgdb *db = NULL;
	struct pkgdb_it *it = NULL;
	match_t match = MATCH_EXACT;
-
	int i, ch;
+
	int ch;
	int flags = PKG_LOAD_BASIC;
	int force = 0;
	int yes = 0;
	int retcode = 1;
+
	int recursive = 0;
+
	int64_t oldsize = 0, newsize = 0;
+
	char size[7];

-
	while ((ch = getopt(argc, argv, "agxXfy")) != -1) {
+
	while ((ch = getopt(argc, argv, "agxXfyr")) != -1) {
		switch (ch) {
			case 'a':
				match = MATCH_ALL;
@@ -52,6 +56,9 @@ exec_delete(int argc, char **argv)
			case 'y':
				yes = 1;
				break;
+
			case 'r':
+
				recursive = 1;
+
				break;
			default:
				usage_delete();
				return (EX_USAGE);
@@ -80,30 +87,14 @@ exec_delete(int argc, char **argv)
		return (EPKG_FATAL);
	}

-
	if (match == MATCH_ALL) {
-
		if ((it = pkgdb_query(db, NULL, match)) == NULL) {
-
			goto cleanup;
-
		}
-

-
		while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
-
			pkg_jobs_add(jobs, pkg);
-
			pkg = NULL;
-
		}
+
	if ((it = pkgdb_query_delete(db, match, argc, argv, recursive)) == NULL)
+
		goto cleanup;

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

-
			while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
-
				pkg_jobs_add(jobs, pkg);
-
				pkg = NULL;
-
			}
-
		
-
			pkgdb_it_free(it);
-
		}
+
	while (pkgdb_it_next(it, &pkg, flags) == EPKG_OK) {
+
		oldsize += pkg_flatsize(pkg);
+
		newsize += pkg_new_flatsize(pkg);
+
		pkg_jobs_add(jobs, pkg);
+
		pkg = NULL;
	}

	/* check if we have something to deinstall */
@@ -113,11 +104,22 @@ exec_delete(int argc, char **argv)
		goto cleanup;
	}

+
	if (oldsize > newsize) {
+
		newsize *= -1;
+
		humanize_number(size, sizeof(size), oldsize - newsize, "B", HN_AUTOSCALE, 0);
+
	} else {
+
		humanize_number(size, sizeof(size), newsize - oldsize, "B", HN_AUTOSCALE, 0);
+
	}
+

	pkg = NULL;
	printf("The following packages will be deinstalled:\n");
	while (pkg_jobs(jobs, &pkg) == EPKG_OK)
		printf("\t%s-%s\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));

+
	if (oldsize > newsize)
+
		printf("\nThe deinstallation will save %s\n", size);
+
	else
+
		printf("\nThe deinstallation will require %s more space\n", size);
	if (yes == 0)
		yes = query_yesno("\nProceed with deinstalling packages [y/N]: ");