Blame src/solver_util.c

Packit Service ff689b
/*
Packit Service ff689b
 * Copyright (c) 2017, SUSE Inc.
Packit Service ff689b
 *
Packit Service ff689b
 * This program is licensed under the BSD license, read LICENSE.BSD
Packit Service ff689b
 * for further information
Packit Service ff689b
 */
Packit Service ff689b
Packit Service ff689b
/*
Packit Service ff689b
 * solver_util.c
Packit Service ff689b
 *
Packit Service ff689b
 * Dependency solver helper functions
Packit Service ff689b
 */
Packit Service ff689b
Packit Service ff689b
#include <stdio.h>
Packit Service ff689b
#include <stdlib.h>
Packit Service ff689b
#include <unistd.h>
Packit Service ff689b
#include <string.h>
Packit Service ff689b
Packit Service ff689b
#include "solver.h"
Packit Service ff689b
#include "solver_private.h"
Packit Service ff689b
#include "bitmap.h"
Packit Service ff689b
#include "pool.h"
Packit Service ff689b
#include "poolarch.h"
Packit Service ff689b
#include "util.h"
Packit Service ff689b
Packit Service ff689b
Packit Service ff689b
/*-------------------------------------------------------------------
Packit Service ff689b
 * check if a installed package p is being updated
Packit Service ff689b
 */
Packit Service ff689b
static int
Packit Service ff689b
solver_is_updating(Solver *solv, Id p)
Packit Service ff689b
{
Packit Service ff689b
  /* check if the update rule is true */
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  Rule *r;
Packit Service ff689b
  Id l, pp;
Packit Service ff689b
  if (solv->decisionmap[p] >= 0)
Packit Service ff689b
    return 0;	/* old package stayed */
Packit Service ff689b
  r = solv->rules + solv->updaterules + (p - solv->installed->start);
Packit Service ff689b
  FOR_RULELITERALS(l, pp, r)
Packit Service ff689b
    if (l > 0 && l != p && solv->decisionmap[l] > 0)
Packit Service ff689b
      return 1;
Packit Service ff689b
  return 0;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
/*-------------------------------------------------------------------
Packit Service ff689b
 * handle split provides
Packit Service ff689b
 *
Packit Service ff689b
 * a splitprovides dep looks like
Packit Service ff689b
 *     namespace:splitprovides(pkg REL_WITH path)
Packit Service ff689b
 * and is only true if pkg is installed and contains the specified path.
Packit Service ff689b
 * we also make sure that pkg is selected for an update, otherwise the
Packit Service ff689b
 * update would always be forced onto the user.
Packit Service ff689b
 * Map m is the map used when called from dep_possible.
Packit Service ff689b
 */
Packit Service ff689b
int
Packit Service ff689b
solver_splitprovides(Solver *solv, Id dep, Map *m)
Packit Service ff689b
{
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  Id p, pp;
Packit Service ff689b
  Reldep *rd;
Packit Service ff689b
  Solvable *s;
Packit Service ff689b
Packit Service ff689b
  if (!solv->dosplitprovides || !solv->installed)
Packit Service ff689b
    return 0;
Packit Service ff689b
  if (!ISRELDEP(dep))
Packit Service ff689b
    return 0;
Packit Service ff689b
  rd = GETRELDEP(pool, dep);
Packit Service ff689b
  if (rd->flags != REL_WITH)
Packit Service ff689b
    return 0;
Packit Service ff689b
  /*
Packit Service ff689b
   * things are a bit tricky here if pool->addedprovides == 1, because most split-provides are in
Packit Service ff689b
   * a non-standard location. If we simply call pool_whatprovides, we'll drag in the complete
Packit Service ff689b
   * file list. Instead we rely on pool_addfileprovides ignoring the addfileprovidesfiltered flag
Packit Service ff689b
   * for installed packages and check the lazywhatprovidesq (ignoring the REL_WITH part, but
Packit Service ff689b
   * we filter the package name further down anyway).
Packit Service ff689b
   */
Packit Service ff689b
  if (pool->addedfileprovides == 1 && !ISRELDEP(rd->evr) && !pool->whatprovides[rd->evr])
Packit Service ff689b
    pp = pool_searchlazywhatprovidesq(pool, rd->evr);
Packit Service ff689b
  else
Packit Service ff689b
    pp = pool_whatprovides(pool, dep);
Packit Service ff689b
  while ((p = pool->whatprovidesdata[pp++]) != 0)
Packit Service ff689b
    {
Packit Service ff689b
      /* here we have packages that provide the correct name and contain the path,
Packit Service ff689b
       * now do extra filtering */
Packit Service ff689b
      s = pool->solvables + p;
Packit Service ff689b
      if (s->repo != solv->installed || s->name != rd->name)
Packit Service ff689b
	continue;
Packit Service ff689b
      /* check if the package is updated. if m is set, we're called from dep_possible */
Packit Service ff689b
      if (m || solver_is_updating(solv, p))
Packit Service ff689b
	return 1;
Packit Service ff689b
    }
Packit Service ff689b
  return 0;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
int
Packit Service ff689b
solver_dep_possible_slow(Solver *solv, Id dep, Map *m)
Packit Service ff689b
{
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  Id p, pp;
Packit Service ff689b
Packit Service ff689b
  if (ISRELDEP(dep))
Packit Service ff689b
    {
Packit Service ff689b
      Reldep *rd = GETRELDEP(pool, dep);
Packit Service ff689b
      if (rd->flags >= 8)
Packit Service ff689b
         {
Packit Service ff689b
          if (rd->flags == REL_COND || rd->flags == REL_UNLESS)
Packit Service ff689b
            return 1;
Packit Service ff689b
          if (rd->flags == REL_AND)
Packit Service ff689b
            {
Packit Service ff689b
              if (!solver_dep_possible_slow(solv, rd->name, m))
Packit Service ff689b
                return 0;
Packit Service ff689b
              return solver_dep_possible_slow(solv, rd->evr, m);
Packit Service ff689b
            }
Packit Service ff689b
          if (rd->flags == REL_OR)
Packit Service ff689b
            {
Packit Service ff689b
              if (solver_dep_possible_slow(solv, rd->name, m))
Packit Service ff689b
                return 1;
Packit Service ff689b
              return solver_dep_possible_slow(solv, rd->evr, m);
Packit Service ff689b
            }
Packit Service ff689b
          if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
Packit Service ff689b
            return solver_splitprovides(solv, rd->evr, m);
Packit Service ff689b
        }
Packit Service ff689b
    }
Packit Service ff689b
  FOR_PROVIDES(p, pp, dep)
Packit Service ff689b
    {
Packit Service ff689b
      if (MAPTST(m, p))
Packit Service ff689b
        return 1;
Packit Service ff689b
    }
Packit Service ff689b
  return 0;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
int
Packit Service ff689b
solver_dep_fulfilled_cplx(Solver *solv, Reldep *rd)
Packit Service ff689b
{
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  if (rd->flags == REL_COND)
Packit Service ff689b
    {
Packit Service ff689b
      if (ISRELDEP(rd->evr))
Packit Service ff689b
	{
Packit Service ff689b
	  Reldep *rd2 = GETRELDEP(pool, rd->evr);
Packit Service ff689b
	  if (rd2->flags == REL_ELSE)
Packit Service ff689b
	    {
Packit Service ff689b
	      if (solver_dep_fulfilled(solv, rd2->name))
Packit Service ff689b
		return solver_dep_fulfilled(solv, rd->name);
Packit Service ff689b
	      return solver_dep_fulfilled(solv, rd2->evr);
Packit Service ff689b
	    }
Packit Service ff689b
	}
Packit Service ff689b
      if (solver_dep_fulfilled(solv, rd->name))
Packit Service ff689b
	return 1;
Packit Service ff689b
      return !solver_dep_fulfilled(solv, rd->evr);
Packit Service ff689b
    }
Packit Service ff689b
  if (rd->flags == REL_UNLESS)
Packit Service ff689b
    {
Packit Service ff689b
      if (ISRELDEP(rd->evr))
Packit Service ff689b
	{
Packit Service ff689b
	  Reldep *rd2 = GETRELDEP(pool, rd->evr);
Packit Service ff689b
	  if (rd2->flags == REL_ELSE)
Packit Service ff689b
	    {
Packit Service ff689b
	      if (!solver_dep_fulfilled(solv, rd2->name))
Packit Service ff689b
		return solver_dep_fulfilled(solv, rd->name);
Packit Service ff689b
	      return solver_dep_fulfilled(solv, rd2->evr);
Packit Service ff689b
	    }
Packit Service ff689b
	}
Packit Service ff689b
      if (!solver_dep_fulfilled(solv, rd->name))
Packit Service ff689b
	return 0;
Packit Service ff689b
      return !solver_dep_fulfilled(solv, rd->evr);
Packit Service ff689b
    }
Packit Service ff689b
  if (rd->flags == REL_AND)
Packit Service ff689b
    {
Packit Service ff689b
      if (!solver_dep_fulfilled(solv, rd->name))
Packit Service ff689b
	return 0;
Packit Service ff689b
      return solver_dep_fulfilled(solv, rd->evr);
Packit Service ff689b
    }
Packit Service ff689b
  if (rd->flags == REL_OR)
Packit Service ff689b
    {
Packit Service ff689b
      if (solver_dep_fulfilled(solv, rd->name))
Packit Service ff689b
	return 1;
Packit Service ff689b
      return solver_dep_fulfilled(solv, rd->evr);
Packit Service ff689b
    }
Packit Service ff689b
  return 0;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
static int
Packit Service ff689b
solver_dep_fulfilled_complex_func(Solver *solv, Reldep *rd, int (*dep_fullfilled)(Solver *, Id))
Packit Service ff689b
{
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  int r1, r2;
Packit Service ff689b
  if (rd->flags == REL_COND)
Packit Service ff689b
    {
Packit Service ff689b
      if (ISRELDEP(rd->evr))
Packit Service ff689b
	{
Packit Service ff689b
	  Reldep *rd2 = GETRELDEP(pool, rd->evr);
Packit Service ff689b
	  if (rd2->flags == REL_ELSE)
Packit Service ff689b
	    {
Packit Service ff689b
	      r1 = dep_fullfilled(solv, rd2->name);
Packit Service ff689b
	      if (r1)
Packit Service ff689b
		{
Packit Service ff689b
		  r2 = dep_fullfilled(solv, rd->name);
Packit Service ff689b
		  return r2 && r1 == 2 ? 2 : r2;
Packit Service ff689b
		}
Packit Service ff689b
	      return dep_fullfilled(solv, rd2->evr);
Packit Service ff689b
	    }
Packit Service ff689b
	}
Packit Service ff689b
      r1 = dep_fullfilled(solv, rd->name);
Packit Service ff689b
      r2 = !dep_fullfilled(solv, rd->evr);
Packit Service ff689b
      if (!r1 && !r2)
Packit Service ff689b
	return 0;
Packit Service ff689b
      return r1 == 2 ? 2 : 1;
Packit Service ff689b
    }
Packit Service ff689b
  if (rd->flags == REL_UNLESS)
Packit Service ff689b
    {
Packit Service ff689b
      if (ISRELDEP(rd->evr))
Packit Service ff689b
	{
Packit Service ff689b
	  Reldep *rd2 = GETRELDEP(pool, rd->evr);
Packit Service ff689b
	  if (rd2->flags == REL_ELSE)
Packit Service ff689b
	    {
Packit Service ff689b
	      r1 = dep_fullfilled(solv, rd2->name);
Packit Service ff689b
	      if (r1)
Packit Service ff689b
		{
Packit Service ff689b
		  r2 = dep_fullfilled(solv, rd2->evr);
Packit Service ff689b
		  return r2 && r1 == 2 ? 2 : r2;
Packit Service ff689b
		}
Packit Service ff689b
	      return dep_fullfilled(solv, rd->name);
Packit Service ff689b
	    }
Packit Service ff689b
	}
Packit Service ff689b
      /* A AND NOT(B) */
Packit Service ff689b
      r1 = dep_fullfilled(solv, rd->name);
Packit Service ff689b
      r2 = !dep_fullfilled(solv, rd->evr);
Packit Service ff689b
      if (!r1 || !r2)
Packit Service ff689b
	return 0;
Packit Service ff689b
      return r1 == 2 ? 2 : 1;
Packit Service ff689b
    }
Packit Service ff689b
  if (rd->flags == REL_AND)
Packit Service ff689b
    {
Packit Service ff689b
      r1 = dep_fullfilled(solv, rd->name);
Packit Service ff689b
      if (!r1)
Packit Service ff689b
	return 0;
Packit Service ff689b
      r2 = dep_fullfilled(solv, rd->evr);
Packit Service ff689b
      if (!r2)
Packit Service ff689b
	return 0;
Packit Service ff689b
      return r1 == 2 || r2 == 2 ? 2 : 1;
Packit Service ff689b
    }
Packit Service ff689b
  if (rd->flags == REL_OR)
Packit Service ff689b
    {
Packit Service ff689b
      r1 = dep_fullfilled(solv, rd->name);
Packit Service ff689b
      r2 = dep_fullfilled(solv, rd->evr);
Packit Service ff689b
      if (!r1 && !r2)
Packit Service ff689b
	return 0;
Packit Service ff689b
      return r1 == 2 || r2 == 2 ? 2 : 1;
Packit Service ff689b
    }
Packit Service ff689b
  return 0;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
/* mirrors solver_dep_fulfilled, but returns 2 if a new package
Packit Service ff689b
 * was involved */
Packit Service ff689b
static int
Packit Service ff689b
solver_dep_fulfilled_alreadyinstalled(Solver *solv, Id dep)
Packit Service ff689b
{
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  Id p, pp;
Packit Service ff689b
  int r;
Packit Service ff689b
Packit Service ff689b
  if (ISRELDEP(dep))
Packit Service ff689b
    {
Packit Service ff689b
      Reldep *rd = GETRELDEP(pool, dep);
Packit Service ff689b
      if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR)
Packit Service ff689b
	return solver_dep_fulfilled_complex_func(solv, rd, solver_dep_fulfilled_alreadyinstalled);
Packit Service ff689b
      if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
Packit Service ff689b
        return solver_splitprovides(solv, rd->evr, 0) ? 2 : 0;
Packit Service ff689b
      if (rd->flags == REL_NAMESPACE && solv->installsuppdepq)
Packit Service ff689b
	{
Packit Service ff689b
	  Queue *q = solv->installsuppdepq;
Packit Service ff689b
	  int i;
Packit Service ff689b
	  for (i = 0; i < q->count; i++)
Packit Service ff689b
	    if (q->elements[i] == dep || q->elements[i] == rd->name)
Packit Service ff689b
	      return 2;
Packit Service ff689b
	}
Packit Service ff689b
    }
Packit Service ff689b
  r = 0;
Packit Service ff689b
  FOR_PROVIDES(p, pp, dep)
Packit Service ff689b
    if (solv->decisionmap[p] > 0)
Packit Service ff689b
      {
Packit Service ff689b
	Solvable *s = pool->solvables + p;
Packit Service ff689b
	if (s->repo && s->repo != solv->installed)
Packit Service ff689b
	  return 2;
Packit Service ff689b
        r = 1;
Packit Service ff689b
      }
Packit Service ff689b
  return r;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
static int
Packit Service ff689b
solver_dep_fulfilled_namespace(Solver *solv, Id dep)
Packit Service ff689b
{
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  Id p, pp;
Packit Service ff689b
  int r = 1;
Packit Service ff689b
Packit Service ff689b
  if (ISRELDEP(dep))
Packit Service ff689b
    {
Packit Service ff689b
      Reldep *rd = GETRELDEP(pool, dep);
Packit Service ff689b
      if (rd->flags == REL_COND || rd->flags == REL_UNLESS || rd->flags == REL_AND || rd->flags == REL_OR)
Packit Service ff689b
	return solver_dep_fulfilled_complex_func(solv, rd, solver_dep_fulfilled_namespace);
Packit Service ff689b
      if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
Packit Service ff689b
        return solver_splitprovides(solv, rd->evr, 0) ? 2 : 0;
Packit Service ff689b
      if (rd->flags == REL_NAMESPACE)
Packit Service ff689b
	r = 2;
Packit Service ff689b
    }
Packit Service ff689b
  FOR_PROVIDES(p, pp, dep)
Packit Service ff689b
    if (solv->decisionmap[p] > 0)
Packit Service ff689b
      return r;
Packit Service ff689b
  return 0;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
int
Packit Service ff689b
solver_is_supplementing_alreadyinstalled(Solver *solv, Solvable *s)
Packit Service ff689b
{
Packit Service ff689b
  Id sup, *supp;
Packit Service ff689b
  supp = s->repo->idarraydata + s->supplements;
Packit Service ff689b
  while ((sup = *supp++) != 0)
Packit Service ff689b
    {
Packit Service ff689b
      if (!solv->addalreadyrecommended && solver_dep_fulfilled_alreadyinstalled(solv, sup) != 2)
Packit Service ff689b
	continue;
Packit Service ff689b
      if (solv->only_namespace_recommended && solver_dep_fulfilled_namespace(solv, sup) != 2)
Packit Service ff689b
	continue;
Packit Service ff689b
      return 1;
Packit Service ff689b
    }
Packit Service ff689b
  return 0;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
int
Packit Service ff689b
solver_is_namespace_dep_slow(Solver *solv, Reldep *rd)
Packit Service ff689b
{
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  for (;;)
Packit Service ff689b
    {
Packit Service ff689b
      if (rd->flags == REL_NAMESPACE)
Packit Service ff689b
	return 1;
Packit Service ff689b
      if (ISRELDEP(rd->name) && solver_is_namespace_dep_slow(solv, GETRELDEP(pool, rd->name)))
Packit Service ff689b
	return 1;
Packit Service ff689b
      if (!ISRELDEP(rd->evr))
Packit Service ff689b
	return 0;
Packit Service ff689b
      rd = GETRELDEP(pool, rd->evr);
Packit Service ff689b
    }
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
/*
Packit Service ff689b
 * add all installed packages that package p obsoletes to Queue q.
Packit Service ff689b
 * Package p is not installed. Also, we know that if
Packit Service ff689b
 * solv->keepexplicitobsoletes is not set, p is not in the multiversion map.
Packit Service ff689b
 * Entries may get added multiple times.
Packit Service ff689b
 */
Packit Service ff689b
static void
Packit Service ff689b
solver_add_obsoleted(Solver *solv, Id p, Queue *q)
Packit Service ff689b
{
Packit Service ff689b
  Pool *pool = solv->pool;
Packit Service ff689b
  Repo *installed = solv->installed;
Packit Service ff689b
  Id p2, pp2;
Packit Service ff689b
  Solvable *s = pool->solvables + p;
Packit Service ff689b
  Id obs, *obsp;
Packit Service ff689b
  Id lastp2 = 0;
Packit Service ff689b
Packit Service ff689b
  if (!solv->keepexplicitobsoletes || !(solv->multiversion.size && MAPTST(&solv->multiversion, p)))
Packit Service ff689b
    {
Packit Service ff689b
      FOR_PROVIDES(p2, pp2, s->name)
Packit Service ff689b
        {
Packit Service ff689b
          Solvable *ps = pool->solvables + p2;
Packit Service ff689b
          if (ps->repo != installed)
Packit Service ff689b
            continue;
Packit Service ff689b
          if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
Packit Service ff689b
            continue;
Packit Service ff689b
          if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps))
Packit Service ff689b
            continue;
Packit Service ff689b
          queue_push(q, p2);
Packit Service ff689b
          lastp2 = p2;
Packit Service ff689b
        }
Packit Service ff689b
    }
Packit Service ff689b
  if (!s->obsoletes)
Packit Service ff689b
    return;
Packit Service ff689b
  obsp = s->repo->idarraydata + s->obsoletes;
Packit Service ff689b
  while ((obs = *obsp++) != 0)
Packit Service ff689b
    FOR_PROVIDES(p2, pp2, obs)
Packit Service ff689b
      {
Packit Service ff689b
        Solvable *ps = pool->solvables + p2;
Packit Service ff689b
        if (ps->repo != installed)
Packit Service ff689b
          continue;
Packit Service ff689b
        if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
Packit Service ff689b
          continue;
Packit Service ff689b
        if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
Packit Service ff689b
          continue;
Packit Service ff689b
        if (p2 == lastp2)
Packit Service ff689b
          continue;
Packit Service ff689b
        queue_push(q, p2);
Packit Service ff689b
        lastp2 = p2;
Packit Service ff689b
      }
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
/*
Packit Service ff689b
 * Call solver_add_obsoleted and intersect the result with the
Packit Service ff689b
 * elements in Queue q starting at qstart.
Packit Service ff689b
 * Assumes that it's the first call if qstart == q->count.
Packit Service ff689b
 * May use auxillary map m for the intersection process, all
Packit Service ff689b
 * elements of q starting at qstart must have their bit cleared.
Packit Service ff689b
 * (This is also true after the function returns.)
Packit Service ff689b
 * (See solver_add_obsoleted for limitations of the package p)
Packit Service ff689b
 */
Packit Service ff689b
void
Packit Service ff689b
solver_intersect_obsoleted(Solver *solv, Id p, Queue *q, int qstart, Map *m)
Packit Service ff689b
{
Packit Service ff689b
  int i, j;
Packit Service ff689b
  int qcount = q->count;
Packit Service ff689b
Packit Service ff689b
  solver_add_obsoleted(solv, p, q);
Packit Service ff689b
  if (qcount == qstart)
Packit Service ff689b
    return;     /* first call */
Packit Service ff689b
  if (qcount == q->count)
Packit Service ff689b
    j = qstart;
Packit Service ff689b
  else if (qcount == qstart + 1)
Packit Service ff689b
    {
Packit Service ff689b
      /* easy if there's just one element */
Packit Service ff689b
      j = qstart;
Packit Service ff689b
      for (i = qcount; i < q->count; i++)
Packit Service ff689b
        if (q->elements[i] == q->elements[qstart])
Packit Service ff689b
          {
Packit Service ff689b
            j++;        /* keep the element */
Packit Service ff689b
            break;
Packit Service ff689b
          }
Packit Service ff689b
    }
Packit Service ff689b
  else if (!m || (!m->size && q->count - qstart <= 8))
Packit Service ff689b
    {
Packit Service ff689b
      /* faster than a map most of the time */
Packit Service ff689b
      int k;
Packit Service ff689b
      for (i = j = qstart; i < qcount; i++)
Packit Service ff689b
        {
Packit Service ff689b
          Id ip = q->elements[i];
Packit Service ff689b
          for (k = qcount; k < q->count; k++)
Packit Service ff689b
            if (q->elements[k] == ip)
Packit Service ff689b
              {
Packit Service ff689b
                q->elements[j++] = ip;
Packit Service ff689b
                break;
Packit Service ff689b
              }
Packit Service ff689b
        }
Packit Service ff689b
    }
Packit Service ff689b
  else
Packit Service ff689b
    {
Packit Service ff689b
      /* for the really pathologic cases we use the map */
Packit Service ff689b
      Repo *installed = solv->installed;
Packit Service ff689b
      if (!m->size)
Packit Service ff689b
        map_init(m, installed->end - installed->start);
Packit Service ff689b
      for (i = qcount; i < q->count; i++)
Packit Service ff689b
        MAPSET(m, q->elements[i] - installed->start);
Packit Service ff689b
      for (i = j = qstart; i < qcount; i++)
Packit Service ff689b
        if (MAPTST(m, q->elements[i] - installed->start))
Packit Service ff689b
          {
Packit Service ff689b
            MAPCLR(m, q->elements[i] - installed->start);
Packit Service ff689b
            q->elements[j++] = q->elements[i];
Packit Service ff689b
          }
Packit Service ff689b
    }
Packit Service ff689b
  queue_truncate(q, j);
Packit Service ff689b
}
Packit Service ff689b