summaryrefslogtreecommitdiff
path: root/src/state.c
diff options
context:
space:
mode:
authorTimo Teras <timo.teras@iki.fi>2009-08-04 13:57:54 +0300
committerTimo Teras <timo.teras@iki.fi>2009-08-04 13:57:54 +0300
commitec2ade154289ce587eab3375445a33cad992c234 (patch)
tree11d7c8731afa608719330ce3d63f719b250d4171 /src/state.c
parent8c19869c2910332913b5a4f341dbe612c691782e (diff)
downloadapk-tools-ec2ade154289ce587eab3375445a33cad992c234.tar.gz
apk-tools-ec2ade154289ce587eab3375445a33cad992c234.tar.bz2
apk-tools-ec2ade154289ce587eab3375445a33cad992c234.tar.xz
apk-tools-ec2ade154289ce587eab3375445a33cad992c234.zip
state: fix world dependencies to be honored always
previously they might have been skipped on certain situations. this also fixes some other reverse dependency enforcements and implements new "pending" state for locked name.
Diffstat (limited to 'src/state.c')
-rw-r--r--src/state.c133
1 files changed, 97 insertions, 36 deletions
diff --git a/src/state.c b/src/state.c
index 82e3f17..28a411f 100644
--- a/src/state.c
+++ b/src/state.c
@@ -29,9 +29,22 @@ struct apk_deferred_state {
};
#endif
+int apk_state_prune_dependency(struct apk_state *state,
+ struct apk_dependency *dep);
+
+#define APK_NS_LOCKED 0x00000001
+#define APK_NS_PENDING 0x00000002
+
static int inline ns_locked(apk_name_state_t name)
{
- if (((intptr_t) name) & 0x1)
+ if (((intptr_t) name) & APK_NS_LOCKED)
+ return TRUE;
+ return FALSE;
+}
+
+static int inline ns_pending(apk_name_state_t name)
+{
+ if (((intptr_t) name) & APK_NS_PENDING)
return TRUE;
return FALSE;
}
@@ -43,12 +56,18 @@ static int ns_empty(apk_name_state_t name)
static apk_name_state_t ns_from_pkg(struct apk_package *pkg)
{
- return (apk_name_state_t) (((intptr_t) pkg) | 0x1);
+ return (apk_name_state_t) (((intptr_t) pkg) | APK_NS_LOCKED | APK_NS_PENDING);
+}
+
+static apk_name_state_t ns_from_pkg_non_pending(struct apk_package *pkg)
+{
+ return (apk_name_state_t) (((intptr_t) pkg) | APK_NS_LOCKED);
}
static struct apk_package *ns_to_pkg(apk_name_state_t name)
{
- return (struct apk_package *) (((intptr_t) name) & ~0x1);
+ return (struct apk_package *)
+ (((intptr_t) name) & ~(APK_NS_LOCKED | APK_NS_PENDING));
}
static apk_name_state_t ns_from_choices(struct apk_name_choices *nc)
@@ -117,7 +136,7 @@ static void ns_free(apk_name_state_t name)
struct apk_state *apk_state_new(struct apk_database *db)
{
struct apk_state *state;
- int num_bytes;
+ int num_bytes, i, r;
num_bytes = sizeof(struct apk_state) + db->name_id * sizeof(char *);
state = (struct apk_state*) calloc(1, num_bytes);
@@ -125,7 +144,22 @@ struct apk_state *apk_state_new(struct apk_database *db)
state->num_names = db->name_id;
list_init(&state->change_list_head);
+ /* Instantiate each 'name' target in world, and lockout incompatible
+ * choices */
+ for (i = 0; i < db->world->num; i++) {
+ r = apk_state_prune_dependency(state, &db->world->item[i]);
+ if (r < 0) {
+ apk_error("Top level dependencies for %s are "
+ "conflicting or unsatisfiable.",
+ db->world->item[i].name->name);
+ goto err;
+ }
+ }
+
return state;
+err:
+ free(state);
+ return NULL;
}
struct apk_state *apk_state_dup(struct apk_state *state)
@@ -159,20 +193,26 @@ static int apk_state_add_change(struct apk_state *state,
return 0;
}
-int apk_state_lock_dependency(struct apk_state *state,
- struct apk_dependency *dep)
+/* returns:
+ * -1 error
+ * 0 locked entry matches and is ok
+ * +n this many candidates on apk_name_choices for the name
+ */
+int apk_state_prune_dependency(struct apk_state *state,
+ struct apk_dependency *dep)
{
struct apk_name *name = dep->name;
struct apk_name_choices *c;
- struct apk_package *installed = NULL, *latest = NULL, *use;
int i;
if (name->id >= state->num_names)
return -1;
if (ns_empty(state->name[name->id])) {
- if (dep->result_mask == APK_DEPMASK_CONFLICT)
- return apk_state_lock_name(state, name, NULL);
+ if (dep->result_mask == APK_DEPMASK_CONFLICT) {
+ state->name[name->id] = ns_from_pkg(NULL);
+ return 1;
+ }
/* This name has not been visited yet.
* Construct list of candidates. */
@@ -186,16 +226,17 @@ int apk_state_lock_dependency(struct apk_state *state,
/* Locked to not-installed / remove? */
if (pkg == NULL) {
- if (dep->result_mask == APK_DEPMASK_CONFLICT)
- return 0;
- return -1;
+ if (dep->result_mask != APK_DEPMASK_CONFLICT)
+ return -1;
+ } else {
+ if (!(apk_version_compare(pkg->version, dep->version)
+ & dep->result_mask))
+ return -1;
}
- if (apk_version_compare(pkg->version, dep->version)
- & dep->result_mask)
- return 0;
-
- return -1;
+ if (ns_pending(state->name[name->id]))
+ return 1;
+ return 0;
}
/* Multiple candidates: prune incompatible versions. */
@@ -219,11 +260,30 @@ int apk_state_lock_dependency(struct apk_state *state,
if (c->num == 1) {
struct apk_package *pkg = c->pkgs[0];
name_choices_unref(c);
- state->name[name->id] = NULL;
- return apk_state_lock_name(state, name, pkg);
+ state->name[name->id] = ns_from_pkg(pkg);
+ return 1;
}
+
state->name[name->id] = ns_from_choices(c);
+ return c->num;
+}
+int apk_state_lock_dependency(struct apk_state *state,
+ struct apk_dependency *dep)
+{
+ struct apk_name *name = dep->name;
+ struct apk_name_choices *c;
+ struct apk_package *installed = NULL, *latest = NULL, *use;
+ int i, r;
+
+ r = apk_state_prune_dependency(state, dep);
+ if (r <= 0)
+ return r;
+
+ if (ns_pending(state->name[name->id]))
+ return apk_state_lock_name(state, name, ns_to_pkg(state->name[name->id]));
+
+ c = ns_to_choices(state->name[name->id]);
#if 1
/* Get latest and installed packages */
for (i = 0; i < c->num; i++) {
@@ -342,10 +402,10 @@ static int for_each_broken_reverse_depency(struct apk_state *state,
pkg0 = ns_to_pkg(state->name[name0->id]);
if (pkg0 == NULL)
continue;
- return call_if_dependency_broke(state, pkg0, name, cb);
- }
-
- if (!ns_empty(state->name[name0->id])) {
+ r = call_if_dependency_broke(state, pkg0, name, cb);
+ if (r != 0)
+ return r;
+ } else if (!ns_empty(state->name[name0->id])) {
struct apk_name_choices *ns =
ns_to_choices(state->name[name0->id]);
@@ -358,21 +418,22 @@ static int for_each_broken_reverse_depency(struct apk_state *state,
name, cb);
if (r != 0)
return r;
+ break;
}
- return 0;
- }
-
- for (j = 0; j < name0->pkgs->num; j++) {
- pkg0 = name0->pkgs->item[j];
+ } else {
+ for (j = 0; j < name0->pkgs->num; j++) {
+ pkg0 = name0->pkgs->item[j];
- if (apk_pkg_get_state(pkg0) != APK_PKG_INSTALLED)
- continue;
+ if (apk_pkg_get_state(pkg0) != APK_PKG_INSTALLED)
+ continue;
- r = call_if_dependency_broke(state,
- name0->pkgs->item[j],
- name, cb);
- if (r != 0)
- return r;
+ r = call_if_dependency_broke(state,
+ name0->pkgs->item[j],
+ name, cb);
+ if (r != 0)
+ return r;
+ break;
+ }
}
}
@@ -407,7 +468,7 @@ int apk_state_lock_name(struct apk_state *state,
return -1;
ns_free(state->name[name->id]);
- state->name[name->id] = ns_from_pkg(newpkg);
+ state->name[name->id] = ns_from_pkg_non_pending(newpkg);
if (name->pkgs != NULL) {
for (i = 0; i < name->pkgs->num; i++) {