Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
pkg info: schema for cache queries, and pkg lists
Philippe Pepiot committed 15 years ago
commit 958f0b992bed9c4c30b413f04fb59dbf011c3f07
parent 694e104
7 files changed +319 -30
added db.txt
@@ -0,0 +1,38 @@
+
pkgdb.cache HOW TO (Draft)
+
key/value store using tinycdb
+

+
Needs:
+
- loop over all packages
+
- build depend tree for a given package
+
- find extra info for each packages
+
- request a remote database
+

+
key			value
+

+
(char*)"nb_packages"		(int)nb_packages
+
[...]
+
(int)N		(char*) package N name
+
[...]
+

+
note that packages are 0-indexed
+

+
(char*)$name			(int)N (package index)
+
(char*)$Nv				(char*)package N version
+
(char*)$Nc				(char*)package N comment
+
(char*)$Nd				(char*)package N desc
+
(char*)$No				(char*)package N origin
+

+
__future__
+

+
(char*)$Np				(char*)package N path
+
		--> fetch from $PACKAGESITE/$path etc (useless ?)
+

+
(char*)$Ns				(char*)package N checksum (for a package)
+
(char*)$ND				(char*)"$dep0-$dep0_version $dep0-$dep0_version..." package N deps
+
						} multiple values for on key ? --> TODO benchmark
+
(char*)$NC				(char*)"$conflict0 $conflict1 ..." package N conflicts
+

+
Why N -> name
+
=> to loop over all packages
+
Why name -> N
+
=> to get package depends without re-looping over all packages
modified libpkg/pkg.h
@@ -1,11 +1,12 @@
#ifndef _PKG_H
#define _PKG_H
+

struct pkg {
-
	const char *name;
-
	const char *version;
-
	const char *origin;
-
	const char *comments;
-
	const char *desc;
+
	char *name;
+
	char *version;
+
	char *origin;
+
	char *comment;
+
	char *desc;
};

#endif
modified libpkg/pkgdb.c
@@ -1,12 +1,51 @@
+
#include <stdio.h>
+
#include <stdlib.h>
+

#include "pkgdb.h"
#include "pkgdb_cache.h"

+

+

struct pkg **
-
pkgdb_list_packages() {
+
pkgdb_list_packages(const char *pattern) {
	/* first check if the cache has to be rebuild */
	struct pkg **pkgs;
+

	pkgdb_cache_update();
-
	pkgs = pkgdb_cache_list_packages();
-
	
+
	pkgs = pkgdb_cache_list_packages(pattern);
+

	return (pkgs);
}
+

+
void
+
pkgdb_free(struct pkg **pkgs)
+
{
+
	int i;
+
	struct pkg *p;
+

+
	if (pkgs) {
+
		for (i = 0; pkgs[i] != NULL; i++) {
+
			p = pkgs[i];
+
			if (p->name) free(p->name);
+
			if (p->version) free(p->version);
+
			if (p->comment) free(p->comment);
+
			if (p->desc) free(p->desc);
+
			if (p->origin) free(p->origin);
+
			free(p);
+
		}
+
		free(pkgs);
+
	}
+
}
+

+
size_t
+
pkgdb_count(struct pkg **pkgs)
+
{
+
	size_t i;
+

+
	if (!pkgs)
+
		return 0;
+

+
	for (i = 0; pkgs[i] != NULL; i++);
+
	return (i);
+
}
+

modified libpkg/pkgdb.h
@@ -4,7 +4,9 @@

#define PKG_DBDIR "/var/db/pkg"

-
struct pkg **pkgdb_list_packages(void);
+
struct pkg **pkgdb_list_packages(const char*pattern);
+
void pkgdb_free(struct pkg **pkgs);
+
size_t pkgdb_count(struct pkg **pkgs);


#endif
modified libpkg/pkgdb_cache.c
@@ -4,10 +4,12 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+
#include <stdarg.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+
#include <fcntl.h>

#include <cdb.h>
#include <cJSON.h>
@@ -16,6 +18,148 @@
#include "pkg_compat.h"
#include "pkgdb_cache.h"

+
/* open a cdb db */
+
static int
+
db_open(struct cdb *db, const char *path, int flags)
+
{
+
	int fd;
+

+
	if (!path || !db)
+
		return (-1);
+

+
	if ((fd = open(path, flags)) == -1)
+
		warn("open(%s):", path);
+
	else
+
		cdb_init(db, fd);
+

+
	return (fd);
+
}
+

+
/* close a cdb db */
+
static void
+
db_close(struct cdb *db)
+
{
+
	int fd;
+

+
	fd = cdb_fileno(db);
+
	cdb_free(db);
+
	close(fd);
+
}
+

+
/* query string -> string */
+
static char *
+
db_query(struct cdb *db, const char *fmt, ...)
+
{
+
	char *string;
+
	va_list args;
+
	char key[BUFSIZ];
+
	size_t len;
+

+
	va_start(args, fmt);
+
	len = vsnprintf(key, sizeof(key), fmt, args);
+

+
	if (len != strlen(key)) {
+
		warnx("key too long:");
+
		vwarnx(fmt, args);
+
		va_end(args);
+
		return NULL;
+
	}
+

+
	va_end(args);
+

+
	if (cdb_find(db, key, len) < 0)
+
		return NULL;
+

+
	len = cdb_datalen(db);
+
	string = malloc(len+1);
+
	cdb_read(db, string, len, cdb_datapos(db));
+
	string[len] = '\0';
+
	return (string);
+
}
+

+
/* add record formated string -> string */
+
static int
+
db_add(struct cdb_make *db, const char *val, const char *fmt, ...)
+
{
+
	char key[BUFSIZ];
+
	va_list args;
+
	size_t len;
+

+
	if (db == NULL || key == NULL || val == NULL)
+
		return (-1);
+

+
	va_start(args, fmt);
+
	len = vsnprintf(key, sizeof(key), fmt, args);
+

+
	if (len != strlen(key)) {
+
		warnx("key too long:");
+
		vwarnx(fmt, args);
+
		va_end(args);
+
		return (-1);
+
	}
+

+
	return (cdb_make_add(db, key, len, val, strlen(val)));
+
}
+

+
/* query a pkg using index */
+
static struct pkg *
+
pkg_idx_query(struct cdb *db, int idx)
+
{
+
	struct pkg *pkg;
+
	size_t len;
+

+
	if (db == NULL)
+
		return NULL;
+

+
	if (cdb_find(db, &idx, sizeof(idx) <= 0))
+
		return NULL;
+

+
	pkg = malloc(sizeof(*pkg));
+
	len = cdb_datalen(db);
+
	pkg->name = malloc(len+1);
+
	cdb_read(db, pkg->name, len, cdb_datapos(db));
+
	pkg->name[len] = '\0';
+

+
	pkg->version = db_query(db, PKGDB_VERSION, idx);
+
	pkg->comment = db_query(db, PKGDB_COMMENT, idx);
+
	pkg->desc    = db_query(db, PKGDB_DESC, idx);
+
	pkg->origin  = db_query(db, PKGDB_ORIGIN, idx);
+

+
	return (pkg);
+
}
+

+
/* query pkg using name */
+
/* static struct pkg *
+
pkg_query(struct cdb *db, char *name)
+
{
+
	int idx;
+

+
	if (name == NULL || db == NULL)
+
		return NULL;
+

+
	if ((cdb_find(db, name, strlen(name))) <= 0)
+
		return NULL;
+

+
	cdb_read(db, &idx, sizeof(idx), cdb_datapos(db));
+

+
	return (pkg_idx_query(db, idx));
+
}
+
*/
+

+
/* open the pkgdb.cache */
+
static int
+
pkgdb_open(struct cdb *db, int flags)
+
{
+
	char *pkgdb_dir;
+
	char filepath[MAXPATHLEN];
+

+
	pkgdb_dir = getenv("PKG_DBDIR");
+

+
	snprintf(filepath, sizeof(filepath), "%s/pkgdb.cache",
+
			(pkgdb_dir) ? pkgdb_dir : PKG_DBDIR);
+
	return (db_open(db, filepath, flags));
+
}
+

static cJSON *
pkgdb_cache_load_port(const char *pkg_dbdir, char *pkgname)
{
@@ -48,14 +192,13 @@ static void
pkgdb_cache_rebuild(const char *pkg_dbdir, const char *cache_path)
{
	int fd;
-
	char key[BUFSIZ];
	char *value;
	char tmppath[MAXPATHLEN];
	struct cdb_make cdb_make;
	DIR *dir;
	struct dirent *portsdir;
-
	cJSON *manifest;
-
	int nb_packages = 0;
+
	cJSON *manifest, *node;
+
	int idx = 0;

	snprintf(tmppath, sizeof(tmppath), "%s/pkgdb.cache-XXXXX", pkg_dbdir);

@@ -82,19 +225,36 @@ pkgdb_cache_rebuild(const char *pkg_dbdir, const char *cache_path)
				if (manifest == 0)
					continue;

-
				nb_packages++;
-
				snprintf(key, BUFSIZ, "%d_name",nb_packages);
				value = cJSON_GetObjectItem(manifest, "name")->valuestring;
-
				ADD_CACHE(&cdb_make, key, value);
-
				snprintf(key, BUFSIZ, "%d_version", nb_packages);
+

+
				/* index -> name */
+
				cdb_make_add(&cdb_make, &idx, sizeof(idx),
+
						value, strlen(value));
+
				/* name -> index */
+
				cdb_make_add(&cdb_make, value, strlen(value), &idx, sizeof(idx));
+

				value = cJSON_GetObjectItem(manifest, "version")->valuestring;
-
				ADD_CACHE(&cdb_make, key, value);
+
				db_add(&cdb_make, value, PKGDB_VERSION, idx);
+

+
				if ((node = cJSON_GetObjectItem(manifest, "comment")) != NULL)
+
					db_add(&cdb_make, node->valuestring, PKGDB_COMMENT, idx);
+

+
				if ((node = cJSON_GetObjectItem(manifest, "desc")) != NULL)
+
					db_add(&cdb_make, node->valuestring, PKGDB_DESC, idx);
+

+
				if ((node = cJSON_GetObjectItem(manifest, "origin")) != NULL)
+
					db_add(&cdb_make, node->valuestring, PKGDB_ORIGIN, idx);

				cJSON_Delete(manifest);
+

+
				idx++;
			}
		}
	}

+
	/* record packages len */
+
	cdb_make_add(&cdb_make, "nb_packages", strlen("nb_packages"), &idx, sizeof(idx));
+

	cdb_make_finish(&cdb_make);

	close(fd);
@@ -141,8 +301,45 @@ pkgdb_cache_update()
}

struct pkg **
-
pkgdb_cache_list_packages()
+
pkgdb_cache_list_packages(const char *pattern)
{
-
	/* TODO */
-
	return NULL;
+
	struct cdb db;
+
	int nb_pkg, i, j;
+
	char key[BUFSIZ];
+
	char *val;
+
	struct pkg **pkgs;
+
	size_t len;
+

+
	if (pkgdb_open(&db, O_RDONLY) == -1)
+
		return NULL;
+

+
	strcpy(key, "nb_packages");
+

+
	if (cdb_find(&db, key, strlen(key)) <= 0) {
+
		warnx("corrupted database");
+
		db_close(&db);
+
	}
+

+
	cdb_read(&db, &nb_pkg, sizeof(nb_pkg), cdb_datapos(&db));
+

+
	pkgs = calloc(nb_pkg+1, sizeof(*pkgs));
+

+
	for (i = 0, j = 0; i < nb_pkg; i++) {
+
		cdb_find(&db, &i, sizeof(i));
+
		len = cdb_datalen(&db);
+
		val = malloc(len+1);
+
		cdb_read(&db, val, len, cdb_datapos(&db));
+
		val[len] = '\0';
+

+
		if (!pattern || strncmp(val, pattern, strlen(pattern)) == 0) {
+
			/* ok we find one pkg matching the pattern */
+
			if ((pkgs[j] = pkg_idx_query(&db, i)) != NULL)
+
				j++;
+
		}
+
	}
+
	pkgs[j] = NULL;
+

+
	db_close(&db);
+

+
	return (pkgs);
}
modified libpkg/pkgdb_cache.h
@@ -2,12 +2,12 @@
#define _PKGDB_CACHE_H
#include "pkgdb.h"

-
#define ADD_CACHE(db, key, val) \
-
	do { \
-
		cdb_make_add((db), key, strlen(key), val, strlen(val)); \
-
	} while (0)
+
#define PKGDB_VERSION "%dv"
+
#define PKGDB_COMMENT "%dc"
+
#define PKGDB_DESC    "%dd"
+
#define PKGDB_ORIGIN  "%do"

void pkgdb_cache_update(void);
-
struct pkg **pkgdb_cache_list_packages(void);
+
struct pkg **pkgdb_cache_list_packages(const char*pattern);

#endif
modified pkg/info.c
@@ -8,12 +8,24 @@
int
cmd_info(int argc, char **argv)
{
-
	struct pkg **pkgs = NULL;
+
	struct pkg **pkgs;
+
	int i;
+
	(void)argc;

-
	if (argc == 1) {
-
		pkgs = pkgdb_list_packages();
-
	} else {
-
		printf("%s: Not implemented yet\n", argv[0]);
+
	if ((pkgs = pkgdb_list_packages(argv[1])) == NULL)
+
		return 0;
+

+
	if (pkgdb_count(pkgs) == 1) {
+
		/* one match */
+
		printf("Information for %s-%s\n", pkgs[0]->name, pkgs[0]->version);
+
		printf("Comment:\n%s\n\n", pkgs[0]->comment);
+
		printf("Description:\n%s\n\n", pkgs[0]->desc);
+
	}
+
	else {
+
		for (i = 0; pkgs[i] != NULL; i++)
+
			printf("%s-%s: %s\n", pkgs[i]->name, pkgs[i]->version, pkgs[i]->comment);
	}
+

+
	pkgdb_free(pkgs);
	return (0);
}