summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/apk_package.h3
-rw-r--r--src/apk_version.h1
-rw-r--r--src/del.c3
-rw-r--r--src/package.c24
-rw-r--r--src/solver.c10
-rw-r--r--test/conflict.repo19
-rw-r--r--test/conflict1.expect2
-rw-r--r--test/conflict2.expect2
8 files changed, 44 insertions, 20 deletions
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