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
This commit is contained in:
Silvan Calarco 2013-01-09 14:07:46 +01:00
parent 56e4ad7c6c
commit 34f9295baf
4 changed files with 168 additions and 150 deletions

View File

@ -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 */

View File

@ -1,7 +1,7 @@
/*
* distromatic - tool for RPM based repositories
*
* Copyright (C) 2004-2010 by Silvan Calarco <silvan.calarco@mambasoft.it>
* Copyright (C) 2004-2013 by Silvan Calarco <silvan.calarco@mambasoft.it>
* Copyright (C) 2006 by Davide Madrisan <davide.madrisan@gmail.com>
*
* 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++) {

View File

@ -122,6 +122,7 @@ struct headerSourceList {
struct changeLog *changelog;
struct headerList *firstchild[ARCHS_MAX];
struct warningList *firstwarning;
struct headerSourceList *updatingparent;
};
struct headerStats {

View File

@ -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,
"<img src=\"%s/warning-icon.png\" title=\"",
@ -128,15 +133,23 @@ printHTMLWarnings(FILE *fout,struct configTag *configtag, struct headerSourceLis
fclose(fin);
}
while (currwarning) {
if (mode == 0) {
fprintf(fout,"&nbsp;&bull;&nbsp;%s\n",currwarning->text);
} else if (mode == 1) {
fprintf(fout,"&nbsp;&bull;&nbsp;%s<br>",currwarning->text);
currwarning = firstwarning;
while (currwarning || pkg->old) {
if (currwarning) {
if (mode == 0) {
fprintf(fout,"&nbsp;&bull;&nbsp;%s\n",currwarning->text);
} else if (mode == 1) {
fprintf(fout,"&nbsp;&bull;&nbsp;%s<br>",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,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
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,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
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,"<i>%s</i>(",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,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
fprintf(fout,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
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,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a> ",
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,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a> ",
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,"<i>%s</i>(",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,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
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,"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s</a>",
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,
"<a href=\"%stag=%s&amp;pkg=%s.%s\">%s(%s)</a> ",
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,
"<a href=\"%stag=%s&amp;pkg=%s.source\">%s</a> ",
ct->configdefaults->url_prefix,
ct->tag,
auxheadersourcelist->name,
auxheadersourcelist->name);
} else {
fprintf(fout,
"%s ",
auxheadersourcelist->name);
}
fprintf(fout,
"<a href=\"%stag=%s&amp;pkg=%s.source\">%s</a> ",
ct->configdefaults->url_prefix,
ct->repository[auxheadersourcelist->altrepository]->tag,
auxheadersourcelist->name,
auxheadersourcelist->name);
found=1;
}
}