PackageInfoLookup
This commit is contained in:
parent
6d8cf66f99
commit
a0d494ca93
|
@ -607,6 +607,12 @@ const QJsonArray Manager::packageInfo(const QJsonObject &pkgSelection, PackageIn
|
|||
const auto pkgName = entryObj.value(QStringLiteral("name")).toString();
|
||||
if(!pkgName.isEmpty()) {
|
||||
QJsonObject res;
|
||||
res.insert(QStringLiteral("name"), pkgName);
|
||||
res.insert(QStringLiteral("repo"), repo->name());
|
||||
const auto index = entryObj.value(QStringLiteral("index"));
|
||||
if(!index.isNull() && !index.isUndefined()) {
|
||||
res.insert(QStringLiteral("index"), index);
|
||||
}
|
||||
if(auto *pkg = repo->packageByName(pkgName)) {
|
||||
if(part & Basics) {
|
||||
res.insert(QStringLiteral("basics"), pkg->basicInfo());
|
||||
|
@ -617,12 +623,6 @@ const QJsonArray Manager::packageInfo(const QJsonObject &pkgSelection, PackageIn
|
|||
} else {
|
||||
res.insert(QStringLiteral("error"), QStringLiteral("na"));
|
||||
}
|
||||
res.insert(QStringLiteral("name"), pkgName);
|
||||
res.insert(QStringLiteral("repo"), repo->name());
|
||||
const auto index = entryObj.value(QStringLiteral("index"));
|
||||
if(!index.isNull() && !index.isUndefined()) {
|
||||
res.insert(QStringLiteral("index"), index);
|
||||
}
|
||||
results << res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "./package.h"
|
||||
#include "./package.h"
|
||||
#include "./alpmdatabase.h"
|
||||
#include "./utilities.h"
|
||||
#include "./repository.h"
|
||||
|
|
|
@ -1,49 +1,101 @@
|
|||
#include "./packageinfolookup.h"
|
||||
#include "./repository.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace RepoIndex {
|
||||
|
||||
PackageInfoLookup::PackageInfoLookup(Manager &manager, const QJsonObject &packageSelection, Manager::PackageInfoPart part, QObject *parent) :
|
||||
PackageLookup(parent)
|
||||
PackageInfoLookup::PackageInfoLookup(Manager &manager, const QJsonObject &request, QObject *parent) :
|
||||
PackageLookup(parent),
|
||||
m_what(request.value(QStringLiteral("what")).toString()),
|
||||
m_part(Manager::None)
|
||||
{
|
||||
if(part != Manager::None) {
|
||||
for(auto i = packageSelection.constBegin(), end = packageSelection.constEnd(); i != end; ++i) {
|
||||
if(auto *repo = manager.repositoryByName(i.key())) {
|
||||
QStringList packagesToBeRequested;
|
||||
for(const auto &entry : i.value().toArray()) {
|
||||
const auto entryObj = entry.toObject();
|
||||
const auto pkgName = entryObj.value(QStringLiteral("name")).toString();
|
||||
if(!pkgName.isEmpty()) {
|
||||
packagesToBeRequested << pkgName;
|
||||
}
|
||||
m_id = request.value(QStringLiteral("id"));
|
||||
if(m_what == QLatin1String("basicpkginfo")) {
|
||||
m_part = Manager::Basics;
|
||||
} else if(m_what == QLatin1String("pkgdetails")) {
|
||||
m_part = Manager::Details;
|
||||
} else if(m_what == QLatin1String("fullpkginfo")) {
|
||||
m_part = Manager::Basics | Manager::Details;
|
||||
} else {
|
||||
QJsonObject errorObj;
|
||||
errorObj.insert(QStringLiteral("error"), QStringLiteral("invalid_request"));
|
||||
m_results << errorObj;
|
||||
return;
|
||||
}
|
||||
m_packageSelection = request.value(QStringLiteral("sel")).toObject();
|
||||
for(auto i = m_packageSelection.constBegin(), end = m_packageSelection.constEnd(); i != end; ++i) {
|
||||
if(auto *repo = manager.repositoryByName(i.key())) {
|
||||
QStringList packagesToBeRequested;
|
||||
for(const auto &entry : i.value().toArray()) {
|
||||
const auto entryObj = entry.toObject();
|
||||
const auto pkgName = entryObj.value(QStringLiteral("name")).toString();
|
||||
if(!pkgName.isEmpty()) {
|
||||
packagesToBeRequested << pkgName;
|
||||
}
|
||||
if(!packagesToBeRequested.isEmpty()) {
|
||||
if(const auto *reply = (part & Manager::Details ? repo->requestFullPackageInfo(packagesToBeRequested) : repo->requestPackageInfo(packagesToBeRequested))) {
|
||||
connect(reply, &PackageReply::resultsAvailable, this, &PackageInfoLookup::addResults);
|
||||
++m_remainingReplies;
|
||||
} else {
|
||||
// no need to request any of the packages
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// specified repository can not be found
|
||||
QJsonObject errorObj;
|
||||
errorObj.insert(QStringLiteral("repo"), i.key());
|
||||
errorObj.insert(QStringLiteral("error"), QStringLiteral("na"));
|
||||
m_results << errorObj;
|
||||
}
|
||||
if(!packagesToBeRequested.isEmpty()) {
|
||||
if(const auto *reply = (m_part & Manager::Details ? repo->requestFullPackageInfo(packagesToBeRequested) : repo->requestPackageInfo(packagesToBeRequested))) {
|
||||
connect(reply, &PackageReply::resultsAvailable, this, &PackageInfoLookup::addResultsFromReply);
|
||||
++m_remainingReplies;
|
||||
} else {
|
||||
// no need to request any of the packages
|
||||
addResultsDirectly(packagesToBeRequested, repo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// specified repository can not be found
|
||||
QJsonObject errorObj;
|
||||
errorObj.insert(QStringLiteral("repo"), i.key());
|
||||
errorObj.insert(QStringLiteral("error"), QStringLiteral("na"));
|
||||
m_results << errorObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PackageInfoLookup::addResults()
|
||||
void PackageInfoLookup::addResultsDirectly(const QStringList &packageNames, const Repository *repo)
|
||||
{
|
||||
const auto &packages = repo->packages();
|
||||
for(const auto &packageName : packageNames) {
|
||||
QJsonObject res;
|
||||
res.insert(QStringLiteral("name"), packageName);
|
||||
res.insert(QStringLiteral("repo"), repo->name());
|
||||
// TODO: remember index
|
||||
const auto index = m_packageSelection.value(repo->name()).toObject().value(packageName).toObject().value(QStringLiteral("index"));
|
||||
if(!index.isNull() && !index.isUndefined()) {
|
||||
res.insert(QStringLiteral("index"), index);
|
||||
}
|
||||
bool avail = false;
|
||||
try {
|
||||
if(const auto &pkg = packages.at(packageName)) {
|
||||
avail = true;
|
||||
if(m_part & Manager::Basics) {
|
||||
res.insert(QStringLiteral("basics"), pkg->basicInfo());
|
||||
}
|
||||
if(m_part & Manager::Details) {
|
||||
res.insert(QStringLiteral("details"), pkg->detailedInfo());
|
||||
}
|
||||
}
|
||||
} catch(const out_of_range &) {
|
||||
}
|
||||
if(!avail) {
|
||||
res.insert(QStringLiteral("error"), QStringLiteral("na"));
|
||||
}
|
||||
m_results << res;
|
||||
}
|
||||
}
|
||||
|
||||
void PackageInfoLookup::addResultsFromReply()
|
||||
{
|
||||
assert(m_remainingReplies);
|
||||
auto *reply = static_cast<PackageReply *>(sender());
|
||||
m_results << reply->;
|
||||
reply->deleteLater();
|
||||
const auto *repo = reply->repository();
|
||||
addResultsDirectly(reply->requestedPackages(), repo);
|
||||
if(!--m_remainingReplies) {
|
||||
emit resultsAvailable(QStringLiteral("pkginfo"), m_id, m_results);
|
||||
emit resultsAvailable(m_what, m_id, m_results);
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,16 @@ class PackageInfoLookup : public PackageLookup
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PackageInfoLookup(Manager &manager, const QJsonObject &packageSelection, Manager::PackageInfoPart part, QObject *parent = nullptr);
|
||||
explicit PackageInfoLookup(Manager &manager, const QJsonObject &request, QObject *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void addResultsDirectly(const QStringList &packageNames, const Repository *repo);
|
||||
void addResultsFromReply();
|
||||
|
||||
private:
|
||||
void addResults();
|
||||
|
||||
const QString m_what;
|
||||
Manager::PackageInfoParts m_part;
|
||||
QJsonObject m_packageSelection;
|
||||
QList<Package *> m_packages;
|
||||
|
||||
};
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
#include "./packagelookup.h"
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -267,7 +267,7 @@ QJsonObject Repository::suggestions(const QString &term) const
|
|||
// }
|
||||
// }
|
||||
for(const auto &pkgEntry : packages()) {
|
||||
if(pkgEntry.first.compare(term, Qt::CaseInsensitive) == 0) {
|
||||
if(pkgEntry.first.contains(term, Qt::CaseInsensitive)) {
|
||||
suggestions << pkgEntry.first;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,27 +45,36 @@ class PackageReply : public Reply
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PackageReply(QNetworkReply *networkReply, std::map<QString, std::unique_ptr<Package> > &packages);
|
||||
PackageReply(const QList<QNetworkReply *> &networkReplies, std::map<QString, std::unique_ptr<Package> > &packages);
|
||||
const std::map<QString, std::unique_ptr<Package> > &packages() const;
|
||||
PackageReply(QNetworkReply *networkReply, const QStringList &requestedPackages, Repository *repo);
|
||||
PackageReply(const QList<QNetworkReply *> &networkReplies, const QStringList &requestedPackages, Repository *repo);
|
||||
const QStringList &requestedPackages() const;
|
||||
const Repository *repository() const;
|
||||
|
||||
protected:
|
||||
std::map<QString, std::unique_ptr<Package> > &m_packages;
|
||||
QStringList m_requestedPackages;
|
||||
Repository *m_repo;
|
||||
};
|
||||
|
||||
inline PackageReply::PackageReply(QNetworkReply *networkReply, std::map<QString, std::unique_ptr<Package> > &packages) :
|
||||
inline PackageReply::PackageReply(QNetworkReply *networkReply, const QStringList &requestedPackages, Repository *repo) :
|
||||
Reply(networkReply),
|
||||
m_packages(packages)
|
||||
m_requestedPackages(requestedPackages),
|
||||
m_repo(repo)
|
||||
{}
|
||||
|
||||
inline PackageReply::PackageReply(const QList<QNetworkReply *> &networkReplies, std::map<QString, std::unique_ptr<Package> > &packages) :
|
||||
inline PackageReply::PackageReply(const QList<QNetworkReply *> &networkReplies, const QStringList &requestedPackages, Repository *repo) :
|
||||
Reply(networkReplies),
|
||||
m_packages(packages)
|
||||
m_requestedPackages(requestedPackages),
|
||||
m_repo(repo)
|
||||
{}
|
||||
|
||||
inline const std::map<QString, std::unique_ptr<Package> > &PackageReply::packages() const
|
||||
inline const QStringList &PackageReply::requestedPackages() const
|
||||
{
|
||||
return m_packages;
|
||||
return m_requestedPackages;
|
||||
}
|
||||
|
||||
inline const Repository *PackageReply::repository() const
|
||||
{
|
||||
return m_repo;
|
||||
}
|
||||
|
||||
class SuggestionsReply : public Reply
|
||||
|
|
|
@ -116,6 +116,7 @@ private slots:
|
|||
protected:
|
||||
explicit UpgradeLookup(QObject *parent = nullptr);
|
||||
|
||||
|
||||
Repository *m_toCheck;
|
||||
unsigned int m_remainingProcesses;
|
||||
bool m_firstFinished;
|
||||
|
@ -136,6 +137,8 @@ class UpgradeLookupJson : public UpgradeLookup
|
|||
public:
|
||||
explicit UpgradeLookupJson(Manager &manager, const QJsonObject &request, QObject *parent = nullptr);
|
||||
const QJsonArray &errors() const;
|
||||
QJsonArray results() const;
|
||||
bool finished() const;
|
||||
|
||||
signals:
|
||||
void resultsAvailable(const QJsonValue &what, const QJsonValue &id, const QJsonValue &value);
|
||||
|
@ -158,6 +161,16 @@ inline const QJsonArray &UpgradeLookupJson::errors() const
|
|||
return m_errorsArray;
|
||||
}
|
||||
|
||||
inline QJsonArray UpgradeLookupJson::results() const
|
||||
{
|
||||
return QJsonArray(); // results are currently only returned by emitting resultsAvailable()
|
||||
}
|
||||
|
||||
inline bool UpgradeLookupJson::finished() const
|
||||
{
|
||||
return !m_remainingProcesses && m_errorsArray.isEmpty();
|
||||
}
|
||||
|
||||
class UpgradeLookupCli : public UpgradeLookup
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
@ -71,6 +71,28 @@ void Connection::sendResults(const QJsonValue &what, const QJsonValue &id, const
|
|||
sendJson(response);
|
||||
}
|
||||
|
||||
template<class Lookup, typename... Args>
|
||||
void Connection::performLookup(const QJsonObject &request, Args &&...args)
|
||||
{
|
||||
auto *lookup = new Lookup(forward<Args>(args)...);
|
||||
if(lookup->finished()) {
|
||||
// the lookup has already finished when constructing the lookup object
|
||||
// -> send the results immidiately
|
||||
sendResult(request.value(QStringLiteral("what")), request.value(QStringLiteral("id")), lookup->results());
|
||||
} else if(!lookup->errors().isEmpty()) {
|
||||
// error occured during the construction of the lookup object
|
||||
// -> send the errors immidiately
|
||||
QJsonObject results;
|
||||
results.insert(QStringLiteral("errors"), lookup->errors());
|
||||
sendResult(request.value(QStringLiteral("what")), request.value(QStringLiteral("id")), results);
|
||||
} else {
|
||||
// the lookup object has been created without errors but the lookup is not done yet
|
||||
// -> send results when available
|
||||
connect(lookup, &Lookup::resultsAvailable, this, &Connection::sendResult);
|
||||
}
|
||||
// in any case: the lookup object destroys itself
|
||||
}
|
||||
|
||||
void Connection::handleQuery(const QJsonObject &obj)
|
||||
{
|
||||
const auto what = obj.value(QStringLiteral("what")).toString();
|
||||
|
@ -79,39 +101,14 @@ void Connection::handleQuery(const QJsonObject &obj)
|
|||
m_repoInfoUpdatesRequested = obj.value(QStringLiteral("updates")).toBool(m_repoInfoUpdatesRequested);
|
||||
sendResult(what, id, m_manager.basicRepoInfo());
|
||||
} else if(what == QLatin1String("basicpkginfo") || what == QLatin1String("pkgdetails") || what == QLatin1String("fullpkginfo")) {
|
||||
auto *packageInfoLookup = new PackageInfoLookup(m_manager, obj);
|
||||
if(packageInfoLookup->finished()) {
|
||||
sendResult(what, id, packageInfoLookup->results());
|
||||
} else if(!packageInfoLookup->errors().isEmpty()) {
|
||||
QJsonObject results;
|
||||
results.insert(QStringLiteral("errors"), packageInfoLookup->errors());
|
||||
sendResult(what, id, results);
|
||||
} else {
|
||||
connect(packageInfoLookup, &SuggestionsLookup::resultsAvailable, this, &Connection::sendResult);
|
||||
}
|
||||
performLookup<PackageInfoLookup>(obj, m_manager, obj);
|
||||
} else if(what == QLatin1String("groupinfo")) {
|
||||
m_groupInfoUpdatesRequested = obj.value(QStringLiteral("updates")).toBool(m_groupInfoUpdatesRequested);
|
||||
sendResults(what, id, m_manager.groupInfo());
|
||||
} else if(what == QLatin1String("suggestions")) {
|
||||
auto *suggestionsLookup = new SuggestionsLookup(m_manager, obj);
|
||||
if(suggestionsLookup->finished()) {
|
||||
sendResult(what, id, suggestionsLookup->results());
|
||||
} else if(!suggestionsLookup->errors().isEmpty()) {
|
||||
QJsonObject results;
|
||||
results.insert(QStringLiteral("errors"), suggestionsLookup->errors());
|
||||
sendResult(what, id, results);
|
||||
} else {
|
||||
connect(suggestionsLookup, &SuggestionsLookup::resultsAvailable, this, &Connection::sendResult);
|
||||
}
|
||||
performLookup<SuggestionsLookup>(obj, m_manager, obj);
|
||||
} else if(what == QLatin1String("upgradelookup")) {
|
||||
auto *upgradeLookup = new UpgradeLookupJson(m_manager, obj);
|
||||
if(upgradeLookup->errors().isEmpty()) {
|
||||
connect(upgradeLookup, &UpgradeLookupJson::resultsAvailable, this, &Connection::sendResult);
|
||||
} else {
|
||||
QJsonObject results;
|
||||
results.insert(QStringLiteral("errors"), upgradeLookup->errors());
|
||||
sendResult(what, id, results);
|
||||
}
|
||||
performLookup<UpgradeLookupJson>(obj, m_manager, obj);
|
||||
} else if(what == QLatin1String("ping")) {
|
||||
sendResult(what, id, QStringLiteral("pong"));
|
||||
} else {
|
||||
|
|
|
@ -31,12 +31,12 @@ private:
|
|||
void sendError(const QString &msg, const QJsonValue &id = QJsonValue());
|
||||
void handleQuery(const QJsonObject &obj);
|
||||
void handleCmd(const QJsonObject &obj);
|
||||
template<class Lookup, typename... Args> void performLookup(const QJsonObject &request, Args &&...args);
|
||||
|
||||
QWebSocket *m_socket;
|
||||
RepoIndex::Manager &m_manager;
|
||||
bool m_repoInfoUpdatesRequested;
|
||||
bool m_groupInfoUpdatesRequested;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ QUrl UserRepository::m_aurPkgbuildUrl = QUrl(QStringLiteral("https://aur.archlin
|
|||
QUrl UserRepository::m_aurSrcInfoUrl = QUrl(QStringLiteral("https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO"));
|
||||
QString UserRepository::m_aurSnapshotPath = QStringLiteral("https://aur.archlinux.org/cgit/aur.git/snapshot/%1.tar.gz");
|
||||
|
||||
AurPackageReply::AurPackageReply(QNetworkReply *networkReply, UserRepository *userRepo) :
|
||||
PackageReply(networkReply, userRepo->packages()),
|
||||
AurPackageReply::AurPackageReply(QNetworkReply *networkReply, const QStringList &requestedPackages, UserRepository *userRepo) :
|
||||
PackageReply(networkReply, requestedPackages, userRepo),
|
||||
m_userRepo(userRepo)
|
||||
{}
|
||||
|
||||
|
@ -46,13 +46,14 @@ void AurPackageReply::processData()
|
|||
//QByteArray data = m_networkReply->readAll();
|
||||
//cerr << shchar << "AUR reply: " << data.data() << endl;
|
||||
//const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
const auto doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
auto &packages = m_repo->packages();
|
||||
if(error.error == QJsonParseError::NoError) {
|
||||
for(const auto &result : doc.object().value(QStringLiteral("results")).toArray()) {
|
||||
QJsonObject obj = result.toObject();
|
||||
QString packageName = obj.value(QStringLiteral("Name")).toString();
|
||||
if(!packageName.isEmpty()) {
|
||||
auto &package = m_packages[packageName];
|
||||
auto &package = packages[packageName];
|
||||
if(package) {
|
||||
static_cast<AurPackage *>(package.get())->putJson(obj);
|
||||
} else {
|
||||
|
@ -69,8 +70,8 @@ void AurPackageReply::processData()
|
|||
emit resultsAvailable();
|
||||
}
|
||||
|
||||
AurFullPackageReply::AurFullPackageReply(const QList<QNetworkReply *> &networkReplies, UserRepository *userRepo) :
|
||||
PackageReply(networkReplies, userRepo->packages()),
|
||||
AurFullPackageReply::AurFullPackageReply(const QList<QNetworkReply *> &networkReplies, const QStringList &requestedPackages, UserRepository *userRepo) :
|
||||
PackageReply(networkReplies, requestedPackages, userRepo),
|
||||
m_userRepo(userRepo)
|
||||
{}
|
||||
|
||||
|
@ -122,7 +123,7 @@ void AurSuggestionsReply::processData()
|
|||
//QByteArray data = m_networkReply->readAll();
|
||||
//cerr << shchar << "AUR reply: " << data.data() << endl;
|
||||
//const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
const auto doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
if(error.error == QJsonParseError::NoError) {
|
||||
auto &packages = m_repo->packages();
|
||||
if(doc.isObject()) {
|
||||
|
@ -226,7 +227,7 @@ AurPackageReply *UserRepository::requestPackageInfo(const QStringList &packageNa
|
|||
auto url = m_aurRpcUrl;
|
||||
query.addQueryItem(rpcRequestTypeKey, rpcRequestTypeMultiInfo);
|
||||
url.setQuery(query);
|
||||
return new AurPackageReply(m_networkAccessManager.get(QNetworkRequest(url)), this);
|
||||
return new AurPackageReply(m_networkAccessManager.get(QNetworkRequest(url)), packageNames, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,7 +253,7 @@ AurFullPackageReply *UserRepository::requestFullPackageInfo(const QStringList &p
|
|||
if(replies.isEmpty()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return new AurFullPackageReply(replies, this);
|
||||
return new AurFullPackageReply(replies, packageNames, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class AurPackageReply : public PackageReply
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AurPackageReply(QNetworkReply *networkReply, UserRepository *userRepo);
|
||||
AurPackageReply(QNetworkReply *networkReply, const QStringList &requestedPackages, UserRepository *userRepo);
|
||||
|
||||
private slots:
|
||||
void processData();
|
||||
|
@ -34,7 +34,7 @@ class AurFullPackageReply : public PackageReply
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AurFullPackageReply(const QList<QNetworkReply *> &networkReplies, UserRepository *userRepo);
|
||||
AurFullPackageReply(const QList<QNetworkReply *> &networkReplies, const QStringList &requestedPackages, UserRepository *userRepo);
|
||||
|
||||
private slots:
|
||||
void processData();
|
||||
|
|
Loading…
Reference in New Issue