From c1ed362facbab3d08b5576950d4c6a68cfae9e75 Mon Sep 17 00:00:00 2001 From: Igor Gnatenko Date: Sat, 25 Feb 2017 12:28:16 +0100 Subject: [PATCH] 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 (cherry picked from commit 8f509d669b9ae79c86dd510c5a4bc5109f60d733) Conflicts: build/rpmfc.c --- build/parsePreamble.c | 4 +-- build/parseReqs.c | 9 +++-- build/parseScript.c | 2 +- build/reqprov.c | 8 +++++ build/rpmbuild_internal.h | 12 ++++++- build/rpmfc.c | 90 ++++++++++++++--------------------------------- 6 files changed, 54 insertions(+), 71 deletions(-) diff --git a/build/parsePreamble.c b/build/parsePreamble.c index bc639e86c..6b3705598 100644 --- a/build/parsePreamble.c +++ b/build/parsePreamble.c @@ -866,13 +866,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: diff --git a/build/parseReqs.c b/build/parseReqs.c index 4d500c1df..554ff49a5 100644 --- a/build/parseReqs.c +++ b/build/parseReqs.c @@ -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; @@ -131,6 +131,9 @@ rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, rpmRC rc = RPMRC_FAIL; /* assume failure */ int allow_richdeps = 0; + if (!cbdata) + cbdata = pkg; + switch (tagN) { default: case RPMTAG_REQUIRENAME: @@ -225,7 +228,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; @@ -300,7 +303,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; } diff --git a/build/parseScript.c b/build/parseScript.c index 64fd89693..849e40244 100644 --- a/build/parseScript.c +++ b/build/parseScript.c @@ -398,7 +398,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; diff --git a/build/reqprov.c b/build/reqprov.c index 7422db65f..5fa0a1c6b 100644 --- a/build/reqprov.c +++ b/build/reqprov.c @@ -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; diff --git a/build/rpmbuild_internal.h b/build/rpmbuild_internal.h index 7ec05b9c9..1c3332faf 100644 --- a/build/rpmbuild_internal.h +++ b/build/rpmbuild_internal.h @@ -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 self-provides to package. diff --git a/build/rpmfc.c b/build/rpmfc.c index 921814ad1..7fa8227d0 100644 --- a/build/rpmfc.c +++ b/build/rpmfc.c @@ -447,44 +447,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; - - 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; - } + struct addReqProvDataFc *data = cbdata; + rpmfc fc = data->fc; + const char *namespace = data->namespace; + regex_t *exclude = data->exclude; + + 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; } /** @@ -522,35 +505,14 @@ static int rpmfcHelper(rpmfc fc, int ix, namespace = rpmfcAttrMacro(nsdep, NULL, "namespace"); exclude = rpmfcAttrReg(depname, NULL, "exclude"); + 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); @@ -1297,7 +1259,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) {