Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
New repos entry in pkg.conf
Baptiste Daroussin committed 14 years ago
commit 90d63ed7da333abd5dd480c8882a920db61d0d2b
parent 8b08809
5 files changed +190 -330
modified libpkg/pkg.h
@@ -203,8 +203,14 @@ typedef enum _pkg_config_key {
	PKG_CONFIG_MULTIREPOS = 5,
	PKG_CONFIG_HANDLE_RC_SCRIPTS = 6,
	PKG_CONFIG_ASSUME_ALWAYS_YES = 7,
+
	PKG_CONFIG_REPOS = 8
} pkg_config_key;

+
typedef enum {
+
	PKG_CONFIG_KV_KEY,
+
	PKG_CONFIG_KV_VALUE
+
} pkg_config_kv_t;
+

/**
 * Error type used everywhere by libpkg.
 */
@@ -738,6 +744,7 @@ int pkg_repo_verify(const char *path, unsigned char *sig, unsigned int sig_len);
int pkg_config_string(pkg_config_key key, const char **value);
int pkg_config_bool(pkg_config_key key, bool *value);
int pkg_config_list(pkg_config_key key, struct pkg_config_kv **kv);
+
const char *pkg_config_kv_get(struct pkg_config_kv *kv, pkg_config_kv_t type);

/**
 * @todo Document
@@ -774,9 +781,9 @@ int pkg_repos_load(struct pkg_repos *repos);
 * Adds a repository entry found from the repositories file to the tail
 * @param repos A valid repository object as returned by pkg_repos_new()
 * @param re A valid repository entry object
-
 * @return EPKG_OK on success and EPKG_FATAL on error
+
 * @return nothing
 */
-
int pkg_repos_add(struct pkg_repos *repos, struct pkg_repos_entry *re);
+
void pkg_repos_add(struct pkg_repos *repos, struct pkg_repos_entry *re);

/**
 * Get the next repository from the configuration file
@@ -788,22 +795,6 @@ int pkg_repos_add(struct pkg_repos *repos, struct pkg_repos_entry *re);
int pkg_repos_next(struct pkg_repos *repos, struct pkg_repos_entry **re);

/**
-
 * Switches to a single repository while running in multi-repos mode
-
 * @param repos A valid repository object as returned by pkg_repos_new()
-
 * @param reponame The name of the repository to switch to
-
 * @return EPKG_OK if switching to reponame was successful and EPKG_FATAL
-
 * in case of error, e.g. repository does not exists
-
 */
-
int pkg_repos_switch(struct pkg_repos *repos, const char *reponame);
-

-
/**
-
 * Switches back to multi-repos mode and resets any switchable repos
-
 * @param repos A valid repository object as returned by pkg_repos_new()
-
 * @return EPKG_OK on success
-
 */
-
int pkg_repos_switch_reset(struct pkg_repos *repos);
-

-
/**
 * Frees the memory used by the repository objects
 * @param repos A valid repository object as returned by pkg_repos_new()
 */
modified libpkg/pkg_config.c
@@ -1,6 +1,7 @@
#include <sys/types.h>
#include <sys/queue.h>

+
#include <assert.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
@@ -78,7 +79,13 @@ static struct config_entry c[] = {
		"ASSUME_ALWAYS_YES",
		NULL,
		{ NULL }
-
	}, 
+
	},
+
	[PKG_CONFIG_REPOS] = {
+
		LIST,
+
		"REPOS",
+
		"NULL",
+
		{ NULL }
+
	}
};

static bool parsed = false;
@@ -197,6 +204,22 @@ pkg_config_list(pkg_config_key key, struct pkg_config_kv **kv)
		return (EPKG_OK);
}

+
const char *
+
pkg_config_kv_get(struct pkg_config_kv *kv, pkg_config_kv_t type)
+
{
+
	assert(kv != NULL);
+

+
	switch (type) {
+
		case PKG_CONFIG_KV_KEY:
+
			return (kv->key);
+
			break;
+
		case PKG_CONFIG_KV_VALUE:
+
			return (kv->value);
+
			break;
+
	}
+
	return (NULL);
+
}
+

int
pkg_init(const char *path)
{
modified libpkg/pkg_private.h
@@ -114,14 +114,11 @@ struct pkg_jobs_node {

struct pkg_repos {
	struct pkg_repos_entry {
-
		struct sbuf *name;
-
		struct sbuf *url;
-
		unsigned int line;
-
		unsigned int switched :1;
+
		const char *name;
+
		const char *url;
		STAILQ_ENTRY(pkg_repos_entry) entries;
	} re;

-
	unsigned int switchable :1;
	STAILQ_HEAD(repos, pkg_repos_entry) nodes;
};

modified libpkg/pkg_repo.c
@@ -21,21 +21,18 @@
#include "pkg_event.h"
#include "pkg_private.h"

-
static int pkg_repos_is_reserved_name(struct pkg_repos *repos, struct pkg_repos_entry *re);
-

-
static int
-
pkg_repos_is_reserved_name(struct pkg_repos *repos, struct pkg_repos_entry *re)
+
static bool
+
pkg_repos_is_reserved_name(struct pkg_repos *repos, const char *repo_name)
{
-
        struct pkg_repos_entry *next = NULL;
-
	const  char *repo_name = NULL;
+
	struct pkg_repos_entry *next = NULL;

-
        assert(repos != NULL && re != NULL);
+
	assert(repos != NULL && repo_name != NULL);

-
        /* 
-
         * Find if a repository name already exists.
+
	/* 
+
	 * Find if a repository name already exists.
	 *
-
         * NOTE1: The 'repo' name is always reserved, 
-
         * as it is being used by default when 
+
	 * NOTE1: The 'repo' name is always reserved, 
+
	 * as it is being used by default when 
	 * working on a single remote repository,
	 * which means that PACKAGESITE is defined.
	 *
@@ -47,21 +44,19 @@ pkg_repos_is_reserved_name(struct pkg_repos *repos, struct pkg_repos_entry *re)
	 *
	 * NOTE3: The 'local' name is always reserved,
	 * because this is the name of the local database.
-
         */
-
	
-
	repo_name = pkg_repos_get_name(re);
+
	 */

	if ((strcmp(repo_name, "repo") == 0) ||
	    (strcmp(repo_name, "main") == 0) ||
	    (strcmp(repo_name, "temp") == 0) ||
	    (strcmp(repo_name, "local") == 0))
-
		return (EPKG_FATAL);
+
		return (true);

-
        while (pkg_repos_next(repos, &next) == EPKG_OK)
-
                if ((strcmp(repo_name, pkg_repos_get_name(next)) == 0))
-
                        return (EPKG_FATAL);
+
	while (pkg_repos_next(repos, &next) == EPKG_OK)
+
		if ((strcmp(repo_name, pkg_repos_get_name(next)) == 0))
+
			return (true);

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

int
@@ -169,130 +164,52 @@ pkg_repos_new(struct pkg_repos **repos)
int
pkg_repos_load(struct pkg_repos *repos)
{
-
        FILE *fp = NULL;
-
        char *repo_buf[MAXPATHLEN];
-
        char buf[MAXPATHLEN];
-
        char *token = NULL, *tmp = NULL;
-
        unsigned int count = 0, line = 0;
-
        struct pkg_repos_entry *re = NULL;
+
	struct pkg_config_kv *repokv;
+
	struct pkg_repos_entry *re;
+
	const char *repo_name;

        assert(repos != NULL);

-
        if ((fp = fopen("/etc/pkg/repositories", "r")) == NULL) {
-
                pkg_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;
-

-
		/* only name and url are needed for the repository */
-
                if (count != 2) {
-
                        pkg_emit_error("Wrong repository format at line %d (ignoring repository)", line);
-
                        continue;
-
                }
-

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

-
		sbuf_set(&re->name, repo_buf[0]);
-
		sbuf_set(&re->url, repo_buf[1]);
-
                re->line = line;
-

-
                pkg_repos_add(repos, re);
-
        }
-

-
        fclose(fp);
-

-
        return (EPKG_OK);
-
}
-

-
int
-
pkg_repos_add(struct pkg_repos *repos, struct pkg_repos_entry *re)
-
{
-
        assert(repos != NULL && re != NULL);
-

-
        if (pkg_repos_is_reserved_name(repos, re) != EPKG_OK) {
-
                pkg_emit_error("Repository name '%s' is already reserved (ignoring repository at line %d)",
-
                                pkg_repos_get_name(re), pkg_repos_get_line(re));
-

-
                sbuf_free(re->name);
-
		sbuf_free(re->url);
-
                free(re);
-

-
                return (EPKG_FATAL);
-
        }
-

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

-
        return (EPKG_OK);
-
}
-

-
int
-
pkg_repos_next(struct pkg_repos *repos, struct pkg_repos_entry **re)
-
{
-
        assert(repos != NULL);
+
	while (pkg_config_list(PKG_CONFIG_REPOS, &repokv) == EPKG_OK) {
+
		repo_name = pkg_config_kv_get(repokv, PKG_CONFIG_KV_KEY);
+
		if (pkg_repos_is_reserved_name(repos, repo_name)) {
+
			pkg_emit_error("Repository name '%s' is already reserved, ignoring",
+
                                repo_name);
+
			continue;
+
		}

-
        if (*re == NULL)
-
                *re = STAILQ_FIRST(&repos->nodes);
-
        else
-
                *re = STAILQ_NEXT(*re, entries);
+
		if ((re = calloc(1, sizeof(struct pkg_repos_entry))) == NULL) {
+
			pkg_emit_errno("calloc", "pkg_repos_entry");
+
			 return (EPKG_FATAL);
+
		 }

-
        if (*re == NULL)
-
                return (EPKG_END);
+
		re->name = repo_name;
+
		re->url = pkg_config_kv_get(repokv, PKG_CONFIG_KV_VALUE);

-
	 /* Check if we have switched to a repo */
-
	if (repos->switchable == 1) {
-
		if ((*re)->switched == 1)
-
			return (EPKG_OK);
-
		else
-
			return(pkg_repos_next(repos, re));
+
		pkg_repos_add(repos, re);
	}

	return (EPKG_OK);
}

-
int
-
pkg_repos_switch(struct pkg_repos *repos, const char *reponame)
+
void
+
pkg_repos_add(struct pkg_repos *repos, struct pkg_repos_entry *re)
{
-
	struct pkg_repos_entry *re = NULL;
-

-
	pkg_repos_switch_reset(repos);
-

-
	while (pkg_repos_next(repos, &re) == EPKG_OK)
-
		if (strcmp(reponame, pkg_repos_get_name(re)) == 0) {
-
			repos->switchable = 1;
-
			re->switched = 1;
-
			return (EPKG_OK);
-
		}
-

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

int
-
pkg_repos_switch_reset(struct pkg_repos *repos)
+
pkg_repos_next(struct pkg_repos *repos, struct pkg_repos_entry **re)
{
-
	struct pkg_repos_entry *re = NULL;
+
	assert(repos != NULL);

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

-
	while (pkg_repos_next(repos, &re) == EPKG_OK)
-
		re->switched = 0;
+
	if (*re == NULL)
+
		return (EPKG_END);

	return (EPKG_OK);
}
@@ -302,7 +219,7 @@ pkg_repos_get_name(struct pkg_repos_entry *re)
{
        assert(re != NULL);

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

const char *
@@ -310,53 +227,24 @@ pkg_repos_get_url(struct pkg_repos_entry *re)
{
        assert(re != NULL);

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

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

-
        return(re->line);
-
}
-

-
int
-
pkg_repos_exists(struct pkg_repos *repos, const char *reponame)
-
{
-
	struct pkg_repos_entry *re = NULL;
-
	bool exists = false;
-

-
	while (pkg_repos_next(repos, &re) == EPKG_OK) {
-
		if (strcmp(pkg_repos_get_name(re), reponame) == 0) {
-
			exists = true;
-
			break;
-
		}
-
	}
-

-
	return (exists == true ? EPKG_OK : EPKG_FATAL);
+
        return (re->url);
}

void
pkg_repos_free(struct pkg_repos *repos)
{
-
        struct pkg_repos_entry *re1, *re2;
-

-
        if (repos == NULL)
-
                return;
+
	struct pkg_repos_entry *re;

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

-
                re1 = re2;
-
        }
+
	while (!STAILQ_EMPTY(&repos->nodes)) {
+
		re = STAILQ_FIRST(&repos->nodes);
+
		STAILQ_REMOVE_HEAD(&repos->nodes, entries);
+
		free(re);
+
	}

-
        free(repos);
+
	free(repos);
}

static RSA *
modified libpkg/pkgdb.c
@@ -34,9 +34,10 @@ static void pkgdb_pkglt(sqlite3_context *, int, sqlite3_value **);
static void pkgdb_pkggt(sqlite3_context *, int, sqlite3_value **);
static int get_pragma(sqlite3 *, const char *, int64_t *);
static int pkgdb_upgrade(struct pkgdb *);
-
static int pkgdb_repos_new(struct pkgdb *, struct pkg_repos **);
static void populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg);
static int create_temporary_pkgjobs(sqlite3 *);
+
static void pkgdb_detach_remotes(sqlite3 *);
+
static bool is_attached(sqlite3 *, const char *);

static struct column_mapping {
	const char * const name;
@@ -67,6 +68,7 @@ static struct column_mapping {
	{ NULL, -1 }
};

+

static int
load_val(sqlite3 *db, struct pkg *pkg, const char *sql, int flags, int (*pkg_adddata)(struct pkg *pkg, const char *data), int list)
{
@@ -424,52 +426,6 @@ pkgdb_init(sqlite3 *sdb)
	return (sql_exec(sdb, sql));
}

-
static int
-
pkgdb_repos_new(struct pkgdb *db, struct pkg_repos **repos)
-
{
-
	sqlite3_stmt *stmt = NULL;
-
	struct pkgdb_it *it = NULL;
-
	struct pkg_repos_entry *re = NULL;
-
	const char *dbname = NULL;
-
	int ret;
-

-
	assert(db != NULL);
-

-
	pkg_repos_new(repos);
-

-
	if (sqlite3_prepare_v2(db->sqlite, "PRAGMA database_list;", -1, &stmt, NULL) != SQLITE_OK) {
-
		ERROR_SQLITE(db->sqlite);
-
		return (EPKG_FATAL);
-
	}
-
	
-
	it = pkgdb_it_new(db, stmt, PKG_REMOTE);
-

-
	while ((ret = sqlite3_step(it->stmt)) == SQLITE_ROW) {
-
		dbname = sqlite3_column_text(it->stmt, 1);
-

-
		/* skip the 'main' and 'temp' databases */
-
		if ((strcmp(dbname, "main") == 0) || (strcmp(dbname, "temp") == 0))
-
			continue;
-

-
		if ((re = calloc(1, sizeof(struct pkg_repos_entry))) == NULL) {
-
			pkg_emit_errno("malloc", "pkgdb_repos_new");
-
			return (EPKG_FATAL);
-
		}
-

-
		sbuf_set(&re->name, dbname);
-
		pkg_repos_add(*repos, re);
-
	}
-

-
	pkgdb_it_free(it);
-

-
	if (ret != SQLITE_DONE) {
-
		ERROR_SQLITE(db->sqlite);
-
		return (EPKG_FATAL);
-
	}
-

-
	return (EPKG_OK);
-
}
-

int
pkgdb_open(struct pkgdb **db_p, pkgdb_t type)
{
@@ -650,46 +606,12 @@ pkgdb_open(struct pkgdb **db_p, pkgdb_t type)
void
pkgdb_close(struct pkgdb *db)
{
-
	struct pkg_repos *repos = NULL;
-
	struct pkg_repos_entry *re = NULL;
-
	struct sbuf *sql = NULL;
-
	bool multirepos_enabled = false;
-

	if (db == NULL)
		return;

	if (db->sqlite != NULL) {
		if (db->type == PKGDB_REMOTE) {
-
			pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multirepos_enabled);
-

-
			if (multirepos_enabled) {
-
				/*
-
				 * Working on multiple remote repositories.
-
				 * Detach the remote repositories from the main database
-
				 */
-
				
-
				if (pkgdb_repos_new(db, &repos) != EPKG_OK) {
-
					pkg_emit_error("cannot get the attached databases");
-
					return;
-
				}
-

-
				sql = sbuf_new_auto();
-

-
				while (pkg_repos_next(repos, &re) == EPKG_OK) {
-
					sbuf_printf(sql, "DETACH '%s';", pkg_repos_get_name(re));
-
				}
-

-
				sbuf_finish(sql);
-
				sql_exec(db->sqlite, sbuf_get(sql));
-
				sbuf_delete(sql);
-
				pkg_repos_free(repos);
-
			} else {
-
				/*
-
				 * Working on a single remote repository.
-
				 * Detach it from the main database
-
				 */
-
				sql_exec(db->sqlite, "DETACH remote;");
-
			}
+
			pkgdb_detach_remotes(db->sqlite);
		}

		sqlite3_close(db->sqlite);
@@ -1935,6 +1857,92 @@ sql_exec(sqlite3 *s, const char *sql, ...)
	return (ret);
}

+
static bool
+
is_attached(sqlite3 *s, const char *name)
+
{
+
	sqlite3_stmt *stmt;
+
	const char *dbname;
+

+
	assert(s != NULL);
+

+
	if (sqlite3_prepare_v2(s, "PRAGMA database_list;", -1, &stmt, NULL) != SQLITE_OK) {
+
		ERROR_SQLITE(s);
+
		return false;
+
	}
+

+
	while (sqlite3_step(stmt) != SQLITE_DONE) {
+
		dbname = sqlite3_column_text(stmt, 0);
+
		if (!strcmp(dbname, name)) {
+
			sqlite3_finalize(stmt);
+
			return (true);
+
		}
+
	}
+

+
	sqlite3_finalize(stmt);
+

+
	return (false);
+
}
+

+
static int
+
sql_on_all_attached_db(sqlite3 *s, struct sbuf *sql, const char *multireposql) {
+
	sqlite3_stmt *stmt;
+
	const char *dbname;
+

+
	assert(s != NULL);
+

+
	if (sqlite3_prepare_v2(s, "PRAGMA database_list;", -1, &stmt, NULL) != SQLITE_OK) {
+
		ERROR_SQLITE(s);
+
		return (EPKG_FATAL);
+
	}
+

+
	sql = sbuf_new_auto();
+

+
	while (sqlite3_step(stmt) != SQLITE_DONE) {
+
		dbname = sqlite3_column_text(stmt, 0);
+
		if (strcmp(dbname, "main") == 0 || strcmp(dbname, "temp") == 0)
+
			continue;
+

+
		sbuf_cat(sql, " UNION ALL ");
+
		sbuf_printf(sql, multireposql, dbname, dbname);
+
	}
+

+
	sqlite3_finalize(stmt);
+

+
	sbuf_delete(sql);
+
	return (EPKG_OK);
+
}
+

+
static void
+
pkgdb_detach_remotes(sqlite3 *s)
+
{
+
	sqlite3_stmt *stmt;
+
	struct sbuf *sql = NULL;
+
	const char *dbname;
+

+
	assert(s != NULL);
+

+
	if (sqlite3_prepare_v2(s, "PRAGMA database_list;", -1, &stmt, NULL) != SQLITE_OK) {
+
		ERROR_SQLITE(s);
+
		return;
+
	}
+

+
	sql = sbuf_new_auto();
+

+
	while (sqlite3_step(stmt) != SQLITE_DONE) {
+
		dbname = sqlite3_column_text(stmt, 0);
+
		if (strcmp(dbname, "main") == 0)
+
			continue;
+

+
		sbuf_printf(sql, "DETACH '%s';", sqlite3_column_text(stmt, 0));
+
		sbuf_finish(sql);
+
		sql_exec(s, sbuf_get(sql));
+
	}
+

+
	sqlite3_finalize(stmt);
+

+
	sbuf_delete(sql);
+
}
+

static int
get_pragma(sqlite3 *s, const char *sql, int64_t *res)
{
@@ -2009,7 +2017,6 @@ create_temporary_pkgjobs(sqlite3 *s)
struct pkgdb_it *
pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs, const char *repo)
{
-
	struct pkg_repos *repos = NULL;
	sqlite3_stmt *stmt = NULL;
	int i = 0;
	struct sbuf *sql = sbuf_new_auto();
@@ -2052,19 +2059,12 @@ pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs, c

	if (multirepos_enabled) {
		if (repo != NULL) {
-
			if (pkgdb_repos_new(db, &repos) != EPKG_OK) {
-
				pkg_emit_error("cannot get the attached databases");
-
				return (NULL);
-
			}
-

-
			if (pkg_repos_exists(repos, repo) != EPKG_OK) {
+
			if (!is_attached(db->sqlite, "repo")) {
				pkg_emit_error("repository '%s' does not exists", repo);
-
				pkg_repos_free(repos);
				return (NULL);
			}

			reponame = repo;
-
			pkg_repos_free(repos);
		} else {
			/* default repository in multi-repos is 'default' */
			reponame = "default";
@@ -2153,7 +2153,6 @@ pkgdb_query_installs(struct pkgdb *db, match_t match, int nbpkgs, char **pkgs, c
struct pkgdb_it *
pkgdb_query_upgrades(struct pkgdb *db, const char *repo)
{
-
	struct pkg_repos *repos = NULL;
	sqlite3_stmt *stmt = NULL;
	struct sbuf *sql = sbuf_new_auto();
	const char *reponame = NULL;
@@ -2203,21 +2202,12 @@ pkgdb_query_upgrades(struct pkgdb *db, const char *repo)

	if (multirepos_enabled) {
		if (repo != NULL) {
-
			if (pkgdb_repos_new(db, &repos) != EPKG_OK) {
-
				pkg_emit_error("cannot get the attached databases");
-
				sbuf_delete(sql);
-
				return (NULL);
-
			}
-

-
			if (pkg_repos_exists(repos, repo) != EPKG_OK) {
+
			if (!is_attached(db->sqlite, repo)) {
				pkg_emit_error("repository '%s' does not exists", repo);
-
				pkg_repos_free(repos);
-
				sbuf_delete(sql);
				return (NULL);
			}

			reponame = repo;
-
			pkg_repos_free(repos);
		} else {
			/* default repository in multi-repos is 'default' */
			reponame = "default";
@@ -2262,7 +2252,6 @@ pkgdb_query_upgrades(struct pkgdb *db, const char *repo)
struct pkgdb_it *
pkgdb_query_downgrades(struct pkgdb *db, const char *repo)
{
-
	struct pkg_repos *repos = NULL;
	struct sbuf *sql = sbuf_new_auto();
	const char *reponame = NULL;
	sqlite3_stmt *stmt = NULL;
@@ -2290,19 +2279,12 @@ pkgdb_query_downgrades(struct pkgdb *db, const char *repo)

	if (multirepos_enabled) {
		if (repo != NULL) {
-
			if (pkgdb_repos_new(db, &repos) != EPKG_OK) {
-
				pkg_emit_error("cannot get the attached databases");
-
				return (NULL);
-
			}
-

-
			if (pkg_repos_exists(repos, repo) != EPKG_OK) {
+
			if (!is_attached(db->sqlite, repo)) {
				pkg_emit_error("repository '%s' does not exists", repo);
-
				pkg_repos_free(repos);
				return (NULL);
			}

			reponame = repo;
-
			pkg_repos_free(repos);
		} else {
			/* default repository in multi-repos is 'default' */
			reponame = "default";
@@ -2499,11 +2481,8 @@ pkgdb_rquery_build_search_query(struct sbuf *sql, match_t match, unsigned int fi
struct pkgdb_it *
pkgdb_rquery(struct pkgdb *db, const char *pattern, match_t match, unsigned int field, const char *reponame)
{
-
	const char *dbname = NULL;
	sqlite3_stmt *stmt = NULL;
	struct sbuf *sql = NULL;
-
	struct pkg_repos *repos = NULL;
-
	struct pkg_repos_entry *re = NULL;
	bool multirepos_enabled = false;
	const char *basesql = ""
				"SELECT id, origin, name, version, comment, "
@@ -2535,43 +2514,25 @@ pkgdb_rquery(struct pkgdb *db, const char *pattern, match_t match, unsigned int
		 */

		/* add the dbname column to the SELECT */
-
		sbuf_cat(sql, ", dbname FROM ");
-

-
		if (pkgdb_repos_new(db, &repos) != EPKG_OK) {
-
			pkg_emit_error("pkgdb_rquery(): %s", "cannot get the attached databases");
-
			return (NULL);
-
		}
+
		sbuf_cat(sql, ", dbname FROM (");

-
		if (reponame != NULL)
-
			if (pkg_repos_switch(repos, reponame) != EPKG_OK) {
-
				pkg_emit_error("pkgdb_rquery(): %s", "cannot switch to repository");
+
		if (reponame != NULL) {
+
			if (is_attached(db->sqlite, reponame)) {
+
				sbuf_printf(sql, multireposql, reponame, reponame);
+
			} else {
+
				pkg_emit_error("Repository %s can't be loaded", reponame);
				return (NULL);
			}
-

-
		/* get the first repository entry */
-
		if (pkg_repos_next(repos, &re) == EPKG_OK) {
-
			dbname = pkg_repos_get_name(re);
-
			sbuf_cat(sql, "(");
-
			sbuf_printf(sql, multireposql, dbname, dbname);
		} else {
-
			/* there are no remote databases attached */
-
			sbuf_finish(sql);
-
			sbuf_delete(sql);
-
			pkg_repos_free(repos);
-
			return (NULL);
-
		}
-

-
		while (pkg_repos_next(repos, &re) == EPKG_OK) {
-
			dbname = pkg_repos_get_name(re);
-
			sbuf_cat(sql, " UNION ALL ");
-
			sbuf_printf(sql, multireposql, dbname, dbname);
+
			/* test on all the attached databases */
+
			if (sql_on_all_attached_db(db->sqlite, sql, multireposql) != EPKG_OK)
+
				return (NULL);
		}

		/* close the UNIONs and build the search query */
		sbuf_cat(sql, ") WHERE ");
		pkgdb_rquery_build_search_query(sql, match, field);
		sbuf_finish(sql);
-
		pkg_repos_free(repos);
	} else {
		/* 
		 * Working on a single remote repository