2015-09-07 19:36:45 +02:00
|
|
|
#include "./repository.h"
|
|
|
|
#include "./upgradelookup.h"
|
|
|
|
#include "./utilities.h"
|
2015-09-04 14:37:01 +02:00
|
|
|
|
|
|
|
#include <QJsonObject>
|
|
|
|
#include <QNetworkReply>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2015-09-05 17:25:05 +02:00
|
|
|
namespace RepoIndex {
|
2015-09-04 14:37:01 +02:00
|
|
|
|
|
|
|
/*!
|
2015-09-05 17:25:05 +02:00
|
|
|
* \brief Constructs a new reply for a single network reply.
|
2015-09-04 14:37:01 +02:00
|
|
|
*/
|
2015-09-05 17:25:05 +02:00
|
|
|
Reply::Reply(QNetworkReply *networkReply)
|
2015-09-04 14:37:01 +02:00
|
|
|
{
|
|
|
|
networkReply->setParent(this);
|
|
|
|
connect(networkReply, &QNetworkReply::finished, this, &Reply::processData);
|
2015-09-05 17:25:05 +02:00
|
|
|
m_networkReplies.reserve(1);
|
|
|
|
m_networkReplies << networkReply;
|
2015-09-04 14:37:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2015-09-05 17:25:05 +02:00
|
|
|
* \brief Constructs a new reply for multiple network replies.
|
|
|
|
*/
|
|
|
|
Reply::Reply(const QList<QNetworkReply *> networkReplies) :
|
|
|
|
m_networkReplies(networkReplies)
|
|
|
|
{
|
|
|
|
for(auto *networkReply : networkReplies) {
|
|
|
|
networkReply->setParent(this);
|
|
|
|
connect(networkReply, &QNetworkReply::finished, this, &Reply::processData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \fn Repository::type()
|
2015-09-04 14:37:01 +02:00
|
|
|
* \brief Returns the type of the package source.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Returns a list of all package names.
|
|
|
|
*/
|
2015-09-05 17:25:05 +02:00
|
|
|
const QStringList RepoIndex::Repository::packageNames() const
|
2015-09-04 14:37:01 +02:00
|
|
|
{
|
|
|
|
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))
|
|
|
|
{}
|
|
|
|
|
|
|
|
/*!
|
2015-09-05 17:25:05 +02:00
|
|
|
* \brief Destroys the repository.
|
2015-09-04 14:37:01 +02:00
|
|
|
*/
|
|
|
|
Repository::~Repository()
|
|
|
|
{}
|
|
|
|
|
|
|
|
/*!
|
2015-09-05 17:25:05 +02:00
|
|
|
* \brief Returns whether explicit requests are required to get the specified information
|
|
|
|
* about the package of this repository.
|
2015-09-04 14:37:01 +02:00
|
|
|
*
|
|
|
|
* AlpmDataBase instances load all available packages in the cache
|
2015-09-05 17:25:05 +02:00
|
|
|
* at the beginning and hence do not require explicit requests for package names, version,
|
|
|
|
* description, dependencies and most other information. However make dependencies are not available at all.
|
2015-09-04 14:37:01 +02:00
|
|
|
*
|
|
|
|
* UserRepository instances on the other hand have an empty package
|
|
|
|
* cache at the beginning so packages must be requested explicitely
|
|
|
|
* using the requestPackageInfo() method.
|
|
|
|
*/
|
2015-09-05 17:25:05 +02:00
|
|
|
PackageDetailAvailability Repository::requestsRequired(PackageDetail ) const
|
2015-09-04 14:37:01 +02:00
|
|
|
{
|
2015-09-05 17:25:05 +02:00
|
|
|
return PackageDetailAvailability::Never;
|
2015-09-04 14:37:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \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.
|
|
|
|
*/
|
2015-09-05 17:25:05 +02:00
|
|
|
PackageReply *Repository::requestFullPackageInfo(const QStringList &, bool ) const
|
2015-09-04 14:37:01 +02:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-09-05 17:25:05 +02:00
|
|
|
/*!
|
|
|
|
* \brief Returns the first package providing the specified \a dependency.
|
|
|
|
* \remarks Returns nullptr if no packages provides the \a dependency.
|
|
|
|
*/
|
|
|
|
Package *Repository::packageProviding(const Dependency &dependency)
|
|
|
|
{
|
|
|
|
for(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(auto &provide : entry.second->provides()) {
|
|
|
|
if(Package::matches(provide.name, provide.version, dependency)) {
|
|
|
|
return entry.second.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-09-04 14:37:01 +02:00
|
|
|
/*!
|
|
|
|
* \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());
|
2015-09-05 17:25:05 +02:00
|
|
|
put(info, QStringLiteral("requestRequired"), requestsRequired(PackageDetail::Basics) != PackageDetailAvailability::Immediately);
|
2015-09-04 14:37:01 +02:00
|
|
|
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
|
|
|
|
|