mirror of
https://git.mirrors.martin98.com/https://github.com/gulrak/filesystem
synced 2025-06-04 11:13:58 +08:00
Merge branch 'feature-68-experimental-emscripten-support'
This commit is contained in:
commit
cdfb593d40
@ -492,7 +492,8 @@ to the expected behavior.
|
||||
* Pull request [#69](https://github.com/gulrak/filesystem/pull/69), use `wchar_t` versions of
|
||||
`std::fstream` from `ghc::filesystem::fstream` wrappers on Windows if using GCC with libc++.
|
||||
* Bugfix for [#68](https://github.com/gulrak/filesystem/issues/68), better handling of
|
||||
permission issues for directory iterators when using `fs::directory_options::skip_permission_denied`.
|
||||
permission issues for directory iterators when using `fs::directory_options::skip_permission_denied`
|
||||
and initial support for compilation with emscripten.
|
||||
* Bugfix for [#63](https://github.com/gulrak/filesystem/issues/63), fixed issues on Windows
|
||||
with clang++ and C++17.
|
||||
* Pull request [#62](https://github.com/gulrak/filesystem/pull/62), various fixes for
|
||||
|
@ -64,6 +64,9 @@
|
||||
#define GHC_OS_SYS5R4
|
||||
#elif defined(BSD)
|
||||
#define GHC_OS_BSD
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#define GHC_OS_WEB
|
||||
#include <wasi/api.h>
|
||||
#else
|
||||
#error "Operating system currently not supported!"
|
||||
#endif
|
||||
@ -590,7 +593,9 @@ enum class copy_options : uint16_t {
|
||||
|
||||
directories_only = 0x40,
|
||||
create_symlinks = 0x80,
|
||||
#ifndef GHC_OS_WEB
|
||||
create_hard_links = 0x100
|
||||
#endif
|
||||
};
|
||||
|
||||
enum class directory_options : uint16_t {
|
||||
@ -701,10 +706,14 @@ public:
|
||||
uintmax_t file_size() const;
|
||||
#endif
|
||||
uintmax_t file_size(std::error_code& ec) const noexcept;
|
||||
|
||||
#ifndef GHC_OS_WEB
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
uintmax_t hard_link_count() const;
|
||||
#endif
|
||||
uintmax_t hard_link_count(std::error_code& ec) const noexcept;
|
||||
#endif
|
||||
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
file_time_type last_write_time() const;
|
||||
#endif
|
||||
@ -934,10 +943,12 @@ GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink
|
||||
#endif
|
||||
GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept;
|
||||
|
||||
#ifndef GHC_OS_WEB
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link);
|
||||
#endif
|
||||
GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept;
|
||||
#endif
|
||||
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
GHC_FS_API void create_symlink(const path& to, const path& new_symlink);
|
||||
@ -969,10 +980,12 @@ GHC_FS_API uintmax_t file_size(const path& p);
|
||||
#endif
|
||||
GHC_FS_API uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
|
||||
|
||||
#ifndef GHC_OS_WEB
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
GHC_FS_API uintmax_t hard_link_count(const path& p);
|
||||
#endif
|
||||
GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
|
||||
#endif
|
||||
|
||||
GHC_FS_API bool is_block_file(file_status s) noexcept;
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
@ -1815,6 +1828,7 @@ GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink,
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef GHC_OS_WEB
|
||||
GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec)
|
||||
{
|
||||
if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) {
|
||||
@ -1822,6 +1836,7 @@ GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlin
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
GHC_INLINE file_status file_status_from_st_mode(T mode)
|
||||
@ -3402,9 +3417,11 @@ GHC_INLINE void copy(const path& from, const path& to, copy_options options, std
|
||||
if ((options & copy_options::create_symlinks) != copy_options::none) {
|
||||
create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec);
|
||||
}
|
||||
#ifndef GHC_OS_WEB
|
||||
else if ((options & copy_options::create_hard_links) != copy_options::none) {
|
||||
create_hard_link(from, to, ec);
|
||||
}
|
||||
#endif
|
||||
else if (is_directory(fs_to)) {
|
||||
copy_file(from, to / from.filename(), options, ec);
|
||||
}
|
||||
@ -3697,6 +3714,7 @@ GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink
|
||||
detail::create_symlink(to, new_symlink, true, ec);
|
||||
}
|
||||
|
||||
#ifndef GHC_OS_WEB
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link)
|
||||
{
|
||||
@ -3712,6 +3730,7 @@ GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link, std:
|
||||
{
|
||||
detail::create_hardlink(to, new_hard_link, ec);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
GHC_INLINE void create_symlink(const path& to, const path& new_symlink)
|
||||
@ -3900,6 +3919,7 @@ GHC_INLINE uintmax_t file_size(const path& p, std::error_code& ec) noexcept
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef GHC_OS_WEB
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
GHC_INLINE uintmax_t hard_link_count(const path& p)
|
||||
{
|
||||
@ -3940,6 +3960,7 @@ GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcep
|
||||
return ec ? static_cast<uintmax_t>(-1) : result;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
GHC_INLINE bool is_block_file(file_status s) noexcept
|
||||
{
|
||||
@ -4176,7 +4197,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
|
||||
times[0].tv_sec = 0;
|
||||
times[0].tv_nsec = UTIME_OMIT;
|
||||
times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
|
||||
times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
|
||||
times[1].tv_nsec = 0; //std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
|
||||
if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
|
||||
ec = detail::make_system_error();
|
||||
}
|
||||
@ -4945,6 +4966,7 @@ GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexc
|
||||
return filesystem::file_size(path(), ec);
|
||||
}
|
||||
|
||||
#ifndef GHC_OS_WEB
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
GHC_INLINE uintmax_t directory_entry::hard_link_count() const
|
||||
{
|
||||
@ -4967,6 +4989,7 @@ GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const
|
||||
#endif
|
||||
return filesystem::hard_link_count(path(), ec);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GHC_WITH_EXCEPTIONS
|
||||
GHC_INLINE file_time_type directory_entry::last_write_time() const
|
||||
|
@ -18,12 +18,16 @@ else()
|
||||
add_executable(filesystem_test filesystem_test.cpp catch.hpp)
|
||||
target_link_libraries(filesystem_test ghc_filesystem)
|
||||
target_compile_options(filesystem_test PRIVATE
|
||||
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
|
||||
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/WX>)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
if(EMSCRIPTEN)
|
||||
set_target_properties(filesystem_test PROPERTIES LINK_FLAGS "-g4 -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1")
|
||||
endif()
|
||||
ParseAndAddCatchTests(filesystem_test)
|
||||
AddExecutableWithStdFS(std_filesystem_test filesystem_test.cpp catch.hpp)
|
||||
if(WIN32)
|
||||
|
@ -144,7 +144,7 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
|
||||
if("${TestType}" STREQUAL "SCENARIO")
|
||||
set(Name "Scenario: ${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture)
|
||||
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture )
|
||||
set(CTestName "${TestFixture}:${Name}")
|
||||
else()
|
||||
set(CTestName "${Name}")
|
||||
@ -189,24 +189,29 @@ function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
|
||||
# Escape commas in the test spec
|
||||
string(REPLACE "," "\\," Name ${Name})
|
||||
|
||||
# Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were neccessary,
|
||||
# only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1
|
||||
if(NOT ${CMAKE_VERSION} VERSION_EQUAL "3.18")
|
||||
set(CTestName "\"${CTestName}\"")
|
||||
endif()
|
||||
# Add the test and set its properties
|
||||
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
|
||||
add_test(NAME "${CTestName}" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
|
||||
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
|
||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property")
|
||||
set_tests_properties("\"${CTestName}\"" PROPERTIES DISABLED ON)
|
||||
set_tests_properties("${CTestName}" PROPERTIES DISABLED ON)
|
||||
else()
|
||||
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||
set_tests_properties("${CTestName}" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||
LABELS "${Labels}")
|
||||
endif()
|
||||
set_property(
|
||||
TARGET ${TestTarget}
|
||||
APPEND
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}")
|
||||
set_property(
|
||||
SOURCE ${SourceFile}
|
||||
APPEND
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}")
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -1229,9 +1229,11 @@ TEST_CASE("30.10.12 class directory_entry", "[filesystem][directory_entry][fs.di
|
||||
ec.clear();
|
||||
CHECK(std::abs(std::chrono::duration_cast<std::chrono::seconds>(de.last_write_time(ec) - now).count()) < 3);
|
||||
CHECK(!ec);
|
||||
#ifndef GHC_OS_WEB
|
||||
CHECK(de.hard_link_count() == 1);
|
||||
CHECK(de.hard_link_count(ec) == 1);
|
||||
CHECK(!ec);
|
||||
#endif
|
||||
CHECK_THROWS_AS(de.replace_filename("bar"), fs::filesystem_error);
|
||||
CHECK_NOTHROW(de.replace_filename("foo"));
|
||||
ec.clear();
|
||||
@ -1239,9 +1241,11 @@ TEST_CASE("30.10.12 class directory_entry", "[filesystem][directory_entry][fs.di
|
||||
CHECK(ec);
|
||||
auto de2none = fs::directory_entry();
|
||||
ec.clear();
|
||||
#ifndef GHC_OS_WEB
|
||||
CHECK(de2none.hard_link_count(ec) == static_cast<uintmax_t>(-1));
|
||||
CHECK_THROWS_AS(de2none.hard_link_count(), fs::filesystem_error);
|
||||
CHECK(ec);
|
||||
#endif
|
||||
ec.clear();
|
||||
CHECK_NOTHROW(de2none.last_write_time(ec));
|
||||
CHECK_THROWS_AS(de2none.last_write_time(), fs::filesystem_error);
|
||||
@ -1593,6 +1597,7 @@ TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
|
||||
CHECK(fs::is_symlink("dir3/dir2/file3"));
|
||||
#endif
|
||||
}
|
||||
#ifndef GHC_OS_WEB
|
||||
{
|
||||
TemporaryDirectory t(TempOpt::change_path);
|
||||
std::error_code ec;
|
||||
@ -1613,6 +1618,7 @@ TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
|
||||
CHECK(fs::exists("dir3/dir2/file3"));
|
||||
CHECK(fs::hard_link_count("dir1/dir2/file3") == f3hl + 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("30.10.15.4 copy_file", "[filesystem][operations][fs.op.copy_file]")
|
||||
@ -1780,6 +1786,7 @@ TEST_CASE("30.10.15.8 create_directory_symlink", "[filesystem][operations][fs.op
|
||||
|
||||
TEST_CASE("30.10.15.9 create_hard_link", "[filesystem][operations][fs.op.create_hard_link]")
|
||||
{
|
||||
#ifndef GHC_OS_WEB
|
||||
TemporaryDirectory t(TempOpt::change_path);
|
||||
std::error_code ec;
|
||||
generateFile("foo", 1234);
|
||||
@ -1793,6 +1800,7 @@ TEST_CASE("30.10.15.9 create_hard_link", "[filesystem][operations][fs.op.create_
|
||||
CHECK_THROWS_AS(fs::create_hard_link("nofoo", "bar"), fs::filesystem_error);
|
||||
CHECK_NOTHROW(fs::create_hard_link("nofoo", "bar", ec));
|
||||
CHECK(ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("30.10.15.10 create_symlink", "[filesystem][operations][fs.op.create_symlink]")
|
||||
@ -1927,6 +1935,7 @@ TEST_CASE("30.10.15.14 file_size", "[filesystem][operations][fs.op.file_size]")
|
||||
|
||||
TEST_CASE("30.10.15.15 hard_link_count", "[filesystem][operations][fs.op.hard_link_count]")
|
||||
{
|
||||
#ifndef GHC_OS_WEB
|
||||
TemporaryDirectory t(TempOpt::change_path);
|
||||
std::error_code ec;
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
@ -1952,6 +1961,9 @@ TEST_CASE("30.10.15.15 hard_link_count", "[filesystem][operations][fs.op.hard_li
|
||||
CHECK_NOTHROW(fs::hard_link_count(t.path() / "bar", ec));
|
||||
CHECK(ec);
|
||||
ec.clear();
|
||||
#else
|
||||
WARN("Test for unsupportet features are disabled on JS/Wasm target.");
|
||||
#endif
|
||||
}
|
||||
|
||||
class FileTypeMixFixture
|
||||
@ -1968,7 +1980,7 @@ public:
|
||||
fs::create_symlink("regular", "file_symlink");
|
||||
fs::create_directory_symlink("directory", "dir_symlink");
|
||||
}
|
||||
#ifndef GHC_OS_WINDOWS
|
||||
#if !defined(GHC_OS_WINDOWS) && !defined(GHC_OS_WEB)
|
||||
REQUIRE(::mkfifo("fifo", 0644) == 0);
|
||||
_hasFifo = true;
|
||||
struct ::sockaddr_un addr;
|
||||
@ -2271,6 +2283,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.24 is_symlink", "[filesystem][ope
|
||||
CHECK(!fs::is_symlink(fs::file_status(fs::file_type::unknown)));
|
||||
}
|
||||
|
||||
#ifndef GHC_OS_WEB
|
||||
static fs::file_time_type timeFromString(const std::string& str)
|
||||
{
|
||||
struct ::tm tm;
|
||||
@ -2282,6 +2295,7 @@ static fs::file_time_type timeFromString(const std::string& str)
|
||||
}
|
||||
return from_time_t<fs::file_time_type>(std::mktime(&tm));
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("30.10.15.25 last_write_time", "[filesystem][operations][fs.op.last_write_time]")
|
||||
{
|
||||
@ -2304,16 +2318,21 @@ TEST_CASE("30.10.15.25 last_write_time", "[filesystem][operations][fs.op.last_wr
|
||||
// checks that the time of the symlink is fetched
|
||||
CHECK(ft == fs::last_write_time("foo2"));
|
||||
}
|
||||
#ifndef GHC_OS_WEB
|
||||
auto nt = timeFromString("2015-10-21T04:30:00");
|
||||
CHECK_NOTHROW(fs::last_write_time(t.path() / "foo", nt));
|
||||
CHECK(std::abs(std::chrono::duration_cast<std::chrono::seconds>(fs::last_write_time("foo") - nt).count()) < 1);
|
||||
nt = timeFromString("2015-10-21T04:29:00");
|
||||
CHECK_NOTHROW(fs::last_write_time("foo", nt, ec));
|
||||
std::cout << "about to call last_write_time" << std::endl;
|
||||
CHECK(std::abs(std::chrono::duration_cast<std::chrono::seconds>(fs::last_write_time("foo") - nt).count()) < 1);
|
||||
CHECK(!ec);
|
||||
std::cout << "about to call last_write_time" << std::endl;
|
||||
CHECK_THROWS_AS(fs::last_write_time("bar", nt), fs::filesystem_error);
|
||||
std::cout << "about to call last_write_time" << std::endl;
|
||||
CHECK_NOTHROW(fs::last_write_time("bar", nt, ec));
|
||||
CHECK(ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("30.10.15.26 permissions", "[filesystem][operations][fs.op.permissions]")
|
||||
@ -2499,6 +2518,7 @@ TEST_CASE("30.10.15.34 space", "[filesystem][operations][fs.op.space]")
|
||||
CHECK(si.free >= si.available);
|
||||
CHECK(!ec);
|
||||
}
|
||||
#ifndef GHC_OS_WEB // statvfs under emscripten always returns a result, so this tests would fail
|
||||
{
|
||||
std::error_code ec;
|
||||
fs::space_info si;
|
||||
@ -2509,6 +2529,7 @@ TEST_CASE("30.10.15.34 space", "[filesystem][operations][fs.op.space]")
|
||||
CHECK(ec);
|
||||
}
|
||||
CHECK_THROWS_AS(fs::space("foobar42"), fs::filesystem_error);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("30.10.15.35 status", "[filesystem][operations][fs.op.status]")
|
||||
|
Loading…
x
Reference in New Issue
Block a user