From 500f8d4a7d7b17871647392e79e4c7a17c210534 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Sat, 29 Oct 2011 05:18:21 +0300 Subject: 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 --- src/apk_database.h | 9 ++++++++- src/apk_package.h | 8 +++++--- src/blob.c | 12 ++++++++---- src/database.c | 53 +++++++++++++++++++++++++++++++++++++++++----------- src/info.c | 34 +++++++++++++++++---------------- src/package.c | 25 ++++++++++++++++--------- src/solver.c | 39 +++++++++++++++++++++++++++++++++----- src/test.c | 19 ++++++++++++++----- test/pinning.repo | 20 ++++++++++++++++++++ test/pinning1.expect | 2 ++ test/pinning1.test | 2 ++ test/pinning2.expect | 2 ++ test/pinning2.test | 2 ++ test/pinning3.expect | 2 ++ test/pinning3.test | 2 ++ test/pinning4.expect | 3 +++ test/pinning4.test | 2 ++ 17 files changed, 182 insertions(+), 54 deletions(-) create mode 100644 test/pinning.repo create mode 100644 test/pinning1.expect create mode 100644 test/pinning1.test create mode 100644 test/pinning2.expect create mode 100644 test/pinning2.test create mode 100644 test/pinning3.expect create mode 100644 test/pinning3.test create mode 100644 test/pinning4.expect create mode 100644 test/pinning4.test 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 -- cgit v1.2.3-60-g2f50