summaryrefslogtreecommitdiff
path: root/lib/libalpm/remove.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/remove.c')
-rw-r--r--lib/libalpm/remove.c97
1 files changed, 72 insertions, 25 deletions
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index a0f9963a..625abe67 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -37,7 +37,6 @@
#include "alpm_list.h"
#include "trans.h"
#include "util.h"
-#include "error.h"
#include "log.h"
#include "backup.h"
#include "package.h"
@@ -57,7 +56,7 @@ int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
- if(_alpm_pkg_find(name, trans->packages)) {
+ if(_alpm_pkg_find(trans->packages, name)) {
RET_ERR(PM_ERR_TRANS_DUP_TARGET, -1);
}
@@ -82,6 +81,60 @@ int _alpm_remove_loadtarget(pmtrans_t *trans, pmdb_t *db, char *name)
return(0);
}
+static void remove_prepare_cascade(pmtrans_t *trans, pmdb_t *db,
+ alpm_list_t *lp)
+{
+ ALPM_LOG_FUNC;
+
+ while(lp) {
+ alpm_list_t *i;
+ for(i = lp; i; i = i->next) {
+ pmdepmissing_t *miss = (pmdepmissing_t *)i->data;
+ pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target);
+ if(info) {
+ if(!_alpm_pkg_find(trans->packages, alpm_pkg_get_name(info))) {
+ _alpm_log(PM_LOG_DEBUG, "pulling %s in the targets list\n",
+ alpm_pkg_get_name(info));
+ trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info));
+ }
+ } else {
+ _alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"),
+ miss->target);
+ }
+ }
+ alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(lp);
+ lp = alpm_checkdeps(db, 1, trans->packages, NULL);
+ }
+}
+
+static void remove_prepare_keep_needed(pmtrans_t *trans, pmdb_t *db,
+ alpm_list_t *lp)
+{
+ ALPM_LOG_FUNC;
+
+ /* Remove needed packages (which break dependencies) from the target list */
+ while(lp != NULL) {
+ alpm_list_t *i;
+ for(i = lp; i; i = i->next) {
+ pmdepmissing_t *miss = (pmdepmissing_t *)i->data;
+ void *vpkg;
+ pmpkg_t *pkg = _alpm_pkg_find(trans->packages, miss->causingpkg);
+ trans->packages = alpm_list_remove(trans->packages, pkg, _alpm_pkg_cmp,
+ &vpkg);
+ pkg = vpkg;
+ if(pkg) {
+ _alpm_log(PM_LOG_WARNING, "removing %s from the target-list\n",
+ alpm_pkg_get_name(pkg));
+ _alpm_pkg_free(pkg);
+ }
+ }
+ alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(lp);
+ lp = alpm_checkdeps(db, 1, trans->packages, NULL);
+ }
+}
+
int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
{
alpm_list_t *lp;
@@ -96,37 +149,30 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
return(0);
}
+ if((trans->flags & PM_TRANS_FLAG_RECURSE) && !(trans->flags & PM_TRANS_FLAG_CASCADE)) {
+ _alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n");
+ _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL);
+ }
+
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
EVENT(trans, PM_TRANS_EVT_CHECKDEPS_START, NULL, NULL);
_alpm_log(PM_LOG_DEBUG, "looking for unsatisfied dependencies\n");
lp = alpm_checkdeps(db, 1, trans->packages, NULL);
if(lp != NULL) {
+
if(trans->flags & PM_TRANS_FLAG_CASCADE) {
- while(lp) {
- alpm_list_t *i;
- for(i = lp; i; i = i->next) {
- pmdepmissing_t *miss = (pmdepmissing_t *)i->data;
- pmpkg_t *info = _alpm_db_get_pkgfromcache(db, miss->target);
- if(info) {
- if(!_alpm_pkg_find(alpm_pkg_get_name(info), trans->packages)) {
- _alpm_log(PM_LOG_DEBUG, "pulling %s in the targets list\n",
- alpm_pkg_get_name(info));
- trans->packages = alpm_list_add(trans->packages, _alpm_pkg_dup(info));
- }
- } else {
- _alpm_log(PM_LOG_ERROR, _("could not find %s in database -- skipping\n"),
- miss->target);
- }
- }
- FREELIST(lp);
- lp = alpm_checkdeps(db, 1, trans->packages, NULL);
- }
+ remove_prepare_cascade(trans, db, lp);
+ } else if (trans->flags & PM_TRANS_FLAG_UNNEEDED) {
+ /* Remove needed packages (which would break dependencies)
+ * from the target list */
+ remove_prepare_keep_needed(trans, db, lp);
} else {
if(data) {
*data = lp;
} else {
- FREELIST(lp);
+ alpm_list_free_inner(lp, (alpm_list_fn_free)_alpm_depmiss_free);
+ alpm_list_free(lp);
}
RET_ERR(PM_ERR_UNSATISFIED_DEPS, -1);
}
@@ -135,14 +181,15 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
/* re-order w.r.t. dependencies */
_alpm_log(PM_LOG_DEBUG, "sorting by dependencies\n");
- lp = _alpm_sortbydeps(trans->packages, PM_TRANS_TYPE_REMOVE);
+ lp = _alpm_sortbydeps(trans->packages, 1);
/* free the old alltargs */
alpm_list_free(trans->packages);
trans->packages = lp;
- if(trans->flags & PM_TRANS_FLAG_RECURSE) {
+ /* -Rcs == -Rc then -Rs */
+ if((trans->flags & PM_TRANS_FLAG_CASCADE) && (trans->flags & PM_TRANS_FLAG_RECURSE)) {
_alpm_log(PM_LOG_DEBUG, "finding removable dependencies\n");
- _alpm_recursedeps(db, trans->packages, 0);
+ _alpm_recursedeps(db, trans->packages, trans->flags & PM_TRANS_FLAG_RECURSEALL);
}
if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {