upgrade.c 3.29 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
 * 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>
14 15
#include <stdlib.h>
#include <unistd.h>
Timo Teräs's avatar
Timo Teräs committed
16 17
#include "apk_applet.h"
#include "apk_database.h"
Natanael Copa's avatar
Natanael Copa committed
18
#include "apk_print.h"
Timo Teräs's avatar
Timo Teräs committed
19 20 21 22
#include "apk_solver.h"

struct upgrade_ctx {
	unsigned short solver_flags;
23
	int no_self_upgrade : 1;
Timo Teräs's avatar
Timo Teräs committed
24
};
Timo Teräs's avatar
Timo Teräs committed
25

26 27
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
28
{
Timo Teräs's avatar
Timo Teräs committed
29 30
	struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx;

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

44
int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags)
45
{
46 47 48
	struct apk_name *name;
	struct apk_changeset changeset = {};
	struct apk_package_array *solution = NULL;
49
	int r;
50

51 52 53 54
	name = apk_db_get_name(db, APK_BLOB_STR("apk-tools"));
	apk_solver_set_name_flags(name, solver_flags);
	db->performing_self_update = 1;

55
	r = apk_solver_solve(db, 0, db->world, &solution, &changeset);
56 57 58 59 60 61 62
	if (r != 0) {
		if (apk_flags & APK_FORCE)
			r = 0;
		else
			apk_solver_print_errors(db, solution, db->world, r);
		goto ret;
	}
63

64 65
	if (changeset.changes->num == 0)
		goto ret;
66 67 68

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

72
	apk_message("Upgrading critical system libraries and apk-tools:");
73
	apk_solver_commit_changeset(db, &changeset, db->world);
74 75
	apk_db_close(db);

76
	apk_message("Continuing the upgrade transaction with new apk-tools:");
77 78 79
	for (r = 0; apk_argv[r] != NULL; r++)
		;
	apk_argv[r] = "--no-self-upgrade";
80 81 82 83
	execvp(apk_argv[0], apk_argv);

	apk_error("PANIC! Failed to re-execute new apk-tools!");
	exit(1);
84 85 86 87 88 89 90

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

	return r;
91 92
}

93
static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **argv)
Timo Teräs's avatar
Timo Teräs committed
94
{
Timo Teräs's avatar
Timo Teräs committed
95 96 97
	struct upgrade_ctx *uctx = (struct upgrade_ctx *) ctx;
	unsigned short solver_flags;
	int r;
98

Timo Teräs's avatar
Timo Teräs committed
99
	solver_flags = APK_SOLVERF_UPGRADE | uctx->solver_flags;
100 101 102 103 104
	if (!uctx->no_self_upgrade) {
		r = apk_do_self_upgrade(db, solver_flags);
		if (r != 0)
			return r;
	}
105

Timo Teräs's avatar
Timo Teräs committed
106
	return apk_solver_commit(db, solver_flags, db->world);
Timo Teräs's avatar
Timo Teräs committed
107 108
}

Timo Teräs's avatar
Timo Teräs committed
109 110 111 112
static struct apk_option upgrade_options[] = {
	{ 'a', "available",
	  "Re-install or downgrade if currently installed package is not "
	  "currently available from any repository" },
113 114
	{ 0x10000, "no-self-upgrade",
	  "Do not do early upgrade of 'apk-tools' package" },
Timo Teräs's avatar
Timo Teräs committed
115 116
};

Timo Teräs's avatar
Timo Teräs committed
117 118
static struct apk_applet apk_upgrade = {
	.name = "upgrade",
Timo Teräs's avatar
Timo Teräs committed
119 120
	.help = "Upgrade (or downgrade with -a) the currently installed "
		"packages to versions available in repositories.",
121
	.open_flags = APK_OPENF_WRITE,
Timo Teräs's avatar
Timo Teräs committed
122
	.context_size = sizeof(struct upgrade_ctx),
Timo Teräs's avatar
Timo Teräs committed
123 124 125
	.num_options = ARRAY_SIZE(upgrade_options),
	.options = upgrade_options,
	.parse = upgrade_parse,
Timo Teräs's avatar
Timo Teräs committed
126 127 128 129 130
	.main = upgrade_main,
};

APK_DEFINE_APPLET(apk_upgrade);