2 * Copyright (c) 2007-2016, SUSE LLC
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Add missing file dependencies to the package provides
31 #define SEARCHFILES_BLOCK 127
34 pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf)
38 struct searchfiles *csf;
40 while ((dep = *ida++) != 0)
46 sid = pool->ss.nstrings + GETRELID(dep);
47 if (MAPTST(&csf->seen, sid))
52 MAPSET(&csf->seen, sid);
53 rd = GETRELDEP(pool, dep);
56 else if (rd->flags == REL_NAMESPACE)
58 if (rd->name == NAMESPACE_SPLITPROVIDES)
61 if (!csf || MAPTST(&csf->seen, sid))
66 MAPSET(&csf->seen, sid);
70 else if (rd->flags == REL_FILECONFLICT)
80 pool_addfileprovides_dep(pool, ids, csf, isf);
86 if (MAPTST(&csf->seen, dep))
88 MAPSET(&csf->seen, dep);
89 s = pool_id2str(pool, dep);
92 if (csf != isf && pool->addedfileprovides == 1 && !repodata_filelistfilter_matches(0, s))
93 continue; /* skip non-standard locations csf == isf: installed case */
94 csf->ids = solv_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
95 csf->ids[csf->nfiles++] = dep;
99 struct addfileprovides_cbdata {
113 addfileprovides_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value)
115 struct addfileprovides_cbdata *cbd = cbdata;
118 if (!cbd->useddirs.size)
120 map_init(&cbd->useddirs, data->dirpool.ndirs + 1);
123 cbd->dirs = solv_malloc2(cbd->nfiles, sizeof(char *));
124 cbd->names = solv_malloc2(cbd->nfiles, sizeof(char *));
125 for (i = 0; i < cbd->nfiles; i++)
127 char *s = solv_strdup(pool_id2str(data->repo->pool, cbd->ids[i]));
131 cbd->names[i] = s + 1;
134 for (i = 0; i < cbd->nfiles; i++)
137 if (MAPTST(&cbd->providedids, cbd->ids[i]))
142 did = repodata_str2dir(data, cbd->dirs[i], 0);
145 MAPSET(&cbd->useddirs, did);
147 repodata_free_dircache(data);
149 if (value->id >= data->dirpool.ndirs || !MAPTST(&cbd->useddirs, value->id))
151 for (i = 0; i < cbd->nfiles; i++)
152 if (cbd->dids[i] == value->id && !strcmp(cbd->names[i], value->str))
153 s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER);
158 pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly)
164 int i, j, repoid, repodataid;
165 int provstart, provend;
167 int ndone, incomplete;
172 cbd->nfiles = sf->nfiles;
176 cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id));
177 map_init(&cbd->providedids, pool->ss.nstrings);
180 repo = repoonly ? repoonly : pool->repos[repoid];
181 map_init(&donemap, pool->nsolvables);
182 queue_init(&fileprovidesq);
183 provstart = provend = 0;
186 if (!repo || repo->disabled)
188 if (repoonly || ++repoid == pool->nrepos)
190 repo = pool->repos[repoid];
194 FOR_REPODATAS(repo, repodataid, data)
196 if (ndone >= repo->nsolvables)
199 if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq))
201 map_empty(&cbd->providedids);
202 for (i = 0; i < fileprovidesq.count; i++)
203 MAPSET(&cbd->providedids, fileprovidesq.elements[i]);
204 provstart = data->start;
206 for (i = 0; i < cbd->nfiles; i++)
207 if (!MAPTST(&cbd->providedids, cbd->ids[i]))
209 if (i == cbd->nfiles)
211 /* great! no need to search files */
212 for (p = data->start; p < data->end; p++)
213 if (pool->solvables[p].repo == repo)
215 if (MAPTST(&donemap, p))
224 if (!repodata_has_keyname(data, SOLVABLE_FILELIST))
227 if (data->start < provstart || data->end > provend)
229 map_empty(&cbd->providedids);
230 provstart = provend = 0;
233 /* check if the data is incomplete */
235 if (data->state == REPODATA_AVAILABLE)
237 for (j = 1; j < data->nkeys; j++)
238 if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
243 for (i = 0; i < cbd->nfiles; i++)
244 if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i])))
245 printf("need complete filelist because of %s\n", pool_id2str(pool, cbd->ids[i]));
247 for (i = 0; i < cbd->nfiles; i++)
248 if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, pool_id2str(pool, cbd->ids[i])))
256 map_init(&cbd->useddirs, 0);
257 for (p = data->start; p < data->end; p++)
258 if (pool->solvables[p].repo == repo)
260 if (MAPTST(&donemap, p))
262 repodata_search(data, p, SOLVABLE_FILELIST, 0, addfileprovides_cb, cbd);
269 map_free(&cbd->useddirs);
272 if (repoonly || ++repoid == pool->nrepos)
274 repo = pool->repos[repoid];
277 queue_free(&fileprovidesq);
278 map_free(&cbd->providedids);
281 for (i = 0; i < cbd->nfiles; i++)
282 solv_free(cbd->dirs[i]);
283 cbd->dirs = solv_free(cbd->dirs);
284 cbd->names = solv_free(cbd->names);
289 pool_addfileprovides_queue(Pool *pool, Queue *idq, Queue *idqinst)
292 Repo *installed, *repo;
293 struct searchfiles sf, isf, *isfp;
294 struct addfileprovides_cbdata cbd;
298 installed = pool->installed;
299 now = solv_timems(0);
300 memset(&sf, 0, sizeof(sf));
301 map_init(&sf.seen, pool->ss.nstrings + pool->nrels);
302 memset(&isf, 0, sizeof(isf));
303 map_init(&isf.seen, pool->ss.nstrings + pool->nrels);
304 pool->addedfileprovides = pool->addfileprovidesfiltered ? 1 : 2;
309 queue_empty(idqinst);
310 isfp = installed ? &isf : 0;
311 for (i = 1, s = pool->solvables + i; i < pool->nsolvables; i++, s++)
317 pool_addfileprovides_dep(pool, repo->idarraydata + s->obsoletes, &sf, isfp);
319 pool_addfileprovides_dep(pool, repo->idarraydata + s->conflicts, &sf, isfp);
321 pool_addfileprovides_dep(pool, repo->idarraydata + s->requires, &sf, isfp);
323 pool_addfileprovides_dep(pool, repo->idarraydata + s->recommends, &sf, isfp);
325 pool_addfileprovides_dep(pool, repo->idarraydata + s->suggests, &sf, isfp);
327 pool_addfileprovides_dep(pool, repo->idarraydata + s->supplements, &sf, isfp);
329 pool_addfileprovides_dep(pool, repo->idarraydata + s->enhances, &sf, isfp);
333 POOL_DEBUG(SOLV_DEBUG_STATS, "found %d file dependencies, %d installed file dependencies\n", sf.nfiles, isf.nfiles);
338 for (i = 0; i < sf.nfiles; i++)
339 POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in filelist\n", pool_id2str(pool, sf.ids[i]));
341 pool_addfileprovides_search(pool, &cbd, &sf, 0);
343 for (i = 0; i < sf.nfiles; i++)
344 queue_push(idq, sf.ids[i]);
346 for (i = 0; i < sf.nfiles; i++)
347 queue_push(idqinst, sf.ids[i]);
353 for (i = 0; i < isf.nfiles; i++)
354 POOL_DEBUG(SOLV_DEBUG_STATS, "looking up %s in installed filelist\n", pool_id2str(pool, isf.ids[i]));
357 pool_addfileprovides_search(pool, &cbd, &isf, installed);
358 if (installed && idqinst)
359 for (i = 0; i < isf.nfiles; i++)
360 queue_pushunique(idqinst, isf.ids[i]);
364 pool_freewhatprovides(pool); /* as we have added provides */
365 POOL_DEBUG(SOLV_DEBUG_STATS, "addfileprovides took %d ms\n", solv_timems(now));
369 pool_addfileprovides(Pool *pool)
371 pool_addfileprovides_queue(pool, 0, 0);