summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2023-02-24 21:39:02 +0100
committerAdmiral H. Curtiss <pikachu025@gmail.com>2023-02-26 23:17:09 +0100
commit5367bf394c6092bed589bc4cdb06a2f0ab2c0f75 (patch)
tree9f0baf8fce2b5b9ec9a03efb762c7b8de844f2b6
parent1ed0e014cd1c9087830fcee94e26f7dc3a3d45a8 (diff)
Common/FileUtil: Add Move() function.
-rw-r--r--Source/Core/Common/FileUtil.cpp52
-rw-r--r--Source/Core/Common/FileUtil.h7
2 files changed, 59 insertions, 0 deletions
diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp
index 656e74134b..333831d39f 100644
--- a/Source/Core/Common/FileUtil.cpp
+++ b/Source/Core/Common/FileUtil.cpp
@@ -558,6 +558,58 @@ bool Copy(std::string_view source_path, std::string_view dest_path, bool overwri
return true;
}
+static bool MoveWithOverwrite(const std::filesystem::path& src, const std::filesystem::path& dst,
+ std::error_code& error)
+{
+ fs::rename(src, dst, error);
+ if (!error)
+ return true;
+
+ // rename failed, try fallbacks
+
+ if (!fs::is_directory(src))
+ {
+ // src is not a directory (ie, probably a file), try to copy file + delete
+ if (!fs::copy_file(src, dst, fs::copy_options::overwrite_existing, error))
+ return false;
+ if (!fs::remove(src, error))
+ return false;
+ return true;
+ }
+
+ // src is a directory, recurse into it and try to move all sub-elements one by one
+ // this usually happens because the target is a non-empty directory
+ for (fs::directory_iterator it(src, error); it != fs::directory_iterator(); it.increment(error))
+ {
+ if (error)
+ return false;
+ if (!MoveWithOverwrite(it->path(), dst / it->path().filename(), error))
+ return false;
+ }
+ if (error)
+ return false;
+
+ // all sub-elements moved, remove top directory
+ if (!fs::remove(src, error))
+ return false;
+
+ return true;
+}
+
+bool MoveWithOverwrite(std::string_view source_path, std::string_view dest_path)
+{
+ DEBUG_LOG_FMT(COMMON, "{}: {} --> {}", __func__, source_path, dest_path);
+ auto src_path = StringToPath(source_path);
+ auto dst_path = StringToPath(dest_path);
+ std::error_code error;
+ if (!MoveWithOverwrite(src_path, dst_path, error))
+ {
+ ERROR_LOG_FMT(COMMON, "{}: failed {} --> {}: {}", __func__, source_path, dest_path,
+ error.message());
+ }
+ return true;
+}
+
// Create directory and copy contents (optionally overwrites existing files)
bool CopyDir(const std::string& source_path, const std::string& dest_path, const bool destructive)
{
diff --git a/Source/Core/Common/FileUtil.h b/Source/Core/Common/FileUtil.h
index f8cd92a880..53d5d46d3f 100644
--- a/Source/Core/Common/FileUtil.h
+++ b/Source/Core/Common/FileUtil.h
@@ -193,6 +193,13 @@ std::string GetCurrentDir();
bool Copy(std::string_view source_path, std::string_view dest_path,
bool overwrite_existing = false);
+// Moves source_path to dest_path. On success, the source_path will no longer exist, and the
+// dest_path will contain the data previously in source_path. Files in dest_path will be overwritten
+// if they match files in source_path, but files that only exist in dest_path will be kept. No
+// guarantee on the state is given on failure; the move may have completely failed or partially
+// completed.
+bool MoveWithOverwrite(std::string_view source_path, std::string_view dest_path);
+
// Create directory and copy contents (optionally overwrites existing files)
bool CopyDir(const std::string& source_path, const std::string& dest_path,
bool destructive = false);