summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rules.c47
-rw-r--r--src/solver.c61
-rw-r--r--src/solver.h8
3 files changed, 85 insertions, 31 deletions
diff --git a/src/rules.c b/src/rules.c
index d16c423..a6940df 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -1190,7 +1190,7 @@ solver_createdupmaps(Solver *solv)
Repo *installed = solv->installed;
Id select, how, what, p, pi, pp, pip, obs, *obsp;
Solvable *s, *ps;
- int i;
+ int i, targeted;
map_init(&solv->dupmap, pool->nsolvables);
map_init(&solv->dupinvolvedmap, pool->nsolvables);
@@ -1204,26 +1204,27 @@ solver_createdupmaps(Solver *solv)
case SOLVER_DISTUPGRADE:
if (select != SOLVER_SOLVABLE_REPO)
{
- int haveinstalled;
- p = 0;
- if (installed)
+ targeted = how & SOLVER_TARGETED ? 1 : 0;
+ if (installed && !targeted && !solv->noautotarget)
{
FOR_JOB_SELECT(p, pp, select, what)
if (pool->solvables[p].repo == installed)
break;
+ targeted = p == 0;
}
- haveinstalled = p != 0;
+ else if (!installed && !solv->noautotarget)
+ targeted = 1;
FOR_JOB_SELECT(p, pp, select, what)
{
Solvable *s = pool->solvables + p;
if (!s->repo)
continue;
- if (haveinstalled && s->repo != installed)
+ if (!targeted && s->repo != installed)
continue;
if (s->repo != installed && !pool_installable(pool, s))
continue;
MAPSET(&solv->dupinvolvedmap, p);
- if (!haveinstalled)
+ if (targeted)
MAPSET(&solv->dupmap, p);
FOR_PROVIDES(pi, pip, s->name)
{
@@ -1237,10 +1238,10 @@ solver_createdupmaps(Solver *solv)
map_grow(&solv->bestupdatemap, installed->end - installed->start);
MAPSET(&solv->bestupdatemap, pi - installed->start);
}
- if (haveinstalled && ps->repo != installed)
+ if (!targeted && ps->repo != installed)
MAPSET(&solv->dupmap, pi);
}
- if (haveinstalled)
+ if (!targeted)
{
if (solv->obsoletes && solv->obsoletes[p - installed->start])
{
@@ -1284,11 +1285,18 @@ solver_createdupmaps(Solver *solv)
if (what <= 0 || what > pool->nrepos)
break;
repo = pool_id2repo(pool, what);
+ if (!repo)
+ break;
+ if (repo != installed && !(how & SOLVER_TARGETED) && solv->noautotarget)
+ break;
+ targeted = repo != installed || (how & SOLVER_TARGETED) != 0;
FOR_REPO_SOLVABLES(repo, p, s)
{
if (repo != installed && !pool_installable(pool, s))
continue;
- MAPSET(&solv->dupmap, p);
+ MAPSET(&solv->dupinvolvedmap, p);
+ if (targeted)
+ MAPSET(&solv->dupmap, p);
FOR_PROVIDES(pi, pip, s->name)
{
ps = pool->solvables + pi;
@@ -1301,8 +1309,25 @@ solver_createdupmaps(Solver *solv)
map_grow(&solv->bestupdatemap, installed->end - installed->start);
MAPSET(&solv->bestupdatemap, pi - installed->start);
}
+ if (!targeted && ps->repo != installed)
+ MAPSET(&solv->dupmap, pi);
+ }
+ if (!targeted)
+ {
+ if (repo == installed && solv->obsoletes && solv->obsoletes[p - installed->start])
+ {
+ Id *opp;
+ for (opp = solv->obsoletes_data + solv->obsoletes[p - installed->start]; (pi = *opp++) != 0;)
+ {
+ ps = pool->solvables + pi;
+ if (ps->repo == installed)
+ continue;
+ MAPSET(&solv->dupinvolvedmap, pi);
+ MAPSET(&solv->dupmap, pi);
+ }
+ }
}
- if (s->obsoletes)
+ else if (s->obsoletes)
{
/* XXX: check obsoletes/provides combination */
obsp = s->repo->idarraydata + s->obsoletes;
diff --git a/src/solver.c b/src/solver.c
index ae0ddcf..bde00a3 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -1485,6 +1485,8 @@ solver_get_flag(Solver *solv, int flag)
return solv->keepexplicitobsoletes;
case SOLVER_FLAG_BEST_OBEY_POLICY:
return solv->bestobeypolicy;
+ case SOLVER_FLAG_NO_AUTOTARGET:
+ return solv->noautotarget;
default:
break;
}
@@ -1533,6 +1535,9 @@ solver_set_flag(Solver *solv, int flag, int value)
case SOLVER_FLAG_BEST_OBEY_POLICY:
solv->bestobeypolicy = value;
break;
+ case SOLVER_FLAG_NO_AUTOTARGET:
+ solv->noautotarget = value;
+ break;
default:
break;
}
@@ -2606,6 +2611,11 @@ add_update_target(Solver *solv, Id p, Id how)
solv->update_targets = solv_calloc(1, sizeof(Queue));
queue_init(solv->update_targets);
}
+ if (s->repo == installed)
+ {
+ queue_push2(solv->update_targets, p, p);
+ return;
+ }
FOR_PROVIDES(pi, pip, s->name)
{
Solvable *si = pool->solvables + pi;
@@ -2794,45 +2804,56 @@ solver_solve(Solver *solv, Queue *job)
}
break;
case SOLVER_UPDATE:
- if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid))
+ if (select == SOLVER_SOLVABLE_ALL)
{
solv->updatemap_all = 1;
if (how & SOLVER_FORCEBEST)
solv->bestupdatemap_all = 1;
}
- else if (select == SOLVER_SOLVABLE_REPO && what != installed->repoid)
+ else if (select == SOLVER_SOLVABLE_REPO)
{
Repo *repo = pool_id2repo(pool, what);
if (!repo)
break;
+ if (repo == installed && !(how & SOLVER_TARGETED))
+ {
+ solv->updatemap_all = 1;
+ if (how & SOLVER_FORCEBEST)
+ solv->bestupdatemap_all = 1;
+ break;
+ }
+ if (solv->noautotarget && !(how & SOLVER_TARGETED))
+ break;
/* targeted update */
FOR_REPO_SOLVABLES(repo, p, s)
add_update_target(solv, p, how);
}
else
{
- int targeted = 1;
- FOR_JOB_SELECT(p, pp, select, what)
+ if (!(how & SOLVER_TARGETED))
{
- s = pool->solvables + p;
- if (s->repo != installed)
- continue;
- if (!solv->updatemap.size)
- map_grow(&solv->updatemap, installed->end - installed->start);
- MAPSET(&solv->updatemap, p - installed->start);
- if (how & SOLVER_FORCEBEST)
+ int targeted = 1;
+ FOR_JOB_SELECT(p, pp, select, what)
{
- if (!solv->bestupdatemap.size)
- map_grow(&solv->bestupdatemap, installed->end - installed->start);
- MAPSET(&solv->bestupdatemap, p - installed->start);
+ s = pool->solvables + p;
+ if (s->repo != installed)
+ continue;
+ if (!solv->updatemap.size)
+ map_grow(&solv->updatemap, installed->end - installed->start);
+ MAPSET(&solv->updatemap, p - installed->start);
+ if (how & SOLVER_FORCEBEST)
+ {
+ if (!solv->bestupdatemap.size)
+ map_grow(&solv->bestupdatemap, installed->end - installed->start);
+ MAPSET(&solv->bestupdatemap, p - installed->start);
+ }
+ targeted = 0;
}
- targeted = 0;
- }
- if (targeted)
- {
- FOR_JOB_SELECT(p, pp, select, what)
- add_update_target(solv, p, how);
+ if (!targeted || solv->noautotarget)
+ break;
}
+ FOR_JOB_SELECT(p, pp, select, what)
+ add_update_target(solv, p, how);
}
break;
default:
diff --git a/src/solver.h b/src/solver.h
index 5e3a162..fac1a17 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -203,6 +203,7 @@ struct _Solver {
int noinfarchcheck; /* true: do not forbid inferior architectures */
int keepexplicitobsoletes; /* true: honor obsoletes during multiinstall */
int bestobeypolicy; /* true: stay in policy with the best rules */
+ int noautotarget; /* true: do not assume targeted for up/dup jobs that contain no installed solvable */
Map dupmap; /* dup these packages*/
@@ -267,6 +268,12 @@ typedef struct _Solver Solver;
* not installable. This can be used with INSTALL, UPDATE
* and DISTUPGRADE */
#define SOLVER_FORCEBEST 0x100000
+/* TARGETED is used in up/dup jobs to make the solver
+ * treat the specified selection as target packages.
+ * It is automatically assumed if the selection does not
+ * contain an "installed" package unless the
+ * NO_AUTOTARGET solver flag is set */
+#define SOLVER_TARGETED 0x200000
#define SOLVER_SETEV 0x01000000
#define SOLVER_SETEVR 0x02000000
@@ -304,6 +311,7 @@ typedef struct _Solver Solver;
#define SOLVER_FLAG_ALLOW_NAMECHANGE 10
#define SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES 11
#define SOLVER_FLAG_BEST_OBEY_POLICY 12
+#define SOLVER_FLAG_NO_AUTOTARGET 13
extern Solver *solver_create(Pool *pool);
extern void solver_free(Solver *solv);