Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
db: allow passing multiple -r options
Baptiste Daroussin committed 1 year ago
commit a9eccd90bd7af4e0ec8f80bc8cb36864c470c8f4
parent 751160c
18 files changed +253 -116
modified libpkg/pkg.h.in
@@ -46,6 +46,7 @@ extern "C" {
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+
#include <pkgvec.h>

/* The expected name of the pkg(8) binary executable. */
#ifndef PKG_EXEC_NAME
@@ -868,7 +869,8 @@ int pkg_repo_create(struct pkg_repo_create *, char *path);
 * If no repositories are specified (e.g. when NULL is the first argument,
 * then all repositories are tried to be accessed).
 */
-
int pkgdb_access(unsigned mode, unsigned database, ...);
+
int pkgdb_access(unsigned mode, unsigned database);
+
int pkgdb_access2(unsigned mode, unsigned database, c_charv_t *databases);

/**
 * Open the local package database.
@@ -884,6 +886,7 @@ int pkgdb_open(struct pkgdb **db, pkgdb_t type);
 * @return An error code
 */
int pkgdb_open_all(struct pkgdb **db, pkgdb_t type, const char *reponame);
+
int pkgdb_open_all2(struct pkgdb **db, pkgdb_t type, c_charv_t *reponames);

/**
 * Locking functions
@@ -931,12 +934,20 @@ struct pkgdb_it * pkgdb_query_cond(struct pkgdb *db, const char *cond,
    const char *pattern, match_t type);
struct pkgdb_it * pkgdb_repo_query(struct pkgdb *db, const char *pattern,
    match_t type, const char *reponame);
+
struct pkgdb_it * pkgdb_repo_query2(struct pkgdb *db, const char *pattern,
+
    match_t type, c_charv_t *reponames);
struct pkgdb_it *pkgdb_repo_query_cond(struct pkgdb *db, const char *cond,
	const char *pattern, match_t type, const char *reponame);
+
struct pkgdb_it *pkgdb_repo_query_cond2(struct pkgdb *db, const char *cond,
+
	const char *pattern, match_t type, c_charv_t *reponames);
struct pkgdb_it * pkgdb_repo_search(struct pkgdb *db, const char *pattern,
    match_t type, pkgdb_field field, pkgdb_field sort, const char *reponame);
+
struct pkgdb_it * pkgdb_repo_search2(struct pkgdb *db, const char *pattern,
+
    match_t type, pkgdb_field field, pkgdb_field sort, c_charv_t *reponames);
struct pkgdb_it * pkgdb_all_search(struct pkgdb *db, const char *pattern,
    match_t type, pkgdb_field field, pkgdb_field sort, const char *reponame);
+
struct pkgdb_it * pkgdb_all_search2(struct pkgdb *db, const char *pattern,
+
    match_t type, pkgdb_field field, pkgdb_field sort, c_charv_t *reponames);

/**
 * @todo Return directly the struct pkg?
@@ -1050,6 +1061,7 @@ void pkg_jobs_free(struct pkg_jobs *jobs);
int pkg_jobs_add(struct pkg_jobs *j, match_t match, char **argv, int argc);
int pkg_jobs_solve(struct pkg_jobs *j);
int pkg_jobs_set_repository(struct pkg_jobs *j, const char *name);
+
int pkg_jobs_set_repositories(struct pkg_jobs *j, c_charv_t *names);
const char* pkg_jobs_destdir(struct pkg_jobs *j);
int pkg_jobs_set_destdir(struct pkg_jobs *j, const char *name);
void pkg_jobs_set_flags(struct pkg_jobs *j, pkg_flags f);
modified libpkg/pkg_jobs.c
@@ -29,6 +29,7 @@
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

+
#include "pkgvec.h"
#ifdef HAVE_CONFIG_H
#include "pkg_config.h"
#endif
@@ -119,14 +120,31 @@ pkg_jobs_set_flags(struct pkg_jobs *j, pkg_flags flags)
int
pkg_jobs_set_repository(struct pkg_jobs *j, const char *ident)
{
-
	if ((pkg_repo_find(ident)) == NULL) {
-
		pkg_emit_error("Unknown repository: %s", ident);
-
		return (EPKG_FATAL);
+
	c_charv_t idents;
+
	pkgvec_init(&idents);
+
	if (ident != NULL)
+
		pkgvec_push(&idents, ident);
+
	return (pkg_jobs_set_repositories(j, &idents));
+
}
+

+
int
+
pkg_jobs_set_repositories(struct pkg_jobs *j, c_charv_t *idents)
+
{
+
	int ret = EPKG_OK;
+
	if (idents == NULL)
+
		return (EPKG_OK);
+
	for (size_t i = 0; i < idents->len; i++) {
+
		if ((pkg_repo_find(idents->d[i])) == NULL) {
+
			pkg_emit_error("Unknown repository: %s", idents->d[i]);
+
			ret = EPKG_FATAL;
+
		}
	}
+
	if (ret == EPKG_FATAL)
+
		return (ret);

-
	j->reponame = ident;
+
	j->reponames = idents;

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

int
@@ -797,7 +815,7 @@ pkg_jobs_try_remote_candidate(struct pkg_jobs *j, const char *cond, const char *
	int rc = EPKG_FATAL;
	xstring *qmsg = NULL;

-
	if ((it = pkgdb_repo_query_cond(j->db, cond, pattern, m, j->reponame)) == NULL)
+
	if ((it = pkgdb_repo_query_cond2(j->db, cond, pattern, m, j->reponames)) == NULL)
		return (EPKG_FATAL);

	while (pkgdb_it_next(it, &p, flags) == EPKG_OK) {
@@ -882,7 +900,7 @@ pkg_jobs_find_upgrade(struct pkg_jobs *j, const char *pattern, match_t m)
			PKG_LOAD_ANNOTATIONS|PKG_LOAD_CONFLICTS;
	struct pkg_job_universe_item *unit = NULL;

-
	if ((it = pkgdb_repo_query(j->db, pattern, m, j->reponame)) == NULL)
+
	if ((it = pkgdb_repo_query2(j->db, pattern, m, j->reponames)) == NULL)
		return (rc);

	/*
@@ -1457,7 +1475,7 @@ pkg_jobs_check_remote_candidate(struct pkg_jobs *j, struct pkg *pkg)
	if (pkg->digest == NULL)
		return (true);

-
	it = pkgdb_repo_query(j->db, pkg->uid, MATCH_INTERNAL, j->reponame);
+
	it = pkgdb_repo_query2(j->db, pkg->uid, MATCH_INTERNAL, j->reponames);
	if (it != NULL) {
		/*
		 * If we have the same package in a remote repo, it is not an
modified libpkg/pkg_jobs_universe.c
@@ -130,8 +130,8 @@ pkg_jobs_universe_get_remote(struct pkg_jobs_universe *universe,
		}
	}

-
	if ((it = pkgdb_repo_query(universe->j->db, uid, MATCH_INTERNAL,
-
		universe->j->reponame)) == NULL)
+
	if ((it = pkgdb_repo_query2(universe->j->db, uid, MATCH_INTERNAL,
+
		universe->j->reponames)) == NULL)
		return (NULL);

	while (pkgdb_it_next(it, &pkg, flag) == EPKG_OK) {
@@ -491,7 +491,7 @@ pkg_jobs_universe_process_shlibs(struct pkg_jobs_universe *universe,
		}
		/* Not found, search in the repos */
		it = pkgdb_repo_shlib_provide(universe->j->db,
-
			s->item, universe->j->reponame);
+
			s->item, universe->j->reponames);

		if (it != NULL) {
			rc = pkg_jobs_universe_handle_provide(universe, it, s->item, true, pkg);
@@ -534,7 +534,7 @@ pkg_jobs_universe_process_provides_requires(struct pkg_jobs_universe *universe,

		/* Not found, search in the repos */
		it = pkgdb_repo_provide(universe->j->db,
-
			r->item, universe->j->reponame);
+
			r->item, universe->j->reponames);

		if (it != NULL) {
			rc = pkg_jobs_universe_handle_provide(universe, it, r->item, false, pkg);
@@ -1001,8 +1001,8 @@ pkg_jobs_universe_get_upgrade_candidates(struct pkg_jobs_universe *universe,
		}
	}

-
	if ((it = pkgdb_repo_query(universe->j->db, uid, MATCH_INTERNAL,
-
		universe->j->reponame)) == NULL)
+
	if ((it = pkgdb_repo_query2(universe->j->db, uid, MATCH_INTERNAL,
+
		universe->j->reponames)) == NULL)
		return (NULL);

	while (pkgdb_it_next(it, &pkg, flag) == EPKG_OK) {
modified libpkg/pkgdb.c
@@ -51,6 +51,7 @@
#include "private/utils.h"
#include "private/pkg_deps.h"
#include "tllist.h"
+
#include "pkgvec.h"

#include "private/db_upgrades.h"

@@ -711,7 +712,14 @@ out:
}

int
-
pkgdb_access(unsigned mode, unsigned database, ...)
+
pkgdb_access(unsigned mode, unsigned database)
+
{
+

+
	return (pkgdb_access2(mode, database, NULL));
+
}
+

+
int
+
pkgdb_access2(unsigned mode, unsigned database, c_charv_t *dbs)
{
	int			 retval = EPKG_OK;

@@ -764,25 +772,15 @@ pkgdb_access(unsigned mode, unsigned database, ...)
	}

	if ((database & PKGDB_DB_REPO) != 0) {
-
		va_list	ap;
		struct pkg_repo	*r = NULL;
-
		const char	*dbname;
-
		ucl_object_t *repos_seen = ucl_object_typed_new(UCL_OBJECT);
-

-
		va_start(ap, database);
-
		while((dbname = va_arg(ap, const char *)) != NULL) {
-
			ucl_object_insert_key(repos_seen, ucl_object_typed_new(UCL_BOOLEAN),
-
			    dbname, strlen(dbname), false);
-
		}
-
		va_end(ap);

		while (pkg_repos(&r) == EPKG_OK) {
			/* Ignore any repos marked as inactive */
			if (!pkg_repo_enabled(r))
				continue;

-
			if (repos_seen->len > 0 && r->name &&
-
			    !ucl_object_lookup(repos_seen, r->name)) {
+
			if (dbs != NULL && dbs->len > 0 && r->name &&
+
			    !c_charv_contains(dbs, r->name, true)) {
				/* Skip what is not needed */
				continue;
			}
@@ -796,13 +794,9 @@ pkgdb_access(unsigned mode, unsigned database, ...)
					    r->name);
				}

-
				ucl_object_unref(repos_seen);
-

				return (retval);
			}
		}
-

-
		ucl_object_unref(repos_seen);
	}
	return (retval);
}
@@ -832,6 +826,9 @@ pkgdb_open_repos(struct pkgdb *db, const char *reponame)
{
	struct pkg_repo *r = NULL;

+
	if (reponame != NULL) {
+
		printf("opening reponame: %s\n", reponame);
+
	}
	while (pkg_repos(&r) == EPKG_OK) {
		if (!r->enable && reponame == NULL) {
			continue;
@@ -978,6 +975,20 @@ pkgdb_nfs_corruption(sqlite3 *db)
int
pkgdb_open_all(struct pkgdb **db_p, pkgdb_t type, const char *reponame)
{
+
	c_charv_t r;
+
	int ret;
+

+
	pkgvec_init(&r);
+
	if (reponame != NULL)
+
		pkgvec_push(&r, reponame);
+

+
	ret = pkgdb_open_all2(db_p, type, &r);
+
	pkgvec_free(&r);
+
	return (ret);
+
}
+
int
+
pkgdb_open_all2(struct pkgdb **db_p, pkgdb_t type, c_charv_t *reponames)
+
{
	struct pkgdb	*db = NULL;
	bool		 reopen = false;
	bool		 profile = false;
@@ -1065,8 +1076,13 @@ retry:
	}

	if (type == PKGDB_REMOTE || type == PKGDB_MAYBE_REMOTE) {
-
		if (reponame != NULL || pkg_repos_activated_count() > 0) {
-
			ret = pkgdb_open_repos(db, reponame);
+
		if (pkg_repos_activated_count() > 0) {
+
			if (reponames == NULL || reponames->len == 0) {
+
				ret = pkgdb_open_repos(db, NULL);
+
			} else {
+
				for (size_t i = 0; i < reponames->len; i++)
+
					ret = pkgdb_open_repos(db, reponames->d[i]);
+
			}
			if (ret != EPKG_OK) {
				pkgdb_close(db);
				return (ret);
modified libpkg/pkgdb_query.c
@@ -34,6 +34,7 @@
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

+
#include "pkgvec.h"
#ifdef HAVE_CONFIG_H
#include "pkg_config.h"
#endif
@@ -380,10 +381,41 @@ pkgdb_query_provide(struct pkgdb *db, const char *req)
	return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
}

+
static bool
+
consider_this_repo(c_charv_t *repos, const char *name)
+
{
+
	/* All repositories */
+
	if (repos == NULL)
+
		return (true);
+

+
	if (repos->len == 0)
+
		return (true);
+

+
	return (c_charv_contains(repos, name, true));
+
}
+

struct pkgdb_it *
pkgdb_repo_query_cond(struct pkgdb *db, const char *cond, const char *pattern, match_t match,
    const char *repo)
{
+
	c_charv_t r;
+
	struct pkgdb_it *ret;
+

+
	pkgvec_init(&r);
+

+
	if (repo != NULL)
+
		pkgvec_push(&r, repo);
+

+
	ret = pkgdb_repo_query_cond2(db, cond, pattern, match, &r);
+
	pkgvec_free(&r);
+

+
	return (ret);
+
}
+

+
struct pkgdb_it *
+
pkgdb_repo_query_cond2(struct pkgdb *db, const char *cond, const char *pattern, match_t match,
+
    c_charv_t *repos)
+
{
	struct pkgdb_it *it;
	struct pkg_repo_it *rit;

@@ -392,7 +424,7 @@ pkgdb_repo_query_cond(struct pkgdb *db, const char *cond, const char *pattern, m
		return (NULL);

	tll_foreach(db->repos, cur) {
-
		if (repo == NULL || STRIEQ(cur->item->name, repo)) {
+
		if (consider_this_repo(repos, cur->item->name)) {
			if (pattern != NULL && *pattern == '@')
				rit = cur->item->ops->groupquery(cur->item, pattern + 1, match);
			else
@@ -411,8 +443,14 @@ struct pkgdb_it *pkgdb_repo_query(struct pkgdb *db, const char *pattern,
	return pkgdb_repo_query_cond(db, NULL, pattern, match, repo);
}

+
struct pkgdb_it *pkgdb_repo_query2(struct pkgdb *db, const char *pattern,
+
	match_t match, c_charv_t *repos)
+
{
+
	return pkgdb_repo_query_cond2(db, NULL, pattern, match, repos);
+
}
+

struct pkgdb_it *
-
pkgdb_repo_shlib_require(struct pkgdb *db, const char *require, const char *repo)
+
pkgdb_repo_shlib_require(struct pkgdb *db, const char *require, c_charv_t *repos)
{
	struct pkgdb_it *it;
	struct pkg_repo_it *rit;
@@ -422,7 +460,7 @@ pkgdb_repo_shlib_require(struct pkgdb *db, const char *require, const char *repo
		return (NULL);

	tll_foreach(db->repos, cur) {
-
		if (repo == NULL || STRIEQ(cur->item->name, repo)) {
+
		if (consider_this_repo(repos, cur->item->name)) {
			if (cur->item->ops->shlib_required != NULL) {
				rit = cur->item->ops->shlib_required(cur->item, require);
				if (rit != NULL)
@@ -435,7 +473,7 @@ pkgdb_repo_shlib_require(struct pkgdb *db, const char *require, const char *repo
}

struct pkgdb_it *
-
pkgdb_repo_shlib_provide(struct pkgdb *db, const char *require, const char *repo)
+
pkgdb_repo_shlib_provide(struct pkgdb *db, const char *require, c_charv_t *repos)
{
	struct pkgdb_it *it;
	struct pkg_repo_it *rit;
@@ -445,7 +483,7 @@ pkgdb_repo_shlib_provide(struct pkgdb *db, const char *require, const char *repo
		return (NULL);

	tll_foreach(db->repos, cur) {
-
		if (repo == NULL || STRIEQ(cur->item->name, repo)) {
+
		if (consider_this_repo(repos, cur->item->name)) {
			if (cur->item->ops->shlib_required != NULL) {
				rit = cur->item->ops->shlib_provided(cur->item, require);
				if (rit != NULL)
@@ -458,7 +496,7 @@ pkgdb_repo_shlib_provide(struct pkgdb *db, const char *require, const char *repo
}

struct pkgdb_it *
-
pkgdb_repo_require(struct pkgdb *db, const char *require, const char *repo)
+
pkgdb_repo_require(struct pkgdb *db, const char *require, c_charv_t *repo)
{
	struct pkgdb_it *it;
	struct pkg_repo_it *rit;
@@ -468,7 +506,7 @@ pkgdb_repo_require(struct pkgdb *db, const char *require, const char *repo)
		return (NULL);

	tll_foreach(db->repos, cur) {
-
		if (repo == NULL || STRIEQ(cur->item->name, repo)) {
+
		if (consider_this_repo(repo, cur->item->name)) {
			if (cur->item->ops->required != NULL) {
				rit = cur->item->ops->required(cur->item, require);
				if (rit != NULL)
@@ -481,7 +519,7 @@ pkgdb_repo_require(struct pkgdb *db, const char *require, const char *repo)
}

struct pkgdb_it *
-
pkgdb_repo_provide(struct pkgdb *db, const char *require, const char *repo)
+
pkgdb_repo_provide(struct pkgdb *db, const char *require, c_charv_t *repo)
{
	struct pkgdb_it *it;
	struct pkg_repo_it *rit;
@@ -491,7 +529,7 @@ pkgdb_repo_provide(struct pkgdb *db, const char *require, const char *repo)
		return (NULL);

	tll_foreach(db->repos, cur) {
-
		if (repo == NULL || STRIEQ(cur->item->name, repo)) {
+
		if (consider_this_repo(repo, cur->item->name)) {
			if (cur->item->ops->required != NULL) {
				rit = cur->item->ops->provided(cur->item, require);
				if (rit != NULL)
@@ -507,6 +545,23 @@ struct pkgdb_it *
pkgdb_repo_search(struct pkgdb *db, const char *pattern, match_t match,
    pkgdb_field field, pkgdb_field sort, const char *repo)
{
+
	c_charv_t r;
+
	struct pkgdb_it *ret;
+

+
	pkgvec_init(&r);
+
	if (repo != NULL)
+
		pkgvec_push(&r, repo);
+

+
	ret = pkgdb_repo_search2(db, pattern, match, field, sort, &r);
+
	pkgvec_free(&r);
+

+
	return (ret);
+
}
+

+
struct pkgdb_it *
+
pkgdb_repo_search2(struct pkgdb *db, const char *pattern, match_t match,
+
    pkgdb_field field, pkgdb_field sort, c_charv_t *repos)
+
{
	struct pkgdb_it *it;
	struct pkg_repo_it *rit;

@@ -515,7 +570,7 @@ pkgdb_repo_search(struct pkgdb *db, const char *pattern, match_t match,
		return (NULL);

	tll_foreach(db->repos, cur) {
-
		if (repo == NULL || STRIEQ(cur->item->name, repo)) {
+
		if (consider_this_repo(repos, cur->item->name)) {
			if (cur->item->ops->search != NULL) {
				rit = cur->item->ops->search(cur->item, pattern, match,
					field, sort);
@@ -537,13 +592,33 @@ struct pkgdb_it *
pkgdb_all_search(struct pkgdb *db, const char *pattern, match_t match,
    pkgdb_field field, pkgdb_field sort, const char *repo)
{
+
	c_charv_t r;
+
	struct pkgdb_it *ret;
+

+
	pkgvec_init(&r);
+

+
	if (repo != NULL)
+
		pkgvec_push(&r, repo);
+

+
	ret = pkgdb_all_search2(db, pattern, match, field, sort, &r);
+

+
	pkgvec_free(&r);
+

+
	return (ret);
+
}
+

+
struct pkgdb_it *
+
pkgdb_all_search2(struct pkgdb *db, const char *pattern, match_t match,
+
    pkgdb_field field, pkgdb_field sort, c_charv_t *repos)
+
{
	struct pkgdb_it *it;
	struct pkg_repo_it *rit;

+

	it = pkgdb_query(db, pattern, match);

	tll_foreach(db->repos, cur) {
-
		if (repo == NULL || STRIEQ(cur->item->name, repo)) {
+
		if (consider_this_repo(repos, cur->item->name)) {
			if (cur->item->ops->search != NULL) {
				rit = cur->item->ops->search(cur->item, pattern, match,
					field, sort);
modified libpkg/pkgvec.h
@@ -4,7 +4,7 @@
#include <stddef.h>

#define pkgvec_t(Type) \
-
  struct { Type *d; int len, cap; }
+
  struct { Type *d; size_t len, cap; }

#define pkgvec_init(v) \
	memset((v), 0, sizeof(*(v)))
modified libpkg/private/pkg_jobs.h
@@ -132,7 +132,7 @@ struct pkg_jobs {
	int total;
	int conflicts_registered;
	bool need_fetch;
-
	const char *reponame;
+
	c_charv_t *reponames;
	const char *destdir;
	TREE_HEAD(, pkg_jobs_conflict_item) *conflict_items;
	struct job_pattern *patterns;
modified libpkg/private/pkgdb.h
@@ -114,7 +114,7 @@ const char * pkgdb_get_pattern_query(const char *pattern, match_t match);
 * @return
 */
struct pkgdb_it *pkgdb_repo_shlib_require(struct pkgdb *db,
-
		const char *provide, const char *repo);
+
		const char *provide, c_charv_t *repos);
/**
 * Find requires for a specified provide in repos
 * @param db
@@ -123,13 +123,11 @@ struct pkgdb_it *pkgdb_repo_shlib_require(struct pkgdb *db,
 * @return
 */
struct pkgdb_it *pkgdb_repo_shlib_provide(struct pkgdb *db,
-
		const char *require, const char *repo);
+
		const char *require, c_charv_t *repos);

-
struct pkgdb_it *pkgdb_repo_provide(struct pkgdb *db, const char *require,
-
    const char *repo);
+
struct pkgdb_it *pkgdb_repo_provide(struct pkgdb *db, const char *require, c_charv_t *repo);

-
struct pkgdb_it *pkgdb_repo_require(struct pkgdb *db, const char *provide,
-
    const char *repo);
+
struct pkgdb_it *pkgdb_repo_require(struct pkgdb *db, const char *provide, c_charv_t *repo);

/**
 * Unregister a package from the database
modified src/add.c
@@ -121,7 +121,7 @@ exec_add(int argc, char **argv)
	retcode = pkgdb_access(PKGDB_MODE_READ  |
			       PKGDB_MODE_WRITE |
			       PKGDB_MODE_CREATE,
-
			       PKGDB_DB_LOCAL, NULL);
+
			       PKGDB_DB_LOCAL);
	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to add packages");
		return (EXIT_FAILURE);
modified src/clean.c
@@ -329,7 +329,7 @@ exec_clean(int argc, char **argv)
		return (errno == ENOENT ? EXIT_SUCCESS : EXIT_FAILURE);
	}

-
	retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO, NULL);
+
	retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO);

	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to clean old packages");
modified src/fetch.c
@@ -56,7 +56,6 @@ exec_fetch(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
	struct pkg_jobs	*jobs = NULL;
-
	const char	*reponame = NULL;
	const char *destdir = NULL;
	int		 ch;
	int		 retcode;
@@ -65,6 +64,7 @@ exec_fetch(int argc, char **argv)
	unsigned	 mode;
	match_t		 match = MATCH_EXACT;
	pkg_flags	 f = PKG_FLAG_NONE;
+
	c_charv_t	reponames;

	struct option longopts[] = {
		{ "all",		no_argument,		NULL,	'a' },
@@ -82,6 +82,7 @@ exec_fetch(int argc, char **argv)
		{ NULL,			0,			NULL,	0   },
	};

+
	pkgvec_init(&reponames);
	while ((ch = getopt_long(argc, argv, "+aCdgiqr:Uuxyo:", longopts, NULL)) != -1) {
		switch (ch) {
		case 'a':
@@ -103,7 +104,7 @@ exec_fetch(int argc, char **argv)
			quiet = true;
			break;
		case 'r':
-
			reponame = optarg;
+
			pkgvec_push(&reponames, optarg);
			break;
		case 'u':
			f |= PKG_FLAG_UPGRADES_FOR_INSTALLED;
@@ -145,7 +146,7 @@ exec_fetch(int argc, char **argv)
	else
		mode = PKGDB_MODE_READ;

-
	retcode = pkgdb_access(mode, PKGDB_DB_REPO, reponame, NULL);
+
	retcode = pkgdb_access2(mode, PKGDB_DB_REPO, &reponames);

	if (retcode == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to access repo catalogue");
@@ -165,10 +166,10 @@ exec_fetch(int argc, char **argv)

	/* first update the remote repositories if needed */
	if (auto_update &&
-
	    (retcode = pkgcli_update(false, false, reponame)) != EPKG_OK)
+
	    (retcode = pkgcli_update(false, false, &reponames)) != EPKG_OK)
		return (retcode);

-
	if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK)
+
	if (pkgdb_open_all2(&db, PKGDB_REMOTE, &reponames) != EPKG_OK)
		return (EXIT_FAILURE);

	if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
@@ -181,7 +182,7 @@ exec_fetch(int argc, char **argv)
	if (pkg_jobs_new(&jobs, PKG_JOBS_FETCH, db) != EPKG_OK)
		goto cleanup;

-
	if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
+
	if (pkg_jobs_set_repositories(jobs, &reponames) != EPKG_OK)
		goto cleanup;

	if (destdir != NULL && pkg_jobs_set_destdir(jobs, destdir) != EPKG_OK)
modified src/install.c
@@ -56,7 +56,6 @@ exec_install(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
	struct pkg_jobs	*jobs = NULL;
-
	const char	*reponame = NULL;
	int		 retcode;
	int		 status;
	int		 updcode = EPKG_OK;
@@ -68,6 +67,7 @@ exec_install(int argc, char **argv)
	bool		 local_only = false;
	match_t		 match = MATCH_EXACT;
	pkg_flags	 f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;
+
	c_charv_t	reponames;

	struct option longopts[] = {
		{ "automatic",		no_argument,		NULL,	'A' },
@@ -98,6 +98,7 @@ exec_install(int argc, char **argv)
		quiet = true;
	}

+
	pkgvec_init(&reponames);
	while ((ch = getopt_long(argc, argv, "+ACfFgiIlMnqr:RUxy", longopts, NULL)) != -1) {
		switch (ch) {
		case 'A':
@@ -138,7 +139,7 @@ exec_install(int argc, char **argv)
			quiet = true;
			break;
		case 'r':
-
			reponame = optarg;
+
			pkgvec_push(&reponames, optarg);
			break;
		case 'R':
			f |= PKG_FLAG_RECURSIVE;
@@ -177,12 +178,12 @@ exec_install(int argc, char **argv)
		repo_type = PKGDB_DB_LOCAL|PKGDB_DB_REPO;

	/* It is safe to use both `reponame` and `NULL` here */
-
	retcode = pkgdb_access(mode, repo_type, reponame, NULL);
+
	retcode = pkgdb_access2(mode, repo_type, &reponames);

	if (retcode == EPKG_ENOACCESS && dry_run) {
		auto_update = false;
-
		retcode = pkgdb_access(PKGDB_MODE_READ,
-
				       repo_type, reponame, NULL);
+
		retcode = pkgdb_access2(PKGDB_MODE_READ,
+
				       repo_type, &reponames);
	}

	if (retcode == EPKG_ENOACCESS) {
@@ -193,12 +194,12 @@ exec_install(int argc, char **argv)

	/* first update the remote repositories if needed */
	if (auto_update && pkg_repos_total_count() > 0 &&
-
	    (updcode = pkgcli_update(false, false, reponame)) != EPKG_OK)
+
	    (updcode = pkgcli_update(false, false, &reponames)) != EPKG_OK)
		return (updcode);

-
	if (pkgdb_open_all(&db,
+
	if (pkgdb_open_all2(&db,
	    local_only ? PKGDB_DEFAULT : PKGDB_MAYBE_REMOTE,
-
	    reponame) != EPKG_OK)
+
	    &reponames) != EPKG_OK)
		return (EXIT_FAILURE);

	if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) {
@@ -211,8 +212,8 @@ exec_install(int argc, char **argv)
	if (pkg_jobs_new(&jobs, PKG_JOBS_INSTALL, db) != EPKG_OK)
		goto cleanup;

-
	if (!local_only && reponame != NULL &&
-
			pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
+
	if (!local_only && reponames.len > 0 &&
+
			pkg_jobs_set_repositories(jobs, &reponames) != EPKG_OK)
		goto cleanup;

	pkg_jobs_set_flags(jobs, f);
modified src/pkgcli.h
@@ -34,6 +34,7 @@
#include <string.h>
#include <xstring.h>
#include <bsd_compat.h>
+
#include <pkgvec.h>

#define pkg_warnx(fmt, ...) pkg_fprintf(stderr, "%S: " fmt, getprogname(), __VA_ARGS__, -1)
#define ll_foreach(head, el) for (el=head; el != NULL; el = (el)->next)
@@ -145,7 +146,7 @@ void usage_triggers(void);
/* pkg update */
int exec_update(int, char **);
void usage_update(void);
-
int pkgcli_update(bool, bool, const char *);
+
int pkgcli_update(bool, bool, c_charv_t *);

/* pkg updating */
int exec_updating(int, char **);
modified src/rquery.c
@@ -118,10 +118,10 @@ exec_rquery(int argc, char **argv)
	const char		*portsdir;
	xstring			*sqlcond = NULL;
	const unsigned int	 q_flags_len = NELEM(accepted_rquery_flags);
-
	const char		*reponame = NULL;
	bool			 onematched = false;
	bool			 old_quiet;
	bool			 index_output = false;
+
	c_charv_t		reponames;

	struct option longopts[] = {
		{ "all",		no_argument,		NULL,	'a' },
@@ -138,6 +138,7 @@ exec_rquery(int argc, char **argv)

	portsdir = pkg_object_string(pkg_config_get("PORTSDIR"));

+
	pkgvec_init(&reponames);
	while ((ch = getopt_long(argc, argv, "+aCgiIxe:r:U", longopts, NULL)) != -1) {
		switch (ch) {
		case 'a':
@@ -159,7 +160,7 @@ exec_rquery(int argc, char **argv)
			index_output = true;
			break;
		case 'r':
-
			reponame = optarg;
+
			pkgvec_push(&reponames, optarg);
			break;
		case 'U':
			auto_update = false;
@@ -205,7 +206,7 @@ exec_rquery(int argc, char **argv)
		}
	}

-
	ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO, reponame, NULL);
+
	ret = pkgdb_access2(PKGDB_MODE_READ, PKGDB_DB_REPO, &reponames);
	if (ret == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to query the package database");
		xstring_free(sqlcond);
@@ -218,13 +219,13 @@ exec_rquery(int argc, char **argv)
	/* first update the remote repositories if needed */
	old_quiet = quiet;
	quiet = true;
-
	if (auto_update && (ret = pkgcli_update(false, false, reponame)) != EPKG_OK) {
+
	if (auto_update && (ret = pkgcli_update(false, false, &reponames)) != EPKG_OK) {
		xstring_free(sqlcond);
		return (ret);
	}
	quiet = old_quiet;

-
	ret = pkgdb_open_all(&db, PKGDB_REMOTE, reponame);
+
	ret = pkgdb_open_all2(&db, PKGDB_REMOTE, &reponames);
	if (ret != EPKG_OK) {
		xstring_free(sqlcond);
		return (EXIT_FAILURE);
@@ -239,7 +240,7 @@ exec_rquery(int argc, char **argv)
		condition_sql = sqlcond->buf;
	}
	if (match == MATCH_ALL) {
-
		if ((it = pkgdb_repo_query_cond(db, condition_sql, NULL, match, reponame)) == NULL) {
+
		if ((it = pkgdb_repo_query_cond2(db, condition_sql, NULL, match, &reponames)) == NULL) {
			xstring_free(sqlcond);
			return (EXIT_FAILURE);
		}
@@ -259,7 +260,7 @@ exec_rquery(int argc, char **argv)
		for (i = (index_output ? 0 : 1); i < argc; i++) {
			pkgname = argv[i];

-
			if ((it = pkgdb_repo_query_cond(db, condition_sql, pkgname, match, reponame)) == NULL) {
+
			if ((it = pkgdb_repo_query_cond2(db, condition_sql, pkgname, match, &reponames)) == NULL) {
				xstring_free(sqlcond);
				return (EXIT_FAILURE);
			}
modified src/search.c
@@ -243,7 +243,6 @@ int
exec_search(int argc, char **argv)
{
	const char	*pattern = NULL;
-
	const char	*reponame = NULL;
	int		 ret = EPKG_OK, ch;
	int		 flags;
	uint64_t	 opt = 0;
@@ -255,6 +254,7 @@ exec_search(int argc, char **argv)
	struct pkg	*pkg = NULL;
	bool		 atleastone = false;
	bool		 old_quiet;
+
	c_charv_t	reponames;

	struct option longopts[] = {
		{ "case-sensitive",	no_argument,		NULL,	'C' },
@@ -280,6 +280,7 @@ exec_search(int argc, char **argv)
		{ NULL,			0,			NULL,	0   },
	};

+
	pkgvec_init(&reponames);
	while ((ch = getopt_long(argc, argv, "+CcDdefgiL:opqQ:r:RS:sUx", longopts, NULL)) != -1) {
		switch (ch) {
		case 'C':
@@ -322,7 +323,7 @@ exec_search(int argc, char **argv)
			opt |= modifier_opt(optarg);
			break;
		case 'r':
-
			reponame = optarg;
+
			pkgvec_push(&reponames, optarg);
			break;
		case 'R':
			opt = INFO_RAW;
@@ -415,7 +416,7 @@ exec_search(int argc, char **argv)
		quiet = false;
	}

-
	ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO, reponame, NULL);
+
	ret = pkgdb_access2(PKGDB_MODE_READ, PKGDB_DB_REPO, &reponames);
	switch(ret) {
	case EPKG_ENOACCESS:
		warnx("Insufficient privileges to query the package database");
@@ -435,15 +436,15 @@ exec_search(int argc, char **argv)
	/* first update the remote repositories if needed */
	old_quiet = quiet;
	quiet = true;
-
	if (auto_update && (ret = pkgcli_update(false, false, reponame)) != EPKG_OK)
+
	if (auto_update && (ret = pkgcli_update(false, false, &reponames)) != EPKG_OK)
		return (ret);
	quiet = old_quiet;

-
	if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK)
+
	if (pkgdb_open_all2(&db, PKGDB_REMOTE, &reponames) != EPKG_OK)
		return (EXIT_FAILURE);

-
	if ((it = pkgdb_repo_search(db, pattern, match, search, search,
-
	    reponame)) == NULL) {
+
	if ((it = pkgdb_repo_search2(db, pattern, match, search, search,
+
	    &reponames)) == NULL) {
		pkgdb_close(db);
		return (EXIT_FAILURE);
	}
modified src/update.c
@@ -41,18 +41,28 @@

#include "pkgcli.h"

+
static bool
+
_find_repo(c_charv_t *reponames, const char *name)
+
{
+
	for (size_t i = 0; i < reponames->len; i++) {
+
		if (STREQ(name, reponames->d[i]))
+
			return (true);
+
	}
+
	return(false);
+
}
+

/**
 * Fetch repository calalogues.
 */
int
-
pkgcli_update(bool force, bool strict, const char *reponame)
+
pkgcli_update(bool force, bool strict, c_charv_t *reponames)
{
	int retcode = EPKG_FATAL, update_count = 0, total_count = 0;
	struct pkg_repo *r = NULL;

	/* Only auto update if the user has write access. */
-
	if (pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE|PKGDB_MODE_CREATE,
-
	    PKGDB_DB_REPO, reponame, NULL) == EPKG_ENOACCESS)
+
	if (pkgdb_access2(PKGDB_MODE_READ|PKGDB_MODE_WRITE|PKGDB_MODE_CREATE,
+
	    PKGDB_DB_REPO, reponames) == EPKG_ENOACCESS)
		return (EPKG_OK);

	if (pkg_repos_total_count() == 0) {
@@ -61,8 +71,8 @@ pkgcli_update(bool force, bool strict, const char *reponame)
	}

	while (pkg_repos(&r) == EPKG_OK) {
-
		if (reponame != NULL) {
-
			if (!STREQ(pkg_repo_name(r), reponame))
+
		if (reponames->len > 0 ) {
+
			if (!_find_repo(reponames, pkg_repo_name(r)))
				continue;
		} else {
			if (!pkg_repo_enabled(r))
@@ -133,7 +143,7 @@ exec_update(int argc, char **argv)
{
	int		 ret;
	int		 ch;
-
	const char	*reponame = NULL;
+
	c_charv_t 	reponames;

	struct option longopts[] = {
		{ "force",	no_argument,		NULL,	'f' },
@@ -142,6 +152,7 @@ exec_update(int argc, char **argv)
		{ NULL,		0,			NULL,	0   },
	};

+
	pkgvec_init(&reponames);
	while ((ch = getopt_long(argc, argv, "+fqr:", longopts, NULL)) != -1) {
		switch (ch) {
		case 'f':
@@ -151,7 +162,7 @@ exec_update(int argc, char **argv)
			quiet = true;
			break;
		case 'r':
-
			reponame = optarg;
+
			pkgvec_push(&reponames, optarg);
			break;
		default:
			usage_update();
@@ -165,8 +176,8 @@ exec_update(int argc, char **argv)
		return (EXIT_FAILURE);
	}

-
	ret = pkgdb_access(PKGDB_MODE_WRITE|PKGDB_MODE_CREATE,
-
			   PKGDB_DB_REPO, reponame, NULL);
+
	ret = pkgdb_access2(PKGDB_MODE_WRITE|PKGDB_MODE_CREATE,
+
			   PKGDB_DB_REPO, &reponames);
	if (ret == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to update the repository "
		      "catalogue.");
@@ -175,7 +186,7 @@ exec_update(int argc, char **argv)
		return (EXIT_FAILURE);

	/* For pkg-update update op is strict */
-
	ret = pkgcli_update(force, true, reponame);
+
	ret = pkgcli_update(force, true, &reponames);

	return ((ret == EPKG_OK) ? EXIT_SUCCESS : EXIT_FAILURE);
}
modified src/upgrade.c
@@ -238,7 +238,6 @@ exec_upgrade(int argc, char **argv)
{
	struct pkgdb	*db = NULL;
	struct pkg_jobs	*jobs = NULL;
-
	const char	*reponame = NULL;
	int		 retcode;
	int		 updcode;
	int		 ch;
@@ -247,6 +246,7 @@ exec_upgrade(int argc, char **argv)
	int		 done = 0;
	bool	rc = true;
	pkg_flags	 f = PKG_FLAG_NONE | PKG_FLAG_PKG_VERSION_TEST;
+
	c_charv_t	reponames;

	struct option longopts[] = {
		{ "case-sensitive",	no_argument,		NULL,	'C' },
@@ -266,6 +266,7 @@ exec_upgrade(int argc, char **argv)
	};

	nbactions = nbdone = 0;
+
	pkgvec_init(&reponames);

	while ((ch = getopt_long(argc, argv, "+CfFgiInqr:Uxyv", longopts, NULL)) != -1) {
		switch (ch) {
@@ -297,7 +298,7 @@ exec_upgrade(int argc, char **argv)
			quiet = true;
			break;
		case 'r':
-
			reponame = optarg;
+
			pkgvec_push(&reponames, optarg);
			break;
		case 'U':
			auto_update = false;
@@ -321,17 +322,17 @@ exec_upgrade(int argc, char **argv)
	argv += optind;

	if (dry_run && !auto_update)
-
		retcode = pkgdb_access(PKGDB_MODE_READ,
-
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO, reponame, NULL);
+
		retcode = pkgdb_access2(PKGDB_MODE_READ,
+
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO, &reponames);
	else
-
		retcode = pkgdb_access(PKGDB_MODE_READ  |
+
		retcode = pkgdb_access2(PKGDB_MODE_READ  |
				       PKGDB_MODE_WRITE |
				       PKGDB_MODE_CREATE,
-
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO, reponame, NULL);
+
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO, &reponames);
	if (retcode == EPKG_ENOACCESS && dry_run) {
		auto_update = false;
-
		retcode = pkgdb_access(PKGDB_MODE_READ,
-
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO, reponame, NULL);
+
		retcode = pkgdb_access2(PKGDB_MODE_READ,
+
				       PKGDB_DB_LOCAL|PKGDB_DB_REPO, &reponames);
	}

	if (retcode == EPKG_ENOACCESS) {
@@ -344,10 +345,10 @@ exec_upgrade(int argc, char **argv)

	/* first update the remote repositories if needed */
	if (auto_update &&
-
	    (updcode = pkgcli_update(false, false, reponame)) != EPKG_OK)
+
	    (updcode = pkgcli_update(false, false, &reponames)) != EPKG_OK)
		return (updcode);

-
	if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK)
+
	if (pkgdb_open_all2(&db, PKGDB_REMOTE, &reponames) != EPKG_OK)
		return (EXIT_FAILURE);

	if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) {
@@ -359,7 +360,7 @@ exec_upgrade(int argc, char **argv)
	if (pkg_jobs_new(&jobs, PKG_JOBS_UPGRADE, db) != EPKG_OK)
		goto cleanup;

-
	if (reponame != NULL && pkg_jobs_set_repository(jobs, reponame) != EPKG_OK)
+
	if (reponames.len > 0 && pkg_jobs_set_repositories(jobs, &reponames) != EPKG_OK)
		goto cleanup;

	pkg_jobs_set_flags(jobs, f);
modified src/version.c
@@ -389,7 +389,7 @@ have_indexfile(const char **indexfile, char *filebuf, size_t filebuflen,

	if (show_error && !have_indexfile)
		warn("Can't access %s", *indexfile);
-
	
+

	return (have_indexfile);
}

@@ -463,7 +463,7 @@ cleanup:

static int
do_source_remote(unsigned int opt, char limchar, char *pattern, match_t match,
-
    bool auto_update, const char *reponame, const char *matchorigin,
+
    bool auto_update, c_charv_t *reponames, const char *matchorigin,
    const char *matchname)
{
	struct pkgdb	*db = NULL;
@@ -486,14 +486,14 @@ do_source_remote(unsigned int opt, char limchar, char *pattern, match_t match,
	   user is forced to have a repo.sqlite */

	if (auto_update) {
-
		retcode = pkgcli_update(false, false, reponame);
+
		retcode = pkgcli_update(false, false, reponames);
		if (retcode != EPKG_OK)
			return (retcode);
		else
			retcode = EXIT_FAILURE;
	}

-
	if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK)
+
	if (pkgdb_open_all2(&db, PKGDB_REMOTE, reponames) != EPKG_OK)
		return (EXIT_FAILURE);

	if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
@@ -525,7 +525,7 @@ do_source_remote(unsigned int opt, char limchar, char *pattern, match_t match,
			continue;
		}

-
		it_remote = pkgdb_repo_query(db, is_origin ? origin : name, MATCH_EXACT, reponame);
+
		it_remote = pkgdb_repo_query2(db, is_origin ? origin : name, MATCH_EXACT, reponames);
		if (it_remote == NULL) {
			retcode = EXIT_FAILURE;
			goto cleanup;
@@ -798,7 +798,6 @@ exec_version(int argc, char **argv)
	char		 limchar = '-';
	const char	*matchorigin = NULL;
	const char	*matchname = NULL;
-
	const char	*reponame = NULL;
	const char	*portsdir;
	const char	*indexfile;
	const char	*versionsource;
@@ -806,6 +805,7 @@ exec_version(int argc, char **argv)
	match_t		 match = MATCH_ALL;
	char		*pattern = NULL;
	int		 ch;
+
	c_charv_t	reponames;

	struct option longopts[] = {
		{ "case-sensitive",	no_argument,		NULL,	'C' },
@@ -831,6 +831,7 @@ exec_version(int argc, char **argv)
		{ NULL,			0,			NULL,	0   },
	};

+
	pkgvec_init(&reponames);
	while ((ch = getopt_long(argc, argv, "+Ce:g:hIiL:l:n:O:oPqRr:TtUvx:",
				 longopts, NULL)) != -1) {
		switch (ch) {
@@ -884,7 +885,7 @@ exec_version(int argc, char **argv)
			break;
		case 'r':
			opt |= VERSION_SOURCE_REMOTE;
-
			reponame = optarg;
+
			pkgvec_push(&reponames, optarg);
			break;
		case 'T':
			opt |= VERSION_TESTPATTERN;
@@ -979,7 +980,7 @@ exec_version(int argc, char **argv)

	if ( (opt & VERSION_SOURCE_REMOTE) == VERSION_SOURCE_REMOTE )
		return (do_source_remote(opt, limchar, pattern, match,
-
			    auto_update, reponame, matchorigin, matchname));
+
			    auto_update, &reponames, matchorigin, matchname));

	if ( (opt & VERSION_SOURCE_PORTS) == VERSION_SOURCE_PORTS ) {
		if (!have_ports(&portsdir, true))
@@ -1009,7 +1010,7 @@ exec_version(int argc, char **argv)
	} else {
		opt |= VERSION_SOURCE_REMOTE;
		return (do_source_remote(opt, limchar, pattern, match,
-
			    auto_update, reponame, matchorigin, matchname));
+
			    auto_update, &reponames, matchorigin, matchname));
	}

	/* NOTREACHED */