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.
cute-signatures
Timo Teräs 2011-01-01 15:48:10 +02:00
parent 0cc41ba4dc
commit 59d222d58c
5 changed files with 61 additions and 7 deletions

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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 &&