Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Order deletes.
jlaffaye committed 14 years ago
commit 1a80a52d379106ee3ae33dabbe6cc33ef692ced9
parent 13c8c78
9 files changed +181 -91
modified libpkg/pkg.c
@@ -673,6 +673,8 @@ pkg_freedeps(struct pkg *pkg)
		STAILQ_REMOVE_HEAD(&pkg->deps, next);
		pkg_dep_free(d);
	}
+

+
	pkg->flags ^= PKG_LOAD_DEPS;
}

void
@@ -685,6 +687,8 @@ pkg_freerdeps(struct pkg *pkg)
		STAILQ_REMOVE_HEAD(&pkg->rdeps, next);
		pkg_dep_free(d);
	}
+

+
	pkg->flags ^= PKG_LOAD_RDEPS;
}

void
@@ -697,6 +701,8 @@ pkg_freefiles(struct pkg *pkg)
		STAILQ_REMOVE_HEAD(&pkg->files, next);
		pkg_file_free(f);
	}
+

+
	pkg->flags ^= PKG_LOAD_FILES;
}

void
@@ -709,6 +715,8 @@ pkg_freedirs(struct pkg *pkg)
		STAILQ_REMOVE_HEAD(&pkg->dirs, next);
		pkg_dir_free(d);
	}
+

+
	pkg->flags ^= PKG_LOAD_DIRS;
}

void
@@ -721,6 +729,8 @@ pkg_freeconflicts(struct pkg *pkg)
		STAILQ_REMOVE_HEAD(&pkg->conflicts, next);
		pkg_conflict_free(c);
	}
+

+
	pkg->flags ^= PKG_LOAD_CONFLICTS;
}

void
@@ -733,6 +743,8 @@ pkg_freescripts(struct pkg *pkg)
		STAILQ_REMOVE_HEAD(&pkg->scripts, next);
		pkg_script_free(s);
	}
+

+
	pkg->flags ^= PKG_LOAD_SCRIPTS;
}

void
@@ -745,6 +757,8 @@ pkg_freeoptions(struct pkg *pkg)
		STAILQ_REMOVE_HEAD(&pkg->options, next);
		pkg_option_free(o);
	}
+

+
	pkg->flags ^= PKG_LOAD_OPTIONS;
}

int
modified libpkg/pkg.h
@@ -115,6 +115,11 @@ typedef enum _pkg_script_t {
	PKG_SCRIPT_UPGRADE
} pkg_script_t;

+
typedef enum _pkg_jobs_t {
+
	PKG_JOBS_INSTALL,
+
	PKG_JOBS_DEINSTALL
+
} pkg_jobs_t;
+

/**
 * Error type used everywhere by libpkg.
 */
@@ -143,8 +148,6 @@ typedef enum {
	EPKG_DEPENDENCY,
} pkg_error_t;

-
typedef void (*status_cb)(void *data, struct pkg *pkg);
-

/**
 * Allocate a new pkg.
 * Allocated pkg must be deallocated by pkg_free().
@@ -507,7 +510,7 @@ int pkg_add(struct pkgdb *db, const char *path);
 * @param db A pkgdb open with PKGDB_REMOTE.
 * @return An error code.
 */
-
int pkg_jobs_new(struct pkg_jobs **jobs, struct pkgdb *db);
+
int pkg_jobs_new(struct pkg_jobs **jobs, pkg_jobs_t type, struct pkgdb *db);

/**
 * Free a pkg_jobs
@@ -531,7 +534,7 @@ int pkg_jobs(struct pkg_jobs *jobs, struct pkg **pkg);
 * Apply the jobs in the queue (fetch and install).
 * @return An error code.
 */
-
int pkg_jobs_apply(struct pkg_jobs *jobs);
+
int pkg_jobs_apply(struct pkg_jobs *jobs, int force);

/**
 * Archive formats options.
@@ -625,7 +628,7 @@ typedef enum {
	PKG_EVENT_ALREADY_INSTALLED,
	PKG_EVENT_FAILED_CKSUM,
	PKG_EVENT_CREATE_DB_ERROR,
-
	PKG_EVENT_DELETE_DEP_EXISTS,
+
	PKG_EVENT_REQUIRED,
	PKG_EVENT_MISSING_DEP,
} pkg_event_t;

@@ -662,6 +665,10 @@ struct pkg_event {
		} e_missing_dep;
		struct {
			struct pkg *pkg;
+
			int force;
+
		} e_required;
+
		struct {
+
			struct pkg *pkg;
		} e_failed_cksum;
	};
};
modified libpkg/pkg_delete.c
@@ -17,7 +17,6 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
{
	struct pkg_dep *rdep = NULL;
	int ret;
-
	struct sbuf *rdep_msg = NULL;

	if (pkg == NULL)
		return (ERROR_BAD_ARG("pkg"));
@@ -26,6 +25,12 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
		return (ERROR_BAD_ARG("db"));

	/*
+
	 * Do not trust the existing entries as it may have changed if we
+
	 * delete packages in batch.
+
	 */
+
	pkg_freerdeps(pkg);
+

+
	/*
	 * Ensure that we have all the informations we need
	 */
	if ((ret = pkgdb_loadrdeps(db, pkg)) != EPKG_OK)
@@ -39,28 +44,11 @@ pkg_delete(struct pkg *pkg, struct pkgdb *db, int force)
	if ((ret = pkgdb_loadmtree(db, pkg)) != EPKG_OK)
		return (ret);

-
	while (pkg_rdeps(pkg, &rdep) == EPKG_OK) {
-
		if (rdep_msg == NULL) {
-
			rdep_msg = sbuf_new_auto();
-
			sbuf_printf(rdep_msg, "%s-%s is required by other packages:", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
-
		}
-
		sbuf_cat(rdep_msg, " ");
-
		sbuf_printf(rdep_msg, "%s-%s", pkg_dep_name(rdep), pkg_dep_version(rdep));
-
	}
	/* If there are dependencies */
-
	if (rdep_msg != NULL) {
-
		if (!force) {
-
			sbuf_finish(rdep_msg);
-
			/*pkg_emit_event(PKG_EVENT_DELETE_DEP_EXISTS, 1,
-
			    sbuf_get(rdep_msg));*/
-
			ret = EPKG_REQUIRED;
-
			sbuf_free(rdep_msg);
-
			return ret;
-
		}
-
		sbuf_cat(rdep_msg, ", deleting anyway");
-
		sbuf_finish(rdep_msg);
-
		fprintf(stderr, "%s\n", sbuf_get(rdep_msg));
-
		sbuf_free(rdep_msg);
+
	if (pkg_rdeps(pkg, &rdep) == EPKG_OK) {
+
		EMIT_REQUIRED(pkg, force);
+
		if (!force)
+
			return (EPKG_REQUIRED);
	}

	if ((ret = pkg_script_run(pkg, PKG_SCRIPT_PRE_DEINSTALL)) != EPKG_OK)
@@ -92,16 +80,16 @@ pkg_delete_files(struct pkg *pkg, int force)
		/* check sha256 */
		if (!force && pkg_file_sha256(file)[0] != '\0') {
			if (sha256_file(path, sha256) == -1) {
-
				warnx("sha256 calculation failed for '%s'",
+
				EMIT_PKG_ERROR("sha256 calculation failed for '%s'",
					  path);
			} else if (strcmp(sha256, pkg_file_sha256(file)) != 0) {
-
				warnx("%s fails original SHA256 checksum, not removing", path);
+
				EMIT_PKG_ERROR("%s fails original SHA256 checksum, not removing", path);
				continue;
			}
		}

		if (unlink(path) == -1) {
-
			warn("unlink(%s)", path);
+
			EMIT_ERRNO("unlink", path);
			continue;
		}
	}
@@ -116,7 +104,7 @@ pkg_delete_dirs(struct pkg *pkg, int force)

	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
		if (rmdir(pkg_dir_path(dir)) == -1 && errno != ENOTEMPTY && force != 1) {
-
			warn("rmdir(%s)", pkg_dir_path(dir));
+
			EMIT_ERRNO("rmdir", pkg_dir_path(dir));
		}
	}

modified libpkg/pkg_event.h
@@ -66,6 +66,14 @@
	_EV_EMIT; \
	_EV_END

+
#define EMIT_REQUIRED(p, f) \
+
	_EV_START; \
+
	ev.type = PKG_EVENT_REQUIRED; \
+
	ev.e_required.pkg = p; \
+
	ev.e_required.force = f; \
+
	_EV_EMIT; \
+
	_EV_END
+

#define EMIT_FAILED_CKSUM(p) \
	_EV_START; \
	ev.type = PKG_EVENT_FAILED_CKSUM; \
modified libpkg/pkg_jobs.c
@@ -5,13 +5,17 @@

#include "pkg.h"
#include "pkgdb.h"
+
#include "pkg_event.h"
#include "pkg_error.h"
#include "pkg_private.h"

int
-
pkg_jobs_new(struct pkg_jobs **j, struct pkgdb *db)
+
pkg_jobs_new(struct pkg_jobs **j, pkg_jobs_t t, struct pkgdb *db)
{
-
	if (db == NULL || db->type != PKGDB_REMOTE)
+
	if (db == NULL)
+
		return (ERROR_BAD_ARG("db"));
+

+
	if (t == PKG_JOBS_INSTALL && db->type != PKGDB_REMOTE)
		return (ERROR_BAD_ARG("db"));

	if((*j = calloc(1, sizeof(struct pkg_jobs))) == NULL)
@@ -20,6 +24,7 @@ pkg_jobs_new(struct pkg_jobs **j, struct pkgdb *db)
	STAILQ_INIT(&(*j)->jobs);
	LIST_INIT(&(*j)->nodes);
	(*j)->db = db;
+
	(*j)->type = t;

	return (EPKG_OK);
}
@@ -59,7 +64,7 @@ pkg_jobs(struct pkg_jobs *j, struct pkg **pkg)
	if (j == NULL)
		return (ERROR_BAD_ARG("jobs"));

-
	pkg_jobs_resolv(j, 0);
+
	pkg_jobs_resolv(j);

	if (*pkg == NULL)
		*pkg = STAILQ_FIRST(&j->jobs);
@@ -72,8 +77,8 @@ pkg_jobs(struct pkg_jobs *j, struct pkg **pkg)
		return (EPKG_OK);
}

-
int
-
pkg_jobs_apply(struct pkg_jobs *j)
+
static int
+
pkg_jobs_install(struct pkg_jobs *j)
{
	struct pkg *p = NULL;
	const char *cachedir;
@@ -100,8 +105,35 @@ pkg_jobs_apply(struct pkg_jobs *j)
	return (EPKG_OK);
}

+
static int
+
pkg_jobs_deinstall(struct pkg_jobs *j, int force)
+
{
+
	struct pkg *p = NULL;
+
	int retcode;
+

+
	while (pkg_jobs(j, &p) == EPKG_OK) {
+
		retcode = pkg_delete(p, j->db, force);
+
		if (retcode != EPKG_OK)
+
			return (retcode);
+
	}
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_jobs_apply(struct pkg_jobs *j, int force)
+
{
+
	if (j->type == PKG_JOBS_INSTALL)
+
		return (pkg_jobs_install(j));
+
	if (j->type == PKG_JOBS_DEINSTALL)
+
		return (pkg_jobs_deinstall(j, force));
+

+
	EMIT_PKG_ERROR("%s", "bad jobs argument");
+
	return (EPKG_FATAL);
+
}
+

static struct pkg_jobs_node *
-
get_node(struct pkg_jobs *j, const char *name)
+
get_node(struct pkg_jobs *j, const char *name, int create)
{
	struct pkg_jobs_node *n;

@@ -112,39 +144,61 @@ get_node(struct pkg_jobs *j, const char *name)
		}
	}

+
	if (create == 0)
+
		return (NULL);
+

	n = calloc(1, sizeof(struct pkg_jobs_node));
	LIST_INSERT_HEAD(&j->nodes, n, entries);
	return (n);
}

static void
-
add_dep(struct pkg_jobs *j, struct pkg_jobs_node *n)
+
add_parent(struct pkg_jobs_node *n, struct pkg_jobs_node *p)
{
-
	struct pkg_dep *d = NULL;
-
	struct pkg_jobs_node *nd;
+
		p->nrefs++;

-
	while (pkg_deps(n->pkg, &d) != EPKG_END) {
-
		n->nrefs++;
-
		nd = get_node(j, pkg_dep_origin(d));
+
		if (n->parents_len == n->parents_cap) {
+
			if (n->parents_cap == 0)
+
				n->parents_cap = 5;
+
			else
+
				n->parents_cap *= 2;
+
			n->parents = realloc(n->parents, n->parents_cap *
+
								  sizeof(struct pkg_jobs_node));
+
		}
+
		n->parents[n->parents_len] = p;
+
		n->parents_len++;
+
}

-
		if (nd->pkg == NULL) {
-
			/* XXX should query with origin */
-
			nd->pkg = pkgdb_query_remote(j->db, pkg_dep_origin(d));
-
			if (nd->pkg == NULL)
+
static void
+
add_dep(struct pkg_jobs *j, struct pkg_jobs_node *n)
+
{
+
	struct pkg_dep *dep = NULL;
+
	struct pkg_jobs_node *ndep;
+

+
	while (pkg_deps(n->pkg, &dep) != EPKG_END) {
+
		ndep = get_node(j, pkg_dep_origin(dep), 1);
+
		if (ndep->pkg == NULL) {
+
			ndep->pkg = pkgdb_query_remote(j->db, pkg_dep_origin(dep));
+
			if (ndep->pkg == NULL)
				err(1, "%s", pkg_error_string());
-
			add_dep(j, nd);
+
			add_dep(j, ndep);
		}
+
		add_parent(ndep, n);
+
	}
+
}

-
		if (nd->parents_len == nd->parents_cap) {
-
			if (nd->parents_cap == 0)
-
				nd->parents_cap = 5;
-
			else
-
				nd->parents_cap *= 2;
-
			nd->parents = realloc(nd->parents, nd->parents_cap *
-
								  sizeof(struct pkg_jobs_node));
-
		}
-
		nd->parents[nd->parents_len] = n;
-
		nd->parents_len++;
+
static void
+
add_rdep(struct pkg_jobs *j, struct pkg_jobs_node *n)
+
{
+
	struct pkg_jobs_node *nrdep;
+
	struct pkg_dep *rdep = NULL;
+

+
	pkgdb_loadrdeps(j->db, n->pkg);
+

+
	while (pkg_rdeps(n->pkg, &rdep) == EPKG_OK) {
+
		nrdep = get_node(j, pkg_dep_origin(rdep), 0);
+
		if (nrdep != NULL)
+
			add_parent(nrdep, n);
	}
}

@@ -156,10 +210,7 @@ remove_node(struct pkg_jobs *j, struct pkg_jobs_node *n)

	assert(n->nrefs == 0);

-
	if (j->reverse == 1)
-
		STAILQ_INSERT_HEAD(&j->jobs, n->pkg, next);
-
	else
-
		STAILQ_INSERT_TAIL(&j->jobs, n->pkg, next);
+
	STAILQ_INSERT_TAIL(&j->jobs, n->pkg, next);

	LIST_REMOVE(n, entries);

@@ -172,7 +223,7 @@ remove_node(struct pkg_jobs *j, struct pkg_jobs_node *n)
}

int
-
pkg_jobs_resolv(struct pkg_jobs *j, int reverse)
+
pkg_jobs_resolv(struct pkg_jobs *j)
{
	struct pkg_jobs_node *n, *tmp;
	struct pkg *p;
@@ -183,21 +234,22 @@ pkg_jobs_resolv(struct pkg_jobs *j, int reverse)
	if (j->resolved == 1)
		return (EPKG_OK);

-
	j->reverse = reverse;
-

	/* Create nodes and remove jobs form the queue */
	while (!STAILQ_EMPTY(&j->jobs)) {
		p = STAILQ_FIRST(&j->jobs);
		STAILQ_REMOVE_HEAD(&j->jobs, next);

-
		n = get_node(j, pkg_get(p, PKG_ORIGIN));
+
		n = get_node(j, pkg_get(p, PKG_ORIGIN), 1);

		n->pkg = p;
	}

	/* Add dependencies into nodes */
	LIST_FOREACH(n, &j->nodes, entries) {
-
		add_dep(j, n);
+
		if (j->type == PKG_JOBS_INSTALL)
+
			add_dep(j, n);
+
		if (j->type == PKG_JOBS_DEINSTALL)
+
			add_rdep(j, n);
	}

	/* Resolv !*/
modified libpkg/pkg_private.h
@@ -79,8 +79,8 @@ struct pkg_jobs {
	STAILQ_HEAD(jobs, pkg) jobs;
	LIST_HEAD(nodes, pkg_jobs_node) nodes;
	struct pkgdb *db;
+
	pkg_jobs_t type;
	unsigned int resolved :1;
-
	unsigned int reverse :1;
};

struct pkg_jobs_node {
@@ -119,7 +119,7 @@ void pkg_script_free(struct pkg_script *);
int pkg_option_new(struct pkg_option **);
void pkg_option_free(struct pkg_option *);

-
int pkg_jobs_resolv(struct pkg_jobs *jobs, int reverse);
+
int pkg_jobs_resolv(struct pkg_jobs *jobs);

struct packing;

modified pkg/delete.c
@@ -20,22 +20,21 @@ usage_delete(void)
int
exec_delete(int argc, char **argv)
{
+
	struct pkg_jobs *jobs = NULL;
	struct pkg *pkg = NULL;
-
	struct pkgdb *db;
-
	struct pkgdb_it *it;
+
	struct pkgdb *db = NULL;
+
	struct pkgdb_it *it = NULL;
	match_t match = MATCH_EXACT;
	char *origin = NULL;
	int ch;
-
	int ret;
	int flags = PKG_LOAD_BASIC;
	int force = 0;
-
	int retcode = 0;
+
	int retcode = EPKG_OK;

	while ((ch = getopt(argc, argv, "af")) != -1) {
		switch (ch) {
			case 'a':
				match = MATCH_ALL;
-
				force = 1;
				break;
			case 'f':
				force = 1;
@@ -58,38 +57,46 @@ exec_delete(int argc, char **argv)
		return (EX_NOPERM);
	}
	
-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if ((retcode = pkgdb_open(&db, PKGDB_DEFAULT)) != EPKG_OK) {
		pkg_error_warn("can not open database");
-
		pkgdb_close(db);
-
		return (-1);
+
		goto cleanup;
	}

	if (argc == 1)
		origin = argv[0];

+
	if ((retcode = pkg_jobs_new(&jobs, PKG_JOBS_DEINSTALL, db)) != EPKG_OK) {
+
		pkg_error_warn("cant create jobs");
+
		goto cleanup;
+
	}
+

	if ((it = pkgdb_query(db, origin, match)) == NULL) {
		pkg_error_warn("Can not query database");
-
		return (1);
+
		retcode = EPKG_FATAL;
+
		goto cleanup;
	}

-
	while ((ret = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) {
-
		if (pkg_delete(pkg, db, force) != EPKG_OK) {
-
			retcode++;
-
			pkg_error_warn("can not delete %s", pkg_get(pkg, PKG_ORIGIN));
-
		}
+
	while ((retcode = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) {
+
		pkg_jobs_add(jobs, pkg);
+
		pkg = NULL;
	}
-
	pkg_free(pkg);

-
	if (ret != EPKG_END) {
+
	if (retcode != EPKG_END) {
		pkg_error_warn("can not iterate over results");
-
		retcode++;
+
		goto cleanup;
	}

-
	pkgdb_it_free(it);
+
	if ((retcode = pkg_jobs_apply(jobs, force)) != EPKG_OK) {
+
		pkg_error_warn("cant deinstall");
+
		goto cleanup;
+
	}

-
	if (pkgdb_compact(db) != EPKG_OK)
+
	if ((retcode = pkgdb_compact(db)) != EPKG_OK)
		pkg_error_warn("can not compact database");

+
	cleanup:
+
	pkgdb_it_free(it);
	pkgdb_close(db);
-
	return (retcode);
+
	pkg_jobs_free(jobs);
+
	return (retcode == EPKG_OK ? 0 : 1);
}
modified pkg/event.c
@@ -6,6 +6,8 @@
int
event_callback(void *data __unused, struct pkg_event *ev)
{
+
	struct pkg *pkg = NULL;
+
	struct pkg_dep *dep = NULL;
	unsigned int percent;
	const char *message;

@@ -34,6 +36,18 @@ event_callback(void *data __unused, struct pkg_event *ev)
		if (message != NULL && message[0] != '\0')
			printf("%s\n", message);
		break;
+
	case PKG_EVENT_REQUIRED:
+
		pkg = ev->e_required.pkg;
+
		fprintf(stderr, "%s-%s is required by:", pkg_get(pkg, PKG_NAME),
+
				pkg_get(pkg, PKG_VERSION));
+
		while (pkg_rdeps(pkg, &dep) == EPKG_OK) {
+
			fprintf(stderr, " %s-%s", pkg_dep_name(dep), pkg_dep_version(dep));
+
		}
+
		if (ev->e_required.force == 1)
+
			fprintf(stderr, ", deleting anyway\n");
+
		else
+
			fprintf(stderr, "\n");
+
		break;
	default:
		break;
	}
modified pkg/install.c
@@ -44,7 +44,7 @@ exec_install(int argc, char **argv)
		goto cleanup;
	}

-
	if (pkg_jobs_new(&jobs, db) != EPKG_OK) {
+
	if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK) {
		pkg_error_warn("pkg_jobs_new()");
		retcode = EPKG_FATAL;
		goto cleanup;
@@ -67,7 +67,7 @@ exec_install(int argc, char **argv)
		printf("%s-%s\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
	}

-
	if (pkg_jobs_apply(jobs) != EPKG_OK)
+
	if (pkg_jobs_apply(jobs, 0) != EPKG_OK)
		pkg_error_warn("can not install");

	cleanup: