From 34f9295baf2fe661c4d2d36e59a57515aa4ad9ea Mon Sep 17 00:00:00 2001 From: Silvan Calarco Date: Wed, 9 Jan 2013 14:07:46 +0100 Subject: [PATCH] General rework to support updated packages - keep updated source and binary rpm structures - detect and report broken requirements due to package updates - TODO: check datatables output before stabilizing for a new release --- src/distromatic.c | 56 ++++++++++--- src/headerlist.c | 93 +++++++++++----------- src/include/headerlist.h | 1 + src/reports.c | 168 ++++++++++++++++++--------------------- 4 files changed, 168 insertions(+), 150 deletions(-) diff --git a/src/distromatic.c b/src/distromatic.c index 49c7346..bc31ab3 100644 --- a/src/distromatic.c +++ b/src/distromatic.c @@ -225,7 +225,7 @@ compareRequiredList(const void *ptr1, const void *ptr2) /* * inspect multiple providing packages in providedList - * and remove providers those that are obsoleted by others + * and remove providers that are obsoleted by others */ int handleObsoletedPackages(struct configTag *ct, int archidx) @@ -247,7 +247,8 @@ handleObsoletedPackages(struct configTag *ct, int archidx) for (i = 0; i < prov->numproviders; i++) for (j = 0; j < prov->provider[i]->obsoletecount; j++) for (k = 0; k < prov->numproviders; k++) - if (!strcmp(prov->provider[i]->obsoletename[j],prov->provider[k]->name)) { + if (!strcmp(prov->provider[i]->obsoletename[j],prov->provider[k]->name) + && strcmp(prov->provider[i]->name,prov->provider[k]->name)) { if (prov->provider[i]->obsoleteflags[j] & (RPMSENSE_EQUAL|RPMSENSE_GREATER|RPMSENSE_LESS)) { snprintf(buf, PATH_MAX, "%s-%s",prov->provider[k]->version,prov->provider[k]->release); if (!checkVersionWithFlags( @@ -324,7 +325,7 @@ handleObsoletedPackages(struct configTag *ct, int archidx) currheader->obsoletename[j],0); if (prov) { for (i = 0; i < prov->numproviders; i++) { - if (prov->provider[i] != currheader) { + if (strcmp(currheader->name,prov->provider[i]->name)) { prov->provider[i]->obsoleted = 1; if (!strcmp(prov->name,prov->provider[i]->name)) { snprintf(buf, PATH_MAX, "%s(%s,%s) obsoletes %s(%s,%s)", @@ -376,9 +377,9 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) while (currheader) { scanheader = ct->headerlist[archidx]; currheader->requirelist = NULL; - if ((!currheader->obsoleted) && (currheader->next) && (!strcmp(currheader->name,currheader->next->name))) { + if ((!currheader->obsoleted) && (currheader->next) && (currheader->sourceheader->updatingparent)) { // mark obsoleted any package with same name in upper level repositories - if (currheader->altrepository < currheader->next->altrepository) { + if (currheader->altrepository < currheader->sourceheader->updatingparent->altrepository) { currheader->obsoleted = 1; if (checkVersionWithFlags( currheader->version, @@ -394,7 +395,7 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) fprintf(stderr,"Warning: %s\n",warning); addWarning(currheader->sourceheader,warning); } - } else if (currheader->altrepository >= currheader->next->altrepository) { + } else if (currheader->altrepository >= currheader->sourceheader->updatingparent->altrepository) { currheader->next->obsoleted = 1; if (checkVersionWithFlags( currheader->version, @@ -413,7 +414,7 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) } } - if (currheader->obsoleted) { + if (currheader->obsoleted || currheader->sourceheader->updatingparent) { currheader = currheader->next; continue; } @@ -471,16 +472,19 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) addWarning(currheader->sourceheader,warning); } } else { /* provided->numproviders > 0 */ + /* warn about provides only provided by older packages */ k=0; for (j = 0; j < provided->numproviders; j++) { - if (provided->provider[j]->obsoleted && !currheader->obsoleted) k++; + if (provided->provider[j]->sourceheader->updatingparent && + provided->provider[j]->sourceheader->updatingparent->firstchild[archidx] && /* skip if not built for arch */ + !currheader->obsoleted) k++; } - if (k == provided->numproviders) { // all provides are obsoleted - snprintf(warning, PATH_MAX, "%s needed by %s(%s,%s) is only provided by obsoleted package(s):", - provided->name, + if (k == provided->numproviders) { // all provides are from older packages + snprintf(warning, PATH_MAX, "%s(%s,%s) requires %s which is only provided by older package(s):", currheader->name, currheader->arch, - ct->repository[currheader->altrepository]->tag); + ct->repository[currheader->altrepository]->tag, + provided->name); for (j = 0; j < provided->numproviders; j++) { snprintf(&warning[strlen(warning)], PATH_MAX - strlen(warning), " %s(%s,%s)", provided->provider[j]->name, @@ -488,7 +492,33 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) ct->repository[provided->provider[j]->altrepository]->tag); } fprintf(stderr,"Warning: %s\n",warning); - addWarning(currheader->sourceheader,warning); + for (j = 0; j < provided->numproviders; j++) { + addWarning(provided->provider[j]->sourceheader,warning); + } + } else { + /* warn about provides provided by obsoleted packages */ + k=0; + for (j = 0; j < provided->numproviders; j++) { + if (provided->provider[j]->obsoleted && !currheader->obsoleted) k++; + } + if (k == provided->numproviders) { // all provides are obsoleted + snprintf(warning, PATH_MAX, "%s(%s,%s) requires %s which is only provided by obsoleted package(s):", + currheader->name, + currheader->arch, + ct->repository[currheader->altrepository]->tag, + provided->name); + for (j = 0; j < provided->numproviders; j++) { + snprintf(&warning[strlen(warning)], PATH_MAX - strlen(warning), " %s(%s,%s)", + provided->provider[j]->name, + provided->provider[j]->arch, + ct->repository[provided->provider[j]->altrepository]->tag); + } + fprintf(stderr,"Warning: %s\n",warning); + addWarning(currheader->sourceheader,warning); + for (j = 0; j < provided->numproviders; j++) { + addWarning(provided->provider[j]->sourceheader,warning); + } + } } if ((currheader->require[i]->name)[0] == '/') { /* when there is a Requires: /file/requirement add provide from file tree as well */ diff --git a/src/headerlist.c b/src/headerlist.c index ae80996..75702fa 100644 --- a/src/headerlist.c +++ b/src/headerlist.c @@ -1,7 +1,7 @@ /* * distromatic - tool for RPM based repositories * - * Copyright (C) 2004-2010 by Silvan Calarco + * Copyright (C) 2004-2013 by Silvan Calarco * Copyright (C) 2006 by Davide Madrisan * * This program is free software; you can redistribute it and/or modify it under @@ -128,14 +128,24 @@ findSourcePackage(struct headerSourceList *list, char *name, char *version, char *release, int altrepository) { struct headerSourceList *currheaderlist = list; + struct headerSourceList *oldheaderlist; while (currheaderlist) { - if ((!strcmp(name, currheaderlist->name)) && - ((!release) || !strcmp(release, currheaderlist->release)) && - ((!version) || !strcmp(version, currheaderlist->version)) && - ((altrepository < 0) || (altrepository == currheaderlist->altrepository))) + if (!strcmp(name, currheaderlist->name)) { + if (((!release) || !strcmp(release, currheaderlist->release)) && + ((!version) || !strcmp(version, currheaderlist->version)) && + ((altrepository < 0) || (altrepository == currheaderlist->altrepository))) return currheaderlist; - currheaderlist = currheaderlist->next; + oldheaderlist = currheaderlist->old; + while (oldheaderlist) { + if (((!release) || !strcmp(release, oldheaderlist->release)) && + ((!version) || !strcmp(version, oldheaderlist->version)) && + ((altrepository < 0) || (altrepository == oldheaderlist->altrepository))) + return oldheaderlist; + oldheaderlist = oldheaderlist->old; + } + } + currheaderlist = currheaderlist->next; } return NULL; @@ -583,6 +593,7 @@ addToSourceHeaderList(struct headerSourceList **headersourcelist, struct configT for (arch = 0; arch < ARCHS_MAX; arch++) { newheadersourcelist->firstchild[arch] = NULL; } + newheadersourcelist->updatingparent = NULL; newheadersourcelist->altrepository = altrepository; newheadersourcelist->firstwarning = NULL; newheadersourcelist->old = NULL; @@ -685,7 +696,7 @@ addToSourceHeaderList(struct headerSourceList **headersourcelist, struct configT newheadersourcelist->next = currheadersourcelist->next; /* overriden package is not deallocated but referenced with currheadersourcelist->old */ newheadersourcelist->old=currheadersourcelist; - currheadersourcelist=newheadersourcelist; + newheadersourcelist->old->updatingparent=newheadersourcelist; } else { /* add the new package to the list */ newheadersourcelist->next = currheadersourcelist; @@ -838,25 +849,26 @@ addToHeaderList(struct configTag *ct, strncpy(filename, namelist[cnt]->d_name,bufsize-strlen(scanpath)); altrepository=0; cnt++; - } - - for (i = 0; i < ALT_REPS_MAX; i++) { - if (altscanpath[i] && (altcnt[i] < altn[i]) && - (strncmp(currname, altnamelist[i][altcnt[i]]->d_name, bufsize) == 0)) { - /* selected package exists in this repository */ - memcpy(filepath, altscanpath[i], strlen(altscanpath[i]) + 1); - filename=&filepath[strlen(altscanpath[i])]; - strncpy(filename, (altnamelist[i])[altcnt[i]]->d_name, bufsize-strlen(altscanpath[i])); - altrepository=i+1; - altcnt[i]++; - /* check for duplicates in alternate repository */ - if ((altcnt[i] < altn[i] - 1) && - (!rpmnamecmp(altnamelist[i][altcnt[i]]->d_name,altnamelist[i][altcnt[i]+1]->d_name,0))) { - if (i == ct->repository_level-1) { - logmsg(LOG_WARNING, "%s: duplicated RPM package (skipped)", - altnamelist[i][altcnt[i]]->d_name, altscantag[i]); - } - } + } else { + for (i = 0; i < ALT_REPS_MAX; i++) { + if (altscanpath[i] && (altcnt[i] < altn[i]) && + (strncmp(currname, altnamelist[i][altcnt[i]]->d_name, bufsize) == 0)) { + /* selected package exists in this repository */ + memcpy(filepath, altscanpath[i], strlen(altscanpath[i]) + 1); + filename=&filepath[strlen(altscanpath[i])]; + strncpy(filename, (altnamelist[i])[altcnt[i]]->d_name, bufsize-strlen(altscanpath[i])); + altrepository=i+1; + altcnt[i]++; + /* check for duplicates in alternate repository */ + if ((altcnt[i] < altn[i] - 1) && + (!rpmnamecmp(altnamelist[i][altcnt[i]]->d_name,altnamelist[i][altcnt[i]+1]->d_name,0))) { + if (i == ct->repository_level-1) { + logmsg(LOG_WARNING, "%s: duplicated RPM package (skipped)", + altnamelist[i][altcnt[i]]->d_name, altscantag[i]); + } + } + break; + } } } @@ -939,17 +951,6 @@ addToHeaderList(struct configTag *ct, } else if (newheaderlist->sourcename) /* missing source header */ { - /* checking whether the source package exists in a - different version. In this case if the SRPM package - is an update from an alternate repository don't - display any warning. */ - newheaderlist->sourceheader = - findSourcePackage(ct->headersourcelist, - newheaderlist->sourcename, - NULL, - NULL, - -1); - if ((!newheaderlist->sourceheader) || (newheaderlist->sourceheader->altrepository) <= altrepository) { @@ -983,16 +984,14 @@ addToHeaderList(struct configTag *ct, if (!strcmp(provided->provider[j]->name,newheaderlist->name)) break; } /* if not add to the list of providers */ - if (j == provided->numproviders) { - provided->numproviders++; - newprovider=malloc(sizeof(struct headerList*)*provided->numproviders); - for (j = 0; j < provided->numproviders-1; j++) { - newprovider[j]=provided->provider[j]; - } - newprovider[provided->numproviders-1] = newheaderlist; - free(provided->provider); - provided->provider=newprovider; - } + provided->numproviders++; + newprovider=malloc(sizeof(struct headerList*)*provided->numproviders); + for (j = 0; j < provided->numproviders-1; j++) { + newprovider[j]=provided->provider[j]; + } + newprovider[provided->numproviders-1] = newheaderlist; + free(provided->provider); + provided->provider=newprovider; /* check if version is already provided */ for (j = 0; j < provided->numversions; j++) { diff --git a/src/include/headerlist.h b/src/include/headerlist.h index 9b0a384..09608a2 100644 --- a/src/include/headerlist.h +++ b/src/include/headerlist.h @@ -122,6 +122,7 @@ struct headerSourceList { struct changeLog *changelog; struct headerList *firstchild[ARCHS_MAX]; struct warningList *firstwarning; + struct headerSourceList *updatingparent; }; struct headerStats { diff --git a/src/reports.c b/src/reports.c index 60fa9cb..2463b3b 100644 --- a/src/reports.c +++ b/src/reports.c @@ -88,15 +88,20 @@ printHTMLWarnings(FILE *fout,struct configTag *configtag, struct headerSourceLis struct stat s; FILE *fin; int n; - struct warningList *currwarning; + struct warningList *firstwarning,*currwarning; if (!pkg) return 0; - currwarning = pkg->firstwarning; - snprintf(warningsfile,PATH_MAX,"%swarnings/%s.in",configtag->html_dir,pkg->name); - if (pkg->firstwarning || !stat(warningsfile,&s)) { + /* find pointer to first warning also looking into old packages */ + firstwarning = pkg->firstwarning; + while (!firstwarning && pkg->old) { + pkg = pkg->old; + firstwarning = pkg->firstwarning; + } + + if (firstwarning || !stat(warningsfile,&s)) { if (mode == 0) { fprintf(fout, "text); - } else if (mode == 1) { - fprintf(fout," • %s
",currwarning->text); + currwarning = firstwarning; + while (currwarning || pkg->old) { + if (currwarning) { + if (mode == 0) { + fprintf(fout," • %s\n",currwarning->text); + } else if (mode == 1) { + fprintf(fout," • %s
",currwarning->text); + } + currwarning = currwarning->next; + } + while (!currwarning && pkg->old) { + /* print warnings coming from updated packages */ + pkg = pkg->old; + currwarning = pkg->firstwarning; } - currwarning = currwarning->next; } - if (pkg->firstwarning || !stat(warningsfile,&s)) { + if (firstwarning || !stat(warningsfile,&s)) { if (mode == 0) { fprintf(fout,"\">"); } else if (mode == 1) { @@ -1183,28 +1196,24 @@ generateHTML_SRPMSFiles(struct configTag *configtag) } else if (currheadersourcelist->require[i]->resolved->numbuildproviders == 1) { // single provider if ((i == 0 || - strcmp(currheadersourcelist->require[i-1]->name, - currheadersourcelist->require[i]->name)) && - strcmp(currheadersourcelist->name, - currheadersourcelist->require[i]->name)) { - if ((configtag->repository_level == 0) || - (currheadersourcelist->require[i]->resolved->buildprovider[0]->sourceheader && - currheadersourcelist->require[i]->resolved->buildprovider[0]->altrepository == configtag->repository_level)) { - fprintf(fout,"%s", - configtag->configdefaults->url_prefix, - configtag->tag, - currheadersourcelist->require[i]->resolved->name, - configtag->arch[0], - currheadersourcelist->require[i]->resolved->name); - if (configtag->repository_level > 0) { - snprintf(buffer, PATH_MAX, "has build requirement %s which is provided in this repository", - currheadersourcelist->require[i]->resolved->name); - addWarning(currheadersourcelist, buffer); - } - } else { - fprintf(fout,"%s",currheadersourcelist->require[i]->resolved->name); - } - } + strcmp(currheadersourcelist->require[i-1]->name, + currheadersourcelist->require[i]->name)) && + strcmp(currheadersourcelist->name, + currheadersourcelist->require[i]->name)) { + fprintf(fout,"%s", + configtag->configdefaults->url_prefix, + configtag->repository[currheadersourcelist->require[i]->resolved->buildprovider[0]->altrepository]->tag, + currheadersourcelist->require[i]->resolved->name, + configtag->arch[0], + currheadersourcelist->require[i]->resolved->name); + if ((configtag->repository_level > 0) && + currheadersourcelist->require[i]->resolved->buildprovider[0]->sourceheader && + (currheadersourcelist->require[i]->resolved->buildprovider[0]->altrepository == configtag->repository_level)) { + snprintf(buffer, PATH_MAX, "has build requirement %s which is only provided in this repository", + currheadersourcelist->require[i]->resolved->name); + addWarning(currheadersourcelist, buffer); + } + } } else { // multiple providers if (i == 0 || @@ -1212,17 +1221,12 @@ generateHTML_SRPMSFiles(struct configTag *configtag) currheadersourcelist->require[i]->resolved->name)) fprintf(fout,"%s(",currheadersourcelist->require[i]->resolved->name); for (j = 0; j < currheadersourcelist->require[i]->resolved->numbuildproviders; j++) { - if ((configtag->repository_level == 0) || - (currheadersourcelist->require[i]->resolved->buildprovider[j]->sourceheader && - currheadersourcelist->require[i]->resolved->buildprovider[j]->altrepository == configtag->repository_level)) - fprintf(fout,"%s", + fprintf(fout,"%s", configtag->configdefaults->url_prefix, - configtag->tag, + configtag->repository[currheadersourcelist->require[i]->resolved->buildprovider[j]->altrepository]->tag, currheadersourcelist->require[i]->resolved->buildprovider[j]->name, configtag->arch[0], currheadersourcelist->require[i]->resolved->buildprovider[j]->name); - else - fprintf(fout,"%s",currheadersourcelist->require[i]->resolved->buildprovider[j]->name); if (j+1 < currheadersourcelist->require[i]->resolved->numbuildproviders) fprintf(fout,"|"); } fprintf(fout,")"); @@ -1612,29 +1616,24 @@ generateHTMLFiles(struct configTag *ct, int arch) currheaderlist->require[i]->resolved->provider[0]->name)) && strcmp(currheaderlist->name, currheaderlist->require[i]->resolved->provider[0]->name)) { - - if ((ct->repository_level == 0) || - (currheaderlist->require[i]->resolved->provider[0]->sourceheader && - currheaderlist->require[i]->resolved->provider[0]->altrepository == ct->repository_level)) { - fprintf(fout,"%s ", - ct->configdefaults->url_prefix, - ct->tag, - currheaderlist->require[i]->resolved->provider[0]->name, - ct->arch[arch], - currheaderlist->require[i]->resolved->provider[0]->name); - if ((ct->repository_level > 0) && - (currheaderlist->sourceheader != currheaderlist->require[i]->resolved->provider[0]->sourceheader)) { - snprintf(buffer, PATH_MAX, "%s(%s,%s) requires %s(%s,%s) which is in this repository", - currheaderlist->name, - ct->arch[arch], - ct->repository[currheaderlist->altrepository]->tag, - currheaderlist->require[i]->resolved->provider[0]->name, - ct->arch[arch], - ct->repository[currheaderlist->require[i]->resolved->provider[0]->altrepository]->tag); - addWarning(currheaderlist->sourceheader, buffer); - } - } else - fprintf(fout,"%s ",currheaderlist->require[i]->resolved->provider[0]->name); + fprintf(fout,"%s ", + ct->configdefaults->url_prefix, + ct->repository[currheaderlist->require[i]->resolved->provider[0]->altrepository]->tag, + currheaderlist->require[i]->resolved->provider[0]->name, + ct->arch[arch], + currheaderlist->require[i]->resolved->provider[0]->name); + if ((ct->repository_level > 0) && + (currheaderlist->sourceheader != currheaderlist->require[i]->resolved->provider[0]->sourceheader) && + (currheaderlist->require[i]->resolved->provider[0]->altrepository == ct->repository_level)) { + snprintf(buffer, PATH_MAX, "%s(%s,%s) requires %s(%s,%s) which is only in this repository", + currheaderlist->name, + ct->arch[arch], + ct->repository[currheaderlist->altrepository]->tag, + currheaderlist->require[i]->resolved->provider[0]->name, + ct->arch[arch], + ct->repository[currheaderlist->require[i]->resolved->provider[0]->altrepository]->tag); + addWarning(currheaderlist->sourceheader, buffer); + } } } else { // multiple providers @@ -1645,20 +1644,15 @@ generateHTMLFiles(struct configTag *ct, int arch) currheaderlist->require[i]->resolved->name)) { fprintf(fout,"%s(",currheaderlist->require[i]->resolved->name); for (j = 0; j < currheaderlist->require[i]->resolved->numproviders; j++) { - if ((ct->repository_level == 0) || - (currheaderlist->require[i]->resolved->provider[j]->sourceheader && - currheaderlist->require[i]->resolved->provider[j]->altrepository == ct->repository_level)) - fprintf(fout,"%s", - ct->configdefaults->url_prefix, - ct->tag, - currheaderlist->require[i]->resolved->provider[j]->name, - ct->arch[arch], - currheaderlist->require[i]->resolved->provider[j]->name); - else - fprintf(fout,"%s",currheaderlist->require[i]->resolved->provider[j]->name); - if (j+1 < currheaderlist->require[i]->resolved->numproviders) fprintf(fout,"|"); - } - fprintf(fout,") "); + fprintf(fout,"%s", + ct->configdefaults->url_prefix, + ct->repository[currheaderlist->require[i]->resolved->provider[j]->altrepository]->tag, + currheaderlist->require[i]->resolved->provider[j]->name, + ct->arch[arch], + currheaderlist->require[i]->resolved->provider[j]->name); + if (j+1 < currheaderlist->require[i]->resolved->numproviders) fprintf(fout,"|"); + } + fprintf(fout,") "); } } // if numproviders } // if required @@ -1680,7 +1674,7 @@ generateHTMLFiles(struct configTag *ct, int arch) fprintf(fout, "%s(%s) ", ct->configdefaults->url_prefix, - ct->tag, + ct->repository[auxheaderlist->altrepository]->tag, auxheaderlist->name, ct->arch[arch], auxheaderlist->name, @@ -1708,18 +1702,12 @@ generateHTMLFiles(struct configTag *ct, int arch) for (j = 0; j < auxheadersourcelist->require[i]->resolved->numbuildproviders; j++) { if (!strcmp(auxheadersourcelist->require[i]->resolved->buildprovider[j]->name, currheaderlist->name)) { - if ((ct->repository_level == 0) || auxheadersourcelist->altrepository == ct->repository_level) { - fprintf(fout, - "%s ", - ct->configdefaults->url_prefix, - ct->tag, - auxheadersourcelist->name, - auxheadersourcelist->name); - } else { - fprintf(fout, - "%s ", - auxheadersourcelist->name); - } + fprintf(fout, + "%s ", + ct->configdefaults->url_prefix, + ct->repository[auxheadersourcelist->altrepository]->tag, + auxheadersourcelist->name, + auxheadersourcelist->name); found=1; } }