312 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			312 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 6c9cef4ef810cd32ffeee20986a16e0871fc0bae Mon Sep 17 00:00:00 2001
 | |
| From: Michael Schroeder <mls@suse.de>
 | |
| Date: Mon, 7 Mar 2016 14:09:40 +0100
 | |
| Subject: [PATCH 9/9] Rework orphan handling in dup mode
 | |
| 
 | |
| The old code had problems when the updaters contained other
 | |
| installed packages.
 | |
| ---
 | |
|  src/rules.c  | 193 +++++++++++++++++++++++++++++++++++++++++++----------------
 | |
|  src/rules.h  |   3 +-
 | |
|  src/solver.c |   7 ++-
 | |
|  3 files changed, 149 insertions(+), 54 deletions(-)
 | |
| 
 | |
| diff --git a/src/rules.c b/src/rules.c
 | |
| index 4cd53d3..0e2c955 100644
 | |
| --- a/src/rules.c
 | |
| +++ b/src/rules.c
 | |
| @@ -1170,35 +1170,56 @@ solver_addpkgrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allow_all)
 | |
|   ***
 | |
|   ***/
 | |
|  
 | |
| +static int
 | |
| +dup_maykeepinstalled(Solver *solv, Solvable *s)
 | |
| +{
 | |
| +  Pool *pool = solv->pool;
 | |
| +  Id ip, pp;
 | |
| +
 | |
| +  if (solv->dupmap.size && MAPTST(&solv->dupmap,  s - pool->solvables))
 | |
| +    return 1;
 | |
| +  /* is installed identical to a good one? */
 | |
| +  FOR_PROVIDES(ip, pp, s->name)
 | |
| +    {
 | |
| +      Solvable *is = pool->solvables + ip;
 | |
| +      if (is->evr != s->evr)
 | |
| +	continue;
 | |
| +      if (solv->dupmap.size)
 | |
| +	{
 | |
| +	  if (!MAPTST(&solv->dupmap, ip))
 | |
| +	    continue;
 | |
| +	}
 | |
| +      else if (is->repo == pool->installed)
 | |
| +	continue;
 | |
| +      if (solvable_identical(s, is))
 | |
| +	return 1;
 | |
| +    }
 | |
| +  return 0;
 | |
| +}
 | |
| +
 | |
| +
 | |
|  static Id
 | |
| -finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all)
 | |
| +finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs)
 | |
|  {
 | |
|    Pool *pool = solv->pool;
 | |
| -  int i;
 | |
| +  int i, j;
 | |
|  
 | |
| -  policy_findupdatepackages(solv, s, qs, allow_all ? allow_all : 2);
 | |
| -  if (!qs->count)
 | |
| +  policy_findupdatepackages(solv, s, qs, 2);
 | |
| +  if (qs->count)
 | |
|      {
 | |
| -      if (allow_all)
 | |
| -        return 0;		/* orphaned, don't create feature rule */
 | |
| -      /* check if this is an orphaned package */
 | |
| -      policy_findupdatepackages(solv, s, qs, 1);
 | |
| -      if (!qs->count)
 | |
| -	return 0;		/* orphaned, don't create update rule */
 | |
| -      qs->count = 0;
 | |
| -      return -SYSTEMSOLVABLE;	/* supported but not installable */
 | |
| +      /* remove installed packages we can't keep */
 | |
| +      for (i = j = 0; i < qs->count; i++)
 | |
| +	{
 | |
| +	  Solvable *ns = pool->solvables + qs->elements[i];
 | |
| +	  if (ns->repo == pool->installed && !dup_maykeepinstalled(solv, ns))
 | |
| +	    continue;
 | |
| +	  qs->elements[j++] = qs->elements[i];
 | |
| +	}
 | |
| +      queue_truncate(qs, j);
 | |
|      }
 | |
| -  if (allow_all)
 | |
| -    return s - pool->solvables;
 | |
|    /* check if it is ok to keep the installed package */
 | |
| -  if (solv->dupmap.size && MAPTST(&solv->dupmap,  s - pool->solvables))
 | |
| +  if (dup_maykeepinstalled(solv, s))
 | |
|      return s - pool->solvables;
 | |
| -  for (i = 0; i < qs->count; i++)
 | |
| -    {
 | |
| -      Solvable *ns = pool->solvables + qs->elements[i];
 | |
| -      if (s->evr == ns->evr && solvable_identical(s, ns))
 | |
| -        return s - pool->solvables;
 | |
| -    }
 | |
|    /* nope, it must be some other package */
 | |
|    return -SYSTEMSOLVABLE;
 | |
|  }
 | |
| @@ -1240,6 +1261,73 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d)
 | |
|    solv->specialupdaters[s - solv->pool->solvables - installed->start] = d;
 | |
|  }
 | |
|  
 | |
| +#ifdef ENABLE_LINKED_PKGS
 | |
| +/* Check if this is a linked pseudo package. As it is linked, we do not need an update/feature rule */
 | |
| +static inline int
 | |
| +is_linked_pseudo_package(Solver *solv, Solvable *s)
 | |
| +{
 | |
| +  Pool *pool = solv->pool;
 | |
| +  if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start])
 | |
| +    {
 | |
| +      const char *name = pool_id2str(pool, s->name);
 | |
| +      if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0)
 | |
| +	return 1;
 | |
| +    }
 | |
| +  return 0;
 | |
| +}
 | |
| +#endif
 | |
| +
 | |
| +void
 | |
| +solver_addfeaturerule(Solver *solv, Solvable *s)
 | |
| +{
 | |
| +  Pool *pool = solv->pool;
 | |
| +  int i;
 | |
| +  Id p;
 | |
| +  Queue qs;
 | |
| +  Id qsbuf[64];
 | |
| +
 | |
| +#ifdef ENABLE_LINKED_PKGS
 | |
| +  if (is_linked_pseudo_package(solv, s))
 | |
| +    {
 | |
| +      solver_addrule(solv, 0, 0, 0);	/* no feature rules for those */
 | |
| +      return;
 | |
| +    }
 | |
| +#endif
 | |
| +  queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
 | |
| +  p = s - pool->solvables;
 | |
| +  policy_findupdatepackages(solv, s, &qs, 1);
 | |
| +  if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))
 | |
| +    {
 | |
| +      if (!dup_maykeepinstalled(solv, s))
 | |
| +	{
 | |
| +	  for (i = 0; i < qs.count; i++)
 | |
| +	    {
 | |
| +	      Solvable *ns = pool->solvables + qs.elements[i];
 | |
| +	      if (ns->repo != pool->installed || dup_maykeepinstalled(solv, ns))
 | |
| +		break;
 | |
| +	    }
 | |
| +	  if (i == qs.count)
 | |
| +	    {
 | |
| +	      solver_addrule(solv, 0, 0, 0);	/* this is an orphan */
 | |
| +	      queue_free(&qs);
 | |
| +	      return;
 | |
| +	    }
 | |
| +	}
 | |
| +    }
 | |
| +  if (qs.count > 1)
 | |
| +    {
 | |
| +      Id d = pool_queuetowhatprovides(pool, &qs);
 | |
| +      queue_free(&qs);
 | |
| +      solver_addrule(solv, p, 0, d);	/* allow update of s */
 | |
| +    }
 | |
| +  else
 | |
| +    {
 | |
| +      Id d = qs.count ? qs.elements[0] : 0;
 | |
| +      queue_free(&qs);
 | |
| +      solver_addrule(solv, p, d, 0);	/* allow update of s */
 | |
| +    }
 | |
| +}
 | |
| +
 | |
|  /*-------------------------------------------------------------------
 | |
|   *
 | |
|   * add rule for update
 | |
| @@ -1249,7 +1337,7 @@ set_specialupdaters(Solver *solv, Solvable *s, Id d)
 | |
|   */
 | |
|  
 | |
|  void
 | |
| -solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
 | |
| +solver_addupdaterule(Solver *solv, Solvable *s)
 | |
|  {
 | |
|    /* installed packages get a special upgrade allowed rule */
 | |
|    Pool *pool = solv->pool;
 | |
| @@ -1257,48 +1345,53 @@ solver_addupdaterule(Solver *solv, Solvable *s, int allow_all)
 | |
|    Queue qs;
 | |
|    Id qsbuf[64];
 | |
|    int isorphaned = 0;
 | |
| +  Rule *r;
 | |
| +  int islinkedpseudo = 0;
 | |
|  
 | |
| -  queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
 | |
|    p = s - pool->solvables;
 | |
| +#ifdef ENABLE_LINKED_PKGS
 | |
| +  islinkedpseudo = is_linked_pseudo_package(solv, s);
 | |
| +#endif
 | |
| +
 | |
| +  /* Orphan detection. We cheat by looking at the feature rule, which
 | |
| +   * we already calculated */
 | |
| +  r = solv->rules + solv->featurerules + (p - solv->installed->start);
 | |
| +  if (!r->p && !islinkedpseudo)
 | |
| +    {
 | |
| +      p = 0;
 | |
| +      queue_push(&solv->orphaned, s - pool->solvables);		/* an orphaned package */
 | |
| +      if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start))))
 | |
| +	p = s - pool->solvables;	/* keep this orphaned package installed */
 | |
| +      solver_addrule(solv, p, 0, 0);
 | |
| +      return;
 | |
| +    }
 | |
| +
 | |
| +  queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
 | |
|    /* find update candidates for 's' */
 | |
|    if (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)))
 | |
| -    p = finddistupgradepackages(solv, s, &qs, allow_all);
 | |
| +    p = finddistupgradepackages(solv, s, &qs);
 | |
|    else
 | |
| -    policy_findupdatepackages(solv, s, &qs, allow_all);
 | |
| +    policy_findupdatepackages(solv, s, &qs, 0);
 | |
|  
 | |
|  #ifdef ENABLE_LINKED_PKGS
 | |
| -  if (solv->instbuddy && solv->instbuddy[s - pool->solvables - solv->installed->start])
 | |
| +  if (islinkedpseudo)
 | |
|      {
 | |
| -      const char *name = pool_id2str(pool, s->name);
 | |
| -      if (strncmp(name, "pattern:", 8) == 0 || strncmp(name, "application:", 12) == 0)
 | |
| +      /* a linked pseudo package. As it is linked, we do not need an update/feature rule */
 | |
| +      /* nevertheless we set specialupdaters so we can update */
 | |
| +      solver_addrule(solv, 0, 0, 0);
 | |
| +      if (qs.count)
 | |
|  	{
 | |
| -	  /* a linked pseudo package. As it is linked, we do not need an update/feature rule */
 | |
| -	  /* nevertheless we set specialupdaters so we can update */
 | |
| -	  solver_addrule(solv, 0, 0, 0);
 | |
| -	  if (!allow_all && qs.count)
 | |
| -	    {
 | |
| -	      if (p != -SYSTEMSOLVABLE)
 | |
| -	        queue_unshift(&qs, p);
 | |
| -	      if (qs.count)
 | |
| -	        set_specialupdaters(solv, s, pool_queuetowhatprovides(pool, &qs));
 | |
| -	    }
 | |
| -	  queue_free(&qs);
 | |
| -	  return;
 | |
| +	  if (p != -SYSTEMSOLVABLE)
 | |
| +	    queue_unshift(&qs, p);
 | |
| +	  if (qs.count)
 | |
| +	    set_specialupdaters(solv, s, pool_queuetowhatprovides(pool, &qs));
 | |
|  	}
 | |
| -    }
 | |
| -#endif
 | |
| -
 | |
| -  if (!allow_all && !p)		/* !p implies qs.count == 0 */
 | |
| -    {
 | |
| -      queue_push(&solv->orphaned, s - pool->solvables);		/* an orphaned package */
 | |
| -      if (solv->keep_orphans && !(solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, s - pool->solvables - solv->installed->start))))
 | |
| -	p = s - pool->solvables;	/* keep this orphaned package installed */
 | |
|        queue_free(&qs);
 | |
| -      solver_addrule(solv, p, 0, 0);
 | |
|        return;
 | |
|      }
 | |
| +#endif
 | |
|  
 | |
| -  if (!allow_all && qs.count && solv->multiversion.size)
 | |
| +  if (qs.count && solv->multiversion.size)
 | |
|      {
 | |
|        int i, j;
 | |
|  
 | |
| diff --git a/src/rules.h b/src/rules.h
 | |
| index 606819b..29325ea 100644
 | |
| --- a/src/rules.h
 | |
| +++ b/src/rules.h
 | |
| @@ -111,7 +111,8 @@ extern void solver_addpkgrulesforlinked(struct _Solver *solv, Map *m);
 | |
|  extern void solver_addpkgrulesforupdaters(struct _Solver *solv, Solvable *s, Map *m, int allow_all);
 | |
|  
 | |
|  /* update/feature rules */
 | |
| -extern void solver_addupdaterule(struct _Solver *solv, Solvable *s, int allow_all);
 | |
| +extern void solver_addfeaturerule(struct _Solver *solv, Solvable *s);
 | |
| +extern void solver_addupdaterule(struct _Solver *solv, Solvable *s);
 | |
|  
 | |
|  /* infarch rules */
 | |
|  extern void solver_addinfarchrules(struct _Solver *solv, Map *addedmap);
 | |
| diff --git a/src/solver.c b/src/solver.c
 | |
| index 261f367..15a3114 100644
 | |
| --- a/src/solver.c
 | |
| +++ b/src/solver.c
 | |
| @@ -3716,7 +3716,7 @@ solver_solve(Solver *solv, Queue *job)
 | |
|  	      solver_addrule(solv, 0, 0, 0);	/* create dummy rule */
 | |
|  	      continue;
 | |
|  	    }
 | |
| -	  solver_addupdaterule(solv, s, 1);    /* allow s to be updated */
 | |
| +	  solver_addfeaturerule(solv, s);
 | |
|  	}
 | |
|        /* make sure we accounted for all rules */
 | |
|        assert(solv->nrules - solv->featurerules == installed->end - installed->start);
 | |
| @@ -3744,7 +3744,7 @@ solver_solve(Solver *solv, Queue *job)
 | |
|  	      solver_addrule(solv, 0, 0, 0);	/* create dummy rule */
 | |
|  	      continue;
 | |
|  	    }
 | |
| -	  solver_addupdaterule(solv, s, 0);	/* allowall = 0: downgrades not allowed */
 | |
| +	  solver_addupdaterule(solv, s);
 | |
|  	  /*
 | |
|  	   * check for and remove duplicate
 | |
|  	   */
 | |
| @@ -3759,9 +3759,10 @@ solver_solve(Solver *solv, Queue *job)
 | |
|  	  /* 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);
 | |
| +
 | |
|  	  if (!solver_rulecmp(solv, r, sr))
 | |
|  	    memset(sr, 0, sizeof(*sr));		/* delete unneeded feature rule */
 | |
| -	  else
 | |
| +	  else if (sr->p)
 | |
|  	    solver_disablerule(solv, sr);	/* disable feature rule for now */
 | |
|  	}
 | |
|        /* consistency check: we added a rule for _every_ installed solvable */
 | |
| -- 
 | |
| 2.5.0
 | |
| 
 |