Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Rework conflicts system.
Vsevolod Stakhov committed 12 years ago
commit 791546442ec76ec98485240561314c154ce238e9
parent f4882df
8 files changed +147 -71
modified libpkg/pkg.c
@@ -463,6 +463,14 @@ pkg_shlibs_provided(const struct pkg *pkg, struct pkg_shlib **s)
}

int
+
pkg_conflicts(const struct pkg *pkg, struct pkg_conflict **c)
+
{
+
	assert(pkg != NULL);
+

+
	HASH_NEXT(pkg->conflicts, (*c));
+
}
+

+
int
pkg_annotations(const struct pkg *pkg, struct pkg_note **an)
{
	assert(pkg != NULL);
@@ -899,6 +907,29 @@ pkg_addshlib_provided(struct pkg *pkg, const char *name)
}

int
+
pkg_addconflict(struct pkg *pkg, const char *name)
+
{
+
	struct pkg_conflict *c = NULL;
+

+
	assert(pkg != NULL);
+
	assert(name != NULL && name[0] != '\0');
+

+
	HASH_FIND_STR(pkg->conflicts, __DECONST(char *, name), c);
+
	/* silently ignore duplicates in case of conflicts */
+
	if (c != NULL)
+
		return (EPKG_OK);
+

+
	pkg_conflict_new(&c);
+
	sbuf_set(&c->origin, name);
+

+
	HASH_ADD_KEYPTR(hh, pkg->conflicts,
+
	    __DECONST(char *, pkg_conflict_origin(c)),
+
	    sbuf_size(c->origin), c);
+

+
	return (EPKG_OK);
+
}
+

+
int
pkg_addannotation(struct pkg *pkg, const char *tag, const char *value)
{
	struct pkg_note *an = NULL;
modified libpkg/pkg.h.in
@@ -609,6 +609,13 @@ int pkg_shlibs_required(const struct pkg *pkg, struct pkg_shlib **shlib);
int pkg_shlibs_provided(const struct pkg *pkg, struct pkg_shlib **shlib);

/**
+
 * Iterates over the conflicts registered in the package.
+
 * @param conflict must be set to NULL for the first call.
+
 * @return An error code
+
 */
+
int pkg_conflicts(const struct pkg *pkg, struct pkg_conflict **conflict);
+

+
/**
 * Iterates over the annotations associated with the package.
 * @param note must be set to NULL for the first call.
 * @return An error code
@@ -785,6 +792,12 @@ int pkg_addshlib_required(struct pkg *pkg, const char *name);
int pkg_addshlib_provided(struct pkg *pkg, const char *name);

/**
+
 * Add a conflict registered with this package
+
 * @return An error code.
+
 */
+
int pkg_addconflict(struct pkg *pkg, const char *name);
+

+
/**
 * Add annotation key+value pair
 * @return An error code
 */
@@ -877,6 +890,9 @@ const char *pkg_option_value(struct pkg_option const * const);
/* pkg_shlib */
const char *pkg_shlib_name(struct pkg_shlib const * const);

+
/* pkg_conflict */
+
const char *pkg_conflict_origin(const struct pkg_conflict *);
+

/* pkg_note */
const char *pkg_annotation_tag(struct pkg_note const * const);
const char *pkg_annotation_value(struct pkg_note const * const);
modified libpkg/pkg_attributes.c
@@ -432,6 +432,37 @@ pkg_shlib_name(struct pkg_shlib const * const sl)
}

/*
+
 * Conflicts
+
 */
+

+
int
+
pkg_conflict_new(struct pkg_conflict **c)
+
{
+
	if ((*c = calloc(1, sizeof(struct pkg_conflict))) == NULL)
+
		return (EPKG_FATAL);
+

+
	return (EPKG_OK);
+
}
+

+
void
+
pkg_conflict_free(struct pkg_conflict *c)
+
{
+
	if (c == NULL)
+
		return;
+

+
	sbuf_free(c->origin);
+
	free(c);
+
}
+

+
const char *
+
pkg_conflict_origin(const struct pkg_conflict *c)
+
{
+
	assert(c != NULL);
+

+
	return (sbuf_get(c->origin));
+
}
+

+
/*
 * Annotations
 */

modified libpkg/pkg_manifest.c
@@ -60,6 +60,7 @@
#define PKG_SHLIBS_PROVIDED -13
#define PKG_ANNOTATIONS -14
#define PKG_INFOS -15		/* Deprecated field: treat as an annotation for backwards compatibility */
+
#define PKG_CONFLICTS -16

static int pkg_set_from_node(struct pkg *, yaml_node_t *, yaml_document_t *, int);
static int pkg_set_size_from_node(struct pkg *, yaml_node_t *, yaml_document_t *, int);
@@ -157,6 +158,7 @@ static struct manifest_key {
	{ "shlibs", PKG_SHLIBS_REQUIRED, YAML_SEQUENCE_NODE, parse_sequence}, /* Backwards compat with 1.0.x packages */
	{ "shlibs_provided", PKG_SHLIBS_PROVIDED, YAML_SEQUENCE_NODE, parse_sequence},
	{ "shlibs_required", PKG_SHLIBS_REQUIRED, YAML_SEQUENCE_NODE, parse_sequence},
+
	{ "conflicts", PKG_CONFLICTS, YAML_SEQUENCE_NODE, parse_sequence},
	{ "sum", PKG_CKSUM, YAML_SCALAR_NODE, pkg_set_from_node},
	{ "users", PKG_USERS, YAML_MAPPING_NODE, parse_mapping},
	{ "users", PKG_USERS, YAML_SEQUENCE_NODE, parse_sequence},
@@ -831,6 +833,12 @@ parse_sequence(struct pkg * pkg, yaml_node_t *node, yaml_document_t *doc,
			else
				pkg_addshlib_provided(pkg, val->data.scalar.value);
			break;
+
		case PKG_CONFLICTS:
+
			if (!is_valid_yaml_scalar(val))
+
				pkg_emit_error("Skipping malformed conflict name");
+
			else
+
				pkg_addconflict(pkg, val->data.scalar.value);
+
			break;
		}
		++item;
	}
@@ -1498,6 +1506,7 @@ emit_manifest(struct pkg *pkg, yaml_emitter_t *emitter, short flags)
	struct pkg_group	*group    = NULL;
	struct pkg_shlib	*shlib    = NULL;
	struct pkg_note		*note     = NULL;
+
	struct pkg_conflict	*conflict = NULL;
	struct sbuf		*tmpsbuf  = NULL;
	int rc = EPKG_OK;
	int mapping;
@@ -1606,6 +1615,11 @@ emit_manifest(struct pkg *pkg, yaml_emitter_t *emitter, short flags)
		manifest_append_seqval(&doc, mapping, &seq, "shlibs_provided",
		    pkg_shlib_name(shlib));

+
	seq = -1;
+
	while (pkg_conflicts(pkg, &conflict) == EPKG_OK)
+
		manifest_append_seqval(&doc, mapping, &seq, "conflicts",
+
		    pkg_conflict_origin(conflict));
+

	map = -1;
	while (pkg_options(pkg, &option) == EPKG_OK) {
		if (map == -1)
modified libpkg/pkg_repo.c
@@ -188,27 +188,16 @@ digest_sort_compare_func(struct digest_list_entry *d1, struct digest_list_entry
}

static void
-
pkg_repo_new_conflict(const char *name, const char *origin,
-
		const char *version, struct pkg_conflict_bulk *bulk, bool need_copy)
+
pkg_repo_new_conflict(const char *origin, struct pkg_conflict_bulk *bulk)
{
	struct pkg_conflict *new;

-
	new = malloc(sizeof(struct pkg_conflict));
-
	if (new == NULL) {
-
		pkg_emit_errno("malloc", "struct pkg_conflict");
-
		return;
-
	}
-
	if (need_copy) {
-
		new->name = strdup(name);
-
		new->version = strdup(version);
-
		new->origin = strdup(origin);
-
	}
-
	else {
-
		new->name = __DECONST(char *, name);
-
		new->version = __DECONST(char *, version);
-
		new->origin = __DECONST(char *, origin);
-
	}
-
	LL_PREPEND(bulk->conflicts, new);
+
	pkg_conflict_new(&new);
+
	sbuf_set(&new->origin, origin);
+

+
	HASH_ADD_KEYPTR(hh, bulk->conflicts,
+
			__DECONST(char *, pkg_conflict_origin(new)),
+
			sbuf_size(new->origin), new);
}

static void
@@ -216,10 +205,10 @@ pkg_repo_insert_conflict(const char *file, struct pkg *pkg,
		sqlite3 *sqlite, struct pkg_conflict_bulk **conflicts)
{
	struct pkg_conflict_bulk	*s;
-
	const char	*name, *origin, *version;
+
	const char	*origin;

	const char package_select_sql[] = ""
-
				"SELECT name,origin,version "
+
				"SELECT origin "
				"FROM packages AS p "
				"LEFT JOIN files AS f ON p.id = f.package_id "
				"WHERE f.file = ?1 GROUP BY p.id"
@@ -232,9 +221,8 @@ pkg_repo_insert_conflict(const char *file, struct pkg *pkg,
		 * If we have a conflict in hash table we just need to add
		 * new package id there.
		 */
-
		pkg_get(pkg, PKG_NAME, &name, PKG_ORIGIN, &origin,
-
					PKG_VERSION, &version);
-
		pkg_repo_new_conflict(name, origin, version, s, true);
+
		pkg_get(pkg, PKG_ORIGIN, &origin);
+
		pkg_repo_new_conflict(origin, s);
	}
	else {
		/*
@@ -265,16 +253,13 @@ pkg_repo_insert_conflict(const char *file, struct pkg *pkg,
			sqlite3_finalize(stmt);
			return;
		}
-
		name = sqlite3_column_text(stmt, 0);
-
		origin = sqlite3_column_text(stmt, 1);
-
		version = sqlite3_column_text(stmt, 2);
-
		pkg_repo_new_conflict(name, origin, version, s, true);
+
		origin = sqlite3_column_text(stmt, 0);
+
		pkg_repo_new_conflict(origin, s);
		sqlite3_finalize(stmt);

		/* Register the second conflicting package */
-
		pkg_get(pkg, PKG_NAME, &name, PKG_ORIGIN, &origin,
-
							PKG_VERSION, &version);
-
		pkg_repo_new_conflict(name, origin, version, s, true);
+
		pkg_get(pkg, PKG_ORIGIN, &origin);
+
		pkg_repo_new_conflict(origin, s);
	}
}

@@ -283,7 +268,7 @@ pkg_repo_check_conflicts(struct pkg *pkg, sqlite3 *sqlite,
		struct pkg_conflict_bulk **conflicts)
{
	sqlite3_stmt	*stmt = NULL;
-
	const char	*name, *origin, *version;
+
	const char	*origin;
	struct pkg_file	*f;
	struct pkg_dir	*d;
	int64_t	package_id;
@@ -291,7 +276,7 @@ pkg_repo_check_conflicts(struct pkg *pkg, sqlite3 *sqlite,

	const char package_insert_sql[] = ""
			"INSERT OR REPLACE INTO packages"
-
			"(name, origin, version)"
+
			"(origin)"
			"VALUES(?1, ?2, ?3)";
	const char file_insert_sql[] = ""
			"INSERT INTO files"
@@ -305,11 +290,8 @@ pkg_repo_check_conflicts(struct pkg *pkg, sqlite3 *sqlite,
	}

	/* Insert a package */
-
	pkg_get(pkg, PKG_NAME, &name, PKG_ORIGIN, &origin,
-
			PKG_VERSION, &version);
-
	sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC);
-
	sqlite3_bind_text(stmt, 2, origin, -1, SQLITE_STATIC);
-
	sqlite3_bind_text(stmt, 3, version, -1, SQLITE_STATIC);
+
	pkg_get(pkg, PKG_ORIGIN, &origin);
+
	sqlite3_bind_text(stmt, 1, origin, -1, SQLITE_STATIC);
	if (sqlite3_step(stmt) != SQLITE_DONE) {
		ERROR_SQLITE(sqlite);
		sqlite3_finalize(stmt);
@@ -360,7 +342,7 @@ static void
pkg_repo_write_conflicts (struct pkg_conflict_bulk *bulk, FILE *out)
{
	struct pkg_conflict_bulk	*pkg_bulk = NULL, *cur, *tmp, *s;
-
	struct pkg_conflict	*c1, *c2, *ctmp;
+
	struct pkg_conflict	*c1, *c1tmp, *c2, *c2tmp, *ctmp;
	bool new;

	/*
@@ -370,8 +352,8 @@ pkg_repo_write_conflicts (struct pkg_conflict_bulk *bulk, FILE *out)
	 */

	HASH_ITER (hh, bulk, cur, tmp) {
-
		LL_FOREACH(cur->conflicts, c1) {
-
			HASH_FIND_STR(pkg_bulk, c1->origin, s);
+
		HASH_ITER (hh, cur->conflicts, c1, c1tmp) {
+
			HASH_FIND_STR(pkg_bulk, sbuf_get(c1->origin), s);
			if (s == NULL) {
				/* New entry required */
				s = malloc(sizeof(struct pkg_conflict_bulk));
@@ -380,42 +362,37 @@ pkg_repo_write_conflicts (struct pkg_conflict_bulk *bulk, FILE *out)
					goto out;
				}
				memset(s, 0, sizeof(struct pkg_conflict_bulk));
-
				s->file = c1->origin;
+
				s->file = sbuf_get(c1->origin);
				HASH_ADD_KEYPTR(hh, pkg_bulk, s->file, strlen(s->file), s);
			}
			/* Now add all new entries from this file to this conflict structure */
-
			LL_FOREACH(cur->conflicts, c2) {
+
			HASH_ITER (hh, cur->conflicts, c2, c2tmp) {
				new = true;
-
				if (strcmp(c1->origin, c2->origin) == 0)
+
				if (strcmp(sbuf_get(c1->origin), sbuf_get(c2->origin)) == 0)
					continue;

-
				LL_FOREACH(s->conflicts, ctmp) {
-
					if (strcmp(ctmp->origin, c2->origin) == 0)
-
						new = false;
-
				}
-
				if (new)
-
					pkg_repo_new_conflict(c2->name, c2->origin, c2->version,
-
							s, false);
+
				HASH_FIND_STR(s->conflicts, sbuf_get(c2->origin), ctmp);
+
				if (s == NULL)
+
					pkg_repo_new_conflict(sbuf_get(c2->origin), s);
			}
		}
	}

	HASH_ITER (hh, pkg_bulk, cur, tmp) {
		fprintf(out, "%s:", cur->file);
-
		LL_FOREACH(cur->conflicts, c1) {
-
			if (c1->next != NULL)
-
				fprintf(out, "%s,", c1->origin);
+
		HASH_ITER (hh, cur->conflicts, c1, c1tmp) {
+
			if (c1->hh.next != NULL)
+
				fprintf(out, "%s,", sbuf_get(c1->origin));
			else
-
				fprintf(out, "%s\n", c1->origin);
+
				fprintf(out, "%s\n", sbuf_get(c1->origin));
		}
	}
out:
	HASH_ITER (hh, pkg_bulk, cur, tmp) {
-
		c1 = cur->conflicts;
-
		while (c1 != NULL) {
-
			ctmp = c1;
-
			c1 = c1->next;
-
			free (ctmp);
+
		HASH_ITER (hh, cur->conflicts, c1, c1tmp) {
+
			HASH_DEL(cur->conflicts, c1);
+
			sbuf_free(c1->origin);
+
			free(c1);
		}
		HASH_DEL(pkg_bulk, cur);
		free(cur);
@@ -630,14 +607,10 @@ cleanup:
		retcode = EPKG_FATAL;
	}
	HASH_ITER (hh, conflicts, curcb, tmpcb) {
-
		c = curcb->conflicts;
-
		while (c != NULL) {
-
			free(c->name);
-
			free(c->origin);
-
			free(c->version);
-
			ctmp = c;
-
			c = c->next;
-
			free(ctmp);
+
		HASH_ITER (hh, curcb->conflicts, c, ctmp) {
+
			sbuf_free(c->origin);
+
			HASH_DEL(curcb->conflicts, c);
+
			free(c);
		}
		HASH_DEL(conflicts, curcb);
		free(curcb);
modified libpkg/private/pkg.h
@@ -146,10 +146,8 @@ struct pkg_dep {
};

struct pkg_conflict {
-
	char	*origin;
-
	char	*name;
-
	char	*version;
-
	struct pkg_conflict *next;
+
	struct sbuf		*origin;
+
	UT_hash_handle	hh;
};

struct pkg_license {
@@ -355,6 +353,9 @@ int pkg_jobs_resolv(struct pkg_jobs *jobs);
int pkg_shlib_new(struct pkg_shlib **);
void pkg_shlib_free(struct pkg_shlib *);

+
int pkg_conflict_new(struct pkg_conflict **);
+
void pkg_conflict_free(struct pkg_conflict *);
+

int pkg_annotation_new(struct pkg_note **);
void pkg_annotation_free(struct pkg_note *);

modified libpkg/private/utils.h
@@ -76,6 +76,7 @@ int sbuf_set(struct sbuf **, const char *);
char * sbuf_get(struct sbuf *);
void sbuf_reset(struct sbuf *);
void sbuf_free(struct sbuf *);
+
ssize_t sbuf_size(struct sbuf *);

int mkdirs(const char *path);
int file_to_buffer(const char *, char **, off_t *);
modified libpkg/utils.c
@@ -91,6 +91,15 @@ sbuf_free(struct sbuf *buf)
		sbuf_delete(buf);
}

+
ssize_t
+
sbuf_size(struct sbuf *buf)
+
{
+
	if (buf != NULL)
+
		return sbuf_len(buf);
+

+
	return 0;
+
}
+

int
mkdirs(const char *_path)
{