Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge categories, licenses, annotations into pkg->fields
Baptiste Daroussin committed 12 years ago
commit 4feccaf4cd5a127b6c6a021d5b2cefe972b3001b
parent d15f025
14 files changed +133 -155
modified libpkg/pkg.c
@@ -89,11 +89,12 @@ pkg_reset(struct pkg *pkg, pkg_t type)

	ucl_object_unref(pkg->fields);
	pkg->fields = ucl_object_typed_new(UCL_OBJECT);
+
	pkg->flags &= ~PKG_LOAD_CATEGORIES;
+
	pkg->flags &= ~PKG_LOAD_LICENSES;
+
	pkg->flags &= ~PKG_LOAD_ANNOTATIONS;

	for (i = 0; i < PKG_NUM_SCRIPTS; i++)
		sbuf_reset(pkg->scripts[i]);
-
	pkg_list_free(pkg, PKG_LICENSES);
-
	pkg_list_free(pkg, PKG_CATEGORIES);
	pkg_list_free(pkg, PKG_DEPS);
	pkg_list_free(pkg, PKG_RDEPS);
	pkg_list_free(pkg, PKG_FILES);
@@ -103,7 +104,6 @@ pkg_reset(struct pkg *pkg, pkg_t type)
	pkg_list_free(pkg, PKG_GROUPS);
	pkg_list_free(pkg, PKG_SHLIBS_REQUIRED);
	pkg_list_free(pkg, PKG_SHLIBS_PROVIDED);
-
	pkg_list_free(pkg, PKG_ANNOTATIONS);

	pkg->type = type;
}
@@ -119,8 +119,6 @@ pkg_free(struct pkg *pkg)
	for (int i = 0; i < PKG_NUM_SCRIPTS; i++)
		sbuf_free(pkg->scripts[i]);

-
	pkg_list_free(pkg, PKG_LICENSES);
-
	pkg_list_free(pkg, PKG_CATEGORIES);
	pkg_list_free(pkg, PKG_DEPS);
	pkg_list_free(pkg, PKG_RDEPS);
	pkg_list_free(pkg, PKG_FILES);
@@ -130,7 +128,6 @@ pkg_free(struct pkg *pkg)
	pkg_list_free(pkg, PKG_GROUPS);
	pkg_list_free(pkg, PKG_SHLIBS_REQUIRED);
	pkg_list_free(pkg, PKG_SHLIBS_PROVIDED);
-
	pkg_list_free(pkg, PKG_ANNOTATIONS);

	free(pkg);
}
@@ -190,6 +187,10 @@ pkg_vget(const struct pkg * restrict pkg, va_list ap)
			}
			*va_arg(ap, int64_t *) = ucl_object_toint(obj);
			break;
+
		case UCL_OBJECT:
+
		case UCL_ARRAY:
+
			*va_arg(ap, const pkg_object **) = obj;
+
			break;
		default:
			va_arg(ap, void *); /* ignore */
			break;
@@ -222,7 +223,7 @@ pkg_vset(struct pkg *pkg, va_list ap)
	char *buf = NULL;
	const char *data;
	const char *str;
-

+
	ucl_object_t *o;

	while ((attr = va_arg(ap, int)) > 0) {
		if (attr >= PKG_NUM_FIELDS || attr <= 0) {
@@ -271,6 +272,12 @@ pkg_vset(struct pkg *pkg, va_list ap)
			    pkg_keys[attr].name, strlen(pkg_keys[attr].name), false))
				return (EPKG_FATAL);
			break;
+
		case UCL_OBJECT:
+
		case UCL_ARRAY:
+
			o = va_arg(ap, ucl_object_t *);
+
			if (!ucl_object_replace_key(pkg->fields, o,
+
			    pkg_keys[attr].name, strlen(pkg_keys[attr].name), false))
+
					return (EPKG_FATAL);
		default:
			(void) va_arg(ap, void *);
			break;
@@ -428,14 +435,16 @@ pkg_provides(const struct pkg *pkg, struct pkg_provide **c)
int
pkg_addlicense(struct pkg *pkg, const char *name)
{
-
	const pkg_object *o;
-
	pkg_object *l;
+
	const pkg_object *o, *licenses;
+
	pkg_object *l, *lic;
	pkg_iter iter = NULL;

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

-
	while ((o = pkg_object_iterate(pkg->licenses, &iter))) {
+
	pkg_get(pkg, PKG_LICENSES, &licenses);
+

+
	while ((o = pkg_object_iterate(licenses, &iter))) {
		if (strcmp(pkg_object_string(o), name) == 0) {
			if (pkg_object_bool(pkg_config_get("DEVELOPER_MODE"))) {
				pkg_emit_error("duplicate license listing: %s, fatal (developer mode)", name);
@@ -447,10 +456,13 @@ pkg_addlicense(struct pkg *pkg, const char *name)
		}
	}

+
	pkg_get(pkg, PKG_LICENSES, &lic);
	l = ucl_object_fromstring_common(name, strlen(name), 0);
-
	if (pkg->licenses == NULL)
-
		pkg->licenses = ucl_object_typed_new(UCL_ARRAY);
-
	ucl_array_append(pkg->licenses, l);
+
	if (lic == NULL) {
+
		lic = ucl_object_typed_new(UCL_ARRAY);
+
		pkg_set(pkg, PKG_LICENSES, lic);
+
	}
+
	ucl_array_append(lic, l);

	return (EPKG_OK);
}
@@ -647,14 +659,15 @@ pkg_addfile_attr(struct pkg *pkg, const char *path, const char *sha256, const ch
int
pkg_addcategory(struct pkg *pkg, const char *name)
{
-
	const pkg_object *o;
-
	pkg_object *c;
+
	const pkg_object *o, *categories;
+
	pkg_object *c, *cat;
	pkg_iter iter = NULL;

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

-
	while ((o = (pkg_object_iterate(pkg->categories, &iter)))) {
+
	pkg_get(pkg, PKG_CATEGORIES, &categories);
+
	while ((o = (pkg_object_iterate(categories, &iter)))) {
		if (strcmp(pkg_object_string(o), name) == 0) {
			if (pkg_object_bool(pkg_config_get("DEVELOPER_MODE"))) {
				pkg_emit_error("duplicate category listing: %s, fatal (developer mode)", name);
@@ -666,10 +679,13 @@ pkg_addcategory(struct pkg *pkg, const char *name)
		}
	}

+
	pkg_get(pkg, PKG_CATEGORIES, &cat);
	c = ucl_object_fromstring_common(name, strlen(name), 0);
-
	if (pkg->categories == NULL)
-
		pkg->categories = ucl_object_typed_new(UCL_ARRAY);
-
	ucl_array_append(pkg->categories, c);
+
	if (cat == NULL) {
+
		cat = ucl_object_typed_new(UCL_ARRAY);
+
		pkg_set(pkg, PKG_CATEGORIES, cat);
+
	}
+
	ucl_array_append(cat, c);

	return (EPKG_OK);
}
@@ -1024,8 +1040,8 @@ pkg_addprovide(struct pkg *pkg, const char *name)
int
pkg_addannotation(struct pkg *pkg, const char *tag, const char *value)
{
-
	const ucl_object_t *an;
-
	ucl_object_t *o;
+
	const ucl_object_t *an, *notes;
+
	ucl_object_t *o, *annotations;

	assert(pkg != NULL);
	assert(tag != NULL);
@@ -1033,7 +1049,8 @@ pkg_addannotation(struct pkg *pkg, const char *tag, const char *value)

	/* Tags are unique per-package */

-
	an = ucl_object_find_key(pkg->annotations, tag);
+
	pkg_get(pkg, PKG_ANNOTATIONS, &notes);
+
	an = pkg_object_find(notes, tag);
	if (an != NULL) {
		if (pkg_object_bool(pkg_config_get("DEVELOPER_MODE"))) {
			pkg_emit_error("duplicate annotation tag: %s value: %s,"
@@ -1046,55 +1063,26 @@ pkg_addannotation(struct pkg *pkg, const char *tag, const char *value)
		}
	}
	o = ucl_object_fromstring_common(value, strlen(value), 0);
-
	if (pkg->annotations == NULL)
-
		pkg->annotations = ucl_object_typed_new(UCL_OBJECT);
-
	ucl_object_insert_key(pkg->annotations, o, tag, strlen(tag), true);
+
	pkg_get(pkg, PKG_ANNOTATIONS, &annotations);
+
	if (annotations == NULL) {
+
		annotations = ucl_object_typed_new(UCL_OBJECT);
+
		pkg_set(pkg, PKG_ANNOTATIONS, annotations);
+
	}
+
	ucl_object_insert_key(annotations, o, tag, strlen(tag), true);

	return (EPKG_OK);
}

-
const pkg_object *
-
pkg_licenses(const struct pkg *pkg)
-
{
-
	assert (pkg != NULL);
-

-
	return (pkg->licenses);
-
}
-

-
const pkg_object *
-
pkg_categories(const struct pkg *pkg)
-
{
-
	assert (pkg != NULL);
-

-
	return (pkg->categories);
-
}
-

-
const pkg_object *
-
pkg_annotations(const struct pkg *pkg)
-
{
-
	assert(pkg != NULL);
-

-
	return (pkg->annotations);
-
}
-

-
const pkg_object *
-
pkg_annotation_lookup(const struct pkg *pkg, const char *tag)
-
{
-
	assert(pkg != NULL);
-
	assert(tag != NULL);
-

-
	return (ucl_object_find_key(pkg->annotations, tag));
-
}
-

int
pkg_delannotation(struct pkg *pkg, const char *tag)
{
-
	ucl_object_t *an;
+
	ucl_object_t *an, *notes;

	assert(pkg != NULL);
	assert(tag != NULL);

-
	an = ucl_object_pop_keyl(pkg->annotations, tag, strlen(tag));
+
	pkg_get(pkg, PKG_ANNOTATIONS, &notes);
+
	an = ucl_object_pop_keyl(notes, tag, strlen(tag));
	if (an != NULL) {
		ucl_object_unref(an);
		return (EPKG_OK);
@@ -1113,12 +1101,8 @@ pkg_list_count(const struct pkg *pkg, pkg_list list)
		return (HASH_COUNT(pkg->deps));
	case PKG_RDEPS:
		return (HASH_COUNT(pkg->rdeps));
-
	case PKG_LICENSES:
-
		return (UCL_COUNT(pkg->licenses));
	case PKG_OPTIONS:
		return (HASH_COUNT(pkg->options));
-
	case PKG_CATEGORIES:
-
		return (UCL_COUNT(pkg->categories));
	case PKG_FILES:
		return (HASH_COUNT(pkg->files));
	case PKG_DIRS:
@@ -1131,8 +1115,6 @@ pkg_list_count(const struct pkg *pkg, pkg_list list)
		return (HASH_COUNT(pkg->shlibs_required));
	case PKG_SHLIBS_PROVIDED:
		return (HASH_COUNT(pkg->shlibs_provided));
-
	case PKG_ANNOTATIONS:
-
		return (UCL_COUNT(pkg->annotations));
	case PKG_CONFLICTS:
		return (HASH_COUNT(pkg->conflicts));
	case PKG_PROVIDES:
@@ -1153,24 +1135,10 @@ pkg_list_free(struct pkg *pkg, pkg_list list) {
		HASH_FREE(pkg->rdeps, pkg_dep_free);
		pkg->flags &= ~PKG_LOAD_RDEPS;
		break;
-
	case PKG_LICENSES:
-
		if (pkg->licenses != NULL) {
-
			ucl_object_unref(pkg->licenses);
-
			pkg->licenses = NULL;
-
		}
-
		pkg->flags &= ~PKG_LOAD_LICENSES;
-
		break;
	case PKG_OPTIONS:
		HASH_FREE(pkg->options, pkg_option_free);
		pkg->flags &= ~PKG_LOAD_OPTIONS;
		break;
-
	case PKG_CATEGORIES:
-
		if (pkg->categories != NULL) {
-
			ucl_object_unref(pkg->categories);
-
			pkg->categories = NULL;
-
		}
-
		pkg->flags &= ~PKG_LOAD_CATEGORIES;
-
		break;
	case PKG_FILES:
		HASH_FREE(pkg->files, pkg_file_free);
		pkg->flags &= ~PKG_LOAD_FILES;
@@ -1195,13 +1163,6 @@ pkg_list_free(struct pkg *pkg, pkg_list list) {
		HASH_FREE(pkg->shlibs_provided, pkg_shlib_free);
		pkg->flags &= ~PKG_LOAD_SHLIBS_PROVIDED;
		break;
-
	case PKG_ANNOTATIONS:
-
		if (pkg->annotations != NULL) {
-
			ucl_object_unref(pkg->annotations);
-
			pkg->annotations = NULL;
-
		}
-
		pkg->flags &= ~PKG_LOAD_ANNOTATIONS;
-
		break;
	case PKG_CONFLICTS:
		HASH_FREE(pkg->conflicts, pkg_conflict_free);
		pkg->flags &= ~PKG_LOAD_CONFLICTS;
modified libpkg/pkg.h.in
@@ -246,6 +246,9 @@ typedef enum {
	PKG_LOCKED,
	PKG_ROWID,
	PKG_TIME,
+
	PKG_ANNOTATIONS,
+
	PKG_LICENSES,
+
	PKG_CATEGORIES,
	PKG_NUM_FIELDS, 	/* end of fields */
} pkg_attr;

@@ -283,16 +286,13 @@ typedef enum {
typedef enum {
	PKG_DEPS = 0,
	PKG_RDEPS,
-
	PKG_LICENSES,
	PKG_OPTIONS,
-
	PKG_CATEGORIES,
	PKG_FILES,
	PKG_DIRS,
	PKG_USERS,
	PKG_GROUPS,
	PKG_SHLIBS_REQUIRED,
	PKG_SHLIBS_PROVIDED,
-
	PKG_ANNOTATIONS,
	PKG_CONFLICTS,
	PKG_PROVIDES
} pkg_list;
@@ -580,9 +580,6 @@ int pkg_files(const struct pkg *, struct pkg_file **file);
 */
int pkg_dirs(const struct pkg *pkg, struct pkg_dir **dir);

-
const pkg_object *pkg_categories(const struct pkg *pkg);
-
const pkg_object *pkg_licenses(const struct pkg *pkg);
-

/**
 * Iterates over the users of the package.
 * @param Must be set to NULL for the first call.
@@ -633,14 +630,6 @@ int pkg_conflicts(const struct pkg *pkg, struct pkg_conflict **conflict);
int pkg_provides(const struct pkg *pkg, struct pkg_provide **provide);

/**
-
 * Iterates over the annotations associated with the package.
-
 * @param note must be set to NULL for the first call.
-
 * @return An error code
-
 */
-
const pkg_object *pkg_annotation_lookup(const struct pkg *p, const char *tag);
-
const pkg_object *pkg_annotations(const struct pkg *p);
-

-
/**
 * Iterate over all of the files within the package pkg, ensuring the
 * dependency list contains all applicable packages providing the
 * shared objects used by pkg.
modified libpkg/pkg_create.c
@@ -54,14 +54,15 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
	struct stat	 st;
	char		 sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	int64_t		 flatsize = 0;
-
	const ucl_object_t	*obj;
+
	const ucl_object_t	*obj, *an;

	if (pkg_is_valid(pkg) != EPKG_OK) {
		pkg_emit_error("the package is not valid");
		return (EPKG_FATAL);
	}

-
	obj = pkg_annotation_lookup(pkg, "relocated");
+
	pkg_get(pkg, PKG_ANNOTATIONS, &an);
+
	obj = pkg_object_find(an, "relocated");

	/*
	 * Get / compute size / checksum if not provided in the manifest
modified libpkg/pkg_delete.c
@@ -144,13 +144,14 @@ pkg_delete_files(struct pkg *pkg, unsigned force)

	while (pkg_files(pkg, &file) == EPKG_OK) {
		const char *sum = pkg_file_cksum(file);
-
		const ucl_object_t *obj;
+
		const ucl_object_t *obj, *an;

		if (file->keep == 1)
			continue;

		path = pkg_file_path(file);
-
		obj = pkg_annotation_lookup(pkg, "relocated");
+
		pkg_get(pkg, PKG_ANNOTATIONS, &an);
+
		obj = pkg_object_find(an, "relocated");
		snprintf(fpath, sizeof(fpath), "%s%s",
		    obj ? pkg_object_string(obj) : "" , path );

@@ -180,14 +181,15 @@ int
pkg_delete_dirs(__unused struct pkgdb *db, struct pkg *pkg, bool force)
{
	struct pkg_dir		*dir = NULL;
-
	const ucl_object_t 	*obj;
+
	const ucl_object_t 	*obj, *an;
	char			 fpath[MAXPATHLEN];

	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
		if (dir->keep == 1)
			continue;

-
		obj = pkg_annotation_lookup(pkg, "relocated");
+
		pkg_get(pkg, PKG_ANNOTATIONS, &an);
+
		obj = pkg_object_find(an, "relocated");
		snprintf(fpath, sizeof(fpath), "%s%s",
		    obj ? pkg_object_string(obj) : "" , pkg_dir_path(dir) );

modified libpkg/pkg_jobs.c
@@ -1236,7 +1236,7 @@ static bool
newer_than_local_pkg(struct pkg_jobs *j, struct pkg *rp, bool force)
{
	char *origin, *newversion, *oldversion, *reponame;
-
	const ucl_object_t *an;
+
	const ucl_object_t *an, *obj;
	int64_t oldsize;
	struct pkg *lp;
	bool automatic;
@@ -1253,10 +1253,11 @@ newer_than_local_pkg(struct pkg_jobs *j, struct pkg *rp, bool force)
	pkg_jobs_add_universe(j, lp, true, false, NULL);
	pkg_get(lp, PKG_AUTOMATIC, &automatic,
	    PKG_VERSION, &oldversion,
-
	    PKG_FLATSIZE, &oldsize);
+
	    PKG_FLATSIZE, &oldsize,
+
	    PKG_ANNOTATIONS, &obj);

	/* Add repo name to the annotation */
-
	an = pkg_annotation_lookup(lp, "repository");
+
	an = pkg_object_find(obj, "repository");
	if (an != NULL)  {
		if (strcmp(pkg_repo_ident(pkg_repo_find_name(reponame)),
		    ucl_object_tostring(an)) != 0)  {
@@ -1849,7 +1850,7 @@ pkg_jobs_handle_install(struct pkg_solved *ps, struct pkg_jobs *j, bool handle_r
{
	struct pkg *new, *old;
	const char *pkgorigin, *oldversion = NULL;
-
	const ucl_object_t *an;
+
	const ucl_object_t *an, *obj;
	char path[MAXPATHLEN], *target;
	bool automatic = false;
	int flags = 0;
@@ -1858,13 +1859,13 @@ pkg_jobs_handle_install(struct pkg_solved *ps, struct pkg_jobs *j, bool handle_r
	old = ps->items[1] ? ps->items[1]->pkg : NULL;
	new = ps->items[0]->pkg;

-
	pkg_get(new, PKG_ORIGIN, &pkgorigin);
+
	pkg_get(new, PKG_ORIGIN, &pkgorigin, PKG_ANNOTATIONS, &obj);
	if (old != NULL)
		pkg_get(old, PKG_VERSION, &oldversion, PKG_AUTOMATIC, &automatic);
	else if (!new->direct)
		automatic = true;

-
	an = pkg_annotation_lookup(new, "repository");
+
	an = pkg_object_find(obj, "repository");

	if (ps->items[0]->jp != NULL && ps->items[0]->jp->is_file) {
		/*
modified libpkg/pkg_manifest.c
@@ -46,8 +46,6 @@
#define PKG_FILES		-3
#define PKG_DIRS		-4
#define PKG_SCRIPTS		-5
-
#define PKG_CATEGORIES		-6
-
#define PKG_LICENSES		-7
#define PKG_OPTIONS		-8
#define PKG_OPTION_DEFAULTS	-9
#define PKG_OPTION_DESCRIPTIONS	-10
@@ -56,7 +54,6 @@
#define PKG_DIRECTORIES		-13
#define PKG_SHLIBS_REQUIRED	-14
#define PKG_SHLIBS_PROVIDED	-15
-
#define PKG_ANNOTATIONS		-16
#define PKG_CONFLICTS		-17
#define PKG_PROVIDES		-18

@@ -859,6 +856,7 @@ emit_manifest(struct pkg *pkg, struct sbuf **out, short flags)
	const char *script_types = NULL;
	lic_t licenselogic;
	int64_t flatsize, pkgsize;
+
	ucl_object_t *annotations, *categories, *licenses;
	ucl_object_t *map, *seq, *submap;
	ucl_object_t *top = ucl_object_typed_new(UCL_OBJECT);

@@ -868,7 +866,9 @@ emit_manifest(struct pkg *pkg, struct sbuf **out, short flags)
	    PKG_LICENSE_LOGIC, &licenselogic, PKG_DESC, &desc,
	    PKG_FLATSIZE, &flatsize, PKG_MESSAGE, &message,
	    PKG_VERSION, &version, PKG_REPOPATH, &repopath,
-
	    PKG_CKSUM, &pkgsum, PKG_PKGSIZE, &pkgsize);
+
	    PKG_CKSUM, &pkgsum, PKG_PKGSIZE, &pkgsize,
+
	    PKG_ANNOTATIONS, &annotations, PKG_LICENSES, &licenses,
+
	    PKG_CATEGORIES, &categories);

	pkg_debug(4, "Emitting basic metadata");
	if (name)
@@ -905,9 +905,9 @@ emit_manifest(struct pkg *pkg, struct sbuf **out, short flags)
	}

	pkg_debug(4, "Emitting licenses");
-
	if (pkg->licenses != NULL)
+
	if (licenses != NULL)
		ucl_object_insert_key(top,
-
		    ucl_object_ref(pkg->licenses), "licenses", 8, false);
+
		    ucl_object_ref(licenses), "licenses", 8, false);

	ucl_object_insert_key(top, ucl_object_fromint(flatsize), "flatsize", 8, false);
	if (pkgsize > 0)
@@ -932,9 +932,9 @@ emit_manifest(struct pkg *pkg, struct sbuf **out, short flags)
		ucl_object_insert_key(top, map, "deps", 4, false);

	pkg_debug(4, "Emitting categories");
-
	if (pkg->categories != NULL)
+
	if (categories != NULL)
		ucl_object_insert_key(top,
-
		    ucl_object_ref(pkg->categories), "categories", 10, false);
+
		    ucl_object_ref(categories), "categories", 10, false);

	pkg_debug(4, "Emitting users");
	seq = NULL;
@@ -1013,12 +1013,12 @@ emit_manifest(struct pkg *pkg, struct sbuf **out, short flags)
	if (map)
		ucl_object_insert_key(top, map, "options", 7, false);

-
	if (pkg->annotations != NULL) {
+
	if (annotations != NULL) {
		/* Remove internal only annotations */
-
		ucl_object_delete_keyl(pkg->annotations, "repository", 10);
-
		ucl_object_delete_keyl(pkg->annotations, "relocated", 9);
+
		ucl_object_delete_keyl(annotations, "repository", 10);
+
		ucl_object_delete_keyl(annotations, "relocated", 9);
		ucl_object_insert_key(top,
-
		    ucl_object_ref(pkg->annotations), "annotations", 11, false);
+
		    ucl_object_ref(annotations), "annotations", 11, false);
	}

	if ((flags & PKG_MANIFEST_EMIT_COMPACT) == 0) {
modified libpkg/pkg_object.c
@@ -126,5 +126,8 @@ pkg_object_count(const pkg_object *o)
const pkg_object *
pkg_object_find(const pkg_object *o, const char *key)
{
+
	if (o == NULL)
+
		return (NULL);
+

	return (ucl_object_find_key(o, key));
}
modified libpkg/pkg_printf.c
@@ -835,9 +835,11 @@ struct sbuf *
format_annotations(struct sbuf *sbuf, const void *data, struct percent_esc *p)
{
	const struct pkg	*pkg = data;
+
	const pkg_object	*an;

+
	pkg_get(pkg, PKG_ANNOTATIONS, &an);
	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
-
		return (list_count(sbuf, pkg_list_count(pkg, PKG_ANNOTATIONS), p));
+
		return (list_count(sbuf, pkg_object_count(an), p));
	else {
		const pkg_object	*note;
		pkg_iter		it = NULL;
@@ -846,7 +848,7 @@ format_annotations(struct sbuf *sbuf, const void *data, struct percent_esc *p)
		set_list_defaults(p, "%An: %Av\n", "");

		count = 1;
-
		while ((note = pkg_object_iterate(pkg->annotations, &it))) {
+
		while ((note = pkg_object_iterate(an, &it))) {
			if (count > 1)
				iterate_item(sbuf, pkg, sbuf_data(p->sep_fmt),
					     note, count, PP_A);
@@ -935,10 +937,12 @@ struct sbuf *
format_categories(struct sbuf *sbuf, const void *data, struct percent_esc *p)
{
	const struct pkg	*pkg = data;
+
	const pkg_object	*obj;
+

+
	pkg_get(pkg, PKG_CATEGORIES, &obj);

	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
-
		return (list_count(sbuf, pkg_list_count(pkg, PKG_CATEGORIES),
-
				   p));
+
		return (list_count(sbuf, pkg_object_count(obj), p));
	else {
		const pkg_object	*cat;
		pkg_iter		 it = NULL;
@@ -947,7 +951,7 @@ format_categories(struct sbuf *sbuf, const void *data, struct percent_esc *p)
		set_list_defaults(p, "%Cn", ", ");

		count = 1;
-
		while ((cat = pkg_object_iterate(pkg->categories, &it))) {
+
		while ((cat = pkg_object_iterate(obj, &it))) {
			if (count > 1)
				iterate_item(sbuf, pkg, sbuf_data(p->sep_fmt),
					     cat, count, PP_C);
@@ -1248,10 +1252,12 @@ struct sbuf *
format_licenses(struct sbuf *sbuf, const void *data, struct percent_esc *p)
{
	const struct pkg	*pkg = data;
+
	const pkg_object	*obj;
+

+
	pkg_get(pkg, PKG_LICENSES, &obj);

	if (p->flags & (PP_ALTERNATE_FORM1|PP_ALTERNATE_FORM2))
-
		return (list_count(sbuf, pkg_object_count(pkg_licenses(pkg)),
-
				   p));
+
		return (list_count(sbuf, pkg_object_count(obj), p));
	else {
		const pkg_object	*lic;
		pkg_iter		 iter = NULL;
@@ -1260,7 +1266,7 @@ format_licenses(struct sbuf *sbuf, const void *data, struct percent_esc *p)
		set_list_defaults(p, "%Ln", " %l ");

		count = 1;
-
		while ((lic = pkg_object_iterate(pkg->licenses, &iter))) {
+
		while ((lic = pkg_object_iterate(obj, &iter))) {
			if (count > 1)
				iterate_item(sbuf, pkg, sbuf_data(p->sep_fmt),
					     lic, count, PP_L);
modified libpkg/pkgdb.c
@@ -2615,6 +2615,8 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forced)
	lic_t			 licenselogic;
	int64_t			 flatsize;

+
	const pkg_object	*licenses, *categories;
+

	assert(db != NULL);

	if (pkg_is_valid(pkg) != EPKG_OK) {
@@ -2645,7 +2647,9 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forced)
		PKG_AUTOMATIC,	&automatic,
		PKG_LICENSE_LOGIC, &licenselogic,
		PKG_NAME,	&name,
-
		PKG_DIGEST,	&digest);
+
		PKG_DIGEST,	&digest,
+
		PKG_LICENSES,	&licenses,
+
		PKG_CATEGORIES,	&categories);

	/*
	 * Insert mtree record
@@ -2785,7 +2789,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forced)
	 */

	iter = NULL;
-
	while ((obj = pkg_object_iterate(pkg->categories, &iter))) {
+
	while ((obj = pkg_object_iterate(categories, &iter))) {
		ret = run_prstmt(CATEGORY1, pkg_object_string(obj));
		if (ret == SQLITE_DONE)
			ret = run_prstmt(CATEGORY2, package_id, pkg_object_string(obj));
@@ -2800,7 +2804,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg, int complete, int forced)
	 */

	iter = NULL;
-
	while ((obj = pkg_object_iterate(pkg->licenses, &iter))) {
+
	while ((obj = pkg_object_iterate(licenses, &iter))) {
		if (run_prstmt(LICENSES1, pkg_object_string(obj))
		    != SQLITE_DONE
		    ||
@@ -2982,10 +2986,11 @@ pkgdb_update_provides(struct pkg *pkg, int64_t package_id, sqlite3 *s)
int
pkgdb_insert_annotations(struct pkg *pkg, int64_t package_id, sqlite3 *s)
{
-
	const pkg_object	*note;
+
	const pkg_object	*note, *annotations;
	pkg_iter		 it = NULL;

-
	while ((note = pkg_object_iterate(pkg->annotations, &it))) {
+
	pkg_get(pkg, PKG_ANNOTATIONS, &annotations);
+
	while ((note = pkg_object_iterate(annotations, &it))) {
		if (run_prstmt(ANNOTATE1, pkg_object_key(note))
		    != SQLITE_DONE
		    ||
modified libpkg/pkgdb_repo.c
@@ -474,7 +474,7 @@ pkgdb_repo_add_package(struct pkg *pkg, const char *pkg_path,
	struct pkg_dep		*dep      = NULL;
	struct pkg_option	*option   = NULL;
	struct pkg_shlib	*shlib    = NULL;
-
	const pkg_object	*obj;
+
	const pkg_object	*obj, *licenses, *categories, *annotations;
	pkg_iter		 it;
	int64_t			 package_id;

@@ -484,7 +484,9 @@ pkgdb_repo_add_package(struct pkg *pkg, const char *pkg_path,
			    PKG_MAINTAINER, &maintainer, PKG_WWW, &www,
			    PKG_PREFIX, &prefix, PKG_FLATSIZE, &flatsize,
			    PKG_LICENSE_LOGIC, &licenselogic, PKG_CKSUM, &sum,
-
			    PKG_PKGSIZE, &pkgsize, PKG_REPOPATH, &rpath);
+
			    PKG_PKGSIZE, &pkgsize, PKG_REPOPATH, &rpath,
+
			    PKG_LICENSES, &licenses, PKG_CATEGORIES, &categories,
+
			    PKG_ANNOTATIONS, &annotations);

try_again:
	if ((ret = run_prepared_statement(PKG, origin, name, version,
@@ -525,7 +527,7 @@ try_again:
	}

	it = NULL;
-
	while ((obj = pkg_object_iterate(pkg->categories, &it))) {
+
	while ((obj = pkg_object_iterate(categories, &it))) {
		ret = run_prepared_statement(CAT1, pkg_object_string(obj));
		if (ret == SQLITE_DONE)
			ret = run_prepared_statement(CAT2, package_id,
@@ -538,7 +540,7 @@ try_again:
	}

	it = NULL;
-
	while ((obj = pkg_object_iterate(pkg->licenses, &it))) {
+
	while ((obj = pkg_object_iterate(licenses, &it))) {
		ret = run_prepared_statement(LIC1, pkg_object_string(obj));
		if (ret == SQLITE_DONE)
			ret = run_prepared_statement(LIC2, package_id,
@@ -589,7 +591,7 @@ try_again:
	}

	it = NULL;
-
	while ((obj = pkg_object_iterate(pkg->annotations, &it))) {
+
	while ((obj = pkg_object_iterate(annotations, &it))) {
		const char *note_tag = pkg_object_key(obj);
		const char *note_val = pkg_object_string(obj);

modified libpkg/private/pkg.h
@@ -112,8 +112,6 @@ struct pkg {
	ucl_object_t	*fields;
	bool		 direct;
	struct sbuf	*scripts[PKG_NUM_SCRIPTS];
-
	ucl_object_t		*licenses;
-
	ucl_object_t		*categories;
	struct pkg_dep		*deps;
	struct pkg_dep		*rdeps;
	struct pkg_file		*files;
@@ -123,7 +121,6 @@ struct pkg {
	struct pkg_group	*groups;
	struct pkg_shlib	*shlibs_required;
	struct pkg_shlib	*shlibs_provided;
-
	ucl_object_t		*annotations;
	struct pkg_conflict *conflicts;
	struct pkg_provide	*provides;
	unsigned       	 flags;
@@ -379,6 +376,9 @@ static struct pkg_key {
	[PKG_LOCKED] = { "locked", UCL_BOOLEAN },
	[PKG_ROWID] = { "rowid", UCL_INT },
	[PKG_TIME] = { "time", UCL_INT },
+
	[PKG_ANNOTATIONS] = { "annotations", UCL_OBJECT },
+
	[PKG_LICENSES] = { "licenses", UCL_ARRAY },
+
	[PKG_CATEGORIES] = { "catagories", UCL_ARRAY },
};

int pkg_fetch_file_to_fd(struct pkg_repo *repo, const char *url,
modified src/query.c
@@ -335,7 +335,7 @@ print_query(struct pkg *pkg, char *qstr, char multiline)
	struct pkg_user		*user   = NULL;
	struct pkg_group	*group  = NULL;
	struct pkg_shlib	*shlib  = NULL;
-
	const pkg_object	*o;
+
	const pkg_object	*o, *list;
	pkg_iter		 it;

	switch (multiline) {
@@ -353,7 +353,8 @@ print_query(struct pkg *pkg, char *qstr, char multiline)
		break;
	case 'C':
		it = NULL;
-
		while ((o = pkg_object_iterate(pkg_categories(pkg), &it))) {
+
		pkg_get(pkg, PKG_CATEGORIES, &list);
+
		while ((o = pkg_object_iterate(list, &it))) {
			format_str(pkg, output, qstr, o);
			printf("%s\n", sbuf_data(output));
		}
@@ -378,7 +379,8 @@ print_query(struct pkg *pkg, char *qstr, char multiline)
		break;
	case 'L':
		it = NULL;
-
		while ((o = pkg_object_iterate(pkg_licenses(pkg), &it))) {
+
		pkg_get(pkg, PKG_LICENSES, &list);
+
		while ((o = pkg_object_iterate(list, &it))) {
			format_str(pkg, output, qstr, o);
			printf("%s\n", sbuf_data(output));
		}
@@ -409,7 +411,8 @@ print_query(struct pkg *pkg, char *qstr, char multiline)
		break;
	case 'A':
		it = NULL;
-
		while ((o = pkg_object_iterate(pkg_annotations(pkg), &it))) {
+
		pkg_get(pkg, PKG_ANNOTATIONS, &list);
+
		while ((o = pkg_object_iterate(list, &it))) {
			format_str(pkg, output, qstr, o);
			printf("%s\n", sbuf_data(output));
		}
modified src/rquery.c
@@ -84,12 +84,13 @@ print_index(struct pkg *pkg)
#ifndef PORTSDIR
#define PORTSDIR "/usr/ports"
#endif
-
	const pkg_object *obj = NULL;
+
	const pkg_object *obj, *list;
	pkg_iter iter = NULL;

	pkg_printf("%n-%v|" PORTSDIR "/%o|%p|%c|" PORTSDIR "/%o/pkg-descr|%m|",
	    pkg, pkg, pkg, pkg, pkg, pkg, pkg);
-
	while ((obj = pkg_object_iterate(pkg_categories(pkg), &iter)))
+
	pkg_get(pkg, PKG_CATEGORIES, &list);
+
	while ((obj = pkg_object_iterate(list, &iter)))
		pkg_printf("%Cn ", obj);
	printf("\n");
}
modified src/utils.c
@@ -256,6 +256,7 @@ print_info(struct pkg * const pkg, uint64_t options)
	bool show_locks = false;
	char size[7];
	const char *repourl;
+
	const pkg_object	*o;
	unsigned opt;
	int64_t flatsize, oldflatsize, pkgsize;
	int cout = 0;		/* Number of characters output */
@@ -372,7 +373,8 @@ print_info(struct pkg * const pkg, uint64_t options)
				printf("\n");
			break;
		case INFO_CATEGORIES:
-
			if (pkg_object_count(pkg_categories(pkg)) > 0) {
+
			pkg_get(pkg, PKG_CATEGORIES, &o);
+
			if (pkg_object_count(o) > 0) {
				if (print_tag)
					printf("%-15s: ", "Categories");
				pkg_printf("%C%{%Cn%| %}\n", pkg);
@@ -380,7 +382,8 @@ print_info(struct pkg * const pkg, uint64_t options)
				printf("\n");
			break;
		case INFO_LICENSES:
-
			if (pkg_object_count(pkg_licenses(pkg)) > 0) {
+
			pkg_get(pkg, PKG_LICENSES, &o);
+
			if (pkg_object_count(o) > 0) {
				if (print_tag)
					printf("%-15s: ", "Licenses");
				pkg_printf("%L%{%Ln%| %l %}\n", pkg);
@@ -433,7 +436,8 @@ print_info(struct pkg * const pkg, uint64_t options)
			}
			break;
		case INFO_ANNOTATIONS:
-
			if (pkg_object_count(pkg_annotations(pkg)) > 0) {
+
			pkg_get(pkg, PKG_ANNOTATIONS, &o);
+
			if (pkg_object_count(o) > 0) {
				if (print_tag)
					printf("%-15s:\n", "Annotations");
				if (quiet)