Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge pull request #51 from dnaeon/multi-repos
Baptiste committed 14 years ago
commit 375249333809971e8b61a50ffd2ccf36b9544515
parent cf0dc8f
17 files changed +308 -55
modified libpkg/pkg.h
@@ -3,6 +3,7 @@

#include <stdarg.h>
#include <sys/types.h>
+
#include <sys/queue.h>
#include <openssl/pem.h>

struct pkg;
@@ -13,6 +14,7 @@ struct pkg_category;
struct pkg_conflict;
struct pkg_script;
struct pkg_option;
+
struct pkg_remote_repo;

struct pkgdb;
struct pkgdb_it;
@@ -401,11 +403,12 @@ int pkg_create_repo(char *path, void (*callback)(struct pkg *, void *), void *);
int pkg_finish_repo(char *patj, pem_password_cb *cb, char *rsa_key_path);

/**
-
 * Open the local package database.
+
 * Open the package database.
 * The db must be free'ed with pkgdb_close().
+
 * @param dbfile Name of the package database file
 * @return An error code.
 */
-
int pkgdb_open(struct pkgdb **db, pkgdb_t type);
+
int pkgdb_open(struct pkgdb **db, pkgdb_t type, const char *dbfile);

/**
 * Close and free the struct pkgdb.
@@ -589,6 +592,42 @@ int pkg_delete(struct pkg *pkg, struct pkgdb *db, int force);
int pkg_repo_fetch(struct pkg *pkg);

/**
+
 * Initializes the remote repositories
+
 */
+
void pkg_remote_repo_init(void);
+

+
/**
+
 * Loads the remote repositories from file
+
 * @return EPKG_OK on success, and EPKG_FATAL on error
+
 */
+
int pkg_remote_repo_load(void);
+

+
/**
+
 * Adds a remote repository
+
 * @param name Name for the repository
+
 * @param url URL of the remote repository
+
 * @return EPKG_OK on success, EPKG_FATAL on error
+
 */
+
int pkg_remote_repo_add(const char *name, const char *url);
+

+
/**
+
 * Get the next repository from the tail
+
 * @return Next repository in the tail
+
 */
+
struct pkg_remote_repo * pkg_remote_repo_next(void);
+

+
/**
+
 * Free the memory used for remote repositories
+
 */
+
void pkg_remote_repo_free(void);
+

+
/**
+
 * Resets the tails and sets the next
+
 * element of the tail to be first one
+
 */
+
void pkg_remote_repo_reset(void);
+

+
/**
 * Get the value of a configuration key
 */
const char * pkg_config(const char *key);
@@ -683,6 +722,12 @@ struct pkg_event {
	};
};

+
struct pkg_remote_repo {
+
	char *name;
+
	char *url;
+
	STAILQ_ENTRY(pkg_remote_repo) entries;
+
};
+

/**
 * Event callback mechanism.  Events will be reported using this callback,
 * providing an event identifier and up to two event-specific pointers.
modified libpkg/pkg_repo.c
@@ -1,3 +1,5 @@
+
#include <err.h>
+
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <libgen.h>
@@ -8,6 +10,12 @@
#include "pkg_event.h"
#include "pkg_private.h"

+
/*
+
 * Head of the remote repository tail and initializer
+
 */
+
static STAILQ_HEAD(remote_repo, pkg_remote_repo) rrh;
+
static int rrh_init;
+

int
pkg_repo_fetch(struct pkg *pkg)
{
@@ -58,3 +66,112 @@ pkg_repo_fetch(struct pkg *pkg)

	return (retcode);
}
+

+
void
+
pkg_remote_repo_init(void)
+
{
+
        STAILQ_INIT(&rrh);
+
        rrh_init = 0;
+
}
+

+
int
+
pkg_remote_repo_load(void)
+
{
+
        FILE *fp;
+
	char *repo_buf[MAXPATHLEN];
+
        char buf[MAXPATHLEN];
+
        char *token = NULL, *tmp = NULL;
+
        unsigned int count = 0, line = 0;
+

+
        if ((fp = fopen("/etc/pkg/repositories", "r")) == NULL) {
+
		EMIT_ERRNO("fopen", "/etc/pkg/repositories");
+
		return(EPKG_FATAL);
+
	}
+

+
        while (fgets(buf, MAXPATHLEN, fp)) {
+
                line++;
+

+
                if (buf[0] == '\n' || buf[0] == '#' || buf[0] == ';')
+
                        continue;
+

+
                count = 0;
+

+
                buf[strlen(buf) - 1] = '\0';
+
                tmp = buf;
+

+
		/* get the repository entries */
+
		while ((token = strsep(&tmp, " \t=")) != NULL)
+
			if (*token != '\0')
+
				repo_buf[count++] = token;
+

+
		if (count != 2) {
+
                        warnx("Wrong repository format at line %d (ignoring repository)", line);
+
                        continue;
+
                }
+
                
+
                pkg_remote_repo_add(repo_buf[0], repo_buf[1]);
+
        }
+

+
        fclose(fp);
+

+
        return(EPKG_OK);
+
}
+

+
int
+
pkg_remote_repo_add(const char *name, const char *url)
+
{
+
        struct pkg_remote_repo *newrepo;
+

+
        if ((newrepo = calloc(1, sizeof(struct pkg_remote_repo))) == NULL) {
+
                EMIT_ERRNO("calloc", "");
+
		return(EPKG_FATAL);
+
        }
+

+
        newrepo->name = strdup(name);
+
        newrepo->url  = strdup(url);
+

+
        assert(newrepo->name != NULL && newrepo->url != NULL);
+
        
+
        STAILQ_INSERT_TAIL(&rrh, newrepo, entries);
+

+
        return(EPKG_OK);
+
}
+

+
struct pkg_remote_repo *
+
pkg_remote_repo_next(void)
+
{
+
        static struct pkg_remote_repo *next;
+
        
+
        if (rrh_init == 0) {
+
                next = STAILQ_FIRST(&rrh);
+
                rrh_init = 1;
+
        } else
+
                next = STAILQ_NEXT(next, entries);
+

+
        return(next);
+
}
+

+
void
+
pkg_remote_repo_free(void)
+
{
+
        struct pkg_remote_repo *n1, *n2;
+

+
        n1 = STAILQ_FIRST(&rrh);
+
        while (n1 != NULL) {
+
                n2 = STAILQ_NEXT(n1, entries);
+
                
+
                if (n1->name != NULL)
+
                        free(n1->name);
+
                if (n1->url != NULL)
+
                        free(n1->url);
+

+
                free(n1);
+
                n1 = n2;
+
        }
+
}
+

+
void
+
pkg_remote_repo_reset(void)
+
{
+
        rrh_init = 0;
+
}
modified libpkg/pkgdb.c
@@ -249,7 +249,7 @@ pkgdb_init(sqlite3 *sdb)
}

int
-
pkgdb_open(struct pkgdb **db, pkgdb_t type)
+
pkgdb_open(struct pkgdb **db, pkgdb_t type, const char *dbfile)
{
	int retcode;
	char *errmsg;
@@ -289,7 +289,7 @@ pkgdb_open(struct pkgdb **db, pkgdb_t type)
	}

	if (type == PKGDB_REMOTE) {
-
		snprintf(remotepath, sizeof(remotepath), "%s/repo.sqlite", dbdir);
+
		snprintf(remotepath, sizeof(remotepath), "%s/%s", dbdir, dbfile);

		if (access(remotepath, R_OK) != 0) {
			EMIT_ERRNO("access", remotepath);
modified pkg/add.c
@@ -51,7 +51,7 @@ exec_add(int argc, char **argv)
		return (EX_NOPERM);
	}

-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_DEFAULT, "local.sqlite") != EPKG_OK) {
		return (EX_IOERR);
	}

modified pkg/autoremove.c
@@ -61,7 +61,7 @@ exec_autoremove(int argc, char **argv)
		return (EX_NOPERM);
	}

-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_DEFAULT, "local.sqlite") != EPKG_OK) {
		return (EX_IOERR);
	}

modified pkg/backup.c
@@ -24,7 +24,7 @@ exec_backup(int argc, char **argv)
	if (argc == 2)
		dest = argv[2];

-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_DEFAULT, "local.sqlite") != EPKG_OK) {
		return (EX_IOERR);
	}

modified pkg/create.c
@@ -30,7 +30,7 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt, const
					  PKG_LOAD_DIRS | PKG_LOAD_SCRIPTS | PKG_LOAD_OPTIONS |
					  PKG_LOAD_MTREE;

-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_DEFAULT, "local.sqlite") != EPKG_OK) {
		pkgdb_close(db);
		return (EX_IOERR);
	}
modified pkg/delete.c
@@ -57,7 +57,7 @@ exec_delete(int argc, char **argv)
		return (EX_NOPERM);
	}
	
-
	if ((retcode = pkgdb_open(&db, PKGDB_DEFAULT)) != EPKG_OK) {
+
	if ((retcode = pkgdb_open(&db, PKGDB_DEFAULT, "local.sqlite")) != EPKG_OK) {
		goto cleanup;
	}

modified pkg/event.c
@@ -20,7 +20,7 @@ event_callback(void *data __unused, struct pkg_event *ev)
		break;
	case PKG_EVENT_FETCHING:
		percent = ((float)ev->e_fetching.done / (float)ev->e_fetching.total) * 100;
-
		printf("\rFetching %s... %d%%", ev->e_fetching.url, percent);
+
		printf("\rFetching from %s... %d%%", ev->e_fetching.url, percent);
		if (ev->e_fetching.done == ev->e_fetching.total)
			printf("\n");
		fflush(stdout);
modified pkg/info.c
@@ -172,7 +172,7 @@ exec_info(int argc, char **argv)
		return (EX_USAGE);
	}

-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_DEFAULT, "local.sqlite") != EPKG_OK) {
		return (EX_IOERR);
	}

modified pkg/install.c
@@ -38,7 +38,7 @@ exec_install(int argc, char **argv)
		return (EX_NOPERM);
	}

-
	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_REMOTE, "repo.sqlite") != EPKG_OK) {
		return (EX_IOERR);
	}

modified pkg/register.c
@@ -181,7 +181,7 @@ exec_register(int argc, char **argv)
	if (plist != NULL)
		free(plist);

-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_DEFAULT, "local.sqlite") != EPKG_OK) {
		return (EX_IOERR);
	}

added pkg/repositories
@@ -0,0 +1,10 @@
+
# Repositories file for pkgng
+
# This file should be installed in /etc/pkg/repositories
+
# For more information on the format of this files
+
# please refer to pkg(1) man page
+

+
# dnaeon's i386 repository
+
dnaeon-i386	=	http://unix-heaven.org/FreeBSD/pkgng/dnaeon-i386/
+

+
# dnaeon's amd64 repository
+
dnaeon-amd64	=	http://unix-heaven.org/FreeBSD/pkgng/dnaeon-amd64/
modified pkg/search.c
@@ -1,3 +1,6 @@
+
#include <sys/param.h>
+

+
#include <err.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
@@ -8,25 +11,25 @@

#include "search.h"

+
static int search_remote_repo(const char *pattern, match_t match, 
+
		unsigned int field, const char *dbname);
+

void
usage_search(void)
{
-
	fprintf(stderr, "usage, pkg search [-gxXcd] pattern\n");
+
	fprintf(stderr, "usage: pkg search [-gxXcd] pattern\n\n");
	fprintf(stderr, "For more information see 'pkg help search'.\n");
}

int
exec_search(int argc, char **argv)
{
-
	char *pattern;
+
	char *pattern = NULL;
	match_t match = MATCH_EXACT;
-
	int  retcode = EPKG_OK;
	unsigned int field = REPO_SEARCH_NAME;
+
	int retcode = EPKG_OK;
	int ch;
-
	char size[7];
-
	struct pkgdb *db = NULL;
-
	struct pkgdb_it *it = NULL;
-
	struct pkg *pkg = NULL;
+
	struct pkg_remote_repo *repo = NULL;

	while ((ch = getopt(argc, argv, "gxXcd")) != -1) {
		switch (ch) {
@@ -61,34 +64,73 @@ exec_search(int argc, char **argv)

	pattern = argv[0];

-
	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) {
-
		retcode = EPKG_FATAL;
-
		goto cleanup;
+
	/*
+
	 * TODO: Implement a feature to search only
+
	 * in a given repository specified in the argument list
+
	 */
+

+
	/* 
+
	 * Honor PACKAGESITE if specified
+
	 */
+
	if (pkg_config("PACKAGESITE") != NULL) {
+
		retcode = search_remote_repo(pattern, match, field, "repo");
+
	} else {
+
		warnx("PACKAGESITE is not defined.");
+
		warnx("Working on multiple repositories...");
+

+
		pkg_remote_repo_init();
+
		pkg_remote_repo_load();
+
	
+
		while ((repo = pkg_remote_repo_next()) != NULL)
+
			retcode = search_remote_repo(pattern, match, field, repo->name);
+

+
		pkg_remote_repo_free();
+
	}
+

+
	return (retcode);
+
}
+

+
static int
+
search_remote_repo(const char *pattern, match_t match, unsigned int field, const char *dbname)
+
{
+
	char size[7];
+
	char dbfile[MAXPATHLEN];
+
	int  retcode = EPKG_OK;
+
	struct pkgdb *db = NULL;
+
	struct pkgdb_it *it = NULL;
+
	struct pkg *pkg = NULL;
+

+
	snprintf(dbfile, MAXPATHLEN, "%s.sqlite", dbname);
+

+
	if (pkgdb_open(&db, PKGDB_REMOTE, dbfile) != EPKG_OK) {
+
		warnx("cannot open repository database: %s/%s\n", 
+
				pkg_config("PKG_DBDIR"), dbfile);
+
		return(EPKG_FATAL);
	}

	if ((it = pkgdb_rquery(db, pattern, match, field)) == NULL) {
-
		retcode = EPKG_FATAL;
-
		goto cleanup;
+
		warnx("cannot query repository database: %s/%s\n",
+
				pkg_config("PKG_DBDIR"), dbfile);
+
		pkgdb_it_free(it);
+
		pkgdb_close(db);
+
		return(EPKG_FATAL);
	}

-
	while (( retcode = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
-
		printf("Name: %s\n", pkg_get(pkg, PKG_NAME));
-
		printf("Version: %s\n", pkg_get(pkg, PKG_VERSION));
-
		printf("Origin: %s\n", pkg_get(pkg, PKG_ORIGIN));
+
	while ((retcode = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
+
		printf("Name:       %s\n", pkg_get(pkg, PKG_NAME));
+
		printf("Version:    %s\n", pkg_get(pkg, PKG_VERSION));
+
		printf("Origin:     %s\n", pkg_get(pkg, PKG_ORIGIN));
+
		printf("Arch:       %s\n", pkg_get(pkg, PKG_ARCH));
		printf("Maintainer: %s\n", pkg_get(pkg, PKG_MAINTAINER));
-
		printf("WWW: %s\n", pkg_get(pkg, PKG_WWW));
-
		printf("Comment: %s\n", pkg_get(pkg, PKG_COMMENT));
+
		printf("WWW:        %s\n", pkg_get(pkg, PKG_WWW));
+
		printf("Comment:    %s\n", pkg_get(pkg, PKG_COMMENT));
+
		printf("Repository: %s\n", dbname);
		humanize_number(size, sizeof(size), pkg_new_flatsize(pkg), "B", HN_AUTOSCALE, 0);
-
		printf("Flat size: %s\n", size);
+
		printf("Flat size:  %s\n", size);
		humanize_number(size, sizeof(size), pkg_new_pkgsize(pkg), "B", HN_AUTOSCALE, 0);
-
		printf("Pkg size: %s\n", size);
+
		printf("Pkg size:   %s\n", size);
		printf("\n");
	}

-
	cleanup:
-
	pkgdb_it_free(it);
-
	pkgdb_close(db);
-

-
	return (retcode);
-

+
	return(retcode);
}
modified pkg/update.c
@@ -21,22 +21,22 @@
		ARCHIVE_EXTRACT_TIME  |ARCHIVE_EXTRACT_ACL | \
		ARCHIVE_EXTRACT_FFLAGS|ARCHIVE_EXTRACT_XATTR)

+
static int update_from_remote_repo(const char *name, const char *url);
+

void
usage_update(void)
{
-
	fprintf(stderr, "usage pkg update\n\n");
+
	fprintf(stderr, "usage: pkg update\n\n");
	fprintf(stderr, "For more information see 'pkg help update'.\n");
}

int
exec_update(int argc, char **argv)
{
+
	struct pkg_remote_repo *repo;
	char url[MAXPATHLEN];
	const char *packagesite = NULL;
-
	char *tmp = NULL;
	int retcode = EPKG_OK;
-
	struct archive *a;
-
	struct archive_entry *ae;

	(void)argv;
	if (argc != 1) {
@@ -49,15 +49,49 @@ exec_update(int argc, char **argv)
		return (EX_NOPERM);
	}

-
	if ((packagesite = pkg_config("PACKAGESITE")) == NULL) {
-
		warnx("unable to determine PACKAGESITE");
-
		return (EPKG_FATAL);
+
	/* 
+
	 * If PACKAGESITE is defined fetch only the remote
+
	 * database to which PACKAGESITE refers, otherwise
+
	 * fetch all remote databases found in the configuration 
+
	 * file.
+
	 */
+
	if ((packagesite = pkg_config("PACKAGESITE")) != NULL) {
+
		if (packagesite[strlen(packagesite) - 1] == '/')
+
			snprintf(url, MAXPATHLEN, "%srepo.txz", packagesite);
+
		else
+
			snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);
+

+
		retcode = update_from_remote_repo("repo", url);
+
	} else {
+
		warnx("PACKAGESITE is not defined.");
+
		warnx("Working on multiple repositories...");
+

+
		pkg_remote_repo_init();
+
		pkg_remote_repo_load();
+

+
		while ((repo = pkg_remote_repo_next()) != NULL) {
+
			if (repo->url[strlen(repo->url) - 1] == '/')
+
				snprintf(url, MAXPATHLEN, "%srepo.txz", repo->url);
+
			else
+
				snprintf(url, MAXPATHLEN, "%s/repo.txz", repo->url);
+

+
			retcode = update_from_remote_repo(repo->name, url);
+
		}
+

+
		pkg_remote_repo_free();
	}

-
	if (packagesite[strlen(packagesite) - 1] == '/')
-
		snprintf(url, MAXPATHLEN, "%srepo.txz", packagesite);
-
	else
-
		snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);
+
	return (retcode);
+
}
+

+
int
+
update_from_remote_repo(const char *name, const char *url)
+
{
+
	struct archive *a = NULL;
+
	struct archive_entry *ae;
+
	char repofile[MAXPATHLEN];
+
	char *tmp = NULL;
+
	int retcode = EPKG_OK;

	tmp = mktemp(strdup("/tmp/repo.txz.XXXXXX"));

@@ -74,16 +108,21 @@ exec_update(int argc, char **argv)

	while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
		if (strcmp(archive_entry_pathname(ae), "repo.sqlite") == 0) {
-
			archive_entry_set_pathname(ae, "/var/db/pkg/repo.sqlite");
+
			snprintf(repofile, MAXPATHLEN, "%s/%s.sqlite",
+
				       pkg_config("PKG_DBDIR"), name);
+
			archive_entry_set_pathname(ae, repofile);
			archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS);
			break;
		}
	}

	cleanup:
-
	archive_read_finish(a);
+

+
	if ( a != NULL) 
+
		archive_read_finish(a);
+

	unlink(tmp);
	free(tmp);

-
	return (retcode);
+
	return(retcode);
}
modified pkg/upgrade.c
@@ -43,7 +43,7 @@ exec_upgrade(int argc, char **argv)
		return (EX_NOPERM);
	}

-
	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_REMOTE, "repo.sqlite") != EPKG_OK) {
		return (EX_IOERR);
	}

modified pkg/which.c
@@ -33,7 +33,7 @@ exec_which(int argc, char **argv)
		return (EX_USAGE);
	}

-
	if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) {
+
	if (pkgdb_open(&db, PKGDB_DEFAULT, "local.sqlite") != EPKG_OK) {
		pkgdb_close(db);
		return (EX_IOERR);
	}