summaryrefslogtreecommitdiff
path: root/src/pacman/upgrade.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pacman/upgrade.c')
-rw-r--r--src/pacman/upgrade.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c
new file mode 100644
index 00000000..e5626516
--- /dev/null
+++ b/src/pacman/upgrade.c
@@ -0,0 +1,171 @@
+/*
+ * upgrade.c
+ *
+ * Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <alpm.h>
+#include <alpm_list.h>
+
+/* pacman */
+#include "pacman.h"
+#include "callback.h"
+#include "conf.h"
+#include "util.h"
+
+/* Free the current transaction and print an error if unsuccessful */
+static int upgrade_cleanup(void)
+{
+ int ret = alpm_trans_release();
+ if(ret != 0) {
+ pm_printf(PM_LOG_ERROR, _("failed to release transaction (%s)\n"),
+ alpm_strerrorlast());
+ ret = 1;
+ }
+
+ return(ret);
+}
+
+/**
+ * @brief Upgrade a specified list of packages.
+ *
+ * @param targets a list of packages (as strings) to upgrade
+ *
+ * @return 0 on success, 1 on failure
+ */
+int pacman_upgrade(alpm_list_t *targets)
+{
+ alpm_list_t *i, *data = NULL;
+ pmtranstype_t transtype = PM_TRANS_TYPE_UPGRADE;
+ int retval = 0;
+
+ if(targets == NULL) {
+ pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
+ return(1);
+ }
+
+ /* Check for URL targets and process them
+ */
+ for(i = targets; i; i = alpm_list_next(i)) {
+ if(strstr(i->data, "://")) {
+ char *str = alpm_fetch_pkgurl(i->data);
+ if(str == NULL) {
+ return(1);
+ } else {
+ free(i->data);
+ i->data = str;
+ }
+ }
+ }
+
+ /* Step 1: create a new transaction */
+ if(alpm_trans_init(transtype, config->flags, cb_trans_evt,
+ cb_trans_conv, cb_trans_progress) == -1) {
+ /* TODO: error messages should be in the front end, not the back */
+ fprintf(stderr, _("error: %s\n"), alpm_strerrorlast());
+ if(pm_errno == PM_ERR_HANDLE_LOCK) {
+ /* TODO this and the 2 other places should probably be on stderr */
+ printf(_(" if you're sure a package manager is not already\n"
+ " running, you can remove %s.\n"), alpm_option_get_lockfile());
+ }
+ return(1);
+ }
+
+ /* add targets to the created transaction */
+ printf(_("loading package data...\n"));
+ for(i = targets; i; i = alpm_list_next(i)) {
+ char *targ = alpm_list_getdata(i);
+ if(alpm_trans_addtarget(targ) == -1) {
+ fprintf(stderr, _("error: '%s': %s\n"),
+ targ, alpm_strerrorlast());
+ upgrade_cleanup();
+ return(1);
+ }
+ }
+
+ /* Step 2: "compute" the transaction based on targets and flags */
+ /* TODO: No, compute nothing. This is stupid. */
+ if(alpm_trans_prepare(&data) == -1) {
+ fprintf(stderr, _("error: failed to prepare transaction (%s)\n"),
+ alpm_strerrorlast());
+ switch(pm_errno) {
+ case PM_ERR_UNSATISFIED_DEPS:
+ for(i = data; i; i = alpm_list_next(i)) {
+ pmdepmissing_t *miss = alpm_list_getdata(i);
+ pmdepend_t *dep = alpm_miss_get_dep(miss);
+ char *depstring = alpm_dep_get_string(dep);
+
+ /* TODO indicate if the error was a virtual package or not:
+ * :: %s: requires %s, provided by %s
+ */
+ printf(_(":: %s: requires %s\n"), alpm_miss_get_target(miss),
+ depstring);
+ free(depstring);
+ }
+ break;
+ case PM_ERR_CONFLICTING_DEPS:
+ for(i = data; i; i = alpm_list_next(i)) {
+ pmconflict_t *conflict = alpm_list_getdata(i);
+ printf(_(":: %s: conflicts with %s\n"),
+ alpm_conflict_get_package1(conflict), alpm_conflict_get_package2(conflict));
+ }
+ break;
+ case PM_ERR_FILE_CONFLICTS:
+ for(i = data; i; i = alpm_list_next(i)) {
+ pmfileconflict_t *conflict = alpm_list_getdata(i);
+ switch(alpm_fileconflict_get_type(conflict)) {
+ case PM_FILECONFLICT_TARGET:
+ printf(_("%s exists in both '%s' and '%s'\n"),
+ alpm_fileconflict_get_file(conflict),
+ alpm_fileconflict_get_target(conflict),
+ alpm_fileconflict_get_ctarget(conflict));
+ break;
+ case PM_FILECONFLICT_FILESYSTEM:
+ printf(_("%s: %s exists in filesystem\n"),
+ alpm_fileconflict_get_target(conflict),
+ alpm_fileconflict_get_file(conflict));
+ break;
+ }
+ }
+ printf(_("\nerrors occurred, no packages were upgraded.\n"));
+ break;
+ default:
+ break;
+ }
+ upgrade_cleanup();
+ FREELIST(data);
+ return(1);
+ }
+ alpm_list_free(data);
+
+ /* Step 3: perform the installation */
+ if(alpm_trans_commit(NULL) == -1) {
+ fprintf(stderr, _("error: failed to commit transaction (%s)\n"), alpm_strerrorlast());
+ upgrade_cleanup();
+ return(1);
+ }
+
+ retval = upgrade_cleanup();
+ return(retval);
+}
+
+/* vim: set ts=2 sw=2 noet: */