diff options
-rw-r--r-- | src/buildtool/file_system/file_system_manager.hpp | 6 | ||||
-rw-r--r-- | test/buildtool/file_system/TARGETS | 3 | ||||
-rw-r--r-- | test/buildtool/file_system/file_system_manager.test.cpp | 28 |
3 files changed, 37 insertions, 0 deletions
diff --git a/src/buildtool/file_system/file_system_manager.hpp b/src/buildtool/file_system/file_system_manager.hpp index 528d50ca..146e6dbf 100644 --- a/src/buildtool/file_system/file_system_manager.hpp +++ b/src/buildtool/file_system/file_system_manager.hpp @@ -1065,6 +1065,12 @@ class FileSystemManager { if (std::filesystem::is_symlink(src)) { return false; } + // Check that src and dst point to different filesystem entities: + if (std::filesystem::weakly_canonical(src) == + std::filesystem::weakly_canonical(dst)) { + return true; + } + if (not RemoveFile(dst)) { Logger::Log( LogLevel::Error, "cannot remove file {}", dst.string()); diff --git a/test/buildtool/file_system/TARGETS b/test/buildtool/file_system/TARGETS index c1ac0af6..141deb42 100644 --- a/test/buildtool/file_system/TARGETS +++ b/test/buildtool/file_system/TARGETS @@ -10,8 +10,11 @@ , ["@", "src", "src/buildtool/file_system", "object_type"] , ["@", "src", "src/buildtool/logging", "log_level"] , ["@", "src", "src/buildtool/logging", "logging"] + , ["@", "src", "src/buildtool/storage", "config"] , ["@", "src", "src/buildtool/system", "system"] + , ["@", "src", "src/utils/cpp", "tmp_dir"] , ["", "catch-main"] + , ["utils", "test_storage_config"] ] , "stage": ["test", "buildtool", "file_system"] } diff --git a/test/buildtool/file_system/file_system_manager.test.cpp b/test/buildtool/file_system/file_system_manager.test.cpp index 805d8bc1..9e6c0591 100644 --- a/test/buildtool/file_system/file_system_manager.test.cpp +++ b/test/buildtool/file_system/file_system_manager.test.cpp @@ -20,6 +20,7 @@ #include <filesystem> #include <fstream> #include <functional> +#include <memory> #include <optional> #include <string> #include <unordered_map> @@ -33,7 +34,10 @@ #include "src/buildtool/file_system/object_type.hpp" #include "src/buildtool/logging/log_level.hpp" #include "src/buildtool/logging/logger.hpp" +#include "src/buildtool/storage/config.hpp" #include "src/buildtool/system/system.hpp" +#include "src/utils/cpp/tmp_dir.hpp" +#include "test/utils/hermeticity/test_storage_config.hpp" class CopyFileFixture { public: @@ -367,6 +371,30 @@ TEST_CASE_METHOD(CopyFileFixture, "CopyFile", "[file_system]") { } } +TEST_CASE("CopyFile equivalent", "[file_system]") { + auto storage_config = TestStorageConfig::Create(); + + auto temp_dir = storage_config.Get().CreateTypedTmpDir("test"); + REQUIRE(temp_dir); + + auto const nested = temp_dir->GetPath() / "dir"; + auto const source = nested / "copy-self"; + auto const target = nested / "../dir/copy-self"; + + REQUIRE(FileSystemManager::CreateDirectory(nested)); + REQUIRE(FileSystemManager::CreateFile(source)); + REQUIRE(FileSystemManager::IsFile(source)); + REQUIRE(FileSystemManager::IsFile(target)); + + // Paths are different, but equivalent: + REQUIRE(source != target); + REQUIRE(std::filesystem::equivalent(source, target)); + + CHECK(FileSystemManager::CopyFile(source, target)); + CHECK(FileSystemManager::IsFile(source)); + CHECK(FileSystemManager::IsFile(target)); +} + TEST_CASE_METHOD(CopyFileFixture, "CopyFileAs", "[file_system]") { SECTION("as file") { auto run_test = [&]<bool kSetEpochTime = false>(bool fd_less) { |