From 418cd3c3d3dce0ed6c6a93300848dcdfed98dc6d Mon Sep 17 00:00:00 2001 From: J-D-K Date: Sun, 21 Sep 2025 12:10:48 -0400 Subject: [PATCH] Add fs::move_directory_recursively. --- include/fs/directory_functions.hpp | 3 +++ source/appstates/SettingsState.cpp | 21 ++++++++++++++------- source/config/config.cpp | 8 +------- source/fs/directory_functions.cpp | 30 ++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/include/fs/directory_functions.hpp b/include/fs/directory_functions.hpp index 634a95e..ee73956 100644 --- a/include/fs/directory_functions.hpp +++ b/include/fs/directory_functions.hpp @@ -18,4 +18,7 @@ namespace fs /// @param directoryPath Path to directory to check. /// @return True if directory has files inside. bool directory_has_contents(const fslib::Path &directoryPath); + + /// @brief Recursively moves (renames) everything in oldPath to newPath. + bool move_directory_recursively(const fslib::Path &oldPath, const fslib::Path &newPath); } // namespace fs diff --git a/source/appstates/SettingsState.cpp b/source/appstates/SettingsState.cpp index db1468b..a0e7001 100644 --- a/source/appstates/SettingsState.cpp +++ b/source/appstates/SettingsState.cpp @@ -6,6 +6,7 @@ #include "config/config.hpp" #include "data/data.hpp" #include "error.hpp" +#include "fs/fs.hpp" #include "fslib.hpp" #include "graphics/colors.hpp" #include "input.hpp" @@ -156,28 +157,34 @@ void SettingsState::change_working_directory() const char *popSuccessFormat = strings::get_by_name(strings::names::SETTINGS_POPS, 1); const char *popFailed = strings::get_by_name(strings::names::SETTINGS_POPS, 2); - const std::string oldPath = config::get_working_directory().string(); + const fslib::Path oldPath = config::get_working_directory(); std::array pathBuffer = {0}; - const bool input = keyboard::get_input(SwkbdType_Normal, oldPath, inputHeader, pathBuffer.data(), FS_MAX_PATH); + const bool input = + keyboard::get_input(SwkbdType_Normal, oldPath.string().c_str(), inputHeader, pathBuffer.data(), FS_MAX_PATH); if (!input) { return; } const fslib::Path newPath{pathBuffer.data()}; - const bool exists = fslib::directory_exists(newPath); - if (exists) + if (!newPath.is_valid()) { ui::PopMessageManager::push_message(popTicks, popFailed); return; } - const bool pathSet = config::set_working_directory(newPath); - const bool renameError = pathSet && error::fslib(fslib::rename_directory(oldPath, newPath)); - if (!pathSet || renameError) + const bool exists = fslib::directory_exists(newPath); + bool moved{}; + if (exists) { moved = fs::move_directory_recursively(oldPath, newPath); } + else { moved = fslib::rename_directory(oldPath, newPath); } + + if (!moved) { ui::PopMessageManager::push_message(popTicks, popFailed); return; } + // Since the path was validated before, this shouldn't need to be checked. + config::set_working_directory(newPath); + const std::string newPathString = newPath.string(); std::string popMessage = stringutil::get_formatted_string(popSuccessFormat, newPathString.c_str()); ui::PopMessageManager::push_message(popTicks, popMessage); diff --git a/source/config/config.cpp b/source/config/config.cpp index 064dfc8..e846b77 100644 --- a/source/config/config.cpp +++ b/source/config/config.cpp @@ -28,13 +28,7 @@ void config::set_by_key(std::string_view key, uint8_t value) noexcept { s_contex fslib::Path config::get_working_directory() { return s_context.get_working_directory(); } -bool config::set_working_directory(const fslib::Path &path) noexcept -{ - const bool pathSet = s_context.set_working_directory(path); - if (!pathSet) { return false; } - - return true; -} +bool config::set_working_directory(const fslib::Path &path) noexcept { return s_context.set_working_directory(path); } double config::get_animation_scaling() noexcept { return s_context.get_animation_scaling(); } diff --git a/source/fs/directory_functions.cpp b/source/fs/directory_functions.cpp index 3d85092..abcc86e 100644 --- a/source/fs/directory_functions.cpp +++ b/source/fs/directory_functions.cpp @@ -43,3 +43,33 @@ bool fs::directory_has_contents(const fslib::Path &directoryPath) return false; } + +bool fs::move_directory_recursively(const fslib::Path &oldPath, const fslib::Path &newPath) +{ + fslib::Directory sourceDir{oldPath}; + if (!sourceDir.is_open()) { return false; } + + for (const fslib::DirectoryEntry &entry : sourceDir) + { + const fslib::Path fullSource{oldPath / entry}; + const fslib::Path fullDest{newPath / entry}; + logger::log("%s -> %s", fullSource.string().c_str(), fullDest.string().c_str()); + + if (entry.is_directory()) + { + const bool exists = fslib::directory_exists(fullDest); + const bool renameError = !exists && error::fslib(fslib::rename_directory(fullSource, fullDest)); + const bool moved = exists && fs::move_directory_recursively(fullSource, fullDest); + + if (renameError && !moved) { return false; } + } + else + { + const bool exists = fslib::file_exists(fullDest); + const bool renamed = !exists && fslib::rename_file(fullSource, fullDest); + if (!exists && !renamed) { return false; } + } + } + + return true; +} \ No newline at end of file