Commit 59d222d5 authored by Timo Teräs's avatar Timo Teräs

upgrade: perform upgrade of apk-tools first if available

Also re-exec's apk-tools to perform rest of the upgrade using
the new apk-tools. This allows handling of new apk-tools features
properly. Fixes #140.
parent 0cc41ba4
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "apk_blob.h" #include "apk_blob.h"
#include "apk_print.h" #include "apk_print.h"
char **apk_argv;
static struct apk_option generic_options[] = { static struct apk_option generic_options[] = {
{ 'h', "help", "Show generic help or applet specific help" }, { 'h', "help", "Show generic help or applet specific help" },
{ 'p', "root", "Install packages to DIR", { 'p', "root", "Install packages to DIR",
...@@ -245,6 +247,10 @@ int main(int argc, char **argv) ...@@ -245,6 +247,10 @@ int main(int argc, char **argv)
struct apk_database db; struct apk_database db;
struct apk_db_options dbopts; 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)); memset(&dbopts, 0, sizeof(dbopts));
list_init(&dbopts.repository_list); list_init(&dbopts.repository_list);
apk_atom_init(); apk_atom_init();
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
extern int apk_verbosity; extern int apk_verbosity;
extern unsigned int apk_flags; extern unsigned int apk_flags;
extern const char *apk_arch; extern const char *apk_arch;
extern char **apk_argv;
#define APK_FORCE 0x0001 #define APK_FORCE 0x0001
#define APK_SIMULATE 0x0002 #define APK_SIMULATE 0x0002
......
...@@ -23,7 +23,8 @@ struct apk_change { ...@@ -23,7 +23,8 @@ struct apk_change {
}; };
struct apk_state { struct apk_state {
unsigned int refs, num_names; unsigned int refs, num_names, num_changes;
int print_ok;
struct apk_database *db; struct apk_database *db;
struct list_head change_list_head; struct list_head change_list_head;
struct apk_package_array *conflicts; struct apk_package_array *conflicts;
......
...@@ -199,6 +199,7 @@ struct apk_state *apk_state_new(struct apk_database *db) ...@@ -199,6 +199,7 @@ struct apk_state *apk_state_new(struct apk_database *db)
state->refs = 1; state->refs = 1;
state->num_names = db->name_id; state->num_names = db->name_id;
state->db = db; state->db = db;
state->print_ok = 1;
list_init(&state->change_list_head); list_init(&state->change_list_head);
apk_name_array_init(&state->missing); apk_name_array_init(&state->missing);
...@@ -235,6 +236,7 @@ static int apk_state_add_change(struct apk_state *state, ...@@ -235,6 +236,7 @@ static int apk_state_add_change(struct apk_state *state,
list_init(&change->change_list); list_init(&change->change_list);
list_add_tail(&change->change_list, &state->change_list_head); list_add_tail(&change->change_list, &state->change_list_head);
state->num_changes++;
change->oldpkg = oldpkg; change->oldpkg = oldpkg;
change->newpkg = newpkg; change->newpkg = newpkg;
...@@ -873,13 +875,11 @@ int apk_state_commit(struct apk_state *state, ...@@ -873,13 +875,11 @@ int apk_state_commit(struct apk_state *state,
{ {
struct progress prog; struct progress prog;
struct apk_change *change; struct apk_change *change;
int r = 0, size_diff = 0, toplevel = FALSE, deleteonly = TRUE; int n = 0, r = 0, size_diff = 0, toplevel = FALSE, deleteonly = TRUE;
int n = 0, numpkg = 0;
/* Count what needs to be done */ /* Count what needs to be done */
memset(&prog, 0, sizeof(prog)); memset(&prog, 0, sizeof(prog));
list_for_each_entry(change, &state->change_list_head, change_list) { list_for_each_entry(change, &state->change_list_head, change_list) {
numpkg++;
if (change->newpkg == NULL) { if (change->newpkg == NULL) {
if (change->oldpkg->name->flags & APK_NAME_TOPLEVEL) if (change->oldpkg->name->flags & APK_NAME_TOPLEVEL)
toplevel = TRUE; toplevel = TRUE;
...@@ -935,7 +935,7 @@ int apk_state_commit(struct apk_state *state, ...@@ -935,7 +935,7 @@ int apk_state_commit(struct apk_state *state,
n = 0; n = 0;
list_for_each_entry(change, &state->change_list_head, change_list) { list_for_each_entry(change, &state->change_list_head, change_list) {
n++; 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; prog.pkg = change->newpkg;
if (!(apk_flags & APK_SIMULATE)) { if (!(apk_flags & APK_SIMULATE)) {
...@@ -963,7 +963,7 @@ update_state: ...@@ -963,7 +963,7 @@ update_state:
apk_db_run_triggers(db); apk_db_run_triggers(db);
apk_db_write_config(db); apk_db_write_config(db);
if (r == 0) if (r == 0 && state->print_ok)
apk_message("OK: %d packages, %d dirs, %d files", apk_message("OK: %d packages, %d dirs, %d files",
db->installed.stats.packages, db->installed.stats.packages,
db->installed.stats.dirs, db->installed.stats.dirs,
......
...@@ -30,6 +30,46 @@ static int upgrade_parse(void *ctx, struct apk_db_options *dbopts, ...@@ -30,6 +30,46 @@ static int upgrade_parse(void *ctx, struct apk_db_options *dbopts,
return 0; 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) static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **argv)
{ {
struct apk_state *state = NULL; struct apk_state *state = NULL;
...@@ -38,12 +78,18 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg ...@@ -38,12 +78,18 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg
int i, r = 0; int i, r = 0;
apk_flags |= APK_UPGRADE; apk_flags |= APK_UPGRADE;
apk_name_array_init(&missing); apk_name_array_init(&missing);
state = apk_state_new(db); state = apk_state_new(db);
if (state == NULL) if (state == NULL)
goto err; 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++) { for (i = 0; i < db->world->num; i++) {
struct apk_dependency *dep = &db->world->item[i]; struct apk_dependency *dep = &db->world->item[i];
if (dep->version != null_atom && if (dep->version != null_atom &&
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment