Port some rpmds improvements from rpm5.org
authorPanu Matilainen <pmatilai@redhat.com>
Tue, 5 Feb 2008 09:43:38 +0000 (11:43 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Tue, 5 Feb 2008 09:43:38 +0000 (11:43 +0200)
- rpmlib provides as rpmds, lose the special case hackery
- new functions rpmdsRpmlib() and rpmdsSearch() + python bindings for them

lib/Makefile.am
lib/depends.c
lib/rpmds.c
lib/rpmds.h
lib/rpmlib.h
lib/rpmlibprov.c [deleted file]
lib/rpmrc.c
python/rpmds-py.c

index 99f9313..c9050e9 100644 (file)
@@ -22,7 +22,7 @@ librpm_la_SOURCES = \
        poptALL.c poptI.c poptQV.c psm.c psm.h query.c \
        rpmal.c rpmchecksig.c rpmds.c rpmfi.c rpmfi_internal.h rpmgi.c \
        rpminstall.c rpmtsscore.h rpmts_internal.h \
-       rpmlead.c rpmlead.h rpmlibprov.c rpmps.c rpmrc.c \
+       rpmlead.c rpmlead.h rpmps.c rpmrc.c \
        rpmte.c rpmte_internal.h rpmts.c \
        rpmvercmp.c signature.c signature.h transaction.c \
        verify.c rpmlock.c rpmlock.h misc.h \
index 89cb3cf..797a6df 100644 (file)
@@ -40,6 +40,9 @@ const char *rpmEVR = VERSION;
 
 int rpmFLAGS = RPMSENSE_EQUAL;
 
+/* rpmlib provides */
+static rpmds rpmlibP = NULL;
+
 /**
  * Compare removed package instances (qsort/bsearch).
  * @param a            1st instance address
@@ -435,7 +438,11 @@ retry:
      * Check those dependencies now.
      */
     if (!strncmp(Name, "rpmlib(", sizeof("rpmlib(")-1)) {
-       if (rpmCheckRpmlibProvides(dep)) {
+       static int oneshot = -1;
+       if (oneshot) 
+           oneshot = rpmdsRpmlib(&rpmlibP, NULL);
+       
+       if (rpmlibP != NULL && rpmdsSearch(rpmlibP, dep) >= 0) {
            rpmdsNotify(dep, _("(rpmlib provides)"), rc);
            goto exit;
        }
index 3af848a..62fd2e7 100644 (file)
@@ -701,6 +701,63 @@ ods->i = save;
     return 0;
 }
 
+
+int rpmdsSearch(rpmds ds, rpmds ods)
+{
+    int comparison;
+    int i, l, u;
+
+    if (ds == NULL || ods == NULL)
+       return -1;
+
+    /* Binary search to find the [l,u) subset that contains N */
+    i = -1;
+    l = 0;
+    u = ds->Count;
+    while (l < u) {
+       i = (l + u) / 2;
+
+       comparison = strcmp(ods->N[ods->i], ds->N[i]);
+
+       if (comparison < 0)
+           u = i;
+       else if (comparison > 0)
+           l = i + 1;
+       else {
+           /* Set l to 1st member of set that contains N. */
+           if (strcmp(ods->N[ods->i], ds->N[l]))
+               l = i;
+           while (l > 0 && !strcmp(ods->N[ods->i], ds->N[l-1]))
+               l--;
+           /* Set u to 1st member of set that does not contain N. */
+           if (u >= ds->Count || strcmp(ods->N[ods->i], ds->N[u]))
+               u = i;
+           while (++u < ds->Count) {
+               if (strcmp(ods->N[ods->i], ds->N[u]))
+                   /*@innerbreak@*/ break;
+           }
+           break;
+       }
+    }
+
+    /* Check each member of [l,u) subset for ranges overlap. */
+    i = -1;
+    if (l < u) {
+       int save = rpmdsSetIx(ds, l-1);
+       while ((l = rpmdsNext(ds)) >= 0 && (l < u)) {
+           if ((i = rpmdsCompare(ods, ds)) != 0)
+               break;
+       }
+       /* Return element index that overlaps, or -1. */
+       if (i)
+           i = rpmdsIx(ds);
+       else {
+           (void) rpmdsSetIx(ds, save);
+           i = -1;
+       }
+    }
+    return i;
+}
 /**
  * Split EVR into epoch, version, and release components.
  * @param evr          [epoch:]version[-release] string
@@ -947,3 +1004,70 @@ int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote)
 
     return rc;
 }
+
+/**
+ */
+struct rpmlibProvides_s {
+    const char * featureName;
+    const char * featureEVR;
+    rpmsenseFlags featureFlags;
+    const char * featureDescription;
+};
+
+static struct rpmlibProvides_s rpmlibProvides[] = {
+    { "rpmlib(VersionedDependencies)", "3.0.3-1",
+       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
+    N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.") },
+    { "rpmlib(CompressedFileNames)",   "3.0.4-1",
+       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
+    N_("file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path.")},
+#if HAVE_BZLIB_H
+    { "rpmlib(PayloadIsBzip2)",                "3.0.5-1",
+       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
+    N_("package payload can be compressed using bzip2.") },
+#endif
+    { "rpmlib(PayloadFilesHavePrefix)",        "4.0-1",
+       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
+    N_("package payload file(s) have \"./\" prefix.") },
+    { "rpmlib(ExplicitPackageProvide)",        "4.0-1",
+       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
+    N_("package name-version-release is not implicitly provided.") },
+    { "rpmlib(HeaderLoadSortsTags)",    "4.0.1-1",
+       (                RPMSENSE_EQUAL),
+    N_("header tags are always sorted after being loaded.") },
+    { "rpmlib(ScriptletInterpreterArgs)",    "4.0.3-1",
+       (                RPMSENSE_EQUAL),
+    N_("the scriptlet interpreter can use arguments from header.") },
+    { "rpmlib(PartialHardlinkSets)",    "4.0.4-1",
+       (                RPMSENSE_EQUAL),
+    N_("a hardlink file set may be installed without being complete.") },
+    { "rpmlib(ConcurrentAccess)",    "4.1-1",
+       (                RPMSENSE_EQUAL),
+    N_("package scriptlets may access the rpm database while installing.") },
+#ifdef WITH_LUA
+    { "rpmlib(BuiltinLuaScripts)",    "4.2.2-1",
+       (                RPMSENSE_EQUAL),
+    N_("internal support for lua scripts.") },
+#endif
+    { NULL,                            NULL, 0,        NULL }
+};
+
+
+int rpmdsRpmlib(rpmds * dsp, void * tblp)
+{
+    const struct rpmlibProvides_s * rltblp = tblp;
+    const struct rpmlibProvides_s * rlp;
+    int xx;
+
+    if (rltblp == NULL)
+       rltblp = rpmlibProvides;
+
+    for (rlp = rltblp; rlp->featureName != NULL; rlp++) {
+       rpmds ds = rpmdsSingle(RPMTAG_PROVIDENAME, rlp->featureName,
+                       rlp->featureEVR, rlp->featureFlags);
+       xx = rpmdsMerge(dsp, ds);
+       ds = rpmdsFree(ds);
+    }
+    return 0;
+}
+
index 2500e6b..75403bb 100644 (file)
@@ -315,6 +315,17 @@ int rpmdsFind(rpmds ds, const rpmds ods);
 int rpmdsMerge(rpmds * dsp, rpmds ods);
 
 /** \ingroup rpmds
+ * Search a sorted dependency set for an element that overlaps.
+ * A boolean result is saved (if allocated) and accessible through
+ * rpmdsResult(ods) afterwards.
+ * @param ds            dependency set to search
+ * @param ods           dependency set element to find.
+ * @return              dependency index (or -1 if not found)
+ **/
+int rpmdsSearch(rpmds ds, rpmds ods);
+
+
+/** \ingroup rpmds
  * Compare two versioned dependency ranges, looking for overlap.
  * @param A            1st dependency
  * @param B            2nd dependency
@@ -352,6 +363,14 @@ int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote);
  */
 int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote);
 
+/**
+ * Load rpmlib provides into a dependency set.
+ * @retval *dsp                (loaded) depedency set
+ * @param tblp         rpmlib provides table (NULL uses internal table)
+ * @return             0 on success
+ */
+int rpmdsRpmlib(rpmds * dsp, void * tblp);
+
 #ifdef __cplusplus
 }
 #endif
index babe007..f0df328 100644 (file)
@@ -202,17 +202,6 @@ rpmRC rpmInstallSourcePackage(rpmts ts, FD_t fd,
                        char ** cookie);
 
 /** \ingroup rpmtrans
- * Return copy of rpmlib internal provides.
- * @retval provNames   address of array of rpmlib internal provide names
- * @retval provFlags   address of array of rpmlib internal provide flags
- * @retval provVersions        address of array of rpmlib internal provide versions
- * @return             no. of entries
- */
-int rpmGetRpmlibProvides(const char *** provNames,
-                       rpmsenseFlags ** provFlags,
-                       const char *** provVersions);
-
-/** \ingroup rpmtrans
  * Segmented string compare for version and/or release.
  *
  * @param a            1st string
@@ -221,19 +210,6 @@ int rpmGetRpmlibProvides(const char *** provNames,
  */
 int rpmvercmp(const char * a, const char * b);
 
-/** \ingroup rpmtrans
- * Check dependency against internal rpmlib feature provides.
- * @param key          dependency
- * @return             1 if dependency overlaps, 0 otherwise
- */
-int rpmCheckRpmlibProvides(const rpmds key);
-
-/** \ingroup rpmcli
- * Display current rpmlib feature provides.
- * @param fp           output file handle
- */
-void rpmShowRpmlibProvides(FILE * fp);
-
 /**
  * Release storage used by file system usage cache.
  */
diff --git a/lib/rpmlibprov.c b/lib/rpmlibprov.c
deleted file mode 100644 (file)
index 39cd659..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/** \ingroup rpmdep
- * \file lib/rpmlibprov.c
- */
-
-#include "system.h"
-
-#include <rpm/rpmtag.h>
-#include <rpm/rpmlib.h>                /* rpmGetRpmlibProvides() & co protos */
-#include <rpm/rpmds.h>
-
-#include "debug.h"
-
-/**
- */
-struct rpmlibProvides_s {
-    const char * featureName;
-    const char * featureEVR;
-    rpmsenseFlags featureFlags;
-    const char * featureDescription;
-};
-
-static struct rpmlibProvides_s rpmlibProvides[] = {
-    { "rpmlib(VersionedDependencies)", "3.0.3-1",
-       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-    N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.") },
-    { "rpmlib(CompressedFileNames)",   "3.0.4-1",
-       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-    N_("file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path.")},
-#if HAVE_BZLIB_H
-    { "rpmlib(PayloadIsBzip2)",                "3.0.5-1",
-       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-    N_("package payload can be compressed using bzip2.") },
-#endif
-    { "rpmlib(PayloadFilesHavePrefix)",        "4.0-1",
-       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-    N_("package payload file(s) have \"./\" prefix.") },
-    { "rpmlib(ExplicitPackageProvide)",        "4.0-1",
-       (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
-    N_("package name-version-release is not implicitly provided.") },
-    { "rpmlib(HeaderLoadSortsTags)",    "4.0.1-1",
-       (                RPMSENSE_EQUAL),
-    N_("header tags are always sorted after being loaded.") },
-    { "rpmlib(ScriptletInterpreterArgs)",    "4.0.3-1",
-       (                RPMSENSE_EQUAL),
-    N_("the scriptlet interpreter can use arguments from header.") },
-    { "rpmlib(PartialHardlinkSets)",    "4.0.4-1",
-       (                RPMSENSE_EQUAL),
-    N_("a hardlink file set may be installed without being complete.") },
-    { "rpmlib(ConcurrentAccess)",    "4.1-1",
-       (                RPMSENSE_EQUAL),
-    N_("package scriptlets may access the rpm database while installing.") },
-#ifdef WITH_LUA
-    { "rpmlib(BuiltinLuaScripts)",    "4.2.2-1",
-       (                RPMSENSE_EQUAL),
-    N_("internal support for lua scripts.") },
-#endif
-    { NULL,                            NULL, 0,        NULL }
-};
-
-void rpmShowRpmlibProvides(FILE * fp)
-{
-    const struct rpmlibProvides_s * rlp;
-
-    for (rlp = rpmlibProvides; rlp->featureName != NULL; rlp++) {
-/* FIX: rlp->featureEVR not NULL */
-       rpmds pro = rpmdsSingle(RPMTAG_PROVIDENAME, rlp->featureName,
-                       rlp->featureEVR, rlp->featureFlags);
-       const char * DNEVR = rpmdsDNEVR(pro);
-
-       if (pro != NULL && DNEVR != NULL) {
-           fprintf(fp, "    %s\n", DNEVR+2);
-           if (rlp->featureDescription)
-               fprintf(fp, "\t%s\n", rlp->featureDescription);
-       }
-       pro = rpmdsFree(pro);
-    }
-}
-
-int rpmCheckRpmlibProvides(const rpmds key)
-{
-    const struct rpmlibProvides_s * rlp;
-    int rc = 0;
-
-    for (rlp = rpmlibProvides; rlp->featureName != NULL; rlp++) {
-       if (rlp->featureEVR && rlp->featureFlags) {
-           rpmds pro;
-           pro = rpmdsSingle(RPMTAG_PROVIDENAME, rlp->featureName,
-                       rlp->featureEVR, rlp->featureFlags);
-           rc = rpmdsCompare(pro, key);
-           pro = rpmdsFree(pro);
-       }
-       if (rc)
-           break;
-    }
-    return rc;
-}
-
-int rpmGetRpmlibProvides(const char *** provNames, rpmsenseFlags ** provFlags,
-                         const char *** provVersions)
-{
-    const char ** names, ** versions;
-    rpmsenseFlags * flags;
-    int n = 0;
-    
-    while (rpmlibProvides[n].featureName != NULL)
-        n++;
-
-    names = xcalloc((n+1), sizeof(*names));
-    versions = xcalloc((n+1), sizeof(*versions));
-    flags = xcalloc((n+1), sizeof(*flags));
-    
-    for (n = 0; rpmlibProvides[n].featureName != NULL; n++) {
-        names[n] = rpmlibProvides[n].featureName;
-        flags[n] = rpmlibProvides[n].featureFlags;
-        versions[n] = rpmlibProvides[n].featureEVR;
-    }
-    
-    if (provNames)
-       *provNames = names;
-    else
-       names = _free(names);
-
-    if (provFlags)
-       *provFlags = flags;
-    else
-       flags = _free(flags);
-
-    if (provVersions)
-       *provVersions = versions;
-    else
-       versions = _free(versions);
-
-    /* FIX: rpmlibProvides[] reachable */
-    return n;
-}
index da1ce14..7b458d5 100644 (file)
@@ -1754,7 +1754,8 @@ int rpmReadConfigFiles(const char * file, const char * target)
 int rpmShowRC(FILE * fp)
 {
     struct rpmOption *opt;
-    int i;
+    rpmds ds = NULL;
+    int i, xx;
     machEquivTable equivTable;
 
     /* the caller may set the build arch which should be printed here */
@@ -1802,7 +1803,14 @@ int rpmShowRC(FILE * fp)
     fprintf(fp, "\n");
 
     fprintf(fp, "Features supported by rpmlib:\n");
-    rpmShowRpmlibProvides(fp);
+    xx = rpmdsRpmlib(&ds, NULL);
+    ds = rpmdsInit(ds);
+    while (rpmdsNext(ds) >= 0) {
+        const char * DNEVR = rpmdsDNEVR(ds);
+        if (DNEVR != NULL)
+            fprintf(fp, "    %s\n", DNEVR+2);
+    }
+    ds = rpmdsFree(ds);
     fprintf(fp, "\n");
 
     rpmDumpMacroTable(NULL, fp);
index fabd99e..87b12dc 100644 (file)
@@ -312,6 +312,33 @@ rpmds_Merge(rpmdsObject * s, PyObject * args, PyObject * kwds)
     o = (rpmdsObject *)to;
     return Py_BuildValue("i", rpmdsMerge(&s->ds, o->ds));
 }
+static PyObject *
+rpmds_Search(rpmdsObject * s, PyObject * args, PyObject * kwds)
+{
+    PyObject * to = NULL;
+    rpmdsObject * o;
+    char * kwlist[] = {"element", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Merge", kwlist, &to))
+        return NULL;
+
+    /* XXX ds type check needed. */
+    o = (rpmdsObject *)to;
+    return Py_BuildValue("i", rpmdsSearch(s->ds, o->ds));
+}
+
+static PyObject *
+rpmds_Rpmlib(rpmdsObject * s)
+{
+    rpmds ds = NULL;
+    int xx;
+
+    /* XXX check return code, permit arg (NULL uses system default). */
+    xx = rpmdsRpmlib(&ds, NULL);
+
+    return (PyObject *) rpmds_Wrap( ds );
+}
+
 
 #ifdef NOTYET
 static PyObject *
@@ -375,6 +402,12 @@ static struct PyMethodDef rpmds_methods[] = {
        NULL},
  {"Merge",     (PyCFunction)rpmds_Merge,       METH_VARARGS|METH_KEYWORDS,
        NULL},
+ {"Search",     (PyCFunction)rpmds_Search,      METH_VARARGS|METH_KEYWORDS,
+"ds.Search(element) -> matching ds index (-1 on failure)\n\
+- Check that element dependency range overlaps some member of ds.\n\
+The current index in ds is positioned at overlapping member upon success.\n" },
+ {"Rpmlib",     (PyCFunction)rpmds_Rpmlib,      METH_NOARGS|METH_STATIC,
+       "ds.Rpmlib -> nds       - Return internal rpmlib dependency set.\n"},
 #ifdef NOTYET
  {"Compare",   (PyCFunction)rpmds_Compare,     METH_VARARGS|METH_KEYWORDS,
        NULL},