diff options
Diffstat (limited to 'src/commit.c')
-rw-r--r-- | src/commit.c | 80 |
1 files changed, 59 insertions, 21 deletions
diff --git a/src/commit.c b/src/commit.c index 4b4f588..7ca39d3 100644 --- a/src/commit.c +++ b/src/commit.c @@ -383,9 +383,10 @@ all_done: } enum { - STATE_SEEN = 0x80000000, - STATE_PRESENT = 0x40000000, - STATE_MISSING = 0x20000000, + STATE_PRESENT = 0x80000000, + STATE_MISSING = 0x40000000, + STATE_VIRTUAL_ONLY = 0x20000000, + STATE_INSTALLIF = 0x10000000, STATE_COUNT_MASK = 0x0000ffff, }; @@ -608,34 +609,71 @@ static void analyze_deps(struct print_state *ps, struct apk_dependency_array *de } static void discover_deps(struct apk_dependency_array *deps); +static void discover_name(struct apk_name *name, int pkg_state); -static void discover_name(struct apk_name *name) +static void discover_reverse_iif(struct apk_name *name) { + struct apk_name **pname0, *name0; + struct apk_dependency *d; struct apk_provider *p; + + foreach_array_item(pname0, name->rinstall_if) { + name0 = *pname0; + + foreach_array_item(p, name0->providers) { + int ok = 1; + if (!p->pkg->marked) continue; + if (p->pkg->install_if->num == 0) continue; + foreach_array_item(d, p->pkg->install_if) { + if (!!d->conflict == !!(d->name->state_int & STATE_PRESENT)) { + ok = 0; + break; + } + } + if (ok) { + discover_name(p->pkg->name, STATE_INSTALLIF); + foreach_array_item(d, p->pkg->provides) + discover_name(d->name, STATE_INSTALLIF); + } + } + } +} + +static int is_name_concrete(struct apk_package *pkg, struct apk_name *name) +{ struct apk_dependency *d; - int concrete; + if (pkg->name == name) return 1; + foreach_array_item(d, pkg->provides) { + if (d->name != name) continue; + if (d->version == &apk_atom_null) continue; + return 1; + } + return 0; +} - if (name->state_int & STATE_SEEN) return; - name->state_int |= STATE_SEEN; +static void discover_name(struct apk_name *name, int pkg_state) +{ + struct apk_provider *p; + struct apk_dependency *d; foreach_array_item(p, name->providers) { + int state = pkg_state; if (!p->pkg->marked) continue; + if (state == STATE_PRESENT && !is_name_concrete(p->pkg, name)) + state = STATE_VIRTUAL_ONLY; + if (p->pkg->state_int & state) continue; + p->pkg->state_int |= state; - 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; + p->pkg->name->state_int |= state; + foreach_array_item(d, p->pkg->provides) + d->name->state_int |= state; + + discover_deps(p->pkg->depends); + if (state == STATE_PRESENT || state == STATE_INSTALLIF) { + discover_reverse_iif(p->pkg->name); foreach_array_item(d, p->pkg->provides) - d->name->state_int |= STATE_PRESENT; + discover_reverse_iif(d->name); } - discover_deps(p->pkg->depends); } } @@ -645,7 +683,7 @@ static void discover_deps(struct apk_dependency_array *deps) foreach_array_item(d, deps) { if (d->conflict) continue; - discover_name(d->name); + discover_name(d->name, STATE_PRESENT); } } |