repoindex/lib/alpm/repository.h

597 lines
16 KiB
C
Raw Normal View History

2015-09-04 14:37:01 +02:00
#ifndef PACKAGEMANAGEMENT_PACKAGESOURCE_H
#define PACKAGEMANAGEMENT_PACKAGESOURCE_H
#include "./package.h"
2015-09-04 14:37:01 +02:00
#include <QObject>
#include <QFuture>
#include <QJsonObject>
2015-11-03 18:19:24 +01:00
#include <QReadWriteLock>
2015-09-04 14:37:01 +02:00
#include <memory>
#include <functional>
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
namespace RepoIndex {
2015-09-04 14:37:01 +02:00
class UpgradeLookupResults;
class Reply : public QObject
{
Q_OBJECT
public:
Reply(QNetworkReply *networkReply);
Reply(const QList<QNetworkReply *> networkReplies);
2015-09-04 14:37:01 +02:00
const QString &error() const;
2020-03-09 18:45:47 +01:00
Q_SIGNALS:
2015-09-04 14:37:01 +02:00
void resultsAvailable();
2020-03-08 14:12:22 +01:00
private Q_SLOTS:
void replyFinished();
private:
virtual void processData(QNetworkReply *reply) = 0;
2015-09-04 14:37:01 +02:00
protected:
QList<QNetworkReply *> m_networkReplies;
unsigned int m_remainingReplies;
2015-09-04 14:37:01 +02:00
QString m_error;
};
inline const QString &Reply::error() const
{
return m_error;
}
class PackageReply : public Reply
{
Q_OBJECT
public:
2015-09-29 21:52:30 +02:00
PackageReply(QNetworkReply *networkReply, const QStringList &requestedPackages, Repository *repo);
PackageReply(const QList<QNetworkReply *> &networkReplies, const QStringList &requestedPackages, Repository *repo);
const QStringList &requestedPackages() const;
Repository *repository();
2015-09-29 21:52:30 +02:00
const Repository *repository() const;
2015-09-04 14:37:01 +02:00
protected:
2015-09-29 21:52:30 +02:00
QStringList m_requestedPackages;
Repository *m_repo;
2015-09-04 14:37:01 +02:00
};
2015-09-29 21:52:30 +02:00
inline PackageReply::PackageReply(QNetworkReply *networkReply, const QStringList &requestedPackages, Repository *repo) :
2015-09-04 14:37:01 +02:00
Reply(networkReply),
2015-09-29 21:52:30 +02:00
m_requestedPackages(requestedPackages),
m_repo(repo)
2015-09-04 14:37:01 +02:00
{}
2015-09-29 21:52:30 +02:00
inline PackageReply::PackageReply(const QList<QNetworkReply *> &networkReplies, const QStringList &requestedPackages, Repository *repo) :
Reply(networkReplies),
2015-09-29 21:52:30 +02:00
m_requestedPackages(requestedPackages),
m_repo(repo)
{}
2015-09-29 21:52:30 +02:00
inline const QStringList &PackageReply::requestedPackages() const
2015-09-04 14:37:01 +02:00
{
2015-09-29 21:52:30 +02:00
return m_requestedPackages;
}
inline Repository *PackageReply::repository()
{
return m_repo;
}
2015-09-29 21:52:30 +02:00
inline const Repository *PackageReply::repository() const
{
return m_repo;
2015-09-04 14:37:01 +02:00
}
class SuggestionsReply : public Reply
{
Q_OBJECT
public:
SuggestionsReply(QNetworkReply *networkReply, const QString &term, Repository *repo);
2015-11-03 18:19:24 +01:00
const Repository *repository() const;
QJsonObject suggestions() const;
2015-09-04 14:37:01 +02:00
protected:
QString m_term;
Repository *m_repo;
2015-09-04 14:37:01 +02:00
};
inline SuggestionsReply::SuggestionsReply(QNetworkReply *networkReply, const QString &term, Repository *repo) :
Reply(networkReply),
m_term(term),
m_repo(repo)
2015-09-04 14:37:01 +02:00
{}
2015-11-03 18:19:24 +01:00
inline const Repository *SuggestionsReply::repository() const
{
return m_repo;
}
2016-01-18 20:34:29 +01:00
class PackageLoader
{
public:
QFuture<void> &future();
virtual ~PackageLoader();
protected:
PackageLoader();
QMutex m_mutex;
QFuture<void> m_future;
};
inline PackageLoader::PackageLoader()
{}
inline PackageLoader::~PackageLoader()
{}
inline QFuture<void> &PackageLoader::future()
{
return m_future;
}
/*!
* \brief The RepositoryType enum specifies the type of a repository object.
*/
2015-09-04 14:37:01 +02:00
enum class RepositoryType
{
AlpmDatabase, /*! The repository is an AlpmDataBase instance. */
2015-09-04 14:37:01 +02:00
UserRepository, /*! The repository is a UserRepository instance. */
Other /*! The repository type is unknown. */
};
/*!
* \brief The PackageDetail enum is used to refer to some kind of information about a package.
*/
enum class PackageDetail
{
Basics, /*! Basic information about the package such as knowing it exists, its name, version and description. */
Dependencies, /*! The runtime dependencies of the package. */
SourceInfo, /*! The source info such as make dependencies of the package. */
PackageInfo, /*! Information related to a specific package (pkg-file). */
AllAvailable /*! All available package details. */
};
/*!
* \brief The PackageDetailAvailability enum describes when some kind of information about a package
* becomes available.
*/
enum class PackageDetailAvailability
{
Never, /*! The information is not available and can't be requested. */
Immediately, /*! The information is available immediately after the repository object has been constructed. */
Request, /*! The information is available after the requestPackageInfo() method has been called for the package. */
FullRequest /*! The information is available after the requestFullPackageInfo() method has been called for the package. */
};
2016-02-14 23:48:43 +01:00
/*!
* \brief The RepositoryUsage enum specifies the usage of a repository.
*/
enum class RepositoryUsage {
None = 0,
Sync = 1, /*! The repository is used when synchronizing. */
Search = (1 << 1), /*! The repository is used when searching. */
Install = (1 << 2), /*! The repository is used to install packages. */
Upgrade = (1 << 3), /*! The repository is used to upgrade packages. */
All = (1 << 4) - 1, /*! The reposiotry is used for everything. */
};
constexpr bool operator &(RepositoryUsage lhs, RepositoryUsage rhs)
{
return (static_cast<int>(lhs) & static_cast<int>(rhs)) != 0;
}
inline RepositoryUsage &operator |=(RepositoryUsage &lhs, RepositoryUsage rhs)
{
lhs = static_cast<RepositoryUsage>(static_cast<int>(lhs) | static_cast<int>(rhs));
return lhs;
}
2015-09-04 14:37:01 +02:00
class Repository : public QObject
{
Q_OBJECT
public:
~Repository();
virtual RepositoryType type() const = 0;
// general meta data
2016-02-25 22:53:33 +01:00
bool isBusy() const;
2019-03-14 18:15:03 +01:00
std::uint32_t index() const;
2015-09-04 14:37:01 +02:00
const QString &name() const;
const QString &description() const;
const std::map<QString, std::unique_ptr<Package> > &packages() const;
std::map<QString, std::unique_ptr<Package> > &packages();
const QStringList packageNames() const;
2016-02-14 23:48:43 +01:00
RepositoryUsage usage() const;
bool isSourceOnly() const;
bool isPackageOnly() const;
std::map<QString, QList<Package *> > &groups();
2015-09-04 14:37:01 +02:00
const std::map<QString, QList<Package *> > &groups() const;
2016-02-27 21:00:58 +01:00
Q_SLOT void updateGroups();
2015-09-04 14:37:01 +02:00
const QStringList &serverUrls() const;
2016-02-14 23:48:43 +01:00
QStringList &serverUrls();
SignatureLevel sigLevel() const;
void setSigLevel(SignatureLevel sigLevel);
2015-09-04 14:37:01 +02:00
// gathering data
2016-02-27 21:00:58 +01:00
Q_SLOT PackageLoader *init();
2016-02-25 22:53:33 +01:00
void initAsSoonAsPossible();
2016-02-27 21:00:58 +01:00
void asSoonAsPossible(std::function<void(void)> operation);
2016-02-25 22:53:33 +01:00
virtual PackageLoader *internalInit();
virtual PackageDetailAvailability requestsRequired(PackageDetail packageDetail = PackageDetail::Basics) const;
2015-09-27 19:29:45 +02:00
virtual SuggestionsReply *requestSuggestions(const QString &phrase);
virtual PackageReply *requestPackageInfo(const QStringList &packageNames, bool forceUpdate = false);
virtual PackageReply *requestFullPackageInfo(const QStringList &packageNames, bool forceUpdate = false);
2015-09-04 14:37:01 +02:00
// package search
const Package *packageByName(const QString &name) const;
Package *packageByName(const QString &name);
const Package *packageProviding(const Dependency &dependency) const;
Package *packageProviding(const Dependency &dependency);
2015-09-04 14:37:01 +02:00
QList<const Package *> packagesProviding(const Dependency &dependency) const;
QList<Package *> packageByFilter(std::function<bool (const Package *)> pred);
2016-02-25 22:53:33 +01:00
QFuture<void> computeRequiredBy(const QList<Repository *> &relevantRepositories, bool forceUpdate = false);
QJsonObject suggestions(const QString &term) const;
2015-09-04 14:37:01 +02:00
// upgrade lookup
2015-09-27 19:29:45 +02:00
const QList<Repository *> &upgradeSources() const;
QList<Repository *> &upgradeSources();
2015-09-04 14:37:01 +02:00
QJsonArray upgradeSourcesJsonArray() const;
void checkForUpgrades(UpgradeLookupResults &results) const;
2015-09-27 19:29:45 +02:00
void checkForUpgrades(UpgradeLookupResults &results, const QList<Repository *> &upgradeSources) const;
2015-09-04 14:37:01 +02:00
// build system
const QString &sourcesDirectory() const;
void setSourcesDirectory(const QString &dir);
const QString &packagesDirectory() const;
void setPackagesDirectory(const QString &dir);
// JSON serialization
QJsonArray packageNamesJsonArray() const;
QJsonObject packagesObjectSkeleton() const;
QJsonObject basicInfo(bool includeName = false) const;
2015-09-04 14:37:01 +02:00
QJsonObject groupInfo() const;
// caching
bool isCachingUseful() const;
void writeToCacheStream(QDataStream &out);
2016-01-18 20:34:29 +01:00
void restoreFromCacheStream(QDataStream &in, bool skipOutdated = true);
virtual void writeSpecificCacheHeader(QDataStream &out);
virtual std::unique_ptr<Package> emptyPackage();
virtual void restoreSpecificCacheHeader(QDataStream &in);
2019-06-10 22:51:09 +02:00
CppUtilities::TimeSpan maxPackageAge() const;
void setMaxPackageAge(CppUtilities::TimeSpan maxPackageAge);
2016-01-18 20:34:29 +01:00
void cleanOutdatedPackages();
2016-02-15 18:26:05 +01:00
bool hasOutdatedPackages();
2016-01-18 20:34:29 +01:00
void wipePackages();
// parsing src/pkg info
2016-02-14 23:48:43 +01:00
static void parsePkgInfo(const QByteArray &pkgInfo, QString &name, QList<QPair<QString, QString> > packageInfo);
static void parseDescriptions(const QList<QByteArray> &descriptions, QString &name, QList<QPair<QString, QStringList> > &fields);
2019-06-10 22:51:09 +02:00
QList<Package *> addPackagesFromSrcInfo(const QByteArray &srcInfo, CppUtilities::DateTime timeStamp);
Package *addPackageFromDescription(QString name, const QList<QByteArray> &descriptions, PackageOrigin origin, CppUtilities::DateTime timeStamp);
2015-11-03 18:19:24 +01:00
// thread synchronization
QReadWriteLock *lock() const;
2019-03-14 18:15:03 +01:00
static const std::uint32_t invalidIndex = static_cast<std::uint32_t>(-1);
2020-03-09 18:45:47 +01:00
Q_SIGNALS:
2016-02-25 22:53:33 +01:00
/*!
* \brief Emitted after initialization has finished.
*/
void initialized();
/*!
* \brief Emitted after required-by computation has finished.
*/
void requiredByComputed();
/*!
* \brief Indicates the repository is not busy anymore; emitted after either initialization or required-by computation has finished.
*/
void available();
2020-03-08 14:12:22 +01:00
protected Q_SLOTS:
2016-02-25 22:53:33 +01:00
void addBusyFlag();
void removeBusyFlag();
2020-03-08 14:12:22 +01:00
private Q_SLOTS:
2016-03-01 20:32:20 +01:00
void discardPackageLoader();
2015-09-04 14:37:01 +02:00
protected:
2019-03-14 18:15:03 +01:00
explicit Repository(const QString &name, std::uint32_t index = invalidIndex, QObject *parent = nullptr);
2015-09-04 14:37:01 +02:00
2019-03-14 18:15:03 +01:00
std::uint32_t m_index;
2015-09-04 14:37:01 +02:00
QString m_name;
QString m_description;
std::map<QString, std::unique_ptr<Package> > m_packages;
2019-06-10 22:51:09 +02:00
CppUtilities::TimeSpan m_maxPackageAge;
2016-02-14 23:48:43 +01:00
RepositoryUsage m_usage;
2015-09-04 14:37:01 +02:00
std::map<QString, QList<Package *> > m_groups;
QStringList m_serverUrls;
2016-02-14 23:48:43 +01:00
SignatureLevel m_sigLevel;
2015-09-27 19:29:45 +02:00
QList<Repository *> m_upgradeSources;
2015-09-04 14:37:01 +02:00
QString m_srcDir;
QString m_pkgDir;
2019-03-14 18:15:03 +01:00
QAtomicInteger<std::uint8_t> m_isBusy;
2016-03-01 20:32:20 +01:00
std::unique_ptr<PackageLoader> m_loader;
2015-11-03 18:19:24 +01:00
private:
QReadWriteLock m_lock;
2015-09-04 14:37:01 +02:00
};
/*!
* \brief Returns the suggestions.
*/
inline QJsonObject SuggestionsReply::suggestions() const
{
return m_repo->suggestions(m_term);
}
2016-02-25 22:53:33 +01:00
/*!
* \brief Returns an indication whether the repository is busy (either initializing or computing required-by).
*
* In this case the repository shouldn't be touched until the available() signal is emitted.
*
* \remarks This method is thread-safe.
*/
inline bool Repository::isBusy() const
{
return m_isBusy.load() != 0;
}
/*!
* \brief Returns the index of the repository.
*
2016-09-17 12:59:33 +02:00
* The index is used to sort the repositories by their occurrence the configuration files.
*/
2019-03-14 18:15:03 +01:00
inline std::uint32_t Repository::index() const
{
return m_index;
}
2015-09-04 14:37:01 +02:00
/*!
* \brief Returns the name.
*/
inline const QString &Repository::name() const
{
return m_name;
}
/*!
* \brief Returns the description.
*/
inline const QString &Repository::description() const
{
return m_description;
}
/*!
* \brief Returns whether the repository only has sources but no built packages.
*/
inline bool Repository::isSourceOnly() const
{
return requestsRequired(PackageDetail::PackageInfo) == PackageDetailAvailability::Never;
}
/*!
* \brief Returns whether the repository only has built packages but no sources.
*/
inline bool Repository::isPackageOnly() const
{
return requestsRequired(PackageDetail::SourceInfo) == PackageDetailAvailability::Never;
}
2015-09-04 14:37:01 +02:00
/*!
* \brief Returns the packages.
*/
inline const std::map<QString, std::unique_ptr<Package> > &Repository::packages() const
{
return m_packages;
}
/*!
* \brief Returns the packages.
*/
inline std::map<QString, std::unique_ptr<Package> > &Repository::packages()
{
return m_packages;
}
/*!
* \brief Returns the package with the specified \a name or nullptr if the package can not be found.
* \remarks Ownership remains by this instance.
*/
inline const Package *Repository::packageByName(const QString &name) const
{
try {
return m_packages.at(name).get();
} catch(const std::out_of_range &) {
return nullptr;
}
}
/*!
* \brief Returns the package with the specified \a name or nullptr if the package can not be found.
* \remarks Ownership remains by this instance.
*/
inline Package *Repository::packageByName(const QString &name)
{
try {
return m_packages.at(name).get();
} catch(const std::out_of_range &) {
return nullptr;
}
}
2016-02-14 23:48:43 +01:00
/*!
* \brief Returns the operations the repository is used for.
*/
inline RepositoryUsage Repository::usage() const
2015-09-04 14:37:01 +02:00
{
return m_usage;
}
2016-02-14 23:48:43 +01:00
/*!
* \brief Returns the groups the packages of the repository belong to.
*/
inline std::map<QString, QList<Package *> > &Repository::groups()
{
return m_groups;
}
2016-02-14 23:48:43 +01:00
/*!
* \brief Returns the groups the packages of the repository belong to.
*/
2015-09-04 14:37:01 +02:00
inline const std::map<QString, QList<Package *> > &Repository::groups() const
{
return m_groups;
}
/*!
* \brief Returns the server URLs.
*/
inline const QStringList &Repository::serverUrls() const
{
return m_serverUrls;
}
2016-02-14 23:48:43 +01:00
/*!
* \brief Returns the server URLs.
* \remarks This non-const version is used by the manager to add the servers.
*/
inline QStringList &Repository::serverUrls()
{
return m_serverUrls;
}
2015-09-04 14:37:01 +02:00
/*!
* \brief Returns the signature level of the database.
*/
2016-02-14 23:48:43 +01:00
inline SignatureLevel Repository::sigLevel() const
2015-09-04 14:37:01 +02:00
{
return m_sigLevel;
}
2016-02-14 23:48:43 +01:00
/*!
* \brief Sets the signature level.
*/
inline void Repository::setSigLevel(SignatureLevel sigLevel)
{
m_sigLevel = sigLevel;
}
2016-02-15 18:26:05 +01:00
/*!
* \brief Returns the upgrade sources for the repository.
*/
2015-09-27 19:29:45 +02:00
inline const QList<Repository *> &Repository::upgradeSources() const
2015-09-04 14:37:01 +02:00
{
return m_upgradeSources;
}
2016-02-15 18:26:05 +01:00
/*!
* \brief Returns the upgrade sources for the repository.
* \remarks This non-const version is used by the manager to add upgrade sources.
*/
2015-09-27 19:29:45 +02:00
inline QList<Repository *> &Repository::upgradeSources()
2015-09-04 14:37:01 +02:00
{
return m_upgradeSources;
}
inline void Repository::checkForUpgrades(UpgradeLookupResults &results) const
{
checkForUpgrades(results, upgradeSources());
}
/*!
* \brief Returns the path of the local sources directory.
*/
inline const QString &Repository::sourcesDirectory() const
{
return m_srcDir;
}
/*!
* \brief Sets the path of the local sources directory.
*/
inline void Repository::setSourcesDirectory(const QString &dir)
{
m_srcDir = dir;
}
/*!
* \brief Returns the path of the local packages directory.
*/
inline const QString &Repository::packagesDirectory() const
{
return m_pkgDir;
}
/*!
* \brief Sets the path of the local packages directory.
*/
inline void Repository::setPackagesDirectory(const QString &dir)
{
m_pkgDir = dir;
}
/*!
* \brief Returns whether caching this repository is useful.
*/
inline bool Repository::isCachingUseful() const
{
switch(requestsRequired(PackageDetail::AllAvailable)) {
case PackageDetailAvailability::Request:
case PackageDetailAvailability::FullRequest:
return true;
default:
return false;
}
}
2016-02-15 18:26:05 +01:00
/*!
* \brief Returns the max package age.
* \sa setMaxPackageAge()
*/
2019-06-10 22:51:09 +02:00
inline CppUtilities::TimeSpan Repository::maxPackageAge() const
2016-01-18 20:34:29 +01:00
{
return m_maxPackageAge;
}
2016-02-15 18:26:05 +01:00
/*!
* \brief Sets the max package age which is used by the cleanOutdatedPackages() and
* the hasOutdatedPackages() method.
*/
2019-06-10 22:51:09 +02:00
inline void Repository::setMaxPackageAge(CppUtilities::TimeSpan maxPackageAge)
2016-01-18 20:34:29 +01:00
{
m_maxPackageAge = maxPackageAge;
}
2016-02-15 18:26:05 +01:00
/*!
* \brief Wipes all packages.
*/
2016-01-18 20:34:29 +01:00
inline void Repository::wipePackages()
{
m_packages.clear();
2016-02-27 21:00:58 +01:00
m_groups.clear();
2016-01-18 20:34:29 +01:00
}
2016-02-15 18:26:05 +01:00
/*!
* \brief Returns the read-write lock used for thread-synchronization.
*/
2015-11-03 18:19:24 +01:00
inline QReadWriteLock *Repository::lock() const
{
return const_cast<QReadWriteLock *>(&m_lock);
}
2015-09-04 14:37:01 +02:00
} // namespace PackageManagement
#endif // PACKAGEMANAGEMENT_PACKAGESOURCE_H