299 lines
8.8 KiB
C++
299 lines
8.8 KiB
C++
#include "repository.h"
|
|
#include "upgradelookup.h"
|
|
#include "utilities.h"
|
|
|
|
#include <QJsonObject>
|
|
#include <QNetworkReply>
|
|
|
|
using namespace std;
|
|
|
|
namespace PackageManagement {
|
|
|
|
/*!
|
|
* \brief Constructs a new reply.
|
|
*/
|
|
Reply::Reply(QNetworkReply *networkReply) :
|
|
m_networkReply(networkReply)
|
|
{
|
|
networkReply->setParent(this);
|
|
connect(networkReply, &QNetworkReply::finished, this, &Reply::processData);
|
|
}
|
|
|
|
/*!
|
|
* \fn PackageSource::type()
|
|
* \brief Returns the type of the package source.
|
|
*/
|
|
|
|
/*!
|
|
* \brief Returns a list of all package names.
|
|
*/
|
|
const QStringList PackageManagement::Repository::packageNames() const
|
|
{
|
|
QStringList names;
|
|
names.reserve(m_packages.size());
|
|
for(const auto &entry : m_packages) {
|
|
names << entry.first;
|
|
}
|
|
return names;
|
|
}
|
|
|
|
/*!
|
|
* \brief Requests suggestions for the specified search phrase.
|
|
* \returns Returns a reply object used for the request. The reply must be destroyed by the caller
|
|
* using destroyLater() after resultsAvailable() has been emitted.
|
|
*/
|
|
SuggestionsReply *Repository::requestSuggestions(const QString &) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
/*!
|
|
* \class Repository
|
|
* \brief The Repository class represents a repository (binary repositories as well as source-only repos).
|
|
*/
|
|
|
|
/*!
|
|
* \brief Constructs a new repository (protected since this is a pure virtual class).
|
|
*/
|
|
Repository::Repository(const QString &name, QObject *parent) :
|
|
QObject(parent),
|
|
m_name(name),
|
|
m_usage(static_cast<alpm_db_usage_t>(0)),
|
|
m_sigLevel(static_cast<alpm_siglevel_t>(ALPM_SIGSTATUS_INVALID))
|
|
{}
|
|
|
|
/*!
|
|
* \brief Destroys the package source.
|
|
*/
|
|
Repository::~Repository()
|
|
{}
|
|
|
|
/*!
|
|
* \brief Returns whether the repository only has sources but no binary packages.
|
|
*/
|
|
bool Repository::isSourceOnly() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns whether requests are required.
|
|
*
|
|
* AlpmDataBase instances load all available packages in the cache
|
|
* at the beginning and hence do not require explicit requests.
|
|
*
|
|
* UserRepository instances on the other hand have an empty package
|
|
* cache at the beginning so packages must be requested explicitely
|
|
* using the requestPackageInfo() method.
|
|
*/
|
|
bool Repository::requestsRequired() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*!
|
|
* \brief Requests package information for the specified package.
|
|
* \returns Returns a reply object used for the request. The reply must be destroyed by the caller
|
|
* using destroyLater() after resultsAvailable() has been emitted.
|
|
* \remarks
|
|
* If \a forceUpdate is true, package information which has already been retrieved
|
|
* and is still cached is requested again. Otherwise these packages will not be
|
|
* requested again. If it turns out, that all packages are already cached, nullptr
|
|
* is returned in this case.
|
|
*/
|
|
PackageReply *Repository::requestPackageInfo(const QStringList &, bool ) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
/*!
|
|
* \brief Requests full package information for the specified package.
|
|
* \returns Returns a reply object used for the request. The reply must be destroyed by the caller
|
|
* using destroyLater() after resultsAvailable() has been emitted.
|
|
* \remarks
|
|
* If \a forceUpdate is true, package information which has already been retrieved
|
|
* and is still cached is requested again. Otherwise these packages will not be
|
|
* requested again. If it turns out, that all packages are already cached, nullptr
|
|
* is returned in this case.
|
|
*/
|
|
PackageReply *Repository::requestFullPackageInfo(const QString &, bool ) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns the first package providing the specified \a dependency.
|
|
* \remarks Returns nullptr if no packages provides the \a dependency.
|
|
*/
|
|
const Package *Repository::packageProviding(const Dependency &dependency) const
|
|
{
|
|
for(const auto &entry : m_packages) {
|
|
if(entry.second->matches(dependency)) {
|
|
// check whether package matches "directly"
|
|
return entry.second.get();
|
|
} else {
|
|
// check whether at least one of the provides matches
|
|
for(const auto &provide : entry.second->provides()) {
|
|
if(Package::matches(provide.name, provide.version, dependency)) {
|
|
return entry.second.get();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns all packages providing the specified \a dependency.
|
|
*/
|
|
QList<const Package *> Repository::packagesProviding(const Dependency &dependency) const
|
|
{
|
|
QList<const Package *> res;
|
|
for(const auto &entry : m_packages) {
|
|
if(entry.second->matches(dependency)) {
|
|
// check whether package matches "directly"
|
|
res << entry.second.get();
|
|
} else {
|
|
// check whether at least one of the provides matches
|
|
for(const auto &provide : entry.second->provides()) {
|
|
if(Package::matches(provide.name, provide.version, dependency)) {
|
|
res << entry.second.get();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns all packages matching the specified predicate.
|
|
*/
|
|
QList<Package *> Repository::packageByFilter(std::function<bool (const Package *)> pred)
|
|
{
|
|
QList<Package *> packages;
|
|
for(const auto &entry : m_packages) {
|
|
if(pred(entry.second.get())) {
|
|
packages << entry.second.get();
|
|
}
|
|
}
|
|
return packages;
|
|
}
|
|
|
|
QJsonArray Repository::upgradeSourcesJsonArray() const
|
|
{
|
|
QJsonArray sources;
|
|
for(const auto *source : upgradeSources()) {
|
|
sources << source->name();
|
|
}
|
|
return sources;
|
|
}
|
|
|
|
void Repository::checkForUpgrades(UpgradeLookupResults &results, const QList<const Repository *> &upgradeSources) const
|
|
{
|
|
if(upgradeSources.isEmpty()) {
|
|
results.noSources = true;
|
|
} else {
|
|
for(const auto &pkgEntry : packages()) {
|
|
bool orphaned = true;
|
|
for(const auto *src : upgradeSources) {
|
|
if(const auto *syncPkg = src->packageByName(pkgEntry.first)) {
|
|
switch(pkgEntry.second->compareVersion(syncPkg)) {
|
|
case PackageVersionComparsion::Equal:
|
|
break; // ignore equal packages
|
|
case PackageVersionComparsion::SoftwareUpgrade:
|
|
results.newVersions << UpgradeResult(syncPkg, pkgEntry.second->version());
|
|
break;
|
|
case PackageVersionComparsion::PackageUpgradeOnly:
|
|
results.newReleases << UpgradeResult(syncPkg, pkgEntry.second->version());
|
|
break;
|
|
case PackageVersionComparsion::NewerThenSyncVersion:
|
|
results.downgrades << UpgradeResult(syncPkg, pkgEntry.second->version());
|
|
}
|
|
orphaned = false;
|
|
}
|
|
}
|
|
if(orphaned) {
|
|
results.orphaned << pkgEntry.second.get();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns all package names as JSON array.
|
|
*/
|
|
QJsonArray Repository::packageNamesJsonArray() const
|
|
{
|
|
QJsonArray names;
|
|
for(const auto &entry : m_packages) {
|
|
names << entry.first;
|
|
}
|
|
return names;
|
|
}
|
|
|
|
/*!
|
|
* \cond
|
|
*/
|
|
|
|
inline void put(QJsonObject &obj, const QString &key, const QJsonValue &value)
|
|
{
|
|
if(!value.isNull()) {
|
|
obj.insert(key, value);
|
|
}
|
|
}
|
|
|
|
inline void put(QJsonObject &obj, const QString &key, const QStringList &values)
|
|
{
|
|
if(!values.isEmpty()) {
|
|
put(obj, key, QJsonArray::fromStringList(values));
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \endcond
|
|
*/
|
|
|
|
/*!
|
|
* \brief Returns basic information about the repository.
|
|
*/
|
|
QJsonObject Repository::basicInfo() const
|
|
{
|
|
QJsonObject info;
|
|
put(info, QStringLiteral("name"), name());
|
|
put(info, QStringLiteral("desc"), description());
|
|
put(info, QStringLiteral("servers"), serverUrls());
|
|
put(info, QStringLiteral("usage"), Utilities::usageStrings(usage()));
|
|
put(info, QStringLiteral("sigLevel"), Utilities::sigLevelStrings(sigLevel()));
|
|
put(info, QStringLiteral("upgradeSources"), upgradeSourcesJsonArray());
|
|
put(info, QStringLiteral("packages"), packageNamesJsonArray());
|
|
put(info, QStringLiteral("requestRequired"), requestsRequired());
|
|
put(info, QStringLiteral("srcOnly"), isSourceOnly());
|
|
return info;
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns group information as JSON object.
|
|
*/
|
|
QJsonObject Repository::groupInfo() const
|
|
{
|
|
QJsonObject info;
|
|
put(info, QStringLiteral("repo"), name());
|
|
QJsonArray groupsArray;
|
|
for(const auto &groupEntry : groups()) {
|
|
QJsonObject info;
|
|
put(info, QStringLiteral("name"), groupEntry.first);
|
|
QJsonArray pkgNames;
|
|
for(const auto *pkg : groupEntry.second) {
|
|
pkgNames << pkg->name();
|
|
}
|
|
put(info, QStringLiteral("pkgs"), pkgNames);
|
|
groupsArray << info;
|
|
}
|
|
info.insert(QStringLiteral("groups"), groupsArray);
|
|
return info;
|
|
}
|
|
|
|
} // namespace PackageManagement
|
|
|