10 #include <rpm/rpmfi.h>
12 #include "lib/rpmal.h"
13 #include "lib/rpmhash.h"
17 typedef struct availablePackage_s * availablePackage;
24 * Info about a single package to be installed.
26 struct availablePackage_s {
27 rpmte p; /*!< transaction member */
28 rpmds provides; /*!< Provides: dependencies. */
29 rpmfi fi; /*!< File info set. */
30 fnpyKey key; /*!< Associated file name/python object */
33 typedef struct availableIndexEntry_s * availableIndexEntry;
36 * A single available item (e.g. a Provides: dependency).
38 struct availableIndexEntry_s {
39 rpmalNum pkgNum; /*!< Containing package index. */
40 unsigned int entryIx; /*!< Dependency index. */
43 struct fileNameEntry_s {
45 const char * baseName;
50 * A file to be installed/removed.
52 typedef struct fileIndexEntry_s * fileIndex;
54 struct fileIndexEntry_s {
55 rpmalNum pkgNum; /*!< Containing package index. */
62 #define HASHTYPE rpmalProvidesHash
63 #define HTKEYTYPE const char *
64 #define HTDATATYPE struct availableIndexEntry_s
65 #include "lib/rpmhash.H"
66 #include "lib/rpmhash.C"
71 #define HASHTYPE rpmalFileHash
72 #define HTKEYTYPE struct fileNameEntry_s
73 #define HTDATATYPE struct fileIndexEntry_s
74 #include "lib/rpmhash.H"
75 #include "lib/rpmhash.C"
80 * Set of available packages, items, and directories.
83 availablePackage list; /*!< Set of packages. */
84 rpmalProvidesHash providesHash;
85 rpmalFileHash fileHash;
86 int delta; /*!< Delta for pkg list reallocation. */
87 int size; /*!< No. of pkgs in list. */
88 int alloced; /*!< No. of pkgs allocated for list. */
89 rpm_color_t tscolor; /*!< Transaction color. */
90 rpm_color_t prefcolor; /*!< Transaction preferred color. */
94 * Destroy available item index.
95 * @param al available list
97 static void rpmalFreeIndex(rpmal al)
99 al->providesHash = rpmalProvidesHashFree(al->providesHash);
100 al->fileHash = rpmalFileHashFree(al->fileHash);
103 rpmal rpmalCreate(int delta, rpm_color_t tscolor, rpm_color_t prefcolor)
105 rpmal al = xcalloc(1, sizeof(*al));
109 al->alloced = al->delta;
110 al->list = xmalloc(sizeof(*al->list) * al->alloced);;
112 al->providesHash = NULL;
114 al->tscolor = tscolor;
115 al->prefcolor = prefcolor;
120 rpmal rpmalFree(rpmal al)
122 availablePackage alp;
128 if ((alp = al->list) != NULL)
129 for (i = 0; i < al->size; i++, alp++) {
130 alp->provides = rpmdsFree(alp->provides);
131 alp->fi = rpmfiFree(alp->fi);
133 al->list = _free(al->list);
141 static unsigned int fileHash(struct fileNameEntry_s file){
142 return hashFunctionString(file.dirName) ^ hashFunctionString(file.baseName);
145 static int fileCompare(struct fileNameEntry_s one, struct fileNameEntry_s two) {
147 rc = strcmp(one.dirName, two.dirName);
149 rc = strcmp(one.baseName, two.baseName);
153 void rpmalDel(rpmal al, rpmte p)
155 availablePackage alp;
158 if (al == NULL || al->list == NULL)
159 return; /* XXX can't happen */
161 // XXX use a search for self provide
162 for (pkgNum=0; pkgNum<al->size; pkgNum++) {
163 if (al->list[pkgNum].p == p) {
167 if (pkgNum == al->size ) return; // Not found!
169 alp = al->list + pkgNum;
170 // do not actually delete, just set p to NULL
171 // and later filter that out of the results
175 static void rpmalAddFiles(rpmal al, rpmalNum pkgNum, rpmfi fi){
176 struct fileNameEntry_s fileName;
177 struct fileIndexEntry_s fileEntry;
181 fileEntry.pkgNum = pkgNum;
183 fi = rpmfiInit(fi, 0);
184 while ((i = rpmfiNext(fi)) >= 0) {
185 /* Ignore colored provides not in our rainbow. */
186 ficolor = rpmfiFColor(fi);
187 if (al->tscolor && ficolor && !(al->tscolor & ficolor))
190 fileName.dirName = rpmfiDN(fi);
191 fileName.baseName = rpmfiBN(fi);
193 fileEntry.entryIx = i;
195 rpmalFileHashAddEntry(al->fileHash, fileName, fileEntry);
199 static void rpmalAddProvides(rpmal al, rpmalNum pkgNum, rpmds provides){
200 struct availableIndexEntry_s indexEntry;
203 indexEntry.pkgNum = pkgNum;
205 if (rpmdsInit(provides) != NULL)
206 while (rpmdsNext(provides) >= 0) {
207 /* Ignore colored provides not in our rainbow. */
208 dscolor = rpmdsColor(provides);
209 if (al->tscolor && dscolor && !(al->tscolor & dscolor))
212 indexEntry.entryIx = rpmdsIx(provides);
213 rpmalProvidesHashAddEntry(al->providesHash, rpmdsN(provides), indexEntry);
217 void rpmalAdd(rpmal al, rpmte p)
220 availablePackage alp;
222 if (al->size == al->alloced) {
223 al->alloced += al->delta;
224 al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
228 alp = al->list + pkgNum;
233 fprintf(stderr, "*** add %p[%d]\n", al->list, (int) pkgNum);
235 alp->provides = rpmdsLink(rpmteDS(p, RPMTAG_PROVIDENAME),
236 RPMDBG_M("Provides (rpmalAdd)"));
237 alp->fi = rpmfiLink(rpmteFI(p), RPMDBG_M("Files (rpmalAdd)"));
239 if (al->providesHash != NULL) { // index is already created
240 rpmalAddProvides(al, pkgNum, alp->provides);
241 rpmalAddFiles(al, pkgNum, alp->fi);
244 assert(((rpmalNum)(alp - al->list)) == pkgNum);
247 void rpmalMakeIndex(rpmal al)
249 availablePackage alp;
254 if (al == NULL || al->list == NULL) return;
255 if (al->providesHash != NULL || al->fileHash != NULL)
257 for (i = 0; i < al->size; i++) {
259 if (alp->provides != NULL)
260 providesCnt += rpmdsCount(alp->provides);
262 fileCnt += rpmfiFC(alp->fi);
265 al->providesHash = rpmalProvidesHashCreate(providesCnt/4+128, hashFunctionString,
267 al->fileHash = rpmalFileHashCreate(fileCnt/4+128, fileHash, fileCompare,
270 for (i = 0; i < al->size; i++) {
272 rpmalAddProvides(al, i, alp->provides);
273 rpmalAddFiles(al, i, alp->fi);
278 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds)
280 const char *fileName = rpmdsN(ds);
284 if (al == NULL || fileName == NULL || *fileName != '/')
287 /* Split path into dirname and basename components for lookup */
288 if ((slash = strrchr(fileName, '/')) != NULL) {
291 size_t bnStart = (slash - fileName) + 1;
292 char dirName[bnStart + 1];
293 struct fileNameEntry_s fne = {
294 .baseName = fileName + bnStart,
297 strncpy(dirName, fileName, bnStart);
298 dirName[bnStart] = '\0';
300 rpmalFileHashGetEntry(al->fileHash, fne, &result, &resultCnt, NULL);
304 ret = xmalloc((resultCnt+1) * sizeof(*ret));
306 for (found = i = 0; i < resultCnt; i++) {
307 availablePackage alp = al->list + result[i].pkgNum;
308 if (alp->p == NULL) // deleted
311 rpmdsNotify(ds, _("(added files)"), 0);
324 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds)
329 availableIndexEntry result;
332 availablePackage alp;
335 if (al == NULL || ds == NULL || (name = rpmdsN(ds)) == NULL)
339 /* First, look for files "contained" in package ... */
340 ret = rpmalAllFileSatisfiesDepend(al, ds);
341 if (ret != NULL && *ret != NULL)
343 /* ... then, look for files "provided" by package. */
347 rpmalProvidesHashGetEntry(al->providesHash, name, &result,
350 if (resultCnt==0) return NULL;
352 ret = xmalloc((resultCnt+1) * sizeof(*ret));
354 for (found=i=0; i<resultCnt; i++) {
355 alp = al->list + result[i].pkgNum;
356 if (alp->p == NULL) // deleted
358 (void) rpmdsSetIx(alp->provides, result[i].entryIx);
360 if (rpmdsIx(alp->provides) >= 0)
361 rc = rpmdsCompare(alp->provides, ds);
364 rpmdsNotify(ds, _("(added provide)"), 0);
375 rpmalSatisfiesDepend(const rpmal al, const rpmds ds)
377 rpmte *providers = rpmalAllSatisfiesDepend(al, ds);
383 * For colored dependencies, try to find a matching provider.
384 * Otherwise prefer provider of ts preferred color.
386 rpm_color_t dscolor = rpmdsColor(ds);
387 for (rpmte *p = providers; *p; p++) {
388 rpm_color_t tecolor = rpmteColor(*p);
390 if (dscolor == tecolor) best = *p;
391 } else if (al->prefcolor) {
392 if (al->prefcolor == tecolor) best = *p;
397 /* if not decided by now, just pick first match */
398 if (!best) best = providers[0];