diff --git a/src/DistroqueryAPI.cpp b/src/DistroqueryAPI.cpp index c5b1f75..150e5d9 100644 --- a/src/DistroqueryAPI.cpp +++ b/src/DistroqueryAPI.cpp @@ -522,6 +522,44 @@ json DistroqueryAPI::getPackageDetails(string repository, string package, string return j; } +json DistroqueryAPI::getRepositoryProblems(string repository) { + json j; + sqlite3_stmt *stmt; + + struct configTag* ct = findRepositoryByTag(repository.c_str()); + if (ct == NULL) { + j["error"] = "repository with tag '" + repository + "' does not exist"; + return j; + } + + auto db = openRepositoryDatabase(ct); + if (!db) { + j["error"] = "error opening sources database for repository " + string(ct->tag); + return j; + } + + attachCtDatabases(ct, db); + + j["problems"] = json::array(); + + // Check build requires + string sql = "SELECT * FROM warnings ORDER BY repository,arch,name"; + if (sqlite3_prepare_v2(db, sql.c_str(), sql.length(), &stmt, NULL) == SQLITE_OK) { + while (sqlite3_step(stmt) == SQLITE_ROW) { + json problem = {}; + problem["repository"] = reinterpret_cast(sqlite3_column_text(stmt,sqlite3_find_column_id(stmt, NULL, "repository"))); + problem["arch"] = reinterpret_cast(sqlite3_column_text(stmt,sqlite3_find_column_id(stmt, NULL, "arch"))); + problem["name"] = reinterpret_cast(sqlite3_column_text(stmt,sqlite3_find_column_id(stmt, NULL, "name"))); + problem["text"] = reinterpret_cast(sqlite3_column_text(stmt,sqlite3_find_column_id(stmt, NULL, "text"))); + j["problems"].push_back(problem); + } + sqlite3_finalize(stmt); + } + + sqlite3_close(db); + return j; +} + void DistroqueryAPI::getApiResponse(string path_info) { cout << "Content-Type: application/json;charset=utf-8\n\n" << endl; @@ -609,6 +647,12 @@ void DistroqueryAPI::getApiResponse(string path_info) { providers = getProvidersForRequirement(path_split[1], urlDecode(path_split[2]), urlDecode(path_split[3]), urlDecode(path_split[4])); cout << providers.dump(); + } else if (path_split[0] == "problems") { + // API service: check problems + if (path_split.size() != 2) + sendErrorResponse("expected 2 arguments for " + path_split[0]); + json problems = getRepositoryProblems(path_split[1]); + cout << problems.dump(); } else { sendErrorResponse("invalid request for service '" + path_split[0]); } diff --git a/src/DistroqueryAPI.hpp b/src/DistroqueryAPI.hpp index 2b5b61c..dbe2e29 100644 --- a/src/DistroqueryAPI.hpp +++ b/src/DistroqueryAPI.hpp @@ -50,6 +50,7 @@ class DistroqueryAPI { json getPackageSourceDetails(string repository, string package); json getBuiltPackagesFromSourceID(configTag* ct, long id); json getPackageDetails(string repository, string package, string arch); + json getRepositoryProblems(string repository); }; #endif // __DISTROQUERY_API_H diff --git a/src/backend-sqlite3.c b/src/backend-sqlite3.c index 2f8b558..e85ce75 100644 --- a/src/backend-sqlite3.c +++ b/src/backend-sqlite3.c @@ -315,6 +315,56 @@ long generateSQLite_add_changelog(sqlite3 *db, struct changeLog* firstchangelog, return lastchangelogid; } +long generateSQLite_add_warnings(sqlite3 *db, struct warningList* firstWarning, char* repository) { + + struct warningList* warning = firstWarning; + long lastwarningid = 0; + + while (warning) { + snprintf(sqlite3_query, PATH_MAX, "INSERT INTO warnings VALUES(NULL,?,?,?,?);"); + + 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, repository, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, warning->arch, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 3, warning->name, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 4, warning->text, -1, SQLITE_STATIC); + if (sqlite3_step(stmt) != SQLITE_DONE) { + fprintf(stderr, "ERROR: SQLite: (%s) %s\n", sqlite3_query, sqlite3_errmsg(db)); + return 3; + } + warning->id = sqlite3_last_insert_rowid(db); + lastwarningid = warning->id; + sqlite3_finalize(stmt); + warning = warning->next; + } + return lastwarningid; +} + +long generateSQLite_add_needrebuild(sqlite3 *db, struct rebuildList* firstRebuild, long id_source) { + + struct rebuildList* rebuild = firstRebuild; + long lastrebuildid = 0; + + while (rebuild) { + snprintf(sqlite3_query, PATH_MAX, "INSERT INTO needrebuild VALUES(NULL,%ld,%ld,%ld);", + id_source, + rebuild->sourceheader->id, + rebuild->provider->id); + + if (sqlite3_prepare_v2(db, sqlite3_query, -1, &stmt, NULL)) { + fprintf(stderr, "ERROR: SQLite: (%s) %s\n", sqlite3_query, sqlite3_errmsg(db)); + } + rebuild->id = sqlite3_last_insert_rowid(db); + lastrebuildid = rebuild->id; + sqlite3_finalize(stmt); + rebuild = rebuild->next; + } + return lastrebuildid; +} + #define SQLITE_TABLE_packages "id INTEGER PRIMARY KEY, "\ "name STRING, arch STRING, altrepository INTEGER, epoch INTEGER, version STRING, release STRING, summary STRING, "\ "groupdescr STRING, description STRING, buildtime INTEGER, size INTEGER, id_source INTEGER" @@ -425,7 +475,7 @@ generateSQLite_packages(struct configTag *ct, sqlite3 *db, int arch) { } sqlite3_finalize(stmt); } else if (strstr(currpackage->require[i]->name,"rpmlib(") != currpackage->require[i]->name) { - fprintf(stderr, "WARNING: package %s require %s not in provided list\n", currpackage->name, currpackage->require[i]->name); + fprintf(stderr, "WARNING: package %s requires %s not in provided list\n", currpackage->name, currpackage->require[i]->name); } } } @@ -440,20 +490,23 @@ generateSQLite_packages(struct configTag *ct, sqlite3 *db, int arch) { #define SQLITE_TABLE_sources "id INTEGER PRIMARY KEY, "\ "name STRING, altrepository INTEGER, epoch INTEGER, version STRING, release STRING, summary STRING, id_packager INTEGER, "\ "groupdescr STRING, description STRING, url STRING, license STRING, arch STRING, buildarchs STRING, " \ - "excludearch STRING, buildtime INTEGER, size INTEGER, id_changelog INTEGER" + "excludearch STRING, buildtime INTEGER, size INTEGER" //#define SQLITE_TABLE_sources_files_rel "id INTEGER PRIMARY KEY, id_source INTEGER, id_files INTEGER" //#define SQLITE_TABLE_sources_provided_rel "id INTEGER PRIMARY KEY, id_source INTEGER, id_provided INTEGER" #define SQLITE_TABLE_changelog "id INTEGER PRIMARY KEY, "\ "id_source INTEGER, time INTEGER, id_packager INTEGER, release STRING, text STRING" #define SQLITE_TABLE_buildrequires "id INTEGER PRIMARY KEY, "\ "id_source INTEGER, buildrequirename STRING, buildrequireflags INTEGER, buildrequireversion STRING" +#define SQLITE_TABLE_warnings "id INTEGER PRIMARY KEY, "\ + "repository STRING, arch STRING, name STRING, text STRING" +#define SQLITE_TABLE_needrebuild "id INTEGER PRIMARY KEY, "\ + "id_source INTEGER, id_source_rebuild INTEGER, id_provider INTEGER" int generateSQLite_sources(struct configTag *ct, sqlite3 *db) { struct headerSourceList* currsource; int i; - long nextchangelogid = 1; SQLite_init_table(db, "sources", SQLITE_TABLE_sources); SQLite_init_table(db, "sources_source", SQLITE_TABLE_sources_source); @@ -462,19 +515,20 @@ generateSQLite_sources(struct configTag *ct, sqlite3 *db) { // SQLite_init_table(db, "sources_provided_rel", SQLITE_TABLE_sources_provided_rel); SQLite_init_table(db, "changelog", SQLITE_TABLE_changelog); SQLite_init_table(db, "buildrequires", SQLITE_TABLE_buildrequires); + SQLite_init_table(db, "warnings", SQLITE_TABLE_warnings); + SQLite_init_table(db, "needrebuild", SQLITE_TABLE_needrebuild); SQLite_begin_transaction(db); currsource = ct->headersourcelist; while (currsource != NULL) { if (currsource->altrepository == ct->repository_level) { - snprintf(sqlite3_query, PATH_MAX, "INSERT INTO sources VALUES(%ld,?,%d,%ld,?,?,?,%ld,?,?,?,?,?,?,?,%ld,%ld,%ld);", + snprintf(sqlite3_query, PATH_MAX, "INSERT INTO sources VALUES(%ld,?,%d,%ld,?,?,?,%ld,?,?,?,?,?,?,?,%ld,%ld);", currsource->id, currsource->altrepository, currsource->epoch, currsource->packager->id, currsource->buildtime, - currsource->size, - (currsource->changelog?nextchangelogid:0)); + currsource->size); if (sqlite3_prepare_v2(db, sqlite3_query, -1, &stmt, NULL)) { fprintf(stderr, "ERROR: SQLite: (%s) %s\n", sqlite3_query, sqlite3_errmsg(db)); } @@ -573,8 +627,16 @@ generateSQLite_sources(struct configTag *ct, sqlite3 *db) { }*/ if (currsource->changelog) { - nextchangelogid = generateSQLite_add_changelog(db, currsource->changelog, currsource->id) + 1; + generateSQLite_add_changelog(db, currsource->changelog, currsource->id); } + + if (currsource->firstrebuild) { + generateSQLite_add_needrebuild(db, currsource->firstrebuild, currsource->id); + } + + } + if (currsource->firstwarning) { + generateSQLite_add_warnings(db, currsource->firstwarning, ct->repository[currsource->altrepository]->tag); } currsource = currsource->next; } @@ -635,6 +697,7 @@ generateSQLite(struct configTag *ct) } generateSQLite_sources(ct, db); + generateSQLite_packagers(db); sqlite3_close(db); diff --git a/src/distromatic.c b/src/distromatic.c index 04dfb1c..753aeba 100644 --- a/src/distromatic.c +++ b/src/distromatic.c @@ -252,7 +252,7 @@ handleObsoletedPackages(struct configTag *ct, int archidx) prov->provider[i]->name, prov->provider[i]->arch, ct->repository[prov->provider[i]->altrepository]->tag); - addWarning(prov->provider[k]->sourceheader, buf); + addWarning(prov->provider[k]->sourceheader, currheader, buf); logmsg(LOG_WARNING,"%s", buf); break; } @@ -269,7 +269,7 @@ handleObsoletedPackages(struct configTag *ct, int archidx) prov->provider[k]->name, prov->provider[k]->arch, ct->repository[prov->provider[k]->altrepository]->tag); - addWarning(prov->provider[i]->sourceheader, buf); + addWarning(prov->provider[i]->sourceheader, prov->provider[i], buf); logmsg(LOG_WARNING,"%s", buf); obs[k]=i; } @@ -350,7 +350,7 @@ handleObsoletedPackages(struct configTag *ct, int archidx) ct->repository[prov->provider[i]->altrepository]->tag); } } - addWarning(currheader->sourceheader, buf); + addWarning(currheader->sourceheader, currheader, buf); logmsg(LOG_WARNING,"%s", buf); } } @@ -399,7 +399,7 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) currheader->version, currheader->next->version); fprintf(stderr,"Warning: %s\n",warning); - addWarning(currheader->sourceheader,warning); + addWarning(currheader->sourceheader, currheader, warning); } } else if (currheader->altrepository >= currheader->sourceheader->updatingparent->altrepository) { currheader->next->obsoleted = 1; @@ -415,7 +415,7 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) currheader->next->version, currheader->version); fprintf(stderr,"Warning: %s\n",warning); - addWarning(currheader->sourceheader,warning); + addWarning(currheader->sourceheader, currheader->next, warning); } } } @@ -472,7 +472,7 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) ct->repository[currheader->altrepository]->tag, currheader->require[i]->name); fprintf(stderr,"Warning: %s\n",warning); - addWarning(currheader->sourceheader,warning); + addWarning(currheader->sourceheader, currheader, warning); } } else { /* provided->numproviders > 0 */ /* warn about provides only provided by older packages */ @@ -495,7 +495,7 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) ct->repository[provided->provider[j]->altrepository]->tag); addRebuild(provided->provider[j]->sourceheader, currheader->sourceheader, provided->provider[j]); - addWarning(provided->provider[j]->sourceheader,warning); + addWarning(provided->provider[j]->sourceheader, currheader, warning); } fprintf(stderr,"Warning: %s\n",warning); } else { @@ -519,9 +519,9 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) ct->repository[provided->provider[j]->altrepository]->tag); } fprintf(stderr,"Warning: %s\n",warning); - addWarning(currheader->sourceheader,warning); + addWarning(currheader->sourceheader, currheader, warning); for (j = 0; j < provided->numproviders; j++) { - addWarning(provided->provider[j]->sourceheader,warning); + addWarning(provided->provider[j]->sourceheader, currheader, warning); } } } @@ -602,7 +602,7 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) provided->name, provided->version[foundprovider]); logmsg(LOG_WARNING,"%s", warning); - addWarning(currheader->sourceheader, warning); + addWarning(currheader->sourceheader, currheader, warning); } else if (!found) { for (j = 0; j < provided->numproviders; j++) { if (!checkVersionWithFlags( @@ -631,12 +631,12 @@ resolveFirstLevelDependencies(struct configTag *ct, int archidx) for (k = 0; k < provided->numproviders; k++) { if (provided->provider[k]->sourceheader && (provided->provider[k]->altrepository == ct->repository_level)) { - addWarning(provided->provider[k]->sourceheader, warning); + 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, warning); + addWarning(currheader->sourceheader, currheader, warning); } } } @@ -725,7 +725,7 @@ resolveFirstLevelSourceDependencies(struct configTag *ct, int archidx) currsourceheader->name, ct->repository[currsourceheader->altrepository]->tag, warning); - addWarning(currsourceheader,warning); + addWarning(currsourceheader, NULL, warning); } //} else if (provided->numbuildproviders > 1) { /*printf("Multiple providers for %s in package %s\n",currsourceheader->require[i]->name,currsourceheader->name);*/ @@ -1187,7 +1187,7 @@ main(int argc, char *argv[]) logmsg(LOG_WARNING, "%s: %s", currheadersourcelist->name, warning); - addWarning(currheadersourcelist, warning); + addWarning(currheadersourcelist, NULL, warning); } warning[0] = '\0'; @@ -1204,7 +1204,7 @@ main(int argc, char *argv[]) logmsg(LOG_WARNING, "%s: %s", currheadersourcelist->name, warning); - addWarning(currheadersourcelist, warning); + addWarning(currheadersourcelist, NULL, warning); } warning[0] = '\0'; @@ -1232,7 +1232,7 @@ main(int argc, char *argv[]) logmsg(LOG_WARNING, "%s: %s", currheadersourcelist->name, warning); - addWarning(currheadersourcelist, warning); + addWarning(currheadersourcelist, NULL, warning); } currheadersourcelist = currheadersourcelist->next; } diff --git a/src/headerlist.c b/src/headerlist.c index a352e32..055465c 100644 --- a/src/headerlist.c +++ b/src/headerlist.c @@ -52,13 +52,13 @@ int sourcerpmselector(const struct dirent *entry); const int bufsize = PATH_MAX; -struct warningList* addWarning(struct headerSourceList *pkg, char* text) +struct warningList* addWarning(struct headerSourceList *srcpkg, struct headerList *package, char* text) { struct warningList *currwarning, *prevwarning = NULL; - if (!pkg) return NULL; + if (!srcpkg) return NULL; - currwarning = pkg->firstwarning; + currwarning = srcpkg->firstwarning; while (currwarning) { if (!strcmp(currwarning->text,text)) return currwarning; @@ -68,14 +68,22 @@ struct warningList* addWarning(struct headerSourceList *pkg, char* text) currwarning=malloc(sizeof(struct warningList)); if (!currwarning) return NULL; - if (!pkg->firstwarning) pkg->firstwarning=currwarning; + if (!srcpkg->firstwarning) srcpkg->firstwarning=currwarning; + + if (package) { + currwarning->arch = strdup(package->arch); + currwarning->name = strdup(package->name); + } else { + currwarning->arch = "src"; + currwarning->name = strdup(srcpkg->name); + } currwarning->text=strdup(text); if (!currwarning->text) return NULL; currwarning->next=NULL; if (prevwarning) prevwarning->next=currwarning; - return pkg->firstwarning; + return srcpkg->firstwarning; } struct rebuildList* addRebuild(struct headerSourceList *pkg, struct headerSourceList* sourceheader, struct headerList* provider) @@ -998,7 +1006,7 @@ void addNewToSourceHeaderList(struct headerSourceList *newheadersourcelist, newheadersourcelist->name, ct->repository[newheadersourcelist->altrepository]->tag, warning); - addWarning(newheadersourcelist, warning); + addWarning(newheadersourcelist, NULL, warning); } } newheadersourcelist->next = currheadersourcelist->next; @@ -1212,7 +1220,7 @@ int addToSourceHeaderList(struct configTag *ct, int mode, int altrepository) { logmsg(LOG_WARNING, "%s: missing changelog name and/or text", newheadersourcelist->name); - addWarning(newheadersourcelist, warning); + addWarning(newheadersourcelist, NULL, warning); } changelog = changelog->next; } @@ -1314,7 +1322,7 @@ int addToSourceHeaderList(struct configTag *ct, int mode, int altrepository) { logmsg(LOG_WARNING, "%s: missing changelog name and/or text", newheadersourcelist->name); - addWarning(newheadersourcelist, warning); + addWarning(newheadersourcelist, NULL, warning); } changelog = changelog->next; } diff --git a/src/include/headerlist.h b/src/include/headerlist.h index 8ad4cab..a95d2fe 100644 --- a/src/include/headerlist.h +++ b/src/include/headerlist.h @@ -52,13 +52,17 @@ struct fileGroupList { struct warningList { char* text; + char *arch; + char *name; struct warningList *next; + long id; }; struct rebuildList { struct headerSourceList *sourceheader; struct headerList *provider; struct rebuildList *next; + long id; }; struct Require { @@ -219,7 +223,7 @@ addToHeaderList(struct configTag *ct, const char* altscantag[ALT_REPS_MAX], int arch); -struct warningList* addWarning(struct headerSourceList *pkg,char* text); +struct warningList* addWarning(struct headerSourceList *srcpkg, struct headerList *package, char* text); struct rebuildList* addRebuild(struct headerSourceList *pkg, struct headerSourceList* sourceheader, struct headerList* provider); diff --git a/src/reports.c b/src/reports.c index 018f9f1..5a93483 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1074,7 +1074,7 @@ generateHTML_SRPMSFiles(struct configTag *configtag) { snprintf(buffer, PATH_MAX, "has build requirement %s which is only provided in this repository", currheadersourcelist->require[i]->resolved->name); - addWarning(currheadersourcelist, buffer); + addWarning(currheadersourcelist, NULL, buffer); } } } else { @@ -1483,7 +1483,7 @@ generateHTMLFiles(struct configTag *ct, int arch) currheaderlist->require[i]->resolved->provider[0]->name, ct->arch[arch], ct->repository[currheaderlist->require[i]->resolved->provider[0]->altrepository]->tag); - addWarning(currheaderlist->sourceheader, buffer); + addWarning(currheaderlist->sourceheader, currheaderlist, buffer); } } } else {