diff --git a/src/cpp/project/pathfinder/src/cli.cpp b/src/cpp/project/pathfinder/src/cli.cpp index 03a148a5..57b16626 100644 --- a/src/cpp/project/pathfinder/src/cli.cpp +++ b/src/cpp/project/pathfinder/src/cli.cpp @@ -9,12 +9,17 @@ #include #include "cmd.hpp" +#include "db.hpp" paf::cli::cli(int argc, char** argv) { - bool help = false; + bool show_help = false; + bool reset_dir_db = false; + bool reset_file_db = false; auto cli = lyra::cli() | - lyra::help(help).description("Pathfinding interface for interactive shells."); + lyra::help(show_help).description("Pathfinding interface for interactive shells.") | + lyra::opt(reset_dir_db)["--reset-directory-database"]("reset directory database") | + lyra::opt(reset_file_db)["--reset-file-database"]("reset file database"); paf::alias _{ cli }; paf::mark _{ cli }; @@ -32,10 +37,16 @@ paf::cli::cli(int argc, char** argv) std::exit(EXIT_FAILURE); } - if (help) { + if (show_help) { std::cout << cli << '\n'; std::exit(EXIT_SUCCESS); } + + if (reset_dir_db) + paf::db::reset_db(paf::db_type::directory); + + if (reset_file_db) + paf::db::reset_db(paf::db_type::file); } [[noreturn]] void paf::cli::run(void) diff --git a/src/cpp/project/pathfinder/src/db.cpp b/src/cpp/project/pathfinder/src/db.cpp index 2e829b5e..3f47983e 100644 --- a/src/cpp/project/pathfinder/src/db.cpp +++ b/src/cpp/project/pathfinder/src/db.cpp @@ -12,9 +12,12 @@ #include #include +#include namespace fs = std::filesystem; +using db_version_t = std::uint64_t; + namespace paf { static std::optional> db_dir_vec = std::nullopt, db_file_vec = std::nullopt; @@ -36,22 +39,44 @@ namespace paf { } } + static void load_db_v0(std::vector& db_vec, std::ifstream& ifs) + { + for (std::string k, v; std::getline(ifs, k, '\0') && std::getline(ifs, v, '\0');) + db_vec.emplace_back(k, v); + } + static void load_db(std::vector& db_vec, db_type type) { const auto path = get_db_path(type); std::ifstream ifs{ path }; - for (std::string k, v; std::getline(ifs, k, '\0') && std::getline(ifs, v, '\0');) - db_vec.emplace_back(k, v); + if (ifs.peek() == std::ifstream::traits_type::eof()) + return; + + db_version_t version; + ifs.read(reinterpret_cast(&version), sizeof(version)); + + if (version == 0) + load_db_v0(db_vec, ifs); + else + xph::die("cannot load database with version [", version, "]"); } static void save_db(const std::vector& db_vec, db_type type) { + static const constexpr db_version_t db_version = 0uz; + const auto path = get_db_path(type); const auto tmp_path = path + ".tmp"; - for (std::ofstream ofs{ tmp_path }; const auto& item : db_vec) - ofs << item.keycode << '\0' << item.path << '\0'; + { + std::ofstream ofs{ tmp_path }; + + ofs.write(reinterpret_cast(&db_version), sizeof(db_version)); + + for (const auto& item : db_vec) + ofs << item.keycode << '\0' << item.path << '\0'; + } fs::rename(tmp_path, path); } @@ -80,6 +105,12 @@ namespace paf { } } + void db::reset_db(db_type type) + { + auto db_path = get_db_path(type); + fs::remove(db_path); + } + db::db(std::vector& db_vec, db_type type) : type(type), m_db_vec(db_vec) {} db::~db() diff --git a/src/cpp/project/pathfinder/src/db.hpp b/src/cpp/project/pathfinder/src/db.hpp index 6ea9301f..7c35924d 100644 --- a/src/cpp/project/pathfinder/src/db.hpp +++ b/src/cpp/project/pathfinder/src/db.hpp @@ -42,6 +42,7 @@ namespace paf { ~db(); static db get_db(db_type type); + static void reset_db(db_type type); void dump(std::string_view sep, std::string_view end); std::optional try_get_mark(const std::string& keycode);