distromatic,distroquery: added support for weak-deps (recommends)

This commit is contained in:
Silvan 2024-11-03 12:17:16 +01:00
parent c56b8ac2b9
commit a89f9552ec
8 changed files with 383 additions and 234 deletions

View File

@ -701,6 +701,22 @@ json DistroqueryAPI::getPackageDetails(string repository, string package, string
sqlite3_finalize(stmt2);
}
// Recommends
sql = "SELECT * FROM recommends WHERE recommends.id_package=" + to_string(id);
j["recommends"] = json::array();
if (sqlite3_prepare_v2(db, sql.c_str(), sql.length(), &stmt2, NULL) == SQLITE_OK) {
while (sqlite3_step(stmt2) == SQLITE_ROW) {
json recommend = {};
recommend["name"] = reinterpret_cast<const char*>(sqlite3_column_text(stmt2,sqlite3_find_column_id(stmt2, NULL, "recommendname")));
recommend["flags"] = rpmSenseFlagsToString(sqlite3_column_int(stmt2,sqlite3_find_column_id(stmt2, NULL, "recommendflags")));
recommend["version"] = reinterpret_cast<const char*>(sqlite3_column_text(stmt2,sqlite3_find_column_id(stmt2, NULL, "recommendversion")));
json jproviders = getProvidersForRequirement(repository, recommend["name"], recommend["flags"], recommend["version"], arch);
recommend["providers"] = jproviders["providers"];
j["recommends"].push_back(recommend);
}
sqlite3_finalize(stmt2);
}
// Package files
json files = getPackageFiles(repository, package, arch);
if (files.contains("files"))

View File

@ -413,6 +413,9 @@ long generateSQLite_add_needrebuild(sqlite3 *db, struct rebuildList* firstRebuil
#define SQLITE_TABLE_requires "id INTEGER PRIMARY KEY, "\
"id_package INTEGER, id_provided STRING, requirename STRING, requireflags INTEGER, requireversion STRING"
#define SQLITE_TABLE_recommends "id INTEGER PRIMARY KEY, "\
"id_package INTEGER, id_provided STRING, recommendname STRING, recommendflags INTEGER, recommendversion STRING"
int
generateSQLite_packages(struct configTag *ct, sqlite3 *db, int arch) {
@ -423,6 +426,7 @@ generateSQLite_packages(struct configTag *ct, sqlite3 *db, int arch) {
SQLite_init_table(db, "obsoletes", SQLITE_TABLE_obsoletes);
SQLite_init_table(db, "provides", SQLITE_TABLE_provides);
SQLite_init_table(db, "requires", SQLITE_TABLE_requires);
SQLite_init_table(db, "recommends", SQLITE_TABLE_recommends);
SQLite_begin_transaction(db);
currpackage = ct->headerlist[arch];
@ -513,6 +517,30 @@ generateSQLite_packages(struct configTag *ct, sqlite3 *db, int arch) {
fprintf(stderr, "WARNING: package %s requires %s not in provided list\n", currpackage->name, currpackage->require[i]->name);
}
}
/* recommends */
for (i = 0; i < currpackage->recommendcount; i++) {
if (currpackage->recommend[i]->resolved) {
snprintf(sqlite3_query, PATH_MAX, "INSERT INTO recommends VALUES(NULL,%ld,%ld,?,%ld,?);",
currpackage->id,
currpackage->recommend[i]->resolved->id,
currpackage->recommend[i]->flags);
if (sqlite3_prepare_v2(db, sqlite3_query, -1, &stmt, NULL)) {
fprintf(stderr, "ERROR: SQLite: (%s) %s\n", sqlite3_query, sqlite3_errmsg(db));
}
sqlite3_bind_text(stmt, 1, currpackage->recommend[i]->name, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, currpackage->recommend[i]->version, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_DONE) {
fprintf(stderr, "ERROR: SQLite: (%s) %s\n", sqlite3_query, sqlite3_errmsg(db));
return 3;
}
sqlite3_finalize(stmt);
} else if (currpackage->obsoleted == 0 && strstr(currpackage->recommend[i]->name,"rpmlib(") != currpackage->recommend[i]->name) {
fprintf(stderr, "WARNING: package %s recommends %s not in provided list\n", currpackage->name, currpackage->recommend[i]->name);
}
}
}
currpackage = currpackage->next;
}

View File

@ -362,6 +362,237 @@ handleObsoletedPackages(struct configTag *ct, int archidx)
return 0;
}
void resolveRequire(struct configTag *ct, int archidx, struct headerList *currheader, struct Require *require) {
struct providedList *provided;
struct headerList *scanheader, **newprovider;
struct fileTree *file;
char warning[PATH_MAX];
assert(require != NULL);
assert(require->name != NULL);
if (!strncmp("executable(",require->name,11)) {
/* dynamic requirement for executable file */
/*fprintf(stderr,"Warning: skipping unhandled requirement %s for package %s\n",
currheader->require[i]->name,currheader->name);*/
require->resolved=NULL;
} else if (strncmp("rpmlib(",require->name,7) &&
strncmp("debuginfo(build-id)",require->name,20)) {
provided=findOrCreateProvidedListEntry((struct providedList**) &ct->providedlist_idx[archidx],
require->name,1,archidx);
if (provided->numproviders == 0) {
// check if require[i]->name requirement is met
scanheader = ct->headerlist[archidx];
if ((require->name)[0] == '/') {
/* requirement is a file, find who provides it */
file=findOrCreateFileTreeEntry(&ct->filetree[archidx],require->name, archidx);
if (file->numproviders > 0) {
scanheader=file->provider[0];
provided->numproviders=file->numproviders;
provided->numbuildproviders=0;
provided->provider=file->provider;
provided->flags=0;
} else {
scanheader=NULL;
}
} else {
/* requirement is not a file, cross-check with provides */
while (scanheader && !checkRequireWithProvides(require->name, scanheader))
scanheader = scanheader->next;
if (scanheader) {
provided->numproviders=1;
provided->numbuildproviders=0;
provided->provider=malloc(sizeof(struct headerList*));
provided->provider[0]=scanheader;
provided->flags=0;
}
}
if (!scanheader && incremental_mode) {
snprintf(warning,PATH_MAX,"%s(%s,%s): missing provider for %s",
currheader->name,
ct->arch[archidx],
ct->repository[currheader->altrepository]->tag,
require->name);
fprintf(stderr,"Warning: %s\n",warning);
addWarning(currheader->sourceheader, currheader, warning);
}
} else { /* provided->numproviders > 0 */
/* warn about provides only provided by older packages */
int k=0;
for (int j = 0; j < provided->numproviders; j++) {
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 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,
provided->name);
for (int 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);
addRebuild(provided->provider[j]->sourceheader,
currheader->sourceheader, provided->provider[j]);
addWarning(provided->provider[j]->sourceheader, currheader, warning);
}
fprintf(stderr,"Warning: %s\n",warning);
} else {
/* warn about provides provided by obsoleted packages */
int k=0;
for (int j = 0; j < provided->numproviders; j++) {
if (provided->provider[j]->obsoleted &&
!provided->provider[j]->sourceheader->updatingparent && // don't fall in case above
!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 (int 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, currheader, warning);
for (int j = 0; j < provided->numproviders; j++) {
addWarning(provided->provider[j]->sourceheader, currheader, warning);
}
}
}
if ((require->name)[0] == '/') {
/* when there is a Requires: /file/requirement add provide from file tree as well */
file=findOrCreateFileTreeEntry(&ct->filetree[archidx],require->name, archidx);
for (k = 0; k < file->numproviders; k++) {
int found = 0;
for (int j = 0; j < provided->numproviders; j++) {
/* avoid duplicates */
if (file->provider[k] == provided->provider[j]) {
found = 1;
break;
}
}
if (!found) {
//printf("%s also provided by %s\n", currheader->require[i]->name, file->provider[k]->name);
provided->numproviders++;
newprovider=malloc(sizeof(struct headerList*)*provided->numproviders);
for (int j = 0; j < provided->numproviders-1; j++) {
newprovider[j]=provided->provider[j];
}
newprovider[provided->numproviders-1] = file->provider[k];
if (provided->provider) free(provided->provider);
provided->provider=newprovider;
char **newversion=malloc(sizeof(char *)*provided->numproviders);
for (int j = 0; j < provided->numproviders-1; j++) {
newversion[j]=provided->version[j];
}
newversion[provided->numproviders-1] = strdup(provided->provider[provided->numproviders-2]->version);
if (provided->version) free(provided->version);
provided->version=newversion;
}
}
}
}
if (provided->numproviders > 0) {
if (strcmp(require->version,"") &&
(require->flags & (RPMSENSE_LESS|RPMSENSE_GREATER|RPMSENSE_EQUAL))) {
int found = 0;
int foundprovider = -1;
int foundupstreamprovider = 0;
for (int j = 0; j < provided->numproviders; j++) {
/* updated packages: ignore check with upstream package */
if ((foundprovider >= 0) &&
!strcmp(provided->provider[foundprovider]->name,provided->provider[j]->name) &&
provided->provider[foundprovider]->altrepository < provided->provider[j]->altrepository) {
found -= 1;
foundupstreamprovider = foundprovider;
foundprovider = -1;
}
if (!strcmp(provided->version[j],"")) {
/* provider with no version; assume ok */
found += 1;
foundupstreamprovider = foundprovider;
foundprovider = j;
} else {
if (checkVersionWithFlags(
require->version,
require->flags,
provided->version[j])) {
found += 1;
foundupstreamprovider = foundprovider;
foundprovider = j;
}
}
} /* for */
if ((found >= 1) && (!foundupstreamprovider) &&
(currheader->altrepository != 0) &&
(currheader->altrepository = ct->repository_level) &&
(provided->provider[foundprovider]->sourceheader != currheader->sourceheader) &&
(provided->provider[foundprovider]->altrepository == currheader->altrepository)) {
snprintf(warning, PATH_MAX, "%s(%s,%s) requires %s(%s,%s) because it needs %s=%s",
currheader->name, currheader->arch,
ct->repository[currheader->altrepository]->tag,
provided->provider[foundprovider]->name,
provided->provider[foundprovider]->arch,
ct->repository[provided->provider[foundprovider]->altrepository]->tag,
provided->name,
provided->version[foundprovider]);
logmsg(LOG_WARNING,"%s", warning);
addWarning(currheader->sourceheader, currheader, warning);
} else if (!found) {
for (int j = 0; j < provided->numproviders; j++) {
if (!checkVersionWithFlags(
require->version,
require->flags,
provided->version[j])) {
snprintf(warning, PATH_MAX, "%s=%s from %s(%s,%s) fails to provide %s",
provided->name,
provided->version[j],
provided->provider[j]->name,
provided->provider[j]->arch,
ct->repository[provided->provider[j]->altrepository]->tag,
provided->name);
if (require->flags & RPMSENSE_LESS)
snprintf(&warning[strlen(warning)], PATH_MAX,"<");
if (require->flags & RPMSENSE_GREATER)
snprintf(&warning[strlen(warning)], PATH_MAX, ">");
if (require->flags & RPMSENSE_EQUAL)
snprintf(&warning[strlen(warning)], PATH_MAX, "=");
snprintf(&warning[strlen(warning)], PATH_MAX, "%s to %s(%s,%s)",
require->version,
currheader->name,
currheader->arch,
ct->repository[currheader->altrepository]->tag);
logmsg(LOG_WARNING,"%s", warning);
for (int k = 0; k < provided->numproviders; k++) {
if (provided->provider[k]->sourceheader &&
(provided->provider[k]->altrepository == ct->repository_level)) {
addWarning(provided->provider[k]->sourceheader, currheader, warning);
addRebuild(provided->provider[k]->sourceheader,
currheader->sourceheader, provided->provider[k]);
}
if ((currheader->altrepository == ct->repository_level)) {
addWarning(currheader->sourceheader, currheader, warning);
}
}
}
} /* for */
}
}
}
require->resolved=provided;
} else {
require->resolved=NULL;
} /* if */
}
/*
* resolve first level requires for given headerList
* note: this function doesn't free allocated memory so it should be called
@ -369,19 +600,14 @@ handleObsoletedPackages(struct configTag *ct, int archidx)
static int
resolveFirstLevelDependencies(struct configTag *ct, int archidx)
{
struct headerList *currheader, *scanheader, **newprovider;
struct providedList *provided;
struct fileTree *file;
int i,j,k,found,foundprovider, foundupstreamprovider;
struct headerList *currheader;
char warning[PATH_MAX];
char ** newversion;
currheader = ct->headerlist[archidx];
logmsg(LOG_DEBUG,"resolveFirstLevelDependencies - binaries");
while (currheader) {
scanheader = ct->headerlist[archidx];
currheader->requirelist = NULL;
if ((!currheader->obsoleted) && (currheader->next) && (currheader->sourceheader->updatingparent)) {
// mark obsoleted any package with same name in upper level repositories
@ -424,236 +650,27 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx)
currheader = currheader->next;
continue;
}
// currheader->require.resolved = malloc(sizeof(struct providedList*)*currheader->requirecount);
for (i = 0; i < currheader->requirecount; i++) {
assert(currheader->require[i] != NULL);
assert(currheader->require[i]->name != NULL);
if (!strncmp("executable(",currheader->require[i]->name,11)) {
/* dynamic requirement for executable file */
/*fprintf(stderr,"Warning: skipping unhandled requirement %s for package %s\n",
currheader->require[i]->name,currheader->name);*/
currheader->require[i]->resolved=NULL;
} else if (strncmp("rpmlib(",currheader->require[i]->name,7) &&
strncmp("debuginfo(build-id)",currheader->require[i]->name,20)) {
provided=findOrCreateProvidedListEntry((struct providedList**) &ct->providedlist_idx[archidx],
currheader->require[i]->name,1,archidx);
if (provided->numproviders == 0) {
// check if require[i]->name requirement is met
scanheader = ct->headerlist[archidx];
if ((currheader->require[i]->name)[0] == '/') {
/* requirement is a file, find who provides it */
file=findOrCreateFileTreeEntry(&ct->filetree[archidx],currheader->require[i]->name, archidx);
if (file->numproviders > 0) {
scanheader=file->provider[0];
provided->numproviders=file->numproviders;
provided->numbuildproviders=0;
provided->provider=file->provider;
provided->flags=0;
} else {
scanheader=NULL;
}
} else {
/* requirement is not a file, cross-check with provides */
while (scanheader && !checkRequireWithProvides(
currheader->require[i]->name, scanheader))
scanheader = scanheader->next;
if (scanheader) {
provided->numproviders=1;
provided->numbuildproviders=0;
provided->provider=malloc(sizeof(struct headerList*));
provided->provider[0]=scanheader;
provided->flags=0;
}
}
if (!scanheader && incremental_mode) {
snprintf(warning,PATH_MAX,"%s(%s,%s): missing provider for %s",
currheader->name,
ct->arch[archidx],
ct->repository[currheader->altrepository]->tag,
currheader->require[i]->name);
fprintf(stderr,"Warning: %s\n",warning);
addWarning(currheader->sourceheader, currheader, 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]->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 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,
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);
addRebuild(provided->provider[j]->sourceheader,
currheader->sourceheader, provided->provider[j]);
addWarning(provided->provider[j]->sourceheader, currheader, warning);
}
fprintf(stderr,"Warning: %s\n",warning);
} else {
/* warn about provides provided by obsoleted packages */
k=0;
for (j = 0; j < provided->numproviders; j++) {
if (provided->provider[j]->obsoleted &&
!provided->provider[j]->sourceheader->updatingparent && // don't fall in case above
!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, currheader, warning);
for (j = 0; j < provided->numproviders; j++) {
addWarning(provided->provider[j]->sourceheader, currheader, warning);
}
}
}
if ((currheader->require[i]->name)[0] == '/') {
/* when there is a Requires: /file/requirement add provide from file tree as well */
file=findOrCreateFileTreeEntry(&ct->filetree[archidx],currheader->require[i]->name, archidx);
for (k = 0; k < file->numproviders; k++) {
for (j = 0, found = 0; j < provided->numproviders; j++) {
/* avoid duplicates */
if (file->provider[k] == provided->provider[j]) {
found = 1;
break;
}
}
if (! found) {
//printf("%s also provided by %s\n", currheader->require[i]->name, file->provider[k]->name);
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] = file->provider[k];
if (provided->provider) free(provided->provider);
provided->provider=newprovider;
newversion=malloc(sizeof(char *)*provided->numproviders);
for (j = 0; j < provided->numproviders-1; j++) {
newversion[j]=provided->version[j];
}
newversion[provided->numproviders-1] = strdup(provided->provider[j]->version);
if (provided->version) free(provided->version);
provided->version=newversion;
}
}
}
}
if (provided->numproviders > 0) {
if (strcmp(currheader->require[i]->version,"") &&
(currheader->require[i]->flags & (RPMSENSE_LESS|RPMSENSE_GREATER|RPMSENSE_EQUAL))) {
found = 0;
foundprovider = -1;
foundupstreamprovider = 0;
for (j = 0; j < provided->numproviders; j++) {
/* updated packages: ignore check with upstream package */
if ((foundprovider >= 0) &&
!strcmp(provided->provider[foundprovider]->name,provided->provider[j]->name) &&
provided->provider[foundprovider]->altrepository < provided->provider[j]->altrepository) {
found -= 1;
foundupstreamprovider = foundprovider;
foundprovider = -1;
}
if (!strcmp(provided->version[j],"")) {
/* provider with no version; assume ok */
found += 1;
foundupstreamprovider = foundprovider;
foundprovider = j;
} else {
if (checkVersionWithFlags(
currheader->require[i]->version,
currheader->require[i]->flags,
provided->version[j])) {
found += 1;
foundupstreamprovider = foundprovider;
foundprovider = j;
}
}
} /* for */
if ((found >= 1) && (!foundupstreamprovider) &&
(currheader->altrepository != 0) &&
(currheader->altrepository = ct->repository_level) &&
(provided->provider[foundprovider]->sourceheader != currheader->sourceheader) &&
(provided->provider[foundprovider]->altrepository == currheader->altrepository)) {
snprintf(warning, PATH_MAX, "%s(%s,%s) requires %s(%s,%s) because it needs %s=%s",
currheader->name, currheader->arch,
ct->repository[currheader->altrepository]->tag,
provided->provider[foundprovider]->name,
provided->provider[foundprovider]->arch,
ct->repository[provided->provider[foundprovider]->altrepository]->tag,
provided->name,
provided->version[foundprovider]);
logmsg(LOG_WARNING,"%s", warning);
addWarning(currheader->sourceheader, currheader, warning);
} else if (!found) {
for (j = 0; j < provided->numproviders; j++) {
if (!checkVersionWithFlags(
currheader->require[i]->version,
currheader->require[i]->flags,
provided->version[j])) {
snprintf(warning, PATH_MAX, "%s=%s from %s(%s,%s) fails to provide %s",
provided->name,
provided->version[j],
provided->provider[j]->name,
provided->provider[j]->arch,
ct->repository[provided->provider[j]->altrepository]->tag,
provided->name);
if (currheader->require[i]->flags & RPMSENSE_LESS)
snprintf(&warning[strlen(warning)], PATH_MAX,"<");
if (currheader->require[i]->flags & RPMSENSE_GREATER)
snprintf(&warning[strlen(warning)], PATH_MAX, ">");
if (currheader->require[i]->flags & RPMSENSE_EQUAL)
snprintf(&warning[strlen(warning)], PATH_MAX, "=");
snprintf(&warning[strlen(warning)], PATH_MAX, "%s to %s(%s,%s)",
currheader->require[i]->version,
currheader->name,
currheader->arch,
ct->repository[currheader->altrepository]->tag);
logmsg(LOG_WARNING,"%s", warning);
for (k = 0; k < provided->numproviders; k++) {
if (provided->provider[k]->sourceheader &&
(provided->provider[k]->altrepository == ct->repository_level)) {
addWarning(provided->provider[k]->sourceheader, currheader, warning);
addRebuild(provided->provider[k]->sourceheader,
currheader->sourceheader, provided->provider[k]);
}
if ((currheader->altrepository == ct->repository_level)) {
addWarning(currheader->sourceheader, currheader, warning);
}
}
}
} /* for */
}
}
}
currheader->require[i]->resolved=provided;
} else {
currheader->require[i]->resolved=NULL;
} /* if */
// Resolve requires
for (int i = 0; i < currheader->requirecount; i++) {
resolveRequire(ct, archidx, currheader, currheader->require[i]);
} /* for currheader->requirecount */
// sort required list by first provider's name
qsort((void *) &currheader->require[0],
currheader->requirecount,
sizeof(struct Require *),
compareRequiredList);
// Resolve recommends
for (int i = 0; i < currheader->recommendcount; i++) {
resolveRequire(ct, archidx, currheader, currheader->recommend[i]);
} /* for currheader->requirecount */
// sort recommend list by first provider's name
qsort((void *) &currheader->recommend[0],
currheader->recommendcount,
sizeof(struct Require *),
compareRequiredList);
currheader = currheader->next;
}
logmsg(LOG_DEBUG,"resolveFirstLevelDependencies - done");

View File

@ -1472,16 +1472,17 @@ char* advanceXMLPackageNode(xmlNode **primary_node, xmlNode **filelists_node) {
char filepath[bufsize + 1], currname[bufsize + 1];
char *filename=NULL;
long i ,j , k, n=0, altn[ALT_REPS_MAX];
int altrepository=0, obsoletecount, providecount, requirecount,
int altrepository=0, obsoletecount, providecount, requirecount, recommendcount,
filenamecount, dirnamecount, alt_reps_num = 0;
int_16 *fileflags;
char **obsoletename, **obsoleteversion,
**providename, **provideversion,
**requirename, **requireversion,
**recommendname, **recommendversion,
**basename, **dirname, **newversion,
**fileusername, **filegroupname;
const char* errstr;
uint_32 *dirindex, *requireflags, *obsoleteflags, *provideflags;
uint_32 *dirindex, *requireflags, *recommendflags, *obsoleteflags, *provideflags;
#if RPM_VERSION >= 0x050000
rpmts ts = rpmtsCreate();
#else
@ -1660,6 +1661,9 @@ char* advanceXMLPackageNode(xmlNode **primary_node, xmlNode **filelists_node) {
getXMLPackageNFV(newheaderlist->name,
findXMLPropertyByName(format, "requires"),
&requirename, &requireflags, &requireversion, &requirecount);
getXMLPackageNFV(newheaderlist->name,
findXMLPropertyByName(format, "recommends"),
&recommendname, &recommendflags, &recommendversion, &recommendcount);
newheaderlist->provided = malloc(sizeof(struct providedList*)*providecount);
for (i=0; i < providecount; i++) {
@ -1703,6 +1707,7 @@ char* advanceXMLPackageNode(xmlNode **primary_node, xmlNode **filelists_node) {
newheaderlist->obsoleteversion = obsoleteversion;
newheaderlist->obsoletecount = obsoletecount;
newheaderlist->altrepository = altidx;
// Requires
newheaderlist->require = malloc(requirecount * sizeof(struct Require *));
for (j=0; j < requirecount; j++) {
@ -1713,6 +1718,18 @@ char* advanceXMLPackageNode(xmlNode **primary_node, xmlNode **filelists_node) {
newheaderlist->require[j]->resolved = NULL;
}
newheaderlist->requirecount = requirecount;
// Recommends
newheaderlist->recommend = malloc(recommendcount * sizeof(struct Require *));
for (j=0; j < recommendcount; j++) {
newheaderlist->recommend[j] = malloc(sizeof(struct Require));
newheaderlist->recommend[j]->name = recommendname[j];
newheaderlist->recommend[j]->flags = recommendflags[j];
newheaderlist->recommend[j]->version = recommendversion[j];
newheaderlist->recommend[j]->resolved = NULL;
}
newheaderlist->recommendcount = recommendcount;
// Files
getXMLPackageFiles(filelists_node[altidx], &basename,
&fileusername, &filegroupname, &filenamecount, &fileflags);
@ -1826,6 +1843,8 @@ char* advanceXMLPackageNode(xmlNode **primary_node, xmlNode **filelists_node) {
&provideversion, &providecount);
getPackageRequires(h, &requirename, &requireflags,
&requireversion, &requirecount);
getPackageRecommends(h, &recommendname, &recommendflags,
&recommendversion, &recommendcount);
getPackageFiles(h, &dirindex, &dirname, &dirnamecount,
&basename, &filenamecount,
&fileusername, &filegroupname, &fileflags);
@ -1885,6 +1904,8 @@ char* advanceXMLPackageNode(xmlNode **primary_node, xmlNode **filelists_node) {
newheaderlist->obsoleteversion = obsoleteversion;
newheaderlist->obsoletecount = obsoletecount;
newheaderlist->altrepository = altrepository;
// Requires
newheaderlist->require = malloc(requirecount * sizeof(struct Require *));
for (j=0; j < requirecount; j++) {
newheaderlist->require[j] = malloc(sizeof(struct Require));
@ -1894,6 +1915,18 @@ char* advanceXMLPackageNode(xmlNode **primary_node, xmlNode **filelists_node) {
newheaderlist->require[j]->resolved = NULL;
}
newheaderlist->requirecount = requirecount;
// Recommends
newheaderlist->recommend = malloc(recommendcount * sizeof(struct Require *));
for (j=0; j < recommendcount; j++) {
newheaderlist->recommend[j] = malloc(sizeof(struct Require));
newheaderlist->recommend[j]->name = recommendname[j];
newheaderlist->recommend[j]->flags = recommendflags[j];
newheaderlist->recommend[j]->version = recommendversion[j];
newheaderlist->recommend[j]->resolved = NULL;
}
newheaderlist->recommendcount = recommendcount;
newheaderlist->file =
malloc(sizeof(struct fileTree*) * filenamecount);
newheaderlist->fileflags =

View File

@ -1,7 +1,7 @@
/*
* distromatic - tool for RPM based repositories
*
* Copyright (C) 2004-2020 by Silvan Calarco <silvan.calarco@mambasoft.it>
* Copyright (C) 2004-2024 by Silvan Calarco <silvan.calarco@mambasoft.it>
* Copyright (C) 2006 by Davide Madrisan <davide.madrisan@gmail.com>
*/
@ -95,6 +95,8 @@ struct headerList {
int providecount;
int requirecount;
struct Require **require;
int recommendcount;
struct Require **recommend;
struct providedList **provided;
int filenamecount;
struct fileTree **file;

View File

@ -55,6 +55,10 @@ int getPackageRequires(
Header h, char ***requirename, uint_32 **requireflags,
char ***requireversion, int *requirecount);
int getPackageRecommends(
Header h, char ***recommendname, uint_32 **recommendflags,
char ***recommendversion, int *recommendcount);
int getPackageProvides(
Header h, char ***providename, uint_32 **provideflags,
char ***provideversion, int *providecount);

View File

@ -26,7 +26,6 @@
#include "reports.h"
#include "rpmfunctions.h"
#include "functions.h"
#include "requirelist.h"
#include <errno.h>
#include <time.h>
@ -1833,6 +1832,8 @@ int print_datatables(struct configTag *ct, int arch) {
currheaderlist = ct->headerlist[arch];
while (currheaderlist) {
fprintf(fd,"%s: ", currheaderlist->name);
// Add requires
for (i = 0; i < currheaderlist->requirecount; i++) {
if (currheaderlist->require[i]->resolved) {
if (currheaderlist->require[i]->resolved->numproviders == 0) {
@ -1868,6 +1869,43 @@ int print_datatables(struct configTag *ct, int arch) {
}
}
}
// Add recommends (weak-deps)
for (i = 0; i < currheaderlist->recommendcount; i++) {
if (currheaderlist->recommend[i]->resolved) {
if (currheaderlist->recommend[i]->resolved->numproviders == 0) {
// Filter out complex deps like "(name >= ver1 with name < ver2)
if (currheaderlist->recommend[i]->resolved->name[0] != '(') {
fprintf_depstable_filtered_var(fd,
currheaderlist->recommend[i]->resolved->name);
fprintf(fd,"_unresolved_ ");
}
} else if (currheaderlist->recommend[i]->resolved->numproviders == 1) {
if ((i == 0 ||
!currheaderlist->recommend[i-1]->resolved ||
!currheaderlist->recommend[i-1]->resolved->numproviders ||
strcmp(currheaderlist->recommend[i-1]->resolved->provider[0]->name,
currheaderlist->recommend[i]->resolved->provider[0]->name)) &&
strcmp(currheaderlist->name,
currheaderlist->recommend[i]->resolved->provider[0]->name)) {
fprintf(fd,"%s ",currheaderlist->recommend[i]->resolved->provider[0]->name);
}
} else {
if (i == 0 ||
!currheaderlist->recommend[i-1]->resolved ||
!currheaderlist->recommend[i-1]->resolved->numproviders ||
strcmp(currheaderlist->recommend[i-1]->resolved->name,
currheaderlist->recommend[i]->resolved->name)) {
fprintf_depstable_filtered_var(fd,currheaderlist->recommend[i]->resolved->name);
fprintf(fd," ");
}
}
for (int j = 0; j < currheaderlist->recommend[i]->resolved->numproviders; j++) {
if (currheaderlist->recommend[i]->resolved->provider[j]->sourceheader != currheaderlist->sourceheader)
currheaderlist->recommend[i]->resolved->provider[j]->sourceheader->childrenrequiredcount[arch]++;
}
}
}
fprintf(fd,"\n");
//

View File

@ -303,6 +303,17 @@ getPackageRequires(Header h, char ***requirename, uint_32 **requireflags,
return 0;
}
int
getPackageRecommends(Header h, char ***recommendname, uint_32 **recommendflags,
char ***recommendversion, int *recommendcount)
{
*recommendname = headerGetStringArrayEntry(h, RPMTAG_RECOMMENDNAME, recommendcount);
*recommendflags = headerGetUIntArrayEntry(h, RPMTAG_RECOMMENDFLAGS, recommendcount);
*recommendversion = headerGetStringArrayEntry(h, RPMTAG_RECOMMENDVERSION, recommendcount);
return 0;
}
int
getPackageProvides(Header h, char ***providename, uint_32 **provideflags,
char ***provideversion, int *providecount)