mirror of
https://github.com/moparisthebest/pacman
synced 2024-12-22 15:58:50 -05:00
* Switched some functions to alpm_pkg_get_* usage as I came across them
* Added some provision switching hackery. This could probably use some refactoring,.. it solves the following case: pkg1 and pkg2 provide 'foo' and are both installed pkg3 depends on 'foo' and so lists 'pkg1' in the REQUIREDBY db section pkg1 is upgraded and no longer provides 'foo' ** This code ensures that the REQUIREDBY of pkg3 is updated to require pkg2 now instead of pkg1
This commit is contained in:
parent
6075b677fc
commit
3ebd125e1a
@ -343,6 +343,7 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
|
||||
oldpkg = _alpm_pkg_new(local->name, local->version);
|
||||
if(oldpkg) {
|
||||
oldpkg->backup = alpm_list_strdup(alpm_pkg_get_backup(local));
|
||||
oldpkg->provides = alpm_list_strdup(alpm_pkg_get_provides(local));
|
||||
strncpy(oldpkg->name, local->name, PKG_NAME_LEN);
|
||||
strncpy(oldpkg->version, local->version, PKG_VERSION_LEN);
|
||||
} else {
|
||||
@ -749,6 +750,35 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
|
||||
* looking for packages depending on the package to add */
|
||||
_alpm_pkg_update_requiredby(newpkg);
|
||||
|
||||
/* special case: if our provides list has changed from oldpkg to newpkg AND
|
||||
* we get here, we need to make sure we find the actual provision that
|
||||
* still satisfies this case, and update its 'requiredby' field... ugh */
|
||||
alpm_list_t *provdiff, *prov;
|
||||
provdiff = alpm_list_diff(alpm_pkg_get_provides(oldpkg),
|
||||
alpm_pkg_get_provides(newpkg),
|
||||
_alpm_str_cmp);
|
||||
for(prov = provdiff; prov; prov = prov->next) {
|
||||
const char *provname = prov->data;
|
||||
_alpm_log(PM_LOG_DEBUG, _("provision '%s' has been removed from package %s (%s => %s)"),
|
||||
provname, oldpkg->name, oldpkg->version, newpkg->version);
|
||||
|
||||
alpm_list_t *p = _alpm_db_whatprovides(handle->db_local, provname);
|
||||
if(p) {
|
||||
/* we now have all the provisions in the local DB for this virtual
|
||||
* package... seeing as we can't really determine which is the 'correct'
|
||||
* provision, we'll use the FIRST for now.
|
||||
* TODO figure out a way to find a "correct" provision */
|
||||
pmpkg_t *provpkg = p->data;
|
||||
_alpm_log(PM_LOG_DEBUG, _("updating '%s' due to provision change (%s)"), provpkg->name, provname);
|
||||
_alpm_pkg_update_requiredby(provpkg);
|
||||
if(_alpm_db_write(db, provpkg, INFRQ_DEPENDS)) {
|
||||
_alpm_log(PM_LOG_ERROR, _("could not update provision '%s' from '%s'"), provname, provpkg->name);
|
||||
alpm_logaction(_("could not update provision '%s' from '%s'"), provname, provpkg->name);
|
||||
RET_ERR(PM_ERR_DB_WRITE, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* make an install date (in UTC) */
|
||||
time_t t = time(NULL);
|
||||
strncpy(newpkg->installdate, asctime(gmtime(&t)), PKG_DATE_LEN);
|
||||
|
@ -457,6 +457,33 @@ int alpm_list_find_str(alpm_list_t *haystack, const char *needle)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the items in list `lhs` that are not present in list `rhs`
|
||||
* @note Entries are not duplicated
|
||||
* @param lhs the first list
|
||||
* @param rhs the second list
|
||||
* @param fn the comparisson function
|
||||
* @return a list containing all items in lhs not present in rhs
|
||||
*/
|
||||
alpm_list_t *alpm_list_diff(alpm_list_t *lhs, alpm_list_t *rhs, alpm_list_fn_cmp fn)
|
||||
{
|
||||
alpm_list_t *i, *j, *ret = NULL;
|
||||
for(i = lhs; i; i = i->next) {
|
||||
int found = 0;
|
||||
for(j = rhs; j; j = j->next) {
|
||||
if(fn(i->data, j->data) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
ret = alpm_list_add(ret, i->data);
|
||||
}
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/* vim: set ts=2 sw=2 noet: */
|
||||
|
@ -65,6 +65,7 @@ void *alpm_list_getdata(const alpm_list_t *entry);
|
||||
int alpm_list_count(const alpm_list_t *list);
|
||||
int alpm_list_find(alpm_list_t *haystack, const void *needle);
|
||||
int alpm_list_find_str(alpm_list_t *haystack,const char *needle);
|
||||
alpm_list_t *alpm_list_diff(alpm_list_t *lhs, alpm_list_t *rhs, alpm_list_fn_cmp fn);
|
||||
|
||||
#endif /* _ALPM_LIST_H */
|
||||
|
||||
|
@ -198,7 +198,7 @@ alpm_list_t *_alpm_checkdeps(pmtrans_t *trans, pmdb_t *db, pmtranstype_t op,
|
||||
alpm_list_t *packages)
|
||||
{
|
||||
pmdepend_t depend;
|
||||
alpm_list_t *i, *j, *k;
|
||||
alpm_list_t *i, *j, *k, *l;
|
||||
int found = 0;
|
||||
alpm_list_t *baddeps = NULL;
|
||||
pmdepmissing_t *miss = NULL;
|
||||
@ -214,19 +214,18 @@ alpm_list_t *_alpm_checkdeps(pmtrans_t *trans, pmdb_t *db, pmtranstype_t op,
|
||||
* listed in the requiredby field.
|
||||
*/
|
||||
for(i = packages; i; i = i->next) {
|
||||
pmpkg_t *tp = i->data;
|
||||
pmpkg_t *newpkg = i->data;
|
||||
pmpkg_t *oldpkg;
|
||||
if(tp == NULL) {
|
||||
if(newpkg == NULL) {
|
||||
_alpm_log(PM_LOG_DEBUG, _("null package found in package list"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if((oldpkg = _alpm_db_get_pkgfromcache(db, tp->name)) == NULL) {
|
||||
_alpm_log(PM_LOG_DEBUG, _("cannot find package installed '%s'"), tp->name);
|
||||
if((oldpkg = _alpm_db_get_pkgfromcache(db, newpkg->name)) == NULL) {
|
||||
_alpm_log(PM_LOG_DEBUG, _("cannot find package installed '%s'"), newpkg->name);
|
||||
continue;
|
||||
}
|
||||
_alpm_db_read(db, oldpkg, INFRQ_DEPENDS);
|
||||
for(j = oldpkg->requiredby; j; j = j->next) {
|
||||
for(j = alpm_pkg_get_requiredby(oldpkg); j; j = j->next) {
|
||||
pmpkg_t *p;
|
||||
found = 0;
|
||||
if((p = _alpm_db_get_pkgfromcache(db, j->data)) == NULL) {
|
||||
@ -237,19 +236,55 @@ alpm_list_t *_alpm_checkdeps(pmtrans_t *trans, pmdb_t *db, pmtranstype_t op,
|
||||
/* this package also in the upgrade list, so don't worry about it */
|
||||
continue;
|
||||
}
|
||||
_alpm_db_read(db, p, INFRQ_DEPENDS);
|
||||
for(k = p->depends; k; k = k->next) {
|
||||
for(k = alpm_pkg_get_depends(p); k; k = k->next) {
|
||||
/* don't break any existing dependencies (possible provides) */
|
||||
_alpm_splitdep(k->data, &depend);
|
||||
if(_alpm_depcmp(oldpkg, &depend) && !_alpm_depcmp(tp, &depend)) {
|
||||
_alpm_log(PM_LOG_DEBUG, _("checkdeps: updated '%s' won't satisfy a dependency of '%s'"),
|
||||
oldpkg->name, p->name);
|
||||
miss = _alpm_depmiss_new(p->name, PM_DEP_TYPE_REQUIRED, depend.mod,
|
||||
depend.name, depend.version);
|
||||
if(!_alpm_depmiss_isin(miss, baddeps)) {
|
||||
baddeps = alpm_list_add(baddeps, miss);
|
||||
} else {
|
||||
FREE(miss);
|
||||
|
||||
/* 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'"),
|
||||
depend.name, oldpkg->name, pkg->name);
|
||||
satisfied = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!satisfied) {
|
||||
/* worst case... check installed packages to see if anything else
|
||||
* satisfies this... */
|
||||
for(l = _alpm_db_get_pkgcache(db, INFRQ_DEPENDS); l; l = l->next) {
|
||||
pmpkg_t *pkg = l->data;
|
||||
|
||||
if(strcmp(pkg->name, oldpkg->name) == 0) {
|
||||
/* well, we know this one fails... skip it */
|
||||
continue;
|
||||
}
|
||||
if(_alpm_depcmp(pkg, &depend)) {
|
||||
_alpm_log(PM_LOG_DEBUG, _("checkdeps: dependency '%s' satisfied by installed package '%s'"),
|
||||
depend.name, pkg->name);
|
||||
satisfied = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!satisfied) {
|
||||
_alpm_log(PM_LOG_DEBUG, _("checkdeps: updated '%s' won't satisfy a dependency of '%s'"),
|
||||
oldpkg->name, p->name);
|
||||
miss = _alpm_depmiss_new(p->name, PM_DEP_TYPE_REQUIRED, depend.mod,
|
||||
depend.name, depend.version);
|
||||
if(!_alpm_depmiss_isin(miss, baddeps)) {
|
||||
baddeps = alpm_list_add(baddeps, miss);
|
||||
} else {
|
||||
FREE(miss);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ alpm_list_t *_alpm_db_whatprovides(pmdb_t *db, const char *package)
|
||||
for(lp = _alpm_db_get_pkgcache(db, INFRQ_DEPENDS); lp; lp = lp->next) {
|
||||
pmpkg_t *info = lp->data;
|
||||
|
||||
if(alpm_list_find_str(info->provides, package)) {
|
||||
if(alpm_list_find_str(alpm_pkg_get_provides(info), package)) {
|
||||
pkgs = alpm_list_add(pkgs, info);
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ int _alpm_depcmp(pmpkg_t *pkg, pmdepend_t *dep)
|
||||
ALPM_LOG_FUNC;
|
||||
|
||||
if(strcmp(pkg->name, dep->name) == 0
|
||||
|| alpm_list_find_str(pkg->provides, dep->name)) {
|
||||
|| alpm_list_find_str(alpm_pkg_get_provides(pkg), dep->name)) {
|
||||
if(dep->mod == PM_DEP_MOD_ANY) {
|
||||
equal = 1;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user