144 lines
5.4 KiB
C++
144 lines
5.4 KiB
C++
#include "./packageinfolookup.h"
|
|
#include "./repository.h"
|
|
|
|
#include <cassert>
|
|
|
|
using namespace std;
|
|
|
|
namespace RepoIndex {
|
|
|
|
PackageInfoLookup::PackageInfoLookup(Manager &manager, const QJsonObject &request, QObject *parent) :
|
|
PackageLookup(parent),
|
|
m_manager(manager),
|
|
m_what(request.value(QStringLiteral("w")).toString()),
|
|
m_part(Manager::None)
|
|
{
|
|
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();
|
|
m_repos.reserve(m_packageSelection.size());
|
|
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()) {
|
|
m_repos << qMakePair(repo, packagesToBeRequested);
|
|
}
|
|
} else {
|
|
// specified repository can not be found
|
|
QJsonObject errorObj;
|
|
errorObj.insert(QStringLiteral("repo"), i.key());
|
|
errorObj.insert(QStringLiteral("error"), QStringLiteral("na"));
|
|
m_results << errorObj;
|
|
}
|
|
}
|
|
performLookup();
|
|
}
|
|
|
|
void PackageInfoLookup::performLookup()
|
|
{
|
|
m_waitingForBusyRepos = false;
|
|
for(auto &entry : m_repos) {
|
|
if(Repository *repo = entry.first) {
|
|
const QStringList &packagesToBeRequested = entry.second;
|
|
if(repo->isBusy()) {
|
|
// repo is busy -> try again when available
|
|
connect(repo, &Repository::available, this, &PackageInfoLookup::performLookup);
|
|
m_waitingForBusyRepos = true;
|
|
} else {
|
|
// disconnect to ensure the lookup isn't done twice
|
|
disconnect(repo, nullptr, this, nullptr);
|
|
// this repo can be skipped when this method is called again because other repos where busy
|
|
entry.first = nullptr;
|
|
// request package info
|
|
QReadLocker locker(repo->lock());
|
|
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: repo already processed
|
|
}
|
|
}
|
|
|
|
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()
|
|
{
|
|
#ifdef DEBUG_BUILD
|
|
assert(m_remainingReplies);
|
|
#endif
|
|
auto *reply = static_cast<PackageReply *>(sender());
|
|
reply->deleteLater();
|
|
if(reply->error().isEmpty()) {
|
|
QReadLocker lock(reply->repository()->lock());
|
|
addResultsDirectly(reply->requestedPackages(), reply->repository());
|
|
} else {
|
|
// TODO: bunch error messages together
|
|
for(const auto &packageName : reply->requestedPackages()) {
|
|
QJsonObject res;
|
|
res.insert(QStringLiteral("name"), packageName);
|
|
res.insert(QStringLiteral("repo"), reply->repository()->name());
|
|
res.insert(QStringLiteral("error"), reply->error());
|
|
m_results << res;
|
|
}
|
|
}
|
|
if(!--m_remainingReplies) {
|
|
emit resultsAvailable(m_what, m_id, m_results);
|
|
deleteLater();
|
|
}
|
|
}
|
|
|
|
} // namespace RepoIndex
|
|
|