summaryrefslogtreecommitdiff
path: root/lib/libalpm/sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/sync.c')
-rw-r--r--lib/libalpm/sync.c1056
1 files changed, 438 insertions, 618 deletions
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index a927f61b..3dc54d0a 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -22,6 +22,7 @@
#include "config.h"
+#include <sys/types.h> /* off_t */
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
@@ -34,7 +35,6 @@
#include "sync.h"
#include "alpm_list.h"
#include "log.h"
-#include "error.h"
#include "package.h"
#include "db.h"
#include "cache.h"
@@ -44,10 +44,10 @@
#include "util.h"
#include "handle.h"
#include "alpm.h"
-#include "server.h"
+#include "dload.h"
#include "delta.h"
-pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data)
+pmsyncpkg_t *_alpm_sync_new(pmpkgreason_t newreason, pmpkg_t *spkg, alpm_list_t *removes)
{
pmsyncpkg_t *sync;
@@ -55,9 +55,9 @@ pmsyncpkg_t *_alpm_sync_new(int type, pmpkg_t *spkg, void *data)
CALLOC(sync, 1, sizeof(pmsyncpkg_t), RET_ERR(PM_ERR_MEMORY, NULL));
- sync->type = type;
+ sync->newreason = newreason;
sync->pkg = spkg;
- sync->data = data;
+ sync->removes = removes;
return(sync);
}
@@ -70,32 +70,11 @@ void _alpm_sync_free(pmsyncpkg_t *sync)
return;
}
- /* TODO wow this is ugly */
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- alpm_list_free_inner(sync->data, (alpm_list_fn_free)_alpm_pkg_free);
- alpm_list_free(sync->data);
- sync->data = NULL;
- } else {
- _alpm_pkg_free(sync->data);
- sync->data = NULL;
- }
+ alpm_list_free(sync->removes);
+ sync->removes = NULL;
FREE(sync);
}
-static void synclist_free(alpm_list_t *syncpkgs)
-{
- if(syncpkgs) {
- alpm_list_t *tmp;
- for(tmp = syncpkgs; tmp; tmp = alpm_list_next(tmp)) {
- if(tmp->data) {
- _alpm_sync_free(tmp->data);
- }
- }
- alpm_list_free(syncpkgs);
- }
-
-}
-
/* Find recommended replacements for packages during a sync.
*/
static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,
@@ -147,27 +126,29 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,
* the package to replace.
*/
pmsyncpkg_t *sync;
- pmpkg_t *dummy = _alpm_pkg_dup(lpkg);
- if(dummy == NULL) {
- pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
- return(-1);
- }
+
/* check if spkg->name is already in the packages list. */
+ /* TODO: same package name doesn't mean same package */
sync = _alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg));
if(sync) {
- /* found it -- just append to the replaces list */
- sync->data = alpm_list_add(sync->data, dummy);
+ /* found it -- just append to the removes list */
+ sync->removes = alpm_list_add(sync->removes, lpkg);
+ /* check the to-be-replaced package's reason field */
+ if(lpkg->reason == PM_PKG_REASON_EXPLICIT) {
+ sync->newreason = PM_PKG_REASON_EXPLICIT;
+ }
} else {
/* none found -- enter pkg into the final sync list */
- sync = _alpm_sync_new(PM_SYNC_TYPE_REPLACE, spkg, NULL);
+ /* copy over reason */
+ sync = _alpm_sync_new(alpm_pkg_get_reason(lpkg), spkg, NULL);
if(sync == NULL) {
- _alpm_pkg_free(dummy);
pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
+ alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free);
+ alpm_list_free(*syncpkgs);
+ *syncpkgs = NULL;
return(-1);
}
- sync->data = alpm_list_add(NULL, dummy);
+ sync->removes = alpm_list_add(NULL, lpkg);
*syncpkgs = alpm_list_add(*syncpkgs, sync);
}
_alpm_log(PM_LOG_DEBUG, "%s-%s elected for removal (to be replaced by %s-%s)\n",
@@ -180,6 +161,35 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,
return(0);
}
+/** Check for new version of pkg in sync repos
+ * (only the first occurrence is considered in sync)
+ */
+pmpkg_t SYMEXPORT *alpm_sync_newversion(pmpkg_t *pkg, alpm_list_t *dbs_sync)
+{
+ alpm_list_t *i;
+ pmpkg_t *spkg = NULL;
+
+ for(i = dbs_sync; !spkg && i; i = i->next) {
+ spkg = _alpm_db_get_pkgfromcache(i->data, alpm_pkg_get_name(pkg));
+ }
+
+ if(spkg == NULL) {
+ _alpm_log(PM_LOG_DEBUG, "'%s' not found in sync db => no upgrade\n",
+ alpm_pkg_get_name(pkg));
+ return(NULL);
+ }
+
+ /* compare versions and see if spkg is an upgrade */
+ if(_alpm_pkg_compare_versions(pkg, spkg)) {
+ _alpm_log(PM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n",
+ alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg),
+ alpm_pkg_get_version(spkg));
+ return(spkg);
+ } else {
+ return(NULL);
+ }
+}
+
/** Get a list of upgradable packages on the current system
* Adds out of date packages to *list.
* @arg list pointer to a list of pmsyncpkg_t.
@@ -193,7 +203,7 @@ int SYMEXPORT alpm_sync_sysupgrade(pmdb_t *db_local,
int _alpm_sync_sysupgrade(pmtrans_t *trans,
pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **syncpkgs)
{
- alpm_list_t *i, *j;
+ alpm_list_t *i, *j, *replaced = NULL;
ALPM_LOG_FUNC;
@@ -205,76 +215,61 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans,
return(-1);
}
- /* match installed packages with the sync dbs and compare versions */
+ /* compute the to-be-replaced packages for efficiency */
+ for(i = *syncpkgs; i; i = i->next) {
+ pmsyncpkg_t *sync = i->data;
+ for(j = sync->removes; j; j = j->next) {
+ replaced = alpm_list_add(replaced, j->data);
+ }
+ }
+
+ /* for all not-replaced local package we check for upgrade */
_alpm_log(PM_LOG_DEBUG, "checking for package upgrades\n");
for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) {
- int replace = 0;
pmpkg_t *local = i->data;
- pmpkg_t *spkg = NULL;
- pmsyncpkg_t *sync;
-
- for(j = dbs_sync; !spkg && j; j = j->next) {
- spkg = _alpm_db_get_pkgfromcache(j->data, alpm_pkg_get_name(local));
- }
- if(spkg == NULL) {
- _alpm_log(PM_LOG_DEBUG, "'%s' not found in sync db -- skipping\n",
- alpm_pkg_get_name(local));
- continue;
- }
- /* we don't care about a to-be-replaced package's newer version */
- for(j = *syncpkgs; j && !replace; j=j->next) {
- sync = j->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- if(_alpm_pkg_find(alpm_pkg_get_name(spkg), sync->data)) {
- replace = 1;
- }
- }
- }
- if(replace) {
+ if(_alpm_pkg_find(replaced, alpm_pkg_get_name(local))) {
_alpm_log(PM_LOG_DEBUG, "'%s' is already elected for removal -- skipping\n",
alpm_pkg_get_name(local));
continue;
}
- /* compare versions and see if we need to upgrade */
- if(_alpm_pkg_compare_versions(local, spkg)) {
- _alpm_log(PM_LOG_DEBUG, "%s elected for upgrade (%s => %s)\n",
- alpm_pkg_get_name(local), alpm_pkg_get_version(local),
- alpm_pkg_get_version(spkg));
- if(!_alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg))) {
- /* If package is in the ignorepkg list, skip it */
- if(_alpm_pkg_should_ignore(spkg)) {
- _alpm_log(PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"),
- alpm_pkg_get_name(local), alpm_pkg_get_version(local),
- alpm_pkg_get_version(spkg));
- continue;
- }
+ pmpkg_t *spkg = alpm_sync_newversion(local, dbs_sync);
+ if(spkg) {
+ /* we found a new version */
+ /* skip packages in IgnorePkg or in IgnoreGroup */
+ if(_alpm_pkg_should_ignore(spkg)) {
+ _alpm_log(PM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"),
+ alpm_pkg_get_name(local), alpm_pkg_get_version(local),
+ alpm_pkg_get_version(spkg));
+ continue;
+ }
- pmpkg_t *tmp = _alpm_pkg_dup(local);
- if(tmp == NULL) {
- pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
- return(-1);
- }
- sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, tmp);
- if(sync == NULL) {
- _alpm_pkg_free(tmp);
- pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
- return(-1);
- }
- *syncpkgs = alpm_list_add(*syncpkgs, sync);
+ /* add the upgrade package to our pmsyncpkg_t list */
+ if(_alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg))) {
+ /* avoid duplicated targets */
+ continue;
}
+ /* we can set any reason here, it will be overridden by add_commit */
+ pmsyncpkg_t *sync = _alpm_sync_new(PM_PKG_REASON_EXPLICIT, spkg, NULL);
+ if(sync == NULL) {
+ alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free);
+ alpm_list_free(*syncpkgs);
+ *syncpkgs = NULL;
+ alpm_list_free(replaced);
+ return(-1);
+ }
+ *syncpkgs = alpm_list_add(*syncpkgs, sync);
}
}
+ alpm_list_free(replaced);
return(0);
}
int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name)
{
- char targline[PKG_FULLNAME_LEN];
+ char *targline;
char *targ;
alpm_list_t *j;
pmpkg_t *local;
@@ -287,8 +282,8 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ STRDUP(targline, name, RET_ERR(PM_ERR_MEMORY, -1));
- strncpy(targline, name, PKG_FULLNAME_LEN);
targ = strchr(targline, '/');
if(targ) {
/* we are looking for a package in a specific database */
@@ -301,13 +296,15 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
repo_found = 1;
spkg = _alpm_db_get_pkgfromcache(db, targ);
if(spkg == NULL) {
- RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_NOT_FOUND;
+ goto error;
}
}
}
if(!repo_found) {
_alpm_log(PM_LOG_ERROR, _("repository '%s' not found\n"), targline);
- RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_REPO_NOT_FOUND;
+ goto error;
}
} else {
targ = targline;
@@ -316,10 +313,16 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
spkg = _alpm_db_get_pkgfromcache(db, targ);
}
if(spkg == NULL) {
- RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_NOT_FOUND;
+ goto error;
}
}
+ if(_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) {
+ FREE(targline);
+ RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1);
+ }
+
if(_alpm_pkg_should_ignore(spkg)) {
int resp;
QUESTION(trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, spkg, NULL, NULL, &resp);
@@ -346,39 +349,80 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
}
/* add the package to the transaction */
- if(!_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) {
- pmpkg_t *dummy = NULL;
- if(local) {
- dummy = _alpm_pkg_dup(local);
- if(dummy == NULL) {
- RET_ERR(PM_ERR_MEMORY, -1);
- }
- }
- sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, dummy);
- if(sync == NULL) {
- _alpm_pkg_free(dummy);
- RET_ERR(PM_ERR_MEMORY, -1);
- }
- _alpm_log(PM_LOG_DEBUG, "adding target '%s' to the transaction set\n",
- alpm_pkg_get_name(spkg));
- trans->packages = alpm_list_add(trans->packages, sync);
+ sync = _alpm_sync_new(PM_PKG_REASON_EXPLICIT, spkg, NULL);
+ if(sync == NULL) {
+ goto error;
}
+ _alpm_log(PM_LOG_DEBUG, "adding target '%s' to the transaction set\n",
+ alpm_pkg_get_name(spkg));
+ trans->packages = alpm_list_add(trans->packages, sync);
+ FREE(targline);
return(0);
+
+error:
+ if(targline) {
+ FREE(targline);
+ }
+ return(-1);
}
/* Helper functions for alpm_list_remove
- */
+*/
static int syncpkg_cmp(const void *s1, const void *s2)
{
const pmsyncpkg_t *sp1 = s1;
const pmsyncpkg_t *sp2 = s2;
- pmpkg_t *p1, *p2;
+ pmpkg_t *p1 = alpm_sync_get_pkg(sp1);
+ pmpkg_t *p2 = alpm_sync_get_pkg(sp2);
+ return(strcmp(alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)));
+}
+
+/** Compute the size of the files that will be downloaded to install a
+ * package.
+ * @param newpkg the new package to upgrade to
+ */
+static int compute_download_size(pmpkg_t *newpkg)
+{
+ const char *fname;
+ char *fpath;
+ off_t size = 0;
- p1 = alpm_sync_get_pkg(sp1);
- p2 = alpm_sync_get_pkg(sp2);
+ fname = alpm_pkg_get_filename(newpkg);
+ ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1));
+ fpath = _alpm_filecache_find(fname);
- return(strcmp(alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)));
+ if(fpath) {
+ FREE(fpath);
+ size = 0;
+ } else if(handle->usedelta) {
+ off_t dltsize;
+ off_t pkgsize = alpm_pkg_get_size(newpkg);
+
+ dltsize = _alpm_shortest_delta_path(
+ alpm_pkg_get_deltas(newpkg),
+ alpm_pkg_get_filename(newpkg),
+ alpm_pkg_get_md5sum(newpkg),
+ &newpkg->delta_path);
+
+ if(newpkg->delta_path && (dltsize < pkgsize * MAX_DELTA_RATIO)) {
+ _alpm_log(PM_LOG_DEBUG, "using delta size\n");
+ size = dltsize;
+ } else {
+ _alpm_log(PM_LOG_DEBUG, "using package size\n");
+ size = alpm_pkg_get_size(newpkg);
+ alpm_list_free(newpkg->delta_path);
+ newpkg->delta_path = NULL;
+ }
+ } else {
+ size = alpm_pkg_get_size(newpkg);
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "setting download size %lld for pkg %s\n",
+ (long long)size, alpm_pkg_get_name(newpkg));
+
+ newpkg->download_size = size;
+ return(0);
}
int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data)
@@ -397,14 +441,15 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
*data = NULL;
}
- if(!(trans->flags & PM_TRANS_FLAG_DEPENDSONLY)) {
- for(i = trans->packages; i; i = i->next) {
- pmsyncpkg_t *sync = i->data;
- list = alpm_list_add(list, sync->pkg);
- }
+ for(i = trans->packages; i; i = i->next) {
+ pmsyncpkg_t *sync = i->data;
+ list = alpm_list_add(list, sync->pkg);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
+ /* store a pointer to the last original target so we can tell what was
+ * pulled by resolvedeps */
+ alpm_list_t *pulled = alpm_list_last(list);
/* Resolve targets dependencies */
EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "resolving target's dependencies\n");
@@ -412,10 +457,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
/* build remove list for resolvedeps */
for(i = trans->packages; i; i = i->next) {
pmsyncpkg_t *sync = i->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- for(j = sync->data; j; j = j->next) {
- remove = alpm_list_add(remove, j->data);
- }
+ for(j = sync->removes; j; j = j->next) {
+ remove = alpm_list_add(remove, j->data);
}
}
@@ -429,33 +472,27 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
}
}
- if((trans->flags & PM_TRANS_FLAG_DEPENDSONLY)) {
- FREELIST(trans->packages);
- }
-
- for(i = list; i; i = i->next) {
- /* add the dependencies found by resolvedeps to the transaction set */
+ for(i = pulled->next; i; i = i->next) {
pmpkg_t *spkg = i->data;
- if(!_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) {
- pmsyncpkg_t *sync = _alpm_sync_new(PM_SYNC_TYPE_DEPEND, spkg, NULL);
- if(sync == NULL) {
- ret = -1;
- goto cleanup;
- }
- trans->packages = alpm_list_add(trans->packages, sync);
- _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
- alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg));
+ pmsyncpkg_t *sync = _alpm_sync_new(PM_PKG_REASON_DEPEND, spkg, NULL);
+ if(sync == NULL) {
+ ret = -1;
+ goto cleanup;
}
+ trans->packages = alpm_list_add(trans->packages, sync);
+ _alpm_log(PM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n",
+ alpm_pkg_get_name(spkg), alpm_pkg_get_version(spkg));
}
/* re-order w.r.t. dependencies */
- alpm_list_t *sortlist = _alpm_sortbydeps(list, PM_TRANS_TYPE_ADD);
+ alpm_list_t *sortlist = _alpm_sortbydeps(list, 0);
alpm_list_t *newpkgs = NULL;
for(i = sortlist; i; i = i->next) {
for(j = trans->packages; j; j = j->next) {
pmsyncpkg_t *s = j->data;
if(s->pkg == i->data) {
newpkgs = alpm_list_add(newpkgs, s);
+ break;
}
}
}
@@ -472,180 +509,130 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "looking for conflicts\n");
- deps = _alpm_checkconflicts(db_local, list);
- if(deps) {
- int errorout = 0;
- alpm_list_t *asked = NULL;
- pmconflict_t *conflict = NULL;
-
- for(i = deps; i && !errorout; i = i->next) {
- pmsyncpkg_t *sync;
- pmpkg_t *found = NULL;
-
- conflict = i->data;
- _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
- conflict->package1, conflict->package2);
- /* check if the conflicting package is about to be removed/replaced.
- * if so, then just ignore it. */
- for(j = trans->packages; j && !found; j = j->next) {
- sync = j->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- found = _alpm_pkg_find(conflict->package2, sync->data);
- }
- }
- if(found) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is already elected for removal -- skipping\n",
- alpm_pkg_get_name(found));
- continue;
- }
- sync = _alpm_sync_find(trans->packages, conflict->package1);
- if(sync == NULL) {
- _alpm_log(PM_LOG_DEBUG, "'%s' not found in transaction set -- skipping\n",
- conflict->package1);
- continue;
- }
- pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
- /* check if this package provides the package it's conflicting with */
- if(alpm_list_find(alpm_pkg_get_provides(sync->pkg),
- conflict->package2, _alpm_prov_cmp)) {
- /* treat like a replaces item so requiredby fields are
- * inherited properly. */
- _alpm_log(PM_LOG_DEBUG, "package '%s' provides its own conflict\n",
- conflict->package1);
- if(!local) {
- char *rmpkg = NULL;
- void *target, *depend;
- /* hmmm, package2 isn't installed, so it must be conflicting
- * with another package in our final list. For example:
- *
- * pacman -S blackbox xfree86
- *
- * If no x-servers are installed and blackbox pulls in xorg, then
- * xorg and xfree86 will conflict with each other. In this case,
- * we should follow the user's preference and rip xorg out of final,
- * opting for xfree86 instead.
- */
-
- /* figure out which one was requested in targets. If they both
- * were, then it's still an unresolvable conflict. */
- target = alpm_list_find_str(trans->targets, conflict->package1);
- depend = alpm_list_find_str(trans->targets, conflict->package2);
- if(depend && !target) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n",
- conflict->package2);
- /* remove conflict->package1 */
- rmpkg = conflict->package1;
- } else if(target && !depend) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n",
- conflict->package1);
- /* remove conflict->package2 */
- rmpkg = conflict->package2;
- } else {
- /* miss->target2 is not needed, miss->target already provides
- * it, let's resolve the conflict */
- rmpkg = conflict->package2;
- }
- if(rmpkg) {
- pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages, rmpkg);
- if(rsync) {
- void *vpkg;
- _alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n",
- rsync->pkg->name);
- trans->packages = alpm_list_remove(trans->packages, rsync,
- syncpkg_cmp, &vpkg);
- _alpm_sync_free(vpkg);
- }
- continue;
- }
+ /* 1. check for conflicts in the target list */
+ _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n");
+ deps = _alpm_innerconflicts(list);
+
+ for(i = deps; i; i = i->next) {
+ pmconflict_t *conflict = i->data;
+ pmsyncpkg_t *rsync, *sync, *sync1, *sync2;
+
+ /* have we already removed one of the conflicting targets? */
+ sync1 = _alpm_sync_find(trans->packages, conflict->package1);
+ sync2 = _alpm_sync_find(trans->packages, conflict->package2);
+ if(!sync1 || !sync2) {
+ continue;
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n",
+ conflict->package1, conflict->package2);
+
+ /* 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->pkg, dep2)) {
+ rsync = sync2;
+ sync = sync1;
+ } else if(alpm_depcmp(sync2->pkg, dep1)) {
+ rsync = sync1;
+ sync = sync2;
+ } else {
+ _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
+ pm_errno = PM_ERR_CONFLICTING_DEPS;
+ ret = -1;
+ if(data) {
+ pmconflict_t *newconflict = _alpm_conflict_dup(conflict);
+ if(newconflict) {
+ *data = alpm_list_add(*data, newconflict);
}
}
- /* It's a conflict -- see if they want to remove it */
- _alpm_log(PM_LOG_DEBUG, "resolving package '%s' conflict\n",
- conflict->package1);
- if(local) {
- int doremove = 0;
- if(!alpm_list_find_str(asked, conflict->package2)) {
- QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
- conflict->package2, NULL, &doremove);
- asked = alpm_list_add(asked, strdup(conflict->package2));
- if(doremove) {
- pmpkg_t *q = _alpm_pkg_dup(local);
- if(sync->type != PM_SYNC_TYPE_REPLACE) {
- /* switch this sync type to REPLACE */
- sync->type = PM_SYNC_TYPE_REPLACE;
- _alpm_pkg_free(sync->data);
- sync->data = NULL;
- }
- /* append to the replaces list */
- _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n",
- conflict->package2);
- sync->data = alpm_list_add(sync->data, q);
- /* see if the package is in the current target list */
- pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages,
- conflict->package2);
- if(rsync) {
- /* remove it from the target list */
- void *vpkg;
- _alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n",
- conflict->package2);
- trans->packages = alpm_list_remove(trans->packages, rsync,
- syncpkg_cmp, &vpkg);
- _alpm_sync_free(vpkg);
- }
- } else {
- /* abort */
- _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
- errorout = 1;
- }
- }
- } else {
- _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
- errorout = 1;
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
+ _alpm_dep_free(dep1);
+ _alpm_dep_free(dep2);
+ goto cleanup;
+ }
+ _alpm_dep_free(dep1);
+ _alpm_dep_free(dep2);
+
+ /* Prints warning */
+ _alpm_log(PM_LOG_WARNING,
+ _("removing '%s' from target list because it conflicts with '%s'\n"),
+ rsync->pkg->name, sync->pkg->name);
+ void *vpkg;
+ trans->packages = alpm_list_remove(trans->packages, rsync,
+ syncpkg_cmp, &vpkg);
+ pmsyncpkg_t *syncpkg = vpkg;
+ list = alpm_list_remove(list, syncpkg->pkg, _alpm_pkg_cmp, NULL);
+ _alpm_sync_free(syncpkg);
+ continue;
+ }
+
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
+ deps = NULL;
+
+ /* 2. we check for target vs db conflicts (and resolve)*/
+ _alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n");
+ deps = _alpm_outerconflicts(db_local, list);
+
+ for(i = deps; i; i = i->next) {
+ pmconflict_t *conflict = i->data;
+
+ /* if conflict->package2 (the local package) is not elected for removal,
+ we ask the user */
+ int found = 0;
+ for(j = trans->packages; j && !found; j = j->next) {
+ pmsyncpkg_t *sync = j->data;
+ if(_alpm_pkg_find(sync->removes, conflict->package2)) {
+ found = 1;
}
}
- if(errorout) {
- /* The last conflict was unresolvable, so we duplicate it and add it to *data */
+ if(found) {
+ continue;
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
+ conflict->package1, conflict->package2);
+
+ pmsyncpkg_t *sync = _alpm_sync_find(trans->packages, conflict->package1);
+ pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
+ int doremove = 0;
+ QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
+ conflict->package2, NULL, &doremove);
+ if(doremove) {
+ /* append to the removes list */
+ _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2);
+ sync->removes = alpm_list_add(sync->removes, local);
+ } else { /* abort */
+ _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
pm_errno = PM_ERR_CONFLICTING_DEPS;
+ ret = -1;
if(data) {
- pmconflict_t *lastconflict = conflict;
- if((conflict = malloc(sizeof(pmconflict_t))) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %zd bytes\n"),
- sizeof(pmconflict_t));
- FREELIST(*data);
- pm_errno = PM_ERR_MEMORY;
- } else {
- *conflict = *lastconflict;
- *data = alpm_list_add(*data, conflict);
+ pmconflict_t *newconflict = _alpm_conflict_dup(conflict);
+ if(newconflict) {
+ *data = alpm_list_add(*data, newconflict);
}
}
- FREELIST(asked);
- FREELIST(deps);
- ret = -1;
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
goto cleanup;
}
- FREELIST(asked);
- FREELIST(deps);
}
EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL);
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
- /* rebuild remove and list */
- alpm_list_free(list);
- list = NULL;
- for(i = trans->packages; i; i = i->next) {
- pmsyncpkg_t *sync = i->data;
- list = alpm_list_add(list, sync->pkg);
- }
+ /* rebuild remove list */
alpm_list_free(remove);
remove = NULL;
for(i = trans->packages; i; i = i->next) {
pmsyncpkg_t *sync = i->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- for(j = sync->data; j; j = j->next) {
- remove = alpm_list_add(remove, j->data);
- }
+ for(j = sync->removes; j; j = j->next) {
+ remove = alpm_list_add(remove, j->data);
}
}
@@ -657,11 +644,20 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
if(data) {
*data = deps;
} else {
- FREELIST(deps);
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(deps);
}
goto cleanup;
}
}
+ for(i = list; i; i = i->next) {
+ /* update download size field */
+ pmpkg_t *spkg = i->data;
+ if(compute_download_size(spkg) != 0) {
+ ret = -1;
+ goto cleanup;
+ }
+ }
cleanup:
alpm_list_free(list);
@@ -670,86 +666,14 @@ cleanup:
return(ret);
}
-/** Returns a list of deltas that should be downloaded instead of the
- * package.
- *
- * It first tests if a delta path exists between the currently installed
- * version (if any) and the version to upgrade to. If so, the delta path
- * is used if its size is below a set percentage (MAX_DELTA_RATIO) of
- * the package size, Otherwise, an empty list is returned.
- *
- * @param newpkg the new package to upgrade to
- * @param db_local the local database
- *
- * @return the list of pmdelta_t * objects. NULL (the empty list) is
- * returned if the package should be downloaded instead of deltas.
- */
-static alpm_list_t *pkg_upgrade_delta_path(pmpkg_t *newpkg, pmdb_t *db_local)
-{
- pmpkg_t *oldpkg = alpm_db_get_pkg(db_local, newpkg->name);
- alpm_list_t *ret = NULL;
-
- if(oldpkg) {
- const char *oldname = alpm_pkg_get_filename(oldpkg);
- char *oldpath = _alpm_filecache_find(oldname);
-
- if(oldpath) {
- alpm_list_t *deltas = _alpm_shortest_delta_path(
- alpm_pkg_get_deltas(newpkg),
- alpm_pkg_get_version(oldpkg),
- alpm_pkg_get_version(newpkg));
-
- if(deltas) {
- unsigned long dltsize = _alpm_delta_path_size(deltas);
- unsigned long pkgsize = alpm_pkg_get_size(newpkg);
-
- if(dltsize < pkgsize * MAX_DELTA_RATIO) {
- ret = deltas;
- } else {
- ret = NULL;
- alpm_list_free(deltas);
- }
- }
-
- FREE(oldpath);
- }
- }
-
- return(ret);
-}
-
/** Returns the size of the files that will be downloaded to install a
* package.
- *
* @param newpkg the new package to upgrade to
- * @param db_local the local database
- *
* @return the size of the download
*/
-unsigned long SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg, pmdb_t *db_local)
+off_t SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg)
{
- char *fpath = _alpm_filecache_find(alpm_pkg_get_filename(newpkg));
- unsigned long size = 0;
-
- if(fpath) {
- size = 0;
- } else if(handle->usedelta) {
- alpm_list_t *deltas = pkg_upgrade_delta_path(newpkg, db_local);
-
- if(deltas) {
- size = _alpm_delta_path_size_uncached(deltas);
- } else {
- size = alpm_pkg_get_size(newpkg);
- }
-
- alpm_list_free(deltas);
- } else {
- size = alpm_pkg_get_size(newpkg);
- }
-
- FREE(fpath);
-
- return(size);
+ return(newpkg->download_size);
}
/** Applies delta files to create an upgraded package file.
@@ -758,88 +682,82 @@ unsigned long SYMEXPORT alpm_pkg_download_size(pmpkg_t *newpkg, pmdb_t *db_local
* ending package files.
*
* @param trans the transaction
- * @param patches A list of alternating pmpkg_t * and pmdelta_t *
- * objects. The patch command will be built using the pmpkg_t, pmdelta_t
- * pair.
*
* @return 0 if all delta files were able to be applied, 1 otherwise.
*/
-static int apply_deltas(pmtrans_t *trans, alpm_list_t *patches)
+static int apply_deltas(pmtrans_t *trans)
{
- /* keep track of the previous package in the loop to decide if a
- * package file should be deleted */
- pmpkg_t *lastpkg = NULL;
- int lastpkg_failed = 0;
+ alpm_list_t *i;
int ret = 0;
const char *cachedir = _alpm_filecache_setup();
- alpm_list_t *p = patches;
- while(p) {
- pmpkg_t *pkg;
- pmdelta_t *d;
- char command[PATH_MAX], fname[PATH_MAX];
- char pkgfilename[PKG_FILENAME_LEN];
+ for(i = trans->packages; i; i = i->next) {
+ pmsyncpkg_t *sync = i->data;
+ pmpkg_t *spkg = sync->pkg;
+ alpm_list_t *delta_path = spkg->delta_path;
+ alpm_list_t *dlts = NULL;
- pkg = alpm_list_getdata(p);
- p = alpm_list_next(p);
+ if(!delta_path) {
+ continue;
+ }
- d = alpm_list_getdata(p);
- p = alpm_list_next(p);
+ for(dlts = delta_path; dlts; dlts = dlts->next) {
+ pmdelta_t *d = dlts->data;
+ char *delta, *from, *to;
+ char command[PATH_MAX];
+ int len = 0;
- /* if patching fails, ignore the rest of that package's deltas */
- if(lastpkg_failed) {
- if(pkg == lastpkg) {
- continue;
+ delta = _alpm_filecache_find(d->delta);
+ /* the initial package might be in a different cachedir */
+ if(dlts == delta_path) {
+ from = _alpm_filecache_find(d->from);
} else {
- lastpkg_failed = 0;
+ /* len = cachedir len + from len + '/' + null */
+ len = strlen(cachedir) + strlen(d->from) + 2;
+ CALLOC(from, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1));
+ snprintf(from, len, "%s/%s", cachedir, d->from);
}
- }
+ len = strlen(cachedir) + strlen(d->to) + 2;
+ CALLOC(to, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1));
+ snprintf(to, len, "%s/%s", cachedir, d->to);
- /* an example of the patch command: (using /cache for cachedir)
- * xdelta patch /cache/pacman_3.0.0-1_to_3.0.1-1-i686.delta \
- * /cache/pacman-3.0.0-1-i686.pkg.tar.gz \
- * /cache/pacman-3.0.1-1-i686.pkg.tar.gz
- */
-
- /* build the patch command */
- snprintf(command, PATH_MAX,
- "xdelta patch" /* the command */
- " %s/%s" /* the delta */
- " %s/%s-%s-%s" PKGEXT /* the 'from' package */
- " %s/%s-%s-%s" PKGEXT, /* the 'to' package */
- cachedir, d->filename,
- cachedir, pkg->name, d->from, pkg->arch,
- cachedir, pkg->name, d->to, pkg->arch);
-
- _alpm_log(PM_LOG_DEBUG, _("command: %s\n"), command);
-
- snprintf(pkgfilename, PKG_FILENAME_LEN, "%s-%s-%s" PKGEXT,
- pkg->name, d->to, pkg->arch);
-
- EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_START, pkgfilename, d->filename);
-
- if(system(command) == 0) {
- EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_DONE, NULL, NULL);
-
- /* delete the delta file */
- snprintf(fname, PATH_MAX, "%s/%s", cachedir, d->filename);
- unlink(fname);
-
- /* Delete the 'from' package but only if it is an intermediate
- * package. The starting 'from' package should be kept, just
- * as if deltas were not used. Delete the package file if the
- * previous iteration of the loop used the same package. */
- if(pkg == lastpkg) {
- snprintf(fname, PATH_MAX, "%s/%s-%s-%s" PKGEXT,
- cachedir, pkg->name, d->from, pkg->arch);
- unlink(fname);
- } else {
- lastpkg = pkg;
+ /* an example of the patch command: (using /cache for cachedir)
+ * xdelta patch /path/to/pacman_3.0.0-1_to_3.0.1-1-i686.delta \
+ * /path/to/pacman-3.0.0-1-i686.pkg.tar.gz \
+ * /cache/pacman-3.0.1-1-i686.pkg.tar.gz
+ */
+
+ /* build the patch command */
+ snprintf(command, PATH_MAX, "xdelta patch %s %s %s", delta, from, to);
+
+ _alpm_log(PM_LOG_DEBUG, _("command: %s\n"), command);
+
+ EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_START, d->to, d->delta);
+
+ int retval = system(command);
+ if(retval == 0) {
+ EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_DONE, NULL, NULL);
+
+ /* delete the delta file */
+ unlink(delta);
+
+ /* Delete the 'from' package but only if it is an intermediate
+ * package. The starting 'from' package should be kept, just
+ * as if deltas were not used. */
+ if(dlts != delta_path) {
+ unlink(from);
+ }
+ }
+ FREE(from);
+ FREE(to);
+ FREE(delta);
+
+ if(retval != 0) {
+ /* one delta failed for this package, cancel the remaining ones */
+ EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_FAILED, NULL, NULL);
+ ret = 1;
+ break;
}
- } else {
- EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_FAILED, NULL, NULL);
- lastpkg_failed = 1;
- ret = 1;
}
}
@@ -854,107 +772,29 @@ static int apply_deltas(pmtrans_t *trans, alpm_list_t *patches)
* @param trans the transaction
* @param filename the filename of the file to test
* @param md5sum the expected md5sum of the file
- * @param data data to write the error messages to
*
- * @return 0 if the md5sum matched, 1 otherwise
+ * @return 0 if the md5sum matched, 1 if not, -1 in case of errors
*/
static int test_md5sum(pmtrans_t *trans, const char *filename,
- const char *md5sum, alpm_list_t **data)
+ const char *md5sum)
{
char *filepath;
- char *md5sum2;
- char *errormsg = NULL;
- int ret = 0;
+ int ret;
filepath = _alpm_filecache_find(filename);
- md5sum2 = alpm_get_md5sum(filepath);
- if(md5sum == NULL) {
- if(data) {
- /* TODO wtf is this? malloc'd strings for error messages? */
- if((errormsg = calloc(512, sizeof(char))) == NULL) {
- RET_ERR(PM_ERR_MEMORY, -1);
- }
- snprintf(errormsg, 512, _("can't get md5 checksum for file %s\n"),
- filename);
- *data = alpm_list_add(*data, errormsg);
- }
- ret = 1;
- } else if(md5sum2 == NULL) {
- if(data) {
- if((errormsg = calloc(512, sizeof(char))) == NULL) {
- RET_ERR(PM_ERR_MEMORY, -1);
- }
- snprintf(errormsg, 512, _("can't get md5 checksum for file %s\n"),
- filename);
- *data = alpm_list_add(*data, errormsg);
- }
- ret = 1;
- } else if(strcmp(md5sum, md5sum2) != 0) {
+ ret = _alpm_test_md5sum(filepath, md5sum);
+
+ if(ret == 1) {
int doremove = 0;
QUESTION(trans, PM_TRANS_CONV_CORRUPTED_PKG, (char *)filename,
NULL, NULL, &doremove);
if(doremove) {
unlink(filepath);
}
- if(data) {
- if((errormsg = calloc(512, sizeof(char))) == NULL) {
- RET_ERR(PM_ERR_MEMORY, -1);
- }
- snprintf(errormsg, 512, _("file %s was corrupted (bad MD5 checksum)\n"),
- filename);
- *data = alpm_list_add(*data, errormsg);
- }
- ret = 1;
}
FREE(filepath);
- FREE(md5sum2);
-
- return(ret);
-}
-
-/** Compares the md5sum of a delta to the expected value.
- *
- * @param trans the transaction
- * @param delta the delta to test
- * @param data data to write the error messages to
- *
- * @return 0 if the md5sum matched, 1 otherwise
- */
-static int test_delta_md5sum(pmtrans_t *trans, pmdelta_t *delta,
- alpm_list_t **data)
-{
- const char *filename;
- const char *md5sum;
- int ret = 0;
-
- filename = alpm_delta_get_filename(delta);
- md5sum = alpm_delta_get_md5sum(delta);
-
- ret = test_md5sum(trans, filename, md5sum, data);
-
- return(ret);
-}
-
-/** Compares the md5sum of a package to the expected value.
- *
- * @param trans the transaction
- * @param pkg the package to test
- * @param data data to write the error messages to
- *
- * @return 0 if the md5sum matched, 1 otherwise
- */
-static int test_pkg_md5sum(pmtrans_t *trans, pmpkg_t *pkg, alpm_list_t **data)
-{
- const char *filename;
- const char *md5sum;
- int ret = 0;
-
- filename = alpm_pkg_get_filename(pkg);
- md5sum = alpm_pkg_get_md5sum(pkg);
-
- ret = test_md5sum(trans, filename, md5sum, data);
return(ret);
}
@@ -962,26 +802,32 @@ static int test_pkg_md5sum(pmtrans_t *trans, pmpkg_t *pkg, alpm_list_t **data)
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 *patches = NULL, *deltas = NULL;
+ alpm_list_t *deltas = NULL;
pmtrans_t *tr = NULL;
- int replaces = 0, retval = 0;
+ int replaces = 0;
+ int errors = 0;
const char *cachedir = NULL;
- int dltotal = 0, dl = 0;
+ int ret = -1;
ALPM_LOG_FUNC;
- ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
cachedir = _alpm_filecache_setup();
trans->state = STATE_DOWNLOADING;
- /* Sum up the download sizes. This has to be in its own loop because
- * the download loop is grouped by db. */
- for(j = trans->packages; j; j = j->next) {
- pmsyncpkg_t *sync = j->data;
- pmpkg_t *spkg = sync->pkg;
- dltotal += alpm_pkg_download_size(spkg, db_local);
+ /* Total progress - figure out the total download size if required to
+ * pass to the callback. This function is called once, and it is up to the
+ * frontend to compute incremental progress. */
+ if(handle->totaldlcb) {
+ off_t total_size = (off_t)0;
+ /* sum up the download size for each package and store total */
+ for(i = trans->packages; i; i = i->next) {
+ pmsyncpkg_t *sync = i->data;
+ pmpkg_t *spkg = sync->pkg;
+ total_size += spkg->download_size;
+ }
+ handle->totaldlcb(total_size);
}
/* group sync records by repository and download */
@@ -997,60 +843,45 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
const char *fname = NULL;
fname = alpm_pkg_get_filename(spkg);
+ ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1));
if(trans->flags & PM_TRANS_FLAG_PRINTURIS) {
EVENT(trans, PM_TRANS_EVT_PRINTURI, (char *)alpm_db_get_url(current),
(char *)fname);
} else {
- char *fpath = _alpm_filecache_find(fname);
- if(!fpath) {
- if(handle->usedelta) {
- alpm_list_t *delta_path = pkg_upgrade_delta_path(spkg, db_local);
-
- if(delta_path) {
- alpm_list_t *dlts = NULL;
-
- for(dlts = delta_path; dlts; dlts = alpm_list_next(dlts)) {
- pmdelta_t *d = (pmdelta_t *)alpm_list_getdata(dlts);
- char *fpath2 = _alpm_filecache_find(d->filename);
-
- if(!fpath2) {
- /* add the delta filename to the download list if
- * it's not in the cache*/
- files = alpm_list_add(files, strdup(d->filename));
- }
-
- /* save the package and delta so that the xdelta patch
- * command can be run after the downloads finish */
- patches = alpm_list_add(patches, spkg);
- patches = alpm_list_add(patches, d);
-
- /* keep a list of the delta files for md5sums */
- deltas = alpm_list_add(deltas, d);
+ if(spkg->download_size != 0) {
+ alpm_list_t *delta_path = spkg->delta_path;
+ if(delta_path) {
+ alpm_list_t *dlts = NULL;
+
+ for(dlts = delta_path; dlts; dlts = dlts->next) {
+ pmdelta_t *d = dlts->data;
+
+ if(d->download_size != 0) {
+ /* add the delta filename to the download list if
+ * it's not in the cache */
+ files = alpm_list_add(files, strdup(d->delta));
}
- alpm_list_free(delta_path);
- delta_path = NULL;
- } else {
- /* no deltas to download, so add the file to the
- * download list */
- files = alpm_list_add(files, strdup(fname));
+ /* keep a list of the delta files for md5sums */
+ deltas = alpm_list_add(deltas, d);
}
+
} else {
/* not using deltas, so add the file to the download list */
files = alpm_list_add(files, strdup(fname));
}
}
- FREE(fpath);
}
}
}
if(files) {
EVENT(trans, PM_TRANS_EVT_RETRIEVE_START, current->treename, NULL);
- if(_alpm_downloadfiles(current->servers, cachedir, files, &dl, dltotal)) {
+ if(_alpm_download_files(files, current->servers, cachedir)) {
_alpm_log(PM_LOG_WARNING, _("failed to retrieve some files from %s\n"),
current->treename);
- RET_ERR(PM_ERR_RETRIEVE, -1);
+ pm_errno = PM_ERR_RETRIEVE;
+ goto error;
}
FREELIST(files);
}
@@ -1059,40 +890,41 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
return(0);
}
+ /* clear out value to let callback know we are done */
+ if(handle->totaldlcb) {
+ handle->totaldlcb(0);
+ }
+
if(handle->usedelta) {
int ret = 0;
/* only output if there are deltas to work with */
if(deltas) {
+ errors = 0;
/* Check integrity of deltas */
EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL);
for(i = deltas; i; i = i->next) {
pmdelta_t *d = alpm_list_getdata(i);
+ const char *filename = alpm_delta_get_filename(d);
+ const char *md5sum = alpm_delta_get_md5sum(d);
- ret = test_delta_md5sum(trans, d, data);
-
- if(ret == 1) {
- retval = 1;
- } else if(ret == -1) { /* -1 is for serious errors */
- RET_ERR(pm_errno, -1);
+ if(test_md5sum(trans, filename, md5sum) != 0) {
+ errors++;
+ *data = alpm_list_add(*data, strdup(filename));
}
}
- if(retval) {
- pm_errno = PM_ERR_DLT_CORRUPTED;
+ if(errors) {
+ pm_errno = PM_ERR_DLT_INVALID;
goto error;
}
EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL);
/* Use the deltas to generate the packages */
EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL);
- ret = apply_deltas(trans, patches);
+ ret = apply_deltas(trans);
EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL);
- alpm_list_free(patches);
- patches = NULL;
- alpm_list_free(deltas);
- deltas = NULL;
}
if(ret) {
pm_errno = PM_ERR_DLT_PATCHFAILED;
@@ -1103,21 +935,20 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
/* Check integrity of packages */
EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL);
+ errors = 0;
for(i = trans->packages; i; i = i->next) {
pmsyncpkg_t *sync = i->data;
pmpkg_t *spkg = sync->pkg;
- int ret = 0;
+ const char *filename = alpm_pkg_get_filename(spkg);
+ const char *md5sum = alpm_pkg_get_md5sum(spkg);
- ret = test_pkg_md5sum(trans, spkg, data);
-
- if(ret == 1) {
- retval = 1;
- } else if(ret == -1) { /* -1 is for serious errors */
- RET_ERR(pm_errno, -1);
+ if(test_md5sum(trans, filename, md5sum) != 0) {
+ errors++;
+ *data = alpm_list_add(*data, strdup(filename));
}
}
- if(retval) {
- pm_errno = PM_ERR_PKG_CORRUPTED;
+ if(errors) {
+ pm_errno = PM_ERR_PKG_INVALID;
goto error;
}
EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL);
@@ -1130,7 +961,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
tr = _alpm_trans_new();
if(tr == NULL) {
_alpm_log(PM_LOG_ERROR, _("could not create removal transaction\n"));
- pm_errno = PM_ERR_MEMORY;
goto error;
}
@@ -1141,16 +971,14 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
for(i = trans->packages; i; i = i->next) {
pmsyncpkg_t *sync = i->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- alpm_list_t *j;
- for(j = sync->data; j; j = j->next) {
- pmpkg_t *pkg = j->data;
- if(!_alpm_pkg_find(pkg->name, tr->packages)) {
- if(_alpm_trans_addtarget(tr, pkg->name) == -1) {
- goto error;
- }
- replaces++;
+ alpm_list_t *j;
+ for(j = sync->removes; j; j = j->next) {
+ pmpkg_t *pkg = j->data;
+ if(!_alpm_pkg_find(tr->packages, pkg->name)) {
+ if(_alpm_trans_addtarget(tr, pkg->name) == -1) {
+ goto error;
}
+ replaces++;
}
}
}
@@ -1175,7 +1003,6 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
tr = _alpm_trans_new();
if(tr == NULL) {
_alpm_log(PM_LOG_ERROR, _("could not create transaction\n"));
- pm_errno = PM_ERR_MEMORY;
goto error;
}
if(_alpm_trans_init(tr, PM_TRANS_TYPE_UPGRADE, trans->flags | PM_TRANS_FLAG_NODEPS, trans->cb_event, trans->cb_conv, trans->cb_progress) == -1) {
@@ -1189,6 +1016,9 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
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);
@@ -1201,9 +1031,7 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
/* using alpm_list_last() is ok because addtarget() adds the new target at the
* end of the tr->packages list */
spkg = alpm_list_last(tr->packages)->data;
- if(sync->type == PM_SYNC_TYPE_DEPEND) {
- spkg->reason = PM_PKG_REASON_DEPEND;
- }
+ spkg->reason = sync->newreason;
}
if(_alpm_trans_prepare(tr, data) == -1) {
_alpm_log(PM_LOG_ERROR, _("could not prepare transaction\n"));
@@ -1214,15 +1042,15 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
_alpm_log(PM_LOG_ERROR, _("could not commit transaction\n"));
goto error;
}
- _alpm_trans_free(tr);
- tr = NULL;
-
- return(0);
+ ret = 0;
error:
+ FREELIST(files);
+ alpm_list_free(deltas);
+ deltas = NULL;
_alpm_trans_free(tr);
tr = NULL;
- return(-1);
+ return(ret);
}
pmsyncpkg_t *_alpm_sync_find(alpm_list_t *syncpkgs, const char* pkgname)
@@ -1246,14 +1074,6 @@ pmsyncpkg_t *_alpm_sync_find(alpm_list_t *syncpkgs, const char* pkgname)
return(NULL); /* not found */
}
-pmsynctype_t SYMEXPORT alpm_sync_get_type(const pmsyncpkg_t *sync)
-{
- /* Sanity checks */
- ASSERT(sync != NULL, return(-1));
-
- return sync->type;
-}
-
pmpkg_t SYMEXPORT *alpm_sync_get_pkg(const pmsyncpkg_t *sync)
{
/* Sanity checks */
@@ -1262,12 +1082,12 @@ pmpkg_t SYMEXPORT *alpm_sync_get_pkg(const pmsyncpkg_t *sync)
return sync->pkg;
}
-void SYMEXPORT *alpm_sync_get_data(const pmsyncpkg_t *sync)
+alpm_list_t SYMEXPORT *alpm_sync_get_removes(const pmsyncpkg_t *sync)
{
/* Sanity checks */
ASSERT(sync != NULL, return(NULL));
- return sync->data;
+ return sync->removes;
}
/* vim: set ts=2 sw=2 noet: */