156 lines
5.5 KiB
C++
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
|