#ifndef PACKAGEMANAGEMENT_PACKAGESOURCE_H #define PACKAGEMANAGEMENT_PACKAGESOURCE_H #include "./package.h" #include "./group.h" #include #include #include #include #include #include QT_FORWARD_DECLARE_CLASS(QNetworkReply) namespace RepoIndex { class UpgradeLookupResults; class Reply : public QObject { Q_OBJECT public: Reply(QNetworkReply *networkReply); Reply(const QList networkReplies); const QString &error() const; signals: void resultsAvailable(); private slots: void replyFinished(); private: virtual void processData(QNetworkReply *reply) = 0; protected: QList m_networkReplies; unsigned int m_remainingReplies; QString m_error; }; inline const QString &Reply::error() const { return m_error; } class PackageReply : public Reply { Q_OBJECT public: PackageReply(QNetworkReply *networkReply, const QStringList &requestedPackages, Repository *repo); PackageReply(const QList &networkReplies, const QStringList &requestedPackages, Repository *repo); const QStringList &requestedPackages() const; Repository *repository(); const Repository *repository() const; protected: QStringList m_requestedPackages; Repository *m_repo; }; inline PackageReply::PackageReply(QNetworkReply *networkReply, const QStringList &requestedPackages, Repository *repo) : Reply(networkReply), m_requestedPackages(requestedPackages), m_repo(repo) {} inline PackageReply::PackageReply(const QList &networkReplies, const QStringList &requestedPackages, Repository *repo) : Reply(networkReplies), m_requestedPackages(requestedPackages), m_repo(repo) {} inline const QStringList &PackageReply::requestedPackages() const { return m_requestedPackages; } inline Repository *PackageReply::repository() { return m_repo; } inline const Repository *PackageReply::repository() const { return m_repo; } class SuggestionsReply : public Reply { Q_OBJECT public: SuggestionsReply(QNetworkReply *networkReply, const QString &term, Repository *repo); const Repository *repository() const; QJsonObject suggestions() const; protected: QString m_term; Repository *m_repo; }; inline SuggestionsReply::SuggestionsReply(QNetworkReply *networkReply, const QString &term, Repository *repo) : Reply(networkReply), m_term(term), m_repo(repo) {} inline const Repository *SuggestionsReply::repository() const { return m_repo; } class PackageLoader { public: QFuture &future(); virtual ~PackageLoader(); protected: PackageLoader(); QMutex m_mutex; QFuture m_future; }; inline PackageLoader::PackageLoader() {} inline PackageLoader::~PackageLoader() {} inline QFuture &PackageLoader::future() { return m_future; } /*! * \brief The RepositoryType enum specifies the type of a repository object. */ enum class RepositoryType { AlpmDatabase, /*! The repository is an AlpmDataBase instance. */ 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. */ }; class Repository : public QObject { Q_OBJECT public: ~Repository(); virtual RepositoryType type() const = 0; // general meta data uint32 index() const; const QString &name() const; const QString &description() const; const std::map > &packages() const; std::map > &packages(); const QStringList packageNames() const; alpm_db_usage_t usage() const; bool isSourceOnly() const; bool isPackageOnly() const; std::map > &groups(); const std::map > &groups() const; const QStringList &serverUrls() const; alpm_siglevel_t sigLevel() const; // gathering data virtual PackageLoader *init(); virtual PackageDetailAvailability requestsRequired(PackageDetail packageDetail = PackageDetail::Basics) const; virtual SuggestionsReply *requestSuggestions(const QString &phrase); virtual PackageReply *requestPackageInfo(const QStringList &packageNames, bool forceUpdate = false); virtual PackageReply *requestFullPackageInfo(const QStringList &packageNames, bool forceUpdate = false); // 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); QList packagesProviding(const Dependency &dependency) const; QList packageByFilter(std::function pred); QFuture computeRequiredBy(Manager &manager, bool forceUpdate = false); QJsonObject suggestions(const QString &term) const; // upgrade lookup const QList &upgradeSources() const; QList &upgradeSources(); QJsonArray upgradeSourcesJsonArray() const; void checkForUpgrades(UpgradeLookupResults &results) const; void checkForUpgrades(UpgradeLookupResults &results, const QList &upgradeSources) const; // 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; QJsonObject groupInfo() const; // caching bool isCachingUseful() const; void writeToCacheStream(QDataStream &out); void restoreFromCacheStream(QDataStream &in, bool skipOutdated = true); virtual void writeSpecificCacheHeader(QDataStream &out); virtual std::unique_ptr emptyPackage(); virtual void restoreSpecificCacheHeader(QDataStream &in); ChronoUtilities::TimeSpan maxPackageAge() const; void setMaxPackageAge(ChronoUtilities::TimeSpan maxPackageAge); void cleanOutdatedPackages(); void wipePackages(); // parsing src/pkg info QList addPackagesFromSrcInfo(const QByteArray &srcInfo); Package *addPackageFromDescription(QString name, const QList &descriptions); // thread synchronization QReadWriteLock *lock() const; static const uint32 invalidIndex = static_cast(-1); protected: explicit Repository(const QString &name, uint32 index = invalidIndex, QObject *parent = nullptr); protected: uint32 m_index; QString m_name; QString m_description; std::map > m_packages; ChronoUtilities::TimeSpan m_maxPackageAge; alpm_db_usage_t m_usage; std::map > m_groups; QStringList m_serverUrls; alpm_siglevel_t m_sigLevel; QList m_upgradeSources; QString m_srcDir; QString m_pkgDir; private: QReadWriteLock m_lock; }; /*! * \brief Returns the suggestions. */ inline QJsonObject SuggestionsReply::suggestions() const { return m_repo->suggestions(m_term); } /*! * \brief Returns the index of the repository. * * The index is used to sort the repositories by their occurance the configuration files. */ inline uint32 Repository::index() const { return m_index; } /*! * \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; } /*! * \brief Returns the packages. */ inline const std::map > &Repository::packages() const { return m_packages; } /*! * \brief Returns the packages. */ inline std::map > &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; } } inline alpm_db_usage_t Repository::usage() const { return m_usage; } inline std::map > &Repository::groups() { return m_groups; } inline const std::map > &Repository::groups() const { return m_groups; } /*! * \brief Returns the server URLs. */ inline const QStringList &Repository::serverUrls() const { return m_serverUrls; } /*! * \brief Returns the signature level of the database. */ inline alpm_siglevel_t Repository::sigLevel() const { return m_sigLevel; } inline const QList &Repository::upgradeSources() const { return m_upgradeSources; } inline QList &Repository::upgradeSources() { 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; } } inline ChronoUtilities::TimeSpan Repository::maxPackageAge() const { return m_maxPackageAge; } inline void Repository::setMaxPackageAge(ChronoUtilities::TimeSpan maxPackageAge) { m_maxPackageAge = maxPackageAge; } inline void Repository::wipePackages() { m_packages.clear(); } inline QReadWriteLock *Repository::lock() const { return const_cast(&m_lock); } } // namespace PackageManagement #endif // PACKAGEMANAGEMENT_PACKAGESOURCE_H