644 lines
16 KiB
C
644 lines
16 KiB
C
/** \ingroup rpmbuild
|
|
* \file build/reqprov.c
|
|
* Add dependency tags to package header(s).
|
|
*/
|
|
|
|
#include "system.h"
|
|
|
|
#include "rpmbuild.h"
|
|
#include "debug.h"
|
|
|
|
static int
|
|
deps_opt_enabled (void)
|
|
{
|
|
static int enabled = -1;
|
|
|
|
if (enabled == -1)
|
|
enabled = rpmExpandNumeric("%{?_deps_optimization}%{?!_deps_optimization:2}") >= 2;
|
|
|
|
return enabled;
|
|
}
|
|
|
|
static int
|
|
tag_is_reqprov (rpmTag tag)
|
|
{
|
|
switch (tag) {
|
|
case RPMTAG_REQUIREFLAGS:
|
|
case RPMTAG_PROVIDEFLAGS:
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static dep_compare_t
|
|
compare_sense_flags (rpmTag tag, int cmp, int wcmp, rpmsenseFlags a, rpmsenseFlags b)
|
|
{
|
|
if (cmp > 0) {
|
|
/* Aevr > Bevr */
|
|
return -compare_sense_flags (tag, -cmp, -wcmp, b, a);
|
|
} else if (cmp == 0) {
|
|
/* Aevr == Bevr */
|
|
if (a == b) {
|
|
if (wcmp == 0)
|
|
return DEP_EQ;
|
|
else if (wcmp < 0)
|
|
return tag_is_reqprov(tag) ? DEP_ST : DEP_WK;
|
|
else
|
|
return tag_is_reqprov(tag) ? DEP_WK : DEP_ST;
|
|
}
|
|
if (a && ((a & b) == a)) {
|
|
/* b contains a */
|
|
/* LT,LE || EQ,LE || EQ,GE || GT,GE */
|
|
if (wcmp <= 0)
|
|
return (tag == RPMTAG_REQUIREFLAGS) ? DEP_ST : DEP_WK;
|
|
if (a == RPMSENSE_EQUAL)
|
|
return DEP_UN;
|
|
return (tag == RPMTAG_REQUIREFLAGS) ? DEP_ST : DEP_WK;
|
|
}
|
|
if (b && ((a & b) == b)) /* a contains b */
|
|
return -compare_sense_flags (tag, -cmp, -wcmp, b, a);
|
|
return DEP_UN;
|
|
}
|
|
/* cmp < 0 => Aevr < Bevr */
|
|
if (a == 0) {
|
|
/* a == 0 && cmp < 0 means b != 0 */
|
|
return tag_is_reqprov(tag) ? DEP_WK : DEP_ST;
|
|
}
|
|
if (tag == RPMTAG_REQUIREFLAGS) {
|
|
/* EQ || LE || LT is stronger than LE || LT */
|
|
if (!(a & RPMSENSE_GREATER) && (b & RPMSENSE_LESS))
|
|
return DEP_ST;
|
|
/* GE || GT is weaker than EQ || GE || GT */
|
|
if ((a & RPMSENSE_GREATER) && !(b & RPMSENSE_LESS))
|
|
return DEP_WK;
|
|
return DEP_UN;
|
|
} else {
|
|
/* GE || GT is stronger than EQ || GE || GT */
|
|
if ((a & RPMSENSE_GREATER) && !(b & RPMSENSE_LESS))
|
|
return DEP_ST;
|
|
/* EQ || LE || LT is weaker than LE || LT */
|
|
if (!(a & RPMSENSE_GREATER) && (b & RPMSENSE_LESS))
|
|
return DEP_WK;
|
|
return DEP_UN;
|
|
}
|
|
}
|
|
|
|
#include "set.h"
|
|
|
|
dep_compare_t
|
|
compare_deps (rpmTag tag, const char *Aevr, rpmsenseFlags Aflags,
|
|
const char *Bevr, rpmsenseFlags Bflags)
|
|
{
|
|
dep_compare_t rc = DEP_UN, cmp_rc;
|
|
rpmsenseFlags Asense, Bsense;
|
|
int sense, wcmp = 0;
|
|
char *aEVR = NULL, *bEVR = NULL;
|
|
const char *aE, *aV, *aR, *aD, *bE, *bV, *bR, *bD;
|
|
|
|
/* 1. filter out noise */
|
|
Aflags &= ~(RPMSENSE_FIND_REQUIRES | RPMSENSE_FIND_PROVIDES);
|
|
Bflags &= ~(RPMSENSE_FIND_REQUIRES | RPMSENSE_FIND_PROVIDES);
|
|
|
|
/* 2. identical? */
|
|
if (Aflags == Bflags && !strcmp (Aevr, Bevr))
|
|
return DEP_EQ;
|
|
|
|
/* 3. whether dependency optimization is enabled? */
|
|
if (!deps_opt_enabled ())
|
|
return DEP_UN;
|
|
|
|
Asense = Aflags & RPMSENSE_SENSEMASK;
|
|
Bsense = Bflags & RPMSENSE_SENSEMASK;
|
|
|
|
/* 4. check for supported tags. */
|
|
switch (tag) {
|
|
case RPMTAG_PROVIDEFLAGS:
|
|
case RPMTAG_OBSOLETEFLAGS:
|
|
case RPMTAG_CONFLICTFLAGS:
|
|
case RPMTAG_REQUIREFLAGS:
|
|
break;
|
|
default:
|
|
/* no way to optimize this case. */
|
|
return DEP_UN;
|
|
}
|
|
|
|
/* 5. sanity checks */
|
|
if (
|
|
((Asense & RPMSENSE_LESS) && (Asense & RPMSENSE_GREATER)) ||
|
|
((Bsense & RPMSENSE_LESS) && (Bsense & RPMSENSE_GREATER)) ||
|
|
((Asense == 0) ^ (Aevr[0] == 0)) ||
|
|
((Bsense == 0) ^ (Bevr[0] == 0))
|
|
)
|
|
return DEP_UN;
|
|
|
|
/* 5. filter out essentially different versions. */
|
|
if (
|
|
((Asense & RPMSENSE_LESS) && (Bsense & RPMSENSE_GREATER)) ||
|
|
((Bsense & RPMSENSE_LESS) && (Asense & RPMSENSE_GREATER))
|
|
)
|
|
return DEP_UN;
|
|
|
|
/* 7. filter out essentially different flags. */
|
|
if ((Aflags & ~RPMSENSE_SENSEMASK) != (Bflags & ~RPMSENSE_SENSEMASK))
|
|
{
|
|
rpmsenseFlags Areq, Breq;
|
|
|
|
/* 7a. no way to optimize different non-REQUIREFLAGS */
|
|
if (tag != RPMTAG_REQUIREFLAGS)
|
|
return DEP_UN;
|
|
|
|
/* 7b. filter out essentially different requires. */
|
|
if ((Aflags & ~RPMSENSE_SENSEMASK & ~_ALL_REQUIRES_MASK) !=
|
|
(Bflags & ~RPMSENSE_SENSEMASK & ~_ALL_REQUIRES_MASK))
|
|
return DEP_UN;
|
|
|
|
Areq = Aflags & _ALL_REQUIRES_MASK;
|
|
Breq = Bflags & _ALL_REQUIRES_MASK;
|
|
/* it is established fact that Areq != Breq */
|
|
|
|
/* 7c. Aflags contains Bflags? */
|
|
if (Breq && (Areq & Breq) == Breq)
|
|
rc = DEP_ST;
|
|
|
|
/* 7d. Bflags contains Aflags? */
|
|
else if (Areq && (Areq & Breq) == Areq)
|
|
rc = DEP_WK;
|
|
|
|
else
|
|
return DEP_UN;
|
|
}
|
|
|
|
/* 8. compare versions. */
|
|
int aset = strncmp(Aevr, "set:", 4) == 0;
|
|
int bset = strncmp(Bevr, "set:", 4) == 0;
|
|
if (aset && bset) {
|
|
sense = rpmsetcmp(Aevr, Bevr);
|
|
if (sense < -1)
|
|
return DEP_UN;
|
|
}
|
|
else if (aset) {
|
|
if (*Bevr)
|
|
return DEP_UN;
|
|
sense = 1;
|
|
}
|
|
else if (bset) {
|
|
if (*Aevr)
|
|
return DEP_UN;
|
|
sense = -1;
|
|
}
|
|
else {
|
|
aEVR = xstrdup(Aevr);
|
|
parseEVRD(aEVR, &aE, &aV, &aR, &aD);
|
|
bEVR = xstrdup(Bevr);
|
|
parseEVRD(bEVR, &bE, &bV, &bR, &bD);
|
|
|
|
/*
|
|
* Promote Epoch by giving it special treatment:
|
|
* if one of deps has Epoch and another one hasn't,
|
|
* we first compare them without Epoch, and if it happens
|
|
* that they are equal, then the dep that has Epoch wins.
|
|
*/
|
|
const char *ae = aE, *be = bE;
|
|
if ((!(aE && *aE) || !(bE && *bE))) {
|
|
ae = NULL; be = NULL;
|
|
}
|
|
|
|
if ((aR && *aR) && !(bR && *bR))
|
|
wcmp = -1;
|
|
else if ((bR && *bR) && !(aR && *aR))
|
|
wcmp = 1;
|
|
|
|
sense = rpmEVRcmp(ae, aV, aR, Aevr, be, bV, bR, Bevr);
|
|
}
|
|
|
|
/* 9. detect overlaps. */
|
|
cmp_rc = compare_sense_flags (tag, sense, wcmp, Asense, Bsense);
|
|
|
|
/* 10. EVRs with Epoch are stronger. */
|
|
if (cmp_rc == DEP_EQ)
|
|
{
|
|
if ((aE && *aE) && !(bE && *bE))
|
|
cmp_rc = DEP_ST;
|
|
else if ((bE && *bE) && !(aE && *aE))
|
|
cmp_rc = DEP_WK;
|
|
}
|
|
/* 10b. EVRs with DistTag are stronger. */
|
|
if (cmp_rc == DEP_EQ)
|
|
{
|
|
if ((aD && *aD) && !(bD && *bD))
|
|
cmp_rc = DEP_ST;
|
|
else if ((bD && *bD) && !(aD && *aD))
|
|
cmp_rc = DEP_WK;
|
|
}
|
|
|
|
aEVR = _free(aEVR);
|
|
bEVR = _free(bEVR);
|
|
|
|
#if 0
|
|
fprintf(stderr, "D: compare_sense_flags=%d: tag=%d, sense=%d, wcmp=%d, Asense=%#x, Bsense=%#x\n",
|
|
cmp_rc, tag, sense, wcmp, Asense, Bsense);
|
|
#endif
|
|
|
|
/* 11. compare expected with received. */
|
|
if (cmp_rc == DEP_UN || rc == DEP_UN)
|
|
return cmp_rc;
|
|
|
|
if (cmp_rc != rc && cmp_rc != DEP_EQ)
|
|
return DEP_UN;
|
|
|
|
return rc;
|
|
}
|
|
|
|
int addReqProv(/*@unused@*/ Spec spec, Header h,
|
|
rpmsenseFlags depFlags, const char *depName, const char *depEVR,
|
|
int index)
|
|
{
|
|
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
|
HFD_t hfd = headerFreeData;
|
|
const char ** names;
|
|
rpmTagType dnt;
|
|
rpmTag nametag = 0;
|
|
rpmTag versiontag = 0;
|
|
rpmTag flagtag = 0;
|
|
rpmTag indextag = 0;
|
|
int len;
|
|
rpmsenseFlags extra = RPMSENSE_ANY;
|
|
int xx;
|
|
|
|
if (depFlags & RPMSENSE_PROVIDES) {
|
|
nametag = RPMTAG_PROVIDENAME;
|
|
versiontag = RPMTAG_PROVIDEVERSION;
|
|
flagtag = RPMTAG_PROVIDEFLAGS;
|
|
extra = depFlags & RPMSENSE_FIND_PROVIDES;
|
|
} else if (depFlags & RPMSENSE_OBSOLETES) {
|
|
nametag = RPMTAG_OBSOLETENAME;
|
|
versiontag = RPMTAG_OBSOLETEVERSION;
|
|
flagtag = RPMTAG_OBSOLETEFLAGS;
|
|
} else if (depFlags & RPMSENSE_CONFLICTS) {
|
|
nametag = RPMTAG_CONFLICTNAME;
|
|
versiontag = RPMTAG_CONFLICTVERSION;
|
|
flagtag = RPMTAG_CONFLICTFLAGS;
|
|
} else if (depFlags & RPMSENSE_PREREQ) {
|
|
nametag = RPMTAG_REQUIRENAME;
|
|
versiontag = RPMTAG_REQUIREVERSION;
|
|
flagtag = RPMTAG_REQUIREFLAGS;
|
|
extra = depFlags & _ALL_REQUIRES_MASK;
|
|
} else if (depFlags & RPMSENSE_TRIGGER) {
|
|
nametag = RPMTAG_TRIGGERNAME;
|
|
versiontag = RPMTAG_TRIGGERVERSION;
|
|
flagtag = RPMTAG_TRIGGERFLAGS;
|
|
indextag = RPMTAG_TRIGGERINDEX;
|
|
extra = depFlags & RPMSENSE_TRIGGER;
|
|
} else {
|
|
nametag = RPMTAG_REQUIRENAME;
|
|
versiontag = RPMTAG_REQUIREVERSION;
|
|
flagtag = RPMTAG_REQUIREFLAGS;
|
|
extra = depFlags & _ALL_REQUIRES_MASK;
|
|
}
|
|
|
|
depFlags = (depFlags & (RPMSENSE_SENSEMASK)) | extra;
|
|
|
|
/*@-branchstate@*/
|
|
if (depEVR == NULL)
|
|
depEVR = "";
|
|
/*@=branchstate@*/
|
|
|
|
/* Check for duplicate dependencies. */
|
|
if (hge(h, nametag, &dnt, (void **) &names, &len) && len > 0) {
|
|
const char ** versions = NULL;
|
|
rpmTagType dvt = RPM_STRING_ARRAY_TYPE;
|
|
int *flags = NULL;
|
|
int *indexes = NULL;
|
|
int i, o_cnt = 0, duplicate = 0;
|
|
char obsolete[len];
|
|
|
|
memset (obsolete, 0, sizeof obsolete);
|
|
|
|
if (flagtag) {
|
|
xx = hge(h, versiontag, &dvt, (void **) &versions, NULL);
|
|
xx = hge(h, flagtag, NULL, (void **) &flags, NULL);
|
|
}
|
|
if (indextag)
|
|
xx = hge(h, indextag, NULL, (void **) &indexes, NULL);
|
|
|
|
for (i = len - 1; i >= 0; --i) {
|
|
if (indextag && indexes && indexes[i] != index)
|
|
continue;
|
|
|
|
if (strcmp(names[i], depName))
|
|
continue;
|
|
|
|
if (flagtag && flags && versions) {
|
|
dep_compare_t rc = compare_deps(flagtag, versions[i], flags[i],
|
|
depEVR, depFlags);
|
|
|
|
#if 0
|
|
fprintf (stderr, "D: name=%s, compare_deps=%d: tag=%d, AEVR=%s, Aflags=%#x, BEVR=%s, Bflags=%#x\n",
|
|
depName, rc, flagtag, versions[i], flags[i], depEVR, depFlags);
|
|
#endif
|
|
if (rc == DEP_UN && flagtag == RPMTAG_REQUIREFLAGS) {
|
|
const rpmsenseFlags mergedFlags =
|
|
(flags[i] & _ALL_REQUIRES_MASK) |
|
|
(depFlags & ~RPMSENSE_FIND_REQUIRES);
|
|
if (mergedFlags != depFlags &&
|
|
compare_deps(flagtag, versions[i], flags[i],
|
|
depEVR, mergedFlags) == DEP_WK) {
|
|
rpmMessage(RPMMESS_DEBUG,
|
|
"new dep \"%s\" flags %#x upgraded to %#x\n",
|
|
depName, depFlags, mergedFlags);
|
|
depFlags = mergedFlags;
|
|
rc = DEP_WK;
|
|
}
|
|
}
|
|
switch (rc) {
|
|
case DEP_EQ:
|
|
rpmMessage (RPMMESS_DEBUG,
|
|
"new dep \"%s\" already exists, optimized out\n",
|
|
depName);
|
|
break;
|
|
case DEP_ST:
|
|
rpmMessage (RPMMESS_DEBUG,
|
|
"new dep \"%s\" is weaker, optimized out\n",
|
|
depName);
|
|
break;
|
|
case DEP_WK:
|
|
++o_cnt;
|
|
obsolete[i] = 1;
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/* This is a duplicate dependency. */
|
|
duplicate = 1;
|
|
|
|
if (o_cnt) {
|
|
rpmMessage(RPMMESS_WARNING, "%d obsolete deps left", o_cnt);
|
|
o_cnt = 0;
|
|
}
|
|
|
|
break;
|
|
} /* end of main loop */
|
|
|
|
if (o_cnt)
|
|
{
|
|
int j, new_len = len - o_cnt;
|
|
const char *new_names[new_len];
|
|
const char *new_versions[new_len];
|
|
int new_flags[new_len];
|
|
|
|
rpmMessage (RPMMESS_DEBUG, "%d old deps to be optimized out\n", o_cnt);
|
|
for (i = 0, j = 0; i < len; ++i)
|
|
{
|
|
char *p;
|
|
|
|
if (obsolete[i])
|
|
{
|
|
rpmMessage (RPMMESS_DEBUG, "old dep \"%s\" optimized out\n", names[i]);
|
|
continue;
|
|
}
|
|
|
|
p = alloca (1 + strlen (names[i]));
|
|
strcpy (p, names[i]);
|
|
new_names[j] = p;
|
|
|
|
p = alloca (1 + strlen (versions[i]));
|
|
strcpy (p, versions[i]);
|
|
new_versions[j] = p;
|
|
|
|
new_flags[j] = flags[i];
|
|
++j;
|
|
}
|
|
|
|
if ( !headerModifyEntry (h, nametag, RPM_STRING_ARRAY_TYPE, new_names, new_len)
|
|
|| !headerModifyEntry (h, versiontag, RPM_STRING_ARRAY_TYPE, new_versions, new_len)
|
|
|| !headerModifyEntry (h, flagtag, RPM_INT32_TYPE, new_flags, new_len))
|
|
rpmError (RPMERR_BADHEADER, "addReqProv: error modifying entry for dep %s\n", depName);
|
|
rpmMessage (RPMMESS_DEBUG, "%d old deps optimized out, %d left\n", o_cnt, new_len);
|
|
}
|
|
|
|
versions = hfd(versions, dvt);
|
|
names = hfd(names, dnt);
|
|
if (duplicate)
|
|
return 1;
|
|
}
|
|
|
|
/* Do not add NEW provided requires. */
|
|
if ( deps_opt_enabled ()
|
|
&& (nametag == RPMTAG_REQUIRENAME)
|
|
&& !(depFlags & _notpre (RPMSENSE_RPMLIB | RPMSENSE_KEYRING |
|
|
RPMSENSE_SCRIPT_PRE | RPMSENSE_SCRIPT_POSTUN)))
|
|
{
|
|
|
|
int skip = 0;
|
|
int *flags = 0;
|
|
const char **versions = 0;
|
|
rpmTagType dvt = RPM_STRING_ARRAY_TYPE;
|
|
|
|
names = NULL;
|
|
hge (h, RPMTAG_PROVIDENAME, &dnt, (void **) &names, &len);
|
|
hge (h, RPMTAG_PROVIDEVERSION, &dvt, (void **) &versions, NULL);
|
|
hge (h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &flags, NULL);
|
|
|
|
while (names && flags && versions && (len > 0))
|
|
{
|
|
--len;
|
|
|
|
if (strcmp (depName, names[len]))
|
|
continue;
|
|
if (!(depFlags & RPMSENSE_SENSEMASK))
|
|
{
|
|
skip = 1;
|
|
break;
|
|
}
|
|
if (!(flags[len] & RPMSENSE_SENSEMASK))
|
|
continue;
|
|
if (rpmRangesOverlap ("", versions[len], flags[len],
|
|
"", depEVR, depFlags))
|
|
{
|
|
rpmMessage (RPMMESS_DEBUG,
|
|
"new dep \"%s\" already provided, optimized out\n",
|
|
depName);
|
|
skip = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
versions = hfd (versions, dvt);
|
|
names = hfd (names, dnt);
|
|
if (skip)
|
|
return 1;
|
|
|
|
if (*depName == '/' && !(depFlags & RPMSENSE_SENSEMASK))
|
|
{
|
|
const char **bn = NULL, **dn = NULL;
|
|
const int_32 *di = NULL;
|
|
rpmTagType bnt = 0, dnt = 0, dit = 0;
|
|
int_32 bnc = 0;
|
|
int i;
|
|
(void) (hge(h, RPMTAG_DIRNAMES, &dnt, (void**)&dn, NULL) &&
|
|
hge(h, RPMTAG_DIRINDEXES, &dit, (void**)&di, NULL) &&
|
|
hge(h, RPMTAG_BASENAMES, &bnt, (void**)&bn, &bnc));
|
|
for (i = 0; i < bnc; i++) {
|
|
const char *d = dn[di[i]], *b = bn[i];
|
|
size_t dl = strlen(d);
|
|
if (strncmp(depName, d, dl) ||
|
|
strcmp(depName + dl, b))
|
|
continue;
|
|
rpmMessage (RPMMESS_DEBUG,
|
|
"new dep \"%s\" is packaged file, optimized out\n",
|
|
depName);
|
|
skip = 1;
|
|
break;
|
|
}
|
|
hfd(dn, dnt);
|
|
hfd(di, dit);
|
|
hfd(bn, bnt);
|
|
}
|
|
else {
|
|
const char *N = NULL, *V = NULL, *R = NULL, *D = NULL;
|
|
headerNVRD(h, &N, &V, &R, &D);
|
|
if (N && strcmp(depName, N) == 0) {
|
|
if (!(depFlags & RPMSENSE_SENSEMASK))
|
|
skip = 1;
|
|
else if (V && R) {
|
|
int_32 *E = NULL;
|
|
const char *EVR, *EVRD = NULL;
|
|
hge(h, RPMTAG_EPOCH, NULL, (void**) &E, NULL);
|
|
if (E)
|
|
EVR = xasprintf("%d:%s-%s", *E, V, R);
|
|
else
|
|
EVR = xasprintf("%s-%s", V, R);
|
|
if (D)
|
|
EVRD = xasprintf("%s:%s", EVR, D);
|
|
if (rpmRangesOverlap("", EVRD ? : EVR, RPMSENSE_EQUAL,
|
|
"", depEVR, depFlags))
|
|
skip = 1;
|
|
EVRD = _free(EVRD);
|
|
EVR = _free(EVR);
|
|
}
|
|
else
|
|
skip = 1;
|
|
if (skip)
|
|
rpmMessage (RPMMESS_DEBUG,
|
|
"new dep \"%s\" is the package name, optimized out\n",
|
|
depName);
|
|
}
|
|
}
|
|
|
|
if (skip)
|
|
return 1;
|
|
}
|
|
|
|
/* Remove OLD provided requires. */
|
|
if ( deps_opt_enabled ()
|
|
&& (nametag == RPMTAG_PROVIDENAME)
|
|
&& hge (h, RPMTAG_REQUIRENAME, &dnt, (void **) &names, &len))
|
|
{
|
|
|
|
int *flags = 0;
|
|
const char **versions = 0;
|
|
rpmTagType dvt = RPM_STRING_ARRAY_TYPE;
|
|
int i, o_cnt = 0;
|
|
char obsolete[len];
|
|
|
|
memset (obsolete, 0, sizeof obsolete);
|
|
|
|
hge (h, RPMTAG_REQUIREVERSION, &dvt, (void **) &versions, NULL);
|
|
hge (h, RPMTAG_REQUIREFLAGS, NULL, (void **) &flags, NULL);
|
|
|
|
for (i = len - 1; flags && versions && (i >= 0); --i)
|
|
{
|
|
rpmsenseFlags f = flags[i];
|
|
|
|
if ((f & _notpre (RPMSENSE_RPMLIB | RPMSENSE_KEYRING |
|
|
RPMSENSE_SCRIPT_PRE | RPMSENSE_SCRIPT_POSTUN)))
|
|
continue;
|
|
if (strcmp (depName, names[i]))
|
|
continue;
|
|
if (!(f & RPMSENSE_SENSEMASK))
|
|
{
|
|
++o_cnt;
|
|
obsolete[i] = 1;
|
|
continue;
|
|
}
|
|
if (!(depFlags & RPMSENSE_SENSEMASK))
|
|
continue;
|
|
if (rpmRangesOverlap ("", depEVR, depFlags,
|
|
"", versions[i], f))
|
|
{
|
|
++o_cnt;
|
|
obsolete[i] = 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (o_cnt)
|
|
{
|
|
int j, new_len = len - o_cnt;
|
|
const char *new_names[new_len];
|
|
const char *new_versions[new_len];
|
|
int new_flags[new_len];
|
|
|
|
rpmMessage (RPMMESS_DEBUG, "%d old deps to be optimized out\n", o_cnt);
|
|
for (i = 0, j = 0; i < len; ++i)
|
|
{
|
|
char *p;
|
|
|
|
if (obsolete[i])
|
|
{
|
|
rpmMessage (RPMMESS_DEBUG, "old dep \"%s\" optimized out\n", names[i]);
|
|
continue;
|
|
}
|
|
|
|
p = alloca (1 + strlen (names[i]));
|
|
strcpy (p, names[i]);
|
|
new_names[j] = p;
|
|
|
|
p = alloca (1 + strlen (versions[i]));
|
|
strcpy (p, versions[i]);
|
|
new_versions[j] = p;
|
|
|
|
new_flags[j] = flags[i];
|
|
++j;
|
|
}
|
|
|
|
if (!headerModifyEntry (h, RPMTAG_REQUIRENAME, RPM_STRING_ARRAY_TYPE, new_names, new_len) ||
|
|
!headerModifyEntry (h, RPMTAG_REQUIREVERSION, RPM_STRING_ARRAY_TYPE, new_versions, new_len) ||
|
|
!headerModifyEntry (h, RPMTAG_REQUIREFLAGS, RPM_INT32_TYPE, new_flags, new_len))
|
|
rpmError (RPMERR_BADHEADER, "addReqProv: error modifying entry for dep %s\n", depName);
|
|
rpmMessage (RPMMESS_DEBUG, "%d old deps optimized out, %d left\n", o_cnt, new_len);
|
|
}
|
|
|
|
versions = hfd (versions, dvt);
|
|
names = hfd (names, dnt);
|
|
}
|
|
|
|
/* Add this dependency. */
|
|
xx = headerAddOrAppendEntry(h, nametag, RPM_STRING_ARRAY_TYPE, &depName, 1);
|
|
if (flagtag) {
|
|
xx = headerAddOrAppendEntry(h, versiontag,
|
|
RPM_STRING_ARRAY_TYPE, &depEVR, 1);
|
|
xx = headerAddOrAppendEntry(h, flagtag,
|
|
RPM_INT32_TYPE, &depFlags, 1);
|
|
}
|
|
if (indextag)
|
|
xx = headerAddOrAppendEntry(h, indextag, RPM_INT32_TYPE, &index, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int rpmlibNeedsFeature(Header h, const char * feature, const char * featureEVR)
|
|
{
|
|
char * reqname = alloca(sizeof("rpmlib()") + strlen(feature));
|
|
(void) stpcpy( stpcpy( stpcpy(reqname, "rpmlib("), feature), ")");
|
|
|
|
rpmsenseFlags depFlags = RPMSENSE_RPMLIB;
|
|
if (featureEVR)
|
|
depFlags |= RPMSENSE_LESS|RPMSENSE_EQUAL;
|
|
|
|
/* XXX 1st arg is unused */
|
|
return addReqProv(NULL, h, depFlags, reqname, featureEVR, 0);
|
|
}
|