summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/sync.c')
-rw-r--r--lib/libalpm/sync.c349
1 files changed, 142 insertions, 207 deletions
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index ced20c5a..efdfa203 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -72,30 +72,12 @@ void _alpm_sync_free(pmsyncpkg_t *sync)
/* TODO wow this is ugly */
if(sync->type == PM_SYNC_TYPE_REPLACE) {
- alpm_list_free_inner(sync->data, (alpm_list_fn_free)_alpm_pkg_free);
alpm_list_free(sync->data);
- sync->data = NULL;
- } else {
- _alpm_pkg_free(sync->data);
- sync->data = NULL;
}
+ sync->data = NULL;
FREE(sync);
}
-static void synclist_free(alpm_list_t *syncpkgs)
-{
- if(syncpkgs) {
- alpm_list_t *tmp;
- for(tmp = syncpkgs; tmp; tmp = alpm_list_next(tmp)) {
- if(tmp->data) {
- _alpm_sync_free(tmp->data);
- }
- }
- alpm_list_free(syncpkgs);
- }
-
-}
-
/* Find recommended replacements for packages during a sync.
*/
static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,
@@ -147,27 +129,23 @@ static int find_replacements(pmtrans_t *trans, pmdb_t *db_local,
* the package to replace.
*/
pmsyncpkg_t *sync;
- pmpkg_t *dummy = _alpm_pkg_dup(lpkg);
- if(dummy == NULL) {
- pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
- return(-1);
- }
+
/* check if spkg->name is already in the packages list. */
sync = _alpm_sync_find(*syncpkgs, alpm_pkg_get_name(spkg));
if(sync) {
/* found it -- just append to the replaces list */
- sync->data = alpm_list_add(sync->data, dummy);
+ sync->data = alpm_list_add(sync->data, lpkg);
} else {
/* none found -- enter pkg into the final sync list */
sync = _alpm_sync_new(PM_SYNC_TYPE_REPLACE, spkg, NULL);
if(sync == NULL) {
- _alpm_pkg_free(dummy);
pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
+ alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free);
+ alpm_list_free(*syncpkgs);
+ *syncpkgs = NULL;
return(-1);
}
- sync->data = alpm_list_add(NULL, dummy);
+ sync->data = alpm_list_add(NULL, lpkg);
*syncpkgs = alpm_list_add(*syncpkgs, sync);
}
_alpm_log(PM_LOG_DEBUG, "%s-%s elected for upgrade (to be replaced by %s-%s)\n",
@@ -251,17 +229,12 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans,
continue;
}
- pmpkg_t *tmp = _alpm_pkg_dup(local);
- if(tmp == NULL) {
- pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
- return(-1);
- }
- sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, tmp);
+ sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, local);
if(sync == NULL) {
- _alpm_pkg_free(tmp);
pm_errno = PM_ERR_MEMORY;
- synclist_free(*syncpkgs);
+ alpm_list_free_inner(*syncpkgs, (alpm_list_fn_free)_alpm_sync_free);
+ alpm_list_free(*syncpkgs);
+ *syncpkgs = NULL;
return(-1);
}
*syncpkgs = alpm_list_add(*syncpkgs, sync);
@@ -274,7 +247,7 @@ int _alpm_sync_sysupgrade(pmtrans_t *trans,
int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, char *name)
{
- char targline[PKG_FULLNAME_LEN];
+ char *targline;
char *targ;
alpm_list_t *j;
pmpkg_t *local;
@@ -287,8 +260,8 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
ASSERT(db_local != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
+ STRDUP(targline, name, RET_ERR(PM_ERR_MEMORY, -1));
- strncpy(targline, name, PKG_FULLNAME_LEN);
targ = strchr(targline, '/');
if(targ) {
/* we are looking for a package in a specific database */
@@ -301,13 +274,15 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
repo_found = 1;
spkg = _alpm_db_get_pkgfromcache(db, targ);
if(spkg == NULL) {
- RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_NOT_FOUND;
+ goto error;
}
}
}
if(!repo_found) {
_alpm_log(PM_LOG_ERROR, _("repository '%s' not found\n"), targline);
- RET_ERR(PM_ERR_PKG_REPO_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_REPO_NOT_FOUND;
+ goto error;
}
} else {
targ = targline;
@@ -316,7 +291,8 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
spkg = _alpm_db_get_pkgfromcache(db, targ);
}
if(spkg == NULL) {
- RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+ pm_errno = PM_ERR_PKG_NOT_FOUND;
+ goto error;
}
}
@@ -345,36 +321,36 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
/* add the package to the transaction */
if(!_alpm_sync_find(trans->packages, alpm_pkg_get_name(spkg))) {
- pmpkg_t *dummy = NULL;
- if(local) {
- dummy = _alpm_pkg_dup(local);
- if(dummy == NULL) {
- RET_ERR(PM_ERR_MEMORY, -1);
- }
- }
- sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, dummy);
+ sync = _alpm_sync_new(PM_SYNC_TYPE_UPGRADE, spkg, local);
if(sync == NULL) {
- _alpm_pkg_free(dummy);
- RET_ERR(PM_ERR_MEMORY, -1);
+ pm_errno = PM_ERR_MEMORY;
+ goto error;
}
_alpm_log(PM_LOG_DEBUG, "adding target '%s' to the transaction set\n",
alpm_pkg_get_name(spkg));
trans->packages = alpm_list_add(trans->packages, sync);
}
+ FREE(targline);
return(0);
+
+error:
+ if(targline) {
+ FREE(targline);
+ }
+ return(-1);
}
/* Helper functions for alpm_list_remove
- */
+*/
static int syncpkg_cmp(const void *s1, const void *s2)
{
const pmsyncpkg_t *sp1 = s1;
const pmsyncpkg_t *sp2 = s2;
pmpkg_t *p1, *p2;
- p1 = alpm_sync_get_pkg(sp1);
- p2 = alpm_sync_get_pkg(sp2);
+ p1 = alpm_sync_get_pkg(sp1);
+ p2 = alpm_sync_get_pkg(sp2);
return(strcmp(alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)));
}
@@ -470,172 +446,130 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "looking for conflicts\n");
- deps = _alpm_checkconflicts(db_local, list);
- if(deps) {
- int errorout = 0;
- alpm_list_t *asked = NULL;
- pmconflict_t *conflict = NULL;
-
- for(i = deps; i && !errorout; i = i->next) {
- pmsyncpkg_t *sync;
- pmpkg_t *found = NULL;
-
- conflict = i->data;
- _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
- conflict->package1, conflict->package2);
- /* check if the conflicting package is about to be removed/replaced.
- * if so, then just ignore it. */
- for(j = trans->packages; j && !found; j = j->next) {
- sync = j->data;
- if(sync->type == PM_SYNC_TYPE_REPLACE) {
- found = _alpm_pkg_find(conflict->package2, sync->data);
+
+ /* 1. check for conflicts in the target list */
+ _alpm_log(PM_LOG_DEBUG, "check targets vs targets\n");
+ deps = _alpm_innerconflicts(list);
+
+ for(i = deps; i; i = i->next) {
+ pmconflict_t *conflict = i->data;
+ pmsyncpkg_t *rsync, *sync, *sync1, *sync2;
+
+ /* have we already removed one of the conflicting targets? */
+ sync1 = _alpm_sync_find(trans->packages, conflict->package1);
+ sync2 = _alpm_sync_find(trans->packages, conflict->package2);
+ if(!sync1 || !sync2) {
+ continue;
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "conflicting packages in the sync list: '%s' <-> '%s'\n",
+ conflict->package1, conflict->package2);
+
+ /* if sync1 provides sync2, we remove sync2 from the targets, and vice versa */
+ if(alpm_list_find(alpm_pkg_get_provides(sync1->pkg),
+ conflict->package2, _alpm_prov_cmp)) {
+ rsync = sync2;
+ sync = sync1;
+ } else if(alpm_list_find(alpm_pkg_get_provides(sync2->pkg),
+ conflict->package1, _alpm_prov_cmp)) {
+ rsync = sync1;
+ sync = sync2;
+ } else {
+ _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
+ pm_errno = PM_ERR_CONFLICTING_DEPS;
+ ret = -1;
+ if(data) {
+ pmconflict_t *newconflict = _alpm_conflict_dup(conflict);
+ if(newconflict) {
+ *data = alpm_list_add(*data, newconflict);
}
}
- if(found) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is already elected for removal -- skipping\n",
- alpm_pkg_get_name(found));
- continue;
- }
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
+ goto cleanup;
+ }
- sync = _alpm_sync_find(trans->packages, conflict->package1);
- if(sync == NULL) {
- _alpm_log(PM_LOG_DEBUG, "'%s' not found in transaction set -- skipping\n",
- conflict->package1);
- continue;
- }
- pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
- /* check if this package provides the package it's conflicting with */
- if(alpm_list_find(alpm_pkg_get_provides(sync->pkg),
- conflict->package2, _alpm_prov_cmp)) {
- /* treat like a replaces item so requiredby fields are
- * inherited properly. */
- _alpm_log(PM_LOG_DEBUG, "package '%s' provides its own conflict\n",
- conflict->package1);
- if(!local) {
- char *rmpkg = NULL;
- void *target, *depend;
- /* hmmm, package2 isn't installed, so it must be conflicting
- * with another package in our final list. For example:
- *
- * pacman -S blackbox xfree86
- *
- * If no x-servers are installed and blackbox pulls in xorg, then
- * xorg and xfree86 will conflict with each other. In this case,
- * we should follow the user's preference and rip xorg out of final,
- * opting for xfree86 instead.
- */
-
- /* figure out which one was requested in targets. If they both
- * were, then it's still an unresolvable conflict. */
- target = alpm_list_find_str(trans->targets, conflict->package1);
- depend = alpm_list_find_str(trans->targets, conflict->package2);
- if(depend && !target) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n",
- conflict->package2);
- /* remove conflict->package1 */
- rmpkg = conflict->package1;
- } else if(target && !depend) {
- _alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n",
- conflict->package1);
- /* remove conflict->package2 */
- rmpkg = conflict->package2;
- } else {
- /* miss->target2 is not needed, miss->target already provides
- * it, let's resolve the conflict */
- rmpkg = conflict->package2;
- }
- if(rmpkg) {
- pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages, rmpkg);
- if(rsync) {
- void *vpkg;
- _alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n",
- rsync->pkg->name);
- trans->packages = alpm_list_remove(trans->packages, rsync,
- syncpkg_cmp, &vpkg);
- _alpm_sync_free(vpkg);
- }
- continue;
- }
+ _alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n", rsync->pkg->name);
+ /* Only prints a warning if rsync is an explicit target. */
+ if(alpm_list_find_str(trans->targets, rsync->pkg->name)) {
+ _alpm_log(PM_LOG_WARNING,
+ _("removing '%s' from target list because it conflicts with '%s'\n"),
+ rsync->pkg->name, sync->pkg->name);
+ }
+ void *vpkg;
+ trans->packages = alpm_list_remove(trans->packages, rsync,
+ syncpkg_cmp, &vpkg);
+ pmsyncpkg_t *syncpkg = vpkg;
+ list = alpm_list_remove(list, syncpkg->pkg, _alpm_pkg_cmp, NULL);
+ _alpm_sync_free(syncpkg);
+ continue;
+ }
+
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
+ deps = NULL;
+
+ /* 2. we check for target vs db conflicts (and resolve)*/
+ _alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n");
+ deps = _alpm_outerconflicts(db_local, list);
+
+ for(i = deps; i; i = i->next) {
+ pmconflict_t *conflict = i->data;
+
+ /* if conflict->package2 (the local package) is not elected for removal,
+ we ask the user */
+ int found = 0;
+ for(j = trans->packages; j && !found; j = j->next) {
+ pmsyncpkg_t *sync = j->data;
+ if(sync->type == PM_SYNC_TYPE_REPLACE) {
+ if(_alpm_pkg_find(conflict->package2, sync->data)) {
+ found = 1;
}
}
- /* It's a conflict -- see if they want to remove it */
- _alpm_log(PM_LOG_DEBUG, "resolving package '%s' conflict\n",
- conflict->package1);
- if(local) {
- int doremove = 0;
- if(!alpm_list_find_str(asked, conflict->package2)) {
- QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
+ }
+ if(found) {
+ continue;
+ }
+
+ _alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
+ conflict->package1, conflict->package2);
+
+ pmsyncpkg_t *sync = _alpm_sync_find(trans->packages, conflict->package1);
+ pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
+ int doremove = 0;
+ QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
conflict->package2, NULL, &doremove);
- asked = alpm_list_add(asked, strdup(conflict->package2));
- if(doremove) {
- pmpkg_t *q = _alpm_pkg_dup(local);
- if(sync->type != PM_SYNC_TYPE_REPLACE) {
- /* switch this sync type to REPLACE */
- sync->type = PM_SYNC_TYPE_REPLACE;
- _alpm_pkg_free(sync->data);
- sync->data = NULL;
- }
- /* append to the replaces list */
- _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n",
- conflict->package2);
- sync->data = alpm_list_add(sync->data, q);
- /* see if the package is in the current target list */
- pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages,
- conflict->package2);
- if(rsync) {
- /* remove it from the target list */
- void *vpkg;
- _alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n",
- conflict->package2);
- trans->packages = alpm_list_remove(trans->packages, rsync,
- syncpkg_cmp, &vpkg);
- _alpm_sync_free(vpkg);
- }
- } else {
- /* abort */
- _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
- errorout = 1;
- }
- }
- } else {
- _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
- errorout = 1;
+ if(doremove) {
+ if(sync->type != PM_SYNC_TYPE_REPLACE) {
+ /* switch this sync type to REPLACE */
+ sync->type = PM_SYNC_TYPE_REPLACE;
+ sync->data = NULL;
}
- }
- if(errorout) {
- /* The last conflict was unresolvable, so we duplicate it and add it to *data */
+ /* append to the replaces list */
+ _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2);
+ sync->data = alpm_list_add(sync->data, local);
+ } else { /* abort */
+ _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
pm_errno = PM_ERR_CONFLICTING_DEPS;
+ ret = -1;
if(data) {
- pmconflict_t *lastconflict = conflict;
- if((conflict = malloc(sizeof(pmconflict_t))) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %zd bytes\n"),
- sizeof(pmconflict_t));
- FREELIST(*data);
- pm_errno = PM_ERR_MEMORY;
- } else {
- *conflict = *lastconflict;
- *data = alpm_list_add(*data, conflict);
+ pmconflict_t *newconflict = _alpm_conflict_dup(conflict);
+ if(newconflict) {
+ *data = alpm_list_add(*data, newconflict);
}
}
- FREELIST(asked);
- FREELIST(deps);
- ret = -1;
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
goto cleanup;
}
- FREELIST(asked);
- FREELIST(deps);
}
EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL);
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free);
+ alpm_list_free(deps);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
- /* rebuild remove and list */
- alpm_list_free(list);
- list = NULL;
- for(i = trans->packages; i; i = i->next) {
- pmsyncpkg_t *sync = i->data;
- list = alpm_list_add(list, sync->pkg);
- }
+ /* rebuild remove list */
alpm_list_free(remove);
remove = NULL;
for(i = trans->packages; i; i = i->next) {
@@ -655,7 +589,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
if(data) {
*data = deps;
} else {
- FREELIST(deps);
+ alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(deps);
}
goto cleanup;
}
@@ -776,7 +711,7 @@ static int apply_deltas(pmtrans_t *trans, alpm_list_t *patches)
pmpkg_t *pkg;
pmdelta_t *d;
char command[PATH_MAX], fname[PATH_MAX];
- char pkgfilename[PKG_FILENAME_LEN];
+ char pkgfilename[PATH_MAX];
pkg = alpm_list_getdata(p);
p = alpm_list_next(p);
@@ -811,7 +746,7 @@ static int apply_deltas(pmtrans_t *trans, alpm_list_t *patches)
_alpm_log(PM_LOG_DEBUG, _("command: %s\n"), command);
- snprintf(pkgfilename, PKG_FILENAME_LEN, "%s-%s-%s" PKGEXT,
+ snprintf(pkgfilename, PATH_MAX, "%s-%s-%s" PKGEXT,
pkg->name, d->to, pkg->arch);
EVENT(trans, PM_TRANS_EVT_DELTA_PATCH_START, pkgfilename, d->filename);