mirror of
https://github.com/openSUSE/libsolv.git
synced 2026-02-05 12:45:46 +01:00
375 lines
8.2 KiB
C
375 lines
8.2 KiB
C
/*
|
|
* Copyright (c) 2012, Novell Inc.
|
|
*
|
|
* This program is licensed under the BSD license, read LICENSE.BSD
|
|
* for further information
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
|
|
#include "pool.h"
|
|
#include "repo.h"
|
|
#include "util.h"
|
|
#include "chksum.h"
|
|
#include "solver.h"
|
|
#include "repo_cudf.h"
|
|
|
|
static Id
|
|
parseonedep(Pool *pool, char *p)
|
|
{
|
|
char *n, *ne, *e, *ee;
|
|
Id name, evr;
|
|
int flags;
|
|
|
|
while (*p == ' ' || *p == '\t' || *p == '\n')
|
|
p++;
|
|
if (!*p)
|
|
return 0;
|
|
if (!strcmp(p, "!true"))
|
|
return 0;
|
|
if (!strcmp(p, "!false"))
|
|
return pool_str2id(pool, p, 1);
|
|
n = p;
|
|
/* find end of name */
|
|
while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != '|')
|
|
p++;
|
|
ne = p;
|
|
while (*p == ' ' || *p == '\t' || *p == '\n')
|
|
p++;
|
|
evr = 0;
|
|
flags = 0;
|
|
e = ee = 0;
|
|
if (*p == '>' || *p == '<' || *p == '=' || *p == '!')
|
|
{
|
|
if (*p == '>')
|
|
flags |= REL_GT;
|
|
else if (*p == '=')
|
|
flags |= REL_EQ;
|
|
else if (*p == '<')
|
|
flags |= REL_LT;
|
|
else if (*p == '!')
|
|
flags |= REL_LT | REL_GT | REL_EQ;
|
|
p++;
|
|
if (flags && *p == '=')
|
|
{
|
|
if (p[-1] != '=')
|
|
flags ^= REL_EQ;
|
|
p++;
|
|
}
|
|
while (*p == ' ' || *p == '\t' || *p == '\n')
|
|
p++;
|
|
e = p;
|
|
while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != '|')
|
|
p++;
|
|
ee = p;
|
|
while (*p == ' ' || *p == '\t' || *p == '\n')
|
|
p++;
|
|
}
|
|
name = pool_strn2id(pool, n, ne - n, 1);
|
|
if (e)
|
|
{
|
|
evr = pool_strn2id(pool, e, ee - e, 1);
|
|
name = pool_rel2id(pool, name, evr, flags, 1);
|
|
}
|
|
if (*p == '|')
|
|
{
|
|
Id id = parseonedep(pool, p + 1);
|
|
if (id)
|
|
name = pool_rel2id(pool, name, id, REL_OR, 1);
|
|
}
|
|
return name;
|
|
}
|
|
static unsigned int
|
|
makedeps(Repo *repo, char *deps, unsigned int olddeps, Id marker)
|
|
{
|
|
Pool *pool = repo->pool;
|
|
char *p;
|
|
Id id;
|
|
|
|
while ((p = strchr(deps, ',')) != 0)
|
|
{
|
|
*p = 0;
|
|
olddeps = makedeps(repo, deps, olddeps, marker);
|
|
*p = ',';
|
|
deps = p + 1;
|
|
}
|
|
id = parseonedep(pool, deps);
|
|
if (!id)
|
|
return olddeps;
|
|
return repo_addid_dep(repo, olddeps, id, marker);
|
|
}
|
|
|
|
static Offset
|
|
copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo)
|
|
{
|
|
Id *ida, *from;
|
|
int cc;
|
|
Offset off;
|
|
|
|
if (!fromoff)
|
|
return 0;
|
|
from = fromrepo->idarraydata + fromoff;
|
|
for (ida = from, cc = 0; *ida; ida++, cc++)
|
|
;
|
|
if (cc == 0)
|
|
return 0;
|
|
off = repo_reserve_ids(repo, 0, cc);
|
|
memcpy(repo->idarraydata + off, from, (cc + 1) * sizeof(Id));
|
|
repo->idarraysize += cc + 1;
|
|
return off;
|
|
}
|
|
|
|
static void
|
|
copysolvabledata(Pool *pool, Solvable *s, Repo *repo)
|
|
{
|
|
Repo *srepo = s->repo;
|
|
if (srepo == repo)
|
|
return;
|
|
s->provides = copydeps(pool, repo, s->provides, srepo);
|
|
s->requires = copydeps(pool, repo, s->requires, srepo);
|
|
s->conflicts = copydeps(pool, repo, s->conflicts, srepo);
|
|
s->obsoletes = copydeps(pool, repo, s->obsoletes, srepo);
|
|
s->recommends = copydeps(pool, repo, s->recommends, srepo);
|
|
s->suggests = copydeps(pool, repo, s->suggests, srepo);
|
|
s->supplements = copydeps(pool, repo, s->supplements, srepo);
|
|
s->enhances = copydeps(pool, repo, s->enhances, srepo);
|
|
}
|
|
|
|
#define KEEP_VERSION 1
|
|
#define KEEP_PACKAGE 2
|
|
#define KEEP_FEATURE 3
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
repo_add_cudf(Repo *repo, Repo *installedrepo, FILE *fp, Queue *job, int flags)
|
|
{
|
|
Pool *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;
|
|
pool = xrepo->pool;
|
|
|
|
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)
|
|
s = solvable_free(s, 1);
|
|
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)
|
|
s = solvable_free(s, 1);
|
|
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)
|
|
s = solvable_free(s, 1);
|
|
if (s)
|
|
finishpackage(pool, s, keep, job);
|
|
solv_free(buf);
|
|
return 0;
|
|
}
|
|
|