예제 #1
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);

  if (repo == pool->installed)
    flags |= ADD_NO_AUTOPRODUCTS;	/* no auto products for installed repos */

  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)
		  {
		    const char *evrstr = pool_id2str(pool, rd->evr);
		    if (evrstr[0] == '.')	/* hack to allow provides that do not create a pattern */
		      continue;
		    if (patq2.count && patq2.elements[patq2.count - 2] == p)
		      {
			/* hmm, two provides. choose by evrstr */
			if (strcmp(evrstr, pool_id2str(pool, patq2.elements[patq2.count - 1])) >= 0)
			  continue;
			patq2.count -= 2;
		      }
		    queue_push2(&patq2, p, rd->evr);
		  }
		if (rd->name == product_id)
		  {
		    const char *evrstr = pool_id2str(pool, rd->evr);
		    if (prdq2.count && prdq2.elements[prdq2.count - 2] == p)
		      {
			/* hmm, two provides. choose by evrstr */
			if (strcmp(evrstr, pool_id2str(pool, prdq2.elements[prdq2.count - 1])) >= 0)
			  continue;
			prdq2.count -= 2;
		      }
		    queue_push2(&prdq2, p, rd->evr);
		  }
	      }
	}
    }
  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 ((flags & ADD_NO_AUTOPRODUCTS) != 0)
    queue_empty(&prdq2);

  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)
	    {
	      Id h = repodata_new_handle(data);
	      repodata_set_str(data, h, PRODUCT_UPDATES_REPOID, newname);
	      repodata_add_flexarray(data, s2 - pool->solvables, PRODUCT_UPDATES, h);
	    }
	  else if (!strcmp(pn, "product-endoflife()") && evr)
	    {
	      time_t t = datestr2timestamp(newname);
	      if (t)
		repodata_set_num(data, s2 - pool->solvables, PRODUCT_ENDOFLIFE, t);
	    }
	  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;
}
예제 #2
0
static void XMLCALL
startElement(void *userData, const char *name, const char **atts)
{
  struct parsedata *pd = userData;
  Pool *pool = pd->pool;
  Solvable *solvable = pd->solvable;
  struct stateswitch *sw;
  /*const char *str; */

#if 0
  fprintf(stderr, "start: [%d]%s\n", pd->state, name);
#endif
  if (pd->depth != pd->statedepth)
    {
      pd->depth++;
      return;
    }

  pd->depth++;
  if (!pd->swtab[pd->state])
    return;
  for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)  /* find name in statetable */
    if (!strcmp(sw->ename, name))
      break;

  if (sw->from != pd->state)
    {
#if 0
      fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state);
      exit( 1 );
#endif
      return;
    }
  pd->state = sw->to;
  pd->docontent = sw->docontent;
  pd->statedepth = pd->depth;
  pd->lcontent = 0;
  *pd->content = 0;

  switch(pd->state)
    {
    case STATE_START:
      break;
    case STATE_UPDATES:
      break;
      /*
       * <update from="*****@*****.**"
       *         status="stable"
       *         type="bugfix" (enhancement, security)
       *         version="1.4">
       */
    case STATE_UPDATE:
      {
	const char *from = 0, *type = 0, *version = 0;
	for (; *atts; atts += 2)
	  {
	    if (!strcmp(*atts, "from"))
	      from = atts[1];
	    else if (!strcmp(*atts, "type"))
	      type = atts[1];
	    else if (!strcmp(*atts, "version"))
	      version = atts[1];
	  }


	solvable = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
	pd->datanum = pd->solvable - pool->solvables;

	solvable->vendor = pool_str2id(pool, from, 1);
	solvable->evr = pool_str2id(pool, version, 1);
	solvable->arch = ARCH_NOARCH;
	if (type)
	  repodata_set_str(pd->data, pd->datanum, SOLVABLE_PATCHCATEGORY, type);
        pd->buildtime = (time_t)0;
      }
      break;
      /* <id>FEDORA-2007-4594</id> */
    case STATE_ID:
      break;
      /* <title>imlib-1.9.15-6.fc8</title> */
    case STATE_TITLE:
      break;
      /* <release>Fedora 8</release> */
    case STATE_RELEASE:
      break;
      /*  <issued date="2008-03-21 21:36:55"/>
      */
    case STATE_ISSUED:
    case STATE_UPDATED:
      {
	const char *date = 0;
	for (; *atts; atts += 2)
	  {
	    if (!strcmp(*atts, "date"))
	      date = atts[1];
	  }
	if (date)
	  {
	    time_t t = datestr2timestamp(date);
	    if (t && t > pd->buildtime)
              pd->buildtime = t;
	  }
      }
      break;
    case STATE_REFERENCES:
      break;
      /*  <reference href="https://bugzilla.redhat.com/show_bug.cgi?id=330471"
       *             id="330471"
       *             title="LDAP schema file missing for dhcpd"
       *             type="bugzilla"/>
       */
    case STATE_REFERENCE:
      {
        const char *href = 0, *id = 0, *title = 0, *type = 0;
	Id handle;
	for (; *atts; atts += 2)
	  {
	    if (!strcmp(*atts, "href"))
	      href = atts[1];
	    else if (!strcmp(*atts, "id"))
	      id = atts[1];
	    else if (!strcmp(*atts, "title"))
	      title = atts[1];
	    else if (!strcmp(*atts, "type"))
	      type = atts[1];
	  }
	handle = repodata_new_handle(pd->data);
	if (href)
	  repodata_set_str(pd->data, handle, UPDATE_REFERENCE_HREF, href);
	if (id)
	  repodata_set_str(pd->data, handle, UPDATE_REFERENCE_ID, id);
	if (title)
	  repodata_set_str(pd->data, handle, UPDATE_REFERENCE_TITLE, title);
	if (type)
	  repodata_set_poolstr(pd->data, handle, UPDATE_REFERENCE_TYPE, type);
	repodata_add_flexarray(pd->data, pd->datanum, UPDATE_REFERENCE, handle);
      }
      break;
      /* <description>This update ...</description> */
    case STATE_DESCRIPTION:
      break;
      /* <message type="confirm">This update ...</message> */
    case STATE_MESSAGE:
      break;
    case STATE_PKGLIST:
      break;
      /* <collection short="F8" */
    case STATE_COLLECTION:
      break;
      /* <name>Fedora 8</name> */
    case STATE_NAME:
      break;
      /*   <package arch="ppc64" name="imlib-debuginfo" release="6.fc8"
       *            src="http://download.fedoraproject.org/pub/fedora/linux/updates/8/ppc64/imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm"
       *            version="1.9.15">
       *
       *
       * -> patch.conflicts: {name} < {version}.{release}
       */
    case STATE_PACKAGE:
      {
	const char *arch = 0, *name = 0;
	Id evr = makeevr_atts(pool, pd, atts); /* parse "epoch", "version", "release" */
	Id n, a = 0;
	Id rel_id;

	for (; *atts; atts += 2)
	  {
	    if (!strcmp(*atts, "arch"))
	      arch = atts[1];
	    else if (!strcmp(*atts, "name"))
	      name = atts[1];
	  }
	/* generated Id for name */
	n = pool_str2id(pool, name, 1);
	rel_id = n;
	if (arch)
	  {
	    /*  generate Id for arch and combine with name */
	    a = pool_str2id(pool, arch, 1);
	    rel_id = pool_rel2id(pool, n, a, REL_ARCH, 1);
	  }
	rel_id = pool_rel2id(pool, rel_id, evr, REL_LT, 1);

	solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, rel_id, 0);

        /* who needs the collection anyway? */
        pd->collhandle = repodata_new_handle(pd->data);
	repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_NAME, n);
	repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_EVR, evr);
	repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_ARCH, a);
        break;
      }
      /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */
      /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */
    case STATE_FILENAME:
      break;
      /* <reboot_suggested>True</reboot_suggested> */
    case STATE_REBOOT:
      break;
      /* <restart_suggested>True</restart_suggested> */
    case STATE_RESTART:
      break;
      /* <relogin_suggested>True</relogin_suggested> */
    case STATE_RELOGIN:
      break;
    default:
      break;
    }
  return;
}
예제 #3
0
static void XMLCALL
endElement(void *userData, const char *name)
{
  struct parsedata *pd = userData;
  Solvable *s = pd->solvable;

#if 0
  fprintf(stderr, "end: [%d]%s\n", pd->state, name);
#endif
  if (pd->depth != pd->statedepth)
    {
      pd->depth--;
#if 0
      fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth);
#endif
      return;
    }

  pd->depth--;
  pd->statedepth--;

  switch (pd->state)
    {
    case STATE_PRODUCT:
      /* product done, finish solvable */
      if (pd->ctime)
        repodata_set_num(pd->data, pd->handle, SOLVABLE_INSTALLTIME, pd->ctime);

      if (pd->basename)
        repodata_set_str(pd->data, pd->handle, PRODUCT_REFERENCEFILE, pd->basename);

      /* this is where <productsdir>/baseproduct points to */
      if (pd->currentproduct == pd->baseproduct)
	repodata_set_str(pd->data, pd->handle, PRODUCT_TYPE, "base");

      if (pd->tmprel)
	{
	  if (pd->tmpvers)
	    s->evr = makeevr(pd->pool, join2(&pd->jd, pd->tmpvers, "-", pd->tmprel));
	  else
	    {
	      fprintf(stderr, "Seen <release> but no <version>\n");
	    }
	}
      else if (pd->tmpvers)
	s->evr = makeevr(pd->pool, pd->tmpvers); /* just version, no release */
      pd->tmpvers = solv_free((void *)pd->tmpvers);
      pd->tmprel = solv_free((void *)pd->tmprel);
      if (!s->arch)
	s->arch = ARCH_NOARCH;
      if (!s->evr)
	s->evr = ID_EMPTY;
      if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
	s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0);
      pd->solvable = 0;
      break;
    case STATE_VENDOR:
      s->vendor = pool_str2id(pd->pool, pd->content, 1);
      break;
    case STATE_NAME:
      s->name = pool_str2id(pd->pool, join2(&pd->jd, "product", ":", pd->content), 1);
      break;
    case STATE_VERSION:
      pd->tmpvers = solv_strdup(pd->content);
      break;
    case STATE_RELEASE:
      pd->tmprel = solv_strdup(pd->content);
      break;
    case STATE_ARCH:
      s->arch = pool_str2id(pd->pool, pd->content, 1);
      break;
    case STATE_PRODUCTLINE:
      repodata_set_str(pd->data, pd->handle, PRODUCT_PRODUCTLINE, pd->content);
    break;
    case STATE_UPDATEREPOKEY:
      /** obsolete **/
      break;
    case STATE_SUMMARY:
      repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), pd->content);
      break;
    case STATE_SHORTSUMMARY:
      repodata_set_str(pd->data, pd->handle, PRODUCT_SHORTLABEL, pd->content);
      break;
    case STATE_DESCRIPTION:
      repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), pd->content);
      break;
    case STATE_URL:
      if (pd->urltype)
        {
          repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content);
          repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, pd->urltype);
        }
      break;
    case STATE_TARGET:
      repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_TARGET, pd->content);
      break;
    case STATE_REGRELEASE:
      repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_RELEASE, pd->content);
      break;
    case STATE_CPEID:
      if (*pd->content)
        repodata_set_str(pd->data, pd->handle, SOLVABLE_CPEID, pd->content);
      break;
    case STATE_ENDOFLIFE:
      if (*pd->content)
	{
	  time_t t = datestr2timestamp(pd->content);
	  if (t)
	    repodata_set_num(pd->data, pd->handle, PRODUCT_ENDOFLIFE, (unsigned long long)t);
	}
      break;
    default:
      break;
    }

  pd->state = pd->sbtab[pd->state];
  pd->docontent = 0;

#if 0
      fprintf(stderr, "end: [%s] -> %d\n", name, pd->state);
#endif
}