Git-Url: 
http://git.frugalware.org/gitweb/gitweb.cgi?p=pacman-g2.git;a=commitdiff;h=65141c56d78c26f926f955d3c64776ab8275377f

commit 65141c56d78c26f926f955d3c64776ab8275377f
Author: Michel Hermier <[email protected]>
Date:   Sun May 11 10:17:49 2014 +0200

libpacman: Merge sync operation inside trans.cpp, and drop __pmtrans_ops_t.

diff --git a/lib/libpacman/sync.cpp b/lib/libpacman/sync.cpp
index eb5697c..3abf897 100644
--- a/lib/libpacman/sync.cpp
+++ b/lib/libpacman/sync.cpp
@@ -42,7 +42,6 @@
#include "util.h"
#include "pacman_p.h"
#include "handle.h"
-#include "server.h"
#include "packages_transaction.h"

#include "hash/md5.h"
@@ -80,869 +79,4 @@ __pmsyncpkg_t::~__pmsyncpkg_t()
}
}

-/* Helper functions for _pacman_list_remove
- */
-static
-int _pacman_syncpkg_cmp(const void *s1, const void *s2)
-{
-       return(strcmp(((pmsyncpkg_t *)s1)->pkg->name(), ((pmsyncpkg_t 
*)s2)->pkg->name()));
-}
-
-int _pacman_sync_addtarget(pmtrans_t *trans, const char *name)
-{
-       char targline[PKG_FULLNAME_LEN];
-       char *targ;
-       pmlist_t *j;
-       Package *pkg_local;
-       Package *spkg = NULL;
-       int cmp;
-       Database *db_local = trans->handle->db_local;
-       pmlist_t *dbs_sync = trans->handle->dbs_sync;
-
-       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));
-
-       STRNCPY(targline, name, PKG_FULLNAME_LEN);
-       targ = strchr(targline, '/');
-       if(targ) {
-               *targ = '\0';
-               targ++;
-               for(j = dbs_sync; j && !spkg; j = j->next) {
-                       Database *dbs = j->data;
-                       if(strcmp(dbs->treename, targline) == 0) {
-                               spkg = _pacman_db_get_pkgfromcache(dbs, targ);
-                               if(spkg == NULL) {
-                                       /* Search provides */
-                                       pmlist_t *p;
-                                       _pacman_log(PM_LOG_FLOW2, _("target 
'%s' not found -- looking for provisions"), targ);
-                                       p = _pacman_db_whatprovides(dbs, targ);
-                                       if(p == NULL) {
-                                               RET_ERR(PM_ERR_PKG_NOT_FOUND, 
-1);
-                                       }
-                                       _pacman_log(PM_LOG_DEBUG, _("found '%s' 
as a provision for '%s'"), p->data, targ);
-                                       spkg = _pacman_db_get_pkgfromcache(dbs, 
p->data);
-                                       FREELISTPTR(p);
-                               }
-                       }
-               }
-       } else {
-               targ = targline;
-               for(j = dbs_sync; j && !spkg; j = j->next) {
-                       Database *dbs = j->data;
-                       spkg = _pacman_db_get_pkgfromcache(dbs, targ);
-               }
-               if(spkg == NULL) {
-                       /* Search provides */
-                       _pacman_log(PM_LOG_FLOW2, _("target '%s' not found -- 
looking for provisions"), targ);
-                       for(j = dbs_sync; j && !spkg; j = j->next) {
-                               Database *dbs = j->data;
-                               pmlist_t *p = _pacman_db_whatprovides(dbs, 
targ);
-                               if(p) {
-                                       _pacman_log(PM_LOG_DEBUG, _("found '%s' 
as a provision for '%s'"), p->data, targ);
-                                       spkg = _pacman_db_get_pkgfromcache(dbs, 
p->data);
-                                       FREELISTPTR(p);
-                               }
-                       }
-               }
-       }
-       if(spkg == NULL) {
-               RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
-       }
-
-       pkg_local = _pacman_db_get_pkgfromcache(db_local, spkg->name());
-       if(pkg_local) {
-               cmp = _pacman_versioncmp(pkg_local->version(), spkg->version());
-               if(cmp > 0) {
-                       /* pkg_local version is newer -- get confirmation 
before adding */
-                       int resp = 0;
-                       QUESTION(trans, PM_TRANS_CONV_LOCAL_NEWER, pkg_local, 
NULL, NULL, &resp);
-                       if(!resp) {
-                               _pacman_log(PM_LOG_WARNING, _("%s-%s: local 
version is newer -- skipping"), pkg_local->name(), pkg_local->version());
-                               return(0);
-                       }
-               } else if(cmp == 0) {
-                       /* versions are identical -- get confirmation before 
adding */
-                       int resp = 0;
-                       QUESTION(trans, PM_TRANS_CONV_LOCAL_UPTODATE, 
pkg_local, NULL, NULL, &resp);
-                       if(!resp) {
-                               _pacman_log(PM_LOG_WARNING, _("%s-%s is up to 
date -- skipping"), pkg_local->name(), pkg_local->version());
-                               return(0);
-                       }
-               }
-       }
-
-       /* add the package to the transaction */
-       if(!trans->find(spkg->name())) {
-               Package *dummy = NULL;
-               pmsyncpkg_t *ps;
-
-               if(pkg_local) {
-                       dummy = new Package(pkg_local->name(), 
pkg_local->version());
-                       if(dummy == NULL) {
-                               RET_ERR(PM_ERR_MEMORY, -1);
-                       }
-               }
-               ps = new __pmsyncpkg_t(PM_SYNC_TYPE_UPGRADE, spkg, dummy);
-               if(ps == NULL) {
-                       delete dummy;
-                       RET_ERR(PM_ERR_MEMORY, -1);
-               }
-               trans->add(ps, 0);
-       }
-
-       return(0);
-}
-
-static int pkg_cmp(const void *p1, const void *p2)
-{
-       return(strcmp(((Package *)p1)->name(), ((pmsyncpkg_t 
*)p2)->pkg->name()));
-}
-
-static int check_olddelay(void)
-{
-       pmlist_t *i;
-       time_t tm;
-
-       if(!handle->olddelay) {
-               return(0);
-       }
-
-       for(i = handle->dbs_sync; i; i= i->next) {
-               Database *db = i->data;
-               if(db->gettimestamp(&tm) == -1) {
-                       continue;
-               }
-               if(difftime(time(NULL), tm) > handle->olddelay) {
-                       _pacman_log(PM_LOG_WARNING, _("local copy of '%s' repo 
is too old"), db->treename);
-               }
-       }
-       return(0);
-}
-
-int _pacman_sync_prepare(pmtrans_t *trans, pmlist_t **data)
-{
-       pmlist_t *deps = NULL;
-       pmlist_t *list = NULL; /* list allowing checkdeps usage with data from 
trans->packages */
-       pmlist_t *trail = NULL; /* breadcrum list to avoid running into circles 
*/
-       pmlist_t *asked = NULL;
-       pmlist_t *i, *j, *k, *l, *m;
-       int ret = 0;
-       Database *db_local = trans->handle->db_local;
-
-       ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
-       ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-       ASSERT(trans->packages == NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
-       if(data) {
-               *data = NULL;
-       }
-
-       for(i = trans->syncpkgs; i; i = i->next) {
-               pmsyncpkg_t *ps = i->data;
-               list = _pacman_list_add(list, ps->pkg);
-       }
-
-       if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
-               trail = _pacman_list_new();
-
-               /* Resolve targets dependencies */
-               EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL);
-               _pacman_log(PM_LOG_FLOW1, _("resolving targets dependencies"));
-               for(i = trans->syncpkgs; i; i = i->next) {
-                       Package *spkg = ((pmsyncpkg_t *)i->data)->pkg;
-                       if(_pacman_resolvedeps(trans, spkg, list, trail, data) 
== -1) {
-                               /* pm_errno is set by resolvedeps */
-                               ret = -1;
-                               goto cleanup;
-                       }
-               }
-
-               for(i = list; i; i = i->next) {
-                       /* add the dependencies found by resolvedeps to the 
transaction set */
-                       Package *spkg = i->data;
-                       if(!trans->find(spkg->name())) {
-                               pmsyncpkg_t *ps = new 
__pmsyncpkg_t(PM_SYNC_TYPE_DEPEND, spkg, NULL);
-                               if(ps == NULL) {
-                                       ret = -1;
-                                       goto cleanup;
-                               }
-                               trans->syncpkgs = 
_pacman_list_add(trans->syncpkgs, ps);
-                               _pacman_log(PM_LOG_FLOW2, _("adding package 
%s-%s to the transaction targets"),
-                                               spkg->name(), spkg->version());
-                       } else {
-                               /* remove the original targets from the list if 
requested */
-                               if((trans->flags & PM_TRANS_FLAG_DEPENDSONLY)) {
-                                       /* they are just pointers so we don't 
have to free them */
-                                       trans->syncpkgs = 
_pacman_list_remove(trans->syncpkgs, spkg, pkg_cmp, NULL);
-                               }
-                       }
-               }
-
-               /* re-order w.r.t. dependencies */
-               k = l = NULL;
-               for(i=trans->syncpkgs; i; i=i->next) {
-                       pmsyncpkg_t *s = (pmsyncpkg_t*)i->data;
-                       k = _pacman_list_add(k, s->pkg);
-               }
-               m = _pacman_sortbydeps(k, PM_TRANS_TYPE_ADD);
-               for(i=m; i; i=i->next) {
-                       for(j=trans->syncpkgs; j; j=j->next) {
-                               pmsyncpkg_t *s = (pmsyncpkg_t*)j->data;
-                               if(s->pkg==i->data) {
-                                       l = _pacman_list_add(l, s);
-                               }
-                       }
-               }
-               FREELISTPTR(k);
-               FREELISTPTR(m);
-               FREELISTPTR(trans->syncpkgs);
-               trans->syncpkgs = l;
-
-               EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL);
-
-               _pacman_log(PM_LOG_FLOW1, _("looking for unresolvable 
dependencies"));
-               deps = _pacman_checkdeps(trans, PM_TRANS_TYPE_UPGRADE, list);
-               if(!f_ptrlist_empty(deps)) {
-                       if(data) {
-                               *data = deps;
-                       }
-                       pm_errno = PM_ERR_UNSATISFIED_DEPS;
-                       ret = -1;
-                       goto cleanup;
-               }
-
-               FREELISTPTR(trail);
-       }
-
-       if(!(trans->flags & PM_TRANS_FLAG_NOCONFLICTS)) {
-               /* check for inter-conflicts and whatnot */
-               EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL);
-
-               _pacman_log(PM_LOG_FLOW1, _("looking for conflicts"));
-               deps = _pacman_checkconflicts(trans, list);
-               if(!f_ptrlist_empty(deps)) {
-                       int errorout = 0;
-
-                       for(i = deps; i && !errorout; i = i->next) {
-                               pmdepmissing_t *miss = i->data;
-                               int found = 0;
-                               pmsyncpkg_t *ps;
-                               Package *local;
-
-                               _pacman_log(PM_LOG_FLOW2, _("package '%s' is 
conflicting with '%s'"),
-                                                 miss->target, 
miss->depend.name);
-
-                               /* check if the conflicting package is one 
that's about to be removed/replaced.
-                                * if so, then just ignore it
-                                */
-                               for(j = trans->syncpkgs; j && !found; j = 
j->next) {
-                                       ps = j->data;
-                                       if(ps->type == PM_SYNC_TYPE_REPLACE) {
-                                               
if(_pacman_pkg_isin(miss->depend.name, ps->data)) {
-                                                       found = 1;
-                                               }
-                                       }
-                               }
-                               if(found) {
-                                       _pacman_log(PM_LOG_DEBUG, _("'%s' is 
already elected for removal -- skipping"),
-                                                       miss->depend.name);
-                                       continue;
-                               }
-
-                               ps = trans->find(miss->target);
-                               if(ps == NULL) {
-                                       _pacman_log(PM_LOG_DEBUG, _("'%s' not 
found in transaction set -- skipping"),
-                                                         miss->target);
-                                       continue;
-                               }
-                               local = _pacman_db_get_pkgfromcache(db_local, 
miss->depend.name);
-                               /* check if this package also "provides" the 
package it's conflicting with
-                                */
-                               if(ps->pkg->provides(miss->depend.name)) {
-                                       /* so just treat it like a "replaces" 
item so the REQUIREDBY
-                                        * fields are inherited properly.
-                                        */
-                                       _pacman_log(PM_LOG_DEBUG, _("package 
'%s' provides its own conflict"), miss->target);
-                                       if(local) {
-                                               /* nothing to do for now: it 
will be handled later
-                                                * (not the same behavior as in 
pacman) */
-                                       } else {
-                                               char *rmpkg = NULL;
-                                               int target, depend;
-                                               /* hmmm, depend.name isn't 
installed, so it must be conflicting
-                                                * with another package in our 
final list.  For example:
-                                                *
-                                                *     pacman-g2 -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 = 
_pacman_list_is_strin(miss->target, trans->targets);
-                                               depend = 
_pacman_list_is_strin(miss->depend.name, trans->targets);
-                                               if(depend && !target) {
-                                                       
_pacman_log(PM_LOG_DEBUG, _("'%s' is in the target list -- keeping it"),
-                                                               
miss->depend.name);
-                                                       /* remove miss->target 
*/
-                                                       rmpkg = miss->target;
-                                               } else if(target && !depend) {
-                                                       
_pacman_log(PM_LOG_DEBUG, _("'%s' is in the target list -- keeping it"),
-                                                               miss->target);
-                                                       /* remove 
miss->depend.name */
-                                                       rmpkg = 
miss->depend.name;
-                                               } else {
-                                                       /* miss->depend.name is 
not needed, miss->target already provides
-                                                        * it, let's resolve 
the conflict */
-                                                       rmpkg = 
miss->depend.name;
-                                               }
-                                               if(rmpkg) {
-                                                       pmsyncpkg_t *rsync = 
trans->find(rmpkg);
-                                                       pmsyncpkg_t *spkg = 
NULL;
-
-                                                       
_pacman_log(PM_LOG_FLOW2, _("removing '%s' from target list"), rmpkg);
-                                                       trans->syncpkgs = 
_pacman_list_remove(trans->syncpkgs, rsync, _pacman_syncpkg_cmp, (void 
**)&spkg);
-                                                       delete spkg;
-                                                       continue;
-                                               }
-                                       }
-                               }
-                               /* It's a conflict -- see if they want to 
remove it
-                               */
-                               _pacman_log(PM_LOG_DEBUG, _("resolving package 
'%s' conflict"), miss->target);
-                               if(local) {
-                                       int doremove = 0;
-                                       
if(!_pacman_list_is_strin(miss->depend.name, asked)) {
-                                               QUESTION(trans, 
PM_TRANS_CONV_CONFLICT_PKG, miss->target, miss->depend.name, NULL, &doremove);
-                                               asked = 
_pacman_stringlist_append(asked, miss->depend.name);
-                                               if(doremove) {
-                                                       pmsyncpkg_t *rsync = 
trans->find(miss->depend.name);
-                                                       Package *q = new 
Package(miss->depend.name, NULL);
-                                                       if(q == NULL) {
-                                                               if(data) {
-                                                                       
FREELIST(*data);
-                                                               }
-                                                               ret = -1;
-                                                               goto cleanup;
-                                                       }
-                                                       q->m_requiredby = 
_pacman_list_strdup(local->requiredby());
-                                                       if(ps->type != 
PM_SYNC_TYPE_REPLACE) {
-                                                               /* switch this 
sync type to REPLACE */
-                                                               ps->type = 
PM_SYNC_TYPE_REPLACE;
-                                                               delete ps->data;
-                                                               ps->data = NULL;
-                                                       }
-                                                       /* append to the 
replaces list */
-                                                       
_pacman_log(PM_LOG_FLOW2, _("electing '%s' for removal"), miss->depend.name);
-                                                       ps->data = 
_pacman_list_add(ps->data, q);
-                                                       if(rsync) {
-                                                               /* remove it 
from the target list */
-                                                               pmsyncpkg_t 
*spkg = NULL;
-
-                                                               
_pacman_log(PM_LOG_FLOW2, _("removing '%s' from target list"), 
miss->depend.name);
-                                                               trans->syncpkgs 
= _pacman_list_remove(trans->syncpkgs, rsync, _pacman_syncpkg_cmp, (void 
**)&spkg);
-                                                               delete spkg;
-                                                       }
-                                               } else {
-                                                       /* abort */
-                                                       
_pacman_log(PM_LOG_ERROR, _("unresolvable package conflicts detected"));
-                                                       errorout = 1;
-                                                       if(data) {
-                                                               if((miss = 
_pacman_malloc(sizeof(pmdepmissing_t))) == NULL) {
-                                                                       
FREELIST(*data);
-                                                                       ret = 
-1;
-                                                                       goto 
cleanup;
-                                                               }
-                                                               *miss = 
*(pmdepmissing_t *)i->data;
-                                                               *data = 
_pacman_list_add(*data, miss);
-                                                       }
-                                               }
-                                       }
-                               } else {
-                                       _pacman_log(PM_LOG_ERROR, 
_("unresolvable package conflicts detected"));
-                                       errorout = 1;
-                                       if(data) {
-                                               if((miss = 
_pacman_malloc(sizeof(pmdepmissing_t))) == NULL) {
-                                                       FREELIST(*data);
-                                                       ret = -1;
-                                                       goto cleanup;
-                                               }
-                                               *miss = *(pmdepmissing_t 
*)i->data;
-                                               *data = _pacman_list_add(*data, 
miss);
-                                       }
-                               }
-                       }
-                       if(errorout) {
-                               pm_errno = PM_ERR_CONFLICTING_DEPS;
-                               ret = -1;
-                               goto cleanup;
-                       }
-                       FREELIST(deps);
-                       FREELIST(asked);
-               }
-               EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL);
-       }
-
-       FREELISTPTR(list);
-
-       /* XXX: this fails for cases where a requested package wants
-        *      a dependency that conflicts with an older version of
-        *      the package.  It will be removed from final, and the user
-        *      has to re-request it to get it installed properly.
-        *
-        *      Not gonna happen very often, but should be dealt with...
-        */
-
-       if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
-               /* Check dependencies of packages in rmtargs and make sure
-                * we won't be breaking anything by removing them.
-                * If a broken dep is detected, make sure it's not from a
-                * package that's in our final (upgrade) list.
-                */
-               /*EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL);*/
-               for(i = trans->syncpkgs; i; i = i->next) {
-                       pmsyncpkg_t *ps = i->data;
-                       if(ps->type == PM_SYNC_TYPE_REPLACE) {
-                               for(j = ps->data; j; j = j->next) {
-                                       list = _pacman_list_add(list, j->data);
-                               }
-                       }
-               }
-               if(list) {
-                       _pacman_log(PM_LOG_FLOW1, _("checking dependencies of 
packages designated for removal"));
-                       deps = _pacman_checkdeps(trans, PM_TRANS_TYPE_REMOVE, 
list);
-                       if(deps) {
-                               int errorout = 0;
-                               for(i = deps; i; i = i->next) {
-                                       pmdepmissing_t *miss = i->data;
-                                       if(!trans->find(miss->depend.name)) {
-                                               int pfound = 0;
-                                               /* If miss->depend.name depends 
on something that miss->target and a
-                                                * package in final both 
provide, then it's okay...  */
-                                               Package *leavingp  = 
_pacman_db_get_pkgfromcache(db_local, miss->target);
-                                               Package *conflictp = 
_pacman_db_get_pkgfromcache(db_local, miss->depend.name);
-                                               if(!leavingp || !conflictp) {
-                                                       
_pacman_log(PM_LOG_ERROR, _("something has gone horribly wrong"));
-                                                       ret = -1;
-                                                       goto cleanup;
-                                               }
-                                               /* Look through the upset 
package's dependencies and try to match one up
-                                                * to a provisio from the 
package we want to remove */
-                                               for(k = conflictp->depends(); k 
&& !pfound; k = k->next) {
-                                                       pmlist_t *m;
-                                                       for(m = 
leavingp->provides(); m && !pfound; m = m->next) {
-                                                               
if(!strcmp(k->data, m->data)) {
-                                                                       /* 
Found a match -- now look through final for a package that
-                                                                        * 
provides the same thing.  If none are found, then it truly
-                                                                        * is 
an unresolvable conflict. */
-                                                                       
pmlist_t *n, *o;
-                                                                       for(n = 
trans->syncpkgs; n && !pfound; n = n->next) {
-                                                                               
pmsyncpkg_t *sp = n->data;
-                                                                               
for(o = sp->pkg->provides(); o && !pfound; o = o->next) {
-                                                                               
        if(!strcmp(m->data, o->data)) {
-                                                                               
                /* found matching provisio -- we're good to go */
-                                                                               
                _pacman_log(PM_LOG_FLOW2, _("found '%s' as a provision for '%s' 
-- conflict aborted"),
-                                                                               
                                sp->pkg->name(), (char *)o->data);
-                                                                               
                pfound = 1;
-                                                                               
        }
-                                                                               
}
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                               if(!pfound) {
-                                                       if(!errorout) {
-                                                               errorout = 1;
-                                                       }
-                                                       if(data) {
-                                                               if((miss = 
_pacman_malloc(sizeof(pmdepmissing_t))) == NULL) {
-                                                                       
FREELIST(*data);
-                                                                       ret = 
-1;
-                                                                       goto 
cleanup;
-                                                               }
-                                                               *miss = 
*(pmdepmissing_t *)i->data;
-                                                               *data = 
_pacman_list_add(*data, miss);
-                                                       }
-                                               }
-                                       }
-                               }
-                               if(errorout) {
-                                       pm_errno = PM_ERR_UNSATISFIED_DEPS;
-                                       ret = -1;
-                                       goto cleanup;
-                               }
-                               FREELIST(deps);
-                       }
-               }
-               /*EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL);*/
-       }
-
-#ifndef __sun__
-       /* check for free space only in case the packages will be extracted */
-       if(!(trans->flags & PM_TRANS_FLAG_NOCONFLICTS)) {
-               if(_pacman_check_freespace(trans, data) == -1) {
-                               /* pm_errno is set by check_freespace */
-                               ret = -1;
-                               goto cleanup;
-               }
-       }
-#endif
-
-       /* issue warning if the local db is too old */
-       check_olddelay();
-
-cleanup:
-       FREELISTPTR(list);
-       FREELISTPTR(trail);
-       FREELIST(asked);
-
-       return(ret);
-}
-
-int _pacman_sync_commit(pmtrans_t *trans, pmlist_t **data)
-{
-       pmlist_t *i, *j;
-       pmtrans_t *tr = NULL;
-       int replaces = 0;
-       Database *db_local = trans->handle->db_local;
-
-       ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
-       ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
-       if(handle->sysupgrade) {
-               _pacman_runhook("pre_sysupgrade", trans);
-       }
-       /* remove conflicting and to-be-replaced packages */
-       tr = new __pmtrans_t(PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAG_NODEPS, 
trans->cbs);
-       if(tr == NULL) {
-               _pacman_log(PM_LOG_ERROR, _("could not create removal 
transaction"));
-               pm_errno = PM_ERR_MEMORY;
-               goto error;
-       }
-       for(i = trans->syncpkgs; i; i = i->next) {
-               pmsyncpkg_t *ps = i->data;
-               if(ps->type == PM_SYNC_TYPE_REPLACE) {
-                       for(j = ps->data; j; j = j->next) {
-                               Package *pkg = j->data;
-                               if(!_pacman_pkg_isin(pkg->name(), 
tr->packages)) {
-                                       if(tr->add(pkg->name()) == -1) {
-                                               goto error;
-                                       }
-                                       replaces++;
-                               }
-                       }
-               }
-       }
-       if(replaces) {
-               _pacman_log(PM_LOG_FLOW1, _("removing conflicting and 
to-be-replaced packages"));
-               if(tr->prepare(data) == -1) {
-                       _pacman_log(PM_LOG_ERROR, _("could not prepare removal 
transaction"));
-                       goto error;
-               }
-               /* we want the frontend to be aware of commit details */
-               tr->cbs.event = trans->cbs.event;
-               if(tr->commit(NULL) == -1) {
-                       _pacman_log(PM_LOG_ERROR, _("could not commit removal 
transaction"));
-                       goto error;
-               }
-       }
-       delete tr;
-       tr = NULL;
-
-       /* install targets */
-       _pacman_log(PM_LOG_FLOW1, _("installing packages"));
-       tr = new __pmtrans_t(PM_TRANS_TYPE_UPGRADE, trans->flags | 
PM_TRANS_FLAG_NODEPS, trans->cbs);
-       if(tr == NULL) {
-               _pacman_log(PM_LOG_ERROR, _("could not create transaction"));
-               pm_errno = PM_ERR_MEMORY;
-               goto error;
-       }
-       for(i = trans->syncpkgs; i; i = i->next) {
-               pmsyncpkg_t *ps = i->data;
-               Package *spkg = ps->pkg;
-               char str[PATH_MAX];
-               snprintf(str, PATH_MAX, "%s%s/%s-%s-%s" PM_EXT_PKG, 
handle->root, handle->cachedir, spkg->name(), spkg->version(), spkg->arch);
-               if(tr->add(str) == -1) {
-                       goto error;
-               }
-               /* using _pacman_list_last() is ok because addtarget() adds the 
new target at the
-                * end of the tr->packages list */
-               spkg = _pacman_list_last(tr->packages)->data;
-               if(ps->type == PM_SYNC_TYPE_DEPEND || trans->flags & 
PM_TRANS_FLAG_ALLDEPS) {
-                       spkg->m_reason = PM_PKG_REASON_DEPEND;
-               } else if(ps->type == PM_SYNC_TYPE_UPGRADE && 
!handle->sysupgrade) {
-                       spkg->m_reason = PM_PKG_REASON_EXPLICIT;
-               }
-       }
-       if(tr->prepare(data) == -1) {
-               _pacman_log(PM_LOG_ERROR, _("could not prepare transaction"));
-               /* pm_errno is set by trans_prepare */
-               goto error;
-       }
-       if(tr->commit(NULL) == -1) {
-               _pacman_log(PM_LOG_ERROR, _("could not commit transaction"));
-               goto error;
-       }
-       delete tr;
-       tr = NULL;
-
-       /* propagate replaced packages' requiredby fields to their new owners */
-       if(replaces) {
-               _pacman_log(PM_LOG_FLOW1, _("updating database for replaced 
packages' dependencies"));
-               for(i = trans->syncpkgs; i; i = i->next) {
-                       pmsyncpkg_t *ps = i->data;
-                       if(ps->type == PM_SYNC_TYPE_REPLACE) {
-                               Package *pkg_new = 
_pacman_db_get_pkgfromcache(db_local, ps->pkg_name);
-                               for(j = ps->data; j; j = j->next) {
-                                       pmlist_t *k;
-                                       Package *old = j->data;
-                                       /* merge lists */
-                                       for(k = old->requiredby(); k; k = 
k->next) {
-                                               
if(!_pacman_list_is_strin(k->data, pkg_new->requiredby())) {
-                                                       /* replace old's name 
with new's name in the requiredby's dependency list */
-                                                       pmlist_t *m;
-                                                       Package *depender = 
_pacman_db_get_pkgfromcache(db_local, k->data);
-                                                       if(depender == NULL) {
-                                                               /* If the 
depending package no longer exists in the local db,
-                                                                * then it must 
have ALSO conflicted with ps->pkg.  If
-                                                                * that's the 
case, then we don't have anything to propagate
-                                                                * here. */
-                                                               continue;
-                                                       }
-                                                       for(m = 
depender->depends(); m; m = m->next) {
-                                                               
if(!strcmp(m->data, old->name())) {
-                                                                       
FREE(m->data);
-                                                                       m->data 
= strdup(pkg_new->name());
-                                                               }
-                                                       }
-                                                       
if(db_local->write(depender, INFRQ_DEPENDS) == -1) {
-                                                               
_pacman_log(PM_LOG_ERROR, _("could not update requiredby for database entry 
%s-%s"),
-                                                                               
  pkg_new->name(), pkg_new->version());
-                                                       }
-                                                       /* add the new 
requiredby */
-                                                       pkg_new->m_requiredby = 
_pacman_stringlist_append(pkg_new->m_requiredby, k->data);
-                                               }
-                                       }
-                               }
-                               if(db_local->write(pkg_new, INFRQ_DEPENDS) == 
-1) {
-                                       _pacman_log(PM_LOG_ERROR, _("could not 
update new database entry %s-%s"),
-                                                         pkg_new->name(), 
pkg_new->version());
-                               }
-                       }
-               }
-       }
-
-       if(handle->sysupgrade) {
-               _pacman_runhook("post_sysupgrade", trans);
-       }
-       return(0);
-
-error:
-       delete tr;
-       /* commiting failed, so this is still just a prepared transaction */
-       return(-1);
-}
-
-int _pacman_trans_download_commit(pmtrans_t *trans, pmlist_t **data)
-{
-       pmlist_t *i, *j, *files = NULL;
-       char ldir[PATH_MAX];
-    int doremove, retval = 0, tries = 0;
-       int varcache = 1;
-
-       ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
-
-       trans->state = STATE_DOWNLOADING;
-       /* group sync records by repository and download */
-       snprintf(ldir, PATH_MAX, "%s%s", handle->root, handle->cachedir);
-
-       for(tries = 0; tries < handle->maxtries; tries++) {
-               retval = 0;
-               FREELIST(*data);
-               int done = 1;
-               for(i = handle->dbs_sync; i; i = i->next) {
-                       struct stat buf;
-                       Database *current = i->data;
-
-                       for(j = trans->syncpkgs; j; j = j->next) {
-                               pmsyncpkg_t *ps = j->data;
-                               Package *spkg = ps->pkg;
-                               Database *dbs = spkg->data;
-
-                               if(current == dbs) {
-                                       char filename[PATH_MAX];
-                                       char lcpath[PATH_MAX];
-                                       spkg->filename(filename, 
sizeof(filename));
-                                       snprintf(lcpath, sizeof(lcpath), 
"%s/%s", ldir, filename);
-
-                                       if(trans->flags & 
PM_TRANS_FLAG_PRINTURIS) {
-                                               if (!(trans->flags & 
PM_TRANS_FLAG_PRINTURIS_CACHED)) {
-                                                       if (stat(lcpath, &buf) 
== 0) {
-                                                               continue;
-                                                       }
-                                               }
-
-                                               EVENT(trans, 
PM_TRANS_EVT_PRINTURI, pacman_db_getinfo(c_cast(current), PM_DB_FIRSTSERVER), 
filename);
-                                       } else {
-                                               if(stat(lcpath, &buf)) {
-                                                       /* file is not in the 
cache dir, so add it to the list */
-                                                       files = 
_pacman_stringlist_append(files, filename);
-                                               } else {
-                                                       
_pacman_log(PM_LOG_DEBUG, _("%s is already in the cache\n"), filename);
-                                               }
-                                       }
-                               }
-                       }
-
-                       if(files) {
-                               EVENT(trans, PM_TRANS_EVT_RETRIEVE_START, 
current->treename, NULL);
-                               if(stat(ldir, &buf)) {
-                                       /* no cache directory.... try creating 
it */
-                                       _pacman_log(PM_LOG_WARNING, _("no %s 
cache exists.  creating..."), ldir);
-                                       if(_pacman_makepath(ldir)) {
-                                               /* couldn't mkdir the cache 
directory, so fall back to /tmp and unlink
-                                                * the package afterwards.
-                                                */
-                                               _pacman_log(PM_LOG_WARNING, 
_("couldn't create package cache, using /tmp instead"));
-                                               snprintf(ldir, PATH_MAX, 
"%s/tmp", handle->root);
-                                               
if(pacman_set_option(PM_OPT_CACHEDIR, (long)"/tmp") == -1) {
-                                                       
_pacman_log(PM_LOG_WARNING, _("failed to set option CACHEDIR (%s)\n"), 
pacman_strerror(pm_errno));
-                                                       
RET_ERR(PM_ERR_RETRIEVE, -1);
-                                               }
-                                               varcache = 0;
-                                       }
-                               }
-                               if(_pacman_downloadfiles(current->servers, 
ldir, files, tries) == -1) {
-                                       _pacman_log(PM_LOG_WARNING, _("failed 
to retrieve some files from %s\n"), current->treename);
-                                       retval=1;
-                                       done = 0;
-                               }
-                               FREELIST(files);
-                       }
-               }
-               if (!done)
-                       continue;
-               if(trans->flags & PM_TRANS_FLAG_PRINTURIS) {
-                       return(0);
-               }
-
-               /* Check integrity of files */
-               if(!(trans->flags & PM_TRANS_FLAG_NOINTEGRITY)) {
-                       EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL);
-
-                       for(i = trans->syncpkgs; i; i = i->next) {
-                               pmsyncpkg_t *ps = i->data;
-                               Package *spkg = ps->pkg;
-                               char str[PATH_MAX], pkgname[PATH_MAX];
-                               char *md5sum1, *md5sum2, *sha1sum1, *sha1sum2;
-                               char *ptr=NULL;
-
-                               spkg->filename(pkgname, sizeof(pkgname));
-                               md5sum1 = spkg->md5sum;
-                               sha1sum1 = spkg->sha1sum;
-
-                               if((md5sum1 == NULL) && (sha1sum1 == NULL)) {
-                                       if((ptr = (char *)malloc(512)) == NULL) 
{
-                                               RET_ERR(PM_ERR_MEMORY, -1);
-                                       }
-                                       snprintf(ptr, 512, _("can't get md5 or 
sha1 checksum for package %s\n"), pkgname);
-                                       *data = _pacman_list_add(*data, ptr);
-                                       retval = 1;
-                                       continue;
-                               }
-                               snprintf(str, PATH_MAX, "%s/%s/%s", 
handle->root, handle->cachedir, pkgname);
-                               md5sum2 = _pacman_MDFile(str);
-                               sha1sum2 = _pacman_SHAFile(str);
-                               if(md5sum2 == NULL && sha1sum2 == NULL) {
-                                       if((ptr = (char *)malloc(512)) == NULL) 
{
-                                               RET_ERR(PM_ERR_MEMORY, -1);
-                                       }
-                                       snprintf(ptr, 512, _("can't get md5 or 
sha1 checksum for package %s\n"), pkgname);
-                                       *data = _pacman_list_add(*data, ptr);
-                                       retval = 1;
-                                       continue;
-                               }
-                               if((strcmp(md5sum1, md5sum2) != 0) && 
(strcmp(sha1sum1, sha1sum2) != 0)) {
-                                       _pacman_log(PM_LOG_DEBUG, _("expected 
md5:  '%s'"), md5sum1);
-                                       _pacman_log(PM_LOG_DEBUG, _("actual 
md5:    '%s'"), md5sum2);
-                                       _pacman_log(PM_LOG_DEBUG, _("expected 
sha1: '%s'"), sha1sum1);
-                                       _pacman_log(PM_LOG_DEBUG, _("actual 
sha1:   '%s'"), sha1sum2);
-
-                                       doremove = 0;
-                                       if((ptr = (char *)malloc(512)) == NULL) 
{
-                                               RET_ERR(PM_ERR_MEMORY, -1);
-                                       }
-                                       if(trans->flags & 
PM_TRANS_FLAG_ALLDEPS) {
-                                               doremove=1;
-                                       } else {
-                                               QUESTION(trans, 
PM_TRANS_CONV_CORRUPTED_PKG, pkgname, NULL, NULL, &doremove);
-                                       }
-                                       if(doremove) {
-                                               snprintf(str, PATH_MAX, 
"%s%s/%s-%s-%s" PM_EXT_PKG, handle->root, handle->cachedir, spkg->name(), 
spkg->version(), spkg->arch);
-                                               unlink(str);
-                                               snprintf(ptr, 512, _("archive 
%s was corrupted (bad MD5 or SHA1 checksum)\n"), pkgname);
-                                       } else {
-                                               snprintf(ptr, 512, _("archive 
%s is corrupted (bad MD5 or SHA1 checksum)\n"), pkgname);
-                                       }
-                                       *data = _pacman_list_add(*data, ptr);
-                                       retval = 1;
-                               }
-                               FREE(md5sum2);
-                               FREE(sha1sum2);
-                       }
-                       if(!retval) {
-                               break;
-                       }
-               }
-       }
-
-       if(retval) {
-               pm_errno = PM_ERR_PKG_CORRUPTED;
-               goto error;
-       }
-       if(!(trans->flags & PM_TRANS_FLAG_NOINTEGRITY)) {
-               EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL);
-       }
-       if(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY) {
-               return(0);
-       }
-       if(!retval) {
-               trans->state = STATE_COMMITING;
-               retval = _pacman_sync_commit(trans, data);
-               if(retval) {
-                       goto error;
-               }
-       }
-
-       if(!varcache && !(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY)) {
-               /* delete packages */
-               for(i = files; i; i = i->next) {
-                       unlink(i->data);
-               }
-       }
-       return(retval);
-
-error:
-       /* commiting failed, so this is still just a prepared transaction */
-       return(-1);
-}
-
-#if 0
-const pmtrans_ops_t _pacman_sync_pmtrans_opts = {
-       .addtarget = _pacman_sync_addtarget,
-       .prepare = _pacman_sync_prepare,
-       .commit = _pacman_sync_commit
-};
-#endif
-
-const pmtrans_ops_t _pacman_sync_pmtrans_opts = {
-       .addtarget = _pacman_sync_addtarget,
-       .prepare = _pacman_sync_prepare,
-       .commit = _pacman_trans_download_commit
-};
-
/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libpacman/sync.h b/lib/libpacman/sync.h
index 1e98ab8..37f8fdb 100644
--- a/lib/libpacman/sync.h
+++ b/lib/libpacman/sync.h
@@ -40,9 +40,6 @@ struct __pmsyncpkg_t
libpacman::Package *pkg_local;
};

-extern
-const pmtrans_ops_t _pacman_sync_pmtrans_opts;
-
#endif /* _PACMAN_SYNC_H */

/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libpacman/trans.cpp b/lib/libpacman/trans.cpp
index f3ea2f8..2938499 100644
--- a/lib/libpacman/trans.cpp
+++ b/lib/libpacman/trans.cpp
@@ -36,6 +36,7 @@
#include "package.h"
#include "util.h"
#include "handle.h"
+#include "server.h"
#include "sync.h"
#include "cache.h"
#include "pacman.h"
@@ -84,13 +85,9 @@ __pmtrans_t::__pmtrans_t(pmtranstype_t type, unsigned int 
flags, pmtrans_cbs_t c
case PM_TRANS_TYPE_ADD:
case PM_TRANS_TYPE_UPGRADE:
case PM_TRANS_TYPE_REMOVE:
-                       ops = NULL;
-               break;
case PM_TRANS_TYPE_SYNC:
-                       ops = &_pacman_sync_pmtrans_opts;
-               break;
+                       break;
default:
-                       ops = NULL;
// Be more verbose about the trans type
_pacman_log(PM_LOG_ERROR,
_("could not initialize transaction: Unknown Transaction Type %d"), type);
@@ -243,6 +240,857 @@ int _pacman_trans_set_state(pmtrans_t *trans, int 
new_state)
return(0);
}

+/* Helper functions for _pacman_list_remove
+ */
+static
+int _pacman_syncpkg_cmp(const void *s1, const void *s2)
+{
+       return(strcmp(((pmsyncpkg_t *)s1)->pkg->name(), ((pmsyncpkg_t 
*)s2)->pkg->name()));
+}
+
+int _pacman_sync_addtarget(pmtrans_t *trans, const char *name)
+{
+       char targline[PKG_FULLNAME_LEN];
+       char *targ;
+       pmlist_t *j;
+       Package *pkg_local;
+       Package *spkg = NULL;
+       int cmp;
+       Database *db_local = trans->handle->db_local;
+       pmlist_t *dbs_sync = trans->handle->dbs_sync;
+
+       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));
+
+       STRNCPY(targline, name, PKG_FULLNAME_LEN);
+       targ = strchr(targline, '/');
+       if(targ) {
+               *targ = '\0';
+               targ++;
+               for(j = dbs_sync; j && !spkg; j = j->next) {
+                       Database *dbs = j->data;
+                       if(strcmp(dbs->treename, targline) == 0) {
+                               spkg = _pacman_db_get_pkgfromcache(dbs, targ);
+                               if(spkg == NULL) {
+                                       /* Search provides */
+                                       pmlist_t *p;
+                                       _pacman_log(PM_LOG_FLOW2, _("target 
'%s' not found -- looking for provisions"), targ);
+                                       p = _pacman_db_whatprovides(dbs, targ);
+                                       if(p == NULL) {
+                                               RET_ERR(PM_ERR_PKG_NOT_FOUND, 
-1);
+                                       }
+                                       _pacman_log(PM_LOG_DEBUG, _("found '%s' 
as a provision for '%s'"), p->data, targ);
+                                       spkg = _pacman_db_get_pkgfromcache(dbs, 
p->data);
+                                       FREELISTPTR(p);
+                               }
+                       }
+               }
+       } else {
+               targ = targline;
+               for(j = dbs_sync; j && !spkg; j = j->next) {
+                       Database *dbs = j->data;
+                       spkg = _pacman_db_get_pkgfromcache(dbs, targ);
+               }
+               if(spkg == NULL) {
+                       /* Search provides */
+                       _pacman_log(PM_LOG_FLOW2, _("target '%s' not found -- 
looking for provisions"), targ);
+                       for(j = dbs_sync; j && !spkg; j = j->next) {
+                               Database *dbs = j->data;
+                               pmlist_t *p = _pacman_db_whatprovides(dbs, 
targ);
+                               if(p) {
+                                       _pacman_log(PM_LOG_DEBUG, _("found '%s' 
as a provision for '%s'"), p->data, targ);
+                                       spkg = _pacman_db_get_pkgfromcache(dbs, 
p->data);
+                                       FREELISTPTR(p);
+                               }
+                       }
+               }
+       }
+       if(spkg == NULL) {
+               RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+       }
+
+       pkg_local = _pacman_db_get_pkgfromcache(db_local, spkg->name());
+       if(pkg_local) {
+               cmp = _pacman_versioncmp(pkg_local->version(), spkg->version());
+               if(cmp > 0) {
+                       /* pkg_local version is newer -- get confirmation 
before adding */
+                       int resp = 0;
+                       QUESTION(trans, PM_TRANS_CONV_LOCAL_NEWER, pkg_local, 
NULL, NULL, &resp);
+                       if(!resp) {
+                               _pacman_log(PM_LOG_WARNING, _("%s-%s: local 
version is newer -- skipping"), pkg_local->name(), pkg_local->version());
+                               return(0);
+                       }
+               } else if(cmp == 0) {
+                       /* versions are identical -- get confirmation before 
adding */
+                       int resp = 0;
+                       QUESTION(trans, PM_TRANS_CONV_LOCAL_UPTODATE, 
pkg_local, NULL, NULL, &resp);
+                       if(!resp) {
+                               _pacman_log(PM_LOG_WARNING, _("%s-%s is up to 
date -- skipping"), pkg_local->name(), pkg_local->version());
+                               return(0);
+                       }
+               }
+       }
+
+       /* add the package to the transaction */
+       if(!trans->find(spkg->name())) {
+               Package *dummy = NULL;
+               pmsyncpkg_t *ps;
+
+               if(pkg_local) {
+                       dummy = new Package(pkg_local->name(), 
pkg_local->version());
+                       if(dummy == NULL) {
+                               RET_ERR(PM_ERR_MEMORY, -1);
+                       }
+               }
+               ps = new __pmsyncpkg_t(PM_SYNC_TYPE_UPGRADE, spkg, dummy);
+               if(ps == NULL) {
+                       delete dummy;
+                       RET_ERR(PM_ERR_MEMORY, -1);
+               }
+               trans->add(ps, 0);
+       }
+
+       return(0);
+}
+
+static int pkg_cmp(const void *p1, const void *p2)
+{
+       return(strcmp(((Package *)p1)->name(), ((pmsyncpkg_t 
*)p2)->pkg->name()));
+}
+
+static int check_olddelay(void)
+{
+       pmlist_t *i;
+       time_t tm;
+
+       if(!handle->olddelay) {
+               return(0);
+       }
+
+       for(i = handle->dbs_sync; i; i= i->next) {
+               Database *db = i->data;
+               if(db->gettimestamp(&tm) == -1) {
+                       continue;
+               }
+               if(difftime(time(NULL), tm) > handle->olddelay) {
+                       _pacman_log(PM_LOG_WARNING, _("local copy of '%s' repo 
is too old"), db->treename);
+               }
+       }
+       return(0);
+}
+
+int _pacman_sync_prepare(pmtrans_t *trans, pmlist_t **data)
+{
+       pmlist_t *deps = NULL;
+       pmlist_t *list = NULL; /* list allowing checkdeps usage with data from 
trans->packages */
+       pmlist_t *trail = NULL; /* breadcrum list to avoid running into circles 
*/
+       pmlist_t *asked = NULL;
+       pmlist_t *i, *j, *k, *l, *m;
+       int ret = 0;
+       Database *db_local = trans->handle->db_local;
+
+       ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
+       ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+       ASSERT(trans->packages == NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+
+       if(data) {
+               *data = NULL;
+       }
+
+       for(i = trans->syncpkgs; i; i = i->next) {
+               pmsyncpkg_t *ps = i->data;
+               list = _pacman_list_add(list, ps->pkg);
+       }
+
+       if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
+               trail = _pacman_list_new();
+
+               /* Resolve targets dependencies */
+               EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL);
+               _pacman_log(PM_LOG_FLOW1, _("resolving targets dependencies"));
+               for(i = trans->syncpkgs; i; i = i->next) {
+                       Package *spkg = ((pmsyncpkg_t *)i->data)->pkg;
+                       if(_pacman_resolvedeps(trans, spkg, list, trail, data) 
== -1) {
+                               /* pm_errno is set by resolvedeps */
+                               ret = -1;
+                               goto cleanup;
+                       }
+               }
+
+               for(i = list; i; i = i->next) {
+                       /* add the dependencies found by resolvedeps to the 
transaction set */
+                       Package *spkg = i->data;
+                       if(!trans->find(spkg->name())) {
+                               pmsyncpkg_t *ps = new 
__pmsyncpkg_t(PM_SYNC_TYPE_DEPEND, spkg, NULL);
+                               if(ps == NULL) {
+                                       ret = -1;
+                                       goto cleanup;
+                               }
+                               trans->syncpkgs = 
_pacman_list_add(trans->syncpkgs, ps);
+                               _pacman_log(PM_LOG_FLOW2, _("adding package 
%s-%s to the transaction targets"),
+                                               spkg->name(), spkg->version());
+                       } else {
+                               /* remove the original targets from the list if 
requested */
+                               if((trans->flags & PM_TRANS_FLAG_DEPENDSONLY)) {
+                                       /* they are just pointers so we don't 
have to free them */
+                                       trans->syncpkgs = 
_pacman_list_remove(trans->syncpkgs, spkg, pkg_cmp, NULL);
+                               }
+                       }
+               }
+
+               /* re-order w.r.t. dependencies */
+               k = l = NULL;
+               for(i=trans->syncpkgs; i; i=i->next) {
+                       pmsyncpkg_t *s = (pmsyncpkg_t*)i->data;
+                       k = _pacman_list_add(k, s->pkg);
+               }
+               m = _pacman_sortbydeps(k, PM_TRANS_TYPE_ADD);
+               for(i=m; i; i=i->next) {
+                       for(j=trans->syncpkgs; j; j=j->next) {
+                               pmsyncpkg_t *s = (pmsyncpkg_t*)j->data;
+                               if(s->pkg==i->data) {
+                                       l = _pacman_list_add(l, s);
+                               }
+                       }
+               }
+               FREELISTPTR(k);
+               FREELISTPTR(m);
+               FREELISTPTR(trans->syncpkgs);
+               trans->syncpkgs = l;
+
+               EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL);
+
+               _pacman_log(PM_LOG_FLOW1, _("looking for unresolvable 
dependencies"));
+               deps = _pacman_checkdeps(trans, PM_TRANS_TYPE_UPGRADE, list);
+               if(!f_ptrlist_empty(deps)) {
+                       if(data) {
+                               *data = deps;
+                       }
+                       pm_errno = PM_ERR_UNSATISFIED_DEPS;
+                       ret = -1;
+                       goto cleanup;
+               }
+
+               FREELISTPTR(trail);
+       }
+
+       if(!(trans->flags & PM_TRANS_FLAG_NOCONFLICTS)) {
+               /* check for inter-conflicts and whatnot */
+               EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL);
+
+               _pacman_log(PM_LOG_FLOW1, _("looking for conflicts"));
+               deps = _pacman_checkconflicts(trans, list);
+               if(!f_ptrlist_empty(deps)) {
+                       int errorout = 0;
+
+                       for(i = deps; i && !errorout; i = i->next) {
+                               pmdepmissing_t *miss = i->data;
+                               int found = 0;
+                               pmsyncpkg_t *ps;
+                               Package *local;
+
+                               _pacman_log(PM_LOG_FLOW2, _("package '%s' is 
conflicting with '%s'"),
+                                                 miss->target, 
miss->depend.name);
+
+                               /* check if the conflicting package is one 
that's about to be removed/replaced.
+                                * if so, then just ignore it
+                                */
+                               for(j = trans->syncpkgs; j && !found; j = 
j->next) {
+                                       ps = j->data;
+                                       if(ps->type == PM_SYNC_TYPE_REPLACE) {
+                                               
if(_pacman_pkg_isin(miss->depend.name, ps->data)) {
+                                                       found = 1;
+                                               }
+                                       }
+                               }
+                               if(found) {
+                                       _pacman_log(PM_LOG_DEBUG, _("'%s' is 
already elected for removal -- skipping"),
+                                                       miss->depend.name);
+                                       continue;
+                               }
+
+                               ps = trans->find(miss->target);
+                               if(ps == NULL) {
+                                       _pacman_log(PM_LOG_DEBUG, _("'%s' not 
found in transaction set -- skipping"),
+                                                         miss->target);
+                                       continue;
+                               }
+                               local = _pacman_db_get_pkgfromcache(db_local, 
miss->depend.name);
+                               /* check if this package also "provides" the 
package it's conflicting with
+                                */
+                               if(ps->pkg->provides(miss->depend.name)) {
+                                       /* so just treat it like a "replaces" 
item so the REQUIREDBY
+                                        * fields are inherited properly.
+                                        */
+                                       _pacman_log(PM_LOG_DEBUG, _("package 
'%s' provides its own conflict"), miss->target);
+                                       if(local) {
+                                               /* nothing to do for now: it 
will be handled later
+                                                * (not the same behavior as in 
pacman) */
+                                       } else {
+                                               char *rmpkg = NULL;
+                                               int target, depend;
+                                               /* hmmm, depend.name isn't 
installed, so it must be conflicting
+                                                * with another package in our 
final list.  For example:
+                                                *
+                                                *     pacman-g2 -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 = 
_pacman_list_is_strin(miss->target, trans->targets);
+                                               depend = 
_pacman_list_is_strin(miss->depend.name, trans->targets);
+                                               if(depend && !target) {
+                                                       
_pacman_log(PM_LOG_DEBUG, _("'%s' is in the target list -- keeping it"),
+                                                               
miss->depend.name);
+                                                       /* remove miss->target 
*/
+                                                       rmpkg = miss->target;
+                                               } else if(target && !depend) {
+                                                       
_pacman_log(PM_LOG_DEBUG, _("'%s' is in the target list -- keeping it"),
+                                                               miss->target);
+                                                       /* remove 
miss->depend.name */
+                                                       rmpkg = 
miss->depend.name;
+                                               } else {
+                                                       /* miss->depend.name is 
not needed, miss->target already provides
+                                                        * it, let's resolve 
the conflict */
+                                                       rmpkg = 
miss->depend.name;
+                                               }
+                                               if(rmpkg) {
+                                                       pmsyncpkg_t *rsync = 
trans->find(rmpkg);
+                                                       pmsyncpkg_t *spkg = 
NULL;
+
+                                                       
_pacman_log(PM_LOG_FLOW2, _("removing '%s' from target list"), rmpkg);
+                                                       trans->syncpkgs = 
_pacman_list_remove(trans->syncpkgs, rsync, _pacman_syncpkg_cmp, (void 
**)&spkg);
+                                                       delete spkg;
+                                                       continue;
+                                               }
+                                       }
+                               }
+                               /* It's a conflict -- see if they want to 
remove it
+                               */
+                               _pacman_log(PM_LOG_DEBUG, _("resolving package 
'%s' conflict"), miss->target);
+                               if(local) {
+                                       int doremove = 0;
+                                       
if(!_pacman_list_is_strin(miss->depend.name, asked)) {
+                                               QUESTION(trans, 
PM_TRANS_CONV_CONFLICT_PKG, miss->target, miss->depend.name, NULL, &doremove);
+                                               asked = 
_pacman_stringlist_append(asked, miss->depend.name);
+                                               if(doremove) {
+                                                       pmsyncpkg_t *rsync = 
trans->find(miss->depend.name);
+                                                       Package *q = new 
Package(miss->depend.name, NULL);
+                                                       if(q == NULL) {
+                                                               if(data) {
+                                                                       
FREELIST(*data);
+                                                               }
+                                                               ret = -1;
+                                                               goto cleanup;
+                                                       }
+                                                       q->m_requiredby = 
_pacman_list_strdup(local->requiredby());
+                                                       if(ps->type != 
PM_SYNC_TYPE_REPLACE) {
+                                                               /* switch this 
sync type to REPLACE */
+                                                               ps->type = 
PM_SYNC_TYPE_REPLACE;
+                                                               delete ps->data;
+                                                               ps->data = NULL;
+                                                       }
+                                                       /* append to the 
replaces list */
+                                                       
_pacman_log(PM_LOG_FLOW2, _("electing '%s' for removal"), miss->depend.name);
+                                                       ps->data = 
_pacman_list_add(ps->data, q);
+                                                       if(rsync) {
+                                                               /* remove it 
from the target list */
+                                                               pmsyncpkg_t 
*spkg = NULL;
+
+                                                               
_pacman_log(PM_LOG_FLOW2, _("removing '%s' from target list"), 
miss->depend.name);
+                                                               trans->syncpkgs 
= _pacman_list_remove(trans->syncpkgs, rsync, _pacman_syncpkg_cmp, (void 
**)&spkg);
+                                                               delete spkg;
+                                                       }
+                                               } else {
+                                                       /* abort */
+                                                       
_pacman_log(PM_LOG_ERROR, _("unresolvable package conflicts detected"));
+                                                       errorout = 1;
+                                                       if(data) {
+                                                               if((miss = 
_pacman_malloc(sizeof(pmdepmissing_t))) == NULL) {
+                                                                       
FREELIST(*data);
+                                                                       ret = 
-1;
+                                                                       goto 
cleanup;
+                                                               }
+                                                               *miss = 
*(pmdepmissing_t *)i->data;
+                                                               *data = 
_pacman_list_add(*data, miss);
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       _pacman_log(PM_LOG_ERROR, 
_("unresolvable package conflicts detected"));
+                                       errorout = 1;
+                                       if(data) {
+                                               if((miss = 
_pacman_malloc(sizeof(pmdepmissing_t))) == NULL) {
+                                                       FREELIST(*data);
+                                                       ret = -1;
+                                                       goto cleanup;
+                                               }
+                                               *miss = *(pmdepmissing_t 
*)i->data;
+                                               *data = _pacman_list_add(*data, 
miss);
+                                       }
+                               }
+                       }
+                       if(errorout) {
+                               pm_errno = PM_ERR_CONFLICTING_DEPS;
+                               ret = -1;
+                               goto cleanup;
+                       }
+                       FREELIST(deps);
+                       FREELIST(asked);
+               }
+               EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL);
+       }
+
+       FREELISTPTR(list);
+
+       /* XXX: this fails for cases where a requested package wants
+        *      a dependency that conflicts with an older version of
+        *      the package.  It will be removed from final, and the user
+        *      has to re-request it to get it installed properly.
+        *
+        *      Not gonna happen very often, but should be dealt with...
+        */
+
+       if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
+               /* Check dependencies of packages in rmtargs and make sure
+                * we won't be breaking anything by removing them.
+                * If a broken dep is detected, make sure it's not from a
+                * package that's in our final (upgrade) list.
+                */
+               /*EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL);*/
+               for(i = trans->syncpkgs; i; i = i->next) {
+                       pmsyncpkg_t *ps = i->data;
+                       if(ps->type == PM_SYNC_TYPE_REPLACE) {
+                               for(j = ps->data; j; j = j->next) {
+                                       list = _pacman_list_add(list, j->data);
+                               }
+                       }
+               }
+               if(list) {
+                       _pacman_log(PM_LOG_FLOW1, _("checking dependencies of 
packages designated for removal"));
+                       deps = _pacman_checkdeps(trans, PM_TRANS_TYPE_REMOVE, 
list);
+                       if(deps) {
+                               int errorout = 0;
+                               for(i = deps; i; i = i->next) {
+                                       pmdepmissing_t *miss = i->data;
+                                       if(!trans->find(miss->depend.name)) {
+                                               int pfound = 0;
+                                               /* If miss->depend.name depends 
on something that miss->target and a
+                                                * package in final both 
provide, then it's okay...  */
+                                               Package *leavingp  = 
_pacman_db_get_pkgfromcache(db_local, miss->target);
+                                               Package *conflictp = 
_pacman_db_get_pkgfromcache(db_local, miss->depend.name);
+                                               if(!leavingp || !conflictp) {
+                                                       
_pacman_log(PM_LOG_ERROR, _("something has gone horribly wrong"));
+                                                       ret = -1;
+                                                       goto cleanup;
+                                               }
+                                               /* Look through the upset 
package's dependencies and try to match one up
+                                                * to a provisio from the 
package we want to remove */
+                                               for(k = conflictp->depends(); k 
&& !pfound; k = k->next) {
+                                                       pmlist_t *m;
+                                                       for(m = 
leavingp->provides(); m && !pfound; m = m->next) {
+                                                               
if(!strcmp(k->data, m->data)) {
+                                                                       /* 
Found a match -- now look through final for a package that
+                                                                        * 
provides the same thing.  If none are found, then it truly
+                                                                        * is 
an unresolvable conflict. */
+                                                                       
pmlist_t *n, *o;
+                                                                       for(n = 
trans->syncpkgs; n && !pfound; n = n->next) {
+                                                                               
pmsyncpkg_t *sp = n->data;
+                                                                               
for(o = sp->pkg->provides(); o && !pfound; o = o->next) {
+                                                                               
        if(!strcmp(m->data, o->data)) {
+                                                                               
                /* found matching provisio -- we're good to go */
+                                                                               
                _pacman_log(PM_LOG_FLOW2, _("found '%s' as a provision for '%s' 
-- conflict aborted"),
+                                                                               
                                sp->pkg->name(), (char *)o->data);
+                                                                               
                pfound = 1;
+                                                                               
        }
+                                                                               
}
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               if(!pfound) {
+                                                       if(!errorout) {
+                                                               errorout = 1;
+                                                       }
+                                                       if(data) {
+                                                               if((miss = 
_pacman_malloc(sizeof(pmdepmissing_t))) == NULL) {
+                                                                       
FREELIST(*data);
+                                                                       ret = 
-1;
+                                                                       goto 
cleanup;
+                                                               }
+                                                               *miss = 
*(pmdepmissing_t *)i->data;
+                                                               *data = 
_pacman_list_add(*data, miss);
+                                                       }
+                                               }
+                                       }
+                               }
+                               if(errorout) {
+                                       pm_errno = PM_ERR_UNSATISFIED_DEPS;
+                                       ret = -1;
+                                       goto cleanup;
+                               }
+                               FREELIST(deps);
+                       }
+               }
+               /*EVENT(trans, PM_TRANS_EVT_CHECKDEPS_DONE, NULL, NULL);*/
+       }
+
+#ifndef __sun__
+       /* check for free space only in case the packages will be extracted */
+       if(!(trans->flags & PM_TRANS_FLAG_NOCONFLICTS)) {
+               if(_pacman_check_freespace(trans, data) == -1) {
+                               /* pm_errno is set by check_freespace */
+                               ret = -1;
+                               goto cleanup;
+               }
+       }
+#endif
+
+       /* issue warning if the local db is too old */
+       check_olddelay();
+
+cleanup:
+       FREELISTPTR(list);
+       FREELISTPTR(trail);
+       FREELIST(asked);
+
+       return(ret);
+}
+
+int _pacman_sync_commit(pmtrans_t *trans, pmlist_t **data)
+{
+       pmlist_t *i, *j;
+       pmtrans_t *tr = NULL;
+       int replaces = 0;
+       Database *db_local = trans->handle->db_local;
+
+       ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
+       ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+
+       if(handle->sysupgrade) {
+               _pacman_runhook("pre_sysupgrade", trans);
+       }
+       /* remove conflicting and to-be-replaced packages */
+       tr = new __pmtrans_t(PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAG_NODEPS, 
trans->cbs);
+       if(tr == NULL) {
+               _pacman_log(PM_LOG_ERROR, _("could not create removal 
transaction"));
+               pm_errno = PM_ERR_MEMORY;
+               goto error;
+       }
+       for(i = trans->syncpkgs; i; i = i->next) {
+               pmsyncpkg_t *ps = i->data;
+               if(ps->type == PM_SYNC_TYPE_REPLACE) {
+                       for(j = ps->data; j; j = j->next) {
+                               Package *pkg = j->data;
+                               if(!_pacman_pkg_isin(pkg->name(), 
tr->packages)) {
+                                       if(tr->add(pkg->name()) == -1) {
+                                               goto error;
+                                       }
+                                       replaces++;
+                               }
+                       }
+               }
+       }
+       if(replaces) {
+               _pacman_log(PM_LOG_FLOW1, _("removing conflicting and 
to-be-replaced packages"));
+               if(tr->prepare(data) == -1) {
+                       _pacman_log(PM_LOG_ERROR, _("could not prepare removal 
transaction"));
+                       goto error;
+               }
+               /* we want the frontend to be aware of commit details */
+               tr->cbs.event = trans->cbs.event;
+               if(tr->commit(NULL) == -1) {
+                       _pacman_log(PM_LOG_ERROR, _("could not commit removal 
transaction"));
+                       goto error;
+               }
+       }
+       delete tr;
+       tr = NULL;
+
+       /* install targets */
+       _pacman_log(PM_LOG_FLOW1, _("installing packages"));
+       tr = new __pmtrans_t(PM_TRANS_TYPE_UPGRADE, trans->flags | 
PM_TRANS_FLAG_NODEPS, trans->cbs);
+       if(tr == NULL) {
+               _pacman_log(PM_LOG_ERROR, _("could not create transaction"));
+               pm_errno = PM_ERR_MEMORY;
+               goto error;
+       }
+       for(i = trans->syncpkgs; i; i = i->next) {
+               pmsyncpkg_t *ps = i->data;
+               Package *spkg = ps->pkg;
+               char str[PATH_MAX];
+               snprintf(str, PATH_MAX, "%s%s/%s-%s-%s" PM_EXT_PKG, 
handle->root, handle->cachedir, spkg->name(), spkg->version(), spkg->arch);
+               if(tr->add(str) == -1) {
+                       goto error;
+               }
+               /* using _pacman_list_last() is ok because addtarget() adds the 
new target at the
+                * end of the tr->packages list */
+               spkg = _pacman_list_last(tr->packages)->data;
+               if(ps->type == PM_SYNC_TYPE_DEPEND || trans->flags & 
PM_TRANS_FLAG_ALLDEPS) {
+                       spkg->m_reason = PM_PKG_REASON_DEPEND;
+               } else if(ps->type == PM_SYNC_TYPE_UPGRADE && 
!handle->sysupgrade) {
+                       spkg->m_reason = PM_PKG_REASON_EXPLICIT;
+               }
+       }
+       if(tr->prepare(data) == -1) {
+               _pacman_log(PM_LOG_ERROR, _("could not prepare transaction"));
+               /* pm_errno is set by trans_prepare */
+               goto error;
+       }
+       if(tr->commit(NULL) == -1) {
+               _pacman_log(PM_LOG_ERROR, _("could not commit transaction"));
+               goto error;
+       }
+       delete tr;
+       tr = NULL;
+
+       /* propagate replaced packages' requiredby fields to their new owners */
+       if(replaces) {
+               _pacman_log(PM_LOG_FLOW1, _("updating database for replaced 
packages' dependencies"));
+               for(i = trans->syncpkgs; i; i = i->next) {
+                       pmsyncpkg_t *ps = i->data;
+                       if(ps->type == PM_SYNC_TYPE_REPLACE) {
+                               Package *pkg_new = 
_pacman_db_get_pkgfromcache(db_local, ps->pkg_name);
+                               for(j = ps->data; j; j = j->next) {
+                                       pmlist_t *k;
+                                       Package *old = j->data;
+                                       /* merge lists */
+                                       for(k = old->requiredby(); k; k = 
k->next) {
+                                               
if(!_pacman_list_is_strin(k->data, pkg_new->requiredby())) {
+                                                       /* replace old's name 
with new's name in the requiredby's dependency list */
+                                                       pmlist_t *m;
+                                                       Package *depender = 
_pacman_db_get_pkgfromcache(db_local, k->data);
+                                                       if(depender == NULL) {
+                                                               /* If the 
depending package no longer exists in the local db,
+                                                                * then it must 
have ALSO conflicted with ps->pkg.  If
+                                                                * that's the 
case, then we don't have anything to propagate
+                                                                * here. */
+                                                               continue;
+                                                       }
+                                                       for(m = 
depender->depends(); m; m = m->next) {
+                                                               
if(!strcmp(m->data, old->name())) {
+                                                                       
FREE(m->data);
+                                                                       m->data 
= strdup(pkg_new->name());
+                                                               }
+                                                       }
+                                                       
if(db_local->write(depender, INFRQ_DEPENDS) == -1) {
+                                                               
_pacman_log(PM_LOG_ERROR, _("could not update requiredby for database entry 
%s-%s"),
+                                                                               
  pkg_new->name(), pkg_new->version());
+                                                       }
+                                                       /* add the new 
requiredby */
+                                                       pkg_new->m_requiredby = 
_pacman_stringlist_append(pkg_new->m_requiredby, k->data);
+                                               }
+                                       }
+                               }
+                               if(db_local->write(pkg_new, INFRQ_DEPENDS) == 
-1) {
+                                       _pacman_log(PM_LOG_ERROR, _("could not 
update new database entry %s-%s"),
+                                                         pkg_new->name(), 
pkg_new->version());
+                               }
+                       }
+               }
+       }
+
+       if(handle->sysupgrade) {
+               _pacman_runhook("post_sysupgrade", trans);
+       }
+       return(0);
+
+error:
+       delete tr;
+       /* commiting failed, so this is still just a prepared transaction */
+       return(-1);
+}
+
+int _pacman_trans_download_commit(pmtrans_t *trans, pmlist_t **data)
+{
+       pmlist_t *i, *j, *files = NULL;
+       char ldir[PATH_MAX];
+    int doremove, retval = 0, tries = 0;
+       int varcache = 1;
+
+       ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+
+       trans->state = STATE_DOWNLOADING;
+       /* group sync records by repository and download */
+       snprintf(ldir, PATH_MAX, "%s%s", handle->root, handle->cachedir);
+
+       for(tries = 0; tries < handle->maxtries; tries++) {
+               retval = 0;
+               FREELIST(*data);
+               int done = 1;
+               for(i = handle->dbs_sync; i; i = i->next) {
+                       struct stat buf;
+                       Database *current = i->data;
+
+                       for(j = trans->syncpkgs; j; j = j->next) {
+                               pmsyncpkg_t *ps = j->data;
+                               Package *spkg = ps->pkg;
+                               Database *dbs = spkg->data;
+
+                               if(current == dbs) {
+                                       char filename[PATH_MAX];
+                                       char lcpath[PATH_MAX];
+                                       spkg->filename(filename, 
sizeof(filename));
+                                       snprintf(lcpath, sizeof(lcpath), 
"%s/%s", ldir, filename);
+
+                                       if(trans->flags & 
PM_TRANS_FLAG_PRINTURIS) {
+                                               if (!(trans->flags & 
PM_TRANS_FLAG_PRINTURIS_CACHED)) {
+                                                       if (stat(lcpath, &buf) 
== 0) {
+                                                               continue;
+                                                       }
+                                               }
+
+                                               EVENT(trans, 
PM_TRANS_EVT_PRINTURI, pacman_db_getinfo(c_cast(current), PM_DB_FIRSTSERVER), 
filename);
+                                       } else {
+                                               if(stat(lcpath, &buf)) {
+                                                       /* file is not in the 
cache dir, so add it to the list */
+                                                       files = 
_pacman_stringlist_append(files, filename);
+                                               } else {
+                                                       
_pacman_log(PM_LOG_DEBUG, _("%s is already in the cache\n"), filename);
+                                               }
+                                       }
+                               }
+                       }
+
+                       if(files) {
+                               EVENT(trans, PM_TRANS_EVT_RETRIEVE_START, 
current->treename, NULL);
+                               if(stat(ldir, &buf)) {
+                                       /* no cache directory.... try creating 
it */
+                                       _pacman_log(PM_LOG_WARNING, _("no %s 
cache exists.  creating..."), ldir);
+                                       if(_pacman_makepath(ldir)) {
+                                               /* couldn't mkdir the cache 
directory, so fall back to /tmp and unlink
+                                                * the package afterwards.
+                                                */
+                                               _pacman_log(PM_LOG_WARNING, 
_("couldn't create package cache, using /tmp instead"));
+                                               snprintf(ldir, PATH_MAX, 
"%s/tmp", handle->root);
+                                               
if(pacman_set_option(PM_OPT_CACHEDIR, (long)"/tmp") == -1) {
+                                                       
_pacman_log(PM_LOG_WARNING, _("failed to set option CACHEDIR (%s)\n"), 
pacman_strerror(pm_errno));
+                                                       
RET_ERR(PM_ERR_RETRIEVE, -1);
+                                               }
+                                               varcache = 0;
+                                       }
+                               }
+                               if(_pacman_downloadfiles(current->servers, 
ldir, files, tries) == -1) {
+                                       _pacman_log(PM_LOG_WARNING, _("failed 
to retrieve some files from %s\n"), current->treename);
+                                       retval=1;
+                                       done = 0;
+                               }
+                               FREELIST(files);
+                       }
+               }
+               if (!done)
+                       continue;
+               if(trans->flags & PM_TRANS_FLAG_PRINTURIS) {
+                       return(0);
+               }
+
+               /* Check integrity of files */
+               if(!(trans->flags & PM_TRANS_FLAG_NOINTEGRITY)) {
+                       EVENT(trans, PM_TRANS_EVT_INTEGRITY_START, NULL, NULL);
+
+                       for(i = trans->syncpkgs; i; i = i->next) {
+                               pmsyncpkg_t *ps = i->data;
+                               Package *spkg = ps->pkg;
+                               char str[PATH_MAX], pkgname[PATH_MAX];
+                               char *md5sum1, *md5sum2, *sha1sum1, *sha1sum2;
+                               char *ptr=NULL;
+
+                               spkg->filename(pkgname, sizeof(pkgname));
+                               md5sum1 = spkg->md5sum;
+                               sha1sum1 = spkg->sha1sum;
+
+                               if((md5sum1 == NULL) && (sha1sum1 == NULL)) {
+                                       if((ptr = (char *)malloc(512)) == NULL) 
{
+                                               RET_ERR(PM_ERR_MEMORY, -1);
+                                       }
+                                       snprintf(ptr, 512, _("can't get md5 or 
sha1 checksum for package %s\n"), pkgname);
+                                       *data = _pacman_list_add(*data, ptr);
+                                       retval = 1;
+                                       continue;
+                               }
+                               snprintf(str, PATH_MAX, "%s/%s/%s", 
handle->root, handle->cachedir, pkgname);
+                               md5sum2 = _pacman_MDFile(str);
+                               sha1sum2 = _pacman_SHAFile(str);
+                               if(md5sum2 == NULL && sha1sum2 == NULL) {
+                                       if((ptr = (char *)malloc(512)) == NULL) 
{
+                                               RET_ERR(PM_ERR_MEMORY, -1);
+                                       }
+                                       snprintf(ptr, 512, _("can't get md5 or 
sha1 checksum for package %s\n"), pkgname);
+                                       *data = _pacman_list_add(*data, ptr);
+                                       retval = 1;
+                                       continue;
+                               }
+                               if((strcmp(md5sum1, md5sum2) != 0) && 
(strcmp(sha1sum1, sha1sum2) != 0)) {
+                                       _pacman_log(PM_LOG_DEBUG, _("expected 
md5:  '%s'"), md5sum1);
+                                       _pacman_log(PM_LOG_DEBUG, _("actual 
md5:    '%s'"), md5sum2);
+                                       _pacman_log(PM_LOG_DEBUG, _("expected 
sha1: '%s'"), sha1sum1);
+                                       _pacman_log(PM_LOG_DEBUG, _("actual 
sha1:   '%s'"), sha1sum2);
+
+                                       doremove = 0;
+                                       if((ptr = (char *)malloc(512)) == NULL) 
{
+                                               RET_ERR(PM_ERR_MEMORY, -1);
+                                       }
+                                       if(trans->flags & 
PM_TRANS_FLAG_ALLDEPS) {
+                                               doremove=1;
+                                       } else {
+                                               QUESTION(trans, 
PM_TRANS_CONV_CORRUPTED_PKG, pkgname, NULL, NULL, &doremove);
+                                       }
+                                       if(doremove) {
+                                               snprintf(str, PATH_MAX, 
"%s%s/%s-%s-%s" PM_EXT_PKG, handle->root, handle->cachedir, spkg->name(), 
spkg->version(), spkg->arch);
+                                               unlink(str);
+                                               snprintf(ptr, 512, _("archive 
%s was corrupted (bad MD5 or SHA1 checksum)\n"), pkgname);
+                                       } else {
+                                               snprintf(ptr, 512, _("archive 
%s is corrupted (bad MD5 or SHA1 checksum)\n"), pkgname);
+                                       }
+                                       *data = _pacman_list_add(*data, ptr);
+                                       retval = 1;
+                               }
+                               FREE(md5sum2);
+                               FREE(sha1sum2);
+                       }
+                       if(!retval) {
+                               break;
+                       }
+               }
+       }
+
+       if(retval) {
+               pm_errno = PM_ERR_PKG_CORRUPTED;
+               goto error;
+       }
+       if(!(trans->flags & PM_TRANS_FLAG_NOINTEGRITY)) {
+               EVENT(trans, PM_TRANS_EVT_INTEGRITY_DONE, NULL, NULL);
+       }
+       if(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY) {
+               return(0);
+       }
+       if(!retval) {
+               trans->state = STATE_COMMITING;
+               retval = _pacman_sync_commit(trans, data);
+               if(retval) {
+                       goto error;
+               }
+       }
+
+       if(!varcache && !(trans->flags & PM_TRANS_FLAG_DOWNLOADONLY)) {
+               /* delete packages */
+               for(i = files; i; i = i->next) {
+                       unlink(i->data);
+               }
+       }
+       return(retval);
+
+error:
+       /* commiting failed, so this is still just a prepared transaction */
+       return(-1);
+}
+
pmsyncpkg_t *__pmtrans_t::add(pmsyncpkg_t *syncpkg, int flags)
{
pmsyncpkg_t *syncpkg_queued;
@@ -340,9 +1188,8 @@ int __pmtrans_t::add(const char *target)
RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1);
}

-       if(ops != NULL && ops->addtarget != NULL) {
-               if(ops->addtarget(this, target) == -1) {
-                       /* pm_errno is set by trans->ops->addtarget() */
+       if(type == PM_TRANS_TYPE_SYNC) {
+               if(_pacman_sync_addtarget(this, target) == -1) {
return(-1);
}
} else {
@@ -599,9 +1446,8 @@ int __pmtrans_t::prepare(pmlist_t **data)

_pacman_trans_compute_triggers(this);

-       if(ops != NULL && ops->prepare != NULL) {
-               if(ops->prepare(this, data) == -1) {
-                       /* pm_errno is set by ops->prepare() */
+       if(type == PM_TRANS_TYPE_SYNC) {
+               if(_pacman_sync_prepare(this, data) == -1) {
return(-1);
}
} else {
@@ -1359,9 +2205,8 @@ int __pmtrans_t::commit(pmlist_t **data)

_pacman_trans_set_state(this, STATE_COMMITING);

-       if(ops != NULL && ops->commit != NULL) {
-               if(ops->commit(this, data) == -1) {
-                       /* pm_errno is set by ops->commit() */
+       if(type == PM_TRANS_TYPE_SYNC) {
+               if(_pacman_trans_download_commit(this, data) == -1) {
_pacman_trans_set_state(this, STATE_PREPARED);
return(-1);
}
diff --git a/lib/libpacman/trans.h b/lib/libpacman/trans.h
index 0679cd9..505e60a 100644
--- a/lib/libpacman/trans.h
+++ b/lib/libpacman/trans.h
@@ -48,12 +48,6 @@ enum {
STATE_MAX
};

-typedef struct __pmtrans_ops_t {
-       int (*addtarget)(pmtrans_t *trans, const char *name);
-       int (*prepare)(pmtrans_t *trans, pmlist_t **data);
-       int (*commit)(pmtrans_t *trans, pmlist_t **data);
-} pmtrans_ops_t;
-
typedef struct __pmtrans_cbs_t {
pacman_trans_cb_event event;
pacman_trans_cb_conv conv;
@@ -76,7 +70,6 @@ struct __pmtrans_t
pmsyncpkg_t *add(const char *target, pmtranstype_t type, int flags);
int add(const char *target);

-       const pmtrans_ops_t *ops;
int (*set_state)(pmtrans_t *trans, int new_state);
libpacman::Handle *handle;
pmtranstype_t type;
_______________________________________________
Frugalware-git mailing list
[email protected]
http://frugalware.org/mailman/listinfo/frugalware-git

Reply via email to