mirror of
https://git.mirrors.martin98.com/https://github.com/gulrak/filesystem
synced 2025-07-28 17:32:03 +08:00
Squashed commit of the following:
commit 8d9f245e379d373942c0f49be19dacc9293cdcf0 Merge: 3ceb4b0 857a355 Author: gulrak <s.schuemann@pobox.com> Date: Fri May 3 23:52:57 2019 +0200 Merge branch 'development-v1.1' of https://github.com/gulrak/filesystem into development-v1.1 commit 3ceb4b0e4fe90be46b1fdbdfb7e2b3f160cccf3c Author: gulrak <s.schuemann@pobox.com> Date: Fri May 3 23:51:48 2019 +0200 Less noisy interoperability testing on weakly_canonial() commit 38f82a90ef5f4ec1fa341ce3ab34f3836a6bd9ea Author: gulrak <s.schuemann@pobox.com> Date: Fri May 3 23:50:43 2019 +0200 Additional fix for recursive_directory_iterator commit 857a3558fb13e8fae76e29b5b91cb76b5e98ea20 Merge: 9da5784 b557b5b Author: Steffen Schuemann <s.schuemann@pobox.com> Date: Fri May 3 23:47:20 2019 +0200 Merge branch 'development-v1.1' of github.com:gulrak/filesystem into development-v1.1 # Conflicts: # test/filesystem_test.cpp commit 9da57846ac4de06c4b0521ab69ea42816fd6a029 Merge: 96e89ae 43e75c3 Author: Steffen Schuemann <s.schuemann@pobox.com> Date: Fri May 3 23:42:31 2019 +0200 Merge remote-tracking branch 'origin/master' into development-v1.1 commit 96e89ae7f9e983cb3d0977d9ba77f421a0c06b0f Merge: 9d71161 882c60b Author: Steffen Schuemann <s.schuemann@pobox.com> Date: Fri May 3 23:40:18 2019 +0200 Merge remote-tracking branch 'origin/master' into development-v1.1 commit b557b5b476c085183bd3da72cc9f511df3b52272 Merge: 263a2d2 9d71161 Author: Steffen Schümann <s.schuemann@pobox.com> Date: Fri May 3 22:44:25 2019 +0200 Merge branch 'development-v1.1' of https://github.com/gulrak/filesystem into development-v1.1 commit 263a2d2c5b9f25631513271a6e26a9cb66e8f9da Author: Steffen Schümann <s.schuemann@pobox.com> Date: Fri May 3 22:44:01 2019 +0200 Work on Windows tests. commit 9d71161323f22e994b51fda73ebc19af9e67d6e6 Author: Steffen Schuemann <s.schuemann@pobox.com> Date: Fri May 3 08:30:40 2019 +0200 Fix for issues with recursive_directory_iterator not behaving like an input iterator and regarding pop()/depth(). commit 2ac1352b4a37fdb247b56fb63c1e2c3f56761649 Author: gulrak <s.schuemann@pobox.com> Date: Thu May 2 09:12:42 2019 +0200 Refactored builds with std::fs to a CMake macro, added du example, added behaviour switch commit 624a6f63e5639504c2b554ba89985ef9c01c6fa9 Author: Steffen Schümann <s.schuemann@pobox.com> Date: Thu May 2 09:01:15 2019 +0200 Add path parameters to filesystem_error::what
This commit is contained in:
parent
da215a8c96
commit
dc37276a9a
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/build*/
|
/build*/
|
||||||
|
.vscode/
|
||||||
|
@ -25,7 +25,10 @@ target_compile_options(ghc_filesystem INTERFACE "$<$<CXX_COMPILER_ID:MSVC>:/utf-
|
|||||||
|
|
||||||
get_directory_property(hasParent PARENT_DIRECTORY)
|
get_directory_property(hasParent PARENT_DIRECTORY)
|
||||||
if(NOT hasParent)
|
if(NOT hasParent)
|
||||||
enable_testing()
|
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
add_subdirectory(test)
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||||
add_subdirectory(examples)
|
include(GhcHelper)
|
||||||
|
enable_testing()
|
||||||
|
add_subdirectory(test)
|
||||||
|
add_subdirectory(examples)
|
||||||
endif()
|
endif()
|
||||||
|
15
README.md
15
README.md
@ -402,9 +402,8 @@ But this makes `fs::copy` with `fs::copy_options::create_symlinks` or `fs::copy_
|
|||||||
just a more complicated syntax for the `fs::create_symlink` or `fs::create_hardlink` operation
|
just a more complicated syntax for the `fs::create_symlink` or `fs::create_hardlink` operation
|
||||||
and I don't want to believe, that this was the intention of the original writing.
|
and I don't want to believe, that this was the intention of the original writing.
|
||||||
As there is another issue related to copy, with a different take on the description,
|
As there is another issue related to copy, with a different take on the description,
|
||||||
I keep my version the way I read the description, as it is not contradicting the standard and useful. Let's see
|
*Note:* With v1.1.2 I decided to integrate a behavior switch for this and make the LWG #2682
|
||||||
what final solution the LWG comes up with in the end.
|
the default.
|
||||||
|
|
||||||
|
|
||||||
## Open Issues
|
## Open Issues
|
||||||
|
|
||||||
@ -446,6 +445,16 @@ to the expected behavior.
|
|||||||
`fs::recursive_directory_iterator` could run into endless loops,
|
`fs::recursive_directory_iterator` could run into endless loops,
|
||||||
the methods depth() and pop() had issues and the copy behaviour and
|
the methods depth() and pop() had issues and the copy behaviour and
|
||||||
`input_iterator_tag` conformance was broken, added tests
|
`input_iterator_tag` conformance was broken, added tests
|
||||||
|
* Restructured some CMake code into a macro to ease the support for
|
||||||
|
C++17 std::filesystem builds of tests and examples for interoperability
|
||||||
|
checks.
|
||||||
|
* Some fixes on Windows tests to ease interoperability test runs.
|
||||||
|
* Reduced noise on `fs::weakly_canonical()` tests against `std::fs`
|
||||||
|
* Added simple `du` example showing the `recursive_directory_iterator`
|
||||||
|
used to add the sizes of files in a directory tree.
|
||||||
|
* Added error checking in `fs::file_time_type` test helpers
|
||||||
|
* `fs::copy()` now conforms LWG #2682, disallowing the use of
|
||||||
|
`copy_option::create_symlinks' to be used on directories
|
||||||
|
|
||||||
### [v1.1.0](https://github.com/gulrak/filesystem/releases/tag/v1.1.0)
|
### [v1.1.0](https://github.com/gulrak/filesystem/releases/tag/v1.1.0)
|
||||||
|
|
||||||
|
36
cmake/GhcHelper.cmake
Normal file
36
cmake/GhcHelper.cmake
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
macro(AddExecutableWithStdFS targetName)
|
||||||
|
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
|
||||||
|
if(APPLE)
|
||||||
|
include_directories(/usr/local/opt/llvm/include)
|
||||||
|
link_directories(/usr/local/opt/llvm/lib)
|
||||||
|
endif()
|
||||||
|
add_executable(${targetName} ${ARGN})
|
||||||
|
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17)
|
||||||
|
if(APPLE)
|
||||||
|
target_link_libraries(${targetName} -lc++fs)
|
||||||
|
else()
|
||||||
|
target_compile_options(${targetName} PRIVATE "-stdlib=libc++")
|
||||||
|
target_link_libraries(${targetName} -stdlib=libc++ -lc++fs)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries(${targetName} -lc++fs)
|
||||||
|
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0))
|
||||||
|
add_executable(${targetName} ${ARGN})
|
||||||
|
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17)
|
||||||
|
target_link_libraries(${targetName} -lstdc++fs)
|
||||||
|
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15))
|
||||||
|
add_executable(${targetName} ${ARGN})
|
||||||
|
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17)
|
||||||
|
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||||
|
target_compile_options(${targetName} PRIVATE "/Zc:__cplusplus")
|
||||||
|
target_compile_definitions(${targetName} PRIVATE USE_STD_FS _CRT_SECURE_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endmacro()
|
@ -4,34 +4,9 @@ target_link_libraries(fs_dir ghc_filesystem)
|
|||||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
target_compile_definitions(fs_dir PRIVATE _CRT_SECURE_NO_WARNINGS)
|
target_compile_definitions(fs_dir PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
AddExecutableWithStdFS(std_fs_dir dir.cpp)
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
|
add_executable(fs_du du.cpp)
|
||||||
if(APPLE)
|
target_link_libraries(fs_du ghc_filesystem)
|
||||||
include_directories(/usr/local/opt/llvm/include)
|
AddExecutableWithStdFS(std_fs_du du.cpp)
|
||||||
link_directories(/usr/local/opt/llvm/lib)
|
|
||||||
endif()
|
|
||||||
add_executable(std_fs_dir dir.cpp)
|
|
||||||
set_property(TARGET std_fs_dir PROPERTY CXX_STANDARD 17)
|
|
||||||
if(APPLE)
|
|
||||||
target_link_libraries(std_fs_dir -lc++fs)
|
|
||||||
else()
|
|
||||||
target_compile_options(std_fs_dir PRIVATE "-stdlib=libc++")
|
|
||||||
target_link_libraries(std_fs_dir -stdlib=libc++ -lc++fs)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(std_fs_dir -lc++fs)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0))
|
|
||||||
add_executable(std_fs_dir dir.cpp)
|
|
||||||
set_property(TARGET std_fs_dir PROPERTY CXX_STANDARD 17)
|
|
||||||
target_link_libraries(std_fs_dir -lstdc++fs)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15))
|
|
||||||
add_executable(std_fs_dir dir.cpp)
|
|
||||||
set_property(TARGET std_fs_dir PROPERTY CXX_STANDARD 17)
|
|
||||||
set_property(TARGET std_fs_dir PROPERTY CXX_STANDARD_REQUIRED ON)
|
|
||||||
target_compile_options(std_fs_dir PRIVATE "/Zc:__cplusplus")
|
|
||||||
target_compile_definitions(std_fs_dir PRIVATE _CRT_SECURE_NO_WARNINGS)
|
|
||||||
endif()
|
|
||||||
|
57
examples/du.cpp
Normal file
57
examples/du.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include) && __has_include(<filesystem>)
|
||||||
|
#include <filesystem>
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
#else
|
||||||
|
#include <ghc/filesystem.hpp>
|
||||||
|
namespace fs = ghc::filesystem;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
#ifdef GHC_FILESYSTEM_VERSION
|
||||||
|
fs::u8arguments u8guard(argc, argv);
|
||||||
|
if(!u8guard.valid()) {
|
||||||
|
std::cerr << "Invalid character encoding, UTF-8 based encoding needed." << std::endl;
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(argc > 2) {
|
||||||
|
std::cerr << "USAGE: du <path>" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fs::path dir{"."};
|
||||||
|
if(argc == 2) {
|
||||||
|
dir = fs::u8path(argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t totalSize = 0;
|
||||||
|
int totalDirs = 0;
|
||||||
|
int totalFiles = 0;
|
||||||
|
int maxDepth = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto rdi = fs::recursive_directory_iterator(dir);
|
||||||
|
for(auto de : rdi) {
|
||||||
|
if(rdi.depth() > maxDepth) {
|
||||||
|
maxDepth = rdi.depth();
|
||||||
|
}
|
||||||
|
if(de.is_regular_file()) {
|
||||||
|
totalSize += de.file_size();
|
||||||
|
++totalFiles;
|
||||||
|
}
|
||||||
|
else if(de.is_directory()) {
|
||||||
|
++totalDirs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(fs::filesystem_error fe) {
|
||||||
|
std::cerr << "Error: " << fe.what() << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
std::cout << totalSize << " bytes in " << totalFiles << " and " << totalDirs << " directories, maximum depth: " << maxDepth << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
@ -92,6 +92,7 @@
|
|||||||
|
|
||||||
#ifdef GHC_OS_WINDOWS
|
#ifdef GHC_OS_WINDOWS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
// additional includes
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -142,9 +143,20 @@
|
|||||||
#include <system_error>
|
#include <system_error>
|
||||||
#endif // GHC_EXPAND_IMPL
|
#endif // GHC_EXPAND_IMPL
|
||||||
|
|
||||||
// configure LWG conformance (see README.md)
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp):
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// LWG #2682 disables the since then invalid use of the copy option create_symlinks on directories
|
||||||
|
// configure LWG conformance ()
|
||||||
|
#define LWG_2682_BEHAVIOUR
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// LWG #2395 makes crate_directory/create_directories not emit an error if there is a regular
|
||||||
|
// file with that name, it is superceded by P1164R1, so only activate if really needed
|
||||||
// #define LWG_2935_BEHAVIOUR
|
// #define LWG_2935_BEHAVIOUR
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2)
|
||||||
#define LWG_2937_BEHAVIOUR
|
#define LWG_2937_BEHAVIOUR
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
|
// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch)
|
||||||
#define GHC_FILESYSTEM_VERSION 10101L
|
#define GHC_FILESYSTEM_VERSION 10101L
|
||||||
@ -1014,6 +1026,7 @@ enum class portable_error {
|
|||||||
not_supported,
|
not_supported,
|
||||||
not_implemented,
|
not_implemented,
|
||||||
invalid_argument,
|
invalid_argument,
|
||||||
|
is_a_directory,
|
||||||
};
|
};
|
||||||
GHC_FS_API std::error_code make_error_code(portable_error err);
|
GHC_FS_API std::error_code make_error_code(portable_error err);
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -1038,6 +1051,8 @@ GHC_INLINE std::error_code make_error_code(portable_error err)
|
|||||||
return std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category());
|
return std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category());
|
||||||
case portable_error::invalid_argument:
|
case portable_error::invalid_argument:
|
||||||
return std::error_code(ERROR_INVALID_PARAMETER, std::system_category());
|
return std::error_code(ERROR_INVALID_PARAMETER, std::system_category());
|
||||||
|
case portable_error::is_a_directory:
|
||||||
|
return std::error_code(ERROR_DIRECTORY_NOT_SUPPORTED, std::system_category());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
switch (err) {
|
switch (err) {
|
||||||
@ -1053,6 +1068,8 @@ GHC_INLINE std::error_code make_error_code(portable_error err)
|
|||||||
return std::error_code(ENOSYS, std::system_category());
|
return std::error_code(ENOSYS, std::system_category());
|
||||||
case portable_error::invalid_argument:
|
case portable_error::invalid_argument:
|
||||||
return std::error_code(EINVAL, std::system_category());
|
return std::error_code(EINVAL, std::system_category());
|
||||||
|
case portable_error::is_a_directory:
|
||||||
|
return std::error_code(EISDIR, std::system_category());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return std::error_code();
|
return std::error_code();
|
||||||
@ -1648,9 +1665,9 @@ GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::er
|
|||||||
GHC_INLINE bool is_not_found_error(std::error_code& ec)
|
GHC_INLINE bool is_not_found_error(std::error_code& ec)
|
||||||
{
|
{
|
||||||
#ifdef GHC_OS_WINDOWS
|
#ifdef GHC_OS_WINDOWS
|
||||||
return ec.value() == ERROR_FILE_NOT_FOUND || ec.value() == ERROR_PATH_NOT_FOUND;
|
return ec.value() == ERROR_FILE_NOT_FOUND || ec.value() == ERROR_PATH_NOT_FOUND || ec.value() == ERROR_INVALID_NAME;
|
||||||
#else
|
#else
|
||||||
return ec.value() == ENOENT;
|
return ec.value() == ENOENT || ec.value() == ENOTDIR;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1672,7 +1689,7 @@ GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uin
|
|||||||
fs.type(file_type::symlink);
|
fs.type(file_type::symlink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ec.value() == ERROR_FILE_NOT_FOUND) {
|
if (detail::is_not_found_error(ec)) {
|
||||||
return file_status(file_type::not_found);
|
return file_status(file_type::not_found);
|
||||||
}
|
}
|
||||||
return ec ? file_status(file_type::none) : fs;
|
return ec ? file_status(file_type::none) : fs;
|
||||||
@ -1687,9 +1704,8 @@ GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uin
|
|||||||
file_status f_s = detail::file_status_from_st_mode(fs.st_mode);
|
file_status f_s = detail::file_status_from_st_mode(fs.st_mode);
|
||||||
return f_s;
|
return f_s;
|
||||||
}
|
}
|
||||||
auto error = errno;
|
ec = std::error_code(errno, std::system_category());
|
||||||
ec = std::error_code(error, std::system_category());
|
if (detail::is_not_found_error(ec)) {
|
||||||
if (error == ENOENT) {
|
|
||||||
return file_status(file_type::not_found, perms::unknown);
|
return file_status(file_type::not_found, perms::unknown);
|
||||||
}
|
}
|
||||||
return file_status(file_type::none);
|
return file_status(file_type::none);
|
||||||
@ -1757,9 +1773,8 @@ GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status
|
|||||||
return fs;
|
return fs;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto error = errno;
|
|
||||||
ec = std::error_code(errno, std::system_category());
|
ec = std::error_code(errno, std::system_category());
|
||||||
if (error == ENOENT) {
|
if (detail::is_not_found_error(ec)) {
|
||||||
return file_status(file_type::not_found, perms::unknown);
|
return file_status(file_type::not_found, perms::unknown);
|
||||||
}
|
}
|
||||||
return file_status(file_type::none);
|
return file_status(file_type::none);
|
||||||
@ -1800,6 +1815,7 @@ GHC_INLINE u8arguments::u8arguments(int& argc, char**& argv)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// 30.10.8.4.1 constructors and destructor
|
// 30.10.8.4.1 constructors and destructor
|
||||||
|
|
||||||
@ -2741,6 +2757,9 @@ GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const
|
|||||||
, _ec(ec)
|
, _ec(ec)
|
||||||
, _p1(p1)
|
, _p1(p1)
|
||||||
{
|
{
|
||||||
|
if (!_p1.empty()) {
|
||||||
|
_what_arg += ": '" + _p1.u8string() + "'";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec)
|
GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec)
|
||||||
@ -2750,6 +2769,12 @@ GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const
|
|||||||
, _p1(p1)
|
, _p1(p1)
|
||||||
, _p2(p2)
|
, _p2(p2)
|
||||||
{
|
{
|
||||||
|
if (!_p1.empty()) {
|
||||||
|
_what_arg += ": '" + _p1.u8string() + "'";
|
||||||
|
}
|
||||||
|
if (!_p2.empty()) {
|
||||||
|
_what_arg += ", '" + _p2.u8string() + "'";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GHC_INLINE const path& filesystem_error::path1() const noexcept
|
GHC_INLINE const path& filesystem_error::path1() const noexcept
|
||||||
@ -2868,7 +2893,7 @@ GHC_INLINE path canonical(const path& p, std::error_code& ec)
|
|||||||
result = result.parent_path();
|
result = result.parent_path();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if ((result/pe).string().length() <= root.string().length()) {
|
else if ((result / pe).string().length() <= root.string().length()) {
|
||||||
result /= pe;
|
result /= pe;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2958,10 +2983,10 @@ GHC_INLINE void copy(const path& from, const path& to, copy_options options, std
|
|||||||
}
|
}
|
||||||
else if (is_regular_file(fs_from)) {
|
else if (is_regular_file(fs_from)) {
|
||||||
if ((options & copy_options::directories_only) == copy_options::none) {
|
if ((options & copy_options::directories_only) == copy_options::none) {
|
||||||
if ((options & copy_options::create_symlinks) == copy_options::create_symlinks) {
|
if ((options & copy_options::create_symlinks) != copy_options::none) {
|
||||||
create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec);
|
create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec);
|
||||||
}
|
}
|
||||||
else if ((options & copy_options::create_hard_links) == copy_options::create_hard_links) {
|
else if ((options & copy_options::create_hard_links) != copy_options::none) {
|
||||||
create_hard_link(from, to, ec);
|
create_hard_link(from, to, ec);
|
||||||
}
|
}
|
||||||
else if (is_directory(fs_to)) {
|
else if (is_directory(fs_to)) {
|
||||||
@ -2972,7 +2997,12 @@ GHC_INLINE void copy(const path& from, const path& to, copy_options options, std
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (is_directory(fs_from) && (options == copy_options::none || (options & copy_options::recursive) == copy_options::recursive)) {
|
#ifdef LWG_2682_BEHAVIOUR
|
||||||
|
else if(is_directory(fs_from) && (options & copy_options::create_symlinks) != copy_options::none) {
|
||||||
|
ec = detail::make_error_code(detail::portable_error::is_a_directory);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (is_directory(fs_from) && (options == copy_options::none || (options & copy_options::recursive) != copy_options::none)) {
|
||||||
if (!exists(fs_to)) {
|
if (!exists(fs_to)) {
|
||||||
create_directory(to, from, ec);
|
create_directory(to, from, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
@ -4077,7 +4107,8 @@ GHC_INLINE path weakly_canonical(const path& p, std::error_code& ec) noexcept
|
|||||||
bool scan = true;
|
bool scan = true;
|
||||||
for (auto pe : p) {
|
for (auto pe : p) {
|
||||||
if (scan) {
|
if (scan) {
|
||||||
if (exists(result / pe, ec)) {
|
std::error_code tec;
|
||||||
|
if (exists(result / pe, tec)) {
|
||||||
result /= pe;
|
result /= pe;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -18,34 +18,7 @@ if(CMAKE_GENERATOR STREQUAL Xcode)
|
|||||||
target_link_libraries(filesystem_test_cov PUBLIC ghc_filesystem PRIVATE --coverage)
|
target_link_libraries(filesystem_test_cov PUBLIC ghc_filesystem PRIVATE --coverage)
|
||||||
endif()
|
endif()
|
||||||
ParseAndAddCatchTests(filesystem_test filesystem_test)
|
ParseAndAddCatchTests(filesystem_test filesystem_test)
|
||||||
|
AddExecutableWithStdFS(std_filesystem_test filesystem_test.cpp catch.hpp)
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
|
|
||||||
if(APPLE)
|
|
||||||
include_directories(/usr/local/opt/llvm/include)
|
|
||||||
link_directories(/usr/local/opt/llvm/lib)
|
|
||||||
endif()
|
|
||||||
add_executable(std_filesystem_test filesystem_test.cpp catch.hpp)
|
|
||||||
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
|
|
||||||
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS)
|
|
||||||
if(APPLE)
|
|
||||||
target_link_libraries(std_filesystem_test -lc++fs)
|
|
||||||
else()
|
|
||||||
target_compile_options(std_filesystem_test PRIVATE "-stdlib=libc++")
|
|
||||||
target_link_libraries(std_filesystem_test -stdlib=libc++ -lc++fs)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0))
|
|
||||||
add_executable(std_filesystem_test filesystem_test.cpp catch.hpp)
|
|
||||||
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
|
|
||||||
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS)
|
|
||||||
target_link_libraries(std_filesystem_test -lstdc++fs)
|
|
||||||
endif()
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15))
|
|
||||||
add_executable(std_filesystem_test filesystem_test.cpp catch.hpp)
|
|
||||||
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
|
|
||||||
target_compile_options(std_filesystem_test PRIVATE "/Zc:__cplusplus")
|
|
||||||
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS _CRT_SECURE_NO_WARNINGS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(multifile_test multi1.cpp multi2.cpp catch.hpp)
|
add_executable(multifile_test multi1.cpp multi2.cpp catch.hpp)
|
||||||
target_link_libraries(multifile_test ghc_filesystem)
|
target_link_libraries(multifile_test ghc_filesystem)
|
||||||
|
@ -88,8 +88,19 @@ using fstream = ghc::filesystem::fstream;
|
|||||||
#endif
|
#endif
|
||||||
#include "catch.hpp"
|
#include "catch.hpp"
|
||||||
|
|
||||||
//#define TEST_LWG_2935_BEHAVIOUR
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// Behaviour Switches (should match the config in ghc/filesystem.hpp):
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// LWG #2682 disables the since then invalid use of the copy option create_symlinks on directories
|
||||||
|
#define TEST_LWG_2682_BEHAVIOUR
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// LWG #2395 makes crate_directory/create_directories not emit an error if there is a regular
|
||||||
|
// file with that name, it is superceded by P1164R1, so only activate if really needed
|
||||||
|
// #define TEST_LWG_2935_BEHAVIOUR
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2)
|
||||||
#define TEST_LWG_2937_BEHAVIOUR
|
#define TEST_LWG_2937_BEHAVIOUR
|
||||||
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
template <typename TP>
|
template <typename TP>
|
||||||
std::time_t to_time_t(TP tp)
|
std::time_t to_time_t(TP tp)
|
||||||
@ -474,13 +485,14 @@ TEST_CASE("30.10.8.4.6 path native format observers", "[filesystem][path][fs.pat
|
|||||||
{
|
{
|
||||||
#ifdef GHC_OS_WINDOWS
|
#ifdef GHC_OS_WINDOWS
|
||||||
#ifdef IS_WCHAR_PATH
|
#ifdef IS_WCHAR_PATH
|
||||||
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").native() == fs::path::string_type(L"ä\\€"));
|
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").native() == fs::path::string_type(L"\u00E4\\\u20AC"));
|
||||||
|
// CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").string() == std::string("ä\\€")); // MSVCs returns local DBCS encoding
|
||||||
#else
|
#else
|
||||||
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").native() == fs::path::string_type("\xc3\xa4\\\xe2\x82\xac"));
|
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").native() == fs::path::string_type("\xc3\xa4\\\xe2\x82\xac"));
|
||||||
|
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").string() == std::string("\xc3\xa4\\\xe2\x82\xac"));
|
||||||
CHECK(!::strcmp(fs::u8path("\xc3\xa4\\\xe2\x82\xac").c_str(), "\xc3\xa4\\\xe2\x82\xac"));
|
CHECK(!::strcmp(fs::u8path("\xc3\xa4\\\xe2\x82\xac").c_str(), "\xc3\xa4\\\xe2\x82\xac"));
|
||||||
CHECK((std::string)fs::u8path("\xc3\xa4\\\xe2\x82\xac") == std::string("\xc3\xa4\\\xe2\x82\xac"));
|
CHECK((std::string)fs::u8path("\xc3\xa4\\\xe2\x82\xac") == std::string("\xc3\xa4\\\xe2\x82\xac"));
|
||||||
#endif
|
#endif
|
||||||
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").string() == std::string("\xc3\xa4\\\xe2\x82\xac"));
|
|
||||||
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").wstring() == std::wstring(L"\u00E4\\\u20AC"));
|
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").wstring() == std::wstring(L"\u00E4\\\u20AC"));
|
||||||
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").u8string() == std::string("\xc3\xa4\\\xe2\x82\xac"));
|
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").u8string() == std::string("\xc3\xa4\\\xe2\x82\xac"));
|
||||||
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").u16string() == std::u16string(u"\u00E4\\\u20AC"));
|
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").u16string() == std::u16string(u"\u00E4\\\u20AC"));
|
||||||
@ -502,7 +514,9 @@ TEST_CASE("30.10.8.4.6 path native format observers", "[filesystem][path][fs.pat
|
|||||||
TEST_CASE("30.10.8.4.7 path generic format observers", "[filesystem][path][fs.path.generic.obs]")
|
TEST_CASE("30.10.8.4.7 path generic format observers", "[filesystem][path][fs.path.generic.obs]")
|
||||||
{
|
{
|
||||||
#ifdef GHC_OS_WINDOWS
|
#ifdef GHC_OS_WINDOWS
|
||||||
|
#ifndef IS_WCHAR_PATH
|
||||||
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_string() == std::string("\xc3\xa4/\xe2\x82\xac"));
|
CHECK(fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_string() == std::string("\xc3\xa4/\xe2\x82\xac"));
|
||||||
|
#endif
|
||||||
#ifndef USE_STD_FS
|
#ifndef USE_STD_FS
|
||||||
auto t = fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_string<char, std::char_traits<char>, TestAllocator<char>>();
|
auto t = fs::u8path("\xc3\xa4\\\xe2\x82\xac").generic_string<char, std::char_traits<char>, TestAllocator<char>>();
|
||||||
CHECK(t.c_str() == std::string("\xc3\xa4/\xe2\x82\xac"));
|
CHECK(t.c_str() == std::string("\xc3\xa4/\xe2\x82\xac"));
|
||||||
@ -1361,6 +1375,9 @@ TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
|
|||||||
generateFile("dir1/file2");
|
generateFile("dir1/file2");
|
||||||
fs::create_directory("dir1/dir2");
|
fs::create_directory("dir1/dir2");
|
||||||
generateFile("dir1/dir2/file3");
|
generateFile("dir1/dir2/file3");
|
||||||
|
#ifdef TEST_LWG_2682_BEHAVIOUR
|
||||||
|
REQUIRE_THROWS_AS(fs::copy("dir1", "dir3", fs::copy_options::create_symlinks | fs::copy_options::recursive), fs::filesystem_error);
|
||||||
|
#else
|
||||||
REQUIRE_NOTHROW(fs::copy("dir1", "dir3", fs::copy_options::create_symlinks | fs::copy_options::recursive));
|
REQUIRE_NOTHROW(fs::copy("dir1", "dir3", fs::copy_options::create_symlinks | fs::copy_options::recursive));
|
||||||
CHECK(!ec);
|
CHECK(!ec);
|
||||||
CHECK(fs::exists("dir3/file1"));
|
CHECK(fs::exists("dir3/file1"));
|
||||||
@ -1369,6 +1386,7 @@ TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
|
|||||||
CHECK(fs::is_symlink("dir3/file2"));
|
CHECK(fs::is_symlink("dir3/file2"));
|
||||||
CHECK(fs::exists("dir3/dir2/file3"));
|
CHECK(fs::exists("dir3/dir2/file3"));
|
||||||
CHECK(fs::is_symlink("dir3/dir2/file3"));
|
CHECK(fs::is_symlink("dir3/dir2/file3"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
TemporaryDirectory t(TempOpt::change_path);
|
TemporaryDirectory t(TempOpt::change_path);
|
||||||
@ -1471,7 +1489,7 @@ TEST_CASE("30.10.15.6 create_directories", "[filesystem][operations][fs.op.creat
|
|||||||
CHECK(!fs::is_directory(p));
|
CHECK(!fs::is_directory(p));
|
||||||
CHECK(!fs::create_directories(p, ec));
|
CHECK(!fs::create_directories(p, ec));
|
||||||
#else
|
#else
|
||||||
INFO("This test expects conformance predating LWG #2935 result. (As suggested by WG21 P1164R0, implemented by GCC with issue #86910.)");
|
INFO("This test expects conformance with P1164R1. (implemented by GCC with issue #86910.)");
|
||||||
p = t.path() / "testfile";
|
p = t.path() / "testfile";
|
||||||
generateFile(p);
|
generateFile(p);
|
||||||
CHECK(fs::is_regular_file(p));
|
CHECK(fs::is_regular_file(p));
|
||||||
@ -1515,7 +1533,7 @@ TEST_CASE("30.10.15.7 create_directory", "[filesystem][operations][fs.op.create_
|
|||||||
CHECK(!fs::is_directory(p));
|
CHECK(!fs::is_directory(p));
|
||||||
CHECK(!fs::create_directories(p, ec));
|
CHECK(!fs::create_directories(p, ec));
|
||||||
#else
|
#else
|
||||||
INFO("This test expects conformance predating LWG #2935 result. (As suggested by WG21 P1164R0, implemented by GCC with issue #86910.)");
|
INFO("This test expects conformance with P1164R1. (implemented by GCC with issue #86910.)");
|
||||||
p = t.path() / "testfile";
|
p = t.path() / "testfile";
|
||||||
generateFile(p);
|
generateFile(p);
|
||||||
CHECK(fs::is_regular_file(p));
|
CHECK(fs::is_regular_file(p));
|
||||||
@ -1618,7 +1636,7 @@ TEST_CASE("30.10.15.12 equivalent", "[filesystem][operations][fs.op.equivalent]"
|
|||||||
INFO("This test expects LWG #2937 result conformance.");
|
INFO("This test expects LWG #2937 result conformance.");
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
CHECK_THROWS_AS(fs::equivalent("foo", "foo3"), fs::filesystem_error);
|
REQUIRE_THROWS_AS(fs::equivalent("foo", "foo3"), fs::filesystem_error);
|
||||||
CHECK_NOTHROW(result = fs::equivalent("foo", "foo3", ec));
|
CHECK_NOTHROW(result = fs::equivalent("foo", "foo3", ec));
|
||||||
CHECK(!result);
|
CHECK(!result);
|
||||||
CHECK(ec);
|
CHECK(ec);
|
||||||
@ -1636,7 +1654,7 @@ TEST_CASE("30.10.15.12 equivalent", "[filesystem][operations][fs.op.equivalent]"
|
|||||||
INFO("This test expects conformance predating LWG #2937 result.");
|
INFO("This test expects conformance predating LWG #2937 result.");
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
CHECK_NOTHROW(result = fs::equivalent("foo", "foo3"));
|
REQUIRE_NOTHROW(result = fs::equivalent("foo", "foo3"));
|
||||||
CHECK(!result);
|
CHECK(!result);
|
||||||
CHECK_NOTHROW(result = fs::equivalent("foo", "foo3", ec));
|
CHECK_NOTHROW(result = fs::equivalent("foo", "foo3", ec));
|
||||||
CHECK(!result);
|
CHECK(!result);
|
||||||
@ -2356,9 +2374,18 @@ TEST_CASE("30.10.15.38 temporary_directory_path", "[filesystem][operations][fs.o
|
|||||||
|
|
||||||
TEST_CASE("30.10.15.39 weakly_canonical", "[filesystem][operations][fs.op.weakly_canonical]")
|
TEST_CASE("30.10.15.39 weakly_canonical", "[filesystem][operations][fs.op.weakly_canonical]")
|
||||||
{
|
{
|
||||||
CHECK(fs::weakly_canonical("foo/bar") == "foo/bar");
|
INFO("This might fail on std::implementations that return fs::current_path() for fs::canonical(\"\")");
|
||||||
CHECK(fs::weakly_canonical("foo/./bar") == "foo/bar");
|
CHECK(fs::weakly_canonical("") == ".");
|
||||||
CHECK(fs::weakly_canonical("foo/../bar") == "bar");
|
if(fs::weakly_canonical("") == ".") {
|
||||||
|
CHECK(fs::weakly_canonical("foo/bar") == "foo/bar");
|
||||||
|
CHECK(fs::weakly_canonical("foo/./bar") == "foo/bar");
|
||||||
|
CHECK(fs::weakly_canonical("foo/../bar") == "bar");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CHECK(fs::weakly_canonical("foo/bar") == fs::current_path() / "foo/bar");
|
||||||
|
CHECK(fs::weakly_canonical("foo/./bar") == fs::current_path() / "foo/bar");
|
||||||
|
CHECK(fs::weakly_canonical("foo/../bar") == fs::current_path() / "bar");
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
TemporaryDirectory t(TempOpt::change_path);
|
TemporaryDirectory t(TempOpt::change_path);
|
||||||
@ -2369,8 +2396,10 @@ TEST_CASE("30.10.15.39 weakly_canonical", "[filesystem][operations][fs.op.weakly
|
|||||||
CHECK(fs::weakly_canonical(dir) == dir);
|
CHECK(fs::weakly_canonical(dir) == dir);
|
||||||
CHECK(fs::weakly_canonical(rel) == dir);
|
CHECK(fs::weakly_canonical(rel) == dir);
|
||||||
CHECK(fs::weakly_canonical(dir / "f0") == dir / "f0");
|
CHECK(fs::weakly_canonical(dir / "f0") == dir / "f0");
|
||||||
|
CHECK(fs::weakly_canonical(dir / "f0/") == dir / "f0/");
|
||||||
CHECK(fs::weakly_canonical(dir / "f1") == dir / "f1");
|
CHECK(fs::weakly_canonical(dir / "f1") == dir / "f1");
|
||||||
CHECK(fs::weakly_canonical(rel / "f0") == dir / "f0");
|
CHECK(fs::weakly_canonical(rel / "f0") == dir / "f0");
|
||||||
|
CHECK(fs::weakly_canonical(rel / "f0/") == dir / "f0/");
|
||||||
CHECK(fs::weakly_canonical(rel / "f1") == dir / "f1");
|
CHECK(fs::weakly_canonical(rel / "f1") == dir / "f1");
|
||||||
CHECK(fs::weakly_canonical(rel / "./f0") == dir / "f0");
|
CHECK(fs::weakly_canonical(rel / "./f0") == dir / "f0");
|
||||||
CHECK(fs::weakly_canonical(rel / "./f1") == dir / "f1");
|
CHECK(fs::weakly_canonical(rel / "./f1") == dir / "f1");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user