summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/sync.c')
-rw-r--r--lib/libalpm/sync.c235
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");