add support for rich dependencies from dependency generators

Mostly achieved by replacing custom parser with the parseRCPOT().

Closes: https://github.com/rpm-software-management/rpm/issues/167
Signed-off-by: Igor Gnatenko <ignatenko@redhat.com>
This commit is contained in:
Igor Gnatenko 2017-02-25 12:28:16 +01:00
parent 5adc56897b
commit 8f509d669b
6 changed files with 53 additions and 70 deletions

View File

@ -871,13 +871,13 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,
case RPMTAG_CONFLICTNAME:
case RPMTAG_OBSOLETENAME:
case RPMTAG_PROVIDENAME:
if (parseRCPOT(spec, pkg, field, tag, 0, tagflags))
if (parseRCPOT(spec, pkg, field, tag, 0, tagflags, addReqProvPkg, NULL))
goto exit;
break;
case RPMTAG_BUILDPREREQ:
case RPMTAG_BUILDREQUIRES:
case RPMTAG_BUILDCONFLICTS:
if (parseRCPOT(spec, spec->sourcePackage, field, tag, 0, tagflags))
if (parseRCPOT(spec, spec->sourcePackage, field, tag, 0, tagflags, addReqProvPkg, NULL))
goto exit;
break;
case RPMTAG_EXCLUDEARCH:

View File

@ -121,7 +121,7 @@ static rpmRC parseRCPOTRichCB(void *cbdata, rpmrichParseType type,
}
rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN,
int index, rpmsenseFlags tagflags)
int index, rpmsenseFlags tagflags, addReqProvFunction cb, void *cbdata)
{
const char *r, *re, *v, *ve;
char *emsg = NULL;
@ -130,6 +130,9 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN,
rpmsenseFlags Flags;
rpmRC rc = RPMRC_FAIL; /* assume failure */
if (!cbdata)
cbdata = pkg;
switch (tagN) {
default:
case RPMTAG_REQUIRENAME:
@ -221,7 +224,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN,
freeStringBuf(data.sb);
goto exit;
}
if (addReqProv(pkg, nametag, getStringBuf(data.sb), NULL, Flags, index)) {
if (cb && cb(cbdata, nametag, getStringBuf(data.sb), NULL, Flags, index) != RPMRC_OK) {
rasprintf(&emsg, _("invalid dependency"));
freeStringBuf(data.sb);
goto exit;
@ -296,7 +299,7 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN,
goto exit;
}
if (addReqProv(pkg, nametag, N, EVR, Flags, index)) {
if (cb && cb(cbdata, nametag, N, EVR, Flags, index) != RPMRC_OK) {
rasprintf(&emsg, _("invalid dependency"));
goto exit;
}

View File

@ -416,7 +416,7 @@ int parseScript(rpmSpec spec, int parsePart)
priority);
/* Generate the trigger tags */
if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags))
if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags, addReqProvPkg, NULL))
goto exit;
} else {
struct rpmtd_s td;

View File

@ -34,6 +34,14 @@ int addReqProv(Package pkg, rpmTagVal tagN,
return 0;
}
rpmRC addReqProvPkg(void *cbdata, rpmTagVal tagN,
const char * N, const char *EVR, rpmsenseFlags Flags,
int index)
{
Package pkg = cbdata;
return addReqProv(pkg, tagN, N, EVR, Flags, index) ? RPMRC_FAIL : RPMRC_OK;
}
int rpmlibNeedsFeature(Package pkg, const char * feature, const char * featureEVR)
{
char *reqname = NULL;

View File

@ -283,6 +283,10 @@ int parseScript(rpmSpec spec, int parsePart);
RPM_GNUC_INTERNAL
rpmRC rpmCharCheck(rpmSpec spec, const char *field, const char *whitelist);
typedef rpmRC (*addReqProvFunction) (void *cbdata, rpmTagVal tagN,
const char * N, const char * EVR, rpmsenseFlags Flags,
int index);
/** \ingroup rpmbuild
* Parse dependency relations from spec file and/or autogenerated output buffer.
* @param spec spec file control structure
@ -291,11 +295,13 @@ rpmRC rpmCharCheck(rpmSpec spec, const char *field, const char *whitelist);
* @param tagN tag, identifies type of dependency
* @param index (0 always)
* @param tagflags dependency flags already known from context
* @param cb Callback for adding dependency (nullable)
* @param cbdata Callback data (@pkg if NULL)
* @return RPMRC_OK on success, RPMRC_FAIL on failure
*/
RPM_GNUC_INTERNAL
rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char * field, rpmTagVal tagN,
int index, rpmsenseFlags tagflags);
int index, rpmsenseFlags tagflags, addReqProvFunction cb, void *cbdata);
/** \ingroup rpmbuild
* Evaluate boolean expression.
@ -440,6 +446,10 @@ int addReqProv(Package pkg, rpmTagVal tagN,
const char * N, const char * EVR, rpmsenseFlags Flags,
uint32_t index);
RPM_GNUC_INTERNAL
rpmRC addReqProvPkg(void *cbdata, rpmTagVal tagN,
const char * N, const char * EVR, rpmsenseFlags Flags,
int index);
/** \ingroup rpmbuild
* Add rpmlib feature dependency.

View File

@ -497,44 +497,27 @@ static ARGV_t runCmd(const char *nsdep, const char *depname,
return output;
}
static const char *parseDep(char **depav, int depac,
const char **N, const char **EVR, rpmsenseFlags *Flags)
struct addReqProvDataFc {
rpmfc fc;
const char *namespace;
regex_t *exclude;
};
static rpmRC addReqProvFc(void *cbdata, rpmTagVal tagN,
const char * N, const char * EVR, rpmsenseFlags Flags,
int index)
{
const char *err = NULL;
struct addReqProvDataFc *data = cbdata;
rpmfc fc = data->fc;
const char *namespace = data->namespace;
regex_t *exclude = data->exclude;
switch (depac) {
case 1: /* only a name */
*N = depav[0];
*EVR = "";
break;
case 3: /* name, range and version */
for (const char *s = depav[1]; *s; s++) {
switch (*s) {
default:
err = _("bad operator");
break;
case '=':
*Flags |= RPMSENSE_EQUAL;
break;
case '<':
*Flags |= RPMSENSE_LESS;
break;
case '>':
*Flags |= RPMSENSE_GREATER;
break;
}
}
if (!err) {
*N = depav[0];
*EVR = depav[2];
}
break;
default:
err = _("bad format");
break;
}
rpmds ds = rpmdsSingleNS(fc->pool, tagN, namespace, N, EVR, Flags);
/* Add to package and file dependencies unless filtered */
if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0)
rpmfcAddFileDep(&fc->fileDeps, ds, index);
return err;
return RPMRC_OK;
}
/**
@ -577,35 +560,14 @@ static int rpmfcHelper(rpmfc fc, int ix,
namespace = rpmfcAttrMacro(nsdep, "namespace", NULL);
exclude = rpmfcAttrReg(depname, "exclude", NULL);
struct addReqProvDataFc data;
data.fc = fc;
data.namespace = namespace;
data.exclude = exclude;
for (int i = 0; i < pac; i++) {
char ** depav = NULL;
int xx, depac = 0;
const char *N = NULL;
const char *EVR = NULL;
const char *err = NULL;
rpmsenseFlags Flags = dsContext;
if ((xx = poptParseArgvString(pav[i], &depac, (const char ***)&depav)))
err = poptStrerror(xx);
if (!err)
err = parseDep(depav, depac, &N, &EVR, &Flags);
if (!err) {
rpmds ds = rpmdsSingleNS(fc->pool, tagN, namespace, N, EVR, Flags);
/* Add to package and file dependencies unless filtered */
if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0) {
//rpmdsMerge(packageDependencies(fc->pkg, tagN), ds);
rpmfcAddFileDep(&fc->fileDeps, ds, ix);
}
} else {
rpmlog(RPMLOG_ERR, _("invalid dependency (%s): %s\n"),
err, pav[i]);
if (parseRCPOT(NULL, fc->pkg, pav[i], tagN, 0, dsContext, addReqProvFc, &data))
rc++;
}
free(depav);
}
argvFree(pav);
@ -1353,7 +1315,7 @@ static rpmRC rpmfcApplyExternal(rpmfc fc)
}
/* Parse dependencies into header */
rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag ? dm->ntag != -1 : RPMTAG_REQUIRENAME, 0, tagflags);
rc = parseRCPOT(NULL, fc->pkg, getStringBuf(sb_stdout), dm->ntag ? dm->ntag != -1 : RPMTAG_REQUIRENAME, 0, tagflags, addReqProvPkg, NULL);
freeStringBuf(sb_stdout);
if (rc) {