repoindex/alpm/upgradelookup.cpp

156 lines
5.5 KiB
C++

#include "upgradelookup.h"
#include "manager.h"
#include "alpmdatabase.h"
#include "config.h"
#include <QtConcurrent/QtConcurrent>
#include <assert.h>
using namespace std;
namespace PackageManagement {
QJsonObject UpgradeResult::json() const
{
QJsonObject obj;
obj.insert(QStringLiteral("pkg"), package->basicInfo(true));
obj.insert(QStringLiteral("prevVersion"), previousVersion);
return obj;
}
UpgradeLookupProcess::UpgradeLookupProcess(UpgradeLookup *upgradeLookup, const Repository *upgradeSource) :
QObject(upgradeLookup),
m_toCheck(upgradeLookup->toCheck()),
m_upgradeSource(upgradeSource),
m_reply(nullptr),
m_watcher(new QFutureWatcher<void>(this))
{
connect(this, &UpgradeLookupProcess::finished, upgradeLookup, &UpgradeLookup::processFinished);
if(m_upgradeSource->requestsRequired()) {
if((m_reply = m_upgradeSource->requestPackageInfo(m_toCheck->packageNames()))) {
m_reply->setParent(this);
connect(m_reply, &PackageReply::resultsAvailable, this, &UpgradeLookupProcess::sourceReady);
return;
}
}
sourceReady();
}
const UpgradeLookupResults &UpgradeLookupProcess::results() const
{
return m_results;
}
void UpgradeLookupProcess::sourceReady()
{
// if a request was required, check whether there occured an error
if(m_reply && !m_reply->error().isEmpty()) {
m_results.errors << m_reply->error();
emit finished();
} else {
connect(m_watcher, &QFutureWatcher<void>::finished, this, &UpgradeLookupProcess::finished);
m_watcher->setFuture(QtConcurrent::run(this, &UpgradeLookupProcess::checkUpgrades));
}
}
void UpgradeLookupProcess::checkUpgrades()
{
m_toCheck->checkForUpgrades(m_results, QList<const Repository *>() << m_upgradeSource);
}
UpgradeLookup::UpgradeLookup(const Manager &manager, const QJsonObject &request, QObject *parent) :
QObject(parent),
m_request(request),
m_toCheck(nullptr),
m_remainingProcesses(0),
m_firstFinished(false)
{
const auto toCheckName = request.value(QStringLiteral("db")).toString();
if((m_toCheck = manager.repositoryByName(toCheckName))) {
// construct upgrade lookup processes
const auto syncDbsArray = request.value(QStringLiteral("syncdbs")).toArray();
if(syncDbsArray.isEmpty()) {
for(const auto *src : m_toCheck->upgradeSources()) {
new UpgradeLookupProcess(this, src);
++m_remainingProcesses;
}
} else {
for(const auto &syncDbValue : syncDbsArray) {
const auto syncDbName = syncDbValue.toString();
if(const auto *src = manager.repositoryByName(syncDbName)) {
new UpgradeLookupProcess(this, src);
++m_remainingProcesses;
} else {
m_warningsArray << QStringLiteral("The specified upgrade source \"%1\" can not be found.").arg(syncDbName);
}
}
}
// check whether any processes could be constructed
if(!m_remainingProcesses) {
m_errorsArray << QStringLiteral("No upgrade sources associated for repository \"%1\".").arg(m_toCheck->name());
} else {
return; // no errors so far
}
} else {
m_errorsArray << QStringLiteral("Repository \"%1\" can not be found.").arg(toCheckName);
}
// there are errors
QJsonObject results;
results.insert(QStringLiteral("errors"), m_errorsArray);
emit resultsAvailable(request.value(QStringLiteral("what")), request.value(QStringLiteral("id")), results);
deleteLater();
}
void UpgradeLookup::processFinished()
{
assert(m_remainingProcesses);
// add results
const auto &results = static_cast<UpgradeLookupProcess *>(sender())->results();
for(const auto pkg : results.newVersions) {
m_softwareUpdatesArray << pkg.json();
}
for(const auto pkg : results.newReleases) {
m_packageOnlyUpdatesArray << pkg.json();
}
for(const auto pkg : results.downgrades) {
m_downgradesArray << pkg.json();
}
for(const auto &warning : results.warnings) {
m_warningsArray << warning;
}
for(const auto &error : results.errors) {
m_errorsArray << error;
}
if(m_firstFinished) {
m_orphanedPackages = m_orphanedPackages.intersect(results.orphaned);
} else {
m_firstFinished = true;
m_orphanedPackages = results.orphaned;
}
// check whether all processes are finished
if(--m_remainingProcesses == 0) {
// finally make info for orphanded packages
for(const auto *pkg : m_orphanedPackages) {
m_orphanedPackagesArray << pkg->basicInfo(true);
}
// add results to results QJsonObject
QJsonObject results;
results.insert(QStringLiteral("softwareUpdates"), m_softwareUpdatesArray);
results.insert(QStringLiteral("packageOnlyUpdates"), m_packageOnlyUpdatesArray);
results.insert(QStringLiteral("downgrades"), m_downgradesArray);
results.insert(QStringLiteral("orphanedPackages"), m_orphanedPackagesArray);
if(!m_warningsArray.isEmpty()) {
results.insert(QStringLiteral("warnings"), m_warningsArray);
}
if(!m_errorsArray.isEmpty()) {
results.insert(QStringLiteral("errors"), m_errorsArray);
}
emit resultsAvailable(m_request.value(QStringLiteral("what")), m_request.value(QStringLiteral("id")), results);
// lookup done, delete this helper object
deleteLater();
}
}
} // namespace PackageManagement