Skip to content

Commit 7a47b84

Browse files
committed
[brief] Adds a way to temporarily switch working directories.
[detailed] - RAII wrapper so the switch occurs upon destruction of the scope. - Made it move-only so weird things can't happen. - Also adds a wrapper namespace for filesystem so it's easier to deal with.
1 parent 7c7a4b0 commit 7a47b84

File tree

2 files changed

+66
-17
lines changed

2 files changed

+66
-17
lines changed

include/zeus/filesystem.hpp

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@
1414
#include <string>
1515

1616
#if defined(ZEUS_PLATFORM_WINDOWS) || defined(ZEUS_PLATFORM_APPLE)
17-
# include <filesystem>
17+
# include <filesystem> // IWYU pragma: export
1818
#else
19-
# include <experimental/filesystem>
19+
# include <experimental/filesystem> // IWYU pragma: export
2020
#endif
2121

2222
namespace zeus
2323
{
24+
#if defined(ZEUS_PLATFORM_WINDOWS) || defined(ZEUS_PLATFORM_APPLE)
25+
namespace zeus_fs = std::filesystem;
26+
#else
27+
namespace zeus_fs = std::experimental::filesystem;
28+
#endif
29+
2430
#if !defined(ZEUS_PLATFORM_APPLE)
2531
inline std::time_t get_file_last_write(std::string filename)
2632
{
27-
# if defined(ZEUS_PLATFORM_WINDOWS)
28-
namespace fs = std::filesystem;
29-
# else
30-
namespace fs = std::experimental::filesystem;
31-
# endif
32-
33-
const fs::path file_path{filename};
33+
const zeus_fs::path file_path{filename};
3434
std::error_code code;
35-
auto ftime = fs::last_write_time(file_path, code);
35+
auto ftime = zeus_fs::last_write_time(file_path, code);
3636
if (code && current_build == BuildType::debug)
3737
{
3838
fmt::print(stderr, "warning: ({}): {}\n", code.value(), code.message());
@@ -49,13 +49,7 @@ namespace zeus
4949

5050
inline std::string get_file_directory(std::string filename)
5151
{
52-
#if defined(ZEUS_PLATFORM_WINDOWS) || defined(ZEUS_PLATFORM_APPLE)
53-
namespace fs = std::filesystem;
54-
#else
55-
namespace fs = std::experimental::filesystem;
56-
#endif
57-
58-
const fs::path file_path{filename};
52+
const zeus_fs::path file_path{filename};
5953
std::string root_dir;
6054
if (file_path.has_parent_path())
6155
{
@@ -64,4 +58,35 @@ namespace zeus
6458

6559
return root_dir;
6660
}
61+
62+
class ChdirScope
63+
{
64+
public:
65+
ChdirScope(zeus_fs::path const& target_path)
66+
{
67+
m_start_path = zeus_fs::current_path();
68+
zeus_fs::current_path(target_path);
69+
}
70+
71+
ChdirScope(ChdirScope const&) = delete;
72+
ChdirScope(ChdirScope&&) = default;
73+
74+
~ChdirScope()
75+
{
76+
try
77+
{
78+
zeus_fs::current_path(m_start_path);
79+
}
80+
catch (zeus_fs::filesystem_error const&) // NOLINT(bugprone-empty-catch)
81+
{
82+
fmt::print("error: unable to switch back to {}", m_start_path.string());
83+
}
84+
}
85+
86+
ChdirScope& operator=(ChdirScope const&) = delete;
87+
ChdirScope& operator=(ChdirScope&&) = default;
88+
89+
private:
90+
zeus_fs::path m_start_path;
91+
};
6792
} // namespace zeus

test/filesystem_test.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,27 @@ TEST_CASE("[filesystem] - get_file_directory: valid root")
2121
auto result = get_file_directory(file_path);
2222
REQUIRE(result == expected);
2323
}
24+
25+
TEST_CASE("[filesystem] - ChdirScope")
26+
{
27+
using zeus::ChdirScope;
28+
namespace fs = zeus::zeus_fs;
29+
30+
const auto start_path = fs::current_path();
31+
const auto new_path = start_path / "test_dir";
32+
auto cur_path = start_path;
33+
fs::create_directory(new_path);
34+
REQUIRE(fs::exists(new_path));
35+
REQUIRE(cur_path == start_path);
36+
37+
{
38+
const auto _ = ChdirScope{new_path};
39+
cur_path = fs::current_path();
40+
REQUIRE(cur_path == new_path);
41+
}
42+
43+
cur_path = fs::current_path();
44+
REQUIRE(cur_path == start_path);
45+
46+
fs::remove(new_path);
47+
}

0 commit comments

Comments
 (0)