示例#1
0
文件: repo_cudf.c 项目: k0da/libsolv
static void
finishpackage(Pool *pool, Solvable *s, int keep, Queue *job)
{
  Id *idp, id, sid;
  if (!s)
    return;
  if (!s->arch)
    s->arch = ARCH_ANY;
  if (!s->evr)
    s->evr = ID_EMPTY;
  sid = pool_rel2id(pool, s->name, s->evr, REL_EQ, 1);
  s->provides = repo_addid_dep(s->repo, s->provides, sid, 0);
  if (!job || !pool->installed || s->repo != pool->installed)
    return;
  if (keep == KEEP_VERSION)
    queue_push2(job, SOLVER_INSTALL|SOLVER_SOLVABLE_NAME, sid);
  else if (keep == KEEP_PACKAGE)
    queue_push2(job, SOLVER_INSTALL|SOLVER_SOLVABLE_NAME, s->name);
  else if (keep == KEEP_FEATURE)
    {
      for (idp = s->repo->idarraydata + s->provides; (id = *idp) != 0; idp++)
	{
	  if (id != sid)	/* skip self-provides */
	    queue_push2(job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES, id);
	}
    }
}
示例#2
0
/*
 * map a directory (containing a trailing /) into a number.
 * for unifywithstat this is the offset to the 16 byte stat result.
 * for unifywithcanon this is the offset to the normailzed dir.
 */
static Id
normalizedir(struct cbdata *cbdata, const char *dir, int dirl, Id hx, int create)
{
  Hashval h, hh;
  Id qx;
  Id nspaceoff;
  int mycnt;

  if (!hx)
    hx = dirl + 1;
  h = hx & cbdata->normapn;
  hh = HASHCHAIN_START;
  for (;;)
    {
      qx = cbdata->normap[2 * h];
      if (!qx)
	break;
      if (qx == hx)
	{
	  Id off = cbdata->normap[2 * h + 1];
	  char *dp = (char *)cbdata->filesspace + cbdata->norq.elements[off];
	  if (!strncmp(dp, dir, dirl) && dp[dirl] == 0)
	    return cbdata->norq.elements[off + 1];
	}
      h = HASHCHAIN_NEXT(h, hh, cbdata->normapn);
    }
  if (!create)
    return 0;
  /* new dir. work. */
  if (dir >= (const char *)cbdata->filesspace && dir < (const char *)cbdata->filesspace + cbdata->filesspacen)
    {
      /* can happen when called from unifywithcanon */
      Id off = dir - (const char *)cbdata->filesspace;
      nspaceoff = addfilesspace(cbdata, dirl + 1);
      dir = (const char *)cbdata->filesspace + off;
    }
  else
    nspaceoff = addfilesspace(cbdata, dirl + 1);
  if (dirl)
    memcpy(cbdata->filesspace + nspaceoff, dir, dirl);
  cbdata->filesspace[nspaceoff + dirl] = 0;
  mycnt = cbdata->norq.count;
  queue_push2(&cbdata->norq, nspaceoff, -1);	/* -1: in progress */
  cbdata->normap[2 * h] = hx;
  cbdata->normap[2 * h + 1] = mycnt;
  if (++cbdata->normapused * 2 > cbdata->normapn)
    cbdata->normap = growhash(cbdata->normap, &cbdata->normapn);
  /* unify */
  if (cbdata->usestat)
    nspaceoff = unifywithstat(cbdata, nspaceoff, dirl);
  else
    nspaceoff = unifywithcanon(cbdata, nspaceoff, dirl);
  cbdata->norq.elements[mycnt + 1] = nspaceoff;	/* patch in result */
#if 0
  if (!cbdata->usestat)
    printf("%s normalized to %d: %s\n", cbdata->filesspace + cbdata->norq.elements[mycnt], nspaceoff, cbdata->filesspace + nspaceoff);
#endif
  return nspaceoff;
}
示例#3
0
void
pool_deb_get_autoinstalled(Pool *pool, FILE *fp, Queue *q, int flags)
{
  Id name = 0, arch = 0;
  int autoinstalled = -1;
  char *buf, *bp;
  int x, l, bufl, eof = 0;
  Id p, pp;

  queue_empty(q);
  buf = solv_malloc(4096);
  bufl = 4096;
  l = 0;
  while (!eof)
    {
      while (bufl - l < 1024)
	{
	  bufl += 4096;
	  if (bufl > 1024 * 64)
	    break;	/* hmm? */
	  buf = solv_realloc(buf, bufl);
	}
      if (!fgets(buf + l, bufl - l, fp))
	{
	  eof = 1;
	  buf[l] = '\n';
	  buf[l + 1] = 0;
	}
      l = strlen(buf);
      if (l && buf[l - 1] == '\n')
	buf[--l] = 0;
      if (!*buf || eof)
	{
	  l = 0;
	  if (name && autoinstalled > 0)
	    {
	      if ((flags & GET_USERINSTALLED_NAMEARCH) != 0)
		queue_push2(q, name, arch);
	      else if ((flags & GET_USERINSTALLED_NAMES) != 0)
		queue_push(q, name);
	      else
		{
		  FOR_PROVIDES(p, pp, name)
		    {
		      Solvable *s = pool->solvables + p;
		      if (s->name != name)
			continue;
		      if (arch && s->arch != arch)
			continue;
		      queue_push(q, p);
		    }
		}
	    }
	  name = arch = 0;
	  autoinstalled = -1;
	  continue;
	}
示例#4
0
int main(int argc, char **argv)
{
  Pool *pool;
  Repo *installed;
  Solvable *s;
  Id p;
  int i;
  Queue todo, conflicts;
  void *state = 0;
 
  pool = pool_create();
  pool_setdebuglevel(pool, 1);
  installed = repo_create(pool, "@System");
  pool_set_installed(pool, installed);
  if (repo_add_rpmdb(installed, 0, 0))
    {
      fprintf(stderr, "findfileconflicts: %s\n", pool_errstr(pool));
      exit(1);
    }
  queue_init(&todo);
  queue_init(&conflicts);
  FOR_REPO_SOLVABLES(installed, p, s)
    queue_push(&todo, p);
  pool_findfileconflicts(pool, &todo, 0, &conflicts, &iterate_handle, (void *)&state);
  queue_free(&todo);
  for (i = 0; i < conflicts.count; i += 5)
    printf("%s: %s[%s] %s[%s]\n", pool_id2str(pool, conflicts.elements[i]), pool_solvid2str(pool, conflicts.elements[i + 1]), pool_id2str(pool, conflicts.elements[i + 2]), pool_solvid2str(pool, conflicts.elements[i + 3]), pool_id2str(pool, conflicts.elements[i + 4]));
  if (conflicts.count)
    {
      Queue job;
      int problemcnt;

      queue_init(&job);
      pool_add_fileconflicts_deps(pool, &conflicts);
      pool_addfileprovides(pool);
      pool_createwhatprovides(pool);
      pool_setdebuglevel(pool, 0);
      Solver *solv = solver_create(pool);
      queue_push2(&job, SOLVER_VERIFY|SOLVER_SOLVABLE_ALL, 0);
#if 0
      solver_set_flag(solv, SOLVER_FLAG_ALLOW_UNINSTALL, 1);
#endif
      problemcnt = solver_solve(solv, &job);
      if (problemcnt)
        solver_printallsolutions(solv);
      else
	{
	  Transaction *trans = solver_create_transaction(solv);
          transaction_print(trans);
          transaction_free(trans);
	}
      queue_free(&job);
      solver_free(solv);
    }
  queue_free(&conflicts);
  exit(0);
}
示例#5
0
static void
findfileconflicts_alias_cb(void *cbdatav, const char *fn, struct filelistinfo *info)
{
  int isdir = S_ISDIR(info->mode);
  struct cbdata *cbdata = cbdatav;
  const char *dp;
  Id idx, dirid;
  Id hx, qx;
  Hashval h, hh;

  idx = cbdata->idx;

  if (!info->dirlen)
    return;
  dp = fn + info->dirlen;
  if (info->diridx != cbdata->lastdiridx)
    {
      cbdata->lastdiridx = info->diridx;
      cbdata->lastdirhash = 0;
    }
  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 || cbdata->cflmap[2 * h + 1] != -1)
    return;
  if (!cbdata->lastdirhash)
    cbdata->lastdirhash = strnhash(fn, dp - fn);
  dirid = normalizedir(cbdata, fn, dp - fn, cbdata->lastdirhash, 1);
  queue_push2(&cbdata->lookat, hx, idx);
  queue_push2(&cbdata->lookat, cbdata->lastdirhash, isdir ? -dirid : dirid);
}
示例#6
0
static Id
unifywithstat(struct cbdata *cbdata, Id diroff, int dirl)
{
  struct stat stb;
  int i;
  Hashval h, hh;
  Id hx, qx;
  Id nspaceoff;
  unsigned char statdata[16 + sizeof(stb.st_dev) + sizeof(stb.st_ino)];

  if (dirl > 1 && cbdata->filesspace[diroff + dirl - 1] == '/')
    cbdata->filesspace[diroff + dirl - 1] = 0;
  cbdata->statsmade++;
  i = stat((char *)cbdata->filesspace + diroff, &stb);
  if (dirl > 1 && cbdata->filesspace[diroff + dirl - 1] == 0)
    cbdata->filesspace[diroff + dirl - 1] = '/';
  if (i)
    return diroff;
  memset(statdata, 0, 16);
  memcpy(statdata + 8, &stb.st_dev, sizeof(stb.st_dev));
  memcpy(statdata, &stb.st_ino, sizeof(stb.st_ino));
  hx = 0;
  for (i = 15; i >= 0; i--)
    hx = (unsigned int)hx * 13 + statdata[i];
  h = hx & cbdata->statmapn;
  hh = HASHCHAIN_START;
  for (;;)
    {
      qx = cbdata->statmap[2 * h];
      if (!qx)
	break;
      if (qx == hx)
	{
	  Id off = cbdata->statmap[2 * h + 1];
	  char *dp = (char *)cbdata->filesspace + cbdata->norq.elements[off];
	  if (!memcmp(dp, statdata, 16))
	    return cbdata->norq.elements[off + 1];
	}
      h = HASHCHAIN_NEXT(h, hh, cbdata->statmapn);
    }
  /* new stat result. work. */
  nspaceoff = addfilesspace(cbdata, 16);
  memcpy(cbdata->filesspace + nspaceoff, statdata, 16);
  queue_push2(&cbdata->norq, nspaceoff, nspaceoff);
  cbdata->statmap[2 * h] = hx;
  cbdata->statmap[2 * h + 1] = cbdata->norq.count - 2;
  if (++cbdata->statmapused * 2 > cbdata->statmapn)
    cbdata->statmap = growhash(cbdata->statmap, &cbdata->statmapn);
  return nspaceoff;
}
示例#7
0
void
transaction_all_obs_pkgs(Transaction *trans, Id p, Queue *pkgs)
{
  Pool *pool = trans->pool;
  Solvable *s = pool->solvables + p;
  Queue *ti = &trans->transaction_info;
  Id q;
  int i;

  queue_empty(pkgs);
  if (p <= 0 || !s->repo)
    return;
  if (s->repo == pool->installed)
    {
      q = trans->transaction_installed[p - pool->installed->start];
      if (!q)
	return;
      if (q > 0)
	{
	  /* only a single obsoleting package */
	  queue_push(pkgs, q);
	  return;
	}
      /* find which packages obsolete us */
      for (i = 0; i < ti->count; i += 2)
	if (ti->elements[i + 1] == p)
	  queue_push2(pkgs, p, ti->elements[i]);
      /* sort obsoleters */
      if (pkgs->count > 2)
	solv_sort(pkgs->elements, pkgs->count / 2, 2 * sizeof(Id), obsq_sortcmp, pool);
      for (i = 0; i < pkgs->count; i += 2)
	pkgs->elements[i / 2] = pkgs->elements[i + 1];
      queue_truncate(pkgs, pkgs->count / 2);
    }
  else
    {
      /* find the packages we obsolete */
      for (i = 0; i < ti->count; i += 2)
	{
	  if (ti->elements[i] == p)
	    queue_push(pkgs, ti->elements[i + 1]);
	  else if (pkgs->count)
	    break;
	}
    }
}
示例#8
0
int
main(int argc, char **argv)
{
  Pool *pool;
  Queue job;
  Queue solq;
  Solver *solv;
  char *result = 0;
  int resultflags = 0;
  int debuglevel = 0;
  int writeresult = 0;
  int multijob = 0;
  int rescallback = 0;
  int c;
  int ex = 0;
  const char *list = 0;
  FILE *fp;
  const char *p;

  queue_init(&solq);
  while ((c = getopt(argc, argv, "vmrhl:s:")) >= 0)
    {
      switch (c)
      {
        case 'v':
          debuglevel++;
          break;
        case 'r':
          writeresult++;
          break;
        case 'm':
          rescallback = 1;
          break;
        case 'h':
	  usage(0);
          break;
        case 'l':
	  list = optarg;
          break;
        case 's':
	  if ((p = strchr(optarg, ':')))
	    queue_push2(&solq, atoi(optarg), atoi(p + 1));
	  else
	    queue_push2(&solq, 1, atoi(optarg));
          break;
        default:
	  usage(1);
          break;
      }
    }
  if (optind == argc)
    usage(1);
  for (; optind < argc; optind++)
    {
      pool = pool_create();
      pool_setdebuglevel(pool, debuglevel);

      fp = fopen(argv[optind], "r");
      if (!fp)
	{
	  perror(argv[optind]);
	  exit(0);
	}
      while (!feof(fp))
	{
	  queue_init(&job);
	  result = 0;
	  resultflags = 0;
	  solv = testcase_read(pool, fp, argv[optind], &job, &result, &resultflags);
	  if (!solv)
	    {
	      pool_free(pool);
	      exit(1);
	    }

	  if (!multijob && !feof(fp))
	    multijob = 1;

	  if (multijob)
	    printf("test %d:\n", multijob++);
	  if (list)
	    {
	      queue_empty(&job);
	      selection_make(pool, &job, list, SELECTION_NAME|SELECTION_PROVIDES|SELECTION_FILELIST|SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL|SELECTION_GLOB|SELECTION_FLAT);
	      if (!job.elements)
		printf("No match\n");
	      else
		{
		  Queue q;
		  int i;
		  queue_init(&q);
		  selection_solvables(pool, &job, &q);
		  for (i = 0; i < q.count; i++)
		    printf("  - %s\n", testcase_solvid2str(pool, q.elements[i]));
		  queue_free(&q);
		}
	    }
	  else if (result || writeresult)
	    {
	      char *myresult, *resultdiff;
	      struct reportsolutiondata reportsolutiondata;
	      memset(&reportsolutiondata, 0, sizeof(reportsolutiondata));
	      if (rescallback)
		{
		  solv->solution_callback = reportsolutioncb;
		  solv->solution_callback_data = &reportsolutiondata;
		}
	      solver_solve(solv, &job);
	      solv->solution_callback = 0;
	      solv->solution_callback_data = 0;
	      if (!resultflags)
		resultflags = TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS;
	      myresult = testcase_solverresult(solv, resultflags);
	      if (rescallback && reportsolutiondata.result)
		{
		  reportsolutiondata.result = solv_dupjoin(reportsolutiondata.result, myresult, 0);
		  solv_free(myresult);
		  myresult = reportsolutiondata.result;
		}
	      if (writeresult)
		{
		  if (*myresult)
		    {
		      if (writeresult > 1)
			{
			  const char *p;
			  int i;
			  
			  printf("result ");
			  p = "%s";
			  for (i = 0; resultflags2str[i].str; i++)
			    if ((resultflags & resultflags2str[i].flag) != 0)
			      {
			        printf(p, resultflags2str[i].str);
			        p = ",%s";
			      }
			  printf(" <inline>\n");
			  p = myresult;
			  while (*p)
			    {
			      const char *p2 = strchr(p, '\n');
			      p2 = p2 ? p2 + 1 : p + strlen(p);
			      printf("#>%.*s", (int)(p2 - p), p);
			      p = p2;
			    }
			}
		      else
			printf("%s", myresult);
		    }
		}
	      else
		{
		  resultdiff = testcase_resultdiff(result, myresult);
		  if (resultdiff)
		    {
		      printf("Results differ:\n%s", resultdiff);
		      ex = 1;
		      solv_free(resultdiff);
		    }
		}
	      solv_free(result);
	      solv_free(myresult);
	    }
	  else
	    {
	      int pcnt = solver_solve(solv, &job);
	      if (pcnt && solq.count)
		{
		  int i, taken = 0;
		  for (i = 0; i < solq.count; i += 2)
		    {
		      if (solq.elements[i] > 0 && solq.elements[i] <= pcnt)
			if (solq.elements[i + 1] > 0 && solq.elements[i + 1] <=  solver_solution_count(solv, solq.elements[i]))
			  {
			    printf("problem %d: taking solution %d\n", solq.elements[i], solq.elements[i + 1]);
			    solver_take_solution(solv, solq.elements[i], solq.elements[i + 1], &job);
			    taken = 1;
			  }
		    }
		  if (taken)
		    pcnt = solver_solve(solv, &job);
		}
	      if (pcnt)
		{
		  int problem, solution, scnt;
		  printf("Found %d problems:\n", pcnt);
		  for (problem = 1; problem <= pcnt; problem++)
		    {
		      printf("Problem %d:\n", problem);
#if 1
		      solver_printprobleminfo(solv, problem);
#else
		      {
			Queue pq;
			int j;
			queue_init(&pq);
			solver_findallproblemrules(solv, problem, &pq);
			for (j = 0; j < pq.count; j++)
			  solver_printproblemruleinfo(solv, pq.elements[j]);
			queue_free(&pq);
		      }
#endif
		      printf("\n");
		      scnt = solver_solution_count(solv, problem);
		      for (solution = 1; solution <= scnt; solution++)
			{
			  printf("Solution %d:\n", solution);
			  solver_printsolution(solv, problem, solution);
			  printf("\n");
			}
		    }
		}
	      else
		{
		  Transaction *trans = solver_create_transaction(solv);
		  printf("Transaction summary:\n\n");
		  transaction_print(trans);
		  transaction_free(trans);
		}
	    }
	  queue_free(&job);
	  solver_free(solv);
	}
      pool_free(pool);
      fclose(fp);
    }
  queue_free(&solq);
  exit(ex);
}
示例#9
0
文件: repo_cudf.c 项目: k0da/libsolv
int
repo_add_cudf(Repo *repo, Repo *installedrepo, FILE *fp, Queue *job, int flags)
{
  Pool *pool = repo->pool;
  char *buf, *p;
  int bufa, bufl, c;
  Solvable *s;
  int instanza = 0;
  int inrequest = 0;
  int isinstalled = 0;
  int keep = 0;
  Repo *xrepo;

  xrepo = repo ? repo : installedrepo;
  if (!xrepo)
    return -1;

  buf = solv_malloc(4096);
  bufa = 4096;
  bufl = 0;
  s = 0;

  while (fgets(buf + bufl, bufa - bufl, fp) > 0)
    {
      bufl += strlen(buf + bufl);
      if (bufl && buf[bufl - 1] != '\n')
	{
	  if (bufa - bufl < 256)
	    {
	      bufa += 4096;
	      buf = solv_realloc(buf, bufa);
	    }
	  continue;
	}
      buf[--bufl] = 0;
      c = getc(fp);
      if (c == ' ' || c == '\t')
	{
	  /* continuation line */
	  buf[bufl++] = ' ';
	  continue;
	}
      if (c != EOF)
	ungetc(c, fp);
      bufl = 0;
      if (*buf == '#')
	continue;
      if (!*buf)
	{
	  if (s && !repo && !isinstalled)
	    {
	      repo_free_solvable(repo, s - pool->solvables, 1);
	      s = 0;
	    }
	  if (s)
	    finishpackage(pool, s, keep, job);
	  s = 0;
	  keep = 0;
	  instanza = 0;
	  inrequest = 0;
	  continue;
	}
      p = strchr(buf, ':');
      if (!p)
	continue;	/* hmm */
      *p++ = 0;
      while (*p == ' ' || *p == '\t')
	p++;
      if (!instanza)
	{
	  instanza = 1;
	  inrequest = 0;
	  if (!strcmp(buf, "request"))
	    {
	      inrequest = 1;
	      continue;
	    }
	  if (!strcmp(buf, "package"))
	    {
	      s = pool_id2solvable(pool, repo_add_solvable(xrepo));
	      isinstalled = 0;
	      keep = 0;
	    }
	}
      if (inrequest)
	{
	  if (!job)
	    continue;
	  if (!strcmp(buf, "install"))
	    {
	      Id id, *idp;
	      Offset off = makedeps(xrepo, p, 0, 0);
	      for (idp = xrepo->idarraydata + off; (id = *idp) != 0; idp++)
		queue_push2(job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES, id);
	    }
	  else if (!strcmp(buf, "remove"))
	    {
	      Id id, *idp;
	      Offset off = makedeps(xrepo, p, 0, 0);
	      for (idp = xrepo->idarraydata + off; (id = *idp) != 0; idp++)
		queue_push2(job, SOLVER_ERASE|SOLVER_SOLVABLE_PROVIDES, id);
	    }
	  else if (!strcmp(buf, "upgrade"))
	    {
	      Id id, *idp;
	      Offset off = makedeps(xrepo, p, 0, 0);
	      for (idp = xrepo->idarraydata + off; (id = *idp) != 0; idp++)
		queue_push2(job, SOLVER_INSTALL|SOLVER_ORUPDATE|SOLVER_SOLVABLE_PROVIDES, id);
	    }
	  continue;
	}
      if (!s)
	continue;	/* we ignore the preamble for now */
      switch (buf[0])
	{
	case 'c':
	  if (!strcmp(buf, "conflicts"))
	    {
	      s->conflicts = makedeps(s->repo, p, s->conflicts, 0);
	      continue;
	    }
	case 'd':
	  if (!strcmp(buf, "depends"))
	    {
	      s->requires = makedeps(s->repo, p, s->requires, 0);
	      continue;
	    }
	  break;
	case 'k':
	  if (!strcmp(buf, "keep"))
	    {
	      if (!job)
		continue;
	      if (!strcmp(p, "version"))
		keep = KEEP_VERSION;
	      else if (!strcmp(p, "package"))
		keep = KEEP_PACKAGE;
	      else if (!strcmp(p, "feature"))
		keep = KEEP_FEATURE;
	      continue;
	    }
	  break;
	case 'i':
	  if (!strcmp(buf, "installed"))
	    {
	      if (!strcmp(p, "true"))
		{
		  isinstalled = 1;
		  if (!installedrepo)
		    {
		      repo_free_solvable(repo, s - pool->solvables, 1);
		      s = 0;
		    }
		  else if (s->repo != installedrepo)
		    {
		      copysolvabledata(pool, s, installedrepo);
		      s->repo->nsolvables--;
		      s->repo = installedrepo;
		      if (s - pool->solvables < s->repo->start)
			s->repo->start = s - pool->solvables;
		      if (s - pool->solvables >= s->repo->end)
			s->repo->end = s - pool->solvables + 1;
		      s->repo->nsolvables++;
		    }
		}
	      continue;
	    }
	  break;
	case 'p':
	  if (!strcmp(buf, "package"))
	    {
	      s->name = pool_str2id(pool, p, 1);
	      continue;
	    }
	  if (!strcmp(buf, "provides"))
	    {
	      s->provides = makedeps(s->repo, p, s->provides, 0);
	      continue;
	    }
	  break;
	case 'r':
	  if (!strcmp(buf, "depends"))
	    {
	      s->recommends = makedeps(s->repo, p, s->recommends, 0);
	      continue;
	    }
	  break;
	case 'v':
	  if (!strcmp(buf, "version"))
	    {
	      s->evr = pool_str2id(pool, p, 1);
	      continue;
	    }
	  break;
	}
    }
  if (s && !repo && !isinstalled)
    {
      repo_free_solvable(repo, s - pool->solvables, 1);
      s = 0;
    }
  if (s)
    finishpackage(pool, s, keep, job);
  solv_free(buf);
  return 0;
}
示例#10
0
int
repo_add_autopattern(Repo *repo, int flags)
{
  Pool *pool = repo->pool;
  Repodata *data = 0;
  Solvable *s, *s2;
  Queue q, q2;
  Id p;
  Id pattern_id;
  Id autopattern_id = 0;
  int i, j;

  queue_init(&q);
  queue_init(&q2);

  pattern_id = pool_str2id(pool, "pattern()", 9);
  FOR_REPO_SOLVABLES(repo, p, s)
    {
      const char *n = pool_id2str(pool, s->name);
      if (!strncmp("pattern:", n, 8))
	queue_push(&q, p);
      else if (s->provides)
	{
	  Id prv, *prvp = repo->idarraydata + s->provides;
	  while ((prv = *prvp++) != 0)            /* go through all provides */
	    if (ISRELDEP(prv))
	      {
	        Reldep *rd = GETRELDEP(pool, prv);
		if (rd->name == pattern_id && rd->flags == REL_EQ)
		  {
		    queue_push2(&q2, p, rd->evr);
		    break;
		  }
	      }
	}
    }
  for (i = 0; i < q2.count; i += 2)
    {
      const char *pn = 0;
      char *newname;
      Id name, prv, *prvp;
      const char *str;
      unsigned long long num;

      s = pool->solvables + q2.elements[i];
      /* construct new name */
      newname = pool_tmpjoin(pool, "pattern:", pool_id2str(pool, q2.elements[i + 1]), 0);
      unescape(newname);
      name = pool_str2id(pool, newname, 0);
      if (name)
	{
	  /* check if we already have that pattern */
	  for (j = 0; j < q.count; j++)
	    {
	      s2 = pool->solvables + q.elements[j];
	      if (s2->name == name && s2->arch == s->arch && s2->evr == s->evr)
		break;
	    }
	  if (j < q.count)
	    continue;	/* yes, do not add again */
	}
      /* new pattern */
      if (!name)
        name = pool_str2id(pool, newname, 1);
      if (!data)
	{
	  repo_internalize(repo);	/* to make that the lookups work */
	  data = repo_add_repodata(repo, flags);
	}
      s2 = pool_id2solvable(pool, repo_add_solvable(repo));
      s = pool->solvables + q2.elements[i];	/* re-calc pointer */
      s2->name = name;
      s2->arch = s->arch;
      s2->evr = s->evr;
      s2->vendor = s->vendor;
      /* add link requires */
      s2->requires = repo_addid_dep(repo, s2->requires, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1) , 0);
      /* add autopattern provides */
      if (!autopattern_id)
	autopattern_id = pool_str2id(pool, "autopattern()", 1);
      s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autopattern_id, s->name, REL_EQ, 1), 0);
      /* add self provides */
      s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0);
      if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0)
	repodata_set_num(data, s2 - pool->solvables, SOLVABLE_INSTALLTIME, num);
      if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0)
	repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num);
      if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0)
	repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str);
      if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0)
	repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str);
      /* fill in stuff from provides */
      prvp = repo->idarraydata + s->provides;
      while ((prv = *prvp++) != 0)            /* go through all provides */
	{
	  Id evr = 0;
	  if (ISRELDEP(prv))
	    {
	      Reldep *rd = GETRELDEP(pool, prv);
	      if (rd->flags != REL_EQ)
	        continue;
	      prv = rd->name;
	      evr = rd->evr;
	    }
	  pn = pool_id2str(pool, prv);
	  if (strncmp("pattern-", pn, 8) != 0)
	    continue;
	  newname = 0;
	  if (evr)
	    {
	      newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0);
	      unescape(newname);
	    }
	  if (!strncmp(pn, "pattern-category(", 17) && evr)
	    {
	      char lang[9];
	      int l = strlen(pn);
	      Id langtag;
	      if (l > 17 + 9 || pn[l - 1] != ')')
		continue;
              strncpy(lang, pn + 17, l - 17 - 1);
	      lang[l - 17 - 1] = 0;
	      langtag = SOLVABLE_CATEGORY;
	      if (*lang && strcmp(lang, "en") != 0)
		langtag = pool_id2langid(pool, SOLVABLE_CATEGORY, lang, 1);
	      repodata_set_str(data, s2 - pool->solvables, langtag, newname);
	    }
	  else if (!strcmp(pn, "pattern-includes()") && evr)
	    repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_INCLUDES, pool_tmpjoin(pool, "pattern:", newname, 0));
	  else if (!strcmp(pn, "pattern-extends()") && evr)
	    repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_EXTENDS, pool_tmpjoin(pool, "pattern:", newname, 0));
	  else if (!strcmp(pn, "pattern-icon()") && evr)
	    repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ICON, newname);
	  else if (!strcmp(pn, "pattern-order()") && evr)
	    repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ORDER, newname);
	  else if (!strcmp(pn, "pattern-visible()") && !evr)
	    repodata_set_void(data, s2 - pool->solvables, SOLVABLE_ISVISIBLE);
	}
    }
  queue_free(&q);
  queue_free(&q2);
  if (data && !(flags & REPO_NO_INTERNALIZE))
    repodata_internalize(data);
  else if (!data && !(flags & REPO_NO_INTERNALIZE))
    repo_internalize(repo);
  return 0;
}
示例#11
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;
}
示例#12
0
static void
findfileconflicts_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, dhx;

  idx = cbdata->idx;

  if (!info->dirlen)
    return;
  dp = fn + info->dirlen;
  if (info->diridx != cbdata->lastdiridx)
    {
      cbdata->lastdiridx = info->diridx;
      cbdata->lastdirhash = strnhash(fn, dp - fn);
    }
  dhx = cbdata->lastdirhash;
  /* this mirrors the "if (!hx) hx = strlen(fn) + 1" in finddirs_cb */
  if (!isindirmap(cbdata, dhx ? dhx : dp - fn + 1))
    return;
  hx = strhash_cont(dp, dhx);
  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 : idx);
      if (++cbdata->cflmapused * 2 > cbdata->cflmapn)
	cbdata->cflmap = growhash(cbdata->cflmap, &cbdata->cflmapn);
      return;
    }
  oidx = cbdata->cflmap[2 * h + 1];
  if (oidx < 0)
    {
      int i;
      if (isdir)
	{
	  /* both are directories. delay the conflict, keep oidx in slot */
          queue_push2(&cbdata->lookat_dir, hx, idx);
	  return;
	}
      oidx = ~oidx;
      /* 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)
	  {
	    queue_push2(&cbdata->lookat, hx, cbdata->lookat_dir.elements[i + 1]);
	    queue_push2(&cbdata->lookat, 0, 0);
	  }
    }
  else if (oidx == idx)
    return;	/* no conflicts with ourself, please */
  queue_push2(&cbdata->lookat, hx, oidx);
  queue_push2(&cbdata->lookat, 0, 0);
  queue_push2(&cbdata->lookat, hx, idx);
  queue_push2(&cbdata->lookat, 0, 0);
}
示例#13
0
文件: solv.c 项目: myungjoo/libsolv
int
main(int argc, char **argv)
{
  Pool *pool;
  Repo *commandlinerepo = 0;
  Id *commandlinepkgs = 0;
  Id p;
  struct repoinfo *repoinfos, installedrepoinfo;
  int nrepoinfos = 0;
  int mainmode = 0, mode = 0;
  int i, newpkgs;
  Queue job, checkq;
  Solver *solv = 0;
  Transaction *trans;
  FILE **newpkgsfps;
  Queue repofilter;
  Queue kindfilter;
  Queue archfilter;
  int archfilter_src = 0;
  int cleandeps = 0;
  int forcebest = 0;
  char *rootdir = 0;
  char *keyname = 0;
  int keyname_depstr = 0;
  int debuglevel = 0;
  int answer, acnt = 0;

  argc--;
  argv++;
  while (argc && !strcmp(argv[0], "-d"))
    {
      debuglevel++;
      argc--;
      argv++;
    }
  if (!argv[0])
    usage(1);
  if (!strcmp(argv[0], "install") || !strcmp(argv[0], "in"))
    {
      mainmode = MODE_INSTALL;
      mode = SOLVER_INSTALL;
    }
#if defined(SUSE) || defined(FEDORA)
  else if (!strcmp(argv[0], "patch"))
    {
      mainmode = MODE_PATCH;
      mode = SOLVER_INSTALL;
    }
#endif
  else if (!strcmp(argv[0], "erase") || !strcmp(argv[0], "rm"))
    {
      mainmode = MODE_ERASE;
      mode = SOLVER_ERASE;
    }
  else if (!strcmp(argv[0], "list") || !strcmp(argv[0], "ls"))
    {
      mainmode = MODE_LIST;
      mode = 0;
    }
  else if (!strcmp(argv[0], "info"))
    {
      mainmode = MODE_INFO;
      mode = 0;
    }
  else if (!strcmp(argv[0], "search") || !strcmp(argv[0], "se"))
    {
      mainmode = MODE_SEARCH;
      mode = 0;
    }
  else if (!strcmp(argv[0], "verify"))
    {
      mainmode = MODE_VERIFY;
      mode = SOLVER_VERIFY;
    }
  else if (!strcmp(argv[0], "update") || !strcmp(argv[0], "up"))
    {
      mainmode = MODE_UPDATE;
      mode = SOLVER_UPDATE;
    }
  else if (!strcmp(argv[0], "dist-upgrade") || !strcmp(argv[0], "dup"))
    {
      mainmode = MODE_DISTUPGRADE;
      mode = SOLVER_DISTUPGRADE;
    }
  else if (!strcmp(argv[0], "repos") || !strcmp(argv[0], "repolist") || !strcmp(argv[0], "lr"))
    {
      mainmode = MODE_REPOLIST;
      mode = 0;
    }
  else
    usage(1);

  for (;;)
    {
      if (argc > 2 && !strcmp(argv[1], "--root"))
	{
	  rootdir = argv[2];
	  argc -= 2;
	  argv += 2;
	}
      else if (argc > 1 && !strcmp(argv[1], "--clean"))
	{
	  cleandeps = 1;
	  argc--;
	  argv++;
	}
      else if (argc > 1 && !strcmp(argv[1], "--best"))
	{
	  forcebest = 1;
	  argc--;
	  argv++;
	}
      else if (argc > 1 && !strcmp(argv[1], "--depstr"))
	{
	  keyname_depstr = 1;
	  argc--;
	  argv++;
	}
      else if (argc > 2 && !strcmp(argv[1], "--keyname"))
	{
	  keyname = argv[2];
	  argc -= 2;
	  argv += 2;
	}
      else
	break;
    }

  set_userhome();
  pool = pool_create();
  pool_set_rootdir(pool, rootdir);

#if 0
  {
    const char *langs[] = {"de_DE", "de", "en"};
    pool_set_languages(pool, langs, sizeof(langs)/sizeof(*langs));
  }
#endif

  pool_setloadcallback(pool, load_stub, 0);
#ifdef SUSE
  pool->nscallback = nscallback;
#endif
  if (debuglevel)
    pool_setdebuglevel(pool, debuglevel);
  setarch(pool);
  pool_set_flag(pool, POOL_FLAG_ADDFILEPROVIDESFILTERED, 1);
  repoinfos = read_repoinfos(pool, &nrepoinfos);
  sort_repoinfos(repoinfos, nrepoinfos);

  if (mainmode == MODE_REPOLIST)
    {
      int j = 1;
      for (i = 0; i < nrepoinfos; i++)
	{
	  struct repoinfo *cinfo = repoinfos + i;
	  if (!cinfo->enabled)
	    continue;
	  printf("%d: %-20s %s (prio %d)\n", j++, cinfo->alias, cinfo->name, cinfo->priority);
	}
      exit(0);
    }
  memset(&installedrepoinfo, 0, sizeof(installedrepoinfo));
  if (!read_installed_repo(&installedrepoinfo, pool))
    exit(1);
  read_repos(pool, repoinfos, nrepoinfos);

  /* setup filters */
  queue_init(&repofilter);
  queue_init(&kindfilter);
  queue_init(&archfilter);
  while (argc > 1)
    {
      if (!strcmp(argv[1], "-i"))
	{
	  queue_push2(&repofilter, SOLVER_SOLVABLE_REPO | SOLVER_SETREPO, pool->installed->repoid);
	  argc--;
	  argv++;
	}
      else if (argc > 2 && (!strcmp(argv[1], "-r") || !strcmp(argv[1], "--repo")))
	{
	  Id repoid = find_repo(argv[2], pool, repoinfos, nrepoinfos);
	  if (!repoid)
	    {
	      fprintf(stderr, "%s: no such repo\n", argv[2]);
	      exit(1);
	    }
	  /* SETVENDOR is actually wrong but useful */
	  queue_push2(&repofilter, SOLVER_SOLVABLE_REPO | SOLVER_SETREPO | SOLVER_SETVENDOR, repoid);
	  argc -= 2;
	  argv += 2;
	}
      else if (argc > 2 && !strcmp(argv[1], "--arch"))
	{
	  if (!strcmp(argv[2], "src") || !strcmp(argv[2], "nosrc"))
	    archfilter_src = 1;
	  queue_push2(&archfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, pool_str2id(pool, argv[2], 1), REL_ARCH, 1));
	  argc -= 2;
	  argv += 2;
	}
      else if (argc > 2 && (!strcmp(argv[1], "-t") || !strcmp(argv[1], "--type")))
	{
	  const char *kind = argv[2];
	  if (!strcmp(kind, "srcpackage"))
	    {
	      /* hey! should use --arch! */
	      queue_push2(&archfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, ARCH_SRC, REL_ARCH, 1));
	      archfilter_src = 1;
	      argc -= 2;
	      argv += 2;
	      continue;
	    }
	  if (!strcmp(kind, "package"))
	    kind = "";
	  if (!strcmp(kind, "all"))
	    queue_push2(&kindfilter, SOLVER_SOLVABLE_ALL, 0);
	  else
	    queue_push2(&kindfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, pool_str2id(pool, kind, 1), REL_KIND, 1));
	  argc -= 2;
	  argv += 2;
	}
      else
	break;
    }

  if (mainmode == MODE_SEARCH)
    {
      Queue sel, q;
      Dataiterator di;
      if (argc != 2)
	usage(1);
      pool_createwhatprovides(pool);
      queue_init(&sel);
      dataiterator_init(&di, pool, 0, 0, 0, argv[1], SEARCH_SUBSTRING|SEARCH_NOCASE);
      dataiterator_set_keyname(&di, SOLVABLE_NAME);
      dataiterator_set_search(&di, 0, 0);
      while (dataiterator_step(&di))
	queue_push2(&sel, SOLVER_SOLVABLE, di.solvid);
      dataiterator_set_keyname(&di, SOLVABLE_SUMMARY);
      dataiterator_set_search(&di, 0, 0);
      while (dataiterator_step(&di))
	queue_push2(&sel, SOLVER_SOLVABLE, di.solvid);
      dataiterator_set_keyname(&di, SOLVABLE_DESCRIPTION);
      dataiterator_set_search(&di, 0, 0);
      while (dataiterator_step(&di))
	queue_push2(&sel, SOLVER_SOLVABLE, di.solvid);
      dataiterator_free(&di);
      if (repofilter.count)
	selection_filter(pool, &sel, &repofilter);
	
      queue_init(&q);
      selection_solvables(pool, &sel, &q);
      queue_free(&sel);
      for (i = 0; i < q.count; i++)
	{
	  Solvable *s = pool_id2solvable(pool, q.elements[i]);
	  printf("  - %s [%s]: %s\n", pool_solvable2str(pool, s), s->repo->name, solvable_lookup_str(s, SOLVABLE_SUMMARY));
	}
      queue_free(&q);
      exit(0);
    }

  /* process command line packages */
  if (mainmode == MODE_LIST || mainmode == MODE_INFO || mainmode == MODE_INSTALL)
    {
      for (i = 1; i < argc; i++)
	{
	  if (!is_cmdline_package((const char *)argv[i]))
	    continue;
	  if (access(argv[i], R_OK))
	    {
	      perror(argv[i]);
	      exit(1);
	    }
	  if (!commandlinepkgs)
	    commandlinepkgs = solv_calloc(argc, sizeof(Id));
	  if (!commandlinerepo)
	    commandlinerepo = repo_create(pool, "@commandline");
	  p = add_cmdline_package(commandlinerepo, (const char *)argv[i]);
	  if (!p)
	    {
	      fprintf(stderr, "could not add '%s'\n", argv[i]);
	      exit(1);
	    }
	  commandlinepkgs[i] = p;
	}
      if (commandlinerepo)
	repo_internalize(commandlinerepo);
    }

#if defined(ENABLE_RPMDB)
  if (pool->disttype == DISTTYPE_RPM)
    addfileprovides(pool);
#endif
#ifdef SUSE
  add_autopackages(pool);
#endif
  pool_createwhatprovides(pool);

  if (keyname)
    keyname = solv_dupjoin("solvable:", keyname, 0);
  queue_init(&job);
  for (i = 1; i < argc; i++)
    {
      Queue job2;
      int flags, rflags;

      if (commandlinepkgs && commandlinepkgs[i])
	{
	  queue_push2(&job, SOLVER_SOLVABLE, commandlinepkgs[i]);
	  continue;
	}
      queue_init(&job2);
      flags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_GLOB;
      flags |= SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL;
      if (kindfilter.count)
	flags |= SELECTION_SKIP_KIND;
      if (mode == MODE_LIST || archfilter_src)
	flags |= SELECTION_WITH_SOURCE;
      if (argv[i][0] == '/')
	flags |= SELECTION_FILELIST | (mode == MODE_ERASE ? SELECTION_INSTALLED_ONLY : 0);
      if (!keyname)
        rflags = selection_make(pool, &job2, argv[i], flags);
      else
	{
	  if (keyname_depstr)
	    flags |= SELECTION_MATCH_DEPSTR;
          rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0);
	}
      if (repofilter.count)
	selection_filter(pool, &job2, &repofilter);
      if (archfilter.count)
	selection_filter(pool, &job2, &archfilter);
      if (kindfilter.count)
	selection_filter(pool, &job2, &kindfilter);
      if (!job2.count)
	{
	  flags |= SELECTION_NOCASE;
	  if (!keyname)
            rflags = selection_make(pool, &job2, argv[i], flags);
	  else
	    rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0);
	  if (repofilter.count)
	    selection_filter(pool, &job2, &repofilter);
	  if (archfilter.count)
	    selection_filter(pool, &job2, &archfilter);
	  if (kindfilter.count)
	    selection_filter(pool, &job2, &kindfilter);
	  if (job2.count)
	    printf("[ignoring case for '%s']\n", argv[i]);
	}
      if (!job2.count)
	{
	  fprintf(stderr, "nothing matches '%s'\n", argv[i]);
	  exit(1);
	}
      if (rflags & SELECTION_FILELIST)
        printf("[using file list match for '%s']\n", argv[i]);
      if (rflags & SELECTION_PROVIDES)
	printf("[using capability match for '%s']\n", argv[i]);
      queue_insertn(&job, job.count, job2.count, job2.elements);
      queue_free(&job2);
    }
  keyname = solv_free(keyname);

  if (!job.count && (mainmode == MODE_UPDATE || mainmode == MODE_DISTUPGRADE || mainmode == MODE_VERIFY || repofilter.count || archfilter.count || kindfilter.count))
    {
      queue_push2(&job, SOLVER_SOLVABLE_ALL, 0);
      if (repofilter.count)
	selection_filter(pool, &job, &repofilter);
      if (archfilter.count)
	selection_filter(pool, &job, &archfilter);
      if (kindfilter.count)
	selection_filter(pool, &job, &kindfilter);
    }
  queue_free(&repofilter);
  queue_free(&archfilter);
  queue_free(&kindfilter);

  if (!job.count && mainmode != MODE_PATCH)
    {
      printf("no package matched\n");
      exit(1);
    }

  if (mainmode == MODE_LIST || mainmode == MODE_INFO)
    {
      /* list mode, no solver needed */
      Queue q;
      queue_init(&q);
      for (i = 0; i < job.count; i += 2)
	{
	  int j;
	  queue_empty(&q);
	  pool_job2solvables(pool, &q, job.elements[i], job.elements[i + 1]);
	  for (j = 0; j < q.count; j++)
	    {
	      Solvable *s = pool_id2solvable(pool, q.elements[j]);
	      if (mainmode == MODE_INFO)
		{
		  const char *str;
		  printf("Name:        %s\n", pool_solvable2str(pool, s));
		  printf("Repo:        %s\n", s->repo->name);
		  printf("Summary:     %s\n", solvable_lookup_str(s, SOLVABLE_SUMMARY));
		  str = solvable_lookup_str(s, SOLVABLE_URL);
		  if (str)
		    printf("Url:         %s\n", str);
		  str = solvable_lookup_str(s, SOLVABLE_LICENSE);
		  if (str)
		    printf("License:     %s\n", str);
		  printf("Description:\n%s\n", solvable_lookup_str(s, SOLVABLE_DESCRIPTION));
		  printf("\n");
		}
	      else
		{
#if 1
		  const char *sum = solvable_lookup_str_lang(s, SOLVABLE_SUMMARY, "de", 1);
#else
		  const char *sum = solvable_lookup_str_poollang(s, SOLVABLE_SUMMARY);
#endif
		  printf("  - %s [%s]\n", pool_solvable2str(pool, s), s->repo->name);
		  if (sum)
		    printf("    %s\n", sum);
		}
	    }
	}
      queue_free(&q);
      queue_free(&job);
      pool_free(pool);
      free_repoinfos(repoinfos, nrepoinfos);
      solv_free(commandlinepkgs);
      exit(0);
    }

#if defined(SUSE) || defined(FEDORA)
  if (mainmode == MODE_PATCH)
    add_patchjobs(pool, &job);
#endif

  // add mode
  for (i = 0; i < job.count; i += 2)
    {
      job.elements[i] |= mode;
      if (mode == SOLVER_UPDATE && pool_isemptyupdatejob(pool, job.elements[i], job.elements[i + 1]))
	job.elements[i] ^= SOLVER_UPDATE ^ SOLVER_INSTALL;
      if (cleandeps)
        job.elements[i] |= SOLVER_CLEANDEPS;
      if (forcebest)
        job.elements[i] |= SOLVER_FORCEBEST;
    }

  // multiversion test
  // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae", 1));
  // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-base", 1));
  // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-extra", 1));
#if 0
  queue_push2(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1));
  queue_push2(&job, SOLVER_ERASE|SOLVER_CLEANDEPS|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1));
#endif

rerunsolver:
  solv = solver_create(pool);
  solver_set_flag(solv, SOLVER_FLAG_SPLITPROVIDES, 1);
#ifdef FEDORA
  solver_set_flag(solv, SOLVER_FLAG_ALLOW_VENDORCHANGE, 1);
#endif
  if (mainmode == MODE_ERASE)
    solver_set_flag(solv, SOLVER_FLAG_ALLOW_UNINSTALL, 1);	/* don't nag */
  solver_set_flag(solv, SOLVER_FLAG_BEST_OBEY_POLICY, 1);

  for (;;)
    {
      Id problem, solution;
      int pcnt, scnt;

      if (!solver_solve(solv, &job))
	break;
      pcnt = solver_problem_count(solv);
      printf("Found %d problems:\n", pcnt);
      for (problem = 1; problem <= pcnt; problem++)
	{
	  int take = 0;
	  printf("Problem %d/%d:\n", problem, pcnt);
	  solver_printprobleminfo(solv, problem);
	  printf("\n");
	  scnt = solver_solution_count(solv, problem);
	  for (solution = 1; solution <= scnt; solution++)
	    {
	      printf("Solution %d:\n", solution);
	      solver_printsolution(solv, problem, solution);
	      printf("\n");
	    }
	  for (;;)
	    {
	      char inbuf[128], *ip;
	      printf("Please choose a solution: ");
	      fflush(stdout);
	      *inbuf = 0;
	      if (!(ip = fgets(inbuf, sizeof(inbuf), stdin)))
		{
		  printf("Abort.\n");
		  exit(1);
		}
	      while (*ip == ' ' || *ip == '\t')
		ip++;
	      if (*ip >= '0' && *ip <= '9')
		{
		  take = atoi(ip);
		  if (take >= 1 && take <= scnt)
		    break;
		}
	      if (*ip == 's')
		{
		  take = 0;
		  break;
		}
	      if (*ip == 'q')
		{
		  printf("Abort.\n");
		  exit(1);
		}
	    }
	  if (!take)
	    continue;
	  solver_take_solution(solv, problem, take, &job);
	}
    }

  trans = solver_create_transaction(solv);
  if (!trans->steps.count)
    {
      printf("Nothing to do.\n");
      transaction_free(trans);
      solver_free(solv);
      queue_free(&job);
      pool_free(pool);
      free_repoinfos(repoinfos, nrepoinfos);
      solv_free(commandlinepkgs);
      exit(1);
    }

  /* display transaction to the user and ask for confirmation */
  printf("\n");
  printf("Transaction summary:\n\n");
  transaction_print(trans);
#if defined(SUSE)
  showdiskusagechanges(trans);
#endif
  printf("install size change: %d K\n", transaction_calc_installsizechange(trans));
  printf("\n");

  acnt = solver_alternatives_count(solv);
  if (acnt)
    {
      if (acnt == 1)
        printf("Have one alternative:\n");
      else
        printf("Have %d alternatives:\n", acnt);
      for (i = 1; i <= acnt; i++)
	{
	  Id id, from;
	  int atype = solver_get_alternative(solv, i, &id, &from, 0, 0, 0);
	  printf("  - %s\n", solver_alternative2str(solv, atype, id, from));
	}
      printf("\n");
      answer = yesno("OK to continue (y/n/a)? ", 'a');
    }
  else
    answer = yesno("OK to continue (y/n)? ", 0);
  if (answer == 'a')
    {
      Queue choicesq;
      Queue answerq;
      Id id, from, chosen;
      int j;

      queue_init(&choicesq);
      queue_init(&answerq);
      for (i = 1; i <= acnt; i++)
	{
	  int atype = solver_get_alternative(solv, i, &id, &from, &chosen, &choicesq, 0);
	  printf("\n%s\n", solver_alternative2str(solv, atype, id, from));
	  for (j = 0; j < choicesq.count; j++)
	    {
	      Id p = choicesq.elements[j];
	      if (p < 0)
		p = -p;
	      queue_push(&answerq, p);
	      printf("%6d: %s\n", answerq.count, pool_solvid2str(pool, p));
	    }
	}
      queue_free(&choicesq);
      printf("\n");
      for (;;)
	{
	  char inbuf[128], *ip;
	  int neg = 0;
	  printf("OK to continue (y/n), or number to change alternative: ");
	  fflush(stdout);
	  *inbuf = 0;
	  if (!(ip = fgets(inbuf, sizeof(inbuf), stdin)))
	    {
	      printf("Abort.\n");
	      exit(1);
	    }
	  while (*ip == ' ' || *ip == '\t')
	    ip++;
	  if (*ip == '-' && ip[1] >= '0' && ip[1] <= '9')
	    {
	      neg = 1;
	      ip++;
	    }
	  if (*ip >= '0' && *ip <= '9')
	    {
	      int take = atoi(ip);
	      if (take > 0 && take <= answerq.count)
		{
		  Id p = answerq.elements[take - 1];
		  queue_free(&answerq);
		  queue_push2(&job, (neg ? SOLVER_DISFAVOR : SOLVER_FAVOR) | SOLVER_SOLVABLE_NAME, pool->solvables[p].name);
		  solver_free(solv);
		  solv = 0;
		  goto rerunsolver;
		  break;
		}
	    }
	  if (*ip == 'n' || *ip == 'y')
	    {
	      answer = *ip == 'n' ? 0 : *ip;
	      break;
	    }
	}
      queue_free(&answerq);
    }
  if (!answer)
    {
      printf("Abort.\n");
      transaction_free(trans);
      solver_free(solv);
      queue_free(&job);
      pool_free(pool);
      free_repoinfos(repoinfos, nrepoinfos);
      solv_free(commandlinepkgs);
      exit(1);
    }

  /* download all new packages */
  queue_init(&checkq);
  newpkgs = transaction_installedresult(trans, &checkq);
  newpkgsfps = 0;
  if (newpkgs)
    {
      int downloadsize = 0;
      for (i = 0; i < newpkgs; i++)
	{
	  Solvable *s;

	  p = checkq.elements[i];
	  s = pool_id2solvable(pool, p);
	  downloadsize += solvable_lookup_sizek(s, SOLVABLE_DOWNLOADSIZE, 0);
	}
      printf("Downloading %d packages, %d K\n", newpkgs, downloadsize);
      newpkgsfps = solv_calloc(newpkgs, sizeof(*newpkgsfps));
      for (i = 0; i < newpkgs; i++)
	{
	  const char *loc;
	  Solvable *s;
	  struct repoinfo *cinfo;

	  p = checkq.elements[i];
	  s = pool_id2solvable(pool, p);
	  if (s->repo == commandlinerepo)
	    {
	      loc = solvable_lookup_location(s, 0);
	      if (!loc)
		continue;
	      if (!(newpkgsfps[i] = fopen(loc, "r")))
		{
		  perror(loc);
		  exit(1);
		}
	      putchar('.');
	      continue;
	    }
	  cinfo = s->repo->appdata;
	  if (!cinfo || cinfo->type == TYPE_INSTALLED)
	    {
	      printf("%s: no repository information\n", s->repo->name);
	      exit(1);
	    }
	  loc = solvable_lookup_location(s, 0);
	  if (!loc)
	     continue;	/* pseudo package? */
#if defined(ENABLE_RPMDB)
	  if (pool->installed && pool->installed->nsolvables)
	    {
	      if ((newpkgsfps[i] = trydeltadownload(s, loc)) != 0)
		{
		  putchar('d');
		  fflush(stdout);
		  continue;		/* delta worked! */
		}
	    }
#endif
	  if ((newpkgsfps[i] = downloadpackage(s, loc)) == 0)
	    {
	      printf("\n%s: %s not found in repository\n", s->repo->name, loc);
	      exit(1);
	    }
	  putchar('.');
	  fflush(stdout);
	}
      putchar('\n');
    }

#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA) || defined(MANDRIVA) || defined(MAGEIA))
  /* check for file conflicts */
  if (newpkgs)
    {
      Queue conflicts;
      queue_init(&conflicts);
      if (checkfileconflicts(pool, &checkq, newpkgs, newpkgsfps, &conflicts))
	{
	  if (yesno("Re-run solver (y/n/q)? ", 0))
	    {
	      for (i = 0; i < newpkgs; i++)
		if (newpkgsfps[i])
		  fclose(newpkgsfps[i]);
	      newpkgsfps = solv_free(newpkgsfps);
	      solver_free(solv);
	      solv = 0;
	      pool_add_fileconflicts_deps(pool, &conflicts);
	      queue_free(&conflicts);
	      goto rerunsolver;
	    }
	}
      queue_free(&conflicts);
    }
#endif

  /* and finally commit the transaction */
  printf("Committing transaction:\n\n");
  transaction_order(trans, 0);
  for (i = 0; i < trans->steps.count; i++)
    {
      int j;
      FILE *fp;
      Id type;

      p = trans->steps.elements[i];
      type = transaction_type(trans, p, SOLVER_TRANSACTION_RPM_ONLY);
      switch(type)
	{
	case SOLVER_TRANSACTION_ERASE:
	  printf("erase %s\n", pool_solvid2str(pool, p));
	  commit_transactionelement(pool, type, p, 0);
	  break;
	case SOLVER_TRANSACTION_INSTALL:
	case SOLVER_TRANSACTION_MULTIINSTALL:
	  printf("install %s\n", pool_solvid2str(pool, p));
	  for (j = 0; j < newpkgs; j++)
	    if (checkq.elements[j] == p)
	      break;
	  fp = j < newpkgs ? newpkgsfps[j] : 0;
	  if (!fp)
	    continue;
	  commit_transactionelement(pool, type, p, fp);
	  fclose(fp);
	  newpkgsfps[j] = 0;
	  break;
	default:
	  break;
	}
    }

  for (i = 0; i < newpkgs; i++)
    if (newpkgsfps[i])
      fclose(newpkgsfps[i]);
  solv_free(newpkgsfps);
  queue_free(&checkq);
  transaction_free(trans);
  solver_free(solv);
  queue_free(&job);
  pool_free(pool);
  free_repoinfos(repoinfos, nrepoinfos);
  solv_free(commandlinepkgs);
  exit(0);
}
示例#14
0
int
repo_add_autopattern(Repo *repo, int flags)
{
  Pool *pool = repo->pool;
  Repodata *data = 0;
  Solvable *s, *s2;
  Queue patq, patq2;
  Queue prdq, prdq2;
  Id p;
  Id pattern_id, product_id;
  Id autopattern_id = 0, autoproduct_id = 0;
  int i, j;

  queue_init(&patq);
  queue_init(&patq2);
  queue_init(&prdq);
  queue_init(&prdq2);

  pattern_id = pool_str2id(pool, "pattern()", 9);
  product_id = pool_str2id(pool, "product()", 9);
  FOR_REPO_SOLVABLES(repo, p, s)
    {
      const char *n = pool_id2str(pool, s->name);
      if (*n == 'p')
	{
	  if (!strncmp("pattern:", n, 8))
	    {
	      queue_push(&patq, p);
	      continue;
	    }
	  else if (!strncmp("product:", n, 8))
	    {
	      queue_push(&prdq, p);
	      continue;
	    }
	}
      if (s->provides)
	{
	  Id prv, *prvp = repo->idarraydata + s->provides;
	  while ((prv = *prvp++) != 0)            /* go through all provides */
	    if (ISRELDEP(prv))
	      {
	        Reldep *rd = GETRELDEP(pool, prv);
		if (rd->flags != REL_EQ)
		  continue;
		if (rd->name == pattern_id)
		  {
		    queue_push2(&patq2, p, rd->evr);
		    break;
		  }
		if (rd->name == product_id)
		  {
		    queue_push2(&prdq2, p, rd->evr);
		    break;
		  }
	      }
	}
    }
  for (i = 0; i < patq2.count; i += 2)
    {
      const char *pn = 0;
      char *newname;
      Id name, prv, *prvp;
      const char *str;
      unsigned long long num;

      s = pool->solvables + patq2.elements[i];
      /* construct new name */
      newname = pool_tmpjoin(pool, "pattern:", pool_id2str(pool, patq2.elements[i + 1]), 0);
      unescape(newname);
      name = pool_str2id(pool, newname, 0);
      if (name)
	{
	  /* check if we already have that pattern */
	  for (j = 0; j < patq.count; j++)
	    {
	      s2 = pool->solvables + patq.elements[j];
	      if (s2->name == name && s2->arch == s->arch && s2->evr == s->evr)
		break;
	    }
	  if (j < patq.count)
	    continue;	/* yes, do not add again */
	}
      /* new pattern */
      if (!name)
        name = pool_str2id(pool, newname, 1);
      if (!data)
	{
	  repo_internalize(repo);	/* to make that the lookups work */
	  data = repo_add_repodata(repo, flags);
	}
      s2 = pool_id2solvable(pool, repo_add_solvable(repo));
      s = pool->solvables + patq2.elements[i];	/* re-calc pointer */
      s2->name = name;
      s2->arch = s->arch;
      s2->evr = s->evr;
      s2->vendor = s->vendor;
      /* add link requires */
      s2->requires = repo_addid_dep(repo, s2->requires, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1) , 0);
      /* add autopattern provides */
      if (!autopattern_id)
	autopattern_id = pool_str2id(pool, "autopattern()", 1);
      s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autopattern_id, s->name, REL_EQ, 1), 0);
      /* add self provides */
      s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0);
      if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0)
	repodata_set_num(data, s2 - pool->solvables, SOLVABLE_INSTALLTIME, num);
      if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0)
	repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num);
      if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0)
	repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str);
      if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0)
	repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str);
      /* fill in stuff from provides */
      prvp = repo->idarraydata + s->provides;
      while ((prv = *prvp++) != 0)            /* go through all provides */
	{
	  Id evr = 0;
	  if (ISRELDEP(prv))
	    {
	      Reldep *rd = GETRELDEP(pool, prv);
	      if (rd->flags != REL_EQ)
	        continue;
	      prv = rd->name;
	      evr = rd->evr;
	    }
	  pn = pool_id2str(pool, prv);
	  if (strncmp("pattern-", pn, 8) != 0)
	    continue;
	  newname = 0;
	  if (evr)
	    {
	      newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0);
	      unescape(newname);
	    }
	  if (!strncmp(pn, "pattern-category(", 17) && evr)
	    {
	      char lang[9];
	      int l = strlen(pn);
	      Id langtag;
	      if (l > 17 + 9 || pn[l - 1] != ')')
		continue;
              strncpy(lang, pn + 17, l - 17 - 1);
	      lang[l - 17 - 1] = 0;
	      langtag = SOLVABLE_CATEGORY;
	      if (*lang && strcmp(lang, "en") != 0)
		langtag = pool_id2langid(pool, SOLVABLE_CATEGORY, lang, 1);
	      if (newname[solv_validutf8(newname)] == 0)
	        repodata_set_str(data, s2 - pool->solvables, langtag, newname);
	      else
		{
		  char *ustr = solv_latin1toutf8(newname);
	          repodata_set_str(data, s2 - pool->solvables, langtag, ustr);
		  solv_free(ustr);
		}
	    }
	  else if (!strcmp(pn, "pattern-includes()") && evr)
	    repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_INCLUDES, pool_tmpjoin(pool, "pattern:", newname, 0));
	  else if (!strcmp(pn, "pattern-extends()") && evr)
	    repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_EXTENDS, pool_tmpjoin(pool, "pattern:", newname, 0));
	  else if (!strcmp(pn, "pattern-icon()") && evr)
	    repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ICON, newname);
	  else if (!strcmp(pn, "pattern-order()") && evr)
	    repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ORDER, newname);
	  else if (!strcmp(pn, "pattern-visible()") && !evr)
	    repodata_set_void(data, s2 - pool->solvables, SOLVABLE_ISVISIBLE);
	}
    }
  queue_free(&patq);
  queue_free(&patq2);

  if (repo == pool->installed)
    queue_empty(&prdq2);	/* no auto products for installed repos */

  for (i = 0; i < prdq2.count; i += 2)
    {
      const char *pn = 0;
      char *newname;
      Id name, evr = 0, prv, *prvp;
      const char *str;
      unsigned long long num;

      s = pool->solvables + prdq2.elements[i];
      /* construct new name */
      newname = pool_tmpjoin(pool, "product(", pool_id2str(pool, prdq2.elements[i + 1]), ")");
      unescape(newname);
      name = pool_str2id(pool, newname, 0);
      if (!name)
	continue;	/* must have it in provides! */
      prvp = repo->idarraydata + s->provides;
      while ((prv = *prvp++) != 0)            /* go through all provides */
	{
	  if (ISRELDEP(prv))
	    {
	      Reldep *rd = GETRELDEP(pool, prv);
	      if (rd->name == name && rd->flags == REL_EQ)
		{
		  evr = rd->evr;
		  break;
		}
	    }
	}
      if (!prv)
	continue;	/* not found in provides */
      newname = pool_tmpjoin(pool, "product:", pool_id2str(pool, prdq2.elements[i + 1]), 0);
      unescape(newname);
      name = pool_str2id(pool, newname, 0);
      if (name)
	{
	  /* check if we already have that product */
	  for (j = 0; j < prdq.count; j++)
	    {
	      s2 = pool->solvables + prdq.elements[j];
	      if (s2->name == name && s2->arch == s->arch && s2->evr == evr)
		break;
	    }
	  if (j < prdq.count)
	    continue;	/* yes, do not add again */
	}
      /* new product */
      if (!name)
        name = pool_str2id(pool, newname, 1);
      if (!data)
	{
	  repo_internalize(repo);	/* to make that the lookups work */
	  data = repo_add_repodata(repo, flags);
	}
      if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0)
	continue;		/* eek, not for installed packages, please! */
      s2 = pool_id2solvable(pool, repo_add_solvable(repo));
      s = pool->solvables + prdq2.elements[i];	/* re-calc pointer */
      s2->name = name;
      s2->arch = s->arch;
      s2->evr = evr;
      s2->vendor = s->vendor;
      /* add link requires */
      s2->requires = repo_addid_dep(repo, s2->requires, prv, 0);
      if (!autoproduct_id)
	autoproduct_id = pool_str2id(pool, "autoproduct()", 1);
      s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autoproduct_id, s->name, REL_EQ, 1), 0);
      /* add self provides */
      s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0);
      if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0)
	repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num);
      if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0)
	repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str);
      if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0)
	repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str);
      if ((str = solvable_lookup_str(s, SOLVABLE_DISTRIBUTION)) != 0)
	repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DISTRIBUTION, str);
      /* fill in stuff from provides */
      prvp = repo->idarraydata + s->provides;
      while ((prv = *prvp++) != 0)            /* go through all provides */
	{
	  Id evr = 0;
	  if (ISRELDEP(prv))
	    {
	      Reldep *rd = GETRELDEP(pool, prv);
	      if (rd->flags != REL_EQ)
	        continue;
	      prv = rd->name;
	      evr = rd->evr;
	    }
	  pn = pool_id2str(pool, prv);
	  if (strncmp("product-", pn, 8) != 0)
	    continue;
	  newname = 0;
	  if (evr)
	    {
	      newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0);
	      unescape(newname);
	    }
	  if (!strcmp(pn, "product-label()") && evr)
	    repodata_set_str(data, s2 - pool->solvables, PRODUCT_SHORTLABEL, newname);
	  else if (!strcmp(pn, "product-type()") && evr)
	    repodata_set_str(data, s2 - pool->solvables, PRODUCT_TYPE, newname);
	  else if (!strcmp(pn, "product-cpeid()") && evr)
	    repodata_set_str(data, s2 - pool->solvables, SOLVABLE_CPEID, newname);
	  else if (!strcmp(pn, "product-flags()") && evr)
	    repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_FLAGS, newname);
	  else if (!strcmp(pn, "product-updates-repoid()") && evr)
	    repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_UPDATES_REPOID, newname);
	  else if (!strncmp(pn, "product-url(", 12) && evr && pn[12] && pn[13] && strlen(pn + 12) < 32)
	    {
	      char type[34];
	      strcpy(type, pn + 12);
	      type[strlen(type) - 1] = 0;	/* closing ) */
	      repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_URL_TYPE, type);
	      repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_URL, newname);
	    }
	}
    }
  queue_free(&prdq);
  queue_free(&prdq2);

  if (data && !(flags & REPO_NO_INTERNALIZE))
    repodata_internalize(data);
  else if (!data && !(flags & REPO_NO_INTERNALIZE))
    repo_internalize(repo);
  return 0;
}
示例#15
0
/*
 * returns:
 *   0: no blocks
 *   1: matches all
 *  -1: at least one block
 */
static int
normalize_dep(Pool *pool, Id dep, Queue *bq, int flags)
{
  int bqcnt = bq->count;
  int bqcnt2;
  int todnf = flags & CPLXDEPS_TODNF ? 1 : 0;
  Id p, dp;

#ifdef CPLXDEBUG
  printf("normalize_dep %s todnf:%d\n", pool_dep2str(pool, dep), todnf);
#endif
  if (pool_is_complex_dep(pool, dep))
    {
      Reldep *rd = GETRELDEP(pool, dep);
      if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_COND)
	{
	  int rdflags = rd->flags;
	  Id name = rd->name;
	  Id evr = rd->evr;
	  int r, mode;
	  
          if (rdflags == REL_COND)
	    {
	      /* check for relly complex ELSE case */
	      if (ISRELDEP(evr))
		{
		  Reldep *rd2 = GETRELDEP(pool, evr);
		  if (rd2->flags == REL_ELSE)
		    {
		      int r2;
		      /* really complex case */
		      if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_1)
			{
			  /* A OR ~B */
			  rdflags = REL_COND;
			  evr = rd2->name;
			}
		      else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_2)
			{
			  /* C OR B */
			  rdflags = REL_OR;
			  name = rd2->evr;
			  evr = rd2->name;
			}
		      else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_1)
			{
			  /* A AND B */
			  rdflags = REL_AND;
			  evr = rd2->name;
			}
		      else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_2)
			{
			  /* A AND C */
			  rdflags = REL_AND;
			  evr = rd2->evr;
			}
		      else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_3)
			{
			  /* C AND ~B */
			  rdflags = REL_ELSE;
			  name = rd2->evr;
			  evr = rd2->name;
			}
		      else if (!todnf)
			{
			  /* we want AND: A IF (B ELSE C) -> (A OR ~B) AND (C OR B) */
			  r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_1);
			  if (r == 0 && (flags & CPLXDEPS_DONTFIX) == 0)
			    return 0;
			  r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_2);
			  if (r2 == 0 && (flags & CPLXDEPS_DONTFIX) == 0)
			    {
			      queue_truncate(bq, bqcnt);
			      return 0;
			    }
			  if (r == -1 || r2 == -1)
			    return -1;
			  return r == 1 || r2 == 1 ? 1 : 0;
			}
		      else
			{
			  int r2, r3;
			  /* we want OR: A IF (B ELSE C) -> (A AND B) OR (A AND C) OR (~B AND C) */
			  r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_1);
			  if (r == 1)
			    return 1;
			  r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_2);
			  if (r2 == 1)
			    {
			      queue_truncate(bq, bqcnt);
			      return 1;
			    }
			  r3 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_3);
			  if (r3 == 1)
			    {
			      queue_truncate(bq, bqcnt);
			      return 1;
			    }
			  if (r == -1 || r2 == -1 || r3 == -1)
			    return -1;
			  return 0;
			}
		    }
		}
	    }
	  mode = rdflags == REL_AND || rdflags == REL_ELSE ? 0 : 1;

	  /* get blocks of first argument */
	  r = normalize_dep(pool, name, bq, flags);
	  if (r == 0)
	    {
	      if (rdflags == REL_ELSE)
		return 0;
	      if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) == 0)
		return 0;
	      if (rdflags == REL_COND)
		{
		  r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
		  return invert_depblocks(pool, bq, bqcnt, r);	/* invert block for COND */
		}
	      return normalize_dep(pool, evr, bq, flags);
	    }
	  if (r == 1)
	    {
	      if (rdflags == REL_ELSE)
		{
		  r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX);
		  return invert_depblocks(pool, bq, bqcnt, r);	/* invert block for ELSE */
		}
	      if (rdflags == REL_OR || rdflags == REL_COND)
		return 1;
	      return normalize_dep(pool, evr, bq, flags);
	    }

	  /* get blocks of second argument */
	  bqcnt2 = bq->count;
	  /* COND is OR with NEG on evr block, so we invert the todnf flag in that case */
	  r = normalize_dep(pool, evr, bq, rdflags == REL_COND || rdflags == REL_ELSE ? ((flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX) : flags);
	  if (rdflags == REL_COND || rdflags == REL_ELSE)
	    r = invert_depblocks(pool, bq, bqcnt2, r);	/* invert 2nd block */
	  if (r == 0)
	    {
	      if (rdflags == REL_OR)
		return -1;
	      if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) != 0)
		return -1;
	      queue_truncate(bq, bqcnt);
	      return 0;
	    }
	  if (r == 1)
	    {
	      if (rdflags == REL_COND || rdflags == REL_OR)
		{
		  queue_truncate(bq, bqcnt);
		  return 1;
		}
	      return -1;
	    }
	  if (mode == todnf)
	    {
	      /* simple case: just join em. nothing more to do here. */
#ifdef CPLXDEBUG
	      printf("SIMPLE JOIN %d %d %d\n", bqcnt, bqcnt2, bq->count);
#endif
	      return -1;
	    }
	  else
	    {
	      /* complex case: mix em */
	      int i, j, bqcnt3;
#ifdef CPLXDEBUG
	      printf("COMPLEX JOIN %d %d %d\n", bqcnt, bqcnt2, bq->count);
#endif
	      bqcnt2 = expand_simpledeps(pool, bq, bqcnt, bqcnt2);
	      bqcnt3 = bq->count;
	      for (i = bqcnt; i < bqcnt2; i++)
		{
		  for (j = bqcnt2; j < bqcnt3; j++)
		    {
		      int a, b;
		      int bqcnt4 = bq->count;
		      int k = i;

		      /* mix i block with j block, both blocks are sorted */
		      while (bq->elements[k] && bq->elements[j])
			{
			  if (bq->elements[k] < bq->elements[j])
			    queue_push(bq, bq->elements[k++]);
			  else
			    {
			      if (bq->elements[k] == bq->elements[j])
				k++;
			      queue_push(bq, bq->elements[j++]);
			    }
			}
		      while (bq->elements[j])
			queue_push(bq, bq->elements[j++]);
		      while (bq->elements[k])
			queue_push(bq, bq->elements[k++]);

		      /* block is finished, check for A + -A */
		      for (a = bqcnt4, b = bq->count - 1; a < b; )
			{
			  if (-bq->elements[a] == bq->elements[b])
			    break;
			  if (-bq->elements[a] > bq->elements[b])
			    a++;
			  else
			    b--;
			}
		      if (a < b)
			queue_truncate(bq, bqcnt4);	/* ignore this block */
		      else
			queue_push(bq, 0);	/* finish block */
		    }
		  /* advance to next block */
		  while (bq->elements[i])
		    i++;
		}
	      i = -1;
	      if (bqcnt3 == bq->count)	/* ignored all blocks? */
		i = todnf ? 0 : 1;
	      queue_deleten(bq, bqcnt, bqcnt3 - bqcnt);
	      return i;
	    }
	}
    }

  /* fallback case: just use package list */
  dp = pool_whatprovides(pool, dep);
  if (dp <= 2 || !pool->whatprovidesdata[dp])
    return dp == 2 ? 1 : 0;
  if (pool->whatprovidesdata[dp] == SYSTEMSOLVABLE)
    return 1;
  bqcnt = bq->count;
  if ((flags & CPLXDEPS_NAME) != 0)
    {
      while ((p = pool->whatprovidesdata[dp++]) != 0)
	{
	  if (!pool_match_nevr(pool, pool->solvables + p, dep))
	    continue;
	  queue_push(bq, p);
	  if (todnf)
	    queue_push(bq, 0);
	}
    }
  else if (todnf)
    {
      while ((p = pool->whatprovidesdata[dp++]) != 0)
        queue_push2(bq, p, 0);
    }
  else
    queue_push2(bq, pool->nsolvables, dp);	/* not yet expanded marker + offset */
  if (bq->count == bqcnt)
    return 0;	/* no provider */
  if (!todnf)
    queue_push(bq, 0);	/* finish block */
  return -1;
}