diff options
Diffstat (limited to 'lib/libalpm/sync.c')
-rw-r--r-- | lib/libalpm/sync.c | 235 |
1 files changed, 62 insertions, 173 deletions
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 4cbaf0cb..fdd37608 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -1,7 +1,7 @@ /* * sync.c * - * Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org> + * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com> * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu> @@ -31,7 +31,7 @@ #include <stdint.h> /* intmax_t */ #include <unistd.h> #include <time.h> -#include <dirent.h> +#include <limits.h> /* libalpm */ #include "sync.h" @@ -39,7 +39,6 @@ #include "log.h" #include "package.h" #include "db.h" -#include "cache.h" #include "deps.h" #include "conflict.h" #include "trans.h" @@ -50,6 +49,7 @@ #include "dload.h" #include "delta.h" #include "remove.h" +#include "diskspace.h" /** Check for new version of pkg in sync repos * (only the first occurrence is considered in sync) @@ -202,177 +202,46 @@ int SYMEXPORT alpm_sync_sysupgrade(int enable_downgrade) return(0); } -static int sync_pkg(pmpkg_t *spkg, alpm_list_t *pkg_list) +/** Find group members across a list of databases. + * If a member exists in several databases, only the first database is used. + * IgnorePkg is also handled. + * @param dbs the list of pmdb_t * + * @pram name the name of the group + * @return the list of pmpkg_t * (caller is responsible for alpm_list_free) + */ +alpm_list_t SYMEXPORT *alpm_find_grp_pkgs(alpm_list_t *dbs, + const char *name) { - pmtrans_t *trans; - pmdb_t *db_local; - pmpkg_t *local; + alpm_list_t *i, *j, *pkgs = NULL, *ignorelist = NULL; - ALPM_LOG_FUNC; - - trans = handle->trans; - db_local = handle->db_local; + for(i = dbs; i; i = i->next) { + pmdb_t *db = i->data; + pmgrp_t *grp = alpm_db_readgrp(db, name); - if(_alpm_pkg_find(pkg_list, alpm_pkg_get_name(spkg))) { - RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1); - } + if(!grp) + continue; - local = _alpm_db_get_pkgfromcache(db_local, alpm_pkg_get_name(spkg)); - if(local) { - int cmp = _alpm_pkg_compare_versions(spkg, local); - if(cmp == 0) { - if(trans->flags & PM_TRANS_FLAG_NEEDED) { - /* with the NEEDED flag, packages up to date are not reinstalled */ - _alpm_log(PM_LOG_WARNING, _("%s-%s is up to date -- skipping\n"), - alpm_pkg_get_name(local), alpm_pkg_get_version(local)); - return(0); - } else { - _alpm_log(PM_LOG_WARNING, _("%s-%s is up to date -- reinstalling\n"), - alpm_pkg_get_name(local), alpm_pkg_get_version(local)); + for(j = alpm_grp_get_pkgs(grp); j; j = j->next) { + pmpkg_t *pkg = j->data; + if(_alpm_pkg_find(ignorelist, alpm_pkg_get_name(pkg))) { + continue; } - } else if(cmp < 0) { - /* local version is newer */ - _alpm_log(PM_LOG_WARNING, _("downgrading package %s (%s => %s)\n"), - alpm_pkg_get_name(local), alpm_pkg_get_version(local), - alpm_pkg_get_version(spkg)); - } - } - - /* add the package to the transaction */ - spkg->reason = PM_PKG_REASON_EXPLICIT; - _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", - alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg)); - trans->add = alpm_list_add(trans->add, spkg); - - return(0); -} - -static int sync_group(alpm_list_t *dbs_sync, const char *target) -{ - alpm_list_t *i, *j; - alpm_list_t *known_pkgs = NULL; - pmgrp_t *grp; - int found = 0; - - ALPM_LOG_FUNC; - - _alpm_log(PM_LOG_DEBUG, "%s package not found, searching for group...\n", target); - for(i = dbs_sync; i; i = i->next) { - pmdb_t *db = i->data; - grp = alpm_db_readgrp(db, target); - if(grp) { - found = 1; - for(j = alpm_grp_get_pkgs(grp); j; j = j->next) { - pmpkg_t *pkg = j->data; - - /* check if group member is ignored */ - if(_alpm_pkg_should_ignore(pkg)) { - int install = 0; - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, - NULL, NULL, &install); - if(install == 0) { - _alpm_log(PM_LOG_WARNING, _("skipping target: %s\n"), alpm_pkg_get_name(pkg)); - continue; - } - } - - if(sync_pkg(pkg, known_pkgs) == -1) { - if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) { - /* just skip duplicate or ignored targets */ - continue; - } else { - alpm_list_free(known_pkgs); - return(-1); - } - } - known_pkgs = alpm_list_add(known_pkgs, pkg); + if(_alpm_pkg_should_ignore(pkg)) { + ignorelist = alpm_list_add(ignorelist, pkg); + int install = 0; + QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, + NULL, NULL, &install); + if(!install) + continue; + } + if(!_alpm_pkg_find(pkgs, alpm_pkg_get_name(pkg))) { + pkgs = alpm_list_add(pkgs, pkg); } } } - alpm_list_free(known_pkgs); - - if(!found) { - /* pass through any 'found but ignored' errors */ - if(pm_errno != PM_ERR_PKG_IGNORED) { - pm_errno = PM_ERR_PKG_NOT_FOUND; - } - return(-1); - } - - return(0); -} - -static int sync_target(alpm_list_t *dbs_sync, const char *target) -{ - pmpkg_t *spkg; - pmdepend_t *dep; /* provisions and dependencies are also allowed */ - - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(target != NULL && strlen(target) != 0, RET_ERR(PM_ERR_WRONG_ARGS, -1)); - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - - dep = _alpm_splitdep(target); - spkg = _alpm_resolvedep(dep, dbs_sync, NULL, 1); - _alpm_dep_free(dep); - - if(spkg != NULL) { - return(sync_pkg(spkg, handle->trans->add)); - } - - return(sync_group(dbs_sync, target)); -} - -/** Add a sync target to the transaction. - * @param target the name of the sync target to add - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_sync_dbtarget(char *dbname, char *target) -{ - alpm_list_t *i; - alpm_list_t *dbs_sync; - - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - dbs_sync = handle->dbs_sync; - - /* we are looking for a package in a specific database */ - alpm_list_t *dbs = NULL; - _alpm_log(PM_LOG_DEBUG, "searching for target '%s' in repo '%s'\n", target, dbname); - for(i = dbs_sync; i; i = i->next) { - pmdb_t *db = i->data; - if(strcmp(db->treename, dbname) == 0) { - dbs = alpm_list_add(NULL, db); - break; - } - } - if(dbs == NULL) { - RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1); - } - int ret = sync_target(dbs, target); - alpm_list_free(dbs); - return(ret); -} - -/** Add a sync target to the transaction. - * @param target the name of the sync target to add - * @return 0 on success, -1 on error (pm_errno is set accordingly) - */ -int SYMEXPORT alpm_sync_target(char *target) -{ - alpm_list_t *dbs_sync; - - ALPM_LOG_FUNC; - - /* Sanity checks */ - ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1)); - dbs_sync = handle->dbs_sync; - - return(sync_target(dbs_sync,target)); + alpm_list_free(ignorelist); + return(pkgs); } /** Compute the size of the files that will be downloaded to install a @@ -385,7 +254,7 @@ static int compute_download_size(pmpkg_t *newpkg) char *fpath; off_t size = 0; - if(newpkg->origin == PKG_FROM_FILE) { + if(newpkg->origin != PKG_FROM_SYNCDB) { newpkg->infolevel |= INFRQ_DSIZE; newpkg->download_size = 0; return(0); @@ -464,7 +333,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* Compute the fake local database for resolvedeps (partial fix for the phonon/qt issue) */ alpm_list_t *localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(db_local), trans->add, _alpm_pkg_cmp); - /* Resolve packages in the transaction one at a time, in addtion + /* Resolve packages in the transaction one at a time, in addition building up a list of packages which could not be resolved. */ for(i = trans->add; i; i = i->next) { pmpkg_t *pkg = i->data; @@ -549,10 +418,10 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync /* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */ pmdepend_t *dep1 = _alpm_splitdep(conflict->package1); pmdepend_t *dep2 = _alpm_splitdep(conflict->package2); - if(alpm_depcmp(sync1, dep2)) { + if(_alpm_depcmp(sync1, dep2)) { rsync = sync2; sync = sync1; - } else if(alpm_depcmp(sync2, dep1)) { + } else if(_alpm_depcmp(sync2, dep1)) { rsync = sync1; sync = sync2; } else { @@ -822,7 +691,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; - int replaces = 0; + size_t numtargs, current = 0, replaces = 0; int errors = 0; const char *cachedir = NULL; int ret = -1; @@ -854,7 +723,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) for(j = trans->add; j; j = j->next) { pmpkg_t *spkg = j->data; - if(spkg->origin == PKG_FROM_CACHE && current == spkg->origin_data.db) { + if(spkg->origin != PKG_FROM_FILE && current == spkg->origin_data.db) { const char *fname = NULL; fname = alpm_pkg_get_filename(spkg); @@ -949,14 +818,18 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) } /* Check integrity of packages */ + numtargs = alpm_list_count(trans->add); EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL); errors = 0; - for(i = trans->add; i; i = i->next) { + for(i = trans->add; i; i = i->next, current++) { pmpkg_t *spkg = i->data; + int percent = (current * 100) / numtargs; if(spkg->origin == PKG_FROM_FILE) { continue; /* pkg_load() has been already called, this package is valid */ } + PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", percent, + numtargs, current); const char *filename = alpm_pkg_get_filename(spkg); const char *md5sum = alpm_pkg_get_md5sum(spkg); @@ -983,11 +856,14 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) i->data = pkgfile; _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */ } + PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", 100, + numtargs, current); + EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL); if(errors) { pm_errno = PM_ERR_PKG_INVALID; goto error; } - EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL); + if(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY) { ret = 0; goto error; @@ -1018,6 +894,19 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data) EVENT(trans, PM_TRANS_EVT_FILECONFLICTS_DONE, NULL, NULL); } + /* check available disk space */ + if(handle->checkspace) { + EVENT(trans, PM_TRANS_EVT_DISKSPACE_START, NULL, NULL); + + _alpm_log(PM_LOG_DEBUG, "checking available disk space\n"); + if(_alpm_check_diskspace(trans, handle->db_local) == -1) { + _alpm_log(PM_LOG_ERROR, _("not enough free disk space\n")); + goto error; + } + + EVENT(trans, PM_TRANS_EVT_DISKSPACE_DONE, NULL, NULL); + } + /* remove conflicting and to-be-replaced packages */ if(replaces) { _alpm_log(PM_LOG_DEBUG, "removing conflicting and to-be-replaced packages\n"); |