#ifndef LIBPKG_DATA_DATABASE_H #define LIBPKG_DATA_DATABASE_H #include "./package.h" #include "./siglevel.h" #include "../global.h" #include #include #include #include #include namespace LibPkg { struct Config; struct Database; struct LIBPKG_EXPORT DatabaseInfo { std::string name; std::string arch; }; struct LIBPKG_EXPORT PackageSearchResult { PackageSearchResult(); PackageSearchResult(Database &database, const std::shared_ptr &package); bool operator==(const PackageSearchResult &other) const; /// \brief The related database. /// \remarks /// - The find functions always use Database* and it is guaranteed to be never nullptr. /// - The deserialization functions always use DatabaseInfo and the values might be empty if the source was empty. /// - The serialization functions can cope with both alternatives. std::variant db; std::shared_ptr pkg; }; /*! * \brief The DatabaseUsage enum specifies the usage of a database within pacman. */ enum class DatabaseUsage { None = 0, Sync = (1 << 0), /*! The database is used when synchronizing. */ Search = (1 << 1), /*! The database is used when searching. */ Install = (1 << 2), /*! The database is used to install packages. */ Upgrade = (1 << 3), /*! The database is used to upgrade packages. */ All = (1 << 4) - 1, /*! The database is used for everything. */ }; enum class UpdateCheckOptions { None = 0, ConsiderRegularPackage = (1 << 0), }; } // namespace LibPkg CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibPkg, LibPkg::DatabaseUsage) CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibPkg, LibPkg::UpdateCheckOptions) namespace LibPkg { struct LIBPKG_EXPORT PackageUpdate : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { PackageUpdate(PackageSearchResult &&oldVersion = PackageSearchResult(), PackageSearchResult &&newVersion = PackageSearchResult()) : oldVersion(oldVersion) , newVersion(newVersion) { } PackageSearchResult oldVersion; PackageSearchResult newVersion; }; struct LIBPKG_EXPORT PackageUpdates : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::vector versionUpdates; std::vector packageUpdates; std::vector downgrades; std::vector orphans; }; struct LIBPKG_EXPORT PackageLocation { std::filesystem::path pathWithinRepo; std::filesystem::path storageLocation; std::optional error; bool exists = false; }; struct LIBPKG_EXPORT UnresolvedDependencies : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { std::vector deps; std::vector libs; }; struct LIBPKG_EXPORT Database : public ReflectiveRapidJSON::JsonSerializable, public ReflectiveRapidJSON::BinarySerializable { using PackageMap = std::unordered_map>; Database(const std::string &name = std::string(), const std::string &path = std::string()); Database(std::string &&name, std::string &&path); void deducePathsFromLocalDirs(); void resetConfiguration(); void clearPackages(); void loadPackages(bool withFiles = false); void loadPackages(const std::string &databaseData, CppUtilities::DateTime lastModified); void loadPackages(FileMap &&databaseFiles, CppUtilities::DateTime lastModified); static bool isFileRelevant(const char *filePath, const char *fileName, mode_t); std::vector> findPackages(const std::function &pred); void removePackageDependencies(typename PackageMap::const_iterator packageIterator); void addPackageDependencies(const std::shared_ptr &package); void removePackage(const std::string &packageName); void removePackage(typename PackageMap::const_iterator packageIterator); void updatePackage(const std::shared_ptr &package); void forceUpdatePackage(const std::shared_ptr &package); void replacePackages(const std::vector> &newPackages, CppUtilities::DateTime lastModified); std::unordered_map, UnresolvedDependencies> detectUnresolvedPackages(Config &config, const std::vector> &newPackages, const DependencySet &removedPackages, const std::unordered_set &depsToIgnore = std::unordered_set(), const std::unordered_set &libsToIgnore = std::unordered_set()); PackageUpdates checkForUpdates(const std::vector &updateSources, UpdateCheckOptions options = UpdateCheckOptions::None); PackageLocation locatePackage(const std::string &packageName) const; std::string filesPathFromRegularPath() const; std::string name; std::string path; std::string filesPath; std::vector mirrors; PackageMap packages; DatabaseUsage usage = DatabaseUsage::None; SignatureLevel signatureLevel = SignatureLevel::Default; std::string arch = "x86_64"; std::vector dependencies; DependencySet providedDeps; DependencySet requiredDeps; std::unordered_map>> providedLibs; std::unordered_map>> requiredLibs; std::string localPkgDir; std::string localDbDir; CppUtilities::DateTime lastUpdate; bool syncFromMirror = false; bool toBeDiscarded = false; // FIXME: The member variables packages, providedDeps, requiredDeps, providedLibs and requiredLibs should // not be updated directly/individually; better make them private and provide a getter to a const ref. }; inline Database::Database(const std::string &name, const std::string &path) : name(name) , path(path) { } inline Database::Database(std::string &&name, std::string &&path) : name(std::move(name)) , path(std::move(path)) { } inline PackageSearchResult::PackageSearchResult() : db(nullptr) { } inline PackageSearchResult::PackageSearchResult(Database &database, const std::shared_ptr &package) : db(&database) , pkg(package) { } inline bool PackageSearchResult::operator==(const PackageSearchResult &other) const { const auto *const *const db1 = std::get_if(&db); const auto *const *const db2 = std::get_if(&other.db); if (!db1 || !db2) { return false; } return ((!*db1 && !*db2) || (*db1 && *db2 && (**db1).name == (**db2).name)) && pkg == other.pkg; } } // namespace LibPkg namespace std { template <> struct hash { std::size_t operator()(const LibPkg::PackageSearchResult &res) const { using std::hash; const std::string *dbName = nullptr; if (const auto *const dbInfo = std::get_if(&res.db)) { dbName = &dbInfo->name; } else if (const auto *const db = std::get(res.db)) { dbName = &db->name; } return ((hash()(dbName ? *dbName : string()) ^ (hash>()(res.pkg) << 1)) >> 1); } }; } // namespace std namespace ReflectiveRapidJSON { namespace JsonReflector { // declare custom (de)serialization for PackageSearchResult template <> LIBPKG_EXPORT void push( const LibPkg::PackageSearchResult &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator); template <> LIBPKG_EXPORT void pull(LibPkg::PackageSearchResult &reflectable, const RAPIDJSON_NAMESPACE::GenericValue> &value, JsonDeserializationErrors *errors); } // namespace JsonReflector namespace BinaryReflector { template <> LIBPKG_EXPORT void writeCustomType( BinarySerializer &serializer, const LibPkg::PackageSearchResult &packageSearchResult, BinaryVersion version); template <> LIBPKG_EXPORT BinaryVersion readCustomType( BinaryDeserializer &deserializer, LibPkg::PackageSearchResult &packageSearchResult, BinaryVersion version); } // namespace BinaryReflector } // namespace ReflectiveRapidJSON #endif // LIBPKG_DATA_DATABASE_H