00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stdarg.h>
00018 #include <unistd.h>
00019 #include <string.h>
00020
00021 #include "pool.h"
00022 #include "repo.h"
00023 #include "poolid.h"
00024 #include "poolid_private.h"
00025 #include "poolarch.h"
00026 #include "util.h"
00027 #include "bitmap.h"
00028 #include "evr.h"
00029
00030 #define SOLVABLE_BLOCK 255
00031
00032 #define KNOWNID_INITIALIZE
00033 #include "knownid.h"
00034 #undef KNOWNID_INITIALIZE
00035
00036
00037 Pool *
00038 pool_create(void)
00039 {
00040 Pool *pool;
00041 Solvable *s;
00042
00043 pool = (Pool *)sat_calloc(1, sizeof(*pool));
00044
00045 stringpool_init (&pool->ss, initpool_data);
00046
00047
00048 pool->rels = sat_extend_resize(0, 1, sizeof(Reldep), REL_BLOCK);
00049 pool->nrels = 1;
00050 memset(pool->rels, 0, sizeof(Reldep));
00051
00052
00053 pool->solvables = sat_extend_resize(0, 2, sizeof(Solvable), SOLVABLE_BLOCK);
00054 pool->nsolvables = 2;
00055 memset(pool->solvables, 0, 2 * sizeof(Solvable));
00056 s = pool->solvables + SYSTEMSOLVABLE;
00057 s->name = SYSTEM_SYSTEM;
00058 s->arch = ARCH_NOARCH;
00059 s->evr = ID_EMPTY;
00060
00061 queue_init(&pool->vendormap);
00062
00063 pool->debugmask = SAT_DEBUG_RESULT;
00064 #ifdef FEDORA
00065 pool->obsoleteusescolors = 1;
00066 #endif
00067 #ifdef DEBIAN
00068 pool->allowselfconflicts = 1;
00069 # ifdef MULTI_SEMANTICS
00070 pool->disttype = DISTTYPE_DEB;
00071 # endif
00072 #endif
00073 return pool;
00074 }
00075
00076
00077
00078 void
00079 pool_free(Pool *pool)
00080 {
00081 int i;
00082
00083 pool_freewhatprovides(pool);
00084 pool_freeidhashes(pool);
00085 repo_freeallrepos(pool, 1);
00086 sat_free(pool->id2arch);
00087 sat_free(pool->solvables);
00088 stringpool_free(&pool->ss);
00089 sat_free(pool->rels);
00090 queue_free(&pool->vendormap);
00091 for (i = 0; i < POOL_TMPSPACEBUF; i++)
00092 sat_free(pool->tmpspacebuf[i]);
00093 for (i = 0; i < pool->nlanguages; i++)
00094 free((char *)pool->languages[i]);
00095 sat_free(pool->languages);
00096 sat_free(pool->languagecache);
00097 sat_free(pool);
00098 }
00099
00100 #ifdef MULTI_SEMANTICS
00101 void
00102 pool_setdisttype(Pool *pool, int disttype)
00103 {
00104 pool->disttype = disttype;
00105 }
00106 #endif
00107
00108 Id
00109 pool_add_solvable(Pool *pool)
00110 {
00111 pool->solvables = sat_extend(pool->solvables, pool->nsolvables, 1, sizeof(Solvable), SOLVABLE_BLOCK);
00112 memset(pool->solvables + pool->nsolvables, 0, sizeof(Solvable));
00113 return pool->nsolvables++;
00114 }
00115
00116 Id
00117 pool_add_solvable_block(Pool *pool, int count)
00118 {
00119 Id nsolvables = pool->nsolvables;
00120 if (!count)
00121 return nsolvables;
00122 pool->solvables = sat_extend(pool->solvables, pool->nsolvables, count, sizeof(Solvable), SOLVABLE_BLOCK);
00123 memset(pool->solvables + nsolvables, 0, sizeof(Solvable) * count);
00124 pool->nsolvables += count;
00125 return nsolvables;
00126 }
00127
00128 void
00129 pool_free_solvable_block(Pool *pool, Id start, int count, int reuseids)
00130 {
00131 if (!count)
00132 return;
00133 if (reuseids && start + count == pool->nsolvables)
00134 {
00135
00136 pool->nsolvables = start;
00137 return;
00138 }
00139 memset(pool->solvables + start, 0, sizeof(Solvable) * count);
00140 }
00141
00142
00143 void
00144 pool_set_installed(Pool *pool, Repo *installed)
00145 {
00146 if (pool->installed == installed)
00147 return;
00148 pool->installed = installed;
00149 pool_freewhatprovides(pool);
00150 }
00151
00152 static int
00153 pool_shrink_whatprovides_sortcmp(const void *ap, const void *bp, void *dp)
00154 {
00155 int r;
00156 Pool *pool = dp;
00157 Id oa, ob, *da, *db;
00158 oa = pool->whatprovides[*(Id *)ap];
00159 ob = pool->whatprovides[*(Id *)bp];
00160 if (oa == ob)
00161 return *(Id *)ap - *(Id *)bp;
00162 if (!oa)
00163 return -1;
00164 if (!ob)
00165 return 1;
00166 da = pool->whatprovidesdata + oa;
00167 db = pool->whatprovidesdata + ob;
00168 while (*db)
00169 if ((r = (*da++ - *db++)) != 0)
00170 return r;
00171 if (*da)
00172 return *da;
00173 return *(Id *)ap - *(Id *)bp;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182 static void
00183 pool_shrink_whatprovides(Pool *pool)
00184 {
00185 Id i, id;
00186 Id *sorted;
00187 Id lastid, *last, *dp, *lp;
00188 Offset o;
00189 int r;
00190
00191 if (pool->ss.nstrings < 3)
00192 return;
00193 sorted = sat_malloc2(pool->ss.nstrings, sizeof(Id));
00194 for (id = 0; id < pool->ss.nstrings; id++)
00195 sorted[id] = id;
00196 sat_sort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp, pool);
00197 last = 0;
00198 lastid = 0;
00199 for (i = 1; i < pool->ss.nstrings; i++)
00200 {
00201 id = sorted[i];
00202 o = pool->whatprovides[id];
00203 if (o == 0 || o == 1)
00204 continue;
00205 dp = pool->whatprovidesdata + o;
00206 if (last)
00207 {
00208 lp = last;
00209 while (*dp)
00210 if (*dp++ != *lp++)
00211 {
00212 last = 0;
00213 break;
00214 }
00215 if (last && *lp)
00216 last = 0;
00217 if (last)
00218 {
00219 pool->whatprovides[id] = -lastid;
00220 continue;
00221 }
00222 }
00223 last = pool->whatprovidesdata + o;
00224 lastid = id;
00225 }
00226 sat_free(sorted);
00227 dp = pool->whatprovidesdata + 2;
00228 for (id = 1; id < pool->ss.nstrings; id++)
00229 {
00230 o = pool->whatprovides[id];
00231 if (o == 0 || o == 1)
00232 continue;
00233 if ((Id)o < 0)
00234 {
00235 i = -(Id)o;
00236 if (i >= id)
00237 abort();
00238 pool->whatprovides[id] = pool->whatprovides[i];
00239 continue;
00240 }
00241 lp = pool->whatprovidesdata + o;
00242 if (lp < dp)
00243 abort();
00244 pool->whatprovides[id] = dp - pool->whatprovidesdata;
00245 while ((*dp++ = *lp++) != 0)
00246 ;
00247 }
00248 o = dp - pool->whatprovidesdata;
00249 POOL_DEBUG(SAT_DEBUG_STATS, "shrunk whatprovidesdata from %d to %d\n", pool->whatprovidesdataoff, o);
00250 if (pool->whatprovidesdataoff == o)
00251 return;
00252 r = pool->whatprovidesdataoff - o;
00253 pool->whatprovidesdataoff = o;
00254 pool->whatprovidesdata = sat_realloc(pool->whatprovidesdata, (o + pool->whatprovidesdataleft) * sizeof(Id));
00255 if (r > pool->whatprovidesdataleft)
00256 r = pool->whatprovidesdataleft;
00257 memset(pool->whatprovidesdata + o, 0, r * sizeof(Id));
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267 void
00268 pool_createwhatprovides(Pool *pool)
00269 {
00270 int i, num, np, extra;
00271 Offset off;
00272 Solvable *s;
00273 Id id;
00274 Offset *idp, n;
00275 Offset *whatprovides;
00276 Id *whatprovidesdata, *d;
00277 Repo *installed = pool->installed;
00278 unsigned int now;
00279
00280 now = sat_timems(0);
00281 POOL_DEBUG(SAT_DEBUG_STATS, "number of solvables: %d\n", pool->nsolvables);
00282 POOL_DEBUG(SAT_DEBUG_STATS, "number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels);
00283
00284 pool_freeidhashes(pool);
00285 pool_freewhatprovides(pool);
00286 num = pool->ss.nstrings;
00287 pool->whatprovides = whatprovides = sat_calloc_block(num, sizeof(Offset), WHATPROVIDES_BLOCK);
00288 pool->whatprovides_rel = sat_calloc_block(pool->nrels, sizeof(Offset), WHATPROVIDES_BLOCK);
00289
00290
00291 for (i = pool->nsolvables - 1; i > 0; i--)
00292 {
00293 Id *pp;
00294 s = pool->solvables + i;
00295 if (!s->provides || !s->repo || s->repo->disabled)
00296 continue;
00297
00298
00299 if (s->repo != installed && !pool_installable(pool, s))
00300 continue;
00301 pp = s->repo->idarraydata + s->provides;
00302 while ((id = *pp++) != 0)
00303 {
00304 while (ISRELDEP(id))
00305 {
00306 Reldep *rd = GETRELDEP(pool, id);
00307 id = rd->name;
00308 }
00309 whatprovides[id]++;
00310 }
00311 }
00312
00313 off = 2;
00314 np = 0;
00315 for (i = 0, idp = whatprovides; i < num; i++, idp++)
00316 {
00317 n = *idp;
00318 if (!n)
00319 continue;
00320 off += n;
00321 *idp = off++;
00322 np++;
00323 }
00324
00325 POOL_DEBUG(SAT_DEBUG_STATS, "provide ids: %d\n", np);
00326
00327
00328 extra = 2 * pool->nrels;
00329 if (extra < 256)
00330 extra = 256;
00331
00332 POOL_DEBUG(SAT_DEBUG_STATS, "provide space needed: %d + %d\n", off, extra);
00333
00334
00335 whatprovidesdata = sat_calloc(off + extra, sizeof(Id));
00336
00337
00338 for (i = pool->nsolvables - 1; i > 0; i--)
00339 {
00340 Id *pp;
00341 s = pool->solvables + i;
00342 if (!s->provides || !s->repo || s->repo->disabled)
00343 continue;
00344 if (s->repo != installed && !pool_installable(pool, s))
00345 continue;
00346
00347
00348 pp = s->repo->idarraydata + s->provides;
00349 while ((id = *pp++) != 0)
00350 {
00351 while (ISRELDEP(id))
00352 {
00353 Reldep *rd = GETRELDEP(pool, id);
00354 id = rd->name;
00355 }
00356 d = whatprovidesdata + whatprovides[id];
00357 if (*d != i)
00358 {
00359 d[-1] = i;
00360 whatprovides[id]--;
00361 }
00362 }
00363 }
00364 pool->whatprovidesdata = whatprovidesdata;
00365 pool->whatprovidesdataoff = off;
00366 pool->whatprovidesdataleft = extra;
00367 pool_shrink_whatprovides(pool);
00368 POOL_DEBUG(SAT_DEBUG_STATS, "whatprovides memory used: %d K id array, %d K data\n", (pool->ss.nstrings + pool->nrels + WHATPROVIDES_BLOCK) / (int)(1024/sizeof(Id)), (pool->whatprovidesdataoff + pool->whatprovidesdataleft) / (int)(1024/sizeof(Id)));
00369 POOL_DEBUG(SAT_DEBUG_STATS, "createwhatprovides took %d ms\n", sat_timems(now));
00370 }
00371
00372
00373
00374
00375
00376
00377 void
00378 pool_freewhatprovides(Pool *pool)
00379 {
00380 pool->whatprovides = sat_free(pool->whatprovides);
00381 pool->whatprovides_rel = sat_free(pool->whatprovides_rel);
00382 pool->whatprovidesdata = sat_free(pool->whatprovidesdata);
00383 pool->whatprovidesdataoff = 0;
00384 pool->whatprovidesdataleft = 0;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 Id
00400 pool_queuetowhatprovides(Pool *pool, Queue *q)
00401 {
00402 Offset off;
00403 int count = q->count;
00404
00405 if (count == 0)
00406 return 1;
00407
00408
00409 if (pool->whatprovidesdataleft < count + 1)
00410 {
00411 POOL_DEBUG(SAT_DEBUG_STATS, "growing provides hash data...\n");
00412 pool->whatprovidesdata = sat_realloc(pool->whatprovidesdata, (pool->whatprovidesdataoff + count + 4096) * sizeof(Id));
00413 pool->whatprovidesdataleft = count + 4096;
00414 }
00415
00416
00417 off = pool->whatprovidesdataoff;
00418 memcpy(pool->whatprovidesdata + pool->whatprovidesdataoff, q->elements, count * sizeof(Id));
00419
00420
00421 pool->whatprovidesdataoff += count;
00422 pool->whatprovidesdata[pool->whatprovidesdataoff++] = ID_NULL;
00423 pool->whatprovidesdataleft -= count + 1;
00424
00425 return (Id)off;
00426 }
00427
00428
00429
00430
00431 #if defined(MULTI_SEMANTICS)
00432 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE)
00433 #elif defined(DEBIAN_SEMANTICS)
00434 # define EVRCMP_DEPCMP EVRCMP_COMPARE
00435 #else
00436 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE
00437 #endif
00438
00439
00440
00441 int
00442 pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
00443 {
00444 Reldep *rd = GETRELDEP(pool, d);
00445 Id name = rd->name;
00446 Id evr = rd->evr;
00447 int flags = rd->flags;
00448
00449 if (flags > 7)
00450 {
00451 switch (flags)
00452 {
00453 case REL_ARCH:
00454 if (s->arch != evr)
00455 return 0;
00456 return pool_match_nevr(pool, s, name);
00457 case REL_OR:
00458 if (pool_match_nevr(pool, s, name))
00459 return 1;
00460 return pool_match_nevr(pool, s, evr);
00461 case REL_AND:
00462 case REL_WITH:
00463 if (!pool_match_nevr(pool, s, name))
00464 return 0;
00465 return pool_match_nevr(pool, s, evr);
00466 default:
00467 return 0;
00468 }
00469 }
00470 if (!pool_match_nevr(pool, s, name))
00471 return 0;
00472 if (evr == s->evr)
00473 return flags & 2 ? 1 : 0;
00474 if (!flags)
00475 return 0;
00476 if (flags == 7)
00477 return 1;
00478 if (flags != 2 && flags != 5)
00479 flags ^= 5;
00480 if ((flags & (1 << (1 + evrcmp(pool, s->evr, evr, EVRCMP_DEPCMP)))) != 0)
00481 return 1;
00482 return 0;
00483 }
00484
00485
00486 static inline int
00487 pool_match_flags_evr(Pool *pool, int pflags, Id pevr, int flags, int evr)
00488 {
00489 if (!pflags || !flags || pflags >= 8 || flags >= 8)
00490 return 0;
00491 if (flags == 7 || pflags == 7)
00492 return 1;
00493 if ((pflags & flags & 5) != 0)
00494 return 1;
00495 if (pevr == evr)
00496 {
00497 if ((pflags & flags & 2) != 0)
00498 return 1;
00499 }
00500 else
00501 {
00502 int f = flags == 5 ? 5 : flags == 2 ? pflags : (flags ^ 5) & (pflags | 5);
00503 if ((f & (1 << (1 + evrcmp(pool, pevr, evr, EVRCMP_DEPCMP)))) != 0)
00504 return 1;
00505 }
00506 return 0;
00507 }
00508
00509
00510
00511 int
00512 pool_match_dep(Pool *pool, Id d1, Id d2)
00513 {
00514 Reldep *rd1, *rd2;
00515
00516 if (d1 == d2)
00517 return 1;
00518 if (!ISRELDEP(d1))
00519 {
00520 if (!ISRELDEP(d2))
00521 return 0;
00522 rd2 = GETRELDEP(pool, d2);
00523 return pool_match_dep(pool, d1, rd2->name);
00524 }
00525 rd1 = GETRELDEP(pool, d1);
00526 if (!ISRELDEP(d2))
00527 {
00528 return pool_match_dep(pool, rd1->name, d2);
00529 }
00530 rd2 = GETRELDEP(pool, d2);
00531
00532 if (!pool_match_dep(pool, rd1->name, rd2->name))
00533 return 0;
00534
00535 return pool_match_flags_evr(pool, rd1->flags, rd1->evr, rd2->flags, rd2->evr);
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 Id
00547 pool_addrelproviders(Pool *pool, Id d)
00548 {
00549 Reldep *rd = GETRELDEP(pool, d);
00550 Reldep *prd;
00551 Queue plist;
00552 Id buf[16];
00553 Id name = rd->name;
00554 Id evr = rd->evr;
00555 int flags = rd->flags;
00556 Id pid, *pidp;
00557 Id p, wp, *pp, *pp2, *pp3;
00558
00559 d = GETRELID(d);
00560 queue_init_buffer(&plist, buf, sizeof(buf)/sizeof(*buf));
00561 switch (flags)
00562 {
00563 case REL_AND:
00564 case REL_WITH:
00565 wp = pool_whatprovides(pool, name);
00566 pp2 = pool_whatprovides_ptr(pool, evr);
00567 pp = pool->whatprovidesdata + wp;
00568 while ((p = *pp++) != 0)
00569 {
00570 for (pp3 = pp2; *pp3;)
00571 if (*pp3++ == p)
00572 {
00573 queue_push(&plist, p);
00574 break;
00575 }
00576 }
00577 break;
00578 case REL_OR:
00579 pp = pool_whatprovides_ptr(pool, name);
00580 while ((p = *pp++) != 0)
00581 queue_push(&plist, p);
00582 pp = pool_whatprovides_ptr(pool, evr);
00583 while ((p = *pp++) != 0)
00584 queue_pushunique(&plist, p);
00585 break;
00586 case REL_NAMESPACE:
00587 if (name == NAMESPACE_OTHERPROVIDERS)
00588 {
00589 wp = pool_whatprovides(pool, evr);
00590 pool->whatprovides_rel[d] = wp;
00591 return wp;
00592 }
00593 if (pool->nscallback)
00594 {
00595
00596
00597
00598
00599
00600 p = pool->nscallback(pool, pool->nscallbackdata, name, evr);
00601 if (p > 1)
00602 {
00603 queue_free(&plist);
00604 pool->whatprovides_rel[d] = p;
00605 return p;
00606 }
00607 if (p == 1)
00608 queue_push(&plist, SYSTEMSOLVABLE);
00609 }
00610 break;
00611 case REL_ARCH:
00612
00613
00614
00615
00616 if (evr == ARCH_SRC)
00617 {
00618 Solvable *s;
00619 for (p = 1, s = pool->solvables + p; p < pool->nsolvables; p++, s++)
00620 {
00621 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
00622 continue;
00623 if (pool_match_nevr(pool, s, name))
00624 queue_push(&plist, p);
00625 }
00626 break;
00627 }
00628 wp = pool_whatprovides(pool, name);
00629 pp = pool->whatprovidesdata + wp;
00630 while ((p = *pp++) != 0)
00631 {
00632 Solvable *s = pool->solvables + p;
00633 if (s->arch == evr)
00634 queue_push(&plist, p);
00635 else
00636 wp = 0;
00637 }
00638 if (wp)
00639 {
00640
00641 queue_free(&plist);
00642 pool->whatprovides_rel[d] = wp;
00643 return wp;
00644 }
00645 break;
00646 case REL_FILECONFLICT:
00647 pp = pool_whatprovides_ptr(pool, name);
00648 while ((p = *pp++) != 0)
00649 {
00650 Id origd = MAKERELDEP(d);
00651 Solvable *s = pool->solvables + p;
00652 if (!s->provides)
00653 continue;
00654 pidp = s->repo->idarraydata + s->provides;
00655 while ((pid = *pidp++) != 0)
00656 if (pid == origd)
00657 break;
00658 if (pid)
00659 queue_push(&plist, p);
00660 }
00661 break;
00662 default:
00663 break;
00664 }
00665
00666
00667 #if 0
00668 POOL_DEBUG(SAT_DEBUG_STATS, "addrelproviders: what provides %s?\n", dep2str(pool, name));
00669 #endif
00670 if (flags && flags < 8)
00671 {
00672 pp = pool_whatprovides_ptr(pool, name);
00673 while (ISRELDEP(name))
00674 {
00675 rd = GETRELDEP(pool, name);
00676 name = rd->name;
00677 }
00678 while ((p = *pp++) != 0)
00679 {
00680 Solvable *s = pool->solvables + p;
00681 #if 0
00682 POOL_DEBUG(DEBUG_1, "addrelproviders: checking package %s\n", id2str(pool, s->name));
00683 #endif
00684 if (!s->provides)
00685 {
00686
00687 if (pool_match_nevr_rel(pool, s, MAKERELDEP(d)))
00688 queue_push(&plist, p);
00689 continue;
00690 }
00691
00692 pidp = s->repo->idarraydata + s->provides;
00693 while ((pid = *pidp++) != 0)
00694 {
00695 if (pid == name)
00696 {
00697 #if defined(MULTI_SEMANTICS)
00698 if (pool->disttype == DISTTYPE_DEB)
00699 continue;
00700 else
00701 break;
00702 #elif defined(DEBIAN_SEMANTICS)
00703 continue;
00704
00705 #else
00706 break;
00707 #endif
00708 }
00709 if (!ISRELDEP(pid))
00710 continue;
00711 prd = GETRELDEP(pool, pid);
00712 if (prd->name != name)
00713 continue;
00714
00715 if (pool_match_flags_evr(pool, prd->flags, prd->evr, flags, evr))
00716 break;
00717 }
00718 if (!pid)
00719 continue;
00720 queue_push(&plist, p);
00721 }
00722
00723 if (plist.count == 0 && !strncmp(id2str(pool, name), "rpmlib(", 7))
00724 queue_push(&plist, SYSTEMSOLVABLE);
00725 }
00726
00727 #if 0
00728 POOL_DEBUG(SAT_DEBUG_STATS, "addrelproviders: adding %d packages to %d\n", plist.count, d);
00729 #endif
00730 pool->whatprovides_rel[d] = pool_queuetowhatprovides(pool, &plist);
00731 queue_free(&plist);
00732
00733 return pool->whatprovides_rel[d];
00734 }
00735
00736
00737
00738 void
00739 pool_debug(Pool *pool, int type, const char *format, ...)
00740 {
00741 va_list args;
00742 char buf[1024];
00743
00744 if ((type & (SAT_FATAL|SAT_ERROR)) == 0)
00745 {
00746 if ((pool->debugmask & type) == 0)
00747 return;
00748 }
00749 va_start(args, format);
00750 if (!pool->debugcallback)
00751 {
00752 if ((type & (SAT_FATAL|SAT_ERROR)) == 0 && !(pool->debugmask & SAT_DEBUG_TO_STDERR))
00753 vprintf(format, args);
00754 else
00755 vfprintf(stderr, format, args);
00756 return;
00757 }
00758 vsnprintf(buf, sizeof(buf), format, args);
00759 pool->debugcallback(pool, pool->debugcallbackdata, type, buf);
00760 }
00761
00762 void
00763 pool_setdebuglevel(Pool *pool, int level)
00764 {
00765 int mask = SAT_DEBUG_RESULT;
00766 if (level > 0)
00767 mask |= SAT_DEBUG_STATS|SAT_DEBUG_ANALYZE|SAT_DEBUG_UNSOLVABLE|SAT_DEBUG_SOLVER|SAT_DEBUG_TRANSACTION;
00768 if (level > 1)
00769 mask |= SAT_DEBUG_JOB|SAT_DEBUG_SOLUTIONS|SAT_DEBUG_POLICY;
00770 if (level > 2)
00771 mask |= SAT_DEBUG_PROPAGATE;
00772 if (level > 3)
00773 mask |= SAT_DEBUG_RULE_CREATION;
00774 if (level > 4)
00775 mask |= SAT_DEBUG_SCHUBI;
00776 mask |= pool->debugmask & SAT_DEBUG_TO_STDERR;
00777 pool->debugmask = mask;
00778 }
00779
00780
00781
00782 struct searchfiles {
00783 Id *ids;
00784 char **dirs;
00785 char **names;
00786 int nfiles;
00787 Map seen;
00788 };
00789
00790 #define SEARCHFILES_BLOCK 127
00791
00792 static void
00793 pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf)
00794 {
00795 Id dep, sid;
00796 const char *s, *sr;
00797 struct searchfiles *csf;
00798
00799 while ((dep = *ida++) != 0)
00800 {
00801 csf = sf;
00802 while (ISRELDEP(dep))
00803 {
00804 Reldep *rd;
00805 sid = pool->ss.nstrings + GETRELID(dep);
00806 if (MAPTST(&csf->seen, sid))
00807 {
00808 dep = 0;
00809 break;
00810 }
00811 MAPSET(&csf->seen, sid);
00812 rd = GETRELDEP(pool, dep);
00813 if (rd->flags < 8)
00814 dep = rd->name;
00815 else if (rd->flags == REL_NAMESPACE)
00816 {
00817 if (rd->name == NAMESPACE_INSTALLED || rd->name == NAMESPACE_SPLITPROVIDES)
00818 {
00819 csf = isf;
00820 if (!csf || MAPTST(&csf->seen, sid))
00821 {
00822 dep = 0;
00823 break;
00824 }
00825 MAPSET(&csf->seen, sid);
00826 }
00827 dep = rd->evr;
00828 }
00829 else if (rd->flags == REL_FILECONFLICT)
00830 {
00831 dep = 0;
00832 break;
00833 }
00834 else
00835 {
00836 Id ids[2];
00837 ids[0] = rd->name;
00838 ids[1] = 0;
00839 pool_addfileprovides_dep(pool, ids, csf, isf);
00840 dep = rd->evr;
00841 }
00842 }
00843 if (!dep)
00844 continue;
00845 if (MAPTST(&csf->seen, dep))
00846 continue;
00847 MAPSET(&csf->seen, dep);
00848 s = id2str(pool, dep);
00849 if (*s != '/')
00850 continue;
00851 csf->ids = sat_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
00852 csf->dirs = sat_extend(csf->dirs, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
00853 csf->names = sat_extend(csf->names, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
00854 csf->ids[csf->nfiles] = dep;
00855 sr = strrchr(s, '/');
00856 csf->names[csf->nfiles] = strdup(sr + 1);
00857 csf->dirs[csf->nfiles] = sat_malloc(sr - s + 1);
00858 if (sr != s)
00859 strncpy(csf->dirs[csf->nfiles], s, sr - s);
00860 csf->dirs[csf->nfiles][sr - s] = 0;
00861 csf->nfiles++;
00862 }
00863 }
00864
00865 struct addfileprovides_cbdata {
00866 int nfiles;
00867 Id *ids;
00868 char **dirs;
00869 char **names;
00870
00871 Id *dids;
00872
00873 Map providedids;
00874
00875 Map useddirs;
00876 };
00877
00878 static int
00879 addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value)
00880 {
00881 struct addfileprovides_cbdata *cbd = cbdata;
00882 int i;
00883
00884 if (!cbd->useddirs.size)
00885 {
00886 map_init(&cbd->useddirs, data->dirpool.ndirs + 1);
00887 for (i = 0; i < cbd->nfiles; i++)
00888 {
00889 Id did;
00890 if (MAPTST(&cbd->providedids, cbd->ids[i]))
00891 {
00892 cbd->dids[i] = 0;
00893 continue;
00894 }
00895 did = repodata_str2dir(data, cbd->dirs[i], 0);
00896 cbd->dids[i] = did;
00897 if (did)
00898 MAPSET(&cbd->useddirs, did);
00899 }
00900 }
00901 if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id))
00902 return 0;
00903 for (i = 0; i < cbd->nfiles; i++)
00904 {
00905 if (cbd->dids[i] != value->id)
00906 continue;
00907 if (!strcmp(cbd->names[i], value->str))
00908 break;
00909 }
00910 if (i == cbd->nfiles)
00911 return 0;
00912 s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER);
00913 return 0;
00914 }
00915
00916 static void
00917 pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly)
00918 {
00919 Id p;
00920 Repodata *data;
00921 Repo *repo;
00922 Queue fileprovidesq;
00923 int i, j, repoid, repodataid;
00924 int provstart, provend;
00925 Map donemap;
00926 int ndone, incomplete;
00927
00928 if (!pool->nrepos)
00929 return;
00930
00931 cbd->nfiles = sf->nfiles;
00932 cbd->ids = sf->ids;
00933 cbd->dirs = sf->dirs;
00934 cbd->names = sf->names;
00935 cbd->dids = sat_realloc2(cbd->dids, sf->nfiles, sizeof(Id));
00936 map_init(&cbd->providedids, pool->ss.nstrings);
00937
00938 repoid = 0;
00939 repo = repoonly ? repoonly : pool->repos[0];
00940 map_init(&donemap, pool->nsolvables);
00941 queue_init(&fileprovidesq);
00942 provstart = provend = 0;
00943 for (;;)
00944 {
00945 if (repo->disabled)
00946 {
00947 if (repoonly || ++repoid == pool->nrepos)
00948 break;
00949 repo = pool->repos[repoid];
00950 continue;
00951 }
00952 ndone = 0;
00953 for (data = repo->repodata, repodataid = 0; repodataid < repo->nrepodata; repodataid++, data++)
00954 {
00955 if (ndone >= repo->nsolvables)
00956 break;
00957
00958 if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq))
00959 {
00960 map_empty(&cbd->providedids);
00961 for (i = 0; i < fileprovidesq.count; i++)
00962 MAPSET(&cbd->providedids, fileprovidesq.elements[i]);
00963 provstart = data->start;
00964 provend = data->end;
00965 for (i = 0; i < cbd->nfiles; i++)
00966 if (!MAPTST(&cbd->providedids, cbd->ids[i]))
00967 break;
00968 if (i == cbd->nfiles)
00969 {
00970
00971 for (p = data->start; p < data->end; p++)
00972 if (pool->solvables[p].repo == repo)
00973 {
00974 if (MAPTST(&donemap, p))
00975 continue;
00976 MAPSET(&donemap, p);
00977 ndone++;
00978 }
00979 continue;
00980 }
00981 }
00982
00983 if (!repodata_has_keyname(data, SOLVABLE_FILELIST))
00984 continue;
00985
00986 if (data->start < provstart || data->end > provend)
00987 {
00988 map_empty(&cbd->providedids);
00989 provstart = provend = 0;
00990 }
00991
00992
00993 incomplete = 0;
00994 if (data->state == REPODATA_AVAILABLE)
00995 {
00996 for (j = 1; j < data->nkeys; j++)
00997 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
00998 break;
00999 if (j < data->nkeys)
01000 {
01001 #if 0
01002 for (i = 0; i < cbd->nfiles; i++)
01003 if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, id2str(pool, cbd->ids[i])))
01004 printf("need complete filelist because of %s\n", id2str(pool, cbd->ids[i]));
01005 #endif
01006 for (i = 0; i < cbd->nfiles; i++)
01007 if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, id2str(pool, cbd->ids[i])))
01008 break;
01009 if (i < cbd->nfiles)
01010 incomplete = 1;
01011 }
01012 }
01013
01014
01015 map_init(&cbd->useddirs, 0);
01016 for (p = data->start; p < data->end; p++)
01017 if (pool->solvables[p].repo == repo)
01018 {
01019 if (MAPTST(&donemap, p))
01020 continue;
01021 repodata_search(data, p, SOLVABLE_FILELIST, 0, addfileprovides_cb, cbd);
01022 if (!incomplete)
01023 {
01024 MAPSET(&donemap, p);
01025 ndone++;
01026 }
01027 }
01028 map_free(&cbd->useddirs);
01029 }
01030
01031 if (repoonly || ++repoid == pool->nrepos)
01032 break;
01033 repo = pool->repos[repoid];
01034 }
01035 map_free(&donemap);
01036 queue_free(&fileprovidesq);
01037 map_free(&cbd->providedids);
01038 }
01039
01040 void
01041 pool_addfileprovides_ids(Pool *pool, Repo *installed, Id **idp)
01042 {
01043 Solvable *s;
01044 Repo *repo;
01045 struct searchfiles sf, isf, *isfp;
01046 struct addfileprovides_cbdata cbd;
01047 int i;
01048 unsigned int now;
01049
01050 now = sat_timems(0);
01051 memset(&sf, 0, sizeof(sf));
01052 map_init(&sf.seen, pool->ss.nstrings + pool->nrels);
01053 memset(&isf, 0, sizeof(isf));
01054 map_init(&isf.seen, pool->ss.nstrings + pool->nrels);
01055
01056 isfp = installed ? &isf : 0;
01057 for (i = 1, s = pool->solvables + i; i < pool->nsolvables; i++, s++)
01058 {
01059 repo = s->repo;
01060 if (!repo)
01061 continue;
01062 if (s->obsoletes)
01063 pool_addfileprovides_dep(pool, repo->idarraydata + s->obsoletes, &sf, isfp);
01064 if (s->conflicts)
01065 pool_addfileprovides_dep(pool, repo->idarraydata + s->conflicts, &sf, isfp);
01066 if (s->requires)
01067 pool_addfileprovides_dep(pool, repo->idarraydata + s->requires, &sf, isfp);
01068 if (s->recommends)
01069 pool_addfileprovides_dep(pool, repo->idarraydata + s->recommends, &sf, isfp);
01070 if (s->suggests)
01071 pool_addfileprovides_dep(pool, repo->idarraydata + s->suggests, &sf, isfp);
01072 if (s->supplements)
01073 pool_addfileprovides_dep(pool, repo->idarraydata + s->supplements, &sf, isfp);
01074 if (s->enhances)
01075 pool_addfileprovides_dep(pool, repo->idarraydata + s->enhances, &sf, isfp);
01076 }
01077 map_free(&sf.seen);
01078 map_free(&isf.seen);
01079 POOL_DEBUG(SAT_DEBUG_STATS, "found %d file dependencies, %d installed file dependencies\n", sf.nfiles, isf.nfiles);
01080 cbd.dids = 0;
01081 if (idp)
01082 *idp = 0;
01083 if (sf.nfiles)
01084 {
01085 #if 0
01086 for (i = 0; i < sf.nfiles; i++)
01087 POOL_DEBUG(SAT_DEBUG_STATS, "looking up %s in filelist\n", id2str(pool, sf.ids[i]));
01088 #endif
01089 pool_addfileprovides_search(pool, &cbd, &sf, 0);
01090 if (idp)
01091 {
01092 sf.ids = sat_extend(sf.ids, sf.nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
01093 sf.ids[sf.nfiles] = 0;
01094 *idp = sf.ids;
01095 sf.ids = 0;
01096 }
01097 sat_free(sf.ids);
01098 for (i = 0; i < sf.nfiles; i++)
01099 {
01100 sat_free(sf.dirs[i]);
01101 sat_free(sf.names[i]);
01102 }
01103 sat_free(sf.dirs);
01104 sat_free(sf.names);
01105 }
01106 if (isf.nfiles)
01107 {
01108 #if 0
01109 for (i = 0; i < isf.nfiles; i++)
01110 POOL_DEBUG(SAT_DEBUG_STATS, "looking up %s in installed filelist\n", id2str(pool, isf.ids[i]));
01111 #endif
01112 if (installed)
01113 pool_addfileprovides_search(pool, &cbd, &isf, installed);
01114 sat_free(isf.ids);
01115 for (i = 0; i < isf.nfiles; i++)
01116 {
01117 sat_free(isf.dirs[i]);
01118 sat_free(isf.names[i]);
01119 }
01120 sat_free(isf.dirs);
01121 sat_free(isf.names);
01122 }
01123 sat_free(cbd.dids);
01124 pool_freewhatprovides(pool);
01125 POOL_DEBUG(SAT_DEBUG_STATS, "addfileprovides took %d ms\n", sat_timems(now));
01126 }
01127
01128 void
01129 pool_addfileprovides(Pool *pool)
01130 {
01131 pool_addfileprovides_ids(pool, pool->installed, 0);
01132 }
01133
01134 void
01135 pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*callback)(void *cbdata, Solvable *s, struct _Repodata *data, struct _Repokey *key, struct _KeyValue *kv), void *cbdata)
01136 {
01137 if (p)
01138 {
01139 if (pool->solvables[p].repo)
01140 repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata);
01141 return;
01142 }
01143
01144 for (p = 1; p < pool->nsolvables; p++)
01145 if (pool->solvables[p].repo)
01146 repo_search(pool->solvables[p].repo, p, key, match, flags, callback, cbdata);
01147 }
01148
01149 void
01150 pool_clear_pos(Pool *pool)
01151 {
01152 memset(&pool->pos, 0, sizeof(pool->pos));
01153 }
01154
01155
01156 void
01157 pool_set_languages(Pool *pool, const char **languages, int nlanguages)
01158 {
01159 int i;
01160
01161 pool->languagecache = sat_free(pool->languagecache);
01162 pool->languagecacheother = 0;
01163 if (pool->nlanguages)
01164 {
01165 for (i = 0; i < pool->nlanguages; i++)
01166 free((char *)pool->languages[i]);
01167 free(pool->languages);
01168 }
01169 pool->nlanguages = nlanguages;
01170 if (!nlanguages)
01171 return;
01172 pool->languages = sat_calloc(nlanguages, sizeof(const char **));
01173 for (i = 0; i < pool->nlanguages; i++)
01174 pool->languages[i] = strdup(languages[i]);
01175 }
01176
01177 Id
01178 pool_id2langid(Pool *pool, Id id, const char *lang, int create)
01179 {
01180 const char *n;
01181 char buf[256], *p;
01182 int l;
01183
01184 if (!lang)
01185 return id;
01186 n = id2str(pool, id);
01187 l = strlen(n) + strlen(lang) + 2;
01188 if (l > sizeof(buf))
01189 p = sat_malloc(strlen(n) + strlen(lang) + 2);
01190 else
01191 p = buf;
01192 sprintf(p, "%s:%s", n, lang);
01193 id = str2id(pool, p, create);
01194 if (p != buf)
01195 free(p);
01196 return id;
01197 }
01198
01199 char *
01200 pool_alloctmpspace(Pool *pool, int len)
01201 {
01202 int n = pool->tmpspacen;
01203 if (!len)
01204 return 0;
01205 if (len > pool->tmpspacelen[n])
01206 {
01207 pool->tmpspacebuf[n] = sat_realloc(pool->tmpspacebuf[n], len + 32);
01208 pool->tmpspacelen[n] = len + 32;
01209 }
01210 pool->tmpspacen = (n + 1) % POOL_TMPSPACEBUF;
01211 return pool->tmpspacebuf[n];
01212 }
01213
01214 char *
01215 pool_tmpjoin(Pool *pool, const char *str1, const char *str2, const char *str3)
01216 {
01217 int l1, l2, l3;
01218 char *s, *str;
01219 l1 = str1 ? strlen(str1) : 0;
01220 l2 = str2 ? strlen(str2) : 0;
01221 l3 = str3 ? strlen(str3) : 0;
01222 s = str = pool_alloctmpspace(pool, l1 + l2 + l3 + 1);
01223 if (l1)
01224 {
01225 strcpy(s, str1);
01226 s += l1;
01227 }
01228 if (l2)
01229 {
01230 strcpy(s, str2);
01231 s += l2;
01232 }
01233 if (l3)
01234 {
01235 strcpy(s, str3);
01236 s += l3;
01237 }
01238 *s = 0;
01239 return str;
01240 }
01241
01242
01243
01244
01245 struct mptree {
01246 Id sibling;
01247 Id child;
01248 const char *comp;
01249 int compl;
01250 Id mountpoint;
01251 };
01252
01253 struct ducbdata {
01254 DUChanges *mps;
01255 struct mptree *mptree;
01256 int addsub;
01257 int hasdu;
01258
01259 Id *dirmap;
01260 int nmap;
01261 Repodata *olddata;
01262 };
01263
01264
01265 static int
01266 solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value)
01267 {
01268 struct ducbdata *cbd = cbdata;
01269 Id mp;
01270
01271 if (data != cbd->olddata)
01272 {
01273 Id dn, mp, comp, *dirmap, *dirs;
01274 int i, compl;
01275 const char *compstr;
01276 struct mptree *mptree;
01277
01278
01279 cbd->dirmap = sat_free(cbd->dirmap);
01280 cbd->nmap = 0;
01281 dirmap = sat_calloc(data->dirpool.ndirs, sizeof(Id));
01282 mptree = cbd->mptree;
01283 mp = 0;
01284 for (dn = 2, dirs = data->dirpool.dirs + dn; dn < data->dirpool.ndirs; dn++)
01285 {
01286 comp = *dirs++;
01287 if (comp <= 0)
01288 {
01289 mp = dirmap[-comp];
01290 continue;
01291 }
01292 if (mp < 0)
01293 {
01294
01295 dirmap[dn] = mp;
01296 continue;
01297 }
01298 if (!mptree[mp].child)
01299 {
01300 dirmap[dn] = -mp;
01301 continue;
01302 }
01303 if (data->localpool)
01304 compstr = stringpool_id2str(&data->spool, comp);
01305 else
01306 compstr = id2str(data->repo->pool, comp);
01307 compl = strlen(compstr);
01308 for (i = mptree[mp].child; i; i = mptree[i].sibling)
01309 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl))
01310 break;
01311 dirmap[dn] = i ? i : -mp;
01312 }
01313
01314 for (dn = 0; dn < data->dirpool.ndirs; dn++)
01315 {
01316 mp = dirmap[dn];
01317 dirmap[dn] = mptree[mp > 0 ? mp : -mp].mountpoint;
01318 }
01319 cbd->dirmap = dirmap;
01320 cbd->nmap = data->dirpool.ndirs;
01321 cbd->olddata = data;
01322 }
01323 cbd->hasdu = 1;
01324 if (value->id < 0 || value->id >= cbd->nmap)
01325 return 0;
01326 mp = cbd->dirmap[value->id];
01327 if (mp < 0)
01328 return 0;
01329 if (cbd->addsub > 0)
01330 {
01331 cbd->mps[mp].kbytes += value->num;
01332 cbd->mps[mp].files += value->num2;
01333 }
01334 else
01335 {
01336 cbd->mps[mp].kbytes -= value->num;
01337 cbd->mps[mp].files -= value->num2;
01338 }
01339 return 0;
01340 }
01341
01342 static void
01343 propagate_mountpoints(struct mptree *mptree, int pos, Id mountpoint)
01344 {
01345 int i;
01346 if (mptree[pos].mountpoint == -1)
01347 mptree[pos].mountpoint = mountpoint;
01348 else
01349 mountpoint = mptree[pos].mountpoint;
01350 for (i = mptree[pos].child; i; i = mptree[i].sibling)
01351 propagate_mountpoints(mptree, i, mountpoint);
01352 }
01353
01354 #define MPTREE_BLOCK 15
01355
01356 void
01357 pool_calc_duchanges(Pool *pool, Map *installedmap, DUChanges *mps, int nmps)
01358 {
01359 char *p;
01360 const char *path, *compstr;
01361 struct mptree *mptree;
01362 int i, nmptree;
01363 int pos, compl;
01364 int mp;
01365 struct ducbdata cbd;
01366 Solvable *s;
01367 Id sp;
01368 Map ignoredu;
01369 Repo *oldinstalled = pool->installed;
01370
01371 memset(&ignoredu, 0, sizeof(ignoredu));
01372 cbd.mps = mps;
01373 cbd.addsub = 0;
01374 cbd.dirmap = 0;
01375 cbd.nmap = 0;
01376 cbd.olddata = 0;
01377
01378 mptree = sat_extend_resize(0, 1, sizeof(struct mptree), MPTREE_BLOCK);
01379
01380
01381 mptree[0].sibling = 0;
01382 mptree[0].child = 0;
01383 mptree[0].comp = 0;
01384 mptree[0].compl = 0;
01385 mptree[0].mountpoint = -1;
01386 nmptree = 1;
01387
01388
01389 for (mp = 0; mp < nmps; mp++)
01390 {
01391 mps[mp].kbytes = 0;
01392 mps[mp].files = 0;
01393 pos = 0;
01394 path = mps[mp].path;
01395 while(*path == '/')
01396 path++;
01397 while (*path)
01398 {
01399 if ((p = strchr(path, '/')) == 0)
01400 {
01401 compstr = path;
01402 compl = strlen(compstr);
01403 path += compl;
01404 }
01405 else
01406 {
01407 compstr = path;
01408 compl = p - path;
01409 path = p + 1;
01410 while(*path == '/')
01411 path++;
01412 }
01413 for (i = mptree[pos].child; i; i = mptree[i].sibling)
01414 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl))
01415 break;
01416 if (!i)
01417 {
01418
01419 mptree = sat_extend(mptree, nmptree, 1, sizeof(struct mptree), MPTREE_BLOCK);
01420 i = nmptree++;
01421 mptree[i].sibling = mptree[pos].child;
01422 mptree[i].child = 0;
01423 mptree[i].comp = compstr;
01424 mptree[i].compl = compl;
01425 mptree[i].mountpoint = -1;
01426 mptree[pos].child = i;
01427 }
01428 pos = i;
01429 }
01430 mptree[pos].mountpoint = mp;
01431 }
01432
01433 propagate_mountpoints(mptree, 0, mptree[0].mountpoint);
01434
01435 #if 0
01436 for (i = 0; i < nmptree; i++)
01437 {
01438 printf("#%d sibling: %d\n", i, mptree[i].sibling);
01439 printf("#%d child: %d\n", i, mptree[i].child);
01440 printf("#%d comp: %s\n", i, mptree[i].comp);
01441 printf("#%d compl: %d\n", i, mptree[i].compl);
01442 printf("#%d mountpont: %d\n", i, mptree[i].mountpoint);
01443 }
01444 #endif
01445
01446 cbd.mptree = mptree;
01447 cbd.addsub = 1;
01448 for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++)
01449 {
01450 if (!s->repo || (oldinstalled && s->repo == oldinstalled))
01451 continue;
01452 if (!MAPTST(installedmap, sp))
01453 continue;
01454 cbd.hasdu = 0;
01455 repo_search(s->repo, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
01456 if (!cbd.hasdu && oldinstalled)
01457 {
01458 Id op, opp;
01459
01460 if (!ignoredu.map)
01461 map_init(&ignoredu, oldinstalled->end - oldinstalled->start);
01462 if (s->obsoletes)
01463 {
01464 Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
01465 while ((obs = *obsp++) != 0)
01466 FOR_PROVIDES(op, opp, obs)
01467 if (op >= oldinstalled->start && op < oldinstalled->end)
01468 MAPSET(&ignoredu, op - oldinstalled->start);
01469 }
01470 FOR_PROVIDES(op, opp, s->name)
01471 if (pool->solvables[op].name == s->name)
01472 if (op >= oldinstalled->start && op < oldinstalled->end)
01473 MAPSET(&ignoredu, op - oldinstalled->start);
01474 }
01475 }
01476 cbd.addsub = -1;
01477 if (oldinstalled)
01478 {
01479
01480 FOR_REPO_SOLVABLES(oldinstalled, sp, s)
01481 {
01482 if (MAPTST(installedmap, sp))
01483 continue;
01484 if (ignoredu.map && MAPTST(&ignoredu, sp - oldinstalled->start))
01485 continue;
01486 repo_search(oldinstalled, sp, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
01487 }
01488 }
01489 if (ignoredu.map)
01490 map_free(&ignoredu);
01491 sat_free(cbd.dirmap);
01492 sat_free(mptree);
01493 }
01494
01495 int
01496 pool_calc_installsizechange(Pool *pool, Map *installedmap)
01497 {
01498 Id sp;
01499 Solvable *s;
01500 int change = 0;
01501 Repo *oldinstalled = pool->installed;
01502
01503 for (sp = 1, s = pool->solvables + sp; sp < pool->nsolvables; sp++, s++)
01504 {
01505 if (!s->repo || (oldinstalled && s->repo == oldinstalled))
01506 continue;
01507 if (!MAPTST(installedmap, sp))
01508 continue;
01509 change += solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
01510 }
01511 if (oldinstalled)
01512 {
01513 FOR_REPO_SOLVABLES(oldinstalled, sp, s)
01514 {
01515 if (MAPTST(installedmap, sp))
01516 continue;
01517 change -= solvable_lookup_num(s, SOLVABLE_INSTALLSIZE, 0);
01518 }
01519 }
01520 return change;
01521 }
01522
01523
01524
01525
01526
01527
01528
01529
01530 static inline Id dep2name(Pool *pool, Id dep)
01531 {
01532 while (ISRELDEP(dep))
01533 {
01534 Reldep *rd = rd = GETRELDEP(pool, dep);
01535 dep = rd->name;
01536 }
01537 return dep;
01538 }
01539
01540 static int providedbyinstalled_multiversion(Pool *pool, unsigned char *map, Id n, Id con)
01541 {
01542 Id p, pp;
01543 Solvable *sn = pool->solvables + n;
01544
01545 FOR_PROVIDES(p, pp, sn->name)
01546 {
01547 Solvable *s = pool->solvables + p;
01548 if (s->name != sn->name || s->arch != sn->arch)
01549 continue;
01550 if ((map[p] & 9) != 9)
01551 continue;
01552 if (pool_match_nevr(pool, pool->solvables + p, con))
01553 continue;
01554 return 1;
01555 }
01556 return 0;
01557 }
01558
01559 static inline int providedbyinstalled(Pool *pool, unsigned char *map, Id dep, int ispatch, Map *noobsoletesmap)
01560 {
01561 Id p, pp;
01562 int r = 0;
01563 FOR_PROVIDES(p, pp, dep)
01564 {
01565 if (p == SYSTEMSOLVABLE)
01566 return 1;
01567 if (ispatch && !pool_match_nevr(pool, pool->solvables + p, dep))
01568 continue;
01569 if (ispatch && noobsoletesmap && noobsoletesmap->size && MAPTST(noobsoletesmap, p) && ISRELDEP(dep))
01570 if (providedbyinstalled_multiversion(pool, map, p, dep))
01571 continue;
01572 if ((map[p] & 9) == 9)
01573 return 9;
01574 r |= map[p] & 17;
01575 }
01576 return r;
01577 }
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590 void
01591 pool_trivial_installable_noobsoletesmap(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res, Map *noobsoletesmap)
01592 {
01593 int i, r, m, did;
01594 Id p, *dp, con, *conp, req, *reqp;
01595 unsigned char *map;
01596 Solvable *s;
01597
01598 map = sat_calloc(pool->nsolvables, 1);
01599 for (p = 1; p < pool->nsolvables; p++)
01600 {
01601 if (!MAPTST(installedmap, p))
01602 continue;
01603 map[p] |= 9;
01604 s = pool->solvables + p;
01605 if (!s->conflicts)
01606 continue;
01607 conp = s->repo->idarraydata + s->conflicts;
01608 while ((con = *conp++) != 0)
01609 {
01610 dp = pool_whatprovides_ptr(pool, con);
01611 for (; *dp; dp++)
01612 map[p] |= 2;
01613 }
01614 }
01615 for (i = 0; i < pkgs->count; i++)
01616 map[pkgs->elements[i]] = 16;
01617
01618 for (i = 0, did = 0; did < pkgs->count; i++, did++)
01619 {
01620 if (i == pkgs->count)
01621 i = 0;
01622 p = pkgs->elements[i];
01623 if ((map[p] & 16) == 0)
01624 continue;
01625 if ((map[p] & 2) != 0)
01626 {
01627 map[p] = 2;
01628 continue;
01629 }
01630 s = pool->solvables + p;
01631 m = 1;
01632 if (s->requires)
01633 {
01634 reqp = s->repo->idarraydata + s->requires;
01635 while ((req = *reqp++) != 0)
01636 {
01637 if (req == SOLVABLE_PREREQMARKER)
01638 continue;
01639 r = providedbyinstalled(pool, map, req, 0, 0);
01640 if (!r)
01641 {
01642
01643 map[p] = 2;
01644 break;
01645 }
01646 m |= r;
01647 }
01648 if (req)
01649 continue;
01650 if ((m & 9) == 9)
01651 m = 9;
01652 }
01653 if (s->conflicts)
01654 {
01655 int ispatch = 0;
01656
01657 if (!strncmp("patch:", id2str(pool, s->name), 6))
01658 ispatch = 1;
01659 conp = s->repo->idarraydata + s->conflicts;
01660 while ((con = *conp++) != 0)
01661 {
01662 if ((providedbyinstalled(pool, map, con, ispatch, noobsoletesmap) & 1) != 0)
01663 {
01664 map[p] = 2;
01665 break;
01666 }
01667 if ((m == 1 || m == 17) && ISRELDEP(con))
01668 {
01669 con = dep2name(pool, con);
01670 if ((providedbyinstalled(pool, map, con, ispatch, noobsoletesmap) & 1) != 0)
01671 m = 9;
01672 }
01673 }
01674 if (con)
01675 continue;
01676 }
01677 #if 0
01678 if (s->repo && s->repo != oldinstalled)
01679 {
01680 Id p2, obs, *obsp, *pp;
01681 Solvable *s2;
01682 if (s->obsoletes)
01683 {
01684 obsp = s->repo->idarraydata + s->obsoletes;
01685 while ((obs = *obsp++) != 0)
01686 {
01687 if ((providedbyinstalled(pool, map, obs, 0, 0) & 1) != 0)
01688 {
01689 map[p] = 2;
01690 break;
01691 }
01692 }
01693 if (obs)
01694 continue;
01695 }
01696 FOR_PROVIDES(p2, pp, s->name)
01697 {
01698 s2 = pool->solvables + p2;
01699 if (s2->name == s->name && (map[p2] & 1) != 0)
01700 {
01701 map[p] = 2;
01702 break;
01703 }
01704 }
01705 if (p2)
01706 continue;
01707 }
01708 #endif
01709 if (m != map[p])
01710 {
01711 map[p] = m;
01712 did = 0;
01713 }
01714 }
01715 queue_free(res);
01716 queue_init_clone(res, pkgs);
01717 for (i = 0; i < pkgs->count; i++)
01718 {
01719 m = map[pkgs->elements[i]];
01720 if ((m & 9) == 9)
01721 r = 1;
01722 else if (m & 1)
01723 r = -1;
01724 else
01725 r = 0;
01726 res->elements[i] = r;
01727 }
01728 free(map);
01729 }
01730
01731 void
01732 pool_trivial_installable(Pool *pool, Map *installedmap, Queue *pkgs, Queue *res)
01733 {
01734 pool_trivial_installable_noobsoletesmap(pool, installedmap, pkgs, res, 0);
01735 }
01736
01737 const char *
01738 pool_lookup_str(Pool *pool, Id entry, Id keyname)
01739 {
01740 if (entry == SOLVID_POS && pool->pos.repo)
01741 return repodata_lookup_str(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname);
01742 if (entry <= 0)
01743 return 0;
01744 return solvable_lookup_str(pool->solvables + entry, keyname);
01745 }
01746
01747 Id
01748 pool_lookup_id(Pool *pool, Id entry, Id keyname)
01749 {
01750 if (entry == SOLVID_POS && pool->pos.repo)
01751 {
01752 Repodata *data = pool->pos.repo->repodata + pool->pos.repodataid;
01753 Id id = repodata_lookup_id(data, SOLVID_POS, keyname);
01754 return data->localpool ? repodata_globalize_id(data, id, 1) : id;
01755 }
01756 if (entry <= 0)
01757 return 0;
01758 return solvable_lookup_id(pool->solvables + entry, keyname);
01759 }
01760
01761 unsigned int
01762 pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned int notfound)
01763 {
01764 if (entry == SOLVID_POS && pool->pos.repo)
01765 {
01766 unsigned int value;
01767 if (repodata_lookup_num(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, &value))
01768 return value;
01769 return notfound;
01770 }
01771 if (entry <= 0)
01772 return notfound;
01773 return solvable_lookup_num(pool->solvables + entry, keyname, notfound);
01774 }
01775
01776 int
01777 pool_lookup_void(Pool *pool, Id entry, Id keyname)
01778 {
01779 if (entry == SOLVID_POS && pool->pos.repo)
01780 return repodata_lookup_void(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname);
01781 if (entry <= 0)
01782 return 0;
01783 return solvable_lookup_void(pool->solvables + entry, keyname);
01784 }
01785
01786 const unsigned char *
01787 pool_lookup_bin_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
01788 {
01789 if (entry == SOLVID_POS && pool->pos.repo)
01790 return repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, typep);
01791 if (entry <= 0)
01792 return 0;
01793 return solvable_lookup_bin_checksum(pool->solvables + entry, keyname, typep);
01794 }
01795
01796 const char *
01797 pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
01798 {
01799 if (entry == SOLVID_POS && pool->pos.repo)
01800 {
01801 const unsigned char *chk = repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, typep);
01802 return chk ? repodata_chk2str(pool->pos.repo->repodata + pool->pos.repodataid, *typep, chk) : 0;
01803 }
01804 if (entry <= 0)
01805 return 0;
01806 return solvable_lookup_checksum(pool->solvables + entry, keyname, typep);
01807 }
01808
01809 void
01810 pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts)
01811 {
01812 int hadhashes = pool->relhashtbl ? 1 : 0;
01813 Solvable *s;
01814 Id fn, p, q, md5;
01815 Id id;
01816 int i;
01817
01818 if (!conflicts->count)
01819 return;
01820 pool_freewhatprovides(pool);
01821 for (i = 0; i < conflicts->count; i += 5)
01822 {
01823 fn = conflicts->elements[i];
01824 p = conflicts->elements[i + 1];
01825 md5 = conflicts->elements[i + 2];
01826 q = conflicts->elements[i + 3];
01827 id = rel2id(pool, fn, md5, REL_FILECONFLICT, 1);
01828 s = pool->solvables + p;
01829 if (!s->repo)
01830 continue;
01831 s->provides = repo_addid_dep(s->repo, s->provides, id, SOLVABLE_FILEMARKER);
01832 s = pool->solvables + q;
01833 if (!s->repo)
01834 continue;
01835 s->conflicts = repo_addid_dep(s->repo, s->conflicts, id, 0);
01836 }
01837 if (!hadhashes)
01838 pool_freeidhashes(pool);
01839 }
01840
01841