mirror of
https://github.com/outbackdingo/sysadm.git
synced 2026-01-27 10:20:26 +00:00
[API CHANGE] Add a new "pkg_install_verify" action to sysadm/pkg
Add an "action" = "pkg_install_verify" option to the sysadm/pkg API call.
REQUIRED: "pkg_origins" - string or array of pkg origins
"repo" - remote repository that the package will be installed from.
----------
REST Request (example):
-------------------------------
PUT /sysadm/pkg
{
"repo" : "trueos-major",
"action" : "pkg_install_verify",
"pkg_origins" : [
"www/qupzilla-qt5-webkit"
]
}
WebSocket Request:
-------------------------------
{
"name" : "pkg",
"namespace" : "sysadm",
"id" : "fooid",
"args" : {
"action" : "pkg_install_verify",
"pkg_origins" : [
"www/qupzilla-qt5-webkit"
],
"repo" : "trueos-major"
}
}
Response:
-------------------------------
{
"args": {
"pkg_install_verify": {
"conflicts": [],
"install": {
"qupzilla-qt5-webkit": {
"comment": "Web browser based on WebKit engine and Qt Framework",
"flatsize": "13380132",
"name": "qupzilla-qt5-webkit",
"origin": "www/qupzilla-qt5-webkit",
"pkgsize": "2574460",
"version": "1.8.9_3"
}
}
}
},
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}
This commit is contained in:
@@ -865,20 +865,20 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmPkgRequest(const QJsonValue
|
||||
if(in_args.toObject().value("pkg_origins").isString()){ pkgs << in_args.toObject().value("pkg_origins").toString(); }
|
||||
else if(in_args.toObject().value("pkg_origins").isArray()){ pkgs = JsonArrayToStringList(in_args.toObject().value("pkg_origins").toArray()); }
|
||||
}
|
||||
|
||||
|
||||
//Parse the action and perform accordingly
|
||||
if(act=="pkg_info"){
|
||||
//OPTIONAL: "pkg_origins" OR "category"
|
||||
//OPTIONAL: "repo"
|
||||
//OPTIONAL: "result" = "full" or "simple" (Default: "simple")
|
||||
bool fullresults = false;
|
||||
bool fullresults = false;
|
||||
if(in_args.toObject().contains("result")){ fullresults = (in_args.toObject().value("result").toString()=="full"); }
|
||||
|
||||
|
||||
//Now run the info fetch routine
|
||||
QJsonObject info = sysadm::PKG::pkg_info(pkgs, repo, cat, fullresults);
|
||||
if(!info.isEmpty()){ out->insert("pkg_info",info); }
|
||||
else{ return RestOutputStruct::NOCONTENT; }
|
||||
|
||||
|
||||
}else if(act=="pkg_search" && in_args.toObject().contains("search_term")){
|
||||
//REQUIRED: "search_term" (string to search for)
|
||||
//OPTIONAL: "repo"
|
||||
@@ -899,22 +899,26 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmPkgRequest(const QJsonValue
|
||||
}else{
|
||||
return RestOutputStruct::NOCONTENT;
|
||||
}
|
||||
|
||||
|
||||
}else if(act=="list_categories"){
|
||||
//OPTIONAL: "repo"
|
||||
QJsonArray cats = sysadm::PKG::list_categories(repo);
|
||||
if(!cats.isEmpty()){ out->insert("list_categories", cats); }
|
||||
else{ return RestOutputStruct::NOCONTENT; }
|
||||
|
||||
|
||||
}else if(act=="list_repos"){
|
||||
QJsonArray repos = sysadm::PKG::list_repos();
|
||||
if(!repos.isEmpty()){ out->insert("list_repos", repos); }
|
||||
else{ return RestOutputStruct::NOCONTENT; }
|
||||
|
||||
|
||||
}else if(act=="pkg_install" && !pkgs.isEmpty() ){
|
||||
//REQUIRED: "pkg_origins"
|
||||
//OPTIONAL: "repo" (pkg will determine the best repo to use if not supplied)
|
||||
out->insert("pkg_install", sysadm::PKG::pkg_install(pkgs,repo));
|
||||
|
||||
}else if(act=="pkg_install_verify"){
|
||||
//REQUIRED: "pkg_origins", "repo"
|
||||
out->insert("pkg_install_verify", sysadm::PKG::evaluateInstall(pkgs,repo) );
|
||||
}else if(act=="pkg_remove" && !pkgs.isEmpty() ){
|
||||
//REQUIRED: "pkg_origins"
|
||||
//OPTIONAL: "recursive"="true" or "false" (default: "true")
|
||||
@@ -923,10 +927,10 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmPkgRequest(const QJsonValue
|
||||
out->insert("pkg_remove", sysadm::PKG::pkg_remove(pkgs, recursive));
|
||||
}else if(act=="pkg_lock" && !pkgs.isEmpty() ){
|
||||
//REQUIRED: "pkg_origins"
|
||||
out->insert("pkg_lock", sysadm::PKG::pkg_lock(pkgs));
|
||||
out->insert("pkg_lock", sysadm::PKG::pkg_lock(pkgs));
|
||||
}else if(act=="pkg_unlock" && !pkgs.isEmpty() ){
|
||||
//REQUIRED: "pkg_origins"
|
||||
out->insert("pkg_unlock", sysadm::PKG::pkg_unlock(pkgs));
|
||||
out->insert("pkg_unlock", sysadm::PKG::pkg_unlock(pkgs));
|
||||
}else if(act=="pkg_update"){
|
||||
//OPTIONAL: "force" = ["true"/"false"] (default: "false")
|
||||
bool force = false;
|
||||
@@ -944,7 +948,7 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmPkgRequest(const QJsonValue
|
||||
//unknown action
|
||||
return RestOutputStruct::BADREQUEST;
|
||||
}
|
||||
|
||||
|
||||
return RestOutputStruct::OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,20 @@ using namespace sysadm;
|
||||
// ==================
|
||||
// INLINE FUNCTIONS
|
||||
// ==================
|
||||
inline QStringList ids_from_origins(QStringList origins, QSqlDatabase DB){
|
||||
QSqlQuery q("SELECT id FROM packages WHERE origin IN ('"+origins.join("', '")+"')",DB);
|
||||
QStringList out;
|
||||
while(q.next()){ out << q.value("id").toString(); }
|
||||
return out;
|
||||
}
|
||||
|
||||
inline QStringList ids_from_names(QStringList names, QSqlDatabase DB){
|
||||
QSqlQuery q("SELECT id FROM packages WHERE name IN ('"+names.join("', '")+"')",DB);
|
||||
QStringList out;
|
||||
while(q.next()){ out << q.value("id").toString(); }
|
||||
return out;
|
||||
}
|
||||
|
||||
//Get annotation variable/values
|
||||
inline void annotations_from_ids(QStringList var_ids, QStringList val_ids, QJsonObject *out, QSqlDatabase DB){
|
||||
//Note: Both input lists *must* be the same length (one variable for one value)
|
||||
@@ -47,7 +61,7 @@ inline QStringList origins_from_package_ids(QStringList ids, QSqlDatabase DB){
|
||||
while(q.next()){ out << q.value("origin").toString(); }
|
||||
return out;
|
||||
}
|
||||
//Generic ID's -> Names function (known databases: users, groups, licenses, shlibs, categories )
|
||||
//Generic ID's -> Names function (known databases: users, groups, licenses, shlibs, categories, packages )
|
||||
inline QStringList names_from_ids(QStringList ids, QString db, QSqlDatabase DB){
|
||||
QSqlQuery q("SELECT name FROM "+db+" WHERE id IN ('"+ids.join("', '")+"')",DB);
|
||||
QStringList out;
|
||||
@@ -68,6 +82,26 @@ inline QStringList requires_from_ids(QStringList ids, QSqlDatabase DB){
|
||||
while(q.next()){ out << q.value("require").toString(); }
|
||||
return out;
|
||||
}
|
||||
|
||||
//conflict ID's from package ID's
|
||||
inline QStringList conflicts_from_ids(QStringList ids, QSqlDatabase DB){
|
||||
QSqlQuery q("SELECT conflict_id FROM pkg_conflicts WHERE package_id IN ('"+ids.join("', '")+"')", DB);
|
||||
QStringList out;
|
||||
while(q.next()){ out << q.value("conflict_id").toString(); }
|
||||
qDebug() << "Last Conflict detection Error:" << q.lastError().text();
|
||||
return out;
|
||||
}
|
||||
|
||||
//dependencies from package ID's
|
||||
inline QStringList depends_from_ids(QStringList ids, QSqlDatabase DB){
|
||||
//Note: This returns package names, not ID's
|
||||
QSqlQuery q("SELECT name FROM deps WHERE package_id IN ('"+ids.join("', '")+"')", DB);
|
||||
QStringList out;
|
||||
while(q.next()){ out << q.value("name").toString(); }
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
inline QString getRepoFile(QString repo){
|
||||
if(repo=="local"){ return "/var/db/pkg/local.sqlite"; }
|
||||
else{ return ("/var/db/pkg/repo-"+repo+".sqlite"); }
|
||||
@@ -204,7 +238,7 @@ QJsonObject PKG::pkg_info(QStringList origins, QString repo, QString category, b
|
||||
QSqlQuery q15("SELECT require_id FROM pkg_requires WHERE package_id = '"+id+"'", DB);
|
||||
tmpList.clear();
|
||||
while(q15.next()){ tmpList << q15.value("require_id").toString(); }
|
||||
if(!tmpList.isEmpty()){ info.insert("requires", QJsonArray::fromStringList(requires_from_ids(tmpList, DB)) ); }
|
||||
if(!tmpList.isEmpty()){ info.insert("requires", QJsonArray::fromStringList(requires_from_ids(tmpList, DB)) ); }\
|
||||
//Now insert this information into the main object
|
||||
retObj.insert(origin,info);
|
||||
} //end loop over pkg matches
|
||||
@@ -350,6 +384,75 @@ QJsonArray PKG::list_repos(bool updated){
|
||||
return QJsonArray::fromStringList(found);
|
||||
}
|
||||
|
||||
QJsonObject PKG::evaluateInstall(QStringList origins, QString repo){
|
||||
qDebug() << "Verify Install:" << origins << repo;
|
||||
QJsonObject out;
|
||||
if(repo=="local" || origins.isEmpty()){ return out; } //nothing to do
|
||||
QString dbconn = openDB(repo);
|
||||
QString ldbconn = openDB("local");
|
||||
if(!dbconn.isEmpty()){
|
||||
QSqlDatabase DB = QSqlDatabase::database(dbconn);
|
||||
QSqlDatabase LDB = QSqlDatabase::database(ldbconn);
|
||||
if(!DB.isOpen() || !LDB.isOpen()){ return out; } //could not open DB (file missing?)
|
||||
|
||||
//First get the list of all packages which need to be installed (ID's) from the remote database
|
||||
QStringList toInstall_id;
|
||||
QStringList tmp = names_from_ids( ids_from_origins(origins, DB), "packages", DB);
|
||||
//qDebug() << " - Initial names:" << tmp;
|
||||
while(!tmp.isEmpty()){
|
||||
QStringList ids = ids_from_names(tmp, DB);
|
||||
for(int i=0; i<ids.length(); i++){
|
||||
if(toInstall_id.contains(ids[i])){ ids.removeAt(i); i--; } //remove any duplicate/evaluated ID's
|
||||
}
|
||||
if(ids.isEmpty()){ break; } //stop the loop - found the last round of dependencies
|
||||
toInstall_id << ids; //add these to the list which are going to get installed
|
||||
tmp = depends_from_ids(ids, DB); //now get the depdendencies of these packages
|
||||
//qDebug() << " - Iteration names:" << tmp;
|
||||
}
|
||||
|
||||
//Now go through and remove any packages from the list which are already installed locally
|
||||
QStringList names = names_from_ids(toInstall_id, "packages", DB); //same order
|
||||
//qDebug() << " - Total Names:" << names;
|
||||
QStringList local_names = names_from_ids( ids_from_names(names, LDB), "packages", LDB);
|
||||
//qDebug() << " - Local Names:" << local_names;
|
||||
for(int i=0; i<local_names.length(); i++){
|
||||
names.removeAll(local_names[i]);
|
||||
}
|
||||
qDebug() << " - Filtered Names:" << names;
|
||||
toInstall_id = ids_from_names(names, DB); //now get the shorter/filtered list of ID's (remote)
|
||||
//qDebug() << " - Filtered ID's:" << toInstall_id;
|
||||
//Get the list of conflicting packages which are already installed
|
||||
QStringList conflict_ids = conflicts_from_ids(toInstall_id, DB); //also get the list of any conflicts for these packages
|
||||
conflict_ids.removeDuplicates();
|
||||
QStringList conflict_names = names_from_ids(conflict_ids, "packages", DB);
|
||||
qDebug() << " - Conflicts (remote):" << conflict_ids << conflict_names;
|
||||
out.insert("conflicts", QJsonArray::fromStringList(names_from_ids( ids_from_names(conflict_names, LDB), "packages", LDB) ) );
|
||||
//Now assemble all the information about the packages (remote database)
|
||||
QJsonObject install;
|
||||
//qDebug() << "Perform Query";
|
||||
QSqlQuery qi("SELECT * FROM packages WHERE id IN ('"+toInstall_id.join("', '")+"')", DB);
|
||||
while(qi.next()){
|
||||
QJsonObject obj;
|
||||
obj.insert( "name", qi.value("name").toString());
|
||||
obj.insert( "origin", qi.value("origin").toString());
|
||||
obj.insert( "pkgsize", qi.value("pkgsize").toString());
|
||||
obj.insert( "flatsize", qi.value("flatsize").toString());
|
||||
obj.insert( "version", qi.value("version").toString());
|
||||
obj.insert( "comment", qi.value("comment").toString());
|
||||
install.insert(qi.value("name").toString(), obj);
|
||||
}
|
||||
qDebug() << "Final Install Object:" << install;
|
||||
//qDebug() << "Last Query Error:" << qi.lastError().text();
|
||||
//Add the info to the output object and close the databases
|
||||
out.insert("install", install);
|
||||
DB.close();
|
||||
LDB.close();
|
||||
} //force DB out of scope
|
||||
QSqlDatabase::removeDatabase(dbconn);
|
||||
QSqlDatabase::removeDatabase(ldbconn);
|
||||
return out;
|
||||
}
|
||||
|
||||
//=================
|
||||
//pkg modification routines (dispatcher events for notifications)
|
||||
//=================
|
||||
|
||||
@@ -24,6 +24,8 @@ public:
|
||||
static QStringList pkg_search(QString repo, QString searchterm, QStringList searchexcludes, QString category = "");
|
||||
static QJsonArray list_categories(QString repo);
|
||||
static QJsonArray list_repos(bool updated = false);
|
||||
static QJsonObject evaluateInstall(QStringList origins, QString repo); //evaluate what will be done if these packages are installed
|
||||
|
||||
|
||||
//pkg modification routines (dispatcher events for notifications)
|
||||
static QJsonObject pkg_install(QStringList origins, QString repo);
|
||||
|
||||
Reference in New Issue
Block a user