Rule *r;
if (m && !MAPTST(m, v - solv->updaterules))
continue;
- /* check if identical to feature rule, we don't like that */
+ /* check if identical to feature rule, we don't like that (except for orphans) */
r = solv->rules + solv->featurerules + (v - solv->updaterules);
if (!r->p)
{
/* update rule == feature rule */
if (v > lastfeature)
lastfeature = v;
+ /* prefer orphaned packages in dup mode */
+ if (solv->keep_orphans)
+ {
+ r = solv->rules + v;
+ if (!r->d && r->p == (solv->installed->start + (v - solv->updaterules)))
+ {
+ lastfeature = v;
+ lastupdate = 0;
+ break;
+ }
+ }
continue;
}
if (v > lastupdate)
if (!solv->decisioncnt_orphan)
solv->decisioncnt_orphan = solv->decisionq.count;
- if (solv->dupmap_all && solv->installed)
+ if (solv->installed && (solv->orphaned.count || solv->brokenorphanrules))
{
int installedone = 0;
Solvable *s;
Rule *r;
int now, solve_start;
- int hasdupjob = 0;
+ int needduprules = 0;
int hasbestinstalljob = 0;
solve_start = solv_timems(0);
MAPSET(&solv->droporphanedmap, p - installed->start);
}
break;
+ case SOLVER_ALLOWUNINSTALL:
+ if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
+ solv->allowuninstall_all = 1;
+ FOR_JOB_SELECT(p, pp, select, what)
+ {
+ s = pool->solvables + p;
+ if (s->repo != installed)
+ continue;
+ if (!solv->allowuninstallmap.size)
+ map_grow(&solv->allowuninstallmap, installed->end - installed->start);
+ MAPSET(&solv->allowuninstallmap, p - installed->start);
+ }
+ break;
default:
break;
}
if (how & SOLVER_FORCEBEST)
solv->bestupdatemap_all = 1;
}
- if (!solv->dupmap_all || solv->allowuninstall)
- hasdupjob = 1;
+ if ((how & SOLVER_TARGETED) != 0)
+ needduprules = 1;
+ if (!solv->dupmap_all || solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size || solv->keep_orphans)
+ needduprules = 1;
break;
default:
break;
/* create dup maps if needed. We need the maps early to create our
* update rules */
- if (hasdupjob)
+ if (needduprules)
solver_createdupmaps(solv);
/*
* check for and remove duplicate
*/
r = solv->rules + solv->nrules - 1; /* r: update rule */
- if (!r->p)
- continue;
sr = r - (installed->end - installed->start); /* sr: feature rule */
+ if (!r->p)
+ {
+ if (sr->p)
+ memset(sr, 0, sizeof(*sr)); /* no feature rules without update rules */
+ continue;
+ }
/* it's also orphaned if the feature rule consists just of the installed package */
if (!solv->dupmap_all && sr->p == i && !sr->d && !sr->w2)
queue_push(&solv->orphaned, i);
break;
case SOLVER_ALLOWUNINSTALL:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: allowuninstall %s\n", solver_select2str(pool, select, what));
- if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
- solv->allowuninstall_all = 1;
- FOR_JOB_SELECT(p, pp, select, what)
- {
- s = pool->solvables + p;
- if (s->repo != installed)
- continue;
- if (!solv->allowuninstallmap.size)
- map_grow(&solv->allowuninstallmap, installed->end - installed->start);
- MAPSET(&solv->allowuninstallmap, p - installed->start);
- }
break;
default:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
else
solv->infarchrules = solv->infarchrules_end = solv->nrules;
- if (hasdupjob)
+ if (needduprules)
solver_addduprules(solv, &addedmap);
else
solv->duprules = solv->duprules_end = solv->nrules;
else
solv->bestrules = solv->bestrules_end = solv->nrules;
- if (hasdupjob)
+ if (needduprules)
solver_freedupmaps(solv); /* no longer needed */
if (solv->do_yum_obsoletes)