Blob Blame History Raw
From 6ac793b215ac8d9db99d9632cbf71b014c7ffee0 Mon Sep 17 00:00:00 2001
From: Lubos Kardos <lkardos@redhat.com>
Date: Thu, 12 May 2016 16:28:09 +0200
Subject: [PATCH] Filter unversioned deps if corresponding versioned deps exist
 (rhbz:678605)

After automatic dependencies are generated filter out from them
unversioned dependencies if versioned dependencies with the same name,
type and color already exist.
---
 build/rpmfc.c | 173 +++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 118 insertions(+), 55 deletions(-)

diff --git a/build/rpmfc.c b/build/rpmfc.c
index 73996e8..10fbd68 100644
--- a/build/rpmfc.c
+++ b/build/rpmfc.c
@@ -34,6 +34,17 @@ typedef struct rpmfcAttr_s {
     struct matchRule excl;
 } * rpmfcAttr;
 
+typedef struct {
+    int fileIx;
+    rpmds dep;
+} rpmfcFileDep;
+
+typedef struct {
+    rpmfcFileDep *data;
+    int size;
+    int alloced;
+} rpmfcFileDeps;
+
 /**
  */
 struct rpmfc_s {
@@ -56,7 +67,7 @@ struct rpmfc_s {
     ARGI_t fddictn;	/*!< (no. files) file depends dictionary no. entries */
     ARGI_t ddictx;	/*!< (no. dependencies) file->dependency mapping */
     rpmstrPool cdict;	/*!< file class dictionary */
-    rpmstrPool ddict;	/*!< file depends dictionary */
+    rpmfcFileDeps fileDeps; /*!< file dependency mapping */
 
     rpmstrPool pool;	/*!< general purpose string storage */
 };
@@ -398,15 +409,15 @@ static void argvAddUniq(ARGV_t * argvp, const char * key)
 
 #define hasAttr(_a, _n) (argvSearch((_a), (_n), NULL) != NULL)
 
-static void rpmfcAddFileDep(rpmstrPool ddict, int ix, rpmds ds, char deptype)
+static void rpmfcAddFileDep(rpmfcFileDeps *fileDeps, rpmds ds, int ix)
 {
-    if (ds) {
-	char *key = NULL;
-	rasprintf(&key, "%08d%c %s %s 0x%08x", ix, deptype,
-		  rpmdsN(ds), rpmdsEVR(ds), rpmdsFlags(ds));
-	rpmstrPoolId(ddict, key, 1);
-	free(key);
+    if (fileDeps->size == fileDeps->alloced) {
+	fileDeps->alloced <<= 2;
+	fileDeps->data  = xrealloc(fileDeps->data,
+	    fileDeps->alloced * sizeof(fileDeps->data[0]));
     }
+    fileDeps->data[fileDeps->size].fileIx = ix;
+    fileDeps->data[fileDeps->size++].dep = ds;
 }
 
 static ARGV_t runCmd(const char *nsdep, const char *depname,
@@ -531,11 +542,9 @@ static int rpmfcHelper(rpmfc fc, int ix,
 
 	    /* Add to package and file dependencies unless filtered */
 	    if (regMatch(exclude, rpmdsDNEVR(ds)+2) == 0) {
-		(void) rpmdsMerge(packageDependencies(fc->pkg, tagN), ds);
-		rpmfcAddFileDep(fc->ddict, ix, ds,
-				tagN == RPMTAG_PROVIDENAME ? 'P' : 'R');
+		//rpmdsMerge(packageDependencies(fc->pkg, tagN), ds);
+		rpmfcAddFileDep(&fc->fileDeps, ds, ix);
 	    }
-	    rpmdsFree(ds);
 	} else {
 	    rpmlog(RPMLOG_ERR, _("invalid dependency (%s): %s\n"),
 		   err, pav[i]);
@@ -745,7 +754,11 @@ rpmfc rpmfcFree(rpmfc fc)
 	argiFree(fc->fddictn);
 	argiFree(fc->ddictx);
 
-	rpmstrPoolFree(fc->ddict);
+	for (int i = 0; i < fc->fileDeps.size; i++) {
+	    rpmdsFree(fc->fileDeps.data[i].dep);
+	}
+	free(fc->fileDeps.data);
+
 	rpmstrPoolFree(fc->cdict);
 
 	rpmstrPoolFree(fc->pool);
@@ -764,6 +777,9 @@ rpmfc rpmfcCreate(const char *buildRoot, rpmFlags flags)
     }
     fc->pool = rpmstrPoolCreate();
     fc->pkg = xcalloc(1, sizeof(*fc->pkg));
+    fc->fileDeps.alloced = 10;
+    fc->fileDeps.data = xmalloc(fc->fileDeps.alloced *
+	sizeof(fc->fileDeps.data[0]));
     return fc;
 }
 
@@ -820,17 +836,82 @@ rpmds rpmfcObsoletes(rpmfc fc)
     return rpmfcDependencies(fc, RPMTAG_OBSOLETENAME);
 }
 
+
+/* Versioned deps are less than unversioned deps */
+static int cmpVerDeps(const void *a, const void *b)
+{
+    rpmfcFileDep *fDepA = (rpmfcFileDep *) a;
+    rpmfcFileDep *fDepB = (rpmfcFileDep *) b;
+
+    int aIsVersioned = rpmdsFlags(fDepA->dep) & RPMSENSE_SENSEMASK ? 1 : 0;
+    int bIsVersioned = rpmdsFlags(fDepB->dep) & RPMSENSE_SENSEMASK ? 1 : 0;
+
+    return bIsVersioned - aIsVersioned;
+}
+
+/* Sort by index */
+static int cmpIndexDeps(const void *a, const void *b)
+{
+    rpmfcFileDep *fDepA = (rpmfcFileDep *) a;
+    rpmfcFileDep *fDepB = (rpmfcFileDep *) b;
+
+    return fDepA->fileIx - fDepB->fileIx;
+}
+
+/*
+ * Remove unversioned deps if corresponding versioned deps exist but only
+ * if the versioned dependency has the same type and the same color as the versioned.
+ */
+static void rpmfcNormalizeFDeps(rpmfc fc)
+{
+    rpmstrPool versionedDeps = rpmstrPoolCreate();
+    rpmfcFileDep *normalizedFDeps = xmalloc(fc->fileDeps.size *
+	sizeof(normalizedFDeps[0]));
+    int ix = 0;
+    char *depStr;
+
+    /* Sort. Versioned dependencies first */
+    qsort(fc->fileDeps.data, fc->fileDeps.size, sizeof(fc->fileDeps.data[0]),
+	cmpVerDeps);
+
+    for (int i = 0; i < fc->fileDeps.size; i++) {
+	switch (rpmdsTagN(fc->fileDeps.data[i].dep)) {
+	case RPMTAG_REQUIRENAME:
+	case RPMTAG_RECOMMENDNAME:
+	case RPMTAG_SUGGESTNAME:
+	    rasprintf(&depStr, "%08x_%c_%s",
+		fc->fcolor[fc->fileDeps.data[i].fileIx],
+		rpmdsD(fc->fileDeps.data[i].dep),
+		rpmdsN(fc->fileDeps.data[i].dep));
+
+	    if (rpmdsFlags(fc->fileDeps.data[i].dep) & RPMSENSE_SENSEMASK) {
+		/* preserve versioned require dependency */
+		normalizedFDeps[ix++] = fc->fileDeps.data[i];
+		rpmstrPoolId(versionedDeps, depStr, 1);
+	    } else if (!rpmstrPoolId(versionedDeps, depStr, 0)) {
+		/* preserve unversioned require dep only if versioned dep doesn't exist */
+		    normalizedFDeps[ix++] =fc-> fileDeps.data[i];
+	    } else {
+		rpmdsFree(fc->fileDeps.data[i].dep);
+	    }
+	    free(depStr);
+	    break;
+	default:
+	    /* Preserve all non-require dependencies */
+	    normalizedFDeps[ix++] = fc->fileDeps.data[i];
+	    break;
+	}
+    }
+    rpmstrPoolFree(versionedDeps);
+
+    free(fc->fileDeps.data);
+    fc->fileDeps.data = normalizedFDeps;
+    fc->fileDeps.size = ix;
+}
+
 static rpmRC rpmfcApplyInternal(rpmfc fc)
 {
-    const char * s;
-    char * se;
     rpmds ds, * dsp;
-    rpmTagVal tagN;
-    const char * N;
-    const char * EVR;
-    rpmsenseFlags Flags;
-    unsigned char deptype;
-    int nddict;
     int previx;
     unsigned int val;
     int dix;
@@ -862,45 +943,28 @@ static rpmRC rpmfcApplyInternal(rpmfc fc)
 	}
     }
     /* No more additions after this, freeze pool to minimize memory use */
-    rpmstrPoolFreeze(fc->ddict, 0);
+
+    rpmfcNormalizeFDeps(fc);
+    for (int i = 0; i < fc->fileDeps.size; i++) {
+	ds = fc->fileDeps.data[i].dep;
+	rpmdsMerge(packageDependencies(fc->pkg, rpmdsTagN(ds)), ds);
+    }
+
+    /* Sort by index */
+    qsort(fc->fileDeps.data, fc->fileDeps.size,
+	sizeof(fc->fileDeps.data[0]), cmpIndexDeps);
 
     /* Generate per-file indices into package dependencies. */
-    nddict = rpmstrPoolNumStr(fc->ddict);
     previx = -1;
-    for (rpmsid id = 1; id <= nddict; id++) {
-	s = rpmstrPoolStr(fc->ddict, id);
-
-	/* Parse out (file#,deptype,N,EVR,Flags) */
-	ix = strtol(s, &se, 10);
-	if ( se == NULL ) {
-		rpmlog(RPMLOG_ERR, _("Conversion of %s to long integer failed.\n"), s);
-		return RPMRC_FAIL;
-	}
-	
-	deptype = *se++;
-	se++;
-	N = se;
-	while (*se && *se != ' ')
-	    se++;
-	*se++ = '\0';
-	EVR = se;
-	while (*se && *se != ' ')
-	    se++;
-	*se++ = '\0';
-	Flags = strtol(se, NULL, 16);
-
-	dix = -1;
-
-	tagN = rpmdsDToTagN(deptype);
-	dsp = packageDependencies(fc->pkg, tagN);
-	ds = rpmdsSinglePool(fc->pool, tagN, N, EVR, Flags);
+    for (int i = 0; i < fc->fileDeps.size; i++) {
+	ds = fc->fileDeps.data[i].dep;
+	ix = fc->fileDeps.data[i].fileIx;
+	dsp = packageDependencies(fc->pkg, rpmdsTagN(ds));
 	dix = rpmdsFind(*dsp, ds);
-	rpmdsFree(ds);
-
 	if (dix < 0)
 	    continue;
 
-	val = (deptype << 24) | (dix & 0x00ffffff);
+	val = (rpmdsD(ds) << 24) | (dix & 0x00ffffff);
 	argiAdd(&fc->ddictx, -1, val);
 
 	if (previx != ix) {
@@ -909,8 +973,8 @@ static rpmRC rpmfcApplyInternal(rpmfc fc)
 	}
 	if (fc->fddictn && fc->fddictn->vals)
 	    fc->fddictn->vals[ix]++;
-    }
 
+    }
     return RPMRC_OK;
 }
 
@@ -968,7 +1032,6 @@ rpmRC rpmfcClassify(rpmfc fc, ARGV_t argv, rpm_mode_t * fmode)
 
     /* Build (sorted) file class dictionary. */
     fc->cdict = rpmstrPoolCreate();
-    fc->ddict = rpmstrPoolCreate();
 
     ms = magic_open(msflags);
     if (ms == NULL) {
-- 
1.9.3