upgrade.c 2.99 KB
Newer Older
Timo Teräs's avatar
Timo Teräs committed
1 2 3
/* upgrade.c - Alpine Package Keeper (APK)
 *
 * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
4
 * Copyright (C) 2008-2011 Timo Teräs <timo.teras@iki.fi>
Timo Teräs's avatar
Timo Teräs committed
5 6 7 8 9 10 11 12 13 14 15 16
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation. See http://www.gnu.org/ for details.
 */

#include <errno.h>
#include <stdio.h>
#include <zlib.h>
#include "apk_applet.h"
#include "apk_database.h"
Natanael Copa's avatar
Natanael Copa committed
17
#include "apk_print.h"
Timo Teräs's avatar
Timo Teräs committed
18 19 20 21 22
#include "apk_solver.h"

struct upgrade_ctx {
	unsigned short solver_flags;
};
Timo Teräs's avatar
Timo Teräs committed
23

24 25
static int upgrade_parse(void *ctx, struct apk_db_options *dbopts,
			 int optch, int optindex, const char *optarg)
Timo Teräs's avatar
Timo Teräs committed
26
{
Timo Teräs's avatar
Timo Teräs committed
27 28
	struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx;

Timo Teräs's avatar
Timo Teräs committed
29 30
	switch (optch) {
	case 'a':
Timo Teräs's avatar
Timo Teräs committed
31
		uctx->solver_flags |= APK_SOLVERF_AVAILABLE;
Timo Teräs's avatar
Timo Teräs committed
32 33 34 35 36 37 38
		break;
	default:
		return -1;
	}
	return 0;
}

39
int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags)
40
{
41 42 43
	struct apk_name *name;
	struct apk_changeset changeset = {};
	struct apk_package_array *solution = NULL;
44
	int r;
45

46 47 48 49 50 51 52 53 54 55 56 57
	name = apk_db_get_name(db, APK_BLOB_STR("apk-tools"));
	apk_solver_set_name_flags(name, solver_flags);
	db->performing_self_update = 1;

	r = apk_solver_solve(db, 0, db->world, &solution, &changeset);
	if (r != 0) {
		if (apk_flags & APK_FORCE)
			r = 0;
		else
			apk_solver_print_errors(db, solution, db->world, r);
		goto ret;
	}
58

59 60
	if (changeset.changes->num == 0)
		goto ret;
61 62 63

	if (apk_flags & APK_SIMULATE) {
		apk_warning("This simulation is not reliable as apk-tools upgrade is available.");
64
		goto ret;
65 66
	}

67
	apk_message("Upgrading critical system libraries and apk-tools:");
68
	apk_solver_commit_changeset(db, &changeset, db->world);
69 70
	apk_db_close(db);

71
	apk_message("Continuing the upgrade transaction with new apk-tools:");
72 73 74 75
	execvp(apk_argv[0], apk_argv);

	apk_error("PANIC! Failed to re-execute new apk-tools!");
	exit(1);
76 77 78 79 80 81 82

ret:
	apk_package_array_free(&solution);
	apk_change_array_free(&changeset.changes);
	db->performing_self_update = 0;

	return r;
83 84
}

85
static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **argv)
Timo Teräs's avatar
Timo Teräs committed
86
{
Timo Teräs's avatar
Timo Teräs committed
87 88 89
	struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx;
	unsigned short solver_flags;
	int r;
90

Timo Teräs's avatar
Timo Teräs committed
91
	solver_flags = APK_SOLVERF_UPGRADE | uctx->solver_flags;
92

93
	r = apk_do_self_upgrade(db, solver_flags);
Timo Teräs's avatar
Timo Teräs committed
94 95
	if (r != 0)
		return r;
96

Timo Teräs's avatar
Timo Teräs committed
97
	return apk_solver_commit(db, solver_flags, db->world);
Timo Teräs's avatar
Timo Teräs committed
98 99
}

Timo Teräs's avatar
Timo Teräs committed
100 101 102 103
static struct apk_option upgrade_options[] = {
	{ 'a', "available",
	  "Re-install or downgrade if currently installed package is not "
	  "currently available from any repository" },
Timo Teräs's avatar
Timo Teräs committed
104 105
};

Timo Teräs's avatar
Timo Teräs committed
106 107
static struct apk_applet apk_upgrade = {
	.name = "upgrade",
Timo Teräs's avatar
Timo Teräs committed
108 109
	.help = "Upgrade (or downgrade with -a) the currently installed "
		"packages to versions available in repositories.",
110
	.open_flags = APK_OPENF_WRITE,
Timo Teräs's avatar
Timo Teräs committed
111
	.context_size = sizeof(struct upgrade_ctx),
Timo Teräs's avatar
Timo Teräs committed
112 113 114
	.num_options = ARRAY_SIZE(upgrade_options),
	.options = upgrade_options,
	.parse = upgrade_parse,
Timo Teräs's avatar
Timo Teräs committed
115 116 117 118 119
	.main = upgrade_main,
};

APK_DEFINE_APPLET(apk_upgrade);