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