summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2011-10-29 05:18:21 +0300
committerTimo Teräs <timo.teras@iki.fi>2011-10-29 05:18:21 +0300
commit500f8d4a7d7b17871647392e79e4c7a17c210534 (patch)
tree47d4b1cd04e374d88e26e352eeac9f51da083451
parente682e6596c101d634b3780a98773c8433b3baadb (diff)
solver, db: implement repository pinning
Improves /etc/apk/repositories format so you can say: http://nl.alpinelinux.org/alpine/v2.3/main @edge http://nl.alpinelinux.org/alpine/edge/main @testing http://nl.alpinelinux.org/alpine/edge/testing After which you can pin dependencies to these tags using: apk add stableapp newapp@edge bleedingapp@testing Apk will now by default only use the untagged repositories, but adding a tag to specific dependency: 1. will prefer that tag for the name 2. allowing pulling in dependencies from that tag (though, it prefers untagged packages to satisfy deps if possible) fixes #575
-rw-r--r--src/apk_database.h9
-rw-r--r--src/apk_package.h8
-rw-r--r--src/blob.c12
-rw-r--r--src/database.c53
-rw-r--r--src/info.c34
-rw-r--r--src/package.c25
-rw-r--r--src/solver.c39
-rw-r--r--src/test.c19
-rw-r--r--test/pinning.repo20
-rw-r--r--test/pinning1.expect2
-rw-r--r--test/pinning1.test2
-rw-r--r--test/pinning2.expect2
-rw-r--r--test/pinning2.test2
-rw-r--r--test/pinning3.expect2
-rw-r--r--test/pinning3.test2
-rw-r--r--test/pinning4.expect3
-rw-r--r--test/pinning4.test2
17 files changed, 182 insertions, 54 deletions
diff --git a/src/apk_database.h b/src/apk_database.h
index d7c4f5b..e5d28f4 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -115,10 +115,15 @@ struct apk_db_options {
struct list_head repository_list;
};
+struct apk_repository_tag {
+ unsigned int allowed_repos;
+ apk_blob_t *name;
+};
+
struct apk_database {
char *root;
int root_fd, lock_fd, cache_fd, cachetmp_fd, keys_fd;
- unsigned num_repos;
+ unsigned num_repos, num_repo_tags;
const char *cache_dir;
char *cache_remount_dir;
apk_blob_t *arch;
@@ -131,6 +136,7 @@ struct apk_database {
struct apk_dependency_array *world;
struct apk_string_array *protected_paths;
struct apk_repository repos[APK_MAX_REPOS];
+ struct apk_repository_tag repo_tags[APK_MAX_REPOS];
struct apk_id_cache id_cache;
struct {
@@ -158,6 +164,7 @@ typedef union apk_database_or_void {
struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name);
struct apk_name *apk_db_query_name(struct apk_database *db, apk_blob_t name);
+int apk_db_get_tag_id(struct apk_database *db, apk_blob_t tag);
struct apk_db_dir *apk_db_dir_query(struct apk_database *db,
apk_blob_t name);
struct apk_db_file *apk_db_file_query(struct apk_database *db,
diff --git a/src/apk_package.h b/src/apk_package.h
index c68fef7..a241a67 100644
--- a/src/apk_package.h
+++ b/src/apk_package.h
@@ -59,6 +59,7 @@ struct apk_sign_ctx {
struct apk_dependency {
struct apk_name *name;
apk_blob_t *version;
+ unsigned short repository_tag;
unsigned optional : 1;
unsigned result_mask : 3;
};
@@ -120,12 +121,13 @@ void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db,
struct apk_package *pkg);
int apk_dep_is_satisfied(struct apk_dependency *dep, struct apk_package *pkg);
-void apk_blob_push_dep(apk_blob_t *to, struct apk_dependency *dep);
-void apk_blob_push_deps(apk_blob_t *to, struct apk_dependency_array *deps);
+void apk_blob_push_dep(apk_blob_t *to, struct apk_database *, struct apk_dependency *dep);
+void apk_blob_push_deps(apk_blob_t *to, struct apk_database *, struct apk_dependency_array *deps);
void apk_blob_pull_dep(apk_blob_t *from, struct apk_database *, struct apk_dependency *);
void apk_blob_pull_deps(apk_blob_t *from, struct apk_database *, struct apk_dependency_array **);
-int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os);
+int apk_deps_write(struct apk_database *db, struct apk_dependency_array *deps,
+ struct apk_ostream *os);
int apk_deps_add(struct apk_dependency_array **depends,
struct apk_dependency *dep);
diff --git a/src/blob.c b/src/blob.c
index aaaa377..8cf4076 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -44,8 +44,10 @@ int apk_blob_spn(apk_blob_t blob, const char *accept, apk_blob_t *l, apk_blob_t
for (i = 0; i < blob.len; i++) {
if (strchr(accept, blob.ptr[i]) == NULL) {
- *l = APK_BLOB_PTR_LEN(blob.ptr, i);
- *r = APK_BLOB_PTR_LEN(blob.ptr+i, blob.len-i);
+ if (l != NULL)
+ *l = APK_BLOB_PTR_LEN(blob.ptr, i);
+ if (r != NULL)
+ *r = APK_BLOB_PTR_LEN(blob.ptr+i, blob.len-i);
return 1;
}
}
@@ -58,8 +60,10 @@ int apk_blob_cspn(apk_blob_t blob, const char *reject, apk_blob_t *l, apk_blob_t
for (i = 0; i < blob.len; i++) {
if (strchr(reject, blob.ptr[i]) != NULL) {
- *l = APK_BLOB_PTR_LEN(blob.ptr, i);
- *r = APK_BLOB_PTR_LEN(blob.ptr+i, blob.len-i);
+ if (l != NULL)
+ *l = APK_BLOB_PTR_LEN(blob.ptr, i);
+ if (r != NULL)
+ *r = APK_BLOB_PTR_LEN(blob.ptr+i, blob.len-i);
return 1;
}
}
diff --git a/src/database.c b/src/database.c
index 482f406..8eaba6c 100644
--- a/src/database.c
+++ b/src/database.c
@@ -713,7 +713,7 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
if (ipkg->replaces->num) {
apk_blob_push_blob(&bbuf, APK_BLOB_STR("r:"));
- apk_blob_push_deps(&bbuf, ipkg->replaces);
+ apk_blob_push_deps(&bbuf, db, ipkg->replaces);
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
}
if (ipkg->replaces_priority) {
@@ -1156,6 +1156,9 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
apk_string_array_init(&db->protected_paths);
db->permanent = 1;
+ /* Get first repository tag (the NULL tag) */
+ apk_db_get_tag_id(db, APK_BLOB_NULL);
+
if (dbopts->root && dbopts->arch) {
db->arch = apk_blob_atomize(APK_BLOB_STR(dbopts->arch));
} else {
@@ -1351,7 +1354,7 @@ int apk_db_write_config(struct apk_database *db)
if (os == NULL)
return -1;
- apk_deps_write(db->world, os);
+ apk_deps_write(db, db->world, os);
os->write(os, "\n", 1);
r = os->close(os);
if (r < 0)
@@ -1443,6 +1446,25 @@ void apk_db_close(struct apk_database *db)
}
}
+int apk_db_get_tag_id(struct apk_database *db, apk_blob_t tag)
+{
+ apk_blob_t *b = apk_blob_atomize_dup(tag);
+ int i;
+
+ for (i = 0; i < db->num_repo_tags; i++) {
+ if (db->repo_tags[i].name == b)
+ return i;
+ }
+ if (i < ARRAY_SIZE(db->repo_tags)) {
+ db->num_repo_tags++;
+ db->repo_tags[i] = (struct apk_repository_tag) {
+ .name = b
+ };
+ return i;
+ }
+ return -1;
+}
+
static int fire_triggers(apk_hash_item item, void *ctx)
{
struct apk_database *db = (struct apk_database *) ctx;
@@ -1696,30 +1718,38 @@ int apk_db_index_read_file(struct apk_database *db, const char *file, int repo)
return load_index(db, apk_bstream_from_file(AT_FDCWD, file), targz, repo);
}
-int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
+int apk_db_add_repository(apk_database_t _db, apk_blob_t _repository)
{
struct apk_database *db = _db.db;
struct apk_bstream *bs = NULL;
struct apk_repository *repo;
- int r, targz = 1;
+ apk_blob_t brepo, btag;
+ int r, targz = 1, tag_id = 0;
char buf[PATH_MAX];
- if (repository.ptr == NULL || repository.len == 0 ||
- *repository.ptr == '#')
- return 0;
-
if (db->num_repos >= APK_MAX_REPOS)
return -1;
- r = db->num_repos++;
+ brepo = _repository;
+ btag = APK_BLOB_NULL;
+ if (brepo.ptr == NULL || brepo.len == 0 || *brepo.ptr == '#')
+ return 0;
+ if (brepo.ptr[0] == '@') {
+ apk_blob_pull_char(&brepo, '@');
+ apk_blob_cspn(brepo, ": ", &btag, &brepo);
+ apk_blob_spn(brepo, ": ", NULL, &brepo);
+ tag_id = apk_db_get_tag_id(db, btag);
+ }
+
+ r = db->num_repos++;
repo = &db->repos[r];
*repo = (struct apk_repository) {
- .url = apk_blob_cstr(repository),
+ .url = apk_blob_cstr(brepo),
};
if (apk_url_local_file(repo->url) == NULL) {
- apk_blob_checksum(repository, apk_checksum_default(), &repo->csum);
+ apk_blob_checksum(brepo, apk_checksum_default(), &repo->csum);
if (apk_flags & APK_UPDATE_CACHE)
apk_repository_update(db, repo);
@@ -1730,6 +1760,7 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t repository)
db->local_repos |= BIT(r);
bs = apk_repo_file_open(repo, db->arch, apkindex_tar_gz, buf, sizeof(buf));
}
+ db->repo_tags[tag_id].allowed_repos |= BIT(r);
if (bs == NULL) {
apk_warning("%s: index failed to open", buf);
return 0;
diff --git a/src/info.c b/src/info.c
index b45eba5..b90fa1a 100644
--- a/src/info.c
+++ b/src/info.c
@@ -18,6 +18,7 @@
#include "apk_print.h"
struct info_ctx {
+ struct apk_database *db;
int (*action)(struct info_ctx *ctx, struct apk_database *db,
int argc, char **argv);
int subaction_mask;
@@ -130,7 +131,7 @@ static int info_who_owns(struct info_ctx *ctx, struct apk_database *db,
struct apk_ostream *os;
os = apk_ostream_to_fd(STDOUT_FILENO);
- apk_deps_write(deps, os);
+ apk_deps_write(db, deps, os);
os->write(os, "\n", 1);
os->close(os);
}
@@ -139,7 +140,7 @@ static int info_who_owns(struct info_ctx *ctx, struct apk_database *db,
return r;
}
-static void info_print_description(struct apk_package *pkg)
+static void info_print_description(struct apk_database *db, struct apk_package *pkg)
{
if (apk_verbosity > 1)
printf("%s: %s", pkg->name->name, pkg->description);
@@ -149,7 +150,7 @@ static void info_print_description(struct apk_package *pkg)
pkg->description);
}
-static void info_print_url(struct apk_package *pkg)
+static void info_print_url(struct apk_database *db, struct apk_package *pkg)
{
if (apk_verbosity > 1)
printf("%s: %s", pkg->name->name, pkg->url);
@@ -159,7 +160,7 @@ static void info_print_url(struct apk_package *pkg)
pkg->url);
}
-static void info_print_size(struct apk_package *pkg)
+static void info_print_size(struct apk_database *db, struct apk_package *pkg)
{
if (apk_verbosity > 1)
printf("%s: %zu", pkg->name->name, pkg->installed_size);
@@ -169,7 +170,7 @@ static void info_print_size(struct apk_package *pkg)
pkg->installed_size);
}
-static void info_print_depends(struct apk_package *pkg)
+static void info_print_depends(struct apk_database *db, struct apk_package *pkg)
{
apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n");
char dep[256];
@@ -182,14 +183,14 @@ static void info_print_depends(struct apk_package *pkg)
printf("%s: ", pkg->name->name);
for (i = 0; i < pkg->depends->num; i++) {
apk_blob_t b = APK_BLOB_BUF(dep);
- apk_blob_push_dep(&b, &pkg->depends->item[i]);
+ apk_blob_push_dep(&b, db, &pkg->depends->item[i]);
apk_blob_push_blob(&b, separator);
b = apk_blob_pushed(APK_BLOB_BUF(dep), b);
fwrite(b.ptr, b.len, 1, stdout);
}
}
-static void info_print_required_by(struct apk_package *pkg)
+static void info_print_required_by(struct apk_database *db, struct apk_package *pkg)
{
int i, j, k;
char *separator = apk_verbosity > 1 ? " " : "\n";
@@ -221,7 +222,7 @@ static void info_print_required_by(struct apk_package *pkg)
}
}
-static void info_print_install_if(struct apk_package *pkg)
+static void info_print_install_if(struct apk_database *db, struct apk_package *pkg)
{
apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n");
char dep[256];
@@ -234,14 +235,14 @@ static void info_print_install_if(struct apk_package *pkg)
printf("%s: ", pkg->name->name);
for (i = 0; i < pkg->install_if->num; i++) {
apk_blob_t b = APK_BLOB_BUF(dep);
- apk_blob_push_dep(&b, &pkg->install_if->item[i]);
+ apk_blob_push_dep(&b, db, &pkg->install_if->item[i]);
apk_blob_push_blob(&b, separator);
b = apk_blob_pushed(APK_BLOB_BUF(dep), b);
fwrite(b.ptr, b.len, 1, stdout);
}
}
-static void info_print_rinstall_if(struct apk_package *pkg)
+static void info_print_rinstall_if(struct apk_database *db, struct apk_package *pkg)
{
int i, j, k;
char *separator = apk_verbosity > 1 ? " " : "\n";
@@ -273,7 +274,7 @@ static void info_print_rinstall_if(struct apk_package *pkg)
}
}
-static void info_print_contents(struct apk_package *pkg)
+static void info_print_contents(struct apk_database *db, struct apk_package *pkg)
{
struct apk_installed_package *ipkg = pkg->ipkg;
struct apk_db_dir_instance *diri;
@@ -295,7 +296,7 @@ static void info_print_contents(struct apk_package *pkg)
}
}
-static void info_print_triggers(struct apk_package *pkg)
+static void info_print_triggers(struct apk_database *db, struct apk_package *pkg)
{
struct apk_installed_package *ipkg = pkg->ipkg;
int i;
@@ -311,7 +312,7 @@ static void info_print_triggers(struct apk_package *pkg)
}
}
-static void info_print_replaces(struct apk_package *pkg)
+static void info_print_replaces(struct apk_database *db, struct apk_package *pkg)
{
apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n");
char dep[256];
@@ -324,7 +325,7 @@ static void info_print_replaces(struct apk_package *pkg)
printf("%s: ", pkg->name->name);
for (i = 0; i < pkg->ipkg->replaces->num; i++) {
apk_blob_t b = APK_BLOB_BUF(dep);
- apk_blob_push_dep(&b, &pkg->ipkg->replaces->item[i]);
+ apk_blob_push_dep(&b, db, &pkg->ipkg->replaces->item[i]);
apk_blob_push_blob(&b, separator);
b = apk_blob_pushed(APK_BLOB_BUF(dep), b);
fwrite(b.ptr, b.len, 1, stdout);
@@ -333,7 +334,7 @@ static void info_print_replaces(struct apk_package *pkg)
static void info_subaction(struct info_ctx *ctx, struct apk_package *pkg)
{
- typedef void (*subaction_t)(struct apk_package *);
+ typedef void (*subaction_t)(struct apk_database *, struct apk_package *);
static subaction_t subactions[] = {
info_print_description,
info_print_url,
@@ -358,7 +359,7 @@ static void info_subaction(struct info_ctx *ctx, struct apk_package *pkg)
if (pkg->ipkg == NULL && (BIT(i) & requireipkg))
continue;
- subactions[i](pkg);
+ subactions[i](ctx->db, pkg);
puts("");
}
}
@@ -437,6 +438,7 @@ static int info_main(void *ctx, struct apk_database *db, int argc, char **argv)
{
struct info_ctx *ictx = (struct info_ctx *) ctx;
+ ictx->db = db;
if (ictx->action != NULL)
return ictx->action(ictx, db, argc, argv);
diff --git a/src/package.c b/src/package.c
index 3886d82..1c7bd2d 100644
--- a/src/package.c
+++ b/src/package.c
@@ -194,8 +194,8 @@ struct parse_depend_ctx {
void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_dependency *dep)
{
struct apk_name *name;
- apk_blob_t bname, bop, bver = APK_BLOB_NULL;
- int mask = APK_DEPMASK_REQUIRE, optional = 0;
+ apk_blob_t bname, bop, bver = APK_BLOB_NULL, btag;
+ int mask = APK_DEPMASK_REQUIRE, optional = 0, tag = 0;
size_t len;
/* [!]name[<,<=,=,>=,>]ver */
@@ -239,6 +239,9 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend
b->ptr += len;
b->len -= len;
+ if (apk_blob_split(bname, APK_BLOB_STR("@"), &bname, &btag))
+ tag = apk_db_get_tag_id(db, btag);
+
name = apk_db_get_name(db, bname);
if (name == NULL)
goto fail;
@@ -249,6 +252,7 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend
*dep = (struct apk_dependency){
.name = name,
.version = apk_blob_atomize_dup(bver),
+ .repository_tag = tag,
.result_mask = mask,
.optional = optional,
};
@@ -325,7 +329,7 @@ void apk_blob_pull_deps(apk_blob_t *b, struct apk_database *db, struct apk_depen
apk_blob_for_each_segment(*b, " ", parse_depend, &ctx);
}
-void apk_blob_push_dep(apk_blob_t *to, struct apk_dependency *dep)
+void apk_blob_push_dep(apk_blob_t *to, struct apk_database *db, struct apk_dependency *dep)
{
int result_mask = dep->result_mask;
@@ -335,14 +339,17 @@ void apk_blob_push_dep(apk_blob_t *to, struct apk_dependency *dep)
}
apk_blob_push_blob(to, APK_BLOB_STR(dep->name->name));
-
if (!APK_BLOB_IS_NULL(*dep->version)) {
apk_blob_push_blob(to, APK_BLOB_STR(apk_version_op_string(dep->result_mask)));
apk_blob_push_blob(to, *dep->version);
}
+ if (dep->repository_tag && db != NULL) {
+ apk_blob_push_blob(to, APK_BLOB_PTR_LEN("@", 1));
+ apk_blob_push_blob(to, *db->repo_tags[dep->repository_tag].name);
+ }
}
-void apk_blob_push_deps(apk_blob_t *to, struct apk_dependency_array *deps)
+void apk_blob_push_deps(apk_blob_t *to, struct apk_database *db, struct apk_dependency_array *deps)
{
int i;
@@ -352,11 +359,11 @@ void apk_blob_push_deps(apk_blob_t *to, struct apk_dependency_array *deps)
for (i = 0; i < deps->num; i++) {
if (i)
apk_blob_push_blob(to, APK_BLOB_PTR_LEN(" ", 1));
- apk_blob_push_dep(to, &deps->item[i]);
+ apk_blob_push_dep(to, db, &deps->item[i]);
}
}
-int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os)
+int apk_deps_write(struct apk_database *db, struct apk_dependency_array *deps, struct apk_ostream *os)
{
apk_blob_t blob;
char tmp[256];
@@ -369,7 +376,7 @@ int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os)
blob = APK_BLOB_BUF(tmp);
if (i)
apk_blob_push_blob(&blob, APK_BLOB_PTR_LEN(" ", 1));
- apk_blob_push_dep(&blob, &deps->item[i]);
+ apk_blob_push_dep(&blob, db, &deps->item[i]);
blob = apk_blob_pushed(APK_BLOB_BUF(tmp), blob);
if (APK_BLOB_IS_NULL(blob) ||
@@ -998,7 +1005,7 @@ static int write_depends(struct apk_ostream *os, const char *field,
if (os->write(os, field, 2) != 2)
return -1;
- r = apk_deps_write(deps, os);
+ r = apk_deps_write(NULL, deps, os);
if (r < 0)
return r;
if (os->write(os, "\n", 1) != 1)
diff --git a/src/solver.c b/src/solver.c
index d277bc5..8718423 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -47,6 +47,7 @@ struct apk_name_state {
struct list_head unsolved_list;
struct apk_name *name;
struct apk_package *chosen;
+ unsigned int allowed_repos, preferred_repos;
unsigned short requirers;
unsigned short install_ifs;
@@ -280,9 +281,18 @@ static void foreach_dependency(struct apk_solver_state *ss, struct apk_dependenc
}
static int compare_package_preference(unsigned short solver_flags,
+ unsigned int preferred_repos,
struct apk_package *pkgA,
struct apk_package *pkgB)
{
+ /* preferred repository pinning */
+ if ((pkgA->ipkg || (pkgA->repos & preferred_repos)) &&
+ !(pkgB->ipkg || (pkgB->repos & preferred_repos)))
+ return 1;
+ if ((pkgB->ipkg || (pkgB->repos & preferred_repos)) &&
+ !(pkgA->ipkg || (pkgA->repos & preferred_repos)))
+ return -1;
+
if (solver_flags & APK_SOLVERF_AVAILABLE) {
if (pkgA->repos != 0 && pkgB->repos == 0)
return 1;
@@ -320,6 +330,7 @@ static int get_preference(struct apk_solver_state *ss,
unsigned short name_flags = ns->solver_flags_local
| ns->solver_flags_inherited
| ss->solver_flags;
+ unsigned int preferred_repos = ns->preferred_repos | ss->db->repo_tags[0].allowed_repos;
unsigned short preference = 0;
int i;
@@ -330,7 +341,9 @@ static int get_preference(struct apk_solver_state *ss,
if (pkg0 == pkg || ps0 == NULL)
continue;
- if (compare_package_preference(name_flags, pkg, pkg0) < 0) {
+ if (compare_package_preference(name_flags,
+ preferred_repos,
+ pkg, pkg0) < 0) {
if (installable_only) {
if (ss->topology_position > pkg0->topology_hard &&
!(ps0->flags & APK_PKGSTF_DECIDED))
@@ -364,6 +377,7 @@ static int update_name_state(struct apk_solver_state *ss, struct apk_name *name)
struct apk_name_state *ns = name_to_ns(name);
struct apk_package *best_pkg = NULL;
unsigned int best_topology = 0;
+ unsigned int allowed_repos = ns->allowed_repos | ss->db->repo_tags[0].allowed_repos;
int i, options = 0, skipped_options = 0;
for (i = 0; i < name->pkgs->num; i++) {
@@ -372,6 +386,7 @@ static int update_name_state(struct apk_solver_state *ss, struct apk_name *name)
if (ps0 == NULL ||
pkg0->topology_hard >= ss->topology_position ||
+ ((pkg0->repos != 0) && (pkg0->ipkg == NULL) && !(pkg0->repos & allowed_repos)) ||
(ps0->flags & APK_PKGSTF_DECIDED))
continue;
@@ -571,6 +586,7 @@ static void inherit_name_state(struct apk_name *to, struct apk_name *from)
tns->solver_flags_inherited |=
fns->solver_flags_inherited |
(fns->solver_flags_local & fns->solver_flags_local_mask);
+ tns->allowed_repos |= fns->allowed_repos;
}
static void inherit_name_state_wrapper(struct apk_package *rdepend, void *ctx)
@@ -587,6 +603,8 @@ static int has_inherited_state(struct apk_name *name)
return 0;
if (ns->solver_flags_inherited || (ns->solver_flags_local & ns->solver_flags_local_mask))
return 1;
+ if (ns->allowed_repos)
+ return 1;
return 0;
}
@@ -595,6 +613,7 @@ static void recalculate_inherted_name_state(struct apk_name *name)
struct apk_name_state *ns = name_to_ns(name);
ns->solver_flags_inherited = 0;
+ ns->allowed_repos = 0;
foreach_locked_reverse_dependency(name, inherit_name_state_wrapper, name);
}
@@ -614,6 +633,16 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency
return;
}
+ if (dep->repository_tag) {
+ unsigned int allowed_repos;
+
+ dbg_printf("%s: enabling repository tag %d\n",
+ dep->name->name, dep->repository_tag);
+ allowed_repos = ss->db->repo_tags[dep->repository_tag].allowed_repos;
+ ns->allowed_repos |= allowed_repos;
+ ns->preferred_repos |= allowed_repos;
+ }
+
for (i = 0; i < name->pkgs->num; i++) {
struct apk_package *pkg0 = name->pkgs->item[i];
struct apk_package_state *ps0 = pkg_to_ps(pkg0);
@@ -1256,7 +1285,7 @@ all_done:
return r;
}
-static void print_dep_errors(char *label, struct apk_dependency_array *deps)
+static void print_dep_errors(struct apk_database *db, char *label, struct apk_dependency_array *deps)
{
int i, print_label = 1;
char buf[256];
@@ -1276,7 +1305,7 @@ static void print_dep_errors(char *label, struct apk_dependency_array *deps)
indent.indent = indent.x + 1;
}
p = APK_BLOB_BUF(buf);
- apk_blob_push_dep(&p, dep);
+ apk_blob_push_dep(&p, db, dep);
p = apk_blob_pushed(APK_BLOB_BUF(buf), p);
apk_print_indented(&indent, p);
}
@@ -1298,12 +1327,12 @@ void apk_solver_print_errors(struct apk_database *db,
pkg->name->state_ptr = pkg;
}
- print_dep_errors("world", world);
+ print_dep_errors(db, "world", world);
for (i = 0; i < solution->num; i++) {
struct apk_package *pkg = solution->item[i];
char pkgtext[256];
snprintf(pkgtext, sizeof(pkgtext), PKG_VER_FMT, PKG_VER_PRINTF(solution->item[i]));
- print_dep_errors(pkgtext, pkg->depends);
+ print_dep_errors(db, pkgtext, pkg->depends);
}
}
diff --git a/src/test.c b/src/test.c
index 9fc3e1f..29ee789 100644
--- a/src/test.c
+++ b/src/test.c
@@ -91,7 +91,7 @@ static inline void print_change(struct apk_package *oldpkg,
}
}
-static void print_dep_errors(char *label, struct apk_dependency_array *deps)
+static void print_dep_errors(struct apk_database *db, char *label, struct apk_dependency_array *deps)
{
int i, print_label = 1;
char buf[256];
@@ -110,7 +110,7 @@ static void print_dep_errors(char *label, struct apk_dependency_array *deps)
} else {
printf(" ");
}
- apk_blob_push_dep(&p, dep);
+ apk_blob_push_dep(&p, db, dep);
p = apk_blob_pushed(APK_BLOB_BUF(buf), p);
fwrite(p.ptr, p.len, 1, stdout);
}
@@ -131,12 +131,12 @@ static void print_errors_in_solution(struct apk_database *db, int unsatisfiable,
pkg->name->state_ptr = pkg;
}
- print_dep_errors("world", db->world);
+ print_dep_errors(db, "world", db->world);
for (i = 0; i < solution->num; i++) {
struct apk_package *pkg = solution->item[i];
char pkgtext[256];
snprintf(pkgtext, sizeof(pkgtext), PKG_VER_FMT, PKG_VER_PRINTF(solution->item[i]));
- print_dep_errors(pkgtext, pkg->depends);
+ print_dep_errors(db, pkgtext, pkg->depends);
}
}
@@ -153,6 +153,8 @@ static int test_main(void *pctx, struct apk_database *db, int argc, char **argv)
if (argc != 1)
return -EINVAL;
+ apk_db_get_tag_id(db, APK_BLOB_STR("testing"));
+
/* load installed db */
if (ctx->installed_db != NULL) {
bs = apk_bstream_from_file(AT_FDCWD, ctx->installed_db);
@@ -165,9 +167,16 @@ static int test_main(void *pctx, struct apk_database *db, int argc, char **argv)
/* load additional indexes */
if (ctx->repos) {
for (i = 0; i < ctx->repos->num; i++) {
- bs = apk_bstream_from_file(AT_FDCWD, ctx->repos->item[i]);
+ char *fn = ctx->repos->item[i];
+ int repo = 0;
+ if (fn[0] == '+') {
+ fn++;
+ repo = 1;
+ }
+ bs = apk_bstream_from_file(AT_FDCWD, fn);
if (bs != NULL) {
apk_db_index_read(db, bs, i);
+ db->repo_tags[repo].allowed_repos |= BIT(i);
bs->close(bs, NULL);
}
}
diff --git a/test/pinning.repo b/test/pinning.repo
new file mode 100644
index 0000000..c41ddf7
--- /dev/null
+++ b/test/pinning.repo
@@ -0,0 +1,20 @@
+C:Q1eVpkasfqZAukAXFYbgwt4xffZWU=
+P:a
+V:3
+S:1
+I:1
+D:b
+
+C:Q1hdUpqRv5mYgJEqW52UmVsv23ysE=
+P:b
+V:3
+S:1
+I:1
+
+C:Q1eVpkasfqZAukAXFYbg324xAt4WU=
+P:c
+V:3
+S:1
+I:1
+D:a>=3
+
diff --git a/test/pinning1.expect b/test/pinning1.expect
new file mode 100644
index 0000000..81756fe
--- /dev/null
+++ b/test/pinning1.expect
@@ -0,0 +1,2 @@
+Installing b (2)
+Installing a (2)
diff --git a/test/pinning1.test b/test/pinning1.test
new file mode 100644
index 0000000..4396875
--- /dev/null
+++ b/test/pinning1.test
@@ -0,0 +1,2 @@
+--raw-repository basic.repo --raw-repository +pinning.repo
+a
diff --git a/test/pinning2.expect b/test/pinning2.expect
new file mode 100644
index 0000000..cce6084
--- /dev/null
+++ b/test/pinning2.expect
@@ -0,0 +1,2 @@
+Installing b (2)
+Installing a (3)
diff --git a/test/pinning2.test b/test/pinning2.test
new file mode 100644
index 0000000..69d4f79
--- /dev/null
+++ b/test/pinning2.test
@@ -0,0 +1,2 @@
+--raw-repository basic.repo --raw-repository +pinning.repo
+a@testing
diff --git a/test/pinning3.expect b/test/pinning3.expect
new file mode 100644
index 0000000..a2b2fca
--- /dev/null
+++ b/test/pinning3.expect
@@ -0,0 +1,2 @@
+Installing b (3)
+Installing a (3)
diff --git a/test/pinning3.test b/test/pinning3.test
new file mode 100644
index 0000000..220f128
--- /dev/null
+++ b/test/pinning3.test
@@ -0,0 +1,2 @@
+--raw-repository basic.repo --raw-repository +pinning.repo
+a@testing b@testing
diff --git a/test/pinning4.expect b/test/pinning4.expect
new file mode 100644
index 0000000..5a03102
--- /dev/null
+++ b/test/pinning4.expect
@@ -0,0 +1,3 @@
+Installing b (2)
+Installing a (3)
+Installing c (3)
diff --git a/test/pinning4.test b/test/pinning4.test
new file mode 100644
index 0000000..4bf8d38
--- /dev/null
+++ b/test/pinning4.test
@@ -0,0 +1,2 @@
+--raw-repository basic.repo --raw-repository +pinning.repo
+c@testing