From e682e6596c101d634b3780a98773c8433b3baadb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 21 Oct 2011 15:24:24 -0400 Subject: [PATCH 2/2] solver, pkg: implement versioned conflicts One can now say in dependency "!foo<2" which means, that if foo is installed, it needs to be >=2, but it's not a required dependency. --- src/apk_package.h | 3 ++- src/apk_version.h | 1 - src/del.c | 3 +-- src/package.c | 24 ++++++++++++++---------- src/solver.c | 10 ++++------ test/conflict.repo | 19 +++++++++++++++++++ test/conflict1.expect | 2 ++ test/conflict2.expect | 2 ++ 8 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 test/conflict.repo create mode 100644 test/conflict1.expect create mode 100644 test/conflict2.expect diff --git a/src/apk_package.h b/src/apk_package.h index 41d65cb..c68fef7 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -59,7 +59,8 @@ struct apk_sign_ctx { struct apk_dependency { struct apk_name *name; apk_blob_t *version; - int result_mask; + unsigned optional : 1; + unsigned result_mask : 3; }; APK_ARRAY(apk_dependency_array, struct apk_dependency); diff --git a/src/apk_version.h b/src/apk_version.h index 8c264e6..514fea9 100644 --- a/src/apk_version.h +++ b/src/apk_version.h @@ -21,7 +21,6 @@ #define APK_DEPMASK_REQUIRE (APK_VERSION_EQUAL|APK_VERSION_LESS|\ APK_VERSION_GREATER) #define APK_DEPMASK_CHECKSUM (APK_VERSION_LESS|APK_VERSION_GREATER) -#define APK_DEPMASK_CONFLICT (0) const char *apk_version_op_string(int result_mask); int apk_version_result_mask(const char *str); diff --git a/src/del.c b/src/del.c index 3d7ffe7..ffa924f 100644 --- a/src/del.c +++ b/src/del.c @@ -58,8 +58,7 @@ static void foreach_installed_reverse_dependency( for (k = 0; k < pkg0->depends->num; k++) { struct apk_dependency *dep = &pkg0->depends->item[k]; if (dep->name == name && - (dep->result_mask == APK_DEPMASK_CONFLICT || - apk_dep_is_satisfied(dep, pkg))) + apk_dep_is_satisfied(dep, pkg)) break; } if (k >= pkg0->depends->num) diff --git a/src/package.c b/src/package.c index cc4c141..3886d82 100644 --- a/src/package.c +++ b/src/package.c @@ -195,16 +195,16 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend { struct apk_name *name; apk_blob_t bname, bop, bver = APK_BLOB_NULL; - int mask = APK_DEPMASK_REQUIRE; + int mask = APK_DEPMASK_REQUIRE, optional = 0; size_t len; /* [!]name[<,<=,=,>=,>]ver */ if (APK_BLOB_IS_NULL(*b)) goto fail; if (b->ptr[0] == '!') { - mask = 0; b->ptr++; b->len--; + optional = 1; } if (apk_blob_cspn(*b, "<>= ", &bname, &bop)) { int i; @@ -243,10 +243,14 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend if (name == NULL) goto fail; + if (optional) + mask ^= APK_DEPMASK_REQUIRE; + *dep = (struct apk_dependency){ .name = name, .version = apk_blob_atomize_dup(bver), .result_mask = mask, + .optional = optional, }; return; fail: @@ -292,11 +296,8 @@ static int parse_depend(void *ctx, apk_blob_t blob) int apk_dep_is_satisfied(struct apk_dependency *dep, struct apk_package *pkg) { - if (pkg == NULL) { - if (dep->result_mask == APK_DEPMASK_CONFLICT) - return 1; - return 0; - } + if (pkg == NULL) + return dep->optional; if (dep->name != pkg->name) return 0; if (dep->result_mask == APK_DEPMASK_CHECKSUM) { @@ -326,13 +327,16 @@ void apk_blob_pull_deps(apk_blob_t *b, struct apk_database *db, struct apk_depen void apk_blob_push_dep(apk_blob_t *to, struct apk_dependency *dep) { - if (dep->result_mask == APK_DEPMASK_CONFLICT) + int result_mask = dep->result_mask; + + if (dep->optional) { apk_blob_push_blob(to, APK_BLOB_PTR_LEN("!", 1)); + result_mask ^= APK_DEPMASK_REQUIRE; + } apk_blob_push_blob(to, APK_BLOB_STR(dep->name->name)); - if (dep->result_mask != APK_DEPMASK_CONFLICT && - dep->result_mask != APK_DEPMASK_REQUIRE) { + 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); } diff --git a/src/solver.c b/src/solver.c index 49cfc79..d277bc5 100644 --- a/src/solver.c +++ b/src/solver.c @@ -126,8 +126,7 @@ static void foreach_dependency_pkg( struct apk_package *pkg0 = name0->pkgs->item[j]; /* conflict depends on all to be not installed */ - if (dep->result_mask != APK_DEPMASK_CONFLICT && - !apk_dep_is_satisfied(dep, pkg0)) + if (!apk_dep_is_satisfied(dep, pkg0)) continue; cb(ss, pkg0); @@ -154,8 +153,7 @@ static void foreach_rinstall_if_pkg( for (k = 0; k < pkg0->install_if->num; k++) { struct apk_dependency *dep = &pkg0->install_if->item[k]; if (dep->name == name && - (dep->result_mask == APK_DEPMASK_CONFLICT || - apk_dep_is_satisfied(dep, pkg))) + apk_dep_is_satisfied(dep, pkg)) break; } if (k >= pkg0->install_if->num) @@ -635,7 +633,7 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency if (ss->latest_decision != NULL) inherit_name_state(name, ss->latest_decision->name); - if (dep->result_mask != APK_DEPMASK_CONFLICT) + if (!dep->optional) ns->requirers++; update_name_state(ss, name); } @@ -675,7 +673,7 @@ static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency * if (ss->latest_decision && has_inherited_state(ss->latest_decision->name)) recalculate_inherted_name_state(name); - if (dep->result_mask != APK_DEPMASK_CONFLICT) + if (!dep->optional) ns->requirers--; update_name_state(ss, name); } diff --git a/test/conflict.repo b/test/conflict.repo new file mode 100644 index 0000000..a95658c --- /dev/null +++ b/test/conflict.repo @@ -0,0 +1,19 @@ +C:Q1EyN5AdpAOBJWKMR89pp/C66o+OE= +P:a +V:1 +S:1 +I:1 +D:!b<2 + +C:Q1C4uoV7SdMdDhYg4OCVmI71D8HIA= +P:b +V:1 +S:1 +I:1 + +C:Q1hdUpqRv5mYgJEqW52UmVsvmyysE= +P:b +V:2 +S:1 +I:1 + diff --git a/test/conflict1.expect b/test/conflict1.expect new file mode 100644 index 0000000..03c6d67 --- /dev/null +++ b/test/conflict1.expect @@ -0,0 +1,2 @@ +Installing b (2) +Installing a (1) diff --git a/test/conflict2.expect b/test/conflict2.expect new file mode 100644 index 0000000..250f942 --- /dev/null +++ b/test/conflict2.expect @@ -0,0 +1,2 @@ +1 unsatisfiable dependencies (solution with 2 names) +world: b<2 -- 1.7.7