applied first try at sync conflict handling (VMiklos) plus a couple changes
This commit is contained in:
parent
a074ddb85b
commit
58c9d5d663
4 changed files with 139 additions and 12 deletions
|
@ -235,6 +235,7 @@ enum {
|
|||
enum {
|
||||
PM_TRANS_CONV_INSTALL_IGNOREPKG,
|
||||
PM_TRANS_CONV_REPLACE_PKG,
|
||||
PM_TRANS_CONV_CONFLICT_PKG,
|
||||
PM_TRANS_CONV_LOCAL_NEWER,
|
||||
PM_TRANS_CONV_LOCAL_UPTODATE
|
||||
};
|
||||
|
|
|
@ -348,6 +348,20 @@ int db_read(pmdb_t *db, char *name, unsigned int inforeq, pmpkg_t *info)
|
|||
if(fgets(info->md5sum, sizeof(info->md5sum), fp) == NULL) {
|
||||
return(-1);
|
||||
}
|
||||
/* XXX: these are only here as backwards-compatibility for pacman 2.x
|
||||
* sync repos.... in pacman3, they have been moved to DEPENDS.
|
||||
* Remove this when we move to pacman3 repos.
|
||||
*/
|
||||
} else if(!strcmp(line, "%REPLACES%")) {
|
||||
/* the REPLACES tag is special -- it only appears in sync repositories,
|
||||
* not the local one. */
|
||||
while(fgets(line, 512, fp) && strlen(_alpm_strtrim(line))) {
|
||||
info->replaces = pm_list_add(info->replaces, strdup(line));
|
||||
}
|
||||
} else if(!strcmp(line, "%FORCE%")) {
|
||||
/* FORCE tag only appears in sync repositories,
|
||||
* not the local one. */
|
||||
info->force = 1;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "sync.h"
|
||||
#include "rpmvercmp.h"
|
||||
#include "handle.h"
|
||||
#include "alpm.h"
|
||||
|
||||
extern pmhandle_t *handle;
|
||||
|
||||
|
@ -225,9 +226,7 @@ int sync_sysupgrade(pmtrans_t *trans, pmdb_t *db_local, PMList *dbs_sync)
|
|||
_alpm_log(PM_LOG_FLOW1, "%s-%s: ignoring package upgrade (%s)",
|
||||
local->name, local->version, spkg->version);
|
||||
} else {
|
||||
pmpkg_t *dummy = pkg_new();
|
||||
STRNCPY(dummy->name, local->name, PKG_NAME_LEN);
|
||||
STRNCPY(dummy->version, local->version, PKG_VERSION_LEN);
|
||||
pmpkg_t *dummy = pkg_dummy(local->name, local->version);
|
||||
sync = sync_new(PM_SYNC_TYPE_UPGRADE, spkg, dummy);
|
||||
if(sync == NULL) {
|
||||
FREEPKG(dummy);
|
||||
|
@ -329,6 +328,13 @@ int sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, PMList *dbs_sync, char *n
|
|||
return(0);
|
||||
}
|
||||
|
||||
/* Helper function for _alpm_list_remove
|
||||
*/
|
||||
static int ptr_cmp(const void *s1, const void *s2)
|
||||
{
|
||||
return((s1 == s2));
|
||||
}
|
||||
|
||||
int sync_prepare(pmtrans_t *trans, pmdb_t *db_local, PMList *dbs_sync, PMList **data)
|
||||
{
|
||||
PMList *deps = NULL;
|
||||
|
@ -368,6 +374,7 @@ int sync_prepare(pmtrans_t *trans, pmdb_t *db_local, PMList *dbs_sync, PMList **
|
|||
trans->packages = pm_list_add(trans->packages, sync);
|
||||
}
|
||||
}
|
||||
|
||||
EVENT(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL);
|
||||
|
||||
/* check for inter-conflicts and whatnot */
|
||||
|
@ -375,7 +382,7 @@ int sync_prepare(pmtrans_t *trans, pmdb_t *db_local, PMList *dbs_sync, PMList **
|
|||
deps = checkdeps(db_local, PM_TRANS_TYPE_UPGRADE, list);
|
||||
if(deps) {
|
||||
int found;
|
||||
PMList *j, *k, *exfinal = NULL;
|
||||
PMList *j, *k, *asked = NULL;
|
||||
int errorout = 0;
|
||||
_alpm_log(PM_LOG_FLOW1, "looking for unresolvable dependencies");
|
||||
for(i = deps; i; i = i->next) {
|
||||
|
@ -406,10 +413,6 @@ int sync_prepare(pmtrans_t *trans, pmdb_t *db_local, PMList *dbs_sync, PMList **
|
|||
if(miss->type != PM_DEP_TYPE_CONFLICT) {
|
||||
continue;
|
||||
}
|
||||
/* make sure this package wasn't already removed from the final list */
|
||||
if(pm_list_is_in(miss->target, exfinal)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check if the conflicting package is one that's about to be removed/replaced.
|
||||
* if so, then just ignore it
|
||||
|
@ -428,8 +431,111 @@ int sync_prepare(pmtrans_t *trans, pmdb_t *db_local, PMList *dbs_sync, PMList **
|
|||
}
|
||||
}
|
||||
|
||||
/* ORE
|
||||
if we didn't find it in any sync->replaces lists, then it's a conflict */
|
||||
/* if we didn't find it in any sync->replaces lists, then it's a conflict */
|
||||
if(!found) {
|
||||
int solved = 0;
|
||||
pmsyncpkg_t *sync = find_pkginsync(miss->target, trans->packages);
|
||||
for(j = sync->pkg->provides; j && j->data && !solved; j = j->next) {
|
||||
if(!strcmp(j->data, miss->depend.name)) {
|
||||
/* this package also "provides" the package it's conflicting with,
|
||||
* so just treat it like a "replaces" item so the REQUIREDBY
|
||||
* fields are inherited properly.
|
||||
*/
|
||||
|
||||
/* we save the dependency info so we can move p's requiredby stuff
|
||||
* over to the replacing package
|
||||
*/
|
||||
pmpkg_t *q = db_scan(db_local, miss->depend.name, INFRQ_DESC | INFRQ_DEPENDS);
|
||||
if(q) {
|
||||
/* append to the replaces list */
|
||||
pmsyncpkg_t *spkg = sync_new(PM_SYNC_TYPE_REPLACE, q, NULL);
|
||||
trans->packages = pm_list_add(trans->packages, spkg);
|
||||
solved = 1;
|
||||
} else {
|
||||
char *rmpkg = NULL;
|
||||
/* hmmm, depend.name 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. */
|
||||
if(pm_list_is_in(miss->depend.name, trans->targets) && !pm_list_is_in(miss->target, trans->targets)) {
|
||||
/* remove miss->target */
|
||||
rmpkg = strdup(miss->target);
|
||||
} else if(pm_list_is_in(miss->target, trans->targets) && !pm_list_is_in(miss->depend.name, trans->targets)) {
|
||||
/* remove miss->depend.name */
|
||||
rmpkg = strdup(miss->depend.name);
|
||||
} else {
|
||||
/* something's not right, bail out with a conflict error */
|
||||
}
|
||||
if(rmpkg) {
|
||||
for(k = trans->packages; k; k = k->next) {
|
||||
pmsyncpkg_t *sync = k->data;
|
||||
if(!strcmp(sync->pkg->name, rmpkg))
|
||||
trans->packages = _alpm_list_remove(trans->packages, sync, ptr_cmp, (void **)&data);
|
||||
}
|
||||
solved = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!solved) {
|
||||
/* It's a conflict -- see if they want to remove it
|
||||
*/
|
||||
pmpkg_t *p,*q = NULL;
|
||||
int pkgfound = 0;
|
||||
for(k = db_get_pkgcache(db_local); k; k = k->next) {
|
||||
p = k->data;
|
||||
if(!strcmp(p->name, miss->depend.name)) {
|
||||
pkgfound = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(pkgfound) {
|
||||
int doremove = 0;
|
||||
if(!pm_list_is_strin(miss->depend.name, asked)) {
|
||||
QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, miss->target, miss->depend.name, NULL, &doremove);
|
||||
asked = pm_list_add(asked, strdup(miss->depend.name));
|
||||
if(doremove) {
|
||||
PMList *l;
|
||||
/* remove miss->depend.name */
|
||||
for(l = trans->packages; l; l = l->next) {
|
||||
pmsyncpkg_t *s = l->data;
|
||||
if(!strcmp(s->pkg->name, miss->target)) {
|
||||
q = pkg_new();
|
||||
strcpy(q->name, miss->depend.name);
|
||||
if(s->type == PM_SYNC_TYPE_REPLACE) {
|
||||
/* append to the replaces list */
|
||||
s->data = pm_list_add(s->data, q);
|
||||
} else {
|
||||
/* switch this sync type to REPLACE */
|
||||
s->type = PM_SYNC_TYPE_REPLACE;
|
||||
/* add miss->depend.name to the replaces list */
|
||||
k = pm_list_new();
|
||||
k = pm_list_add(k, q);
|
||||
s->data = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* abort */
|
||||
_alpm_log(PM_LOG_ERROR, "package conflicts detected");
|
||||
errorout = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_alpm_log(PM_LOG_ERROR, "%s conflicts with %s", miss->target, miss->depend.name);
|
||||
errorout = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(errorout) {
|
||||
|
@ -494,8 +600,7 @@ int sync_commit(pmtrans_t *trans, pmdb_t *db_local)
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* ORE
|
||||
trans_init(PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAGS_NODEPS); */
|
||||
trans_init(tr, PM_TRANS_TYPE_REMOVE, PM_TRANS_FLAG_NODEPS, trans->cb_event, trans->cb_conv);
|
||||
|
||||
for(i = trans->packages; i; i = i->next) {
|
||||
pmsyncpkg_t *sync = i->data;
|
||||
|
|
|
@ -112,6 +112,13 @@ void cb_trans_conv(unsigned char event, void *data1, void *data2, void *data3, i
|
|||
(char *)alpm_pkg_getinfo(data2, PM_PKG_NAME));
|
||||
*response = yesno(str);
|
||||
break;
|
||||
case PM_TRANS_CONV_CONFLICT_PKG:
|
||||
snprintf(str, LOG_STR_LEN, "\n:: %s conflicts with %s. Remove %s? [Y/n] ",
|
||||
(char *)data1,
|
||||
(char *)data2,
|
||||
(char *)data2);
|
||||
*response = yesno(str);
|
||||
break;
|
||||
case PM_TRANS_CONV_LOCAL_NEWER:
|
||||
snprintf(str, LOG_STR_LEN, ":: %s-%s: local version is newer. Upgrade anyway? [Y/n] ",
|
||||
(char *)alpm_pkg_getinfo(data1, PM_PKG_NAME),
|
||||
|
|
Loading…
Add table
Reference in a new issue