va_start(args, format);
if (!pool->debugcallback)
{
- if ((type & (SAT_FATAL|SAT_ERROR)) == 0 || !(pool->debugmask & SAT_DEBUG_TO_STDERR))
+ if ((type & (SAT_FATAL|SAT_ERROR)) == 0 && !(pool->debugmask & SAT_DEBUG_TO_STDERR))
vprintf(format, args);
else
vfprintf(stderr, format, args);
char **dirs;
char **names;
- Repodata *olddata;
Id *dids;
+
+ Map providedids;
+
Map useddirs;
};
struct addfileprovides_cbdata *cbd = cbdata;
int i;
- if (data != cbd->olddata)
+ if (!cbd->useddirs.size)
{
- map_free(&cbd->useddirs);
- map_init(&cbd->useddirs, data->dirpool.ndirs);
+ map_init(&cbd->useddirs, data->dirpool.ndirs + 1);
for (i = 0; i < cbd->nfiles; i++)
{
- Id did = repodata_str2dir(data, cbd->dirs[i], 0);
- cbd->dids[i] = did;
+ Id did;
+ if (MAPTST(&cbd->providedids, cbd->ids[i]))
+ {
+ cbd->dids[i] = 0;
+ continue;
+ }
+ did = repodata_str2dir(data, cbd->dirs[i], 0);
+ cbd->dids[i] = did;
if (did)
MAPSET(&cbd->useddirs, did);
}
- cbd->olddata = data;
}
if (!MAPTST(&cbd->useddirs, value->id))
return 0;
return 0;
}
-static int
-addfileprovides_setid_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
-{
- Map *provideids = cbdata;
- if (key->type != REPOKEY_TYPE_IDARRAY)
- return 0;
- MAPSET(provideids, kv->id);
- return kv->eof ? SEARCH_NEXT_SOLVABLE : 0;
-}
-
-
static void
pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, struct searchfiles *sf, Repo *repoonly)
{
- Id p, start, end;
- Solvable *s;
- Repodata *data = 0, *nextdata;
- Repo *oldrepo = 0;
- int dataincludes = 0;
- int i, j;
- Map providedids;
+ Id p;
+ Repodata *data;
+ Repo *repo;
+ Queue fileprovidesq;
+ int i, j, repoid, repodataid;
+ int provstart, provend;
+ Map donemap;
+ int ndone, incomplete;
+
+ if (!pool->nrepos)
+ return;
cbd->nfiles = sf->nfiles;
cbd->ids = sf->ids;
cbd->dirs = sf->dirs;
cbd->names = sf->names;
- cbd->olddata = 0;
cbd->dids = sat_realloc2(cbd->dids, sf->nfiles, sizeof(Id));
- if (repoonly)
+ map_init(&cbd->providedids, pool->ss.nstrings);
+
+ repoid = 0;
+ repo = repoonly ? repoonly : pool->repos[0];
+ map_init(&donemap, pool->nsolvables);
+ queue_init(&fileprovidesq);
+ provstart = provend = 0;
+ for (;;)
{
- start = repoonly->start;
- end = repoonly->end;
- }
- else
- {
- start = 2; /* skip system solvable */
- end = pool->nsolvables;
- }
- for (p = start, s = pool->solvables + p; p < end; p++, s++)
- {
- if (!s->repo || (repoonly && s->repo != repoonly))
- continue;
- /* check if p is in (oldrepo,data) */
- if (s->repo != oldrepo || (data && p >= data->end))
+ if (repo->disabled)
{
- data = 0;
- oldrepo = 0;
+ if (repoonly || ++repoid == pool->nrepos)
+ break;
+ repo = pool->repos[repoid];
+ continue;
}
- if (oldrepo == 0)
+ ndone = 0;
+ for (data = repo->repodata, repodataid = 0; repodataid < repo->nrepodata; repodataid++, data++)
{
- /* nope, find new repo/repodata */
- /* if we don't find a match, set data to the next repodata */
- nextdata = 0;
- for (i = 0, data = s->repo->repodata; i < s->repo->nrepodata; i++, data++)
+ if (ndone >= repo->nsolvables)
+ break;
+ if (!repodata_precheck_keyname(data, SOLVABLE_FILELIST))
+ continue;
+ for (j = 1; j < data->nkeys; j++)
+ if (data->keys[j].name == SOLVABLE_FILELIST)
+ break;
+ if (j == data->nkeys)
+ continue;
+ if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq))
{
- if (p >= data->end)
- continue;
- if (data->state != REPODATA_AVAILABLE)
- continue;
- for (j = 1; j < data->nkeys; j++)
- if (data->keys[j].name == REPOSITORY_ADDEDFILEPROVIDES && data->keys[j].type == REPOKEY_TYPE_IDARRAY)
+ map_empty(&cbd->providedids);
+ for (i = 0; i < fileprovidesq.count; i++)
+ MAPSET(&cbd->providedids, fileprovidesq.elements[i]);
+ provstart = data->start;
+ provend = data->end;
+ for (i = 0; i < cbd->nfiles; i++)
+ if (!MAPTST(&cbd->providedids, cbd->ids[i]))
break;
- if (j == data->nkeys)
- continue;
- /* great, this repodata contains addedfileprovides */
- if (!nextdata || nextdata->start > data->start)
- nextdata = data;
- if (p >= data->start)
- break;
+ if (i == cbd->nfiles)
+ {
+ /* great! no need to search files */
+ for (p = data->start; p < data->end; p++)
+ if (pool->solvables[p].repo == repo)
+ {
+ if (MAPTST(&donemap, p))
+ continue;
+ MAPSET(&donemap, p);
+ ndone++;
+ }
+ continue;
+ }
}
- if (i == s->repo->nrepodata)
- data = nextdata; /* no direct hit, use next repodata */
- if (data)
+ else
{
- map_init(&providedids, pool->ss.nstrings);
- repodata_search(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, 0, addfileprovides_setid_cb, &providedids);
- for (i = 0; i < cbd->nfiles; i++)
- if (!MAPTST(&providedids, cbd->ids[i]))
+ if (data->start < provstart || data->end > provend)
+ {
+ map_empty(&cbd->providedids);
+ provstart = provend = 0;
+ }
+ }
+
+ /* check if the data is incomplete */
+ incomplete = 0;
+ if (data->state == REPODATA_AVAILABLE)
+ {
+ for (j = 1; j < data->nkeys; j++)
+ if (data->keys[j].name != REPOSITORY_SOLVABLES && data->keys[j].name != SOLVABLE_FILELIST)
break;
- map_free(&providedids);
- dataincludes = i == cbd->nfiles;
+ if (j < data->nkeys)
+ {
+#if 0
+ for (i = 0; i < cbd->nfiles; i++)
+ if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, id2str(pool, cbd->ids[i])))
+ printf("need complete filelist because of %s\n", id2str(pool, cbd->ids[i]));
+#endif
+ for (i = 0; i < cbd->nfiles; i++)
+ if (!MAPTST(&cbd->providedids, cbd->ids[i]) && !repodata_filelistfilter_matches(data, id2str(pool, cbd->ids[i])))
+ break;
+ if (i < cbd->nfiles)
+ incomplete = 1;
+ }
}
- oldrepo = s->repo;
+
+ /* do the search */
+ map_init(&cbd->useddirs, 0);
+ for (p = data->start; p < data->end; p++)
+ if (pool->solvables[p].repo == repo)
+ {
+ if (MAPTST(&donemap, p))
+ continue;
+ repodata_search(data, p, SOLVABLE_FILELIST, 0, addfileprovides_cb, cbd);
+ if (!incomplete)
+ {
+ MAPSET(&donemap, p);
+ ndone++;
+ }
+ }
+ map_free(&cbd->useddirs);
}
- if (data && p >= data->start && dataincludes)
- continue;
- repo_search(s->repo, p, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, cbd);
+
+ if (repoonly || ++repoid == pool->nrepos)
+ break;
+ repo = pool->repos[repoid];
}
+ map_free(&donemap);
+ queue_free(&fileprovidesq);
+ map_free(&cbd->providedids);
}
void
struct searchfiles sf, isf, *isfp;
struct addfileprovides_cbdata cbd;
int i;
+ unsigned int now;
+ now = sat_timems(0);
memset(&sf, 0, sizeof(sf));
map_init(&sf.seen, pool->ss.nstrings + pool->nrels);
memset(&isf, 0, sizeof(isf));
}
map_free(&sf.seen);
map_free(&isf.seen);
- POOL_DEBUG(SAT_DEBUG_STATS, "found %d file dependencies\n", sf.nfiles);
- POOL_DEBUG(SAT_DEBUG_STATS, "found %d installed file dependencies\n", isf.nfiles);
+ POOL_DEBUG(SAT_DEBUG_STATS, "found %d file dependencies, %d installed file dependencies\n", sf.nfiles, isf.nfiles);
cbd.dids = 0;
- map_init(&cbd.useddirs, 1);
if (idp)
*idp = 0;
if (sf.nfiles)
sat_free(isf.dirs);
sat_free(isf.names);
}
- map_free(&cbd.useddirs);
sat_free(cbd.dids);
pool_freewhatprovides(pool); /* as we have added provides */
+ POOL_DEBUG(SAT_DEBUG_STATS, "addfileprovides took %d ms\n", sat_timems(now));
}
void
return dep;
}
-static int providedbyinstalled_multiversion(Pool *pool, unsigned char *map, Id n, Id dep)
+static int providedbyinstalled_multiversion(Pool *pool, unsigned char *map, Id n, Id con)
{
Id p, pp;
Solvable *sn = pool->solvables + n;
Solvable *s = pool->solvables + p;
if (s->name != sn->name || s->arch != sn->arch)
continue;
- if ((map[p] & 9) == 9)
- return 1;
- }
+ if ((map[p] & 9) != 9)
+ continue;
+ if (pool_match_nevr(pool, pool->solvables + p, con))
+ continue;
+ return 1; /* found installed package that doesn't conflict */
+ }
return 0;
}