2005-03-15 01:51:43 +00:00
|
|
|
/*
|
|
|
|
* sync.c
|
2007-11-16 20:18:45 -06:00
|
|
|
*
|
2022-01-02 13:34:52 +10:00
|
|
|
* Copyright (c) 2006-2022 Pacman Development Team <pacman-dev@lists.archlinux.org>
|
2009-07-01 02:08:33 -05:00
|
|
|
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
|
2006-10-15 19:31:03 +00:00
|
|
|
* Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
|
|
|
|
* Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
|
|
|
|
* Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
|
2007-11-16 20:18:45 -06:00
|
|
|
*
|
2005-03-15 01:51:43 +00:00
|
|
|
* 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
|
2007-12-10 22:55:22 -06:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2005-03-15 01:51:43 +00:00
|
|
|
*/
|
|
|
|
|
2008-06-01 21:47:31 -05:00
|
|
|
#include <sys/types.h> /* off_t */
|
2020-05-18 14:30:04 -07:00
|
|
|
#include <stdbool.h>
|
2005-03-15 01:51:43 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2009-02-19 19:12:34 +01:00
|
|
|
#include <stdint.h> /* intmax_t */
|
2007-04-29 12:47:02 -04:00
|
|
|
#include <unistd.h>
|
2010-12-18 04:48:09 +10:00
|
|
|
#include <limits.h>
|
2007-03-05 22:13:33 +00:00
|
|
|
|
|
|
|
/* libalpm */
|
|
|
|
#include "sync.h"
|
|
|
|
#include "alpm_list.h"
|
2005-03-15 01:51:43 +00:00
|
|
|
#include "log.h"
|
|
|
|
#include "package.h"
|
|
|
|
#include "db.h"
|
|
|
|
#include "deps.h"
|
2006-01-15 15:55:16 +00:00
|
|
|
#include "conflict.h"
|
2005-03-15 01:51:43 +00:00
|
|
|
#include "trans.h"
|
Use sync.c for upgrade transaction prepare and commit
This patch utilizes the power of sync.c to fix FS#3492 and FS#5798.
Now an upgrade transaction is just a sync transaction internally (in alpm),
so all sync features are available with -U as well:
* conflict resolving
* sync dependencies from sync repos
* remove unresolvable targets
See http://www.archlinux.org/pipermail/pacman-dev/2009-June/008725.html
for the concept.
We use "mixed" target list, where PKG_FROM_FILE origin indicates local
package file, PKG_FROM_CACHE indicates sync package. The front-end can add
only one type of packages (depending on transaction type) atm, but if alpm
resolves dependencies for -U, we may get a real mixed trans->packages list.
_alpm_pkg_free_trans() was modified so that it can handle both target types
_alpm_add_prepare() was removed, we use _alpm_sync_prepare() instead
_alpm_add_commit() was renamed to _alpm_upgrade_targets()
sync.c (and deps.c) was modified slightly to handle mixed target lists,
the modifications are straightforward. There is one notable change here: We
don't create new upgrade trans in sync.c, we replace the pkgcache entries
with the loaded package files in the target list (this is a bit hackish) and
call _alpm_upgrade_targets(). This implies a TODO (pkg->origin_data.db is
not accessible anymore), but it doesn't hurt anything with pacman front-end,
so it will be fixed later (otherwise this patch would be huge).
I updated the documentation of -U and I added a new pactest, upgrade090.py,
to test the syncdeps feature of -U.
Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-06-09 17:23:46 +02:00
|
|
|
#include "add.h"
|
2006-10-15 19:31:03 +00:00
|
|
|
#include "util.h"
|
2005-03-15 01:51:43 +00:00
|
|
|
#include "handle.h"
|
2005-12-26 06:40:29 +00:00
|
|
|
#include "alpm.h"
|
2008-01-22 21:36:11 -06:00
|
|
|
#include "dload.h"
|
2009-07-15 19:14:01 +02:00
|
|
|
#include "remove.h"
|
2010-11-16 15:57:39 +10:00
|
|
|
#include "diskspace.h"
|
2008-12-07 11:58:24 -06:00
|
|
|
#include "signing.h"
|
2005-03-15 01:51:43 +00:00
|
|
|
|
2019-10-02 16:40:54 +02:00
|
|
|
struct keyinfo_t {
|
|
|
|
char* uid;
|
|
|
|
char* keyid;
|
|
|
|
};
|
|
|
|
|
2019-01-10 13:44:32 +10:00
|
|
|
alpm_pkg_t SYMEXPORT *alpm_sync_get_new_version(alpm_pkg_t *pkg, alpm_list_t *dbs_sync)
|
2008-01-28 01:44:23 +01:00
|
|
|
{
|
|
|
|
alpm_list_t *i;
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *spkg = NULL;
|
2008-01-28 01:44:23 +01:00
|
|
|
|
2011-06-14 10:01:08 -05:00
|
|
|
ASSERT(pkg != NULL, return NULL);
|
2016-10-12 15:13:31 -05:00
|
|
|
pkg->handle->pm_errno = ALPM_ERR_OK;
|
2011-06-14 10:01:08 -05:00
|
|
|
|
2008-01-28 01:44:23 +01:00
|
|
|
for(i = dbs_sync; !spkg && i; i = i->next) {
|
2013-03-09 18:28:28 -05:00
|
|
|
alpm_db_t *db = i->data;
|
|
|
|
spkg = _alpm_db_get_pkgfromcache(db, pkg->name);
|
2008-01-28 01:44:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if(spkg == NULL) {
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(pkg->handle, ALPM_LOG_DEBUG, "'%s' not found in sync db => no upgrade\n",
|
2011-08-17 23:25:19 -05:00
|
|
|
pkg->name);
|
2011-03-20 19:45:57 -05:00
|
|
|
return NULL;
|
2008-01-28 01:44:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* compare versions and see if spkg is an upgrade */
|
2009-04-13 15:08:38 +02:00
|
|
|
if(_alpm_pkg_compare_versions(spkg, pkg) > 0) {
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(pkg->handle, ALPM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n",
|
2011-08-17 23:25:19 -05:00
|
|
|
pkg->name, pkg->version, spkg->version);
|
2011-03-20 19:45:57 -05:00
|
|
|
return spkg;
|
2008-01-28 01:44:23 +01:00
|
|
|
}
|
2009-04-13 15:08:38 +02:00
|
|
|
/* spkg is not an upgrade */
|
2011-03-20 19:45:57 -05:00
|
|
|
return NULL;
|
2008-01-28 01:44:23 +01:00
|
|
|
}
|
|
|
|
|
2011-08-17 23:39:41 -05:00
|
|
|
static int check_literal(alpm_handle_t *handle, alpm_pkg_t *lpkg,
|
|
|
|
alpm_pkg_t *spkg, int enable_downgrade)
|
|
|
|
{
|
|
|
|
/* 1. literal was found in sdb */
|
|
|
|
int cmp = _alpm_pkg_compare_versions(spkg, lpkg);
|
|
|
|
if(cmp > 0) {
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n",
|
|
|
|
lpkg->name, lpkg->version, spkg->version);
|
|
|
|
/* check IgnorePkg/IgnoreGroup */
|
2013-10-16 12:23:11 +10:00
|
|
|
if(alpm_pkg_should_ignore(handle, spkg)
|
|
|
|
|| alpm_pkg_should_ignore(handle, lpkg)) {
|
2011-08-17 23:39:41 -05:00
|
|
|
_alpm_log(handle, ALPM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"),
|
|
|
|
lpkg->name, lpkg->version, spkg->version);
|
|
|
|
} else {
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
|
|
|
|
spkg->name, spkg->version);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else if(cmp < 0) {
|
|
|
|
if(enable_downgrade) {
|
|
|
|
/* check IgnorePkg/IgnoreGroup */
|
2013-10-16 12:23:11 +10:00
|
|
|
if(alpm_pkg_should_ignore(handle, spkg)
|
|
|
|
|| alpm_pkg_should_ignore(handle, lpkg)) {
|
2011-08-17 23:39:41 -05:00
|
|
|
_alpm_log(handle, ALPM_LOG_WARNING, _("%s: ignoring package downgrade (%s => %s)\n"),
|
|
|
|
lpkg->name, lpkg->version, spkg->version);
|
|
|
|
} else {
|
|
|
|
_alpm_log(handle, ALPM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"),
|
|
|
|
lpkg->name, lpkg->version, spkg->version);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
alpm_db_t *sdb = alpm_pkg_get_db(spkg);
|
|
|
|
_alpm_log(handle, ALPM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"),
|
|
|
|
lpkg->name, lpkg->version, sdb->treename, spkg->version);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-08-17 23:52:28 -05:00
|
|
|
static alpm_list_t *check_replacers(alpm_handle_t *handle, alpm_pkg_t *lpkg,
|
|
|
|
alpm_db_t *sdb)
|
|
|
|
{
|
|
|
|
/* 2. search for replacers in sdb */
|
|
|
|
alpm_list_t *replacers = NULL;
|
|
|
|
alpm_list_t *k;
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG,
|
2012-08-05 20:05:42 +10:00
|
|
|
"searching for replacements for %s in %s\n",
|
|
|
|
lpkg->name, sdb->treename);
|
2011-08-17 23:52:28 -05:00
|
|
|
for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) {
|
|
|
|
int found = 0;
|
|
|
|
alpm_pkg_t *spkg = k->data;
|
|
|
|
alpm_list_t *l;
|
|
|
|
for(l = alpm_pkg_get_replaces(spkg); l; l = l->next) {
|
|
|
|
alpm_depend_t *replace = l->data;
|
2011-08-18 00:23:06 -05:00
|
|
|
/* we only want to consider literal matches at this point. */
|
|
|
|
if(_alpm_depcmp_literal(lpkg, replace)) {
|
2011-08-17 23:52:28 -05:00
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(found) {
|
2014-06-15 19:42:40 +02:00
|
|
|
alpm_question_replace_t question = {
|
|
|
|
.type = ALPM_QUESTION_REPLACE_PKG,
|
|
|
|
.replace = 0,
|
|
|
|
.oldpkg = lpkg,
|
|
|
|
.newpkg = spkg,
|
|
|
|
.newdb = sdb
|
|
|
|
};
|
2011-08-17 23:52:28 -05:00
|
|
|
alpm_pkg_t *tpkg;
|
|
|
|
/* check IgnorePkg/IgnoreGroup */
|
2013-10-16 12:23:11 +10:00
|
|
|
if(alpm_pkg_should_ignore(handle, spkg)
|
|
|
|
|| alpm_pkg_should_ignore(handle, lpkg)) {
|
2011-08-17 23:52:28 -05:00
|
|
|
_alpm_log(handle, ALPM_LOG_WARNING,
|
|
|
|
_("ignoring package replacement (%s-%s => %s-%s)\n"),
|
|
|
|
lpkg->name, lpkg->version, spkg->name, spkg->version);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-06-15 19:42:40 +02:00
|
|
|
QUESTION(handle, &question);
|
|
|
|
if(!question.replace) {
|
2011-08-17 23:52:28 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If spkg is already in the target list, we append lpkg to spkg's
|
|
|
|
* removes list */
|
2012-08-12 20:48:53 +10:00
|
|
|
tpkg = alpm_pkg_find(handle->trans->add, spkg->name);
|
2011-08-17 23:52:28 -05:00
|
|
|
if(tpkg) {
|
|
|
|
/* sanity check, multiple repos can contain spkg->name */
|
|
|
|
if(tpkg->origin_data.db != sdb) {
|
|
|
|
_alpm_log(handle, ALPM_LOG_WARNING, _("cannot replace %s by %s\n"),
|
|
|
|
lpkg->name, spkg->name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "appending %s to the removes list of %s\n",
|
|
|
|
lpkg->name, tpkg->name);
|
|
|
|
tpkg->removes = alpm_list_add(tpkg->removes, lpkg);
|
|
|
|
/* check the to-be-replaced package's reason field */
|
|
|
|
if(alpm_pkg_get_reason(lpkg) == ALPM_PKG_REASON_EXPLICIT) {
|
|
|
|
tpkg->reason = ALPM_PKG_REASON_EXPLICIT;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* add spkg to the target list */
|
|
|
|
/* copy over reason */
|
|
|
|
spkg->reason = alpm_pkg_get_reason(lpkg);
|
|
|
|
spkg->removes = alpm_list_add(NULL, lpkg);
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG,
|
|
|
|
"adding package %s-%s to the transaction targets\n",
|
|
|
|
spkg->name, spkg->version);
|
|
|
|
replacers = alpm_list_add(replacers, spkg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return replacers;
|
|
|
|
}
|
|
|
|
|
2011-06-28 14:04:00 +10:00
|
|
|
int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade)
|
2006-12-29 17:04:58 +00:00
|
|
|
{
|
2011-08-08 23:54:46 -05:00
|
|
|
alpm_list_t *i, *j;
|
2011-06-28 23:27:16 +10:00
|
|
|
alpm_trans_t *trans;
|
2005-03-15 01:51:43 +00:00
|
|
|
|
2011-06-14 10:01:08 -05:00
|
|
|
CHECK_HANDLE(handle, return -1);
|
2009-07-16 14:55:45 +02:00
|
|
|
trans = handle->trans;
|
2011-07-02 02:01:39 +10:00
|
|
|
ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1));
|
|
|
|
ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1));
|
2009-07-16 14:55:45 +02:00
|
|
|
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "checking for package upgrades\n");
|
2011-08-08 23:54:46 -05:00
|
|
|
for(i = _alpm_db_get_pkgcache(handle->db_local); i; i = i->next) {
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *lpkg = i->data;
|
2007-08-25 00:10:40 +02:00
|
|
|
|
2013-11-25 11:16:47 -05:00
|
|
|
if(alpm_pkg_find(trans->remove, lpkg->name)) {
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "%s is marked for removal -- skipping\n", lpkg->name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-08-12 20:48:53 +10:00
|
|
|
if(alpm_pkg_find(trans->add, lpkg->name)) {
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name);
|
2007-08-25 00:10:40 +02:00
|
|
|
continue;
|
|
|
|
}
|
2006-12-29 17:04:58 +00:00
|
|
|
|
2013-03-04 09:48:10 +01:00
|
|
|
/* Search for replacers then literal (if no replacer) in each sync database. */
|
2011-08-08 23:54:46 -05:00
|
|
|
for(j = handle->dbs_sync; j; j = j->next) {
|
2011-06-28 14:11:43 +10:00
|
|
|
alpm_db_t *sdb = j->data;
|
2013-03-09 18:28:28 -05:00
|
|
|
alpm_list_t *replacers;
|
|
|
|
|
|
|
|
if(!(sdb->usage & ALPM_DB_USAGE_UPGRADE)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-04-13 15:08:38 +02:00
|
|
|
/* Check sdb */
|
2013-03-09 18:28:28 -05:00
|
|
|
replacers = check_replacers(handle, lpkg, sdb);
|
2013-03-04 09:48:10 +01:00
|
|
|
if(replacers) {
|
|
|
|
trans->add = alpm_list_join(trans->add, replacers);
|
2011-04-20 19:00:59 -05:00
|
|
|
/* jump to next local package */
|
|
|
|
break;
|
|
|
|
} else {
|
2013-03-04 09:48:10 +01:00
|
|
|
alpm_pkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name);
|
|
|
|
if(spkg) {
|
2013-03-07 08:56:13 -05:00
|
|
|
if(check_literal(handle, lpkg, spkg, enable_downgrade)) {
|
2013-03-04 09:48:10 +01:00
|
|
|
trans->add = alpm_list_add(trans->add, spkg);
|
|
|
|
}
|
|
|
|
/* jump to next local package */
|
|
|
|
break;
|
2009-04-13 15:08:38 +02:00
|
|
|
}
|
2008-01-28 01:44:23 +01:00
|
|
|
}
|
2005-03-15 01:51:43 +00:00
|
|
|
}
|
2006-12-29 17:04:58 +00:00
|
|
|
}
|
2007-08-25 00:10:40 +02:00
|
|
|
|
2011-03-20 19:45:57 -05:00
|
|
|
return 0;
|
2005-03-15 01:51:43 +00:00
|
|
|
}
|
|
|
|
|
2011-06-29 15:46:49 +10:00
|
|
|
alpm_list_t SYMEXPORT *alpm_find_group_pkgs(alpm_list_t *dbs,
|
2010-10-17 00:59:53 +02:00
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
alpm_list_t *i, *j, *pkgs = NULL, *ignorelist = NULL;
|
|
|
|
|
|
|
|
for(i = dbs; i; i = i->next) {
|
2011-06-28 14:11:43 +10:00
|
|
|
alpm_db_t *db = i->data;
|
2012-02-01 23:45:52 -06:00
|
|
|
alpm_group_t *grp = alpm_db_get_group(db, name);
|
2010-10-17 00:59:53 +02:00
|
|
|
|
2017-07-15 14:56:30 +02:00
|
|
|
if(!grp) {
|
2010-10-17 00:59:53 +02:00
|
|
|
continue;
|
2017-07-15 14:56:30 +02:00
|
|
|
}
|
2010-10-17 00:59:53 +02:00
|
|
|
|
2011-06-16 11:55:26 -05:00
|
|
|
for(j = grp->packages; j; j = j->next) {
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *pkg = j->data;
|
2018-10-17 16:40:47 +01:00
|
|
|
alpm_trans_t *trans = db->handle->trans;
|
2010-10-17 00:59:53 +02:00
|
|
|
|
2012-08-12 20:48:53 +10:00
|
|
|
if(alpm_pkg_find(ignorelist, pkg->name)) {
|
2010-10-17 00:59:53 +02:00
|
|
|
continue;
|
|
|
|
}
|
2018-10-17 16:40:47 +01:00
|
|
|
if(trans != NULL && trans->flags & ALPM_TRANS_FLAG_NEEDED) {
|
|
|
|
alpm_pkg_t *local = _alpm_db_get_pkgfromcache(db->handle->db_local, pkg->name);
|
|
|
|
if(local && _alpm_pkg_compare_versions(pkg, local) == 0) {
|
|
|
|
/* with the NEEDED flag, packages up to date are not reinstalled */
|
|
|
|
_alpm_log(db->handle, ALPM_LOG_WARNING, _("%s-%s is up to date -- skipping\n"),
|
|
|
|
local->name, local->version);
|
|
|
|
ignorelist = alpm_list_add(ignorelist, pkg);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2013-10-16 12:23:11 +10:00
|
|
|
if(alpm_pkg_should_ignore(db->handle, pkg)) {
|
2014-06-15 19:42:40 +02:00
|
|
|
alpm_question_install_ignorepkg_t question = {
|
|
|
|
.type = ALPM_QUESTION_INSTALL_IGNOREPKG,
|
|
|
|
.install = 0,
|
|
|
|
.pkg = pkg
|
|
|
|
};
|
2010-10-17 00:59:53 +02:00
|
|
|
ignorelist = alpm_list_add(ignorelist, pkg);
|
2014-06-15 19:42:40 +02:00
|
|
|
QUESTION(db->handle, &question);
|
2017-07-15 14:56:30 +02:00
|
|
|
if(!question.install) {
|
2010-10-17 00:59:53 +02:00
|
|
|
continue;
|
2017-07-15 14:56:30 +02:00
|
|
|
}
|
2010-10-17 00:59:53 +02:00
|
|
|
}
|
2012-08-12 20:48:53 +10:00
|
|
|
if(!alpm_pkg_find(pkgs, pkg->name)) {
|
2010-10-17 00:59:53 +02:00
|
|
|
pkgs = alpm_list_add(pkgs, pkg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
alpm_list_free(ignorelist);
|
2011-03-20 19:45:57 -05:00
|
|
|
return pkgs;
|
2010-10-17 00:59:53 +02:00
|
|
|
}
|
|
|
|
|
2008-02-16 10:47:22 -06:00
|
|
|
/** Compute the size of the files that will be downloaded to install a
|
|
|
|
* package.
|
|
|
|
* @param newpkg the new package to upgrade to
|
|
|
|
*/
|
2011-06-28 23:26:39 +10:00
|
|
|
static int compute_download_size(alpm_pkg_t *newpkg)
|
2008-02-16 10:47:22 -06:00
|
|
|
{
|
2011-09-07 16:01:43 -04:00
|
|
|
const char *fname;
|
|
|
|
char *fpath, *fnamepart = NULL;
|
2008-06-01 21:47:31 -05:00
|
|
|
off_t size = 0;
|
2011-06-28 14:04:00 +10:00
|
|
|
alpm_handle_t *handle = newpkg->handle;
|
2011-10-18 10:46:47 -04:00
|
|
|
int ret = 0;
|
2008-02-16 10:47:22 -06:00
|
|
|
|
2012-04-01 15:37:19 +10:00
|
|
|
if(newpkg->origin != ALPM_PKG_FROM_SYNCDB) {
|
2010-05-06 10:07:37 +12:00
|
|
|
newpkg->infolevel |= INFRQ_DSIZE;
|
Use sync.c for upgrade transaction prepare and commit
This patch utilizes the power of sync.c to fix FS#3492 and FS#5798.
Now an upgrade transaction is just a sync transaction internally (in alpm),
so all sync features are available with -U as well:
* conflict resolving
* sync dependencies from sync repos
* remove unresolvable targets
See http://www.archlinux.org/pipermail/pacman-dev/2009-June/008725.html
for the concept.
We use "mixed" target list, where PKG_FROM_FILE origin indicates local
package file, PKG_FROM_CACHE indicates sync package. The front-end can add
only one type of packages (depending on transaction type) atm, but if alpm
resolves dependencies for -U, we may get a real mixed trans->packages list.
_alpm_pkg_free_trans() was modified so that it can handle both target types
_alpm_add_prepare() was removed, we use _alpm_sync_prepare() instead
_alpm_add_commit() was renamed to _alpm_upgrade_targets()
sync.c (and deps.c) was modified slightly to handle mixed target lists,
the modifications are straightforward. There is one notable change here: We
don't create new upgrade trans in sync.c, we replace the pkgcache entries
with the loaded package files in the target list (this is a bit hackish) and
call _alpm_upgrade_targets(). This implies a TODO (pkg->origin_data.db is
not accessible anymore), but it doesn't hurt anything with pacman front-end,
so it will be fixed later (otherwise this patch would be huge).
I updated the documentation of -U and I added a new pactest, upgrade090.py,
to test the syncdeps feature of -U.
Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-06-09 17:23:46 +02:00
|
|
|
newpkg->download_size = 0;
|
2011-03-20 19:45:57 -05:00
|
|
|
return 0;
|
Use sync.c for upgrade transaction prepare and commit
This patch utilizes the power of sync.c to fix FS#3492 and FS#5798.
Now an upgrade transaction is just a sync transaction internally (in alpm),
so all sync features are available with -U as well:
* conflict resolving
* sync dependencies from sync repos
* remove unresolvable targets
See http://www.archlinux.org/pipermail/pacman-dev/2009-June/008725.html
for the concept.
We use "mixed" target list, where PKG_FROM_FILE origin indicates local
package file, PKG_FROM_CACHE indicates sync package. The front-end can add
only one type of packages (depending on transaction type) atm, but if alpm
resolves dependencies for -U, we may get a real mixed trans->packages list.
_alpm_pkg_free_trans() was modified so that it can handle both target types
_alpm_add_prepare() was removed, we use _alpm_sync_prepare() instead
_alpm_add_commit() was renamed to _alpm_upgrade_targets()
sync.c (and deps.c) was modified slightly to handle mixed target lists,
the modifications are straightforward. There is one notable change here: We
don't create new upgrade trans in sync.c, we replace the pkgcache entries
with the loaded package files in the target list (this is a bit hackish) and
call _alpm_upgrade_targets(). This implies a TODO (pkg->origin_data.db is
not accessible anymore), but it doesn't hurt anything with pacman front-end,
so it will be fixed later (otherwise this patch would be huge).
I updated the documentation of -U and I added a new pactest, upgrade090.py,
to test the syncdeps feature of -U.
Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-06-09 17:23:46 +02:00
|
|
|
}
|
|
|
|
|
2011-09-02 22:07:06 -05:00
|
|
|
ASSERT(newpkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1));
|
2011-09-07 16:01:43 -04:00
|
|
|
fname = newpkg->filename;
|
|
|
|
fpath = _alpm_filecache_find(handle, fname);
|
2008-04-26 13:03:53 -05:00
|
|
|
|
2011-09-07 16:01:43 -04:00
|
|
|
/* downloaded file exists, so there's nothing to grab */
|
2008-02-16 10:47:22 -06:00
|
|
|
if(fpath) {
|
|
|
|
size = 0;
|
2011-09-07 16:01:43 -04:00
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
|
|
|
|
CALLOC(fnamepart, strlen(fname) + 6, sizeof(char), return -1);
|
|
|
|
sprintf(fnamepart, "%s.part", fname);
|
|
|
|
fpath = _alpm_filecache_find(handle, fnamepart);
|
|
|
|
if(fpath) {
|
|
|
|
struct stat st;
|
|
|
|
if(stat(fpath, &st) == 0) {
|
|
|
|
/* subtract the size of the .part file */
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "using (package - .part) size\n");
|
|
|
|
size = newpkg->size - st.st_size;
|
|
|
|
size = size < 0 ? 0 : size;
|
|
|
|
}
|
2011-10-18 10:46:47 -04:00
|
|
|
|
|
|
|
/* tell the caller that we have a partial */
|
|
|
|
ret = 1;
|
2008-02-16 10:47:22 -06:00
|
|
|
} else {
|
2011-09-02 19:26:07 -05:00
|
|
|
size = newpkg->size;
|
2008-02-16 10:47:22 -06:00
|
|
|
}
|
|
|
|
|
2011-09-07 16:01:43 -04:00
|
|
|
finish:
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "setting download size %jd for pkg %s\n",
|
2011-08-17 23:25:19 -05:00
|
|
|
(intmax_t)size, newpkg->name);
|
2008-02-16 10:47:22 -06:00
|
|
|
|
2010-05-06 10:07:37 +12:00
|
|
|
newpkg->infolevel |= INFRQ_DSIZE;
|
2008-02-16 10:47:22 -06:00
|
|
|
newpkg->download_size = size;
|
2011-09-07 16:01:43 -04:00
|
|
|
|
|
|
|
FREE(fpath);
|
|
|
|
FREE(fnamepart);
|
|
|
|
|
2011-10-18 10:46:47 -04:00
|
|
|
return ret;
|
2008-02-16 10:47:22 -06:00
|
|
|
}
|
|
|
|
|
Add an alternative dependency resolution algorithm
The existing dependency resolution, as implemented in resolvedep(),
prioritises name matches for a dependency over packages that only
provide that dependency. We would like the option to prioritise
database ordering above a precise name match.
To do this, we add a DependencyStrategy configuration parameter. The
default is to behave as pacman currently does, with
DependencyStrategy=Default. However, we also add a Strict strategy
(to strictly honour the priorities of repositories) which matches our
desired behaviour in some circumstances.
For the sake of clarity, the default strategy will:
- take the package with the exact name given from the highest priority
repository, ignoring all other packages.
- if this doesn't exist, take an installed package providing this
name, ignoring all other packages.
- otherwise, it will give a list of packages that provide this name,
in repository priority order, accumulated from every repository.
In contrast, the strict strategy will:
- take an installed package providing the dependency name, ignoring
all other packages.
- otherwise, give a list of all packages that either have this name,
or provide this name, accumulated from every repository. The
ordering is by repository priority order, with packages having the
exact name being first among the packages from their repository.
When does this difference matter? Let's suppose we have two repositories,
- customizations
- base
Let's say we have a list of instructions that involve installing the
name foo, which is provided by customizations/foo-customized. One day,
base/foo comes into existence. Under the default strategy, our
instructions now no longer install customizations/foo-customized,
meaning our instructions no longer install our customized version of
foo. Under the strict strategy, our instructions will now either
prompt for the correct package to install, or because the default will
be correct, will simply install the correct package with --noconfirm.
Signed-off-by: Ed Smith <ed.smith@collabora.com>
2024-01-16 16:36:56 +00:00
|
|
|
int _alpm_sync_prepare(alpm_handle_t *handle, alpm_depstrategy_t depstrategy, alpm_list_t **data)
|
2005-03-15 01:51:43 +00:00
|
|
|
{
|
2011-06-07 16:06:16 -05:00
|
|
|
alpm_list_t *i, *j;
|
2007-01-19 09:28:44 +00:00
|
|
|
alpm_list_t *deps = NULL;
|
2009-01-27 01:48:39 +13:00
|
|
|
alpm_list_t *unresolvable = NULL;
|
2014-01-13 23:01:44 -05:00
|
|
|
int from_sync = 0;
|
2006-03-04 10:16:36 +00:00
|
|
|
int ret = 0;
|
2011-06-28 23:27:16 +10:00
|
|
|
alpm_trans_t *trans = handle->trans;
|
2014-01-10 16:25:14 +01:00
|
|
|
alpm_event_t event;
|
2005-04-08 19:37:23 +00:00
|
|
|
|
2006-01-07 18:25:28 +00:00
|
|
|
if(data) {
|
|
|
|
*data = NULL;
|
|
|
|
}
|
2005-04-06 21:01:40 +00:00
|
|
|
|
2011-11-15 09:12:18 -06:00
|
|
|
for(i = trans->add; i; i = i->next) {
|
|
|
|
alpm_pkg_t *spkg = i->data;
|
2014-01-13 23:01:44 -05:00
|
|
|
if (spkg->origin == ALPM_PKG_FROM_SYNCDB){
|
|
|
|
from_sync = 1;
|
|
|
|
break;
|
|
|
|
}
|
2011-11-15 09:12:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ensure all sync database are valid if we will be using them */
|
2011-06-07 23:08:06 -05:00
|
|
|
for(i = handle->dbs_sync; i; i = i->next) {
|
|
|
|
const alpm_db_t *db = i->data;
|
2011-08-17 21:06:04 -05:00
|
|
|
if(db->status & DB_STATUS_INVALID) {
|
2011-06-07 23:08:06 -05:00
|
|
|
RET_ERR(handle, ALPM_ERR_DB_INVALID, -1);
|
|
|
|
}
|
2011-11-15 09:12:18 -06:00
|
|
|
/* missing databases are not allowed if we have sync targets */
|
|
|
|
if(from_sync && db->status & DB_STATUS_MISSING) {
|
2011-08-17 21:06:04 -05:00
|
|
|
RET_ERR(handle, ALPM_ERR_DB_NOT_FOUND, -1);
|
|
|
|
}
|
2011-06-07 23:08:06 -05:00
|
|
|
}
|
|
|
|
|
2011-07-02 02:01:39 +10:00
|
|
|
if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) {
|
2011-11-15 09:12:18 -06:00
|
|
|
alpm_list_t *resolved = NULL;
|
2014-03-24 09:59:45 -04:00
|
|
|
alpm_list_t *remove = alpm_list_copy(trans->remove);
|
2011-11-15 09:12:18 -06:00
|
|
|
alpm_list_t *localpkgs;
|
2009-03-07 19:44:34 +01:00
|
|
|
|
2009-01-27 01:48:39 +13:00
|
|
|
/* Build up list by repeatedly resolving each transaction package */
|
2005-04-13 19:59:04 +00:00
|
|
|
/* Resolve targets dependencies */
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_RESOLVEDEPS_START;
|
|
|
|
EVENT(handle, &event);
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "resolving target's dependencies\n");
|
2007-08-12 22:26:54 +02:00
|
|
|
|
2009-09-12 20:50:03 +02:00
|
|
|
/* build remove list for resolvedeps */
|
2009-07-15 19:14:01 +02:00
|
|
|
for(i = trans->add; i; i = i->next) {
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *spkg = i->data;
|
2009-03-07 19:44:34 +01:00
|
|
|
for(j = spkg->removes; j; j = j->next) {
|
2008-01-27 12:24:50 +01:00
|
|
|
remove = alpm_list_add(remove, j->data);
|
2007-08-12 22:26:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-21 09:02:03 -05:00
|
|
|
/* Compute the fake local database for resolvedeps (partial fix for the
|
|
|
|
* phonon/qt issue) */
|
2011-11-15 09:12:18 -06:00
|
|
|
localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local),
|
2011-03-21 09:02:03 -05:00
|
|
|
trans->add, _alpm_pkg_cmp);
|
2010-05-17 02:33:28 +02:00
|
|
|
|
2011-02-25 07:51:58 -06:00
|
|
|
/* Resolve packages in the transaction one at a time, in addition
|
2009-01-27 01:48:39 +13:00
|
|
|
building up a list of packages which could not be resolved. */
|
2009-07-15 19:14:01 +02:00
|
|
|
for(i = trans->add; i; i = i->next) {
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *pkg = i->data;
|
Add an alternative dependency resolution algorithm
The existing dependency resolution, as implemented in resolvedep(),
prioritises name matches for a dependency over packages that only
provide that dependency. We would like the option to prioritise
database ordering above a precise name match.
To do this, we add a DependencyStrategy configuration parameter. The
default is to behave as pacman currently does, with
DependencyStrategy=Default. However, we also add a Strict strategy
(to strictly honour the priorities of repositories) which matches our
desired behaviour in some circumstances.
For the sake of clarity, the default strategy will:
- take the package with the exact name given from the highest priority
repository, ignoring all other packages.
- if this doesn't exist, take an installed package providing this
name, ignoring all other packages.
- otherwise, it will give a list of packages that provide this name,
in repository priority order, accumulated from every repository.
In contrast, the strict strategy will:
- take an installed package providing the dependency name, ignoring
all other packages.
- otherwise, give a list of all packages that either have this name,
or provide this name, accumulated from every repository. The
ordering is by repository priority order, with packages having the
exact name being first among the packages from their repository.
When does this difference matter? Let's suppose we have two repositories,
- customizations
- base
Let's say we have a list of instructions that involve installing the
name foo, which is provided by customizations/foo-customized. One day,
base/foo comes into existence. Under the default strategy, our
instructions now no longer install customizations/foo-customized,
meaning our instructions no longer install our customized version of
foo. Under the strict strategy, our instructions will now either
prompt for the correct package to install, or because the default will
be correct, will simply install the correct package with --noconfirm.
Signed-off-by: Ed Smith <ed.smith@collabora.com>
2024-01-16 16:36:56 +00:00
|
|
|
if(_alpm_resolvedeps(handle, localpkgs, pkg, depstrategy, trans->add,
|
2009-03-09 09:56:13 +13:00
|
|
|
&resolved, remove, data) == -1) {
|
2009-01-27 01:48:39 +13:00
|
|
|
unresolvable = alpm_list_add(unresolvable, pkg);
|
|
|
|
}
|
2009-03-07 19:44:34 +01:00
|
|
|
/* Else, [resolved] now additionally contains [pkg] and all of its
|
2009-01-27 01:48:39 +13:00
|
|
|
dependencies not already on the list */
|
|
|
|
}
|
2010-05-17 02:33:28 +02:00
|
|
|
alpm_list_free(localpkgs);
|
2011-11-15 09:12:18 -06:00
|
|
|
alpm_list_free(remove);
|
2009-01-27 01:48:39 +13:00
|
|
|
|
2009-02-22 23:25:31 +13:00
|
|
|
/* If there were unresolvable top-level packages, prompt the user to
|
|
|
|
see if they'd like to ignore them rather than failing the sync */
|
2009-01-27 01:48:39 +13:00
|
|
|
if(unresolvable != NULL) {
|
2014-06-15 19:42:40 +02:00
|
|
|
alpm_question_remove_pkgs_t question = {
|
|
|
|
.type = ALPM_QUESTION_REMOVE_PKGS,
|
|
|
|
.skip = 0,
|
|
|
|
.packages = unresolvable
|
|
|
|
};
|
|
|
|
QUESTION(handle, &question);
|
|
|
|
if(question.skip) {
|
2009-02-22 23:25:31 +13:00
|
|
|
/* User wants to remove the unresolvable packages from the
|
2009-03-07 16:25:29 +01:00
|
|
|
transaction. The packages will be removed from the actual
|
|
|
|
transaction when the transaction packages are replaced with a
|
2009-02-22 23:25:31 +13:00
|
|
|
dependency-reordered list below */
|
2016-10-12 15:13:31 -05:00
|
|
|
handle->pm_errno = ALPM_ERR_OK;
|
2009-03-07 16:25:29 +01:00
|
|
|
if(data) {
|
2014-02-03 12:09:18 -05:00
|
|
|
alpm_list_free_inner(*data,
|
|
|
|
(alpm_list_fn_free)alpm_depmissing_free);
|
2009-03-07 16:25:29 +01:00
|
|
|
alpm_list_free(*data);
|
|
|
|
*data = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
2011-11-15 09:12:18 -06:00
|
|
|
/* pm_errno was set by resolvedeps, callback may have overwrote it */
|
2009-03-07 19:44:34 +01:00
|
|
|
alpm_list_free(resolved);
|
2014-02-06 20:49:07 -05:00
|
|
|
alpm_list_free(unresolvable);
|
2009-02-22 23:25:31 +13:00
|
|
|
ret = -1;
|
2020-04-13 22:24:23 +10:00
|
|
|
GOTO_ERR(handle, ALPM_ERR_UNSATISFIED_DEPS, cleanup);
|
2009-02-22 23:25:31 +13:00
|
|
|
}
|
2005-04-02 23:21:10 +00:00
|
|
|
}
|
2006-10-15 19:31:03 +00:00
|
|
|
|
2021-05-09 15:18:17 +01:00
|
|
|
/* Ensure two packages don't have the same filename */
|
|
|
|
for(i = resolved; i; i = i->next) {
|
|
|
|
alpm_pkg_t *pkg1 = i->data;
|
|
|
|
for(j = i->next; j; j = j->next) {
|
|
|
|
alpm_pkg_t *pkg2 = j->data;
|
|
|
|
if(strcmp(pkg1->filename, pkg2->filename) == 0) {
|
|
|
|
ret = -1;
|
|
|
|
handle->pm_errno = ALPM_ERR_TRANS_DUP_FILENAME;
|
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR, _("packages %s and %s have the same filename: %s\n"),
|
|
|
|
pkg1->name, pkg2->name, pkg1->filename);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ret != 0) {
|
2022-12-12 23:44:10 +10:00
|
|
|
alpm_list_free(resolved);
|
2021-05-09 15:18:17 +01:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2009-03-07 19:44:34 +01:00
|
|
|
/* Set DEPEND reason for pulled packages */
|
|
|
|
for(i = resolved; i; i = i->next) {
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *pkg = i->data;
|
2012-08-12 20:48:53 +10:00
|
|
|
if(!alpm_pkg_find(trans->add, pkg->name)) {
|
2011-07-02 02:01:38 +10:00
|
|
|
pkg->reason = ALPM_PKG_REASON_DEPEND;
|
2005-04-08 19:37:23 +00:00
|
|
|
}
|
|
|
|
}
|
2006-10-15 19:31:03 +00:00
|
|
|
|
2011-09-28 01:53:43 -05:00
|
|
|
/* Unresolvable packages will be removed from the target list; set these
|
|
|
|
* aside in the transaction as a list we won't operate on. If we free them
|
|
|
|
* before the end of the transaction, we may kill pointers the frontend
|
|
|
|
* holds to package objects. */
|
|
|
|
trans->unresolvable = unresolvable;
|
Use sync.c for upgrade transaction prepare and commit
This patch utilizes the power of sync.c to fix FS#3492 and FS#5798.
Now an upgrade transaction is just a sync transaction internally (in alpm),
so all sync features are available with -U as well:
* conflict resolving
* sync dependencies from sync repos
* remove unresolvable targets
See http://www.archlinux.org/pipermail/pacman-dev/2009-June/008725.html
for the concept.
We use "mixed" target list, where PKG_FROM_FILE origin indicates local
package file, PKG_FROM_CACHE indicates sync package. The front-end can add
only one type of packages (depending on transaction type) atm, but if alpm
resolves dependencies for -U, we may get a real mixed trans->packages list.
_alpm_pkg_free_trans() was modified so that it can handle both target types
_alpm_add_prepare() was removed, we use _alpm_sync_prepare() instead
_alpm_add_commit() was renamed to _alpm_upgrade_targets()
sync.c (and deps.c) was modified slightly to handle mixed target lists,
the modifications are straightforward. There is one notable change here: We
don't create new upgrade trans in sync.c, we replace the pkgcache entries
with the loaded package files in the target list (this is a bit hackish) and
call _alpm_upgrade_targets(). This implies a TODO (pkg->origin_data.db is
not accessible anymore), but it doesn't hurt anything with pacman front-end,
so it will be fixed later (otherwise this patch would be huge).
I updated the documentation of -U and I added a new pactest, upgrade090.py,
to test the syncdeps feature of -U.
Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-06-09 17:23:46 +02:00
|
|
|
|
2009-07-15 19:14:01 +02:00
|
|
|
alpm_list_free(trans->add);
|
2013-10-17 23:38:58 -04:00
|
|
|
trans->add = resolved;
|
2006-10-15 19:31:03 +00:00
|
|
|
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_RESOLVEDEPS_DONE;
|
|
|
|
EVENT(handle, &event);
|
2006-03-04 10:16:36 +00:00
|
|
|
}
|
|
|
|
|
2011-07-02 02:01:39 +10:00
|
|
|
if(!(trans->flags & ALPM_TRANS_FLAG_NOCONFLICTS)) {
|
2006-03-04 10:16:36 +00:00
|
|
|
/* check for inter-conflicts and whatnot */
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_INTERCONFLICTS_START;
|
|
|
|
EVENT(handle, &event);
|
2006-03-04 10:16:36 +00:00
|
|
|
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "looking for conflicts\n");
|
2005-04-17 20:09:06 +00:00
|
|
|
|
2007-08-13 00:17:32 +02:00
|
|
|
/* 1. check for conflicts in the target list */
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs targets\n");
|
2011-06-07 13:53:53 -05:00
|
|
|
deps = _alpm_innerconflicts(handle, trans->add);
|
2007-08-13 00:17:32 +02:00
|
|
|
|
|
|
|
for(i = deps; i; i = i->next) {
|
2011-06-28 14:33:55 +10:00
|
|
|
alpm_conflict_t *conflict = i->data;
|
2019-11-14 05:45:51 +00:00
|
|
|
const char *name1 = conflict->package1->name;
|
|
|
|
const char *name2 = conflict->package2->name;
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *rsync, *sync, *sync1, *sync2;
|
2007-08-13 00:17:32 +02:00
|
|
|
|
|
|
|
/* have we already removed one of the conflicting targets? */
|
2019-11-14 05:45:51 +00:00
|
|
|
sync1 = alpm_pkg_find(trans->add, name1);
|
|
|
|
sync2 = alpm_pkg_find(trans->add, name2);
|
2007-08-13 00:17:32 +02:00
|
|
|
if(!sync1 || !sync2) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n",
|
2019-11-14 05:45:51 +00:00
|
|
|
name1, name2);
|
2007-08-13 00:17:32 +02:00
|
|
|
|
|
|
|
/* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */
|
2019-11-14 05:45:51 +00:00
|
|
|
alpm_depend_t *dep1 = alpm_dep_from_string(name1);
|
|
|
|
alpm_depend_t *dep2 = alpm_dep_from_string(name2);
|
2010-10-12 21:47:40 +02:00
|
|
|
if(_alpm_depcmp(sync1, dep2)) {
|
2007-08-13 00:17:32 +02:00
|
|
|
rsync = sync2;
|
|
|
|
sync = sync1;
|
2010-10-12 21:47:40 +02:00
|
|
|
} else if(_alpm_depcmp(sync2, dep1)) {
|
2007-08-13 00:17:32 +02:00
|
|
|
rsync = sync1;
|
|
|
|
sync = sync2;
|
|
|
|
} else {
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
|
2011-07-02 02:01:39 +10:00
|
|
|
handle->pm_errno = ALPM_ERR_CONFLICTING_DEPS;
|
2007-08-13 00:17:32 +02:00
|
|
|
ret = -1;
|
2008-01-25 21:52:35 +01:00
|
|
|
if(data) {
|
2011-06-28 14:33:55 +10:00
|
|
|
alpm_conflict_t *newconflict = _alpm_conflict_dup(conflict);
|
2008-01-25 21:52:35 +01:00
|
|
|
if(newconflict) {
|
|
|
|
*data = alpm_list_add(*data, newconflict);
|
|
|
|
}
|
|
|
|
}
|
2014-02-03 12:09:18 -05:00
|
|
|
alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_conflict_free);
|
2008-01-25 21:52:35 +01:00
|
|
|
alpm_list_free(deps);
|
2014-09-15 18:06:47 +02:00
|
|
|
alpm_dep_free(dep1);
|
|
|
|
alpm_dep_free(dep2);
|
2007-08-13 00:17:32 +02:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2014-09-15 18:06:47 +02:00
|
|
|
alpm_dep_free(dep1);
|
|
|
|
alpm_dep_free(dep2);
|
2007-08-13 00:17:32 +02:00
|
|
|
|
2008-03-10 15:38:08 +01:00
|
|
|
/* Prints warning */
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_WARNING,
|
2019-11-14 05:45:51 +00:00
|
|
|
_("removing '%s-%s' from target list because it conflicts with '%s-%s'\n"),
|
|
|
|
rsync->name, rsync->version, sync->name, sync->version);
|
2009-07-15 19:14:01 +02:00
|
|
|
trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL);
|
2011-09-28 01:53:43 -05:00
|
|
|
/* rsync is not a transaction target anymore */
|
|
|
|
trans->unresolvable = alpm_list_add(trans->unresolvable, rsync);
|
2007-08-13 00:17:32 +02:00
|
|
|
}
|
|
|
|
|
2014-02-03 12:09:18 -05:00
|
|
|
alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_conflict_free);
|
2007-08-13 00:17:32 +02:00
|
|
|
alpm_list_free(deps);
|
|
|
|
deps = NULL;
|
|
|
|
|
|
|
|
/* 2. we check for target vs db conflicts (and resolve)*/
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "check targets vs db and db vs targets\n");
|
2011-06-07 16:06:16 -05:00
|
|
|
deps = _alpm_outerconflicts(handle->db_local, trans->add);
|
2007-08-13 00:17:32 +02:00
|
|
|
|
|
|
|
for(i = deps; i; i = i->next) {
|
2014-06-15 19:42:40 +02:00
|
|
|
alpm_question_conflict_t question = {
|
|
|
|
.type = ALPM_QUESTION_CONFLICT_PKG,
|
|
|
|
.remove = 0,
|
|
|
|
.conflict = i->data
|
|
|
|
};
|
2011-06-28 14:33:55 +10:00
|
|
|
alpm_conflict_t *conflict = i->data;
|
2019-11-14 05:45:51 +00:00
|
|
|
const char *name1 = conflict->package1->name;
|
|
|
|
const char *name2 = conflict->package2->name;
|
2013-02-13 18:54:28 -05:00
|
|
|
int found = 0;
|
2007-08-13 00:17:32 +02:00
|
|
|
|
2019-11-14 05:45:51 +00:00
|
|
|
/* if name2 (the local package) is not elected for removal,
|
2007-08-13 00:17:32 +02:00
|
|
|
we ask the user */
|
2019-11-14 05:45:51 +00:00
|
|
|
if(alpm_pkg_find(trans->remove, name2)) {
|
2014-03-03 18:29:08 -05:00
|
|
|
found = 1;
|
|
|
|
}
|
2009-07-15 19:14:01 +02:00
|
|
|
for(j = trans->add; j && !found; j = j->next) {
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *spkg = j->data;
|
2019-11-14 05:45:51 +00:00
|
|
|
if(alpm_pkg_find(spkg->removes, name2)) {
|
2008-01-27 12:24:50 +01:00
|
|
|
found = 1;
|
2006-01-17 21:18:33 +00:00
|
|
|
}
|
2007-08-13 00:17:32 +02:00
|
|
|
}
|
|
|
|
if(found) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-11-14 05:45:51 +00:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "package '%s-%s' conflicts with '%s-%s'\n",
|
|
|
|
name1, conflict->package1->version, name2,conflict->package2->version);
|
2007-08-13 00:17:32 +02:00
|
|
|
|
2014-06-15 19:42:40 +02:00
|
|
|
QUESTION(handle, &question);
|
|
|
|
if(question.remove) {
|
2008-01-27 12:24:50 +01:00
|
|
|
/* append to the removes list */
|
2019-11-14 05:45:51 +00:00
|
|
|
alpm_pkg_t *sync = alpm_pkg_find(trans->add, name1);
|
|
|
|
alpm_pkg_t *local = _alpm_db_get_pkgfromcache(handle->db_local, name2);
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "electing '%s' for removal\n", name2);
|
2008-01-27 12:24:50 +01:00
|
|
|
sync->removes = alpm_list_add(sync->removes, local);
|
2007-08-13 00:17:32 +02:00
|
|
|
} else { /* abort */
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
|
2011-07-02 02:01:39 +10:00
|
|
|
handle->pm_errno = ALPM_ERR_CONFLICTING_DEPS;
|
2008-01-25 21:52:35 +01:00
|
|
|
ret = -1;
|
Fix several memleaks, mostly related to errors handling.
* The frontend calls alpm_trans_prepare(&data), and in case of errors,
receive the missing dependencies / conflicts / etc in the data pointer.
It apparently needs to free this structure totally with :
alpm_list_free_inner(data, free)
alpm_list_free(data)
So I added alpm_list_free_inner(data, free) in
pacman/{sync.c,remove.c,add,c}
* in _alpm_sync_prepare, the deps and asked lists were not freed in case
of errors (unresolvable conflicts).
Besides the code for handling this case was duplicated.
* in _alpm_remove_commit, free was used instead of alpm_list_free for
newfiles.
* newline fix in pacman/sync.c
Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2007-11-21 19:51:46 +01:00
|
|
|
if(data) {
|
2011-06-28 14:33:55 +10:00
|
|
|
alpm_conflict_t *newconflict = _alpm_conflict_dup(conflict);
|
2008-01-25 21:52:35 +01:00
|
|
|
if(newconflict) {
|
|
|
|
*data = alpm_list_add(*data, newconflict);
|
Fix several memleaks, mostly related to errors handling.
* The frontend calls alpm_trans_prepare(&data), and in case of errors,
receive the missing dependencies / conflicts / etc in the data pointer.
It apparently needs to free this structure totally with :
alpm_list_free_inner(data, free)
alpm_list_free(data)
So I added alpm_list_free_inner(data, free) in
pacman/{sync.c,remove.c,add,c}
* in _alpm_sync_prepare, the deps and asked lists were not freed in case
of errors (unresolvable conflicts).
Besides the code for handling this case was duplicated.
* in _alpm_remove_commit, free was used instead of alpm_list_free for
newfiles.
* newline fix in pacman/sync.c
Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2007-11-21 19:51:46 +01:00
|
|
|
}
|
|
|
|
}
|
2014-02-03 12:09:18 -05:00
|
|
|
alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_conflict_free);
|
2008-01-11 00:01:58 -06:00
|
|
|
alpm_list_free(deps);
|
2006-03-04 10:16:36 +00:00
|
|
|
goto cleanup;
|
2005-04-17 20:09:06 +00:00
|
|
|
}
|
2005-04-06 21:01:40 +00:00
|
|
|
}
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_INTERCONFLICTS_DONE;
|
|
|
|
EVENT(handle, &event);
|
2014-02-03 12:09:18 -05:00
|
|
|
alpm_list_free_inner(deps, (alpm_list_fn_free)alpm_conflict_free);
|
2007-08-13 00:17:32 +02:00
|
|
|
alpm_list_free(deps);
|
2006-03-04 10:16:36 +00:00
|
|
|
}
|
2005-04-13 19:59:04 +00:00
|
|
|
|
2009-09-12 20:50:03 +02:00
|
|
|
/* Build trans->remove list */
|
|
|
|
for(i = trans->add; i; i = i->next) {
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *spkg = i->data;
|
2009-09-12 20:50:03 +02:00
|
|
|
for(j = spkg->removes; j; j = j->next) {
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *rpkg = j->data;
|
2012-08-12 20:48:53 +10:00
|
|
|
if(!alpm_pkg_find(trans->remove, rpkg->name)) {
|
2011-08-19 11:06:55 -05:00
|
|
|
alpm_pkg_t *copy;
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "adding '%s' to remove list\n", rpkg->name);
|
2011-08-19 11:06:55 -05:00
|
|
|
if(_alpm_pkg_dup(rpkg, ©) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
trans->remove = alpm_list_add(trans->remove, copy);
|
2011-03-21 08:59:59 -05:00
|
|
|
}
|
2006-01-05 20:53:41 +00:00
|
|
|
}
|
2009-09-12 20:50:03 +02:00
|
|
|
}
|
2007-08-12 22:26:54 +02:00
|
|
|
|
2011-07-02 02:01:39 +10:00
|
|
|
if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) {
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "checking dependencies\n");
|
2011-06-07 14:05:42 -05:00
|
|
|
deps = alpm_checkdeps(handle, _alpm_db_get_pkgcache(handle->db_local),
|
|
|
|
trans->remove, trans->add, 1);
|
2007-08-12 22:26:54 +02:00
|
|
|
if(deps) {
|
2011-07-02 02:01:39 +10:00
|
|
|
handle->pm_errno = ALPM_ERR_UNSATISFIED_DEPS;
|
2007-08-12 22:26:54 +02:00
|
|
|
ret = -1;
|
2007-12-23 01:57:43 +10:00
|
|
|
if(data) {
|
|
|
|
*data = deps;
|
|
|
|
} else {
|
2014-02-03 12:09:18 -05:00
|
|
|
alpm_list_free_inner(deps,
|
|
|
|
(alpm_list_fn_free)alpm_depmissing_free);
|
2007-08-13 00:17:32 +02:00
|
|
|
alpm_list_free(deps);
|
2007-12-23 01:57:43 +10:00
|
|
|
}
|
2007-08-12 22:26:54 +02:00
|
|
|
goto cleanup;
|
2006-01-05 20:53:41 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-15 19:14:01 +02:00
|
|
|
for(i = trans->add; i; i = i->next) {
|
2008-02-16 10:47:22 -06:00
|
|
|
/* update download size field */
|
2011-06-28 23:26:39 +10:00
|
|
|
alpm_pkg_t *spkg = i->data;
|
2016-02-21 21:46:35 -05:00
|
|
|
alpm_pkg_t *lpkg = alpm_db_get_pkg(handle->db_local, spkg->name);
|
2011-10-18 10:46:47 -04:00
|
|
|
if(compute_download_size(spkg) < 0) {
|
2008-04-26 13:03:53 -05:00
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2016-02-21 21:46:35 -05:00
|
|
|
if(lpkg && _alpm_pkg_dup(lpkg, &spkg->oldpkg) != 0) {
|
|
|
|
ret = -1;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-02-16 10:47:22 -06:00
|
|
|
}
|
2005-03-15 01:51:43 +00:00
|
|
|
|
2006-03-04 10:16:36 +00:00
|
|
|
cleanup:
|
2011-03-20 19:45:57 -05:00
|
|
|
return ret;
|
2005-03-15 01:51:43 +00:00
|
|
|
}
|
|
|
|
|
2011-06-28 23:26:39 +10:00
|
|
|
off_t SYMEXPORT alpm_pkg_download_size(alpm_pkg_t *newpkg)
|
2007-10-19 13:17:54 -04:00
|
|
|
{
|
2010-05-06 10:07:37 +12:00
|
|
|
if(!(newpkg->infolevel & INFRQ_DSIZE)) {
|
|
|
|
compute_download_size(newpkg);
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return newpkg->download_size;
|
2007-10-19 13:17:54 -04:00
|
|
|
}
|
|
|
|
|
2011-09-01 17:16:56 -05:00
|
|
|
/**
|
|
|
|
* Prompts to delete the file now that we know it is invalid.
|
|
|
|
* @param handle the context handle
|
2008-12-07 11:58:24 -06:00
|
|
|
* @param filename the absolute path of the file to test
|
2011-08-08 19:55:44 -05:00
|
|
|
* @param reason an error code indicating the reason for package invalidity
|
2007-10-19 13:17:52 -04:00
|
|
|
*
|
2011-08-08 19:42:52 -05:00
|
|
|
* @return 1 if file was removed, 0 otherwise
|
2007-10-19 13:17:52 -04:00
|
|
|
*/
|
2011-09-01 17:16:56 -05:00
|
|
|
static int prompt_to_delete(alpm_handle_t *handle, const char *filepath,
|
2011-10-29 15:03:24 +13:00
|
|
|
alpm_errno_t reason)
|
2007-10-19 13:17:52 -04:00
|
|
|
{
|
2014-06-15 19:42:40 +02:00
|
|
|
alpm_question_corrupted_t question = {
|
|
|
|
.type = ALPM_QUESTION_CORRUPTED_PKG,
|
|
|
|
.remove = 0,
|
|
|
|
.filepath = filepath,
|
|
|
|
.reason = reason
|
|
|
|
};
|
|
|
|
QUESTION(handle, &question);
|
|
|
|
if(question.remove) {
|
2020-09-14 18:52:56 -07:00
|
|
|
char *sig_filepath;
|
|
|
|
|
2011-08-08 19:42:52 -05:00
|
|
|
unlink(filepath);
|
2020-09-14 18:52:56 -07:00
|
|
|
|
|
|
|
sig_filepath = _alpm_sigpath(handle, filepath);
|
|
|
|
unlink(sig_filepath);
|
|
|
|
FREE(sig_filepath);
|
2007-10-19 13:17:52 -04:00
|
|
|
}
|
2014-06-15 19:42:40 +02:00
|
|
|
return question.remove;
|
2007-10-19 13:17:52 -04:00
|
|
|
}
|
|
|
|
|
2020-01-29 21:27:10 -08:00
|
|
|
static int find_dl_candidates(alpm_handle_t *handle, alpm_list_t **files)
|
2011-10-14 19:59:04 -04:00
|
|
|
{
|
2020-01-29 21:27:10 -08:00
|
|
|
for(alpm_list_t *i = handle->trans->add; i; i = i->next) {
|
2011-10-14 19:59:04 -04:00
|
|
|
alpm_pkg_t *spkg = i->data;
|
|
|
|
|
2020-01-29 21:27:10 -08:00
|
|
|
if(spkg->origin != ALPM_PKG_FROM_FILE) {
|
|
|
|
alpm_db_t *repo = spkg->origin_data.db;
|
2020-05-18 14:30:04 -07:00
|
|
|
bool need_download;
|
|
|
|
int siglevel = alpm_db_get_siglevel(alpm_pkg_get_db(spkg));
|
2019-11-15 23:29:20 +10:00
|
|
|
|
2011-10-14 19:59:04 -04:00
|
|
|
if(!repo->servers) {
|
|
|
|
handle->pm_errno = ALPM_ERR_SERVER_NONE;
|
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR, "%s: %s\n",
|
|
|
|
alpm_strerror(handle->pm_errno), repo->treename);
|
2021-10-04 20:01:24 +01:00
|
|
|
return -1;
|
2011-10-14 19:59:04 -04:00
|
|
|
}
|
|
|
|
|
2019-11-15 23:29:20 +10:00
|
|
|
ASSERT(spkg->filename != NULL, RET_ERR(handle, ALPM_ERR_PKG_INVALID_NAME, -1));
|
|
|
|
|
2020-05-18 14:30:04 -07:00
|
|
|
need_download = spkg->download_size != 0 || !_alpm_filecache_exists(handle, spkg->filename);
|
|
|
|
/* even if the package file in the cache we need to check for
|
|
|
|
* accompanion *.sig file as well.
|
|
|
|
* If *.sig is not cached then force download the package + its signature file.
|
|
|
|
*/
|
|
|
|
if(!need_download && (siglevel & ALPM_SIG_PACKAGE)) {
|
|
|
|
char *sig_filename = NULL;
|
|
|
|
int len = strlen(spkg->filename) + 5;
|
|
|
|
|
|
|
|
MALLOC(sig_filename, len, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
|
|
|
|
snprintf(sig_filename, len, "%s.sig", spkg->filename);
|
|
|
|
|
|
|
|
need_download = !_alpm_filecache_exists(handle, sig_filename);
|
|
|
|
|
|
|
|
FREE(sig_filename);
|
2019-11-15 23:29:20 +10:00
|
|
|
}
|
|
|
|
|
2020-05-18 14:30:04 -07:00
|
|
|
if(need_download) {
|
2020-02-19 17:40:45 -08:00
|
|
|
*files = alpm_list_add(*files, spkg);
|
2011-10-14 19:59:04 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-03-02 18:57:20 +10:00
|
|
|
static int download_files(alpm_handle_t *handle)
|
2005-03-15 01:51:43 +00:00
|
|
|
{
|
2011-04-21 21:40:00 -05:00
|
|
|
const char *cachedir;
|
2011-10-14 19:59:04 -04:00
|
|
|
alpm_list_t *i, *files = NULL;
|
2020-05-18 14:13:11 -07:00
|
|
|
int ret = 0;
|
2021-03-15 16:33:08 -07:00
|
|
|
alpm_event_t event = {0};
|
2020-04-18 19:00:49 -07:00
|
|
|
alpm_list_t *payloads = NULL;
|
2005-04-14 21:07:38 +00:00
|
|
|
|
2011-06-07 13:15:43 -05:00
|
|
|
cachedir = _alpm_filecache_setup(handle);
|
2011-06-03 13:18:36 -05:00
|
|
|
handle->trans->state = STATE_DOWNLOADING;
|
2007-11-09 19:54:19 -05:00
|
|
|
|
2021-01-16 17:12:55 +00:00
|
|
|
ret = find_dl_candidates(handle, &files);
|
|
|
|
if(ret != 0) {
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
|
2020-05-18 14:13:11 -07:00
|
|
|
if(files) {
|
2011-10-14 22:43:14 -04:00
|
|
|
/* check for necessary disk space for download */
|
|
|
|
if(handle->checkspace) {
|
|
|
|
off_t *file_sizes;
|
|
|
|
size_t idx, num_files;
|
|
|
|
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space for download\n");
|
|
|
|
|
|
|
|
num_files = alpm_list_count(files);
|
|
|
|
CALLOC(file_sizes, num_files, sizeof(off_t), goto finish);
|
|
|
|
|
|
|
|
for(i = files, idx = 0; i; i = i->next, idx++) {
|
2020-02-19 17:40:45 -08:00
|
|
|
const alpm_pkg_t *pkg = i->data;
|
|
|
|
file_sizes[idx] = pkg->size;
|
2011-10-14 22:43:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = _alpm_check_downloadspace(handle, cachedir, num_files, file_sizes);
|
|
|
|
free(file_sizes);
|
|
|
|
|
|
|
|
if(ret != 0) {
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-05 18:28:49 -07:00
|
|
|
event.type = ALPM_EVENT_PKG_RETRIEVE_START;
|
2021-03-15 16:33:08 -07:00
|
|
|
|
|
|
|
/* sum up the number of packages to download and its total size */
|
|
|
|
for(i = files; i; i = i->next) {
|
|
|
|
alpm_pkg_t *spkg = i->data;
|
|
|
|
event.pkg_retrieve.total_size += spkg->download_size;
|
|
|
|
event.pkg_retrieve.num++;
|
|
|
|
}
|
|
|
|
|
2014-01-10 16:25:14 +01:00
|
|
|
EVENT(handle, &event);
|
2011-10-14 19:59:04 -04:00
|
|
|
for(i = files; i; i = i->next) {
|
2020-05-18 14:30:04 -07:00
|
|
|
alpm_pkg_t *pkg = i->data;
|
|
|
|
int siglevel = alpm_db_get_siglevel(alpm_pkg_get_db(pkg));
|
2020-04-18 19:00:49 -07:00
|
|
|
struct dload_payload *payload = NULL;
|
|
|
|
|
|
|
|
CALLOC(payload, 1, sizeof(*payload), GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
|
|
|
|
STRDUP(payload->remote_name, pkg->filename, FREE(payload); GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
|
|
|
|
STRDUP(payload->filepath, pkg->filename,
|
|
|
|
FREE(payload->remote_name); FREE(payload);
|
|
|
|
GOTO_ERR(handle, ALPM_ERR_MEMORY, finish));
|
|
|
|
payload->max_size = pkg->size;
|
2023-11-22 14:19:21 -08:00
|
|
|
payload->cache_servers = pkg->origin_data.db->cache_servers;
|
2020-04-18 19:00:49 -07:00
|
|
|
payload->servers = pkg->origin_data.db->servers;
|
|
|
|
payload->handle = handle;
|
|
|
|
payload->allow_resume = 1;
|
2020-05-18 14:30:04 -07:00
|
|
|
payload->download_signature = (siglevel & ALPM_SIG_PACKAGE);
|
|
|
|
payload->signature_optional = (siglevel & ALPM_SIG_PACKAGE_OPTIONAL);
|
2020-04-18 19:00:49 -07:00
|
|
|
|
|
|
|
payloads = alpm_list_add(payloads, payload);
|
|
|
|
}
|
2020-11-30 18:21:26 +00:00
|
|
|
|
|
|
|
ret = _alpm_download(handle, payloads, cachedir);
|
2021-04-26 20:47:58 -07:00
|
|
|
if(ret == -1) {
|
2020-04-18 19:00:49 -07:00
|
|
|
event.type = ALPM_EVENT_PKG_RETRIEVE_FAILED;
|
2020-05-18 14:13:11 -07:00
|
|
|
EVENT(handle, &event);
|
2020-04-18 19:00:49 -07:00
|
|
|
_alpm_log(handle, ALPM_LOG_WARNING, _("failed to retrieve some files\n"));
|
2020-05-18 14:13:11 -07:00
|
|
|
goto finish;
|
2006-10-15 19:31:03 +00:00
|
|
|
}
|
2020-05-18 14:13:11 -07:00
|
|
|
event.type = ALPM_EVENT_PKG_RETRIEVE_DONE;
|
2014-01-10 16:25:16 +01:00
|
|
|
EVENT(handle, &event);
|
2011-10-14 22:43:14 -04:00
|
|
|
}
|
2011-10-14 19:59:04 -04:00
|
|
|
|
2011-10-14 22:43:14 -04:00
|
|
|
finish:
|
2020-04-18 19:00:49 -07:00
|
|
|
if(payloads) {
|
|
|
|
alpm_list_free_inner(payloads, (alpm_list_fn_free)_alpm_dload_payload_reset);
|
|
|
|
FREELIST(payloads);
|
|
|
|
}
|
|
|
|
|
2011-10-14 22:43:14 -04:00
|
|
|
if(files) {
|
2020-02-19 17:40:45 -08:00
|
|
|
alpm_list_free(files);
|
2006-10-15 19:31:03 +00:00
|
|
|
}
|
|
|
|
|
2011-10-14 19:59:04 -04:00
|
|
|
for(i = handle->trans->add; i; i = i->next) {
|
|
|
|
alpm_pkg_t *pkg = i->data;
|
2010-05-14 21:58:31 +02:00
|
|
|
pkg->infolevel &= ~INFRQ_DSIZE;
|
|
|
|
pkg->download_size = 0;
|
|
|
|
}
|
|
|
|
|
2020-05-18 14:13:11 -07:00
|
|
|
return ret;
|
2011-04-21 21:40:00 -05:00
|
|
|
}
|
|
|
|
|
2013-02-11 13:39:57 +10:00
|
|
|
#ifdef HAVE_LIBGPGME
|
2019-11-12 07:29:52 +10:00
|
|
|
|
|
|
|
static int key_cmp(const void *k1, const void *k2) {
|
|
|
|
const struct keyinfo_t *key1 = k1;
|
|
|
|
const char *key2 = k2;
|
|
|
|
|
|
|
|
return strcmp(key1->keyid, key2);
|
|
|
|
}
|
|
|
|
|
2012-11-03 00:21:48 +10:00
|
|
|
static int check_keyring(alpm_handle_t *handle)
|
|
|
|
{
|
|
|
|
size_t current = 0, numtargs;
|
|
|
|
alpm_list_t *i, *errors = NULL;
|
2014-01-10 16:25:14 +01:00
|
|
|
alpm_event_t event;
|
2019-10-02 16:40:54 +02:00
|
|
|
struct keyinfo_t *keyinfo;
|
2012-11-03 00:21:48 +10:00
|
|
|
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_KEYRING_START;
|
|
|
|
EVENT(handle, &event);
|
2012-11-03 00:21:48 +10:00
|
|
|
|
|
|
|
numtargs = alpm_list_count(handle->trans->add);
|
|
|
|
|
|
|
|
for(i = handle->trans->add; i; i = i->next, current++) {
|
|
|
|
alpm_pkg_t *pkg = i->data;
|
2016-10-12 15:13:32 -05:00
|
|
|
int level;
|
2012-11-03 00:21:48 +10:00
|
|
|
|
|
|
|
int percent = (current * 100) / numtargs;
|
|
|
|
PROGRESS(handle, ALPM_PROGRESS_KEYRING_START, "", percent,
|
|
|
|
numtargs, current);
|
|
|
|
|
|
|
|
if(pkg->origin == ALPM_PKG_FROM_FILE) {
|
|
|
|
continue; /* pkg_load() has been already called, this package is valid */
|
|
|
|
}
|
|
|
|
|
|
|
|
level = alpm_db_get_siglevel(alpm_pkg_get_db(pkg));
|
2020-05-26 19:12:08 -07:00
|
|
|
if((level & ALPM_SIG_PACKAGE)) {
|
|
|
|
unsigned char *sig = NULL;
|
|
|
|
size_t sig_len;
|
|
|
|
int ret = alpm_pkg_get_sig(pkg, &sig, &sig_len);
|
|
|
|
if(ret == 0) {
|
2012-11-03 00:21:48 +10:00
|
|
|
alpm_list_t *keys = NULL;
|
2020-05-26 19:12:08 -07:00
|
|
|
if(alpm_extract_keyid(handle, pkg->name, sig,
|
|
|
|
sig_len, &keys) == 0) {
|
2012-11-03 00:21:48 +10:00
|
|
|
alpm_list_t *k;
|
|
|
|
for(k = keys; k; k = k->next) {
|
|
|
|
char *key = k->data;
|
2020-05-26 19:12:08 -07:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "found signature key: %s\n", key);
|
2019-11-12 07:29:52 +10:00
|
|
|
if(!alpm_list_find(errors, key, key_cmp) &&
|
2014-09-30 15:00:32 -04:00
|
|
|
_alpm_key_in_keychain(handle, key) == 0) {
|
2019-10-02 16:40:54 +02:00
|
|
|
keyinfo = malloc(sizeof(struct keyinfo_t));
|
|
|
|
if(!keyinfo) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
keyinfo->uid = strdup(pkg->packager);
|
|
|
|
keyinfo->keyid = strdup(key);
|
|
|
|
errors = alpm_list_add(errors, keyinfo);
|
2012-11-03 00:21:48 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
FREELIST(keys);
|
|
|
|
}
|
|
|
|
}
|
2020-05-26 19:12:08 -07:00
|
|
|
free(sig);
|
2012-11-03 00:21:48 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PROGRESS(handle, ALPM_PROGRESS_KEYRING_START, "", 100,
|
|
|
|
numtargs, current);
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_KEYRING_DONE;
|
|
|
|
EVENT(handle, &event);
|
2012-11-03 00:21:48 +10:00
|
|
|
|
|
|
|
if(errors) {
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_KEY_DOWNLOAD_START;
|
|
|
|
EVENT(handle, &event);
|
2012-11-03 00:21:48 +10:00
|
|
|
int fail = 0;
|
|
|
|
alpm_list_t *k;
|
|
|
|
for(k = errors; k; k = k->next) {
|
2019-10-02 16:40:54 +02:00
|
|
|
keyinfo = k->data;
|
2019-11-12 07:29:52 +10:00
|
|
|
if(_alpm_key_import(handle, keyinfo->uid, keyinfo->keyid) == -1) {
|
2012-11-03 00:21:48 +10:00
|
|
|
fail = 1;
|
|
|
|
}
|
2019-10-02 16:40:54 +02:00
|
|
|
free(keyinfo->uid);
|
|
|
|
free(keyinfo->keyid);
|
2021-01-15 23:20:58 -08:00
|
|
|
free(keyinfo);
|
2012-11-03 00:21:48 +10:00
|
|
|
}
|
2021-01-15 23:20:58 -08:00
|
|
|
alpm_list_free(errors);
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_KEY_DOWNLOAD_DONE;
|
|
|
|
EVENT(handle, &event);
|
2012-11-03 00:21:48 +10:00
|
|
|
if(fail) {
|
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR, _("required key missing from keyring\n"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2013-02-11 13:39:57 +10:00
|
|
|
#endif /* HAVE_LIBGPGME */
|
2012-11-03 00:21:48 +10:00
|
|
|
|
2011-09-20 16:52:18 -05:00
|
|
|
static int check_validity(alpm_handle_t *handle,
|
2013-10-14 14:55:20 +10:00
|
|
|
size_t total, uint64_t total_bytes)
|
2011-04-21 21:40:00 -05:00
|
|
|
{
|
2011-09-20 16:52:18 -05:00
|
|
|
struct validity {
|
|
|
|
alpm_pkg_t *pkg;
|
|
|
|
char *path;
|
|
|
|
alpm_siglist_t *siglist;
|
2016-10-12 15:13:32 -05:00
|
|
|
int siglevel;
|
|
|
|
int validation;
|
2011-10-29 15:03:24 +13:00
|
|
|
alpm_errno_t error;
|
2011-09-20 16:52:18 -05:00
|
|
|
};
|
2013-10-14 14:55:20 +10:00
|
|
|
size_t current = 0;
|
|
|
|
uint64_t current_bytes = 0;
|
2011-09-20 16:52:18 -05:00
|
|
|
alpm_list_t *i, *errors = NULL;
|
2014-01-10 16:25:14 +01:00
|
|
|
alpm_event_t event;
|
2011-08-29 16:27:00 -05:00
|
|
|
|
2007-10-19 13:17:53 -04:00
|
|
|
/* Check integrity of packages */
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_INTEGRITY_START;
|
|
|
|
EVENT(handle, &event);
|
2006-10-15 19:31:03 +00:00
|
|
|
|
2011-09-19 23:47:06 -05:00
|
|
|
for(i = handle->trans->add; i; i = i->next, current++) {
|
2012-02-18 16:31:37 +10:00
|
|
|
struct validity v = { i->data, NULL, NULL, 0, 0, 0 };
|
2011-08-29 16:27:00 -05:00
|
|
|
int percent = (int)(((double)current_bytes / total_bytes) * 100);
|
2011-04-21 23:39:01 -05:00
|
|
|
|
2011-09-01 17:35:50 -05:00
|
|
|
PROGRESS(handle, ALPM_PROGRESS_INTEGRITY_START, "", percent,
|
2011-09-19 23:47:06 -05:00
|
|
|
total, current);
|
2012-04-01 15:37:19 +10:00
|
|
|
if(v.pkg->origin == ALPM_PKG_FROM_FILE) {
|
Use sync.c for upgrade transaction prepare and commit
This patch utilizes the power of sync.c to fix FS#3492 and FS#5798.
Now an upgrade transaction is just a sync transaction internally (in alpm),
so all sync features are available with -U as well:
* conflict resolving
* sync dependencies from sync repos
* remove unresolvable targets
See http://www.archlinux.org/pipermail/pacman-dev/2009-June/008725.html
for the concept.
We use "mixed" target list, where PKG_FROM_FILE origin indicates local
package file, PKG_FROM_CACHE indicates sync package. The front-end can add
only one type of packages (depending on transaction type) atm, but if alpm
resolves dependencies for -U, we may get a real mixed trans->packages list.
_alpm_pkg_free_trans() was modified so that it can handle both target types
_alpm_add_prepare() was removed, we use _alpm_sync_prepare() instead
_alpm_add_commit() was renamed to _alpm_upgrade_targets()
sync.c (and deps.c) was modified slightly to handle mixed target lists,
the modifications are straightforward. There is one notable change here: We
don't create new upgrade trans in sync.c, we replace the pkgcache entries
with the loaded package files in the target list (this is a bit hackish) and
call _alpm_upgrade_targets(). This implies a TODO (pkg->origin_data.db is
not accessible anymore), but it doesn't hurt anything with pacman front-end,
so it will be fixed later (otherwise this patch would be huge).
I updated the documentation of -U and I added a new pactest, upgrade090.py,
to test the syncdeps feature of -U.
Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-06-09 17:23:46 +02:00
|
|
|
continue; /* pkg_load() has been already called, this package is valid */
|
|
|
|
}
|
|
|
|
|
2011-09-20 16:52:18 -05:00
|
|
|
current_bytes += v.pkg->size;
|
|
|
|
v.path = _alpm_filecache_find(handle, v.pkg->filename);
|
2021-09-27 18:30:17 +01:00
|
|
|
|
|
|
|
if(!v.path) {
|
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR,
|
|
|
|
_("%s: could not find package in cache\n"), v.pkg->name);
|
|
|
|
RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, -1);
|
|
|
|
}
|
|
|
|
|
2016-10-12 15:13:32 -05:00
|
|
|
v.siglevel = alpm_db_get_siglevel(alpm_pkg_get_db(v.pkg));
|
2011-03-25 21:40:16 -04:00
|
|
|
|
2011-09-20 16:52:18 -05:00
|
|
|
if(_alpm_pkg_validate_internal(handle, v.path, v.pkg,
|
2016-10-12 15:13:32 -05:00
|
|
|
v.siglevel, &v.siglist, &v.validation) == -1) {
|
2014-03-08 16:58:30 +10:00
|
|
|
struct validity *invalid;
|
2011-09-20 16:52:18 -05:00
|
|
|
v.error = handle->pm_errno;
|
2014-03-08 16:58:30 +10:00
|
|
|
MALLOC(invalid, sizeof(struct validity), return -1);
|
2011-09-20 16:52:18 -05:00
|
|
|
memcpy(invalid, &v, sizeof(struct validity));
|
|
|
|
errors = alpm_list_add(errors, invalid);
|
|
|
|
} else {
|
|
|
|
alpm_siglist_cleanup(v.siglist);
|
|
|
|
free(v.siglist);
|
|
|
|
free(v.path);
|
2012-02-18 16:31:37 +10:00
|
|
|
v.pkg->validation = v.validation;
|
2006-10-15 19:31:03 +00:00
|
|
|
}
|
2011-09-19 21:01:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
PROGRESS(handle, ALPM_PROGRESS_INTEGRITY_START, "", 100,
|
2011-09-19 23:47:06 -05:00
|
|
|
total, current);
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_INTEGRITY_DONE;
|
|
|
|
EVENT(handle, &event);
|
2011-09-19 21:01:26 -05:00
|
|
|
|
|
|
|
if(errors) {
|
2011-09-20 16:52:18 -05:00
|
|
|
for(i = errors; i; i = i->next) {
|
|
|
|
struct validity *v = i->data;
|
2018-09-19 14:28:35 +12:00
|
|
|
switch(v->error) {
|
|
|
|
case ALPM_ERR_PKG_MISSING_SIG:
|
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR,
|
|
|
|
_("%s: missing required signature\n"), v->pkg->name);
|
|
|
|
break;
|
|
|
|
case ALPM_ERR_PKG_INVALID_SIG:
|
|
|
|
_alpm_process_siglist(handle, v->pkg->name, v->siglist,
|
|
|
|
v->siglevel & ALPM_SIG_PACKAGE_OPTIONAL,
|
|
|
|
v->siglevel & ALPM_SIG_PACKAGE_MARGINAL_OK,
|
|
|
|
v->siglevel & ALPM_SIG_PACKAGE_UNKNOWN_OK);
|
2021-05-17 20:02:17 +10:00
|
|
|
__attribute__((fallthrough));
|
2018-09-19 14:28:35 +12:00
|
|
|
case ALPM_ERR_PKG_INVALID_CHECKSUM:
|
|
|
|
prompt_to_delete(handle, v->path, v->error);
|
|
|
|
break;
|
2018-09-19 14:30:37 +12:00
|
|
|
case ALPM_ERR_PKG_NOT_FOUND:
|
|
|
|
case ALPM_ERR_BADPERMS:
|
|
|
|
case ALPM_ERR_PKG_OPEN:
|
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR, _("failed to read file %s: %s\n"), v->path, alpm_strerror(v->error));
|
|
|
|
break;
|
2018-09-19 14:28:35 +12:00
|
|
|
default:
|
|
|
|
/* ignore */
|
|
|
|
break;
|
2011-09-20 16:52:18 -05:00
|
|
|
}
|
|
|
|
alpm_siglist_cleanup(v->siglist);
|
|
|
|
free(v->siglist);
|
|
|
|
free(v->path);
|
|
|
|
free(v);
|
2011-09-19 21:01:26 -05:00
|
|
|
}
|
2011-09-20 16:52:18 -05:00
|
|
|
alpm_list_free(errors);
|
|
|
|
|
2016-10-12 15:13:31 -05:00
|
|
|
if(handle->pm_errno == ALPM_ERR_OK) {
|
2012-11-03 00:29:11 +10:00
|
|
|
RET_ERR(handle, ALPM_ERR_PKG_INVALID, -1);
|
2011-09-20 16:52:18 -05:00
|
|
|
}
|
2012-11-03 00:29:11 +10:00
|
|
|
return -1;
|
2011-09-19 21:01:26 -05:00
|
|
|
}
|
|
|
|
|
2011-09-19 23:47:06 -05:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int load_packages(alpm_handle_t *handle, alpm_list_t **data,
|
|
|
|
size_t total, size_t total_bytes)
|
|
|
|
{
|
|
|
|
size_t current = 0, current_bytes = 0;
|
|
|
|
int errors = 0;
|
|
|
|
alpm_list_t *i;
|
2014-01-10 16:25:14 +01:00
|
|
|
alpm_event_t event;
|
2011-09-19 21:01:26 -05:00
|
|
|
|
|
|
|
/* load packages from disk now that they are known-valid */
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_LOAD_START;
|
|
|
|
EVENT(handle, &event);
|
2011-09-19 21:01:26 -05:00
|
|
|
|
2011-09-19 23:47:06 -05:00
|
|
|
for(i = handle->trans->add; i; i = i->next, current++) {
|
2015-07-18 17:58:23 +02:00
|
|
|
int error = 0;
|
2011-09-19 21:01:26 -05:00
|
|
|
alpm_pkg_t *spkg = i->data;
|
|
|
|
char *filepath;
|
|
|
|
int percent = (int)(((double)current_bytes / total_bytes) * 100);
|
|
|
|
|
|
|
|
PROGRESS(handle, ALPM_PROGRESS_LOAD_START, "", percent,
|
2011-09-19 23:47:06 -05:00
|
|
|
total, current);
|
2012-04-01 15:37:19 +10:00
|
|
|
if(spkg->origin == ALPM_PKG_FROM_FILE) {
|
2011-09-19 21:01:26 -05:00
|
|
|
continue; /* pkg_load() has been already called, this package is valid */
|
|
|
|
}
|
|
|
|
|
|
|
|
current_bytes += spkg->size;
|
|
|
|
filepath = _alpm_filecache_find(handle, spkg->filename);
|
|
|
|
|
2021-09-27 18:30:17 +01:00
|
|
|
if(!filepath) {
|
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR,
|
|
|
|
_("%s: could not find package in cache\n"), spkg->name);
|
|
|
|
RET_ERR(handle, ALPM_ERR_PKG_NOT_FOUND, -1);
|
|
|
|
}
|
|
|
|
|
2011-09-19 21:01:26 -05:00
|
|
|
/* load the package file and replace pkgcache entry with it in the target list */
|
|
|
|
/* TODO: alpm_pkg_get_db() will not work on this target anymore */
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG,
|
|
|
|
"replacing pkgcache entry with package file for target %s\n",
|
|
|
|
spkg->name);
|
2011-09-19 20:40:32 -05:00
|
|
|
alpm_pkg_t *pkgfile =_alpm_pkg_load_internal(handle, filepath, 1);
|
|
|
|
if(!pkgfile) {
|
2015-07-18 17:58:23 +02:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "failed to load pkgfile internal\n");
|
|
|
|
error = 1;
|
|
|
|
} else {
|
|
|
|
if(strcmp(spkg->name, pkgfile->name) != 0) {
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG,
|
|
|
|
"internal package name mismatch, expected: '%s', actual: '%s'\n",
|
|
|
|
spkg->name, pkgfile->name);
|
|
|
|
error = 1;
|
|
|
|
}
|
|
|
|
if(strcmp(spkg->version, pkgfile->version) != 0) {
|
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG,
|
|
|
|
"internal package version mismatch, expected: '%s', actual: '%s'\n",
|
|
|
|
spkg->version, pkgfile->version);
|
|
|
|
error = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(error != 0) {
|
2011-09-19 20:40:32 -05:00
|
|
|
errors++;
|
|
|
|
*data = alpm_list_add(*data, strdup(spkg->filename));
|
2011-09-19 23:28:05 -05:00
|
|
|
free(filepath);
|
2022-12-13 00:43:43 +10:00
|
|
|
_alpm_pkg_free(pkgfile);
|
2011-09-19 20:40:32 -05:00
|
|
|
continue;
|
|
|
|
}
|
2011-09-19 23:28:05 -05:00
|
|
|
free(filepath);
|
2011-09-28 01:53:43 -05:00
|
|
|
/* copy over the install reason */
|
|
|
|
pkgfile->reason = spkg->reason;
|
2012-02-18 16:31:37 +10:00
|
|
|
/* copy over validation method */
|
|
|
|
pkgfile->validation = spkg->validation;
|
2016-02-21 21:46:35 -05:00
|
|
|
/* transfer oldpkg */
|
|
|
|
pkgfile->oldpkg = spkg->oldpkg;
|
|
|
|
spkg->oldpkg = NULL;
|
Use sync.c for upgrade transaction prepare and commit
This patch utilizes the power of sync.c to fix FS#3492 and FS#5798.
Now an upgrade transaction is just a sync transaction internally (in alpm),
so all sync features are available with -U as well:
* conflict resolving
* sync dependencies from sync repos
* remove unresolvable targets
See http://www.archlinux.org/pipermail/pacman-dev/2009-June/008725.html
for the concept.
We use "mixed" target list, where PKG_FROM_FILE origin indicates local
package file, PKG_FROM_CACHE indicates sync package. The front-end can add
only one type of packages (depending on transaction type) atm, but if alpm
resolves dependencies for -U, we may get a real mixed trans->packages list.
_alpm_pkg_free_trans() was modified so that it can handle both target types
_alpm_add_prepare() was removed, we use _alpm_sync_prepare() instead
_alpm_add_commit() was renamed to _alpm_upgrade_targets()
sync.c (and deps.c) was modified slightly to handle mixed target lists,
the modifications are straightforward. There is one notable change here: We
don't create new upgrade trans in sync.c, we replace the pkgcache entries
with the loaded package files in the target list (this is a bit hackish) and
call _alpm_upgrade_targets(). This implies a TODO (pkg->origin_data.db is
not accessible anymore), but it doesn't hurt anything with pacman front-end,
so it will be fixed later (otherwise this patch would be huge).
I updated the documentation of -U and I added a new pactest, upgrade090.py,
to test the syncdeps feature of -U.
Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
Signed-off-by: Dan McGee <dan@archlinux.org>
2009-06-09 17:23:46 +02:00
|
|
|
i->data = pkgfile;
|
2011-09-28 01:53:43 -05:00
|
|
|
/* spkg has been removed from the target list, so we can free the
|
|
|
|
* sync-specific fields */
|
|
|
|
_alpm_pkg_free_trans(spkg);
|
2006-10-15 19:31:03 +00:00
|
|
|
}
|
2008-12-17 16:25:07 +05:30
|
|
|
|
2011-09-19 21:01:26 -05:00
|
|
|
PROGRESS(handle, ALPM_PROGRESS_LOAD_START, "", 100,
|
2011-09-19 23:47:06 -05:00
|
|
|
total, current);
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_LOAD_DONE;
|
|
|
|
EVENT(handle, &event);
|
2008-12-17 16:25:07 +05:30
|
|
|
|
2008-02-27 00:50:17 +01:00
|
|
|
if(errors) {
|
2016-10-12 15:13:31 -05:00
|
|
|
if(handle->pm_errno == ALPM_ERR_OK) {
|
2011-08-08 19:42:52 -05:00
|
|
|
RET_ERR(handle, ALPM_ERR_PKG_INVALID, -1);
|
|
|
|
}
|
|
|
|
return -1;
|
2006-10-15 19:31:03 +00:00
|
|
|
}
|
2011-01-11 21:12:08 -06:00
|
|
|
|
2011-09-19 23:47:06 -05:00
|
|
|
return 0;
|
|
|
|
}
|
2009-01-02 17:43:05 +01:00
|
|
|
|
2014-10-11 04:08:20 -04:00
|
|
|
int _alpm_sync_load(alpm_handle_t *handle, alpm_list_t **data)
|
2011-09-19 23:47:06 -05:00
|
|
|
{
|
2019-03-02 18:57:20 +10:00
|
|
|
alpm_list_t *i;
|
2013-10-14 14:55:20 +10:00
|
|
|
size_t total = 0;
|
|
|
|
uint64_t total_bytes = 0;
|
2011-09-19 23:47:06 -05:00
|
|
|
alpm_trans_t *trans = handle->trans;
|
|
|
|
|
2021-05-01 21:25:35 +01:00
|
|
|
if(download_files(handle) == -1) {
|
2011-09-19 23:47:06 -05:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-01-10 14:32:38 +10:00
|
|
|
#ifdef HAVE_LIBGPGME
|
2012-11-03 00:21:48 +10:00
|
|
|
/* make sure all required signatures are in keyring */
|
|
|
|
if(check_keyring(handle)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-09-19 23:47:06 -05:00
|
|
|
/* get the total size of all packages so we can adjust the progress bar more
|
|
|
|
* realistically if there are small and huge packages involved */
|
|
|
|
for(i = trans->add; i; i = i->next) {
|
|
|
|
alpm_pkg_t *spkg = i->data;
|
2012-04-01 15:37:19 +10:00
|
|
|
if(spkg->origin != ALPM_PKG_FROM_FILE) {
|
2011-09-19 23:47:06 -05:00
|
|
|
total_bytes += spkg->size;
|
|
|
|
}
|
|
|
|
total++;
|
|
|
|
}
|
|
|
|
/* this can only happen maliciously */
|
|
|
|
total_bytes = total_bytes ? total_bytes : 1;
|
|
|
|
|
2014-09-30 14:44:42 -04:00
|
|
|
if(check_validity(handle, total, total_bytes) != 0) {
|
|
|
|
return -1;
|
2011-09-19 23:47:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if(trans->flags & ALPM_TRANS_FLAG_DOWNLOADONLY) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(load_packages(handle, data, total, total_bytes)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-10-11 04:08:20 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-09-14 18:37:40 -04:00
|
|
|
int _alpm_sync_check(alpm_handle_t *handle, alpm_list_t **data)
|
2014-10-11 04:08:20 -04:00
|
|
|
{
|
|
|
|
alpm_trans_t *trans = handle->trans;
|
|
|
|
alpm_event_t event;
|
2009-01-02 17:43:05 +01:00
|
|
|
|
|
|
|
/* fileconflict check */
|
2013-02-12 22:00:53 +10:00
|
|
|
if(!(trans->flags & ALPM_TRANS_FLAG_DBONLY)) {
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_FILECONFLICTS_START;
|
|
|
|
EVENT(handle, &event);
|
2009-01-02 17:43:05 +01:00
|
|
|
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "looking for file conflicts\n");
|
2011-06-03 13:18:36 -05:00
|
|
|
alpm_list_t *conflict = _alpm_db_find_fileconflicts(handle,
|
|
|
|
trans->add, trans->remove);
|
2009-01-02 17:43:05 +01:00
|
|
|
if(conflict) {
|
|
|
|
if(data) {
|
|
|
|
*data = conflict;
|
|
|
|
} else {
|
2015-09-14 18:37:40 -04:00
|
|
|
alpm_list_free_inner(conflict,
|
|
|
|
(alpm_list_fn_free)alpm_fileconflict_free);
|
2009-01-02 17:43:05 +01:00
|
|
|
alpm_list_free(conflict);
|
|
|
|
}
|
2011-07-02 02:01:39 +10:00
|
|
|
RET_ERR(handle, ALPM_ERR_FILE_CONFLICTS, -1);
|
2009-01-02 17:43:05 +01:00
|
|
|
}
|
|
|
|
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_FILECONFLICTS_DONE;
|
|
|
|
EVENT(handle, &event);
|
2005-04-13 21:01:28 +00:00
|
|
|
}
|
2009-01-02 17:43:05 +01:00
|
|
|
|
2010-11-16 15:57:39 +10:00
|
|
|
/* check available disk space */
|
2011-12-21 16:42:47 -06:00
|
|
|
if(handle->checkspace && !(trans->flags & ALPM_TRANS_FLAG_DBONLY)) {
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_DISKSPACE_START;
|
|
|
|
EVENT(handle, &event);
|
2010-11-16 17:07:43 +10:00
|
|
|
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "checking available disk space\n");
|
2011-06-03 12:36:13 -05:00
|
|
|
if(_alpm_check_diskspace(handle) == -1) {
|
2012-03-12 21:47:29 -05:00
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR, _("not enough free disk space\n"));
|
2011-04-21 21:57:08 -05:00
|
|
|
return -1;
|
2010-11-16 16:54:30 +10:00
|
|
|
}
|
2010-11-16 17:07:43 +10:00
|
|
|
|
2014-01-10 16:25:14 +01:00
|
|
|
event.type = ALPM_EVENT_DISKSPACE_DONE;
|
|
|
|
EVENT(handle, &event);
|
2010-11-16 15:57:39 +10:00
|
|
|
}
|
|
|
|
|
2015-09-14 18:37:40 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int _alpm_sync_commit(alpm_handle_t *handle)
|
|
|
|
{
|
|
|
|
alpm_trans_t *trans = handle->trans;
|
|
|
|
|
2009-01-02 17:43:05 +01:00
|
|
|
/* remove conflicting and to-be-replaced packages */
|
2011-09-19 23:47:06 -05:00
|
|
|
if(trans->remove) {
|
2015-09-14 18:37:40 -04:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG,
|
|
|
|
"removing conflicting and to-be-replaced packages\n");
|
2009-01-02 17:43:05 +01:00
|
|
|
/* we want the frontend to be aware of commit details */
|
2011-09-19 13:18:42 -05:00
|
|
|
if(_alpm_remove_packages(handle, 0) == -1) {
|
2015-09-14 18:37:40 -04:00
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR,
|
|
|
|
_("could not commit removal transaction\n"));
|
2011-04-21 21:57:08 -05:00
|
|
|
return -1;
|
2009-01-02 17:43:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* install targets */
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_DEBUG, "installing packages\n");
|
2011-06-03 13:18:36 -05:00
|
|
|
if(_alpm_upgrade_packages(handle) == -1) {
|
2011-07-02 02:01:38 +10:00
|
|
|
_alpm_log(handle, ALPM_LOG_ERROR, _("could not commit transaction\n"));
|
2011-04-21 21:57:08 -05:00
|
|
|
return -1;
|
2005-03-15 01:51:43 +00:00
|
|
|
}
|
2005-04-13 21:01:28 +00:00
|
|
|
|
2011-04-21 21:57:08 -05:00
|
|
|
return 0;
|
2005-03-15 01:51:43 +00:00
|
|
|
}
|