summaryrefslogtreecommitdiff
path: root/lib/libalpm/deps.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/deps.c')
-rw-r--r--lib/libalpm/deps.c285
1 files changed, 121 insertions, 164 deletions
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c
index ac07c0b7..4a4f6545 100644
--- a/lib/libalpm/deps.c
+++ b/lib/libalpm/deps.c
@@ -121,7 +121,7 @@ static alpm_list_t *_alpm_graph_init(alpm_list_t *targets)
for(i = vertices; i; i = i->next) {
pmgraph_t *vertex_i = i->data;
pmpkg_t *p_i = vertex_i->data;
- /* TODO this should be somehow combined with _alpm_checkdeps */
+ /* TODO this should be somehow combined with alpm_checkdeps */
for(j = vertices; j; j = j->next) {
pmgraph_t *vertex_j = j->data;
pmpkg_t *p_j = vertex_j->data;
@@ -232,18 +232,13 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode)
/** Checks dependencies and returns missing ones in a list.
* Dependencies can include versions with depmod operators.
* @param db pointer to the local package database
- * @param op transaction type
- * @param packages an alpm_list_t* of packages to be checked
+ * @param reversedeps handles the backward dependencies
+ * @param remove an alpm_list_t* of packages to be removed
+ * @param upgrade an alpm_list_t* of packages to be upgraded (remove-then-upgrade)
* @return an alpm_list_t* of pmpkg_t* of missing_t pointers.
*/
-alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
- alpm_list_t *packages)
-{
- return(_alpm_checkdeps(db, op, packages));
-}
-
-alpm_list_t *_alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
- alpm_list_t *packages)
+alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps,
+ alpm_list_t *remove, alpm_list_t *upgrade)
{
alpm_list_t *i, *j, *k, *l;
int found = 0;
@@ -256,16 +251,68 @@ alpm_list_t *_alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
return(NULL);
}
- if(op == PM_TRANS_TYPE_UPGRADE) {
- /* PM_TRANS_TYPE_UPGRADE handles the backwards dependencies, ie,
- * the packages listed in the requiredby field.
- */
- for(i = packages; i; i = i->next) {
+ /* look for unsatisfied dependencies of the upgrade list */
+ for(i = upgrade; i; i = i->next) {
+ pmpkg_t *tp = i->data;
+ if(tp == NULL) {
+ _alpm_log(PM_LOG_DEBUG, "null package found in upgrade list\n");
+ continue;
+ }
+ _alpm_log(PM_LOG_DEBUG, "checkdeps: package %s-%s\n",
+ alpm_pkg_get_name(tp), alpm_pkg_get_version(tp));
+
+ for(j = alpm_pkg_get_depends(tp); j; j = j->next) {
+ /* split into name/version pairs */
+ pmdepend_t *depend = j->data;
+ found = 0;
+ /* 1. we check the upgrade list */
+ for(k = upgrade; k && !found; k = k->next) {
+ pmpkg_t *p = k->data;
+ found = p && alpm_depcmp(p, depend);
+ }
+ /* 2. we check database for untouched satisfying packages */
+ for(k = _alpm_db_get_pkgcache(db); k && !found; k = k->next) {
+ pmpkg_t *p = k->data;
+ found = p && alpm_depcmp(p, depend)
+ && !_alpm_pkg_find(alpm_pkg_get_name(p), upgrade)
+ && !_alpm_pkg_find(alpm_pkg_get_name(p), remove);
+ }
+ /* else if still not found... */
+ if(!found) {
+ char *missdepstring = alpm_dep_get_string(depend);
+ _alpm_log(PM_LOG_DEBUG, "missing dependency '%s' for package '%s'\n",
+ missdepstring, alpm_pkg_get_name(tp));
+ free(missdepstring);
+ miss = _alpm_depmiss_new(alpm_pkg_get_name(tp), depend->mod,
+ depend->name, depend->version);
+ if(!_alpm_depmiss_isin(miss, baddeps)) {
+ baddeps = alpm_list_add(baddeps, miss);
+ } else {
+ FREE(miss);
+ }
+ }
+ }
+ }
+
+ if(reversedeps) {
+ /* reversedeps handles the backwards dependencies, ie,
+ * the packages listed in the requiredby field. */
+
+ /* we check the upgrade list then the remove list in one loop */
+ int upgr = 1; /* we are in the upgrade list */
+ i = upgrade;
+ while(upgr || i) {
+ if(!i) { /*this is the end of the upgrade list, jump to the remove list*/
+ i = remove;
+ upgr = 0;
+ continue;
+ }
pmpkg_t *newpkg = i->data;
pmpkg_t *oldpkg;
alpm_list_t *requiredby;
if(newpkg == NULL) {
_alpm_log(PM_LOG_DEBUG, "null package found in package list\n");
+ i = i->next;
continue;
}
_alpm_log(PM_LOG_DEBUG, "checkdeps: package %s-%s\n",
@@ -273,7 +320,8 @@ alpm_list_t *_alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
if((oldpkg = _alpm_db_get_pkgfromcache(db, alpm_pkg_get_name(newpkg))) == NULL) {
_alpm_log(PM_LOG_DEBUG, "cannot find package installed '%s'\n",
- alpm_pkg_get_name(newpkg));
+ alpm_pkg_get_name(newpkg));
+ i = i->next;
continue;
}
@@ -282,8 +330,7 @@ alpm_list_t *_alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
pmpkg_t *p;
found = 0;
- if(_alpm_pkg_find(j->data, packages)) {
- /* this package also in the upgrade list, so don't worry about it */
+ if(_alpm_pkg_find(j->data, upgrade) || _alpm_pkg_find(j->data, remove)) {
continue;
}
if((p = _alpm_db_get_pkgfromcache(db, j->data)) == NULL) {
@@ -292,95 +339,60 @@ alpm_list_t *_alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
}
for(k = alpm_pkg_get_depends(p); k; k = k->next) {
- /* don't break any existing dependencies (possible provides) */
pmdepend_t *depend = k->data;
+ char *missdepstring = alpm_dep_get_string(depend);
- /* if oldpkg satisfied this dep, and newpkg doesn't */
- if(alpm_depcmp(oldpkg, depend) && !alpm_depcmp(newpkg, depend)) {
- /* we've found a dep that was removed... see if any other package
- * still contains/provides the dep */
- int satisfied = 0;
- for(l = packages; l; l = l->next) {
- pmpkg_t *pkg = l->data;
-
- if(alpm_depcmp(pkg, depend)) {
- _alpm_log(PM_LOG_DEBUG, "checkdeps: dependency '%s' has moved from '%s' to '%s'\n",
- depend->name,
- alpm_pkg_get_name(oldpkg), alpm_pkg_get_name(pkg));
- satisfied = 1;
- break;
- }
- }
-
- if(!satisfied) {
- /* worst case... check installed packages to see if anything else
- * satisfies this... */
- for(l = _alpm_db_get_pkgcache(db); l; l = l->next) {
- pmpkg_t *pkg = l->data;
-
- if(alpm_depcmp(pkg, depend) && !_alpm_pkg_find(alpm_pkg_get_name(pkg), packages)) {
- /* we ignore packages that will be updated because we know
- * that the updated ones don't satisfy depend */
- _alpm_log(PM_LOG_DEBUG, "checkdeps: dependency '%s' satisfied by installed package '%s'\n",
- depend->name, alpm_pkg_get_name(pkg));
- satisfied = 1;
- break;
- }
- }
+ if(!alpm_depcmp(oldpkg, depend)) {
+ continue;
+ }
+ /* OK, we don't want to break this depend */
+
+ /* 1. for efficiency we check newpkg first if we are in the upgrade list */
+ if(upgr && alpm_depcmp(newpkg, depend)) {
+ _alpm_log(PM_LOG_DEBUG, "checkdeps: dependency '%s' also satisfied by the upgraded version of '%s'\n",
+ missdepstring, alpm_pkg_get_name(newpkg));
+ free(missdepstring);
+ continue;
+ }
+ /* 2. we check the upgrade targets */
+ int satisfied = 0;
+ for(l = upgrade; l; l = l->next) {
+ pmpkg_t *pkg = l->data;
+ if(pkg && alpm_depcmp(pkg, depend)) {
+ _alpm_log(PM_LOG_DEBUG, "checkdeps: dependency '%s' satisfied by '%s' from the upgrade list\n",
+ missdepstring, alpm_pkg_get_name(pkg));
+ free(missdepstring);
+ satisfied = 1;
+ break;
}
-
- if(!satisfied) {
- _alpm_log(PM_LOG_DEBUG, "checkdeps: updated '%s' won't satisfy a dependency of '%s'\n",
- alpm_pkg_get_name(oldpkg), alpm_pkg_get_name(p));
- miss = _alpm_depmiss_new(p->name, depend->mod, depend->name, depend->version);
- if(!_alpm_depmiss_isin(miss, baddeps)) {
- baddeps = alpm_list_add(baddeps, miss);
- } else {
- FREE(miss);
- }
+ }
+ if(satisfied) {
+ continue;
+ }
+ /* 3. we check untouched installed packages to see if anything else
+ * satisfies this... */
+ for(l = _alpm_db_get_pkgcache(db); l; l = l->next) {
+ pmpkg_t *pkg = l->data;
+
+ if(pkg && alpm_depcmp(pkg, depend)
+ && !_alpm_pkg_find(alpm_pkg_get_name(pkg), upgrade)
+ && !_alpm_pkg_find(alpm_pkg_get_name(pkg), remove)) {
+ _alpm_log(PM_LOG_DEBUG, "checkdeps: dependency '%s' satisfied by installed package '%s'\n",
+ missdepstring, alpm_pkg_get_name(pkg));
+ free(missdepstring);
+ satisfied = 1;
+ break;
}
}
- }
- }
- FREELIST(requiredby);
- }
- }
- if(op == PM_TRANS_TYPE_ADD || op == PM_TRANS_TYPE_UPGRADE) {
- /* DEPENDENCIES -- look for unsatisfied dependencies */
- for(i = packages; i; i = i->next) {
- pmpkg_t *tp = i->data;
- if(tp == NULL) {
- _alpm_log(PM_LOG_DEBUG, "null package found in package list\n");
- continue;
- }
- _alpm_log(PM_LOG_DEBUG, "checkdeps: package %s-%s\n",
- alpm_pkg_get_name(tp), alpm_pkg_get_version(tp));
-
- for(j = alpm_pkg_get_depends(tp); j; j = j->next) {
- pmdepend_t *depend = j->data;
-
- found = 0;
- /* check other targets */
- for(k = packages; k && !found; k = k->next) {
- pmpkg_t *p = k->data;
- found = alpm_depcmp(p, depend);
- }
-
- /* check database for satisfying packages */
- /* we can ignore packages being updated, they were checked above */
- for(k = _alpm_db_get_pkgcache(db); k && !found; k = k->next) {
- pmpkg_t *p = k->data;
- found = alpm_depcmp(p, depend)
- && !_alpm_pkg_find(alpm_pkg_get_name(p), packages);
- }
+ if(satisfied) {
+ continue;
+ }
- /* else if still not found... */
- if(!found) {
- char *depstring = alpm_dep_get_string(depend);
- _alpm_log(PM_LOG_DEBUG, "missing dependency '%s' for package '%s'\n",
- depstring, alpm_pkg_get_name(tp));
- free(depstring);
- miss = _alpm_depmiss_new(alpm_pkg_get_name(tp), depend->mod,
+ /* The transaction would break this depend, record it */
+ _alpm_log(PM_LOG_DEBUG, "checkdeps: the transaction would break '%s' dependency of '%s'\n",
+ missdepstring, alpm_pkg_get_name(p));
+ free(missdepstring);
+ miss = _alpm_depmiss_new(p->name, depend->mod,
depend->name, depend->version);
if(!_alpm_depmiss_isin(miss, baddeps)) {
baddeps = alpm_list_add(baddeps, miss);
@@ -389,65 +401,8 @@ alpm_list_t *_alpm_checkdeps(pmdb_t *db, pmtranstype_t op,
}
}
}
- }
- } else if(op == PM_TRANS_TYPE_REMOVE) {
- /* check requiredby fields */
- for(i = packages; i; i = i->next) {
- pmpkg_t *rmpkg = alpm_list_getdata(i);
- alpm_list_t *requiredby;
-
- if(rmpkg == NULL) {
- _alpm_log(PM_LOG_DEBUG, "null package found in package list\n");
- continue;
- }
-
- requiredby = alpm_pkg_compute_requiredby(rmpkg);
- for(j = requiredby; j; j = j->next) {
- pmpkg_t *p;
- found = 0;
- if(_alpm_pkg_find(j->data, packages)) {
- /* package also in the remove list, so don't worry about it */
- continue;
- }
-
- if((p = _alpm_db_get_pkgfromcache(db, j->data)) == NULL) {
- /* hmmm... package isn't installed... */
- continue;
- }
- for(k = alpm_pkg_get_depends(p); k; k = k->next) {
- pmdepend_t *depend = k->data;
-
- /* if rmpkg satisfied this dep, try to find an other satisfier
- * (which won't be removed)*/
- if(alpm_depcmp(rmpkg, depend)) {
- int satisfied = 0;
- for(l = _alpm_db_get_pkgcache(db); l; l = l->next) {
- pmpkg_t *pkg = l->data;
- if(alpm_depcmp(pkg, depend) && !_alpm_pkg_find(alpm_pkg_get_name(pkg), packages)) {
- char *depstring = alpm_dep_get_string(depend);
- _alpm_log(PM_LOG_DEBUG, "checkdeps: dependency '%s' satisfied by installed package '%s'\n",
- depstring, alpm_pkg_get_name(pkg));
- free(depstring);
- satisfied = 1;
- break;
- }
- }
-
- if(!satisfied) {
- _alpm_log(PM_LOG_DEBUG, "checkdeps: found %s which requires %s\n",
- alpm_pkg_get_name(p), alpm_pkg_get_name(rmpkg));
- miss = _alpm_depmiss_new(alpm_pkg_get_name(p),
- depend->mod, depend->name, depend->version);
- if(!_alpm_depmiss_isin(miss, baddeps)) {
- baddeps = alpm_list_add(baddeps, miss);
- } else {
- FREE(miss);
- }
- }
- }
- }
- }
FREELIST(requiredby);
+ i = alpm_list_next(i);
}
}
@@ -642,10 +597,11 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit)
/* populates *list with packages that need to be installed to satisfy all
* dependencies (recursive) for syncpkg
*
+ * @param remove contains packages elected for removal
* make sure **list is already initialized
*/
int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,
- alpm_list_t **list, pmtrans_t *trans, alpm_list_t **data)
+ alpm_list_t **list, alpm_list_t *remove, pmtrans_t *trans, alpm_list_t **data)
{
alpm_list_t *i, *j, *k;
alpm_list_t *targ;
@@ -659,7 +615,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,
_alpm_log(PM_LOG_DEBUG, "started resolving dependencies\n");
targ = alpm_list_add(NULL, syncpkg);
- deps = _alpm_checkdeps(local, PM_TRANS_TYPE_ADD, targ);
+ deps = alpm_checkdeps(local, 0, remove, targ);
alpm_list_free(targ);
if(deps == NULL) {
@@ -694,7 +650,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,
if(!sync) {
continue;
}
- found = alpm_depcmp(sync, missdep);
+ found = alpm_depcmp(sync, missdep) && !_alpm_pkg_find(alpm_pkg_get_name(sync), remove);
if(!found) {
continue;
}
@@ -715,6 +671,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,
continue;
}
found = alpm_depcmp(sync, missdep);
+ found = alpm_depcmp(sync, missdep) && !_alpm_pkg_find(alpm_pkg_get_name(sync), remove);
if(!found) {
continue;
}
@@ -747,7 +704,7 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *syncpkg,
_alpm_log(PM_LOG_DEBUG, "pulling dependency %s (needed by %s)\n",
alpm_pkg_get_name(sync), alpm_pkg_get_name(syncpkg));
*list = alpm_list_add(*list, sync);
- if(_alpm_resolvedeps(local, dbs_sync, sync, list, trans, data)) {
+ if(_alpm_resolvedeps(local, dbs_sync, sync, list, remove, trans, data)) {
goto error;
}
}