1 /*
2  * Copyright (c) 2016, SUSE LLC.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7 
8 /* weird SUSE stuff. better not use it for your projects. */
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14 
15 #include "solver.h"
16 #include "solver_private.h"
17 #include "bitmap.h"
18 #include "pool.h"
19 #include "poolvendor.h"
20 #include "util.h"
21 
22 Offset
repo_fix_supplements(Repo * repo,Offset provides,Offset supplements,Offset freshens)23 repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens)
24 {
25   Pool *pool = repo->pool;
26   Id id, idp, idl;
27   char buf[1024], *p, *dep;
28   int i, l;
29 
30   if (provides)
31     {
32       for (i = provides; repo->idarraydata[i]; i++)
33 	{
34 	  id = repo->idarraydata[i];
35 	  if (ISRELDEP(id))
36 	    continue;
37 	  dep = (char *)pool_id2str(pool, id);
38 	  if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2)
39 	    {
40 	      idp = 0;
41 	      strcpy(buf + 2, dep);
42 	      dep = buf + 2 + 7;
43 	      if ((p = strchr(dep, ':')) != 0 && p != dep)
44 		{
45 		  *p++ = 0;
46 		  idp = pool_str2id(pool, dep, 1);
47 		  dep = p;
48 		}
49 	      id = 0;
50 	      while ((p = strchr(dep, ';')) != 0)
51 		{
52 		  if (p == dep)
53 		    {
54 		      dep = p + 1;
55 		      continue;
56 		    }
57 		  *p++ = 0;
58 		  idl = pool_str2id(pool, dep, 1);
59 		  idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
60 		  if (id)
61 		    id = pool_rel2id(pool, id, idl, REL_OR, 1);
62 		  else
63 		    id = idl;
64 		  dep = p;
65 		}
66 	      if (dep[0] && dep[1])
67 		{
68 	 	  for (p = dep; *p && *p != ')'; p++)
69 		    ;
70 		  *p = 0;
71 		  idl = pool_str2id(pool, dep, 1);
72 		  idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1);
73 		  if (id)
74 		    id = pool_rel2id(pool, id, idl, REL_OR, 1);
75 		  else
76 		    id = idl;
77 		}
78 	      if (idp)
79 		id = pool_rel2id(pool, idp, id, REL_AND, 1);
80 	      if (id)
81 		supplements = repo_addid_dep(repo, supplements, id, 0);
82 	    }
83 	  else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf))
84 	    {
85 	      strcpy(buf, dep);
86 	      p = buf + (p - dep);
87 	      *p++ = 0;
88 	      idp = pool_str2id(pool, buf, 1);
89 	      /* strip trailing slashes */
90 	      l = strlen(p);
91 	      while (l > 1 && p[l - 1] == '/')
92 		p[--l] = 0;
93 	      id = pool_str2id(pool, p, 1);
94 	      id = pool_rel2id(pool, idp, id, REL_WITH, 1);
95 	      id = pool_rel2id(pool, NAMESPACE_SPLITPROVIDES, id, REL_NAMESPACE, 1);
96 	      supplements = repo_addid_dep(repo, supplements, id, 0);
97 	    }
98 	}
99     }
100   if (supplements)
101     {
102       for (i = supplements; repo->idarraydata[i]; i++)
103 	{
104 	  id = repo->idarraydata[i];
105 	  if (ISRELDEP(id))
106 	    continue;
107 	  dep = (char *)pool_id2str(pool, id);
108 	  if (!strncmp(dep, "system:modalias(", 16))
109 	    dep += 7;
110 	  if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf))
111 	    {
112 	      strcpy(buf, dep);
113 	      p = strchr(buf + 9, ':');
114 	      if (p && p != buf + 9 && strchr(p + 1, ':'))
115 		{
116 		  *p++ = 0;
117 		  idp = pool_str2id(pool, buf + 9, 1);
118 		  p[strlen(p) - 1] = 0;
119 		  id = pool_str2id(pool, p, 1);
120 		  id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
121 		  id = pool_rel2id(pool, idp, id, REL_AND, 1);
122 		}
123 	      else
124 		{
125 		  p = buf + 9;
126 		  p[strlen(p) - 1] = 0;
127 		  id = pool_str2id(pool, p, 1);
128 		  id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1);
129 		}
130 	      if (id)
131 		repo->idarraydata[i] = id;
132 	    }
133 	  else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf))
134 	    {
135 	      strcpy(buf, dep);
136 	      id = 0;
137 	      dep = buf + 11;
138 	      while ((p = strchr(dep, ':')) != 0)
139 		{
140 		  if (p == dep)
141 		    {
142 		      dep = p + 1;
143 		      continue;
144 		    }
145 		  /* argh, allow pattern: prefix. sigh */
146 		  if (p - dep == 7 && !strncmp(dep, "pattern", 7))
147 		    {
148 		      p = strchr(p + 1, ':');
149 		      if (!p)
150 			break;
151 		    }
152 		  *p++ = 0;
153 		  idp = pool_str2id(pool, dep, 1);
154 		  if (id)
155 		    id = pool_rel2id(pool, id, idp, REL_AND, 1);
156 		  else
157 		    id = idp;
158 		  dep = p;
159 		}
160 	      if (dep[0] && dep[1])
161 		{
162 		  dep[strlen(dep) - 1] = 0;
163 		  idp = pool_str2id(pool, dep, 1);
164 		  if (id)
165 		    id = pool_rel2id(pool, id, idp, REL_AND, 1);
166 		  else
167 		    id = idp;
168 		}
169 	      if (id)
170 		repo->idarraydata[i] = id;
171 	    }
172 	  else if (!strncmp(dep, "filesystem(", 11) && strlen(dep) < sizeof(buf))
173 	    {
174 	      strcpy(buf, dep + 11);
175 	      if ((p = strrchr(buf, ')')) != 0)
176 		*p = 0;
177 	      id = pool_str2id(pool, buf, 1);
178 	      id = pool_rel2id(pool, NAMESPACE_FILESYSTEM, id, REL_NAMESPACE, 1);
179 	      repo->idarraydata[i] = id;
180 	    }
181 	}
182     }
183   if (freshens && repo->idarraydata[freshens])
184     {
185       Id idsupp = 0, idfresh = 0;
186       if (!supplements || !repo->idarraydata[supplements])
187 	return freshens;
188       for (i = supplements; repo->idarraydata[i]; i++)
189         {
190 	  if (!idsupp)
191 	    idsupp = repo->idarraydata[i];
192 	  else
193 	    idsupp = pool_rel2id(pool, idsupp, repo->idarraydata[i], REL_OR, 1);
194         }
195       for (i = freshens; repo->idarraydata[i]; i++)
196         {
197 	  if (!idfresh)
198 	    idfresh = repo->idarraydata[i];
199 	  else
200 	    idfresh = pool_rel2id(pool, idfresh, repo->idarraydata[i], REL_OR, 1);
201         }
202       if (!idsupp)
203         idsupp = idfresh;
204       else
205 	idsupp = pool_rel2id(pool, idsupp, idfresh, REL_AND, 1);
206       supplements = repo_addid_dep(repo, 0, idsupp, 0);
207     }
208   return supplements;
209 }
210 
211 Offset
repo_fix_conflicts(Repo * repo,Offset conflicts)212 repo_fix_conflicts(Repo *repo, Offset conflicts)
213 {
214   char buf[1024], *dep;
215   Pool *pool = repo->pool;
216   Id id;
217   int i;
218 
219   if (!conflicts)
220     return conflicts;
221   for (i = conflicts; repo->idarraydata[i]; i++)
222     {
223       id = repo->idarraydata[i];
224       if (ISRELDEP(id))
225 	continue;
226       dep = (char *)pool_id2str(pool, id);
227       if (!strncmp(dep, "otherproviders(", 15) && dep[15] && strlen(dep) < sizeof(buf) - 2)
228 	{
229 	  strcpy(buf, dep + 15);
230 	  buf[strlen(buf) - 1] = 0;
231 	  id = pool_str2id(pool, buf, 1);
232 	  id = pool_rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1);
233 	  repo->idarraydata[i] = id;
234 	}
235     }
236   return conflicts;
237 }
238 
239 void
repo_rewrite_suse_deps(Solvable * s,Offset freshens)240 repo_rewrite_suse_deps(Solvable *s, Offset freshens)
241 {
242   s->supplements = repo_fix_supplements(s->repo, s->provides, s->supplements, freshens);
243   if (s->conflicts)
244     s->conflicts = repo_fix_conflicts(s->repo, s->conflicts);
245 }
246 
247 /**********************************************************************************/
248 
249 static inline Id
dep2name(Pool * pool,Id dep)250 dep2name(Pool *pool, Id dep)
251 {
252   while (ISRELDEP(dep))
253     {
254       Reldep *rd = GETRELDEP(pool, dep);
255       dep = rd->name;
256     }
257   return dep;
258 }
259 
260 static int
providedbyinstalled_multiversion(Pool * pool,Map * installed,Id n,Id con)261 providedbyinstalled_multiversion(Pool *pool, Map *installed, Id n, Id con)
262 {
263   Id p, pp;
264   Solvable *sn = pool->solvables + n;
265 
266   FOR_PROVIDES(p, pp, sn->name)
267     {
268       Solvable *s = pool->solvables + p;
269       if (s->name != sn->name || s->arch != sn->arch)
270         continue;
271       if (!MAPTST(installed, p))
272         continue;
273       if (pool_match_nevr(pool, pool->solvables + p, con))
274         continue;
275       return 1;         /* found installed package that doesn't conflict */
276     }
277   return 0;
278 }
279 
280 static inline int
providedbyinstalled(Pool * pool,Map * installed,Id dep,int ispatch,Map * multiversionmap)281 providedbyinstalled(Pool *pool, Map *installed, Id dep, int ispatch, Map *multiversionmap)
282 {
283   Id p, pp;
284   FOR_PROVIDES(p, pp, dep)
285     {
286       if (p == SYSTEMSOLVABLE)
287 	return -1;
288       if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
289 	continue;
290       if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep))
291 	if (providedbyinstalled_multiversion(pool, installed, p, dep))
292 	  continue;
293       if (MAPTST(installed, p))
294 	return 1;
295     }
296   return 0;
297 }
298 
299 /* xmap:
300  *  1: installed
301  *  2: conflicts with installed
302  *  8: interesting (only true if installed)
303  * 16: undecided
304  */
305 
306 static int
providedbyinstalled_multiversion_xmap(Pool * pool,unsigned char * map,Id n,Id con)307 providedbyinstalled_multiversion_xmap(Pool *pool, unsigned char *map, Id n, Id con)
308 {
309   Id p, pp;
310   Solvable *sn = pool->solvables + n;
311 
312   FOR_PROVIDES(p, pp, sn->name)
313     {
314       Solvable *s = pool->solvables + p;
315       if (s->name != sn->name || s->arch != sn->arch)
316         continue;
317       if ((map[p] & 9) != 9)
318         continue;
319       if (pool_match_nevr(pool, pool->solvables + p, con))
320         continue;
321       return 1;         /* found installed package that doesn't conflict */
322     }
323   return 0;
324 }
325 
326 
327 static inline int
providedbyinstalled_xmap(Pool * pool,unsigned char * map,Id dep,int ispatch,Map * multiversionmap)328 providedbyinstalled_xmap(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *multiversionmap)
329 {
330   Id p, pp;
331   int r = 0;
332   FOR_PROVIDES(p, pp, dep)
333     {
334       if (p == SYSTEMSOLVABLE)
335         return 1;       /* always boring, as never constraining */
336       if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
337         continue;
338       if (ispatch && multiversionmap && multiversionmap->size && MAPTST(multiversionmap, p) && ISRELDEP(dep))
339         if (providedbyinstalled_multiversion_xmap(pool, map, p, dep))
340           continue;
341       if ((map[p] & 9) == 9)
342         return 9;
343       r |= map[p] & 17;
344     }
345   return r;
346 }
347 
348 /* FIXME: this mirrors policy_illegal_vendorchange */
349 static int
pool_illegal_vendorchange(Pool * pool,Solvable * s1,Solvable * s2)350 pool_illegal_vendorchange(Pool *pool, Solvable *s1, Solvable *s2)
351 {
352   Id v1, v2;
353   Id vendormask1, vendormask2;
354 
355   if (pool->custom_vendorcheck)
356     return pool->custom_vendorcheck(pool, s1, s2);
357   /* treat a missing vendor as empty string */
358   v1 = s1->vendor ? s1->vendor : ID_EMPTY;
359   v2 = s2->vendor ? s2->vendor : ID_EMPTY;
360   if (v1 == v2)
361     return 0;
362   vendormask1 = pool_vendor2mask(pool, v1);
363   if (!vendormask1)
364     return 1;   /* can't match */
365   vendormask2 = pool_vendor2mask(pool, v2);
366   if ((vendormask1 & vendormask2) != 0)
367     return 0;
368   return 1;     /* no class matches */
369 }
370 
371 /* check if this patch is relevant according to the vendor. To bad that patches
372  * don't have a vendor, so we need to do some careful repo testing. */
373 int
solvable_is_irrelevant_patch(Solvable * s,Map * installedmap)374 solvable_is_irrelevant_patch(Solvable *s, Map *installedmap)
375 {
376   Pool *pool = s->repo->pool;
377   Id con, *conp;
378   int hadpatchpackage = 0;
379   const char *status;
380 
381   status = solvable_lookup_str(s, UPDATE_STATUS);
382   if (status && !strcmp(status, "retracted"))
383     return 1;
384   if (!s->conflicts)
385     return 0;
386   conp = s->repo->idarraydata + s->conflicts;
387   while ((con = *conp++) != 0)
388     {
389       Reldep *rd;
390       Id p, pp, p2, pp2;
391       if (!ISRELDEP(con))
392         continue;
393       rd = GETRELDEP(pool, con);
394       if (rd->flags != REL_LT)
395         continue;
396       FOR_PROVIDES(p, pp, con)
397         {
398           Solvable *si;
399           if (!MAPTST(installedmap, p))
400             continue;
401           si = pool->solvables + p;
402           if (!pool_match_nevr(pool, si, con))
403             continue;
404           FOR_PROVIDES(p2, pp2, rd->name)
405             {
406               Solvable *s2 = pool->solvables + p2;
407               if (!pool_match_nevr(pool, s2, rd->name))
408                 continue;
409               if (pool_match_nevr(pool, s2, con))
410                 continue;       /* does not fulfill patch */
411               if (s2->repo == s->repo)
412                 {
413                   hadpatchpackage = 1;
414                   /* ok, we have a package from the patch repo that solves the conflict. check vendor */
415                   if (si->vendor == s2->vendor)
416                     return 0;
417                   if (!pool_illegal_vendorchange(pool, si, s2))
418                     return 0;
419                   /* vendor change was illegal, ignore conflict */
420                 }
421             }
422         }
423     }
424   /* if we didn't find a patchpackage don't claim that the patch is irrelevant */
425   if (!hadpatchpackage)
426     return 0;
427   return 1;
428 }
429 
430 /*
431  * solvable_trivial_installable_map - answers if a solvable is installable
432  * without any other installs/deinstalls.
433  * The packages considered to be installed are provided via the
434  * installedmap bitmap. A additional "conflictsmap" bitmap providing
435  * information about the conflicts of the installed packages can be
436  * used for extra speed up. Provide a NULL pointer if you do not
437  * have this information.
438  * Both maps can be created with pool_create_state_maps() or
439  * solver_create_state_maps().
440  *
441  * returns:
442  * 1:  solvable is installable without any other package changes
443  * 0:  solvable is not installable
444  * -1: solvable is installable, but doesn't constrain any installed packages
445  */
446 int
solvable_trivial_installable_map(Solvable * s,Map * installedmap,Map * conflictsmap,Map * multiversionmap)447 solvable_trivial_installable_map(Solvable *s, Map *installedmap, Map *conflictsmap, Map *multiversionmap)
448 {
449   Pool *pool = s->repo->pool;
450   Solvable *s2;
451   Id p, *dp;
452   Id *reqp, req;
453   Id *conp, con;
454   int r, interesting = 0;
455 
456   if (conflictsmap && MAPTST(conflictsmap, s - pool->solvables))
457     return 0;
458   if (s->requires)
459     {
460       reqp = s->repo->idarraydata + s->requires;
461       while ((req = *reqp++) != 0)
462 	{
463 	  if (req == SOLVABLE_PREREQMARKER)
464 	    continue;
465           r = providedbyinstalled(pool, installedmap, req, 0, 0);
466 	  if (!r)
467 	    return 0;
468 	  if (r > 0)
469 	    interesting = 1;
470 	}
471     }
472   if (s->conflicts)
473     {
474       int ispatch = 0;
475 
476       if (!strncmp("patch:", pool_id2str(pool, s->name), 6))
477 	ispatch = 1;
478       conp = s->repo->idarraydata + s->conflicts;
479       while ((con = *conp++) != 0)
480 	{
481 	  if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap))
482 	    {
483 	      if (ispatch && solvable_is_irrelevant_patch(s, installedmap))
484 		return -1;
485 	      return 0;
486 	    }
487 	  if (!interesting && ISRELDEP(con))
488 	    {
489               con = dep2name(pool, con);
490 	      if (providedbyinstalled(pool, installedmap, con, ispatch, multiversionmap))
491 		interesting = 1;
492 	    }
493 	}
494       if (ispatch && interesting && solvable_is_irrelevant_patch(s, installedmap))
495 	interesting = 0;
496     }
497   if (!conflictsmap)
498     {
499       int i;
500 
501       p = s - pool->solvables;
502       for (i = 1; i < pool->nsolvables; i++)
503 	{
504 	  if (!MAPTST(installedmap, i))
505 	    continue;
506 	  s2 = pool->solvables + i;
507 	  if (!s2->conflicts)
508 	    continue;
509 	  conp = s2->repo->idarraydata + s2->conflicts;
510 	  while ((con = *conp++) != 0)
511 	    {
512 	      dp = pool_whatprovides_ptr(pool, con);
513 	      for (; *dp; dp++)
514 		if (*dp == p)
515 		  return 0;
516 	    }
517 	}
518      }
519   return interesting ? 1 : -1;
520 }
521 
522 /*
523  * different interface for solvable_trivial_installable_map, where
524  * the information about the installed packages is provided
525  * by a queue.
526  */
527 int
solvable_trivial_installable_queue(Solvable * s,Queue * installed,Map * multiversionmap)528 solvable_trivial_installable_queue(Solvable *s, Queue *installed, Map *multiversionmap)
529 {
530   Pool *pool = s->repo->pool;
531   int i;
532   Id p;
533   Map installedmap;
534   int r;
535 
536   map_init(&installedmap, pool->nsolvables);
537   for (i = 0; i < installed->count; i++)
538     {
539       p = installed->elements[i];
540       if (p > 0)		/* makes it work with decisionq */
541 	MAPSET(&installedmap, p);
542     }
543   r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap);
544   map_free(&installedmap);
545   return r;
546 }
547 
548 /*
549  * different interface for solvable_trivial_installable_map, where
550  * the information about the installed packages is provided
551  * by a repo containing the installed solvables.
552  */
553 int
solvable_trivial_installable_repo(Solvable * s,Repo * installed,Map * multiversionmap)554 solvable_trivial_installable_repo(Solvable *s, Repo *installed, Map *multiversionmap)
555 {
556   Pool *pool = s->repo->pool;
557   Id p;
558   Solvable *s2;
559   Map installedmap;
560   int r;
561 
562   map_init(&installedmap, pool->nsolvables);
563   FOR_REPO_SOLVABLES(installed, p, s2)
564     MAPSET(&installedmap, p);
565   r = solvable_trivial_installable_map(s, &installedmap, 0, multiversionmap);
566   map_free(&installedmap);
567   return r;
568 }
569 
570 /*
571  * pool_trivial_installable - calculate if a set of solvables is
572  * trivial installable without any other installs/deinstalls of
573  * packages not belonging to the set.
574  *
575  * the state is returned in the result queue:
576  * 1:  solvable is installable without any other package changes
577  * 0:  solvable is not installable
578  * -1: solvable is installable, but doesn't constrain any installed packages
579  */
580 
581 void
pool_trivial_installable_multiversionmap(Pool * pool,Map * installedmap,Queue * pkgs,Queue * res,Map * multiversionmap)582 pool_trivial_installable_multiversionmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *multiversionmap)
583 {
584   int i, r, m, did;
585   Id p, *dp, con, *conp, req, *reqp;
586   unsigned char *map;
587   Solvable *s;
588 
589   map = solv_calloc(pool->nsolvables, 1);
590   for (p = 1; p < pool->nsolvables; p++)
591     {
592       if (!MAPTST(installedmap, p))
593 	continue;
594       map[p] |= 9;
595       s = pool->solvables + p;
596       if (!s->conflicts)
597 	continue;
598       conp = s->repo->idarraydata + s->conflicts;
599       while ((con = *conp++) != 0)
600 	{
601 	  dp = pool_whatprovides_ptr(pool, con);
602 	  for (; *dp; dp++)
603 	    map[p] |= 2;	/* XXX: self conflict ? */
604 	}
605     }
606   for (i = 0; i < pkgs->count; i++)
607     map[pkgs->elements[i]] = 16;
608 
609   for (i = 0, did = 0; did < pkgs->count; i++, did++)
610     {
611       if (i == pkgs->count)
612 	i = 0;
613       p = pkgs->elements[i];
614       if ((map[p] & 16) == 0)
615 	continue;
616       if ((map[p] & 2) != 0)
617 	{
618 	  map[p] = 2;
619 	  continue;
620 	}
621       s = pool->solvables + p;
622       m = 1;
623       if (s->requires)
624 	{
625 	  reqp = s->repo->idarraydata + s->requires;
626 	  while ((req = *reqp++) != 0)
627 	    {
628 	      if (req == SOLVABLE_PREREQMARKER)
629 		continue;
630 	      r = providedbyinstalled_xmap(pool, map, req, 0, 0);
631 	      if (!r)
632 		{
633 		  /* decided and miss */
634 		  map[p] = 2;
635 		  did = 0;
636 		  break;
637 		}
638 	      if (r == 16)
639 		break;	/* undecided */
640 	      m |= r;	/* 1 | 9 | 17 */
641 	    }
642 	  if (req)
643 	    continue;
644 	  if ((m & 9) == 9)
645 	    m = 9;
646 	}
647       if (s->conflicts)
648 	{
649 	  int ispatch = 0;	/* see solver.c patch handling */
650 
651 	  if (!strncmp("patch:", pool_id2str(pool, s->name), 6))
652 	    ispatch = 1;
653 	  conp = s->repo->idarraydata + s->conflicts;
654 	  while ((con = *conp++) != 0)
655 	    {
656 	      if ((providedbyinstalled_xmap(pool, map, con, ispatch, multiversionmap) & 1) != 0)
657 		{
658 		  map[p] = 2;
659 		  did = 0;
660 		  break;
661 		}
662 	      if ((m == 1 || m == 17) && ISRELDEP(con))
663 		{
664 		  con = dep2name(pool, con);
665 		  if ((providedbyinstalled_xmap(pool, map, con, ispatch, multiversionmap) & 1) != 0)
666 		    m = 9;
667 		}
668 	    }
669 	  if (con)
670 	    continue;	/* found a conflict */
671 	}
672       if (m != map[p])
673 	{
674 	  map[p] = m;
675 	  did = 0;
676 	}
677     }
678   queue_free(res);
679   queue_init_clone(res, pkgs);
680   for (i = 0; i < pkgs->count; i++)
681     {
682       m = map[pkgs->elements[i]];
683       if ((m & 9) == 9)
684 	r = 1;
685       else if (m & 1)
686 	r = -1;
687       else
688 	r = 0;
689       res->elements[i] = r;
690     }
691   free(map);
692 }
693 
694 void
pool_trivial_installable(Pool * pool,Map * installedmap,Queue * pkgs,Queue * res)695 pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res)
696 {
697   pool_trivial_installable_multiversionmap(pool, installedmap, pkgs, res, 0);
698 }
699 
700 void
solver_trivial_installable(Solver * solv,Queue * pkgs,Queue * res)701 solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res)
702 {
703   Pool *pool = solv->pool;
704   Map installedmap;
705   int i;
706   pool_create_state_maps(pool,  &solv->decisionq, &installedmap, 0);
707   pool_trivial_installable_multiversionmap(pool, &installedmap, pkgs, res, solv->multiversion.size ? &solv->multiversion : 0);
708   for (i = 0; i < res->count; i++)
709     if (res->elements[i] != -1)
710       {
711         Solvable *s = pool->solvables + pkgs->elements[i];
712         if (!strncmp("patch:", pool_id2str(pool, s->name), 6) && solvable_is_irrelevant_patch(s, &installedmap))
713           res->elements[i] = -1;
714       }
715   map_free(&installedmap);
716 }
717 
718 void
solver_printtrivial(Solver * solv)719 solver_printtrivial(Solver *solv)
720 {
721   Pool *pool = solv->pool;
722   Queue in, out;
723   Id p;
724   const char *n;
725   Solvable *s;
726   int i;
727 
728   queue_init(&in);
729   for (p = 1, s = pool->solvables + p; p < solv->pool->nsolvables; p++, s++)
730     {
731       n = pool_id2str(pool, s->name);
732       if (strncmp(n, "patch:", 6) != 0 && strncmp(n, "pattern:", 8) != 0)
733         continue;
734       queue_push(&in, p);
735     }
736   if (!in.count)
737     {
738       queue_free(&in);
739       return;
740     }
741   queue_init(&out);
742   solver_trivial_installable(solv, &in, &out);
743   POOL_DEBUG(SOLV_DEBUG_RESULT, "trivial installable status:\n");
744   for (i = 0; i < in.count; i++)
745     POOL_DEBUG(SOLV_DEBUG_RESULT, "  %s: %d\n", pool_solvid2str(pool, in.elements[i]), out.elements[i]);
746   POOL_DEBUG(SOLV_DEBUG_RESULT, "\n");
747   queue_free(&in);
748   queue_free(&out);
749 }
750 
751 
752