arch-repo-manager/libpkg/data/database.h

228 lines
8.7 KiB
C
Raw Normal View History

2021-01-25 00:24:31 +01:00
#ifndef LIBPKG_DATA_DATABASE_H
#define LIBPKG_DATA_DATABASE_H
#include "./package.h"
#include "./siglevel.h"
#include "../global.h"
#include <c++utilities/chrono/datetime.h>
#include <c++utilities/misc/flagenumclass.h>
#include <filesystem>
#include <optional>
#include <unordered_set>
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> &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<Database *, DatabaseInfo> db;
std::shared_ptr<Package> 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. */
2021-01-25 00:24:31 +01:00
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),
};
2021-01-25 00:24:31 +01:00
} // namespace LibPkg
CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibPkg, LibPkg::DatabaseUsage)
CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(LibPkg, LibPkg::UpdateCheckOptions)
2021-01-25 00:24:31 +01:00
namespace LibPkg {
struct LIBPKG_EXPORT PackageUpdate : public ReflectiveRapidJSON::JsonSerializable<PackageUpdate>,
public ReflectiveRapidJSON::BinarySerializable<PackageUpdate> {
PackageUpdate(PackageSearchResult &&oldVersion = PackageSearchResult(), PackageSearchResult &&newVersion = PackageSearchResult())
: oldVersion(oldVersion)
, newVersion(newVersion)
{
}
PackageSearchResult oldVersion;
PackageSearchResult newVersion;
};
struct LIBPKG_EXPORT PackageUpdates : public ReflectiveRapidJSON::JsonSerializable<PackageUpdates>,
public ReflectiveRapidJSON::BinarySerializable<PackageUpdates> {
std::vector<PackageUpdate> versionUpdates;
std::vector<PackageUpdate> packageUpdates;
std::vector<PackageUpdate> downgrades;
std::vector<PackageSearchResult> orphans;
};
struct LIBPKG_EXPORT PackageLocation {
std::filesystem::path pathWithinRepo;
std::filesystem::path storageLocation;
std::optional<std::filesystem::filesystem_error> error;
bool exists = false;
};
struct LIBPKG_EXPORT UnresolvedDependencies : public ReflectiveRapidJSON::JsonSerializable<UnresolvedDependencies>,
public ReflectiveRapidJSON::BinarySerializable<UnresolvedDependencies> {
std::vector<Dependency> deps;
std::vector<std::string> libs;
};
struct LIBPKG_EXPORT Database : public ReflectiveRapidJSON::JsonSerializable<Database>, public ReflectiveRapidJSON::BinarySerializable<Database> {
using PackageMap = std::unordered_map<std::string, std::shared_ptr<Package>>;
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<std::shared_ptr<Package>> findPackages(const std::function<bool(const Database &, const Package &)> &pred);
void removePackageDependencies(typename PackageMap::const_iterator packageIterator);
void addPackageDependencies(const std::shared_ptr<Package> &package);
void removePackage(const std::string &packageName);
void removePackage(typename PackageMap::const_iterator packageIterator);
void updatePackage(const std::shared_ptr<Package> &package);
void forceUpdatePackage(const std::shared_ptr<Package> &package);
void replacePackages(const std::vector<std::shared_ptr<Package>> &newPackages, CppUtilities::DateTime lastModified);
std::unordered_map<std::shared_ptr<Package>, UnresolvedDependencies> detectUnresolvedPackages(Config &config,
const std::vector<std::shared_ptr<Package>> &newPackages, const DependencySet &removedPackages,
const std::unordered_set<std::string_view> &depsToIgnore = std::unordered_set<std::string_view>(),
const std::unordered_set<std::string_view> &libsToIgnore = std::unordered_set<std::string_view>());
PackageUpdates checkForUpdates(const std::vector<Database *> &updateSources, UpdateCheckOptions options = UpdateCheckOptions::None);
2021-01-25 00:24:31 +01:00
PackageLocation locatePackage(const std::string &packageName) const;
std::string filesPathFromRegularPath() const;
std::string name;
std::string path;
std::string filesPath;
std::vector<std::string> mirrors;
PackageMap packages;
DatabaseUsage usage = DatabaseUsage::None;
SignatureLevel signatureLevel = SignatureLevel::Default;
std::string arch = "x86_64";
std::vector<std::string> dependencies;
DependencySet providedDeps;
DependencySet requiredDeps;
std::unordered_map<std::string, std::vector<std::shared_ptr<Package>>> providedLibs;
std::unordered_map<std::string, std::vector<std::shared_ptr<Package>>> 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> &package)
: db(&database)
, pkg(package)
{
}
inline bool PackageSearchResult::operator==(const PackageSearchResult &other) const
{
const auto *const *const db1 = std::get_if<Database *>(&db);
const auto *const *const db2 = std::get_if<Database *>(&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<LibPkg::PackageSearchResult> {
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<LibPkg::DatabaseInfo>(&res.db)) {
dbName = &dbInfo->name;
} else if (const auto *const db = std::get<LibPkg::Database *>(res.db)) {
dbName = &db->name;
}
return ((hash<string>()(dbName ? *dbName : string()) ^ (hash<std::shared_ptr<LibPkg::Package>>()(res.pkg) << 1)) >> 1);
}
};
} // namespace std
namespace ReflectiveRapidJSON {
namespace JsonReflector {
// declare custom (de)serialization for PackageSearchResult
template <>
LIBPKG_EXPORT void push<LibPkg::PackageSearchResult>(
const LibPkg::PackageSearchResult &reflectable, RAPIDJSON_NAMESPACE::Value &value, RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator);
template <>
LIBPKG_EXPORT void pull<LibPkg::PackageSearchResult>(LibPkg::PackageSearchResult &reflectable,
const RAPIDJSON_NAMESPACE::GenericValue<RAPIDJSON_NAMESPACE::UTF8<char>> &value, JsonDeserializationErrors *errors);
} // namespace JsonReflector
namespace BinaryReflector {
template <>
LIBPKG_EXPORT void writeCustomType<LibPkg::PackageSearchResult>(
BinarySerializer &serializer, const LibPkg::PackageSearchResult &packageSearchResult, BinaryVersion version);
2021-01-25 00:24:31 +01:00
template <>
LIBPKG_EXPORT BinaryVersion readCustomType<LibPkg::PackageSearchResult>(
BinaryDeserializer &deserializer, LibPkg::PackageSearchResult &packageSearchResult, BinaryVersion version);
2021-01-25 00:24:31 +01:00
} // namespace BinaryReflector
} // namespace ReflectiveRapidJSON
#endif // LIBPKG_DATA_DATABASE_H