repoindex/alpm/packageinfolookup.cpp

142 lines
5.4 KiB
C++
Raw Normal View History

2015-09-27 19:29:45 +02:00
#include "./packageinfolookup.h"
#include "./repository.h"
2015-09-29 21:52:30 +02:00
#include <cassert>
using namespace std;
2015-09-27 19:29:45 +02:00
namespace RepoIndex {
2015-09-29 21:52:30 +02:00
PackageInfoLookup::PackageInfoLookup(Manager &manager, const QJsonObject &request, QObject *parent) :
PackageLookup(parent),
2016-02-25 22:53:33 +01:00
m_manager(manager),
2015-09-29 21:52:30 +02:00
m_what(request.value(QStringLiteral("what")).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();
2016-02-25 22:53:33 +01:00
m_repos.reserve(m_packageSelection.size());
2015-09-29 21:52:30 +02:00
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()) {
2016-02-25 22:53:33 +01:00
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()
{
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);
} 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
2015-11-03 18:19:24 +01:00
QReadLocker locker(repo->lock());
2015-09-29 21:52:30 +02:00
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);
}
}
2016-02-25 22:53:33 +01:00
} // else: repo already processed
2015-09-29 21:52:30 +02:00
}
}
void PackageInfoLookup::addResultsDirectly(const QStringList &packageNames, const Repository *repo)
2015-09-27 19:29:45 +02:00
{
2015-09-29 21:52:30 +02:00
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)) {
2015-09-29 21:52:30 +02:00
avail = true;
if(m_part & Manager::Basics) {
res.insert(QStringLiteral("basics"), pkg->basicInfo());
2015-09-27 19:29:45 +02:00
}
2015-09-29 21:52:30 +02:00
if(m_part & Manager::Details) {
res.insert(QStringLiteral("details"), pkg->detailedInfo());
2015-09-27 19:29:45 +02:00
}
}
2015-09-29 21:52:30 +02:00
} catch(const out_of_range &) {
}
if(!avail) {
res.insert(QStringLiteral("error"), QStringLiteral("na"));
2015-09-27 19:29:45 +02:00
}
2015-09-29 21:52:30 +02:00
m_results << res;
2015-09-27 19:29:45 +02:00
}
}
2015-09-29 21:52:30 +02:00
void PackageInfoLookup::addResultsFromReply()
2015-09-27 19:29:45 +02:00
{
2016-02-25 22:53:33 +01:00
#ifdef DEBUG_BUILD
2015-09-27 19:29:45 +02:00
assert(m_remainingReplies);
2016-02-25 22:53:33 +01:00
#endif
2015-09-27 19:29:45 +02:00
auto *reply = static_cast<PackageReply *>(sender());
reply->deleteLater();
2015-10-28 19:55:36 +01:00
if(reply->error().isEmpty()) {
2015-11-03 18:19:24 +01:00
QReadLocker lock(reply->repository()->lock());
2015-10-28 19:55:36 +01:00
addResultsDirectly(reply->requestedPackages(), reply->repository());
} else {
2015-11-03 18:19:24 +01:00
// TODO: bunch error messages together
for(const auto &packageName : reply->requestedPackages()) {
2015-10-28 19:55:36 +01:00
QJsonObject res;
res.insert(QStringLiteral("name"), packageName);
res.insert(QStringLiteral("repo"), reply->repository()->name());
2015-11-03 18:19:24 +01:00
res.insert(QStringLiteral("error"), reply->error());
m_results << res;
2015-10-28 19:55:36 +01:00
}
2015-09-27 19:29:45 +02:00
}
2015-11-03 18:19:24 +01:00
if(!--m_remainingReplies) {
emit resultsAvailable(m_what, m_id, m_results);
deleteLater();
}
2015-09-27 19:29:45 +02:00
}
} // namespace RepoIndex