Esempio n. 1
0
static void
finddirs_cb(void *cbdatav, const char *fn, struct filelistinfo *info)
{
  struct cbdata *cbdata = cbdatav;
  Hashval h, hh;
  Id hx, qx;
  Id oidx, idx = cbdata->idx;

  hx = strhash(fn);
  if (!hx)
    hx = strlen(fn) + 1;
  h = hx & cbdata->dirmapn;
  hh = HASHCHAIN_START;
  for (;;)
    {
      qx = cbdata->dirmap[2 * h];
      if (!qx)
	break;
      if (qx == hx)
	break;
      h = HASHCHAIN_NEXT(h, hh, cbdata->dirmapn);
    }
  if (!qx)
    {
      /* a miss */
      if (!cbdata->create)
	return;
      cbdata->dirmap[2 * h] = hx;
      cbdata->dirmap[2 * h + 1] = idx;
      if (++cbdata->dirmapused * 2 > cbdata->dirmapn)
	cbdata->dirmap = growhash(cbdata->dirmap, &cbdata->dirmapn);
      return;
    }
  oidx = cbdata->dirmap[2 * h + 1];
  if (oidx == idx)
    return;
  /* found a conflict, this dir may be used in multiple packages */
  if (oidx != -1)
    {
      MAPSET(&cbdata->idxmap, oidx);
      cbdata->dirmap[2 * h + 1] = -1;
      cbdata->dirconflicts++;
    }
  MAPSET(&cbdata->idxmap, idx);
}
void PackageSet::set(Id id) { MAPSET(&pImpl->map, id); }
void PackageSet::set(DnfPackage *pkg) { MAPSET(&pImpl->map, dnf_package_get_id(pkg)); }
Esempio n. 4
0
static void
repo_addfileprovides_search(Repo *repo, struct addfileprovides_cbdata *cbd, struct searchfiles *sf)
{
  Repodata *data;
  int rdid, p, i;
  int provstart, provend;
  Map todo;
  Map providedids;

  if (repo->end <= repo->start || !repo->nsolvables || !sf->nfiles)
    return;

  /* update search data if changed */
  if (cbd->nfiles != sf->nfiles || cbd->ids != sf->ids)
    {
      free_dirs_names_array(cbd);
      cbd->nfiles = sf->nfiles;
      cbd->ids = sf->ids;
      cbd->dids = solv_realloc2(cbd->dids, sf->nfiles, sizeof(Id));
    }

  /* create todo map and range */
  map_init(&todo, repo->end - repo->start);
  for (p = repo->start; p < repo->end; p++)
    if (repo->pool->solvables[p].repo == repo)
      MAPSET(&todo, p - repo->start);
  cbd->todo = &todo;
  cbd->todo_start = repo->start;
  cbd->todo_end = repo->end;
  prune_todo_range(repo, cbd);

  provstart = provend = 0;
  map_init(&providedids, 0);
  data = repo_lookup_repodata(repo, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES);
  if (data)
    {
      Queue fileprovidesq;
      queue_init(&fileprovidesq);
      if (repodata_lookup_idarray(data, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, &fileprovidesq))
	{
	  map_grow(&providedids, repo->pool->ss.nstrings);
	  cbd->providedids = &providedids;
	  provstart = data->start;
	  provend = data->end;
	  for (i = 0; i < fileprovidesq.count; i++)
	    MAPSET(&providedids, fileprovidesq.elements[i]);
	  for (i = 0; i < cbd->nfiles; i++)
	    if (!MAPTST(&providedids, cbd->ids[i]))
	      break;
	  if (i == cbd->nfiles)
	    {
	      /* all included, clear entries from todo list */
	      if (provstart <= cbd->todo_start && provend >= cbd->todo_end)
		cbd->todo_end = cbd->todo_start;	/* clear complete range */
	      else
		{
		  for (p = provstart; p < provend; p++)
		    MAPCLR(&todo, p - repo->start);
		  prune_todo_range(repo, cbd);
		}
	    }
	}
      queue_free(&fileprovidesq);
    }

  if (cbd->todo_start >= cbd->todo_end)
    {
      map_free(&todo);
      cbd->todo = 0;
      map_free(&providedids);
      cbd->providedids = 0;
      return;
    }

  /* this is similar to repo_lookup_filelist_repodata in repo.c */

  for (rdid = 1, data = repo->repodata + rdid; rdid < repo->nrepodata; rdid++, data++)
    if (data->filelisttype == REPODATA_FILELIST_FILTERED)
      break;
  for (; rdid < repo->nrepodata; rdid++, data++)
    if (data->filelisttype == REPODATA_FILELIST_EXTENSION)
      break;

  if (rdid < repo->nrepodata)
    {
      /* have at least one repodata with REPODATA_FILELIST_FILTERED followed by REPODATA_FILELIST_EXTENSION */
      Map postpone;
      map_init(&postpone, 0);
      for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--)
	{
	  if (data->filelisttype != REPODATA_FILELIST_FILTERED)
	    continue;
	  if (!repodata_intersects_todo(data, cbd))
	    continue;
	  if (data->state != REPODATA_AVAILABLE)
	    {
	      if (data->state != REPODATA_STUB)
		continue;
	      repodata_load(data);
	      if (data->state != REPODATA_AVAILABLE || data->filelisttype != REPODATA_FILELIST_FILTERED)
		continue;
	    }
	  repo_addfileprovides_search_filtered(repo, cbd, rdid, &postpone);
	}
      if (postpone.size)
	{
	  /* add postponed entries back to todo */
	  map_or(&todo, &postpone);
	  cbd->todo_start = repo->start;
	  cbd->todo_end = repo->end;
	  prune_todo_range(repo, cbd);
	}
      map_free(&postpone);
    }

  /* search remaining entries in the standard way */
  if (cbd->todo_start < cbd->todo_end)
    {
      for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > 0; rdid--, data--)
	{
	  if (data->start >= cbd->todo_end || data->end <= cbd->todo_start)
	    continue;
	  if (!repodata_has_keyname(data, SOLVABLE_FILELIST))
	    continue;
	  if (!repodata_intersects_todo(data, cbd))
	    continue;
	  repodata_addfileprovides_search(data, cbd);
	  if (cbd->todo_start >= cbd->todo_end)
	    break;
	}
    }

  map_free(&todo);
  cbd->todo = 0;
  map_free(&providedids);
  cbd->providedids = 0;
}
Esempio n. 5
0
static void
pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf)
{
  Id dep, sid;
  const char *s;
  struct searchfiles *csf;

  while ((dep = *ida++) != 0)
    {
      csf = sf;
      while (ISRELDEP(dep))
	{
	  Reldep *rd;
	  sid = pool->ss.nstrings + GETRELID(dep);
	  if (MAPTST(&csf->seen, sid))
	    {
	      dep = 0;
	      break;
	    }
	  MAPSET(&csf->seen, sid);
	  rd = GETRELDEP(pool, dep);
	  if (rd->flags < 8)
	    dep = rd->name;
	  else if (rd->flags == REL_NAMESPACE)
	    {
	      if (rd->name == NAMESPACE_SPLITPROVIDES)
		{
		  csf = isf;
		  if (!csf || MAPTST(&csf->seen, sid))
		    {
		      dep = 0;
		      break;
		    }
		  MAPSET(&csf->seen, sid);
		}
	      dep = rd->evr;
	    }
	  else if (rd->flags == REL_FILECONFLICT)
	    {
	      dep = 0;
	      break;
	    }
	  else
	    {
	      Id ids[2];
	      ids[0] = rd->name;
	      ids[1] = 0;
	      pool_addfileprovides_dep(pool, ids, csf, isf);
	      dep = rd->evr;
	    }
	}
      if (!dep)
	continue;
      if (MAPTST(&csf->seen, dep))
	continue;
      MAPSET(&csf->seen, dep);
      s = pool_id2str(pool, dep);
      if (*s != '/')
	continue;
      if (csf != isf && pool->addedfileprovides == 1 && !repodata_filelistfilter_matches(0, s))
	continue;	/* skip non-standard locations csf == isf: installed case */
      csf->ids = solv_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
      csf->ids[csf->nfiles++] = dep;
    }
}
Esempio n. 6
0
static void
repo_addfileprovides_search_filtered(Repo *repo, struct addfileprovides_cbdata *cbd, int filteredid, Map *postpone)
{
  Repodata *data = repo->repodata + filteredid;
  Map *providedids = cbd->providedids;
  int rdid;
  int start, end, p, i;
  Map old_todo;
  int old_todo_start, old_todo_end;

  start = cbd->todo_start > data->start ? cbd->todo_start : data->start;
  end = cbd->todo_end > data->end ? data->end : cbd->todo_end;

  if (providedids)
    {
      /* check if all solvables are in the provide range */
      if (start < cbd->provstart || end > cbd->provend)
	{
	  /* unclear, check each solvable */
	  for (p = start; p < end; p++)
	    {
	      if (p >= cbd->provstart && p < cbd->provend)
		continue;
	      if (data->incoreoffset[p - data->start] && MAPTST(cbd->todo, p - repo->start))
		{
		  providedids = 0;	/* nope, cannot prune with providedids */
		  break;
		}
	    }
	}
    }

  /* check if the filtered files are enough */
  for (i = 0; i < cbd->nfiles; i++)
    {
      if (providedids && MAPTST(providedids, cbd->ids[i]))	/* this one is already provided */
	continue;
      if (!repodata_filelistfilter_matches(data, pool_id2str(repo->pool, cbd->ids[i])))
        break;
    }
  if (i < cbd->nfiles)
    {
      /* nope, need to search the extensions as well. postpone. */
      for (p = start; p < end; p++)
	{
	  if (data->incoreoffset[p - data->start] && MAPTST(cbd->todo, p - repo->start))
	    {
	      if (!postpone->size)
		map_grow(postpone, repo->nsolvables);
	      MAPSET(postpone, p - repo->start);
	      MAPCLR(cbd->todo, p - repo->start);
	    }
	}
      prune_todo_range(repo, cbd);
      return;
    }

  /* now check if there is no data marked withour EXTENSION */
  /* limit todo to the solvables in this repodata */
  old_todo_start = cbd->todo_start;
  old_todo_end = cbd->todo_end;
  old_todo = *cbd->todo;
  map_init(cbd->todo, repo->nsolvables);
  for (p = start; p < end; p++)
    if (data->incoreoffset[p - data->start] && MAPTST(&old_todo, p - repo->start))
      {
        MAPCLR(&old_todo, p - repo->start);
        MAPSET(cbd->todo, p - repo->start);
      }
  prune_todo_range(repo, cbd);

  /* do the check */
  for (rdid = repo->nrepodata - 1, data = repo->repodata + rdid; rdid > filteredid ; rdid--, data--)
    {
      if (data->filelisttype == REPODATA_FILELIST_EXTENSION)
	continue;
      if (data->start >= cbd->todo_end || data->end <= cbd->todo_start)
	continue;
      if (!repodata_has_keyname(data, SOLVABLE_FILELIST))
	continue;
      if (!repodata_intersects_todo(data, cbd))
	continue;
      /* oh no, this filelist data is not tagged with REPODATA_FILELIST_EXTENSION! */
      /* postpone entries that have filelist data */
      start = cbd->todo_start > data->start ? cbd->todo_start : data->start;
      end = cbd->todo_end > data->end ? data->end : cbd->todo_end;
      for (p = start; p < end; p++)
	if (MAPTST(cbd->todo, p - repo->start))
	  if (repodata_lookup_type(data, p, SOLVABLE_FILELIST))
	    {
	      if (!postpone->size)
		map_grow(postpone, repo->nsolvables);
	      MAPSET(postpone, p - repo->start);
	      MAPCLR(cbd->todo, p - repo->start);
	    }
      prune_todo_range(repo, cbd);
      if (cbd->todo_start >= cbd->todo_end)
	break;
    }

  /* do the search over the filtered file list with the remaining entries*/
  if (cbd->todo_start < cbd->todo_end)
    repodata_addfileprovides_search(repo->repodata + filteredid, cbd);

  /* restore todo map */
  map_free(cbd->todo);
  *cbd->todo = old_todo;
  cbd->todo_start = old_todo_start;
  cbd->todo_end = old_todo_end;
  prune_todo_range(repo, cbd);
}
Esempio n. 7
0
static void
repodata_addfileprovides_search(Repodata *data, struct addfileprovides_cbdata *cbd)
{
  Repo *repo = data->repo;
  int i, p, start, end;
  Map useddirs;
  Map *providedids = 0;

  /* make it available */
  if (data->state == REPODATA_STUB)
    repodata_load(data);
  if (data->state != REPODATA_AVAILABLE)
    return;
  if (!data->incoredata || !data->dirpool.ndirs)
    return;

  start = cbd->todo_start > data->start ? cbd->todo_start : data->start;
  end = cbd->todo_end > data->end ? data->end : cbd->todo_end;

  if (start >= end)
    return;

  /* deal with provideids overlap */
  if (cbd->providedids)
    {
      if (start >= cbd->provstart && end <= cbd->provend)
	providedids = cbd->providedids;	/* complete overlap */
      else if (start < cbd->provend && end > cbd->provstart)
	{
	  /* partial overlap, need to split search */
	  if (start < cbd->provstart)
	    {
	      repodata_addfileprovides_search_limited(data, cbd, start, cbd->provstart);
	      start = cbd->provstart;
	    }
	  if (end > cbd->provend)
	    {
	      repodata_addfileprovides_search_limited(data, cbd, cbd->provend, end);
	      end = cbd->provend;
	    }
	  if (start < end)
	    repodata_addfileprovides_search_limited(data, cbd, start, end);
	  return;
	}
    }

  /* set up dirs and names array if not already done */
  if (!cbd->dirs)
    create_dirs_names_array(cbd, repo->pool);

  /* set up useddirs map and the cbd->dids array */
  map_init(&useddirs, data->dirpool.ndirs);
  for (i = 0; i < cbd->nfiles; i++)
    {
      Id did;
      if (providedids && MAPTST(providedids, cbd->ids[i]))
	{
	  cbd->dids[i] = 0;	/* already included, do not add again */
	  continue;
	}
      cbd->dids[i] = did = repodata_str2dir(data, cbd->dirs[i], 0);
      if (did)
	MAPSET(&useddirs, did);
    }
  repodata_free_dircache(data);		/* repodata_str2dir created it */

  for (p = start; p < end; p++)
    {
      const unsigned char *dp;
      Solvable *s;
      if (!MAPTST(cbd->todo, p - repo->start))
	continue;
      dp = repodata_lookup_packed_dirstrarray(data, p, SOLVABLE_FILELIST);
      if (!dp)
	continue;
      /* now iterate through the packed array */
      s = repo->pool->solvables + p;
      MAPCLR(cbd->todo, p - repo->start);	/* this entry is done */
      for (;;)
	{
	  Id did = 0;
	  int c;
	  while ((c = *dp++) & 0x80)
	    did = (did << 7) ^ c ^ 0x80;
	  did = (did << 6) | (c & 0x3f);
	  if ((unsigned int)did < (unsigned int)data->dirpool.ndirs && MAPTST(&useddirs, did))
	    {
	      /* there is at least one entry with that did */
	      for (i = 0; i < cbd->nfiles; i++)
		if (cbd->dids[i] == did && !strcmp(cbd->names[i], (const char *)dp))
		  s->provides = repo_addid_dep(s->repo, s->provides, cbd->ids[i], SOLVABLE_FILEMARKER);
	    }
	  if (!(c & 0x40))
	    break;
	  dp += strlen((const char *)dp) + 1;
	}
    }
  map_free(&useddirs);
  prune_todo_range(repo, cbd);
}
Esempio n. 8
0
static void
prune_to_recommended(Solver *solv, Queue *plist)
{
  Pool *pool = solv->pool;
  int i, j, k, ninst;
  Solvable *s;
  Id p, pp, rec, *recp, sug, *sugp;

  ninst = 0;
  if (pool->installed)
    {
      for (i = 0; i < plist->count; i++)
	{
	  p = plist->elements[i];
	  s = pool->solvables + p;
	  if (pool->installed && s->repo == pool->installed)
	    ninst++;
	}
    }
  if (plist->count - ninst < 2)
    return;

  /* update our recommendsmap/suggestsmap */
  if (solv->recommends_index < 0)
    {
      MAPZERO(&solv->recommendsmap);
      MAPZERO(&solv->suggestsmap);
      solv->recommends_index = 0;
    }
  while (solv->recommends_index < solv->decisionq.count)
    {
      p = solv->decisionq.elements[solv->recommends_index++];
      if (p < 0)
	continue;
      s = pool->solvables + p;
      if (s->recommends)
	{
	  recp = s->repo->idarraydata + s->recommends;
          while ((rec = *recp++) != 0)
	    FOR_PROVIDES(p, pp, rec)
	      MAPSET(&solv->recommendsmap, p);
	}
      if (s->suggests)
	{
	  sugp = s->repo->idarraydata + s->suggests;
          while ((sug = *sugp++) != 0)
	    FOR_PROVIDES(p, pp, sug)
	      MAPSET(&solv->suggestsmap, p);
	}
    }

  /* prune to recommended/supplemented */
  ninst = 0;
  for (i = j = 0; i < plist->count; i++)
    {
      p = plist->elements[i];
      s = pool->solvables + p;
      if (pool->installed && s->repo == pool->installed)
	{
	  ninst++;
	  if (j)
	    plist->elements[j++] = p;
	  continue;
	}
      if (!MAPTST(&solv->recommendsmap, p))
	if (!solver_is_supplementing(solv, s))
	  continue;
      if (!j && ninst)
	{
	  for (k = 0; j < ninst; k++)
	    {
	      s = pool->solvables + plist->elements[k];
	      if (pool->installed && s->repo == pool->installed)
	        plist->elements[j++] = plist->elements[k];
	    }
	}
      plist->elements[j++] = p;
    }
  if (j)
    plist->count = j;

  /* anything left to prune? */
  if (plist->count - ninst < 2)
    return;

  /* prune to suggested/enhanced */
  ninst = 0;
  for (i = j = 0; i < plist->count; i++)
    {
      p = plist->elements[i];
      s = pool->solvables + p;
      if (pool->installed && s->repo == pool->installed)
	{
	  ninst++;
	  if (j)
	    plist->elements[j++] = p;
	  continue;
	}
      if (!MAPTST(&solv->suggestsmap, p))
        if (!solver_is_enhancing(solv, s))
	  continue;
      if (!j && ninst)
	{
	  for (k = 0; j < ninst; k++)
	    {
	      s = pool->solvables + plist->elements[k];
	      if (pool->installed && s->repo == pool->installed)
	        plist->elements[j++] = plist->elements[k];
	    }
	}
      plist->elements[j++] = p;
    }
  if (j)
    plist->count = j;
}
Esempio n. 9
0
/* same as findfileconflicts_cb, but
 * - hashes with just the basename
 * - sets idx in a map instead of pushing to lookat
 * - sets the hash element to -1 if there may be a conflict
 */
static void
findfileconflicts_basename_cb(void *cbdatav, const char *fn, struct filelistinfo *info)
{
  struct cbdata *cbdata = cbdatav;
  int isdir = S_ISDIR(info->mode);
  const char *dp;
  Id idx, oidx;
  Id hx, qx;
  Hashval h, hh;

  idx = cbdata->idx;

  if (!info->dirlen)
    return;
  dp = fn + info->dirlen;
  hx = strhash(dp);
  if (!hx)
    hx = strlen(fn) + 1;

  h = hx & cbdata->cflmapn;
  hh = HASHCHAIN_START;
  for (;;)
    {
      qx = cbdata->cflmap[2 * h];
      if (!qx)
	break;
      if (qx == hx)
	break;
      h = HASHCHAIN_NEXT(h, hh, cbdata->cflmapn);
    }
  if (!qx)
    {
      /* a miss */
      if (!cbdata->create)
	return;
      cbdata->cflmap[2 * h] = hx;
      cbdata->cflmap[2 * h + 1] = (isdir ? -idx - 2 : idx);
      if (++cbdata->cflmapused * 2 > cbdata->cflmapn)
	cbdata->cflmap = growhash(cbdata->cflmap, &cbdata->cflmapn);
      return;
    }
  oidx = cbdata->cflmap[2 * h + 1];
  if (oidx < -1)
    {
      int i;
      if (isdir)
	{
	  /* both are directories. delay the conflict, keep oidx in slot */
          queue_push2(&cbdata->lookat_dir, hx, idx);
	  return;
	}
      oidx = -idx - 2;
      /* now have file, had directories before. */
      cbdata->cflmap[2 * h + 1] = oidx;	/* make it a file */
      /* dump all delayed directory hits for hx */
      for (i = 0; i < cbdata->lookat_dir.count; i += 2)
	if (cbdata->lookat_dir.elements[i] == hx)
	  MAPSET(&cbdata->idxmap, cbdata->lookat_dir.elements[i + 1]);
    }
  else if (oidx == idx)
    return;	/* no conflicts with ourself, please */
  if (oidx >= 0)
    MAPSET(&cbdata->idxmap, oidx);
  MAPSET(&cbdata->idxmap, idx);
  if (oidx != -1)
    cbdata->cflmap[2 * h + 1] = -1;
}