From 2c673900ceacf28684b332fc38e97f878f37d9ba Mon Sep 17 00:00:00 2001 From: Alexey Tourbin Date: Mon, 10 Jan 2011 13:02:49 +0300 Subject: [PATCH] build/interdep.c: initial revision --- build/Makefile.am | 6 +-- build/files.c | 4 ++ build/interdep.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ build/interdep.h | 7 +++ 4 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 build/interdep.c create mode 100644 build/interdep.h diff --git a/build/Makefile.am b/build/Makefile.am index e765f38..2c5388e 100644 --- a/build/Makefile.am +++ b/build/Makefile.am @@ -12,12 +12,12 @@ LIBS = pkgincdir = $(pkgincludedir) pkginc_HEADERS = rpmbuild.h rpmspec.h -noinst_HEADERS = buildio.h checkFiles.h +noinst_HEADERS = buildio.h checkFiles.h interdep.h lib_LTLIBRARIES = librpmbuild.la librpmbuild_la_SOURCES = \ - build.c checkFiles.c expression.c files.c misc.c names.c pack.c \ - parseBuildInstallClean.c parseChangelog.c parseDescription.c \ + build.c checkFiles.c expression.c files.c interdep.c misc.c names.c \ + pack.c parseBuildInstallClean.c parseChangelog.c parseDescription.c \ parseFiles.c parsePreamble.c parsePrep.c parseReqs.c parseScript.c \ parseSpec.c poptBT.c reqprov.c spec.c librpmbuild_la_LDFLAGS = -release @VERSION@.1 diff --git a/build/files.c b/build/files.c index 2d5ca92..dc15770 100644 --- a/build/files.c +++ b/build/files.c @@ -2909,6 +2909,7 @@ static void printDeps(Header h) versions = hfd(versions, dvt); } +#include "interdep.h" #include "checkFiles.h" int processBinaryFiles(Spec spec, int installSpecialDoc, int test) @@ -2939,6 +2940,9 @@ int processBinaryFiles(Spec spec, int installSpecialDoc, int test) if (rc) break; } + if (rc == 0) + rc = processInterdep(spec); + if (rc == 0) rc = checkFiles(spec); diff --git a/build/interdep.c b/build/interdep.c new file mode 100644 index 0000000..05116fe --- /dev/null +++ b/build/interdep.c @@ -0,0 +1,124 @@ +/* + * interdep.c - inter-package analysis and optimizations based on + * strict dependencies between subpackages (Requires: N = [E:]V-R). + * + * Written by Alexey Tourbin . + * License: GPLv2+. + */ + +#include "system.h" +#include "rpmbuild.h" +#include "interdep.h" + +static +const char *skipPrefixDash(const char *str, const char *prefix) +{ + int len = strlen(prefix); + if (strncmp(str, prefix, len)) + return NULL; + if (str[len] != '-') + return NULL; + return str + len + 1; +} + +struct Req { + int c; + struct Pair { + Package pkg1; + Package pkg2; + } *v; +}; + +static +int Requires(struct Req *r, Package pkg1, Package pkg2) +{ + int i; + for (i = 0; i < r->c; i++) + if (pkg1 == r->v[i].pkg1 && pkg2 == r->v[i].pkg2) + return 1; + return 0; +} + +static +void addRequires(struct Req *r, Package pkg1, Package pkg2) +{ + if (Requires(r, pkg1, pkg2)) + return; + AUTO_REALLOC(r->v, r->c, 8); + r->v[r->c++] = (struct Pair) { pkg1, pkg2 }; +} + +static +void makeReq1(struct Req *r, Package pkg1, Package pkg2) +{ + int c = 0; + const char **reqNv = NULL; + const char **reqVv = NULL; + const int *reqFv = NULL; + const HGE_t hge = (HGE_t)headerGetEntryMinMemory; + int ok = + hge(pkg1->header, RPMTAG_REQUIRENAME, NULL, (void **) &reqNv, &c) && + hge(pkg1->header, RPMTAG_REQUIREVERSION, NULL, (void **) &reqVv, NULL) && + hge(pkg1->header, RPMTAG_REQUIREFLAGS, NULL, (void **) &reqFv, NULL); + if (!ok) + return; + const char *provN, *provV, *provR; + headerNVR(pkg2->header, &provN, &provV, &provR); + int i; + for (i = 0; i < c; i++) { + if (strcmp(reqNv[i], provN)) + continue; + if ((reqFv[i] & RPMSENSE_SENSEMASK) != RPMSENSE_EQUAL) + continue; + const char *reqVR = reqVv[i]; + if (*reqVR == '\0') + continue; + const char *reqR = skipPrefixDash(reqVR, provV); + if (reqR == NULL) { + // XXX handle epoch properly? + const char *colon = strchr(reqVR, ':'); + if (colon) + reqR = skipPrefixDash(colon + 1, provV); + } + if (reqR == NULL) + continue; + if (strcmp(reqR, provR)) + continue; + addRequires(r, pkg1, pkg2); + break; + } + const HFD_t hfd = (HFD_t) headerFreeData; + reqNv = hfd(reqNv, RPM_STRING_ARRAY_TYPE); + reqVv = hfd(reqVv, RPM_STRING_ARRAY_TYPE); +} + +static +struct Req *makeRequires(Spec spec) +{ + struct Req *r = xmalloc(sizeof *r); + r->c = 0; + r->v = NULL; + Package pkg1, pkg2; + for (pkg1 = spec->packages; pkg1; pkg1 = pkg1->next) + for (pkg2 = pkg1->next; pkg2; pkg2 = pkg2->next) { + makeReq1(r, pkg1, pkg2); + makeReq1(r, pkg2, pkg1); + } + return r; +} + +static +struct Req *freeRequires(struct Req *r) +{ + r->v = _free(r->v); + return _free(r); +} + +int processInterdep(Spec spec) +{ + struct Req *r = makeRequires(spec); + r = freeRequires(r); + return 0; +} + +// ex: set ts=8 sts=4 sw=4 noet: diff --git a/build/interdep.h b/build/interdep.h new file mode 100644 index 0000000..ea052a9 --- /dev/null +++ b/build/interdep.h @@ -0,0 +1,7 @@ +#ifndef INTERDEP_H +#define INTERDEP_H + +/* Perform inter-package analysis and optimizations. */ +int processInterdep(Spec spec); + +#endif