summaryrefslogtreecommitdiffstats
path: root/src/state.c
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2011-04-20 17:51:44 +0200
committerNatanael Copa <ncopa@alpinelinux.org>2011-04-20 17:51:44 +0200
commitf372bfd978be3874c3361cc022e8fc5842657ad2 (patch)
treec058b1de64347d4e65e862a1f5f9124434240a24 /src/state.c
parentfde9ad1782dd4ddb28c428b488e0278471a91c90 (diff)
parent35bba3de1f4d6464dc03ffc60b6a6b6ec25ef6b0 (diff)
downloadapk-tools-lua.tar.bz2
apk-tools-lua.tar.xz
Merge branch 'lua-apk' into luaHEADlua
Conflicts: src/lua-apk.c
Diffstat (limited to 'src/state.c')
-rw-r--r--src/state.c235
1 files changed, 153 insertions, 82 deletions
diff --git a/src/state.c b/src/state.c
index 4a4641d..6de3629 100644
--- a/src/state.c
+++ b/src/state.c
@@ -138,14 +138,20 @@ static struct apk_name_choices *name_choices_new(struct apk_database *db,
if (dep->name != name)
continue;
- for (j = 0; j < nc->num; ) {
- if (apk_dep_is_satisfied(dep, nc->pkgs[j])) {
- j++;
- } else {
- nc->pkgs[j] = nc->pkgs[nc->num - 1];
- nc->num--;
+ if (apk_flags & APK_PREFER_AVAILABLE) {
+ dep->version = apk_blob_atomize(APK_BLOB_NULL);
+ dep->result_mask = APK_DEPMASK_REQUIRE;
+ } else {
+ for (j = 0; j < nc->num; ) {
+ if (apk_dep_is_satisfied(dep, nc->pkgs[j])) {
+ j++;
+ } else {
+ nc->pkgs[j] = nc->pkgs[nc->num - 1];
+ nc->num--;
+ }
}
}
+ break;
}
return nc;
@@ -232,6 +238,50 @@ void apk_state_unref(struct apk_state *state)
free(state);
}
+static struct apk_package *get_locked_or_installed_package(
+ struct apk_state *state,
+ struct apk_name *name)
+{
+ int i;
+
+ if (ns_locked(state->name[name->id]))
+ return ns_to_pkg(state->name[name->id]);
+
+ if (!ns_empty(state->name[name->id])) {
+ struct apk_name_choices *ns =
+ ns_to_choices(state->name[name->id]);
+
+ for (i = 0; i < ns->num; i++) {
+ if (ns->pkgs[i]->ipkg != NULL)
+ return ns->pkgs[i];
+ }
+ return NULL;
+ }
+
+ for (i = 0; i < name->pkgs->num; i++) {
+ if (name->pkgs->item[i]->ipkg != NULL)
+ return name->pkgs->item[i];
+ }
+ return NULL;
+}
+
+static int check_dependency_array(struct apk_state *state,
+ struct apk_dependency_array *da)
+{
+ struct apk_package *pkg;
+ int i;
+
+ for (i = 0; i < da->num; i++) {
+ pkg = get_locked_or_installed_package(state, da->item[i].name);
+ if (pkg == NULL && da->item[i].result_mask != APK_DEPMASK_CONFLICT)
+ return 0;
+ if (!apk_dep_is_satisfied(&da->item[i], pkg))
+ return 0;
+ }
+
+ return da->num;
+}
+
static int apk_state_add_change(struct apk_state *state,
struct apk_package *oldpkg,
struct apk_package *newpkg)
@@ -334,20 +384,22 @@ int apk_state_prune_dependency(struct apk_state *state,
return c->num;
}
-int apk_state_lock_dependency(struct apk_state *state,
- struct apk_dependency *dep)
+int apk_state_autolock_name(struct apk_state *state, struct apk_name *name,
+ int install_if)
{
- 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;
+ struct apk_package *installed = NULL, *latest = NULL, *use;
+ int i;
if (ns_pending(state->name[name->id]))
return apk_state_lock_name(state, name, ns_to_pkg(state->name[name->id]));
+ if (ns_locked(state->name[name->id]))
+ return 0;
+ if (ns_empty(state->name[name->id])) {
+ /* This name has not been visited yet.
+ * Construct list of candidates. */
+ state->name[name->id] = ns_from_choices(name_choices_new(state->db, name));
+ }
c = ns_to_choices(state->name[name->id]);
#if 1
@@ -355,6 +407,10 @@ int apk_state_lock_dependency(struct apk_state *state,
for (i = 0; i < c->num; i++) {
struct apk_package *pkg = c->pkgs[i];
+ if (install_if &&
+ !check_dependency_array(state, pkg->install_if))
+ continue;
+
if (pkg->ipkg != NULL)
installed = pkg;
else if (!apk_state_pkg_available(state, pkg))
@@ -396,7 +452,13 @@ int apk_state_lock_dependency(struct apk_state *state,
use = latest;
}
if (use == NULL)
- return -1;
+ return -2;
+
+ /* Install_if check did not result in package selection change:
+ * do not lock the package yet as the preferency might change
+ * later. */
+ if (install_if && use->ipkg != NULL)
+ return 0;
return apk_state_lock_name(state, name, use);
#else
@@ -411,6 +473,18 @@ int apk_state_lock_dependency(struct apk_state *state,
#endif
}
+int apk_state_lock_dependency(struct apk_state *state,
+ struct apk_dependency *dep)
+{
+ int r;
+
+ r = apk_state_prune_dependency(state, dep);
+ if (r <= 0)
+ return r;
+
+ return apk_state_autolock_name(state, dep->name, FALSE);
+}
+
static int apk_state_fix_package(struct apk_state *state,
struct apk_package *pkg)
{
@@ -420,12 +494,18 @@ static int apk_state_fix_package(struct apk_state *state,
return 0;
for (i = 0; i < pkg->depends->num; i++) {
- r = apk_state_lock_dependency(state,
- &pkg->depends->item[i]);
- if (r != 0)
- ret = -1;
+ if (pkg->depends->item[i].name->flags & APK_NAME_TOPLEVEL_OVERRIDE) {
+ r = apk_state_prune_dependency(state,
+ &pkg->depends->item[i]);
+ if (r < 0)
+ ret = -1;
+ } else {
+ r = apk_state_lock_dependency(state,
+ &pkg->depends->item[i]);
+ if (r != 0)
+ ret = -1;
+ }
}
-
return ret;
}
@@ -467,48 +547,19 @@ static int for_each_broken_reverse_depency(struct apk_state *state,
void *ctx)
{
struct apk_package *pkg0;
- int i, j, r;
+ int i, r;
for (i = 0; i < name->rdepends->num; i++) {
struct apk_name *name0 = name->rdepends->item[i];
- if (ns_locked(state->name[name0->id])) {
- pkg0 = ns_to_pkg(state->name[name0->id]);
- if (pkg0 == NULL)
- continue;
- r = call_if_dependency_broke(state, pkg0, name,
- cb, ctx);
- 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]);
-
- for (j = 0; j < ns->num; j++) {
- if (ns->pkgs[j]->ipkg == NULL)
- continue;
- r = call_if_dependency_broke(state,
- ns->pkgs[j],
- name, cb, ctx);
- if (r != 0)
- return r;
- break;
- }
- } else {
- for (j = 0; j < name0->pkgs->num; j++) {
- pkg0 = name0->pkgs->item[j];
-
- if (pkg0->ipkg == NULL)
- continue;
+ pkg0 = get_locked_or_installed_package(state, name0);
+ if (pkg0 == NULL)
+ continue;
- r = call_if_dependency_broke(state,
- name0->pkgs->item[j],
- name, cb, ctx);
- if (r != 0)
- return r;
- break;
- }
- }
+ r = call_if_dependency_broke(state, pkg0, name,
+ cb, ctx);
+ if (r != 0)
+ return r;
}
return 0;
@@ -578,15 +629,19 @@ int apk_state_lock_name(struct apk_state *state,
}
/* If the chosen package is installed, all is done here */
- if (oldpkg == newpkg &&
- (newpkg == NULL ||
- !(newpkg->name->flags & APK_NAME_REINSTALL)))
- return 0;
+ if ((oldpkg != newpkg) ||
+ (newpkg != NULL && (newpkg->name->flags & APK_NAME_REINSTALL))) {
+ /* Track change */
+ r = apk_state_add_change(state, oldpkg, newpkg);
+ if (r != 0)
+ return r;
+ }
- /* Track change */
- r = apk_state_add_change(state, oldpkg, newpkg);
- if (r != 0)
- return r;
+ /* Check all reverse install_if's */
+ if (newpkg != NULL) {
+ for (i = 0; i < newpkg->name->rinstall_if->num; i++)
+ apk_state_autolock_name(state, newpkg->name->rinstall_if->item[i], TRUE);
+ }
return 0;
}
@@ -655,22 +710,19 @@ static void apk_count_change(struct apk_change *change, struct apk_stats *stats)
stats->packages ++;
}
-static inline void apk_draw_progress(int percent, int last)
+static void apk_draw_progress(int percent)
{
- char tmp[128];
- char reset[128];
+ const int bar_width = (apk_screen_width - 7);
int i;
- snprintf(tmp, sizeof(tmp), "-[ ]- %3i%%", percent);
- for (i = 0; (i < (percent/5)) && (i < (sizeof(tmp)-2)); i++)
- tmp[2+i] = '#';
- memset(reset, '\b', strlen(tmp));
- fwrite(tmp, strlen(tmp), 1, stderr);
- if (!last)
- fwrite(reset, strlen(tmp), 1, stderr);
- else if (apk_verbosity > 0)
- fwrite("\n", 1, 1, stderr);
+ fprintf(stderr, "\e7%3i%% [", percent);
+ for (i = 0; i < bar_width * percent / 100; i++)
+ fputc('#', stderr);
+ for (; i < bar_width; i++)
+ fputc(' ', stderr);
+ fputc(']', stderr);
fflush(stderr);
+ fputs("\e8\e[0K", stderr);
}
struct progress {
@@ -692,7 +744,7 @@ static void progress_cb(void *ctx, size_t progress)
prog->total.bytes + prog->total.packages);
if (prog->count != count)
- apk_draw_progress(count, 0);
+ apk_draw_progress(count);
prog->count = count;
}
@@ -799,6 +851,23 @@ static int apk_state_autoclean(struct apk_state *state,
return r;
}
}
+
+ for (i = 0; i < pkg->name->rinstall_if->num; i++) {
+ struct apk_name *n = pkg->name->rinstall_if->item[i];
+
+ if (ns_locked(state->name[n->id]))
+ continue;
+ if (n->flags & APK_NAME_TOPLEVEL)
+ continue;
+
+ r = apk_state_autolock_name(state, n, TRUE);
+ if (r == -2) {
+ r = apk_state_lock_name(state, n, NULL);
+ if (r != 0)
+ return r;
+ }
+ }
+
return 0;
}
@@ -874,11 +943,11 @@ void apk_state_print_errors(struct apk_state *state)
printf("\n");
}
-int apk_state_commit(struct apk_state *state,
- struct apk_database *db)
+int apk_state_commit(struct apk_state *state)
{
struct progress prog;
struct apk_change *change;
+ struct apk_database *db = state->db;
int n = 0, r = 0, size_diff = 0, toplevel = FALSE, deleteonly = TRUE;
/* Count what needs to be done */
@@ -940,6 +1009,8 @@ int apk_state_commit(struct apk_state *state,
list_for_each_entry(change, &state->change_list_head, change_list) {
n++;
apk_print_change(db, change->oldpkg, change->newpkg, n, state->num_changes);
+ if (apk_flags & APK_PROGRESS)
+ apk_draw_progress(prog.count);
prog.pkg = change->newpkg;
if (!(apk_flags & APK_SIMULATE)) {
@@ -961,7 +1032,7 @@ int apk_state_commit(struct apk_state *state,
apk_count_change(change, &prog.done);
}
if (apk_flags & APK_PROGRESS)
- apk_draw_progress(100, 1);
+ apk_draw_progress(100);
update_state:
apk_db_run_triggers(db);