diff options
| -rw-r--r-- | lib/libalpm/add.c | 3 | ||||
| -rw-r--r-- | lib/libalpm/deps.c | 96 | 
2 files changed, 53 insertions, 46 deletions
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c index 28e66354..a2d79eb4 100644 --- a/lib/libalpm/add.c +++ b/lib/libalpm/add.c @@ -441,6 +441,9 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)  			/* Add files in the NEW package's backup array to the noupgrade array  			 * so this removal operation doesn't kill them */ +			/* TODO if we add here, all backup=() entries for all targets, new and +			 * old, we cover all bases, including backup=() locations changing hands. +			 * But is this viable? */  			alpm_list_t *old_noupgrade = alpm_list_strdup(handle->noupgrade);  			for(b = newpkg->backup; b; b = b->next) {  				_alpm_log(PM_LOG_DEBUG, _("adding %s to the NoUpgrade array temporarilly"), (char *)b->data); diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index 7065efa7..99056071 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -138,9 +138,7 @@ alpm_list_t *_alpm_sortbydeps(alpm_list_t *targets, pmtranstype_t mode)  		for(i = newtargs; i; i = i->next) {  			pmpkg_t *p = (pmpkg_t*)i->data;  			_alpm_log(PM_LOG_DEBUG, "sorting %s", p->name); -			/* TODO this may not always work if p->data is a fd, not db */ -			_alpm_db_read(p->data, INFRQ_DEPENDS, p); -			for(j = p->depends; j; j = j->next) { +			for(j = alpm_pkg_get_depends(p); j; j = j->next) {  				pmdepend_t dep;  				pmpkg_t *q = NULL;  				if(_alpm_splitdep(j->data, &dep)) { @@ -438,6 +436,35 @@ int _alpm_splitdep(char *depstr, pmdepend_t *depend)  	return(0);  } +/* These parameters are messy.  We check if this package, given a list of + * targets (and a db), is safe to remove.  We do NOT remove it if it is in the + * target list */ +static int can_remove_package(pmdb_t *db, pmpkg_t *pkg, alpm_list_t *targets) +{ +	alpm_list_t *i; + +	if(_alpm_pkg_isin(pkg->name, targets)) { +		return(0); +	} + +	/* see if it was explicitly installed */ +	if(alpm_pkg_get_reason(pkg) == PM_PKG_REASON_EXPLICIT) { +		_alpm_log(PM_LOG_DEBUG, _("excluding %s -- explicitly installed"), pkg->name); +		return(0); +	} + +	/* see if other packages need it */ +	for(i = alpm_pkg_get_requiredby(pkg); i; i = i->next) { +		pmpkg_t *reqpkg = _alpm_db_get_pkgfromcache(db, i->data); +		if(reqpkg && !_alpm_pkg_isin(reqpkg->name, targets)) { +			return(0); +		} +	} + +	/* it's ok to remove */ +	return(1); +} +  /* return a new alpm_list_t target list containing all packages in the original   * target list, as well as all their un-needed dependencies.  By un-needed,   * I mean dependencies that are *only* required for packages in the target @@ -456,67 +483,44 @@ alpm_list_t *_alpm_removedeps(pmdb_t *db, alpm_list_t *targs)  	for(i = targs; i; i = i->next) {  		pmpkg_t *pkg = i->data; -		if(pkg) { -			_alpm_db_read(db, INFRQ_DEPENDS, pkg); -		} else { -			continue; -		} -		for(j = pkg->depends; j; j = j->next) { +		for(j = alpm_pkg_get_depends(pkg); j; j = j->next) {  			pmdepend_t depend;  			pmpkg_t *dep; -			int needed = 0; -  			if(_alpm_splitdep(j->data, &depend)) {  				continue;  			}  			dep = _alpm_db_get_pkgfromcache(db, depend.name);  			if(dep == NULL) { -				/* package not found... look for a provisio instead */ -				k = _alpm_db_whatprovides(db, depend.name); -				if(k == NULL) { +				/* package not found... look for a provision instead */ +				alpm_list_t *provides = _alpm_db_whatprovides(db, depend.name); +				if(!provides) {  					/* Not found, that's fine, carry on */  					_alpm_log(PM_LOG_DEBUG, _("cannot find package \"%s\" or anything that provides it!"), depend.name);  					continue;  				} -				dep = _alpm_db_get_pkgfromcache(db, ((pmpkg_t *)k->data)->name); -				if(dep == NULL) { -					_alpm_log(PM_LOG_ERROR, _("dep is NULL!")); -					/* wtf */ -					continue; -				} -				FREELISTPTR(k); -			} +				for(k = provides; k; k = k->next) { +					pmpkg_t *provpkg = k->data; +					if(can_remove_package(db, provpkg, newtargs)) { +						pmpkg_t *pkg = _alpm_pkg_new(provpkg->name, provpkg->version); +						_alpm_db_read(db, INFRQ_ALL, pkg); -			_alpm_db_read(db, INFRQ_DEPENDS, dep); +						_alpm_log(PM_LOG_DEBUG, _("adding '%s' to the targets"), pkg->name); -			if(_alpm_pkg_isin(dep->name, targs)) { -				continue; -			} - -			/* see if it was explicitly installed */ -			if(dep->reason == PM_PKG_REASON_EXPLICIT) { -				_alpm_log(PM_LOG_DEBUG, _("excluding %s -- explicitly installed"), dep->name); -				needed = 1; -			} - -			/* see if other packages need it */ -			for(k = dep->requiredby; k && !needed; k = k->next) { -				pmpkg_t *dummy = _alpm_db_get_pkgfromcache(db, k->data); -				if(!_alpm_pkg_isin(dummy->name, targs)) { -					needed = 1; +						/* add it to the target list */ +						newtargs = alpm_list_add(newtargs, pkg); +						newtargs = _alpm_removedeps(db, newtargs); +					}  				} -			} -			if(!needed) { +				FREELISTPTR(provides); +			} else if(can_remove_package(db, dep, newtargs)) {  				pmpkg_t *pkg = _alpm_pkg_new(dep->name, dep->version); -				if(pkg == NULL) { -					continue; -				} -				/* add it to the target list */ -				_alpm_log(PM_LOG_DEBUG, _("loading ALL info for '%s'"), pkg->name);  				_alpm_db_read(db, INFRQ_ALL, pkg); -				newtargs = alpm_list_add(newtargs, pkg); +  				_alpm_log(PM_LOG_DEBUG, _("adding '%s' to the targets"), pkg->name); + +				/* add it to the target list */ +				newtargs = alpm_list_add(newtargs, pkg);  				newtargs = _alpm_removedeps(db, newtargs);  			}  		}  | 
