diff --git a/libpkg/data/config.cpp b/libpkg/data/config.cpp index 6c38428..34eeb22 100644 --- a/libpkg/data/config.cpp +++ b/libpkg/data/config.cpp @@ -71,6 +71,15 @@ void LibPkg::Config::rebuildDb() aur.rebuildDb(); } +void Config::dumpDb(const std::optional &filterRegex) +{ + assert(m_storage != nullptr); + for (auto &db : databases) { + db.dumpDb(filterRegex); + } + aur.dumpDb(filterRegex); +} + std::size_t Config::cachedPackages() const { return m_storage ? m_storage->packageCache().size() : 0; diff --git a/libpkg/data/config.h b/libpkg/data/config.h index f88fb6f..fac74df 100644 --- a/libpkg/data/config.h +++ b/libpkg/data/config.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace LibPkg { @@ -123,6 +124,7 @@ struct LIBPKG_EXPORT Config : public Lockable, public ReflectiveRapidJSON::Binar // storage and caching void initStorage(const char *path = "libpkg.db", std::uint32_t maxDbs = 0); void rebuildDb(); + void dumpDb(const std::optional &filterRegex); std::size_t cachedPackages() const; void setPackageCacheLimit(std::size_t limit); std::unique_ptr &storage(); diff --git a/libpkg/data/database.cpp b/libpkg/data/database.cpp index a38ca17..dba681e 100644 --- a/libpkg/data/database.cpp +++ b/libpkg/data/database.cpp @@ -104,6 +104,28 @@ void LibPkg::Database::rebuildDb() txn.commit(); } +void Database::dumpDb(const std::optional &filterRegex) +{ + std::cout << "db: " << name << '@' << arch << '\n'; + auto txn = m_storage->packages.getROTransaction(); + auto end = txn.end(); + std::cout << "packages (" << txn.size() << "):\n"; + for (auto i = txn.begin(); i != end; ++i) { + if (const auto &value = i.value(); !filterRegex.has_value() || std::regex_match(value.name, filterRegex.value())) { + const auto key = i.getKey().get(); + std::cout << key << ':' << ' ' << value.name << '\n'; + } + } + std::cout << "index (" << txn.size<0>() << "):\n"; + for (auto i = txn.begin<0>(); i != end; ++i) { + if (const auto key = i.getKey().get(); !filterRegex.has_value() || std::regex_match(key.cbegin(), key.cend(), filterRegex.value())) { + const auto value = i.getID(); + std::cout << key << ':' << ' ' << value << '\n'; + } + } + std::cout << '\n'; +} + void LibPkg::Database::deducePathsFromLocalDirs() { if (localDbDir.empty()) { diff --git a/libpkg/data/database.h b/libpkg/data/database.h index 51cc59e..ba85cf0 100644 --- a/libpkg/data/database.h +++ b/libpkg/data/database.h @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace LibPkg { @@ -161,6 +162,7 @@ struct LIBPKG_EXPORT Database : public ReflectiveRapidJSON::JsonSerializable &filterRegex); void deducePathsFromLocalDirs(); void resetConfiguration(bool keepLocalPaths = false); void clearPackages(); diff --git a/librepomgr/serversetup.cpp b/librepomgr/serversetup.cpp index 5d6bf92..71778b4 100644 --- a/librepomgr/serversetup.cpp +++ b/librepomgr/serversetup.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include using namespace std; @@ -885,6 +886,25 @@ int ServiceSetup::fixDb() return EXIT_SUCCESS; } +int ServiceSetup::dumpDb(std::string_view filterRegex) +{ +#ifndef CPP_UTILITIES_DEBUG_BUILD + try { +#endif + loadConfigFiles(true); + config.dumpDb(filterRegex.empty() ? std::nullopt : std::optional(std::regex(filterRegex.begin(), filterRegex.end()))); +#ifndef CPP_UTILITIES_DEBUG_BUILD + } catch (const std::exception &e) { + cerr << Phrases::ErrorMessage << "Exception occurred: " << Phrases::End << " " << e.what() << Phrases::EndFlush; + return EXIT_FAILURE + 5; + } catch (...) { + cerr << Phrases::ErrorMessage << "Unknown error occurred." << Phrases::EndFlush; + return EXIT_FAILURE + 5; + } +#endif + return EXIT_SUCCESS; +} + void ServiceSetup::Locks::clear() { auto log = LogContext(); diff --git a/librepomgr/serversetup.h b/librepomgr/serversetup.h index f49670e..cefff29 100644 --- a/librepomgr/serversetup.h +++ b/librepomgr/serversetup.h @@ -61,6 +61,7 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable { void initStorage(); int run(); int fixDb(); + int dumpDb(std::string_view filterRegex); ServiceStatus computeStatus(); // variables relevant for the web server; only changed when (re)loading config diff --git a/srv/main.cpp b/srv/main.cpp index e01c6d3..86d7f24 100644 --- a/srv/main.cpp +++ b/srv/main.cpp @@ -41,9 +41,18 @@ int main(int argc, const char *argv[]) } exitCode = setup.fixDb(); }); + OperationArgument dumpDb("dump-db", '\0', "dumps package database entries"); + ConfigValueArgument filterRegexArg("filter-regex", 'r', "dump only packages which name matches the specified regex", { "regex" }); + dumpDb.setSubArguments({ &filterRegexArg, &configFileArg }); + dumpDb.setCallback([&setup, &exitCode, &filterRegexArg, &configFileArg](const ArgumentOccurrence &) { + if (const auto configFilePath = configFileArg.firstValue()) { + setup.configFilePath = configFilePath; + } + exitCode = setup.dumpDb(filterRegexArg.isPresent() ? std::string_view(filterRegexArg.firstValue()) : std::string_view()); + }); HelpArgument helpArg(parser); NoColorArgument noColorArg; - parser.setMainArguments({ &runArg, &fixDb, &noColorArg, &helpArg }); + parser.setMainArguments({ &runArg, &fixDb, &dumpDb, &noColorArg, &helpArg }); parser.setDefaultArgument(&runArg); parser.parseArgs(argc, argv); return exitCode;