DistroqueryAPI: added package_files API call and files list in package details response

This commit is contained in:
Silvan Calarco 2024-08-11 17:56:14 +02:00
parent ec3f7b4847
commit e27c278b13
3 changed files with 101 additions and 4 deletions

View File

@ -5,6 +5,9 @@
"vector": "cpp",
"string": "cpp",
"format": "cpp",
"string.h": "c"
"string.h": "c",
"chrono": "cpp",
"text_encoding": "cpp",
"typeinfo": "cpp"
}
}

View File

@ -416,13 +416,90 @@ json DistroqueryAPI::getPackageSourceDetails(string repository, string package)
}
} else {
j["error"] = "error preparing query '" + sql + "'";
j["error"] = "error preparing query '" + sql + "': " + sqlite3_errmsg(db);
return j;
}
sqlite3_close(db);
return j;
}
string DistroqueryAPI::resolvePackageFilePathById(sqlite3 *db, long id) {
string sql;
sqlite3_stmt *stmt;
string outpath="";
static long cachedid = -1;
static string cachedpath = "";
if (id == cachedid)
return cachedpath;
cachedid = id;
while (id >= 0) {
sql = "SELECT parent,name FROM files WHERE id=" + to_string(id);
if (sqlite3_prepare_v2(db, sql.c_str(), sql.length(), &stmt, NULL) == SQLITE_OK) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
id = sqlite3_column_int(stmt,sqlite3_find_column_id(stmt, NULL, "parent"));
string name = reinterpret_cast<const char*>(sqlite3_column_text(stmt,sqlite3_find_column_id(stmt, NULL, "name")));
outpath = "/" + name + outpath;
}
} else {
return "?";
}
}
cachedpath = outpath;
return outpath;
}
json DistroqueryAPI::getPackageFiles(string repository, string package, string arch) {
json j;
string sql;
sqlite3_stmt *stmt;
struct configTag* ct = findRepositoryByTag(repository.c_str());
if (ct == NULL) {
j["error"] = "repository with tag '" + repository + "' does not exist";
return j;
}
if (ct->repodata_url == NULL) {
j["error"] = "repository with tag '" + repository + "' is not supported by this API";
return j;
}
auto db = openRepositoryDatabase(ct, arch, "-files");
if (!db) {
j["error"] = "error opening database for repository " + repository + " and arch " + arch;
return j;
}
sql = "SELECT files.id,files.parent,files.name FROM files,packages_files_rel WHERE packages_files_rel.name = '" + package + "' " +
"AND files.id=packages_files_rel.id_file";
if (sqlite3_prepare_v2(db, sql.c_str(), sql.length(), &stmt, NULL) == SQLITE_OK) {
json files = json::array();
while (sqlite3_step(stmt) == SQLITE_ROW) {
json file;
long parent = sqlite3_column_int(stmt,sqlite3_find_column_id(stmt, NULL, "parent"));
file["path"] = resolvePackageFilePathById(db, parent) + "/" +
reinterpret_cast<const char*>(sqlite3_column_text(stmt,sqlite3_find_column_id(stmt, NULL, "name")));
// TODO: unusable/missing values
/*file["flags"] = sqlite3_column_int(stmt,sqlite3_find_column_id(stmt, "packages_files_rel", "flags"));
file["user"] = sqlite3_column_int(stmt,sqlite3_find_column_id(stmt, "packages_files_rel", "user"));
file["group"] = sqlite3_column_int(stmt,sqlite3_find_column_id(stmt, "packages_files_rel", "group"));*/
files.push_back(file);
}
j["files"] = files;
} else {
j["error"] = "error preparing query '" + sql + "': " + sqlite3_errmsg(db);
return j;
}
sqlite3_close(db);
return j;
}
json DistroqueryAPI::getPackageDetails(string repository, string package, string arch) {
json j;
string sql;
@ -534,8 +611,15 @@ json DistroqueryAPI::getPackageDetails(string repository, string package, string
sqlite3_finalize(stmt2);
}
// Package files
json files = getPackageFiles(repository, package, arch);
if (files.contains("files"))
j["files"] = files["files"];
else
j["files"] = files;
} else {
j["error"] = "error preparing query '" + sql + "'";
j["error"] = "error preparing query '" + sql + "': " + sqlite3_errmsg(db);
return j;
}
@ -698,6 +782,14 @@ void DistroqueryAPI::getApiResponse(string path_info) {
details = getPackageDetails(path_split[1], package, path_split[3]);
}
cout << details.dump();
} else if (path_split[0] == "package_files") {
// API service: package_files
if (path_split.size() != 4)
sendErrorResponse("expected 4 arguments for " + path_split[0]);
json details;
string package = urlDecode(path_split[2]);
details = getPackageFiles(path_split[1], package, path_split[3]);
cout << details.dump();
} else if (path_split[0] == "providers") {
// API service: providers
if (path_split.size() != 3 && path_split.size() != 5)
@ -717,7 +809,7 @@ void DistroqueryAPI::getApiResponse(string path_info) {
json problems = getRepositoryProblems(path_split[1]);
cout << problems.dump();
} else {
sendErrorResponse("invalid request for service '" + path_split[0]);
sendErrorResponse("unknown service: '" + path_split[0]);
}
} else {
sendErrorResponse("empty request");

View File

@ -48,7 +48,9 @@ class DistroqueryAPI {
json getProvidersForRequirement(string repository, string requirement, string flags,
string version, string onlyarch="");
json getPackageSourceDetails(string repository, string package);
string resolvePackageFilePathById(sqlite3 *db, long id);
json getBuiltPackagesFromSourceID(configTag* ct, long id);
json getPackageFiles(string repository, string package, string arch);
json getPackageDetails(string repository, string package, string arch);
json getRepositoryProblems(string repository);
};