Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge pull request #54 from dnaeon/multi-repos
Baptiste committed 14 years ago
commit 1aee2f50a0dec02b82c8fb314a6dbfe5430977b2
parent df211f9
5 files changed +197 -101
modified libpkg/pkg.h
@@ -3,7 +3,6 @@

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

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

struct pkgdb;
struct pkgdb_it;

struct pkg_jobs;

+
struct pkg_repos;
+
struct pkg_repos_entry;
+

typedef enum {
	PKGDB_DEFAULT=0,
	PKGDB_REMOTE
@@ -592,40 +593,56 @@ int pkg_delete(struct pkg *pkg, struct pkgdb *db, int force);
int pkg_repo_fetch(struct pkg *pkg);

/**
-
 * Initializes the remote repositories
+
 * Initializes the repositories object
+
 * @return EPKG_OK on success, otherwise EPKG_FATAL
 */
-
void pkg_remote_repo_init(void);
+
int pkg_repos_new(struct pkg_repos **repos);

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

/**
-
 * Adds a remote repository
-
 * @param name Name for the repository
-
 * @param url URL of the remote repository
+
 * Adds a repository entry to the tail
+
 * @param repos A valid repository object received from pkg_repos_new()
+
 * @param re A valid repository entry object
 * @return EPKG_OK on success, EPKG_FATAL on error
 */
-
int pkg_remote_repo_add(const char *name, const char *url);
+
int pkg_repos_add(struct pkg_repos *repos, struct pkg_repos_entry *re);

/**
 * Get the next repository from the tail
-
 * @return Next repository in the tail
+
 * @param repos A valid repository pointer as returned by pkg_repos_new()
+
 * @param re A pointer to a repository entry to save the result. Must be set to
+
 * NULL for the first repository entry
+
 * @return EPKG_OK on success, EPKG_END if end of repository is reached
 */
-
struct pkg_remote_repo * pkg_remote_repo_next(void);
+
int pkg_repos_next(struct pkg_repos *repos, struct pkg_repos_entry **re);

/**
-
 * Free the memory used for remote repositories
+
 * Returns the name associated with a repository entry object
+
 * @param re A valid repository entry object
 */
-
void pkg_remote_repo_free(void);
+
const char * pkg_repos_get_name(struct pkg_repos_entry *re);

/**
-
 * Resets the tails and sets the next
-
 * element of the tail to be first one
+
 * Returns the URL associated wth a repository entry object
+
 * @param re A valid repository entry object
 */
-
void pkg_remote_repo_reset(void);
+
const char * pkg_repos_get_url(struct pkg_repos_entry *re);
+

+
/**
+
 * Returns the line in the configuration where a repository is found
+
 * @param re A valid repository entry
+
 */
+
unsigned int pkg_repos_get_line(struct pkg_repos_entry *re);
+

+
/**
+
 * Free the memory used by the repository objects
+
 */
+
void pkg_repos_free(struct pkg_repos *repos);

/**
 * Get the value of a configuration key
@@ -722,12 +739,6 @@ 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_private.h
@@ -98,6 +98,17 @@ struct pkg_jobs_node {
	LIST_ENTRY(pkg_jobs_node) entries;
};

+
struct pkg_repos {
+
	STAILQ_HEAD(repos, pkg_repos_entry) nodes;
+
};
+

+
struct pkg_repos_entry {
+
	char *name;
+
	char *url;
+
	unsigned int line;
+
	STAILQ_ENTRY(pkg_repos_entry) entries;
+
};
+

int pkg_open2(struct pkg **p, struct archive **a, struct archive_entry **ae, const char *path);
void pkg_freecategories(struct pkg *pkg);
void pkg_freedeps(struct pkg *pkg);
modified libpkg/pkg_repo.c
@@ -10,11 +10,7 @@
#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;
+
static int pkg_repos_is_reserved_name(struct pkg_repos *repos, struct pkg_repos_entry *re);

int
pkg_repo_fetch(struct pkg *pkg)
@@ -67,25 +63,34 @@ pkg_repo_fetch(struct pkg *pkg)
	return (retcode);
}

-
void
-
pkg_remote_repo_init(void)
+
int
+
pkg_repos_new(struct pkg_repos **repos)
{
-
        STAILQ_INIT(&rrh);
-
        rrh_init = 0;
+
	if ((*repos = calloc(1, sizeof(struct pkg_repos))) == NULL) {
+
		EMIT_ERRNO("calloc", "pkg_repos");
+
		return (EPKG_FATAL);
+
	}
+

+
	STAILQ_INIT(&(*repos)->nodes);
+

+
	return (EPKG_OK);
}

int
-
pkg_remote_repo_load(void)
+
pkg_repos_load(struct pkg_repos *repos)
{
        FILE *fp;
	char *repo_buf[MAXPATHLEN];
        char buf[MAXPATHLEN];
        char *token = NULL, *tmp = NULL;
        unsigned int count = 0, line = 0;
+
	struct pkg_repos_entry *re;
+

+
	assert(repos != NULL);

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

        while (fgets(buf, MAXPATHLEN, fp)) {
@@ -108,70 +113,126 @@ pkg_remote_repo_load(void)
                        warnx("Wrong repository format at line %d (ignoring repository)", line);
                        continue;
                }
+

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

+
		re->name = strdup(repo_buf[0]);
+
		re->url  = strdup(repo_buf[1]);
+
		re->line = line;
+

+
		assert(re->name != NULL && re->url != NULL);
                
-
                pkg_remote_repo_add(repo_buf[0], repo_buf[1]);
+
                pkg_repos_add(repos, re);
        }

        fclose(fp);

-
        return(EPKG_OK);
+
        return (EPKG_OK);
}

int
-
pkg_remote_repo_add(const char *name, const char *url)
+
pkg_repos_add(struct pkg_repos *repos, struct pkg_repos_entry *re)
{
-
        struct pkg_remote_repo *newrepo;
+
	assert(repos != NULL && re != NULL);

-
        if ((newrepo = calloc(1, sizeof(struct pkg_remote_repo))) == NULL) {
-
                EMIT_ERRNO("calloc", "");
-
		return(EPKG_FATAL);
-
        }
+
	if (pkg_repos_is_reserved_name(repos, re) != EPKG_OK) {
+
		warnx("Repository name for '%s' is already reserved (ignoring repository at line %d)",
+
				pkg_repos_get_name(re), pkg_repos_get_line(re));
+

+
		if (re->name != NULL)
+
			free(re->name);
+
		if (re->url != NULL)
+
			free(re->url);

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

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

+
        STAILQ_INSERT_TAIL(&repos->nodes, re, entries);

-
        return(EPKG_OK);
+
        return (EPKG_OK);
}

-
struct pkg_remote_repo *
-
pkg_remote_repo_next(void)
+
int
+
pkg_repos_next(struct pkg_repos *repos, struct pkg_repos_entry **re)
{
-
        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);
+
	assert(repos != NULL);
+

+
	if (*re == NULL)
+
		*re = STAILQ_FIRST(&repos->nodes);
+
	else
+
		*re = STAILQ_NEXT(*re, entries);
+

+
	if (*re == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
+
}
+

+
const char *
+
pkg_repos_get_name(struct pkg_repos_entry *re)
+
{
+
	assert(re != NULL);
+

+
	return (re->name);
+
}
+

+
const char *
+
pkg_repos_get_url(struct pkg_repos_entry *re)
+
{
+
	assert(re != NULL);
+

+
	return (re->url);
+
}
+

+
unsigned int
+
pkg_repos_get_line(struct pkg_repos_entry *re)
+
{
+
	assert(re != NULL);
+

+
	return(re->line);
}

void
-
pkg_remote_repo_free(void)
+
pkg_repos_free(struct pkg_repos *repos)
{
-
        struct pkg_remote_repo *n1, *n2;
+
	struct pkg_repos_entry *re1, *re2;

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

-
                free(n1);
-
                n1 = n2;
+
                free(re1);
+
                re1 = re2;
        }
+

+
	free(repos);
}

-
void
-
pkg_remote_repo_reset(void)
+
static int
+
pkg_repos_is_reserved_name(struct pkg_repos *repos, struct pkg_repos_entry *re)
{
-
        rrh_init = 0;
+
	struct pkg_repos_entry *next = NULL;
+

+
	/* 
+
	 * Find if a repository name already exists.
+
	 * NOTE: The 'repo' name is always reserved, 
+
	 * as it is being used by default when 
+
	 * PACKAGESITE is defined.
+
	 */
+
	while (pkg_repos_next(repos, &next) == EPKG_OK)
+
		if ((strcmp(pkg_repos_get_name(re), pkg_repos_get_name(next)) == 0) || \
+
		    (strcmp(pkg_repos_get_name(re), "repo") == 0))
+
			return (EPKG_FATAL);
+

+
	return (EPKG_OK);
}
modified pkg/search.c
@@ -29,7 +29,8 @@ exec_search(int argc, char **argv)
	unsigned int field = REPO_SEARCH_NAME;
	int retcode = EPKG_OK;
	int ch;
-
	struct pkg_remote_repo *repo = NULL;
+
	struct pkg_repos *repos = NULL;
+
	struct pkg_repos_entry *re = NULL;

	while ((ch = getopt(argc, argv, "gxXcd")) != -1) {
		switch (ch) {
@@ -75,18 +76,22 @@ exec_search(int argc, char **argv)
	if (pkg_config("PACKAGESITE") != NULL) {
		retcode = search_remote_repo(pattern, match, field, "repo");
	} else {
-
		warnx("PACKAGESITE is not defined.");
-
		warnx("Working on multiple repositories...");
-
		warnx("/!\\ This is an unsupported preview feature /!\\ ");
-
		warnx("/!\\ It can kill kittens and puppies /!\\ ");
+
		fprintf(stderr, "\n");
+
		warnx("/!\\     Working on multiple repositories     /!\\");
+
		warnx("/!\\  This is an unsupported preview feature  /!\\");
+
		warnx("/!\\     It can kill kittens and puppies      /!\\");
+
		fprintf(stderr, "\n");

-
		pkg_remote_repo_init();
-
		pkg_remote_repo_load();
+
		if (pkg_repos_new(&repos) != EPKG_OK)
+
			return (EPKG_FATAL);
+

+
		if (pkg_repos_load(repos) != EPKG_OK)
+
			return (EPKG_FATAL);
	
-
		while ((repo = pkg_remote_repo_next()) != NULL)
-
			retcode = search_remote_repo(pattern, match, field, repo->name);
+
		while (pkg_repos_next(repos, &re) == EPKG_OK)
+
			retcode = search_remote_repo(pattern, match, field, pkg_repos_get_name(re));

-
		pkg_remote_repo_free();
+
		pkg_repos_free(repos);
	}

	return (retcode);
@@ -107,7 +112,7 @@ search_remote_repo(const char *pattern, match_t match, unsigned int field, const
	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);
+
		return (EPKG_FATAL);
	}

	if ((it = pkgdb_rquery(db, pattern, match, field)) == NULL) {
@@ -115,7 +120,7 @@ search_remote_repo(const char *pattern, match_t match, unsigned int field, const
				pkg_config("PKG_DBDIR"), dbfile);
		pkgdb_it_free(it);
		pkgdb_close(db);
-
		return(EPKG_FATAL);
+
		return (EPKG_FATAL);
	}

	while ((retcode = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC)) == EPKG_OK) {
@@ -134,5 +139,5 @@ search_remote_repo(const char *pattern, match_t match, unsigned int field, const
		printf("\n");
	}

-
	return(retcode);
+
	return (retcode);
}
modified pkg/update.c
@@ -33,10 +33,11 @@ usage_update(void)
int
exec_update(int argc, char **argv)
{
-
	struct pkg_remote_repo *repo;
	char url[MAXPATHLEN];
	const char *packagesite = NULL;
	int retcode = EPKG_OK;
+
	struct pkg_repos *repos = NULL;
+
	struct pkg_repos_entry *re = NULL;

	(void)argv;
	if (argc != 1) {
@@ -52,8 +53,7 @@ exec_update(int argc, char **argv)
	/* 
	 * If PACKAGESITE is defined fetch only the remote
	 * database to which PACKAGESITE refers, otherwise
-
	 * fetch all remote databases found in the configuration 
-
	 * file.
+
	 * fetch all remote databases found in the configuration file.
	 */
	if ((packagesite = pkg_config("PACKAGESITE")) != NULL) {
		if (packagesite[strlen(packagesite) - 1] == '/')
@@ -63,22 +63,30 @@ exec_update(int argc, char **argv)

		retcode = update_from_remote_repo("repo", url);
	} else {
-
		warnx("PACKAGESITE is not defined.");
-
		warnx("Working on multiple repositories...");
+
		fprintf(stderr, "\n");
+
                warnx("/!\\     Working on multiple repositories     /!\\");
+
                warnx("/!\\  This is an unsupported preview feature  /!\\");
+
                warnx("/!\\     It can kill kittens and puppies      /!\\\n");
+
		fprintf(stderr, "\n");

-
		pkg_remote_repo_init();
-
		pkg_remote_repo_load();
+
		if (pkg_repos_new(&repos) != EPKG_OK)
+
			return (EPKG_FATAL);

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

+
		while (pkg_repos_next(repos, &re) == EPKG_OK) {
+
			packagesite = pkg_repos_get_url(re);
+

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

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

-
		pkg_remote_repo_free();
+
		pkg_repos_free(repos);
	}

	return (retcode);
@@ -97,7 +105,9 @@ update_from_remote_repo(const char *name, const char *url)

	if (pkg_fetch_file(url, tmp) != EPKG_OK) {
		retcode = EPKG_FATAL;
-
		goto cleanup;
+
		unlink(tmp);
+
		free(tmp);
+
		return (EPKG_FATAL);
	}

	a = archive_read_new();
@@ -116,8 +126,6 @@ update_from_remote_repo(const char *name, const char *url)
		}
	}

-
	cleanup:
-

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