diff --git a/src/apk.c b/src/apk.c index 7663d4c..4b97be5 100644 --- a/src/apk.c +++ b/src/apk.c @@ -30,6 +30,8 @@ #include "apk_blob.h" #include "apk_print.h" +char **apk_argv; + static struct apk_option generic_options[] = { { 'h', "help", "Show generic help or applet specific help" }, { 'p', "root", "Install packages to DIR", @@ -245,6 +247,10 @@ int main(int argc, char **argv) struct apk_database db; struct apk_db_options dbopts; + apk_argv = malloc(sizeof(char*[argc+1])); + memcpy(apk_argv, argv, sizeof(char*[argc])); + apk_argv[argc] = NULL; + memset(&dbopts, 0, sizeof(dbopts)); list_init(&dbopts.repository_list); apk_atom_init(); diff --git a/src/apk_defines.h b/src/apk_defines.h index 6d5f49c..b11d181 100644 --- a/src/apk_defines.h +++ b/src/apk_defines.h @@ -50,6 +50,7 @@ extern int apk_verbosity; extern unsigned int apk_flags; extern const char *apk_arch; +extern char **apk_argv; #define APK_FORCE 0x0001 #define APK_SIMULATE 0x0002 diff --git a/src/apk_state.h b/src/apk_state.h index 42d3f3f..1ac049a 100644 --- a/src/apk_state.h +++ b/src/apk_state.h @@ -23,7 +23,8 @@ struct apk_change { }; struct apk_state { - unsigned int refs, num_names; + unsigned int refs, num_names, num_changes; + int print_ok; struct apk_database *db; struct list_head change_list_head; struct apk_package_array *conflicts; diff --git a/src/state.c b/src/state.c index 0471850..ddfca57 100644 --- a/src/state.c +++ b/src/state.c @@ -199,6 +199,7 @@ struct apk_state *apk_state_new(struct apk_database *db) state->refs = 1; state->num_names = db->name_id; state->db = db; + state->print_ok = 1; list_init(&state->change_list_head); apk_name_array_init(&state->missing); @@ -235,6 +236,7 @@ static int apk_state_add_change(struct apk_state *state, list_init(&change->change_list); list_add_tail(&change->change_list, &state->change_list_head); + state->num_changes++; change->oldpkg = oldpkg; change->newpkg = newpkg; @@ -873,13 +875,11 @@ int apk_state_commit(struct apk_state *state, { struct progress prog; struct apk_change *change; - int r = 0, size_diff = 0, toplevel = FALSE, deleteonly = TRUE; - int n = 0, numpkg = 0; + int n = 0, r = 0, size_diff = 0, toplevel = FALSE, deleteonly = TRUE; /* Count what needs to be done */ memset(&prog, 0, sizeof(prog)); list_for_each_entry(change, &state->change_list_head, change_list) { - numpkg++; if (change->newpkg == NULL) { if (change->oldpkg->name->flags & APK_NAME_TOPLEVEL) toplevel = TRUE; @@ -935,7 +935,7 @@ int apk_state_commit(struct apk_state *state, n = 0; list_for_each_entry(change, &state->change_list_head, change_list) { n++; - apk_print_change(db, change->oldpkg, change->newpkg, n, numpkg); + apk_print_change(db, change->oldpkg, change->newpkg, n, state->num_changes); prog.pkg = change->newpkg; if (!(apk_flags & APK_SIMULATE)) { @@ -963,7 +963,7 @@ update_state: apk_db_run_triggers(db); apk_db_write_config(db); - if (r == 0) + if (r == 0 && state->print_ok) apk_message("OK: %d packages, %d dirs, %d files", db->installed.stats.packages, db->installed.stats.dirs, diff --git a/src/upgrade.c b/src/upgrade.c index be6a499..8763cb2 100644 --- a/src/upgrade.c +++ b/src/upgrade.c @@ -30,6 +30,46 @@ static int upgrade_parse(void *ctx, struct apk_db_options *dbopts, return 0; } +int apk_do_self_upgrade(struct apk_database *db, struct apk_state *state) +{ + struct apk_dependency dep; + int r, i; + + apk_dep_from_blob(&dep, db, APK_BLOB_STR("apk-tools")); + + if (apk_flags & APK_PREFER_AVAILABLE) { + for (i = 0; i < db->world->num; i++) { + struct apk_dependency *dep0 = &db->world->item[i]; + if (dep0->name != dep.name) + continue; + dep0->version = apk_blob_atomize(APK_BLOB_NULL); + dep0->result_mask = APK_VERSION_EQUAL | APK_VERSION_LESS | APK_VERSION_GREATER; + break; + } + } + + r = apk_state_lock_dependency(state, &dep); + if (r != 0 || state->num_changes == 0) + return r; + + if (apk_flags & APK_SIMULATE) { + apk_warning("This simulation is not reliable as apk-tools upgrade is available."); + return 0; + } + + apk_message("Uprading first to new apk-tools:"); + state->print_ok = 0; + r = apk_state_commit(state, db); + apk_state_unref(state); + apk_db_close(db); + + apk_message("Performing rest of the operation:"); + execvp(apk_argv[0], apk_argv); + + apk_error("PANIC! Failed to re-execute new apk-tools!"); + exit(1); +} + static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **argv) { struct apk_state *state = NULL; @@ -38,12 +78,18 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg int i, r = 0; apk_flags |= APK_UPGRADE; - apk_name_array_init(&missing); + state = apk_state_new(db); if (state == NULL) goto err; + r = apk_do_self_upgrade(db, state); + if (r != 0) { + apk_state_print_errors(state); + goto err; + } + for (i = 0; i < db->world->num; i++) { struct apk_dependency *dep = &db->world->item[i]; if (dep->version != null_atom &&