From 0da96abc900560f21c643b255c94a60232f4a24b Mon Sep 17 00:00:00 2001 From: Nagy Gabor Date: Tue, 9 Jun 2009 17:23:46 +0200 Subject: 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 Signed-off-by: Dan McGee --- lib/libalpm/add.c | 87 +-------------------------------------------------- lib/libalpm/add.h | 3 +- lib/libalpm/deps.c | 2 +- lib/libalpm/package.c | 11 ++++++- lib/libalpm/sync.c | 86 +++++++++++++++++++++++--------------------------- lib/libalpm/trans.c | 16 ++-------- 6 files changed, 56 insertions(+), 149 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 1b228b2d..86355007 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -99,91 +99,6 @@ error: return(-1); } -int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data) -{ - alpm_list_t *lp = NULL; - - ALPM_LOG_FUNC; - - ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1)); - ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1)); - - /* Check dependencies - */ - if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) { - EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL); - - /* look for unsatisfied dependencies */ - _alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n"); - lp = alpm_checkdeps(_alpm_db_get_pkgcache(db), 1, NULL, trans->packages); - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free); - alpm_list_free(lp); - } - RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1); - } - - /* no unsatisfied deps, so look for conflicts */ - _alpm_log(PM_LOG_DEBUG, "looking for conflicts\n"); - alpm_list_t *inner = _alpm_innerconflicts(trans->packages); - alpm_list_t *outer = _alpm_outerconflicts(db, trans->packages); - lp = alpm_list_join(inner, outer); - - /* TODO : factorize the conflict resolving code from sync.c to use it here (FS#3492) */ - - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_conflict_free); - alpm_list_free(lp); - } - if(inner) { - _alpm_log(PM_LOG_ERROR, _("conflicting packages were found in the target list\n")); - _alpm_log(PM_LOG_ERROR, _("you cannot install two conflicting packages at the same time\n")); - } - if(outer) { - _alpm_log(PM_LOG_ERROR, _("replacing packages with -U is not supported yet\n")); - _alpm_log(PM_LOG_ERROR, _("you can replace packages manually using -Rd and -U\n")); - } - RET_ERR(PM_ERR_CONFLICTING_DEPS, -1); - } - - /* re-order w.r.t. dependencies */ - _alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n"); - lp = _alpm_sortbydeps(trans->packages, 0); - /* free the old alltargs */ - alpm_list_free(trans->packages); - trans->packages = lp; - - EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL); - } - - /* Check for file conflicts */ - if(!(trans->flags & PM_TRANS_FLAG_FORCE)) { - EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); - - _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - lp = _alpm_db_find_fileconflicts(db, trans, trans->packages, NULL); - if(lp != NULL) { - if(data) { - *data = lp; - } else { - alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_fileconflict_free); - alpm_list_free(lp); - } - RET_ERR(PM_ERR_FILE_CONFLICTS, -1); - } - - EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); - } - - return(0); -} - static int upgrade_remove(pmpkg_t *oldpkg, pmpkg_t *newpkg, pmtrans_t *trans, pmdb_t *db) { /* this is kinda odd. If the old package exists, at this point we make a * NEW transaction, unrelated to handle->trans, and instantiate a "remove" @@ -858,7 +773,7 @@ cleanup: return(ret); } -int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db) +int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db) { int pkg_count, pkg_current; alpm_list_t *targ; diff --git a/lib/libalpm/add.h b/lib/libalpm/add.h index 6983de9e..1a3b799d 100644 --- a/lib/libalpm/add.h +++ b/lib/libalpm/add.h @@ -25,8 +25,7 @@ #include "trans.h" int _alpm_add_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name); -int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data); -int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db); +int _alpm_upgrade_packages(pmtrans_t *trans, pmdb_t *db); #endif /* _ALPM_ADD_H */ diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 02a4c7b6..46699ac6 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -605,7 +605,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *pkg, ALPM_LOG_FUNC; - if(local == NULL || dbs_sync == NULL) { + if(local == NULL) { return(-1); } diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 002b1c89..2e0d0dfd 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -858,7 +858,11 @@ void _alpm_pkg_free(pmpkg_t *pkg) FREE(pkg); } -/* Free transaction specific fields */ +/* This function should be used when removing a target from upgrade/sync target list + * Case 1: If pkg is a loaded package file (PKG_FROM_FILE), it will be freed. + * Case 2: If pkg is a pkgcache entry (PKG_FROM_CACHE), it won't be freed, + * only the transaction specific fields of pkg will be freed. + */ void _alpm_pkg_free_trans(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -867,6 +871,11 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg) return; } + if(pkg->origin == PKG_FROM_FILE) { + _alpm_pkg_free(pkg); + return; + } + alpm_list_free(pkg->removes); pkg->removes = NULL; } diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index dda4953d..a738d1b8 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -43,6 +43,7 @@ #include "deps.h" #include "conflict.h" #include "trans.h" +#include "add.h" #include "util.h" #include "handle.h" #include "alpm.h" @@ -282,6 +283,11 @@ static int compute_download_size(pmpkg_t *newpkg) char *fpath; off_t size = 0; + if(newpkg->origin == PKG_FROM_FILE) { + newpkg->download_size = 0; + return(0); + } + fname = alpm_pkg_get_filename(newpkg); ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1)); fpath = _alpm_filecache_find(fname); @@ -392,10 +398,6 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } } - /* Unresolvable packages will be removed from the target list, so - we free the transaction specific fields */ - alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans); - /* Set DEPEND reason for pulled packages */ for(i = resolved; i; i = i->next) { pmpkg_t *pkg = i->data; @@ -404,6 +406,10 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync } } + /* Unresolvable packages will be removed from the target list, so + we free the transaction specific fields */ + alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans); + /* re-order w.r.t. dependencies */ alpm_list_free(trans->packages); trans->packages = _alpm_sortbydeps(resolved, 0); @@ -468,8 +474,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync _alpm_log(PM_LOG_WARNING, _("removing '%s' from target list because it conflicts with '%s'\n"), rsync->name, sync->name); - _alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */ trans->packages = alpm_list_remove(trans->packages, rsync, _alpm_pkg_cmp, NULL); + _alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */ continue; } @@ -711,7 +717,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) { alpm_list_t *i, *j, *files = NULL; alpm_list_t *deltas = NULL; - pmtrans_t *tr_remove = NULL, *tr_upgrade = NULL; + pmtrans_t *tr_remove = NULL; int replaces = 0; int errors = 0; const char *cachedir = NULL; @@ -743,9 +749,8 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) for(j = trans->packages; j; j = j->next) { pmpkg_t *spkg = j->data; - pmdb_t *dbs = spkg->origin_data.db; - if(current == dbs) { + if(spkg->origin == PKG_FROM_CACHE && current == spkg->origin_data.db) { const char *fname = NULL; fname = alpm_pkg_get_filename(spkg); @@ -837,13 +842,35 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) errors = 0; for(i = trans->packages; i; i = i->next) { pmpkg_t *spkg = i->data; + if(spkg->origin == PKG_FROM_FILE) { + continue; /* pkg_load() has been already called, this package is valid */ + } + const char *filename = alpm_pkg_get_filename(spkg); const char *md5sum = alpm_pkg_get_md5sum(spkg); if(test_md5sum(trans, filename, md5sum) != 0) { errors++; *data = alpm_list_add(*data, strdup(filename)); + continue; + } + /* 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(PM_LOG_DEBUG, "replacing pkgcache entry with package file for target %s\n", spkg->name); + char *filepath = _alpm_filecache_find(filename); + pmpkg_t *pkgfile; + if(alpm_pkg_load(filepath, 1, &pkgfile) != 0) { + _alpm_pkg_free(pkgfile); + errors++; + *data = alpm_list_add(*data, strdup(filename)); + FREE(filepath); + continue; } + FREE(filepath); + pkgfile->reason = spkg->reason; /* copy over install reason */ + pkgfile->removes = alpm_list_copy(spkg->removes); /* copy over removes list */ + i->data = pkgfile; + _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */ } if(errors) { pm_errno = PM_ERR_PKG_INVALID; @@ -856,32 +883,22 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) trans->state = STATE_COMMITING; - /* Create remove and upgrade transactions */ + /* Create remove transaction */ tr_remove = _alpm_trans_new(); if(tr_remove == NULL) { _alpm_log(PM_LOG_ERROR, _("could not create removal transaction\n")); goto error; } - tr_upgrade = _alpm_trans_new(); - if(tr_upgrade == NULL) { - _alpm_log(PM_LOG_ERROR, _("could not create transaction\n")); - goto error; - } if(_alpm_trans_init(tr_remove, PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAG_NODEPS, NULL, NULL, NULL) == -1) { _alpm_log(PM_LOG_ERROR, _("could not initialize the removal transaction\n")); goto error; } - if(_alpm_trans_init(tr_upgrade, PM_TRANS_TYPE_UPGRADE, trans->flags, trans->cb_event, trans->cb_conv, trans->cb_progress) == -1) { - _alpm_log(PM_LOG_ERROR, _("could not initialize transaction\n")); - goto error; - } - /* adding targets */ + /* adding targets to the remove transaction */ for(i = trans->packages; i; i = i->next) { pmpkg_t *spkg = i->data; alpm_list_t *j; - /* remove transaction */ for(j = spkg->removes; j; j = j->next) { pmpkg_t *pkg = j->data; if(!_alpm_pkg_find(tr_remove->packages, pkg->name)) { @@ -891,27 +908,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) replaces++; } } - /* upgrade transaction */ - const char *fname; - char *fpath; - - fname = alpm_pkg_get_filename(spkg); - if(fname == NULL) { - goto error; - } - /* Loop through the cache dirs until we find a matching file */ - fpath = _alpm_filecache_find(fname); - - if(_alpm_trans_addtarget(tr_upgrade, fpath) == -1) { - FREE(fpath); - goto error; - } - FREE(fpath); - - /* using alpm_list_last() is ok because addtarget() adds the new target at the - * end of the tr->packages list */ - pmpkg_t *ipkg = alpm_list_last(tr_upgrade->packages)->data; - ipkg->reason = spkg->reason; } /* fileconflict check */ @@ -919,8 +915,8 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_START, NULL, NULL); _alpm_log(PM_LOG_DEBUG, "looking for file conflicts\n"); - alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, tr_upgrade, - tr_upgrade->packages, tr_remove->packages); + alpm_list_t *conflict = _alpm_db_find_fileconflicts(db_local, trans, + trans->packages, tr_remove->packages); if(conflict) { pm_errno = PM_ERR_FILE_CONFLICTS; if(data) { @@ -953,8 +949,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) /* install targets */ _alpm_log(PM_LOG_DEBUG, "installing packages\n"); - /* add_prepare is not needed */ - if(_alpm_trans_commit(tr_upgrade, NULL) == -1) { + if(_alpm_upgrade_packages(trans, handle->db_local) == -1) { _alpm_log(PM_LOG_ERROR, _("could not commit transaction\n")); goto error; } @@ -964,7 +959,6 @@ error: FREELIST(files); alpm_list_free(deltas); _alpm_trans_free(tr_remove); - _alpm_trans_free(tr_upgrade); return(ret); } diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c index 240bf816..f913ba9e 100644 --- a/lib/libalpm/trans.c +++ b/lib/libalpm/trans.c @@ -247,7 +247,7 @@ void _alpm_trans_free(pmtrans_t *trans) return; } - if(trans->type == PM_TRANS_TYPE_SYNC) { + if(trans->type == PM_TRANS_TYPE_SYNC || trans->type == PM_TRANS_TYPE_UPGRADE) { alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free_trans); } else { alpm_list_free_inner(trans->packages, (alpm_list_fn_free)_alpm_pkg_free); @@ -367,12 +367,6 @@ int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data) } switch(trans->type) { - case PM_TRANS_TYPE_UPGRADE: - if(_alpm_add_prepare(trans, handle->db_local, data) == -1) { - /* pm_errno is set by _alpm_add_prepare() */ - return(-1); - } - break; case PM_TRANS_TYPE_REMOVE: case PM_TRANS_TYPE_REMOVEUPGRADE: if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) { @@ -380,6 +374,7 @@ int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data) return(-1); } break; + case PM_TRANS_TYPE_UPGRADE: case PM_TRANS_TYPE_SYNC: if(_alpm_sync_prepare(trans, handle->db_local, handle->dbs_sync, data) == -1) { /* pm_errno is set by _alpm_sync_prepare() */ @@ -411,12 +406,6 @@ int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data) trans->state = STATE_COMMITING; switch(trans->type) { - case PM_TRANS_TYPE_UPGRADE: - if(_alpm_add_commit(trans, handle->db_local) == -1) { - /* pm_errno is set by _alpm_add_commit() */ - return(-1); - } - break; case PM_TRANS_TYPE_REMOVE: case PM_TRANS_TYPE_REMOVEUPGRADE: if(_alpm_remove_commit(trans, handle->db_local) == -1) { @@ -424,6 +413,7 @@ int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data) return(-1); } break; + case PM_TRANS_TYPE_UPGRADE: case PM_TRANS_TYPE_SYNC: if(_alpm_sync_commit(trans, handle->db_local, data) == -1) { /* pm_errno is set by _alpm_sync_commit() */ -- cgit v1.2.3-24-g4f1b