summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2013-06-19 21:39:01 +0300
committerTimo Teräs <timo.teras@iki.fi>2013-06-19 21:39:01 +0300
commit17145f82aeba9a9fdfdf03cb4f74cb41cf3ab913 (patch)
treed97030f3ce9abe46670952a35e1eba056177523c
parent6da083fc24e4f1ef0363957074148d1bc11cef83 (diff)
downloadapk-tools-17145f82aeba9a9fdfdf03cb4f74cb41cf3ab913.tar.gz
apk-tools-17145f82aeba9a9fdfdf03cb4f74cb41cf3ab913.tar.bz2
apk-tools-17145f82aeba9a9fdfdf03cb4f74cb41cf3ab913.tar.xz
apk-tools-17145f82aeba9a9fdfdf03cb4f74cb41cf3ab913.zip
solver: fix package deletion to consier provides properly
-rw-r--r--src/apk_solver_data.h13
-rw-r--r--src/commit.c5
-rw-r--r--src/solver.c58
3 files changed, 48 insertions, 28 deletions
diff --git a/src/apk_solver_data.h b/src/apk_solver_data.h
index cf7a3bd..7853af5 100644
--- a/src/apk_solver_data.h
+++ b/src/apk_solver_data.h
@@ -17,10 +17,17 @@
#include "apk_provider_data.h"
struct apk_solver_name_state {
- struct list_head dirty_list;
- struct list_head unresolved_list;
struct apk_provider chosen;
-
+ union {
+ struct {
+ struct list_head dirty_list;
+ struct list_head unresolved_list;
+ };
+ struct {
+ struct apk_name *installed_name;
+ struct apk_package *installed_pkg;
+ };
+ };
unsigned short requirers;
unsigned short merge_depends;
unsigned short merge_provides;
diff --git a/src/commit.c b/src/commit.c
index fc4fafd..09e8b28 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -232,11 +232,10 @@ int apk_solver_commit_changeset(struct apk_database *db,
foreach_array_item(change, changeset->changes) {
count_change(change, &prog.total);
if (change->new_pkg)
- size_diff += change->new_pkg->installed_size;
+ size_diff += change->new_pkg->installed_size / 1024;
if (change->old_pkg)
- size_diff -= change->old_pkg->installed_size;
+ size_diff -= change->old_pkg->installed_size / 1024;
}
- size_diff /= 1024;
size_unit = 'K';
if (abs(size_diff) > 10000) {
size_diff /= 1024;
diff --git a/src/solver.c b/src/solver.c
index d6ebc0e..889cffd 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -665,13 +665,15 @@ static void cset_gen_name_change(struct apk_solver_state *ss, struct apk_name *n
static void cset_gen_name_remove(struct apk_solver_state *ss, struct apk_package *pkg);
static void cset_gen_dep(struct apk_solver_state *ss, struct apk_package *ppkg, struct apk_dependency *dep);
-static void cset_track_deps_added(struct apk_dependency_array *deps)
+static void cset_track_deps_added(struct apk_package *pkg)
{
struct apk_dependency *d;
- foreach_array_item(d, deps)
- if (!d->conflict)
- d->name->ss.requirers++;
+ foreach_array_item(d, pkg->depends) {
+ if (d->conflict || !d->name->ss.installed_name)
+ continue;
+ d->name->ss.installed_name->ss.requirers++;
+ }
}
static void cset_track_deps_removed(struct apk_solver_state *ss, struct apk_package *pkg)
@@ -680,12 +682,11 @@ static void cset_track_deps_removed(struct apk_solver_state *ss, struct apk_pack
struct apk_package *pkg0;
foreach_array_item(d, pkg->depends) {
- if (d->conflict)
+ if (d->conflict || !d->name->ss.installed_name)
continue;
- d->name->ss.requirers--;
- if (d->name->ss.requirers > 0)
+ if (--d->name->ss.installed_name->ss.requirers > 0)
continue;
- pkg0 = apk_pkg_get_installed(d->name);
+ pkg0 = d->name->ss.installed_pkg;
if (pkg0 != NULL)
cset_gen_name_remove(ss, pkg0);
}
@@ -717,14 +718,10 @@ static void cset_check_install_by_iif(struct apk_solver_state *ss, struct apk_na
static void cset_check_removal_by_iif(struct apk_solver_state *ss, struct apk_name *name)
{
- struct apk_package *pkg;
+ struct apk_package *pkg = name->ss.installed_pkg;
struct apk_dependency *dep0;
- if (name->ss.in_changeset || name->ss.chosen.pkg != NULL)
- return;
-
- pkg = apk_pkg_get_installed(name);
- if (pkg == NULL)
+ if (pkg == NULL || name->ss.in_changeset || name->ss.chosen.pkg != NULL)
return;
foreach_array_item(dep0, pkg->install_if) {
@@ -748,7 +745,7 @@ static void cset_gen_name_change(struct apk_solver_state *ss, struct apk_name *n
pkg->ss.in_changeset = 1;
pkg->name->ss.in_changeset = 1;
- opkg = apk_pkg_get_installed(pkg->name);
+ opkg = pkg->name->ss.installed_pkg;
if (opkg) {
foreach_array_item(pname, opkg->name->rinstall_if)
cset_check_removal_by_iif(ss, *pname);
@@ -763,7 +760,7 @@ static void cset_gen_name_change(struct apk_solver_state *ss, struct apk_name *n
foreach_array_item(pname, pkg->name->rinstall_if)
cset_check_install_by_iif(ss, *pname);
- cset_track_deps_added(pkg->depends);
+ cset_track_deps_added(pkg);
if (opkg)
cset_track_deps_removed(ss, opkg);
}
@@ -796,18 +793,35 @@ static void cset_gen_dep(struct apk_solver_state *ss, struct apk_package *ppkg,
mark_error(ss, ppkg);
}
+static int cset_reset_name(apk_hash_item item, void *ctx)
+{
+ struct apk_name *name = (struct apk_name *) item;
+ name->ss.installed_pkg = NULL;
+ name->ss.installed_name = NULL;
+ name->ss.requirers = 0;
+ return 0;
+}
+
static void generate_changeset(struct apk_solver_state *ss, struct apk_dependency_array *world)
{
struct apk_changeset *changeset = ss->changeset;
+ struct apk_package *pkg;
struct apk_installed_package *ipkg;
struct apk_dependency *d;
apk_change_array_init(&changeset->changes);
+ apk_hash_foreach(&ss->db->available.names, cset_reset_name, NULL);
+ list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list) {
+ pkg = ipkg->pkg;
+ pkg->name->ss.installed_pkg = pkg;
+ pkg->name->ss.installed_name = pkg->name;
+ foreach_array_item(d, pkg->provides)
+ if (d->version != &apk_null_blob)
+ d->name->ss.installed_name = pkg->name;
+ }
list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list)
- ipkg->pkg->name->ss.requirers = 0;
- list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list)
- cset_track_deps_added(ipkg->pkg->depends);
+ cset_track_deps_added(ipkg->pkg);
list_for_each_entry(ipkg, &ss->db->installed.packages, installed_pkgs_list)
cset_check_removal_by_deps(ss, ipkg->pkg);
@@ -823,7 +837,7 @@ static void generate_changeset(struct apk_solver_state *ss, struct apk_dependenc
changeset->num_adjust;
}
-static int free_state(apk_hash_item item, void *ctx)
+static int free_name(apk_hash_item item, void *ctx)
{
struct apk_name *name = (struct apk_name *) item;
memset(&name->ss, 0, sizeof(name->ss));
@@ -909,12 +923,12 @@ restart:
dbg_printf("disabling broken world dep: %s", name->name);
}
}
- apk_hash_foreach(&db->available.names, free_state, NULL);
+ apk_hash_foreach(&db->available.names, free_name, NULL);
apk_hash_foreach(&db->available.packages, free_package, NULL);
goto restart;
}
- apk_hash_foreach(&db->available.names, free_state, NULL);
+ apk_hash_foreach(&db->available.names, free_name, NULL);
apk_hash_foreach(&db->available.packages, free_package, NULL);
dbg_printf("solver done, errors=%d\n", ss->errors);