|
Packit |
54873f |
/*
|
|
Packit |
54873f |
* Copyright (c) 2007, Novell Inc.
|
|
Packit |
54873f |
*
|
|
Packit |
54873f |
* This program is licensed under the BSD license, read LICENSE.BSD
|
|
Packit |
54873f |
* for further information
|
|
Packit |
54873f |
*/
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/*
|
|
Packit |
54873f |
* repo_helix.c
|
|
Packit |
54873f |
*
|
|
Packit |
54873f |
* Parse 'helix' XML representation
|
|
Packit |
54873f |
* and create 'repo'
|
|
Packit |
54873f |
*
|
|
Packit |
54873f |
* A bit of history: "Helix Code" was the name of the company that
|
|
Packit |
54873f |
* wrote Red Carpet. The company was later renamed to Ximian.
|
|
Packit |
54873f |
* The Red Carpet solver was merged into the ZYPP project, the
|
|
Packit |
54873f |
* library used both by ZENworks and YaST for package management.
|
|
Packit |
54873f |
* Red Carpet came with solver testcases in its own repository
|
|
Packit |
54873f |
* format, the 'helix' format.
|
|
Packit |
54873f |
*
|
|
Packit |
54873f |
*/
|
|
Packit |
54873f |
|
|
Packit |
54873f |
#include <sys/types.h>
|
|
Packit |
54873f |
#include <stdio.h>
|
|
Packit |
54873f |
#include <stdlib.h>
|
|
Packit |
54873f |
#include <string.h>
|
|
Packit |
54873f |
|
|
Packit |
54873f |
#include "queue.h"
|
|
Packit |
54873f |
#include "solv_xmlparser.h"
|
|
Packit |
54873f |
#include "repo_helix.h"
|
|
Packit |
54873f |
#include "evr.h"
|
|
Packit |
54873f |
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* XML parser states */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
enum state {
|
|
Packit |
54873f |
STATE_START,
|
|
Packit |
54873f |
STATE_CHANNEL,
|
|
Packit |
54873f |
STATE_SUBCHANNEL,
|
|
Packit |
54873f |
STATE_PACKAGE,
|
|
Packit |
54873f |
STATE_NAME,
|
|
Packit |
54873f |
STATE_VENDOR,
|
|
Packit |
54873f |
STATE_BUILDTIME,
|
|
Packit |
54873f |
STATE_HISTORY,
|
|
Packit |
54873f |
STATE_UPDATE,
|
|
Packit |
54873f |
STATE_EPOCH,
|
|
Packit |
54873f |
STATE_VERSION,
|
|
Packit |
54873f |
STATE_RELEASE,
|
|
Packit |
54873f |
STATE_ARCH,
|
|
Packit |
54873f |
STATE_PROVIDES,
|
|
Packit |
54873f |
STATE_PROVIDESENTRY,
|
|
Packit |
54873f |
STATE_REQUIRES,
|
|
Packit |
54873f |
STATE_REQUIRESENTRY,
|
|
Packit |
54873f |
STATE_PREREQUIRES,
|
|
Packit |
54873f |
STATE_PREREQUIRESENTRY,
|
|
Packit |
54873f |
STATE_OBSOLETES,
|
|
Packit |
54873f |
STATE_OBSOLETESENTRY,
|
|
Packit |
54873f |
STATE_CONFLICTS,
|
|
Packit |
54873f |
STATE_CONFLICTSENTRY,
|
|
Packit |
54873f |
STATE_RECOMMENDS,
|
|
Packit |
54873f |
STATE_RECOMMENDSENTRY,
|
|
Packit |
54873f |
STATE_SUPPLEMENTS,
|
|
Packit |
54873f |
STATE_SUPPLEMENTSENTRY,
|
|
Packit |
54873f |
STATE_SUGGESTS,
|
|
Packit |
54873f |
STATE_SUGGESTSENTRY,
|
|
Packit |
54873f |
STATE_ENHANCES,
|
|
Packit |
54873f |
STATE_ENHANCESENTRY,
|
|
Packit |
54873f |
STATE_FRESHENS,
|
|
Packit |
54873f |
STATE_FRESHENSENTRY,
|
|
Packit |
54873f |
|
|
Packit |
54873f |
STATE_SELECTTION,
|
|
Packit |
54873f |
STATE_PATTERN,
|
|
Packit |
54873f |
STATE_ATOM,
|
|
Packit |
54873f |
STATE_PATCH,
|
|
Packit |
54873f |
STATE_PRODUCT,
|
|
Packit |
54873f |
|
|
Packit |
54873f |
NUMSTATES
|
|
Packit |
54873f |
};
|
|
Packit |
54873f |
|
|
Packit |
54873f |
static struct solv_xmlparser_element stateswitches[] = {
|
|
Packit |
54873f |
{ STATE_START, "channel", STATE_CHANNEL, 0 },
|
|
Packit |
54873f |
{ STATE_CHANNEL, "subchannel", STATE_SUBCHANNEL, 0 },
|
|
Packit |
54873f |
{ STATE_SUBCHANNEL, "package", STATE_PACKAGE, 0 },
|
|
Packit |
54873f |
{ STATE_SUBCHANNEL, "srcpackage", STATE_PACKAGE, 0 },
|
|
Packit |
54873f |
{ STATE_SUBCHANNEL, "selection", STATE_PACKAGE, 0 },
|
|
Packit |
54873f |
{ STATE_SUBCHANNEL, "pattern", STATE_PACKAGE, 0 },
|
|
Packit |
54873f |
{ STATE_SUBCHANNEL, "atom", STATE_PACKAGE, 0 },
|
|
Packit |
54873f |
{ STATE_SUBCHANNEL, "patch", STATE_PACKAGE, 0 },
|
|
Packit |
54873f |
{ STATE_SUBCHANNEL, "product", STATE_PACKAGE, 0 },
|
|
Packit |
54873f |
{ STATE_SUBCHANNEL, "application", STATE_PACKAGE, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "name", STATE_NAME, 1 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "vendor", STATE_VENDOR, 1 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "buildtime", STATE_BUILDTIME, 1 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "epoch", STATE_EPOCH, 1 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "version", STATE_VERSION, 1 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "release", STATE_RELEASE, 1 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "arch", STATE_ARCH, 1 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "history", STATE_HISTORY, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "provides", STATE_PROVIDES, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "requires", STATE_REQUIRES, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "prerequires", STATE_PREREQUIRES, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "obsoletes", STATE_OBSOLETES , 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "conflicts", STATE_CONFLICTS , 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "recommends" , STATE_RECOMMENDS , 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "supplements", STATE_SUPPLEMENTS, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "suggests", STATE_SUGGESTS, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "enhances", STATE_ENHANCES, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "freshens", STATE_FRESHENS, 0 },
|
|
Packit |
54873f |
{ STATE_PACKAGE, "deps", STATE_PACKAGE, 0 }, /* ignore deps element */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
{ STATE_HISTORY, "update", STATE_UPDATE, 0 },
|
|
Packit |
54873f |
{ STATE_UPDATE, "epoch", STATE_EPOCH, 1 },
|
|
Packit |
54873f |
{ STATE_UPDATE, "version", STATE_VERSION, 1 },
|
|
Packit |
54873f |
{ STATE_UPDATE, "release", STATE_RELEASE, 1 },
|
|
Packit |
54873f |
{ STATE_UPDATE, "arch", STATE_ARCH, 1 },
|
|
Packit |
54873f |
|
|
Packit |
54873f |
{ STATE_PROVIDES, "dep", STATE_PROVIDESENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_REQUIRES, "dep", STATE_REQUIRESENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_PREREQUIRES, "dep", STATE_PREREQUIRESENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_OBSOLETES, "dep", STATE_OBSOLETESENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_CONFLICTS, "dep", STATE_CONFLICTSENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_RECOMMENDS, "dep", STATE_RECOMMENDSENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_SUPPLEMENTS, "dep", STATE_SUPPLEMENTSENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_SUGGESTS, "dep", STATE_SUGGESTSENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_ENHANCES, "dep", STATE_ENHANCESENTRY, 0 },
|
|
Packit |
54873f |
{ STATE_FRESHENS, "dep", STATE_FRESHENSENTRY, 0 },
|
|
Packit |
54873f |
{ NUMSTATES }
|
|
Packit |
54873f |
|
|
Packit |
54873f |
};
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/*
|
|
Packit |
54873f |
* parser data
|
|
Packit |
54873f |
*/
|
|
Packit |
54873f |
|
|
Packit |
54873f |
struct parsedata {
|
|
Packit |
54873f |
int ret;
|
|
Packit |
54873f |
/* repo data */
|
|
Packit |
54873f |
Pool *pool; /* current pool */
|
|
Packit |
54873f |
Repo *repo; /* current repo */
|
|
Packit |
54873f |
Repodata *data; /* current repo data */
|
|
Packit |
54873f |
Solvable *solvable; /* current solvable */
|
|
Packit |
54873f |
Offset freshens; /* current freshens vector */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* package data */
|
|
Packit |
54873f |
int srcpackage; /* is srcpackage element */
|
|
Packit |
54873f |
int epoch; /* epoch (as offset into evrspace) */
|
|
Packit |
54873f |
int version; /* version (as offset into evrspace) */
|
|
Packit |
54873f |
int release; /* release (as offset into evrspace) */
|
|
Packit |
54873f |
char *evrspace; /* buffer for evr */
|
|
Packit |
54873f |
int aevrspace; /* actual buffer space */
|
|
Packit |
54873f |
int levrspace; /* actual evr length */
|
|
Packit |
54873f |
char *kind;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
struct solv_xmlparser xmlp;
|
|
Packit |
54873f |
};
|
|
Packit |
54873f |
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/*------------------------------------------------------------------*/
|
|
Packit |
54873f |
/* E:V-R handling */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* create Id from epoch:version-release */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
static Id
|
|
Packit |
54873f |
evr2id(Pool *pool, struct parsedata *pd, const char *e, const char *v, const char *r)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
char *c, *space;
|
|
Packit |
54873f |
int l;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* treat explitcit 0 as NULL */
|
|
Packit |
54873f |
if (e && (!*e || !strcmp(e, "0")))
|
|
Packit |
54873f |
e = 0;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (v && !e)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
const char *v2;
|
|
Packit |
54873f |
/* scan version for ":" */
|
|
Packit |
54873f |
for (v2 = v; *v2 >= '0' && *v2 <= '9'; v2++) /* skip leading digits */
|
|
Packit |
54873f |
;
|
|
Packit |
54873f |
/* if version contains ":", set epoch to "0" */
|
|
Packit |
54873f |
if (v2 > v && *v2 == ':')
|
|
Packit |
54873f |
e = "0";
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* compute length of Id string */
|
|
Packit |
54873f |
l = 1; /* for the \0 */
|
|
Packit |
54873f |
if (e)
|
|
Packit |
54873f |
l += strlen(e) + 1; /* e: */
|
|
Packit |
54873f |
if (v)
|
|
Packit |
54873f |
l += strlen(v); /* v */
|
|
Packit |
54873f |
if (r)
|
|
Packit |
54873f |
l += strlen(r) + 1; /* -r */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* get content space */
|
|
Packit |
54873f |
c = space = solv_xmlparser_contentspace(&pd->xmlp, l);
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* copy e-v-r */
|
|
Packit |
54873f |
if (e)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
strcpy(c, e);
|
|
Packit |
54873f |
c += strlen(c);
|
|
Packit |
54873f |
*c++ = ':';
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
if (v)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
strcpy(c, v);
|
|
Packit |
54873f |
c += strlen(c);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
if (r)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
*c++ = '-';
|
|
Packit |
54873f |
strcpy(c, r);
|
|
Packit |
54873f |
c += strlen(c);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
*c = 0;
|
|
Packit |
54873f |
/* if nothing inserted, return Id 0 */
|
|
Packit |
54873f |
if (!*space)
|
|
Packit |
54873f |
return 0;
|
|
Packit |
54873f |
#if 0
|
|
Packit |
54873f |
fprintf(stderr, "evr: %s\n", space);
|
|
Packit |
54873f |
#endif
|
|
Packit |
54873f |
/* intern and create */
|
|
Packit |
54873f |
return pool_str2id(pool, space, 1);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* create e:v-r from attributes
|
|
Packit |
54873f |
* atts is array of name,value pairs, NULL at end
|
|
Packit |
54873f |
* even index into atts is name
|
|
Packit |
54873f |
* odd index is value
|
|
Packit |
54873f |
*/
|
|
Packit |
54873f |
static Id
|
|
Packit |
54873f |
evr_atts2id(Pool *pool, struct parsedata *pd, const char **atts)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
const char *e, *v, *r;
|
|
Packit |
54873f |
e = v = r = 0;
|
|
Packit |
54873f |
for (; *atts; atts += 2)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
if (!strcmp(*atts, "epoch"))
|
|
Packit |
54873f |
e = atts[1];
|
|
Packit |
54873f |
else if (!strcmp(*atts, "version"))
|
|
Packit |
54873f |
v = atts[1];
|
|
Packit |
54873f |
else if (!strcmp(*atts, "release"))
|
|
Packit |
54873f |
r = atts[1];
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
return evr2id(pool, pd, e, v, r);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/*------------------------------------------------------------------*/
|
|
Packit |
54873f |
/* rel operator handling */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
struct flagtab {
|
|
Packit |
54873f |
char *from;
|
|
Packit |
54873f |
int to;
|
|
Packit |
54873f |
};
|
|
Packit |
54873f |
|
|
Packit |
54873f |
static struct flagtab flagtab[] = {
|
|
Packit |
54873f |
{ ">", REL_GT },
|
|
Packit |
54873f |
{ "=", REL_EQ },
|
|
Packit |
54873f |
{ ">=", REL_GT|REL_EQ },
|
|
Packit |
54873f |
{ "<", REL_LT },
|
|
Packit |
54873f |
{ "!=", REL_GT|REL_LT },
|
|
Packit |
54873f |
{ "<=", REL_LT|REL_EQ },
|
|
Packit |
54873f |
{ "(any)", REL_LT|REL_EQ|REL_GT },
|
|
Packit |
54873f |
{ "==", REL_EQ },
|
|
Packit |
54873f |
{ "gt", REL_GT },
|
|
Packit |
54873f |
{ "eq", REL_EQ },
|
|
Packit |
54873f |
{ "ge", REL_GT|REL_EQ },
|
|
Packit |
54873f |
{ "lt", REL_LT },
|
|
Packit |
54873f |
{ "ne", REL_GT|REL_LT },
|
|
Packit |
54873f |
{ "le", REL_LT|REL_EQ },
|
|
Packit |
54873f |
{ "gte", REL_GT|REL_EQ },
|
|
Packit |
54873f |
{ "lte", REL_LT|REL_EQ },
|
|
Packit |
54873f |
{ "GT", REL_GT },
|
|
Packit |
54873f |
{ "EQ", REL_EQ },
|
|
Packit |
54873f |
{ "GE", REL_GT|REL_EQ },
|
|
Packit |
54873f |
{ "LT", REL_LT },
|
|
Packit |
54873f |
{ "NE", REL_GT|REL_LT },
|
|
Packit |
54873f |
{ "LE", REL_LT|REL_EQ }
|
|
Packit |
54873f |
};
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/*
|
|
Packit |
54873f |
* process new dependency from parser
|
|
Packit |
54873f |
* olddeps = already collected deps, this defines the 'kind' of dep
|
|
Packit |
54873f |
* atts = array of name,value attributes of dep
|
|
Packit |
54873f |
* isreq == 1 if its a requires
|
|
Packit |
54873f |
*/
|
|
Packit |
54873f |
|
|
Packit |
54873f |
static unsigned int
|
|
Packit |
54873f |
adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts, Id marker)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
Id id, name;
|
|
Packit |
54873f |
const char *n, *f, *k;
|
|
Packit |
54873f |
const char **a;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
n = f = k = NULL;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* loop over name,value pairs */
|
|
Packit |
54873f |
for (a = atts; *a; a += 2)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
if (!strcmp(*a, "name"))
|
|
Packit |
54873f |
n = a[1];
|
|
Packit |
54873f |
if (!strcmp(*a, "kind"))
|
|
Packit |
54873f |
k = a[1];
|
|
Packit |
54873f |
else if (!strcmp(*a, "op"))
|
|
Packit |
54873f |
f = a[1];
|
|
Packit |
54873f |
else if (marker && !strcmp(*a, "pre") && a[1][0] == '1')
|
|
Packit |
54873f |
marker = SOLVABLE_PREREQMARKER;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
if (!n) /* quit if no name found */
|
|
Packit |
54873f |
return olddeps;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* kind, name */
|
|
Packit |
54873f |
if (k && !strcmp(k, "package"))
|
|
Packit |
54873f |
k = NULL; /* package is default */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (k) /* if kind!=package, intern <kind>:<name> */
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
int l = strlen(k) + 1 + strlen(n) + 1;
|
|
Packit |
54873f |
char *space = solv_xmlparser_contentspace(&pd->xmlp, l);
|
|
Packit |
54873f |
sprintf(space, "%s:%s", k, n);
|
|
Packit |
54873f |
name = pool_str2id(pool, space, 1);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
else
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
name = pool_str2id(pool, n, 1); /* package: just intern <name> */
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (f) /* operator ? */
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
/* intern e:v-r */
|
|
Packit |
54873f |
Id evr = evr_atts2id(pool, pd, atts);
|
|
Packit |
54873f |
/* parser operator to flags */
|
|
Packit |
54873f |
int flags;
|
|
Packit |
54873f |
for (flags = 0; flags < sizeof(flagtab)/sizeof(*flagtab); flags++)
|
|
Packit |
54873f |
if (!strcmp(f, flagtab[flags].from))
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
flags = flagtab[flags].to;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
if (flags > 7)
|
|
Packit |
54873f |
flags = 0;
|
|
Packit |
54873f |
/* intern rel */
|
|
Packit |
54873f |
id = pool_rel2id(pool, name, evr, flags, 1);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
else
|
|
Packit |
54873f |
id = name; /* no operator */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* add new dependency to repo */
|
|
Packit |
54873f |
return repo_addid_dep(pd->repo, olddeps, id, marker);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/*----------------------------------------------------------------*/
|
|
Packit |
54873f |
|
|
Packit |
54873f |
static void
|
|
Packit |
54873f |
startElement(struct solv_xmlparser *xmlp, int state, const char *name, const char **atts)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
struct parsedata *pd = xmlp->userdata;
|
|
Packit |
54873f |
Pool *pool = pd->pool;
|
|
Packit |
54873f |
Solvable *s = pd->solvable;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
switch (state)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
|
|
Packit |
54873f |
case STATE_NAME:
|
|
Packit |
54873f |
if (pd->kind) /* if kind is set (non package) */
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
strcpy(xmlp->content, pd->kind);
|
|
Packit |
54873f |
xmlp->lcontent = strlen(xmlp->content);
|
|
Packit |
54873f |
xmlp->content[xmlp->lcontent++] = ':'; /* prefix name with '<kind>:' */
|
|
Packit |
54873f |
xmlp->content[xmlp->lcontent] = 0;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
case STATE_PACKAGE: /* solvable name */
|
|
Packit |
54873f |
pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo));
|
|
Packit |
54873f |
pd->srcpackage = 0;
|
|
Packit |
54873f |
pd->kind = NULL; /* default is (src)package */
|
|
Packit |
54873f |
if (!strcmp(name, "selection"))
|
|
Packit |
54873f |
pd->kind = "selection";
|
|
Packit |
54873f |
else if (!strcmp(name, "pattern"))
|
|
Packit |
54873f |
pd->kind = "pattern";
|
|
Packit |
54873f |
else if (!strcmp(name, "atom"))
|
|
Packit |
54873f |
pd->kind = "atom";
|
|
Packit |
54873f |
else if (!strcmp(name, "product"))
|
|
Packit |
54873f |
pd->kind = "product";
|
|
Packit |
54873f |
else if (!strcmp(name, "patch"))
|
|
Packit |
54873f |
pd->kind = "patch";
|
|
Packit |
54873f |
else if (!strcmp(name, "application"))
|
|
Packit |
54873f |
pd->kind = "application";
|
|
Packit |
54873f |
else if (!strcmp(name, "srcpackage"))
|
|
Packit |
54873f |
pd->srcpackage = 1;
|
|
Packit |
54873f |
pd->levrspace = 1;
|
|
Packit |
54873f |
pd->epoch = 0;
|
|
Packit |
54873f |
pd->version = 0;
|
|
Packit |
54873f |
pd->release = 0;
|
|
Packit |
54873f |
pd->freshens = 0;
|
|
Packit |
54873f |
#if 0
|
|
Packit |
54873f |
fprintf(stderr, "package #%d\n", s - pool->solvables);
|
|
Packit |
54873f |
#endif
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
case STATE_UPDATE:
|
|
Packit |
54873f |
pd->levrspace = 1;
|
|
Packit |
54873f |
pd->epoch = 0;
|
|
Packit |
54873f |
pd->version = 0;
|
|
Packit |
54873f |
pd->release = 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
case STATE_PROVIDES: /* start of provides */
|
|
Packit |
54873f |
s->provides = 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_PROVIDESENTRY: /* entry within provides */
|
|
Packit |
54873f |
s->provides = adddep(pool, pd, s->provides, atts, 0);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_REQUIRESENTRY:
|
|
Packit |
54873f |
s->requires = adddep(pool, pd, s->requires, atts, -SOLVABLE_PREREQMARKER);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_PREREQUIRESENTRY:
|
|
Packit |
54873f |
s->requires = adddep(pool, pd, s->requires, atts, SOLVABLE_PREREQMARKER);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_OBSOLETES:
|
|
Packit |
54873f |
s->obsoletes = 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_OBSOLETESENTRY:
|
|
Packit |
54873f |
s->obsoletes = adddep(pool, pd, s->obsoletes, atts, 0);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_CONFLICTS:
|
|
Packit |
54873f |
s->conflicts = 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_CONFLICTSENTRY:
|
|
Packit |
54873f |
s->conflicts = adddep(pool, pd, s->conflicts, atts, 0);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_RECOMMENDS:
|
|
Packit |
54873f |
s->recommends = 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_RECOMMENDSENTRY:
|
|
Packit |
54873f |
s->recommends = adddep(pool, pd, s->recommends, atts, 0);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_SUPPLEMENTS:
|
|
Packit |
54873f |
s->supplements= 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_SUPPLEMENTSENTRY:
|
|
Packit |
54873f |
s->supplements = adddep(pool, pd, s->supplements, atts, 0);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_SUGGESTS:
|
|
Packit |
54873f |
s->suggests = 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_SUGGESTSENTRY:
|
|
Packit |
54873f |
s->suggests = adddep(pool, pd, s->suggests, atts, 0);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_ENHANCES:
|
|
Packit |
54873f |
s->enhances = 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_ENHANCESENTRY:
|
|
Packit |
54873f |
s->enhances = adddep(pool, pd, s->enhances, atts, 0);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_FRESHENS:
|
|
Packit |
54873f |
pd->freshens = 0;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_FRESHENSENTRY:
|
|
Packit |
54873f |
pd->freshens = adddep(pool, pd, pd->freshens, atts, 0);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
default:
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
static const char *
|
|
Packit |
54873f |
findKernelFlavor(struct parsedata *pd, Solvable *s)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
Pool *pool = pd->pool;
|
|
Packit |
54873f |
Id pid, *pidp;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (s->provides)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
pidp = pd->repo->idarraydata + s->provides;
|
|
Packit |
54873f |
while ((pid = *pidp++) != 0)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
Reldep *prd;
|
|
Packit |
54873f |
const char *depname;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (!ISRELDEP(pid))
|
|
Packit |
54873f |
continue; /* wrong provides name */
|
|
Packit |
54873f |
prd = GETRELDEP(pool, pid);
|
|
Packit |
54873f |
depname = pool_id2str(pool, prd->name);
|
|
Packit |
54873f |
if (!strncmp(depname, "kernel-", 7))
|
|
Packit |
54873f |
return depname + 7;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (s->requires)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
pidp = pd->repo->idarraydata + s->requires;
|
|
Packit |
54873f |
while ((pid = *pidp++) != 0)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
const char *depname;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (!ISRELDEP(pid))
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
depname = pool_id2str(pool, pid);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
else
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
Reldep *prd = GETRELDEP(pool, pid);
|
|
Packit |
54873f |
depname = pool_id2str(pool, prd->name);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
if (!strncmp(depname, "kernel-", 7))
|
|
Packit |
54873f |
return depname + 7;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
return 0;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
|
|
Packit |
54873f |
static void
|
|
Packit |
54873f |
endElement(struct solv_xmlparser *xmlp, int state, char *content)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
struct parsedata *pd = xmlp->userdata;
|
|
Packit |
54873f |
Pool *pool = pd->pool;
|
|
Packit |
54873f |
Solvable *s = pd->solvable;
|
|
Packit |
54873f |
Id evr;
|
|
Packit |
54873f |
unsigned int t = 0;
|
|
Packit |
54873f |
const char *flavor;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
switch (state)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
|
|
Packit |
54873f |
case STATE_PACKAGE: /* package complete */
|
|
Packit |
54873f |
if (pd->srcpackage && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
|
|
Packit |
54873f |
s->arch = ARCH_SRC;
|
|
Packit |
54873f |
if (!s->arch) /* default to "noarch" */
|
|
Packit |
54873f |
s->arch = ARCH_NOARCH;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (!s->evr && pd->version) /* set solvable evr */
|
|
Packit |
54873f |
s->evr = evr2id(pool, pd,
|
|
Packit |
54873f |
pd->epoch ? pd->evrspace + pd->epoch : 0,
|
|
Packit |
54873f |
pd->version ? pd->evrspace + pd->version : 0,
|
|
Packit |
54873f |
pd->release ? pd->evrspace + pd->release : 0);
|
|
Packit |
54873f |
/* ensure self-provides */
|
|
Packit |
54873f |
if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
|
|
Packit |
54873f |
s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
|
|
Packit |
54873f |
repo_rewrite_suse_deps(s, pd->freshens);
|
|
Packit |
54873f |
pd->freshens = 0;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* see bugzilla bnc#190163 */
|
|
Packit |
54873f |
flavor = findKernelFlavor(pd, s);
|
|
Packit |
54873f |
if (flavor)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
char *cflavor = solv_strdup(flavor); /* make pointer safe */
|
|
Packit |
54873f |
|
|
Packit |
54873f |
Id npr;
|
|
Packit |
54873f |
Id pid;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* this is either a kernel package or a kmp */
|
|
Packit |
54873f |
if (s->provides)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
Offset prov = s->provides;
|
|
Packit |
54873f |
npr = 0;
|
|
Packit |
54873f |
while ((pid = pd->repo->idarraydata[prov++]) != 0)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
const char *depname = 0;
|
|
Packit |
54873f |
Reldep *prd = 0;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (ISRELDEP(pid))
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
prd = GETRELDEP(pool, pid);
|
|
Packit |
54873f |
depname = pool_id2str(pool, prd->name);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
else
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
depname = pool_id2str(pool, pid);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (!strncmp(depname, "kernel(", 7) && !strchr(depname, ':'))
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
char newdep[100];
|
|
Packit |
54873f |
snprintf(newdep, sizeof(newdep), "kernel(%s:%s", cflavor, depname + 7);
|
|
Packit |
54873f |
pid = pool_str2id(pool, newdep, 1);
|
|
Packit |
54873f |
if (prd)
|
|
Packit |
54873f |
pid = pool_rel2id(pool, pid, prd->evr, prd->flags, 1);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
npr = repo_addid_dep(pd->repo, npr, pid, 0);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
s->provides = npr;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
#if 1
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (s->requires)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
Offset reqs = s->requires;
|
|
Packit |
54873f |
npr = 0;
|
|
Packit |
54873f |
while ((pid = pd->repo->idarraydata[reqs++]) != 0)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
const char *depname = 0;
|
|
Packit |
54873f |
Reldep *prd = 0;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (ISRELDEP(pid))
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
prd = GETRELDEP(pool, pid);
|
|
Packit |
54873f |
depname = pool_id2str(pool, prd->name);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
else
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
depname = pool_id2str(pool, pid);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (!strncmp(depname, "kernel(", 7) && !strchr(depname, ':'))
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
char newdep[100];
|
|
Packit |
54873f |
snprintf(newdep, sizeof(newdep), "kernel(%s:%s", cflavor, depname + 7);
|
|
Packit |
54873f |
pid = pool_str2id(pool, newdep, 1);
|
|
Packit |
54873f |
if (prd)
|
|
Packit |
54873f |
pid = pool_rel2id(pool, pid, prd->evr, prd->flags, 1);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
npr = repo_addid_dep(pd->repo, npr, pid, 0);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
s->requires = npr;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
#endif
|
|
Packit |
54873f |
free(cflavor);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_NAME:
|
|
Packit |
54873f |
s->name = pool_str2id(pool, content, 1);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_VENDOR:
|
|
Packit |
54873f |
s->vendor = pool_str2id(pool, content, 1);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_BUILDTIME:
|
|
Packit |
54873f |
t = atoi(content);
|
|
Packit |
54873f |
if (t)
|
|
Packit |
54873f |
repodata_set_num(pd->data, s - pool->solvables, SOLVABLE_BUILDTIME, t);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_UPDATE: /* new version, keeping all other metadata */
|
|
Packit |
54873f |
evr = evr2id(pool, pd,
|
|
Packit |
54873f |
pd->epoch ? pd->evrspace + pd->epoch : 0,
|
|
Packit |
54873f |
pd->version ? pd->evrspace + pd->version : 0,
|
|
Packit |
54873f |
pd->release ? pd->evrspace + pd->release : 0);
|
|
Packit |
54873f |
pd->levrspace = 1;
|
|
Packit |
54873f |
pd->epoch = 0;
|
|
Packit |
54873f |
pd->version = 0;
|
|
Packit |
54873f |
pd->release = 0;
|
|
Packit |
54873f |
/* use highest evr */
|
|
Packit |
54873f |
if (!s->evr || pool_evrcmp(pool, s->evr, evr, EVRCMP_COMPARE) <= 0)
|
|
Packit |
54873f |
s->evr = evr;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_EPOCH:
|
|
Packit |
54873f |
case STATE_VERSION:
|
|
Packit |
54873f |
case STATE_RELEASE:
|
|
Packit |
54873f |
/* ensure buffer space */
|
|
Packit |
54873f |
if (xmlp->lcontent + 1 + pd->levrspace > pd->aevrspace)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
pd->aevrspace = xmlp->lcontent + 1 + pd->levrspace + 256;
|
|
Packit |
54873f |
pd->evrspace = (char *)realloc(pd->evrspace, pd->aevrspace);
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
memcpy(pd->evrspace + pd->levrspace, xmlp->content, xmlp->lcontent + 1);
|
|
Packit |
54873f |
if (state == STATE_EPOCH)
|
|
Packit |
54873f |
pd->epoch = pd->levrspace;
|
|
Packit |
54873f |
else if (state == STATE_VERSION)
|
|
Packit |
54873f |
pd->version = pd->levrspace;
|
|
Packit |
54873f |
else
|
|
Packit |
54873f |
pd->release = pd->levrspace;
|
|
Packit |
54873f |
pd->levrspace += xmlp->lcontent + 1;
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
case STATE_ARCH:
|
|
Packit |
54873f |
s->arch = pool_str2id(pool, content, 1);
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
default:
|
|
Packit |
54873f |
break;
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
}
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/*-------------------------------------------------------------------*/
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/*
|
|
Packit |
54873f |
* read 'helix' type xml from fp
|
|
Packit |
54873f |
* add packages to pool/repo
|
|
Packit |
54873f |
*
|
|
Packit |
54873f |
*/
|
|
Packit |
54873f |
|
|
Packit |
54873f |
int
|
|
Packit |
54873f |
repo_add_helix(Repo *repo, FILE *fp, int flags)
|
|
Packit |
54873f |
{
|
|
Packit |
54873f |
Pool *pool = repo->pool;
|
|
Packit |
54873f |
struct parsedata pd;
|
|
Packit |
54873f |
Repodata *data;
|
|
Packit |
54873f |
unsigned int now;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
now = solv_timems(0);
|
|
Packit |
54873f |
data = repo_add_repodata(repo, flags);
|
|
Packit |
54873f |
|
|
Packit |
54873f |
/* prepare parsedata */
|
|
Packit |
54873f |
memset(&pd, 0, sizeof(pd));
|
|
Packit |
54873f |
pd.pool = pool;
|
|
Packit |
54873f |
pd.repo = repo;
|
|
Packit |
54873f |
pd.data = data;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
pd.evrspace = (char *)solv_malloc(256);
|
|
Packit |
54873f |
pd.aevrspace = 256;
|
|
Packit |
54873f |
pd.levrspace = 1;
|
|
Packit |
54873f |
|
|
Packit |
54873f |
solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement);
|
|
Packit |
54873f |
if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK)
|
|
Packit |
54873f |
pd.ret = pool_error(pd.pool, -1, "repo_helix: %s at line %u", pd.xmlp.errstr, pd.xmlp.line);
|
|
Packit |
54873f |
solv_xmlparser_free(&pd.xmlp);
|
|
Packit |
54873f |
|
|
Packit |
54873f |
solv_free(pd.evrspace);
|
|
Packit |
54873f |
|
|
Packit |
54873f |
if (!(flags & REPO_NO_INTERNALIZE))
|
|
Packit |
54873f |
repodata_internalize(data);
|
|
Packit |
54873f |
POOL_DEBUG(SOLV_DEBUG_STATS, "repo_add_helix took %d ms\n", solv_timems(now));
|
|
Packit |
54873f |
POOL_DEBUG(SOLV_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables);
|
|
Packit |
54873f |
POOL_DEBUG(SOLV_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", repodata_memused(data)/1024, repo->idarraysize / (int)(1024/sizeof(Id)));
|
|
Packit |
54873f |
return pd.ret;
|
|
Packit |
54873f |
}
|