Blob Blame History Raw
From c1ed362facbab3d08b5576950d4c6a68cfae9e75 Mon Sep 17 00:00:00 2001
From: Igor Gnatenko <ignatenko@redhat.com>
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 <ignatenko@redhat.com>
(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) {