From b12cb085232a586ebca8673ee766d9d6e826c8dd Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Tue, 5 Feb 2008 11:43:38 +0200 Subject: [PATCH] Port some rpmds improvements from rpm5.org - rpmlib provides as rpmds, lose the special case hackery - new functions rpmdsRpmlib() and rpmdsSearch() + python bindings for them --- lib/Makefile.am | 2 +- lib/depends.c | 9 +++- lib/rpmds.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/rpmds.h | 19 ++++++++ lib/rpmlib.h | 24 ---------- lib/rpmlibprov.c | 135 ------------------------------------------------------ lib/rpmrc.c | 12 ++++- python/rpmds-py.c | 33 +++++++++++++ 8 files changed, 195 insertions(+), 163 deletions(-) delete mode 100644 lib/rpmlibprov.c diff --git a/lib/Makefile.am b/lib/Makefile.am index 99f9313..c9050e9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 \ diff --git a/lib/depends.c b/lib/depends.c index 89cb3cf..797a6df 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -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; } diff --git a/lib/rpmds.c b/lib/rpmds.c index 3af848a..62fd2e7 100644 --- a/lib/rpmds.c +++ b/lib/rpmds.c @@ -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; +} + diff --git a/lib/rpmds.h b/lib/rpmds.h index 2500e6b..75403bb 100644 --- a/lib/rpmds.h +++ b/lib/rpmds.h @@ -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 diff --git a/lib/rpmlib.h b/lib/rpmlib.h index babe007..f0df328 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -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 index 39cd659..0000000 --- a/lib/rpmlibprov.c +++ /dev/null @@ -1,135 +0,0 @@ -/** \ingroup rpmdep - * \file lib/rpmlibprov.c - */ - -#include "system.h" - -#include -#include /* rpmGetRpmlibProvides() & co protos */ -#include - -#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; -} diff --git a/lib/rpmrc.c b/lib/rpmrc.c index da1ce14..7b458d5 100644 --- a/lib/rpmrc.c +++ b/lib/rpmrc.c @@ -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); diff --git a/python/rpmds-py.c b/python/rpmds-py.c index fabd99e..87b12dc 100644 --- a/python/rpmds-py.c +++ b/python/rpmds-py.c @@ -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}, -- 2.7.4