summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2022-12-20 14:57:51 +0200
committerTimo Teräs <timo.teras@iki.fi>2022-12-20 15:22:37 +0200
commitcb6742953386cb958e52d90ec9198fb8f65c3a71 (patch)
tree5902d23f4331223a0ee3de7c373dc23d87142f3c
parentc21f61ddd8d742e4de2202aa623b0c06573f567b (diff)
downloadapk-tools-cb6742953386cb958e52d90ec9198fb8f65c3a71.tar.gz
apk-tools-cb6742953386cb958e52d90ec9198fb8f65c3a71.tar.bz2
apk-tools-cb6742953386cb958e52d90ec9198fb8f65c3a71.tar.xz
apk-tools-cb6742953386cb958e52d90ec9198fb8f65c3a71.zip
commit: correctly analyze virtual provides induced errors
The package list cannot be used to determine name state, as packages are not selected through all of their names, and that effects the status of unversioned provides. Thus the name state must be calculated in separate step via the dependency graphs. ref #10847
-rw-r--r--src/commit.c66
-rw-r--r--test/provides.repo15
-rw-r--r--test/provides14.test10
-rw-r--r--test/provides15.test7
4 files changed, 83 insertions, 15 deletions
diff --git a/src/commit.c b/src/commit.c
index db548c7..0096a9a 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -385,8 +385,9 @@ all_done:
}
enum {
- STATE_PRESENT = 0x80000000,
- STATE_MISSING = 0x40000000,
+ STATE_SEEN = 0x80000000,
+ STATE_PRESENT = 0x40000000,
+ STATE_MISSING = 0x20000000,
STATE_COUNT_MASK = 0x0000ffff,
};
@@ -518,7 +519,7 @@ static void analyze_package(struct print_state *ps, struct apk_package *pkg, uns
print_deps(ps, pkg, APK_DEP_SATISFIES);
}
-static void analyze_name(struct print_state *ps, struct apk_name *name)
+static void analyze_missing_name(struct print_state *ps, struct apk_name *name)
{
struct apk_name **pname0, *name0;
struct apk_provider *p0;
@@ -596,12 +597,53 @@ static void analyze_deps(struct print_state *ps, struct apk_dependency_array *de
foreach_array_item(d0, deps) {
name0 = d0->name;
- if (d0->conflict)
- continue;
+ if (d0->conflict) continue;
if ((name0->state_int & (STATE_PRESENT | STATE_MISSING)) != 0)
continue;
name0->state_int |= STATE_MISSING;
- analyze_name(ps, name0);
+ analyze_missing_name(ps, name0);
+ }
+}
+
+static void discover_deps(struct apk_dependency_array *deps);
+
+static void discover_name(struct apk_name *name)
+{
+ struct apk_provider *p;
+ struct apk_dependency *d;
+ int concrete;
+
+ if (name->state_int & STATE_SEEN) return;
+ name->state_int |= STATE_SEEN;
+
+ foreach_array_item(p, name->providers) {
+ if (!p->pkg->marked) continue;
+
+ concrete = p->pkg->name == name;
+ if (!concrete) {
+ foreach_array_item(d, p->pkg->provides) {
+ if (d->name != name) continue;
+ if (d->version == &apk_atom_null) continue;
+ concrete = 1;
+ break;
+ }
+ }
+ if (concrete) {
+ p->pkg->name->state_int |= STATE_PRESENT;
+ foreach_array_item(d, p->pkg->provides)
+ d->name->state_int |= STATE_PRESENT;
+ }
+ discover_deps(p->pkg->depends);
+ }
+}
+
+static void discover_deps(struct apk_dependency_array *deps)
+{
+ struct apk_dependency *d;
+
+ foreach_array_item(d, deps) {
+ if (d->conflict) continue;
+ discover_name(d->name);
}
}
@@ -612,7 +654,6 @@ void apk_solver_print_errors(struct apk_database *db,
struct apk_out *out = &db->ctx->out;
struct print_state ps;
struct apk_change *change;
- struct apk_dependency *p;
/* ERROR: unsatisfiable dependencies:
* name:
@@ -654,13 +695,9 @@ void apk_solver_print_errors(struct apk_database *db,
/* Construct information about names */
foreach_array_item(change, changeset->changes) {
struct apk_package *pkg = change->new_pkg;
- if (pkg == NULL)
- continue;
- pkg->marked = 1;
- pkg->name->state_int |= STATE_PRESENT;
- foreach_array_item(p, pkg->provides)
- p->name->state_int |= STATE_PRESENT;
+ if (pkg) pkg->marked = 1;
}
+ discover_deps(world);
/* Analyze is package, and missing names referred to */
ps = (struct print_state) {
@@ -672,8 +709,7 @@ void apk_solver_print_errors(struct apk_database *db,
analyze_deps(&ps, world);
foreach_array_item(change, changeset->changes) {
struct apk_package *pkg = change->new_pkg;
- if (pkg == NULL)
- continue;
+ if (!pkg) continue;
analyze_package(&ps, pkg, change->new_repository_tag);
analyze_deps(&ps, pkg->depends);
}
diff --git a/test/provides.repo b/test/provides.repo
index ed72f72..75ede8c 100644
--- a/test/provides.repo
+++ b/test/provides.repo
@@ -133,3 +133,18 @@ S:1
I:1
k:1
p:pulseaudio=1 pulseaudio-alsa=1
+
+C:Q1FAFBeAhWPV1oiuybW+TSjrUghxU=
+P:sane-backends
+V:1
+S:1
+I:1
+
+C:Q1FAFBeAhWPV1asdfoW+TSjrUghxU=
+P:sane-backend-hpaio
+V:1
+S:1
+I:1
+i:sane-backends
+p:hplip-sane
+
diff --git a/test/provides14.test b/test/provides14.test
new file mode 100644
index 0000000..37cc4a4
--- /dev/null
+++ b/test/provides14.test
@@ -0,0 +1,10 @@
+@ARGS
+--test-repo provides.repo
+add hplip-sane sane-backends
+@EXPECT
+ERROR: unable to select packages:
+ hplip-sane (virtual):
+ note: please select one of the 'provided by'
+ packages explicitly
+ provided by: sane-backend-hpaio
+ required by: world[hplip-sane]
diff --git a/test/provides15.test b/test/provides15.test
new file mode 100644
index 0000000..62f8534
--- /dev/null
+++ b/test/provides15.test
@@ -0,0 +1,7 @@
+@ARGS
+--test-repo provides.repo
+add hplip-sane sane-backend-hpaio sane-backends nonexistent
+@EXPECT
+ERROR: unable to select packages:
+ nonexistent (no such package):
+ required by: world[nonexistent]