Compare commits

...

133 Commits

Author SHA1 Message Date
Steffen Schümann
9fda7b0afb
Update build_cmake.yml, removing macOS build versions not supported by GitHub 2025-01-23 07:26:01 +01:00
Steffen Schümann
076592ce6e
Merge pull request #188 from bbannier/topic/bbannier/getcwd-with-NULL-buf
Avoid GNU `getcwd` extension behavior
2025-01-07 21:00:06 +01:00
Steffen Schümann
157feb3651
Merge pull request #190 from dpogue/wundef-fix
Check macros are defined before use
2025-01-05 17:01:49 +01:00
Darryl Pogue
f08e8b0064
Check macros are defined before use
This resolves warnings when compiling with -wundef (and errors when
combined with -werror).
2025-01-04 21:45:29 -08:00
Benjamin Bannier
99c3500205 Replace EOL centos CI with rockylinux
centos7 has reached EOL on 2024-06-30, centos8 on 2021-10-31. In
practical terms this means that their package repositories are offline
for the foreseeable future and the CI tasks making use of them might
never run again.

This patch replaces the existing CI jobs on centos7/centos8 with jobs on
rockylinux8/9. Since rockylinux is an open source variant similar to
RHEL this should provide testing with similar spirit. In contrast to
centos, rockylinux does provide very granular tagging of releases which
if used would help avoid breaking on e.g., subtle package changes in
their package repositories. I however did not use very precise tags in
the patch and instead went with broad "trains" for the 8 and 9 series;
I hope this minimizes maintenance overhead (e.g., bumping to new
releases) while still giving a good testing signal.
2024-12-18 15:45:33 +01:00
Benjamin Bannier
f43846877b Avoid GNU getcwd extension behavior
GNU `getcwd` can allocate a buffer if passed `NULL` for it. This is an
extension which is e.g., not recognized by clang-tidy-19's
`StdCLibraryFunctions` check[^1] which emits a diagnostic on a violated
precondition `buf != NULL`,

```
The 1st argument to 'getcwd' is NULL but should not be NULL [clang-analyzer-unix.StdCLibraryFunctions,-warnings-as-errors]
[build]  3987 |     std::unique_ptr<char, decltype(&std::free)> buffer{::getcwd(NULL, 0), std::free};
```

This patch modifies this use of `getcwd` with this extension behavior to
instead use `get_current_dir_name` which is also a GNU extension, but
does not trigger this diagnostic.

[^1]: https://clang.llvm.org/docs/analyzer/checkers.html#unix-stdclibraryfunctions-c
2024-12-18 15:26:19 +01:00
Steffen Schuemann
b1982f06c8 work on ci scripts 2024-04-27 12:20:18 +02:00
Steffen Schuemann
fbc5d213fc work on ci scripts 2024-04-27 12:07:57 +02:00
Steffen Schuemann
72a03b3c6d work on ci scripts 2024-04-27 12:00:20 +02:00
Steffen Schuemann
9fe68b91c7 work on ci scripts 2024-04-27 10:41:56 +02:00
Steffen Schuemann
56776c92f7 work on ci scripts 2024-04-27 09:58:19 +02:00
gulrak
42ea4fc615
Merge pull request #179 from vgeorgiev/lexically_relative_fix
Fix lexically_relative return when base path evaluates to *this
2024-02-29 07:55:33 +01:00
vgeorgiev
eeed314237
Fix handling of trailing slash 2024-02-21 17:55:00 -06:00
vgeorgiev
768b5cb11b
Fix lexically_relative return when base path evaluates to *this 2024-02-21 11:07:19 -06:00
gulrak
2fc4b46375
Merge pull request #177 from noexcept/master
fix infinite loop when errno is EINTR
2024-01-01 21:48:11 +01:00
noexcept
fc19b58459 fix infinite loop when errno is EINTR 2023-12-20 11:56:57 +00:00
gulrak
f19cbbbd31
Merge pull request #176 from cpsauer/patch-1
Add reference to Bazel rules
2023-11-16 18:08:10 +01:00
Chris Sauer
0ef214a7a0
Add reference to Bazel rules 2023-11-15 14:18:03 -08:00
gulrak
fcea331ebb
Merge pull request #174 from bugdea1er/remove-debug-info
Removed debug information from CMakeLists.txt
2023-09-16 10:11:14 +02:00
gulrak
1ab54e53cc
Merge pull request #172 from rikyoz/glibcxx_wchar_streams
Allow wchar_t constructors of fstreams on Windows when using libstdc++
2023-09-16 10:09:38 +02:00
bugdea1er
58e983167c Removed debug information from CMakeLists.txt 2023-09-11 14:54:59 +03:00
Oz
c4683aa4a1
Allow wchar_t constructors of iostreams on Windows when using libstdc++ 2023-09-05 09:00:51 +02:00
gulrak
144954ff4e
Merge pull request #167 from cpsauer/dynamic-selection-more-apple-platforms 2023-07-30 19:40:45 +02:00
Chris Sauer
48d46cccef Improve apple conditionals in filesystem.hpp
Two changes:
- (minor) Rename GHC_OS_MACOS -> GHC_OS_APPLE, since it is defined all apple platforms (iOS, watchOS, etc.), not just macOS.
- Changed the preprocessor conditional in last_write_time to align with its presumed intent. Previously, it would always have been true, which can't be intentional, because the *_OS_VERSION_MIN_REQUIRED is undefined and thus zero for platforms besides the current one, and therefore less than the constants--except for on very old SDKs where, e.g., MAC_OS_X_VERSION_10_13  and others would be undefined and therefore 0 and therefore making the clause false when it needed to be true. Therefore, I changed the conditions to be parallel to those in the dynamic selection headers, checking for the undefined, zero case and hardcoding the version values to support old SDKs.
2023-07-26 23:07:09 -07:00
Chris Sauer
23710d3b56 Remove conditional inclusion snippet in filesystem.hpp
Reduces duplication and tendency to get out of sync.
As evidence of the problem, the snippet had previously (before this PR) started to diverge. It seemed more prudent to delete than to fix, given the usage instructions seem to be centralized in the readme and the dynamic selection headers should probably be recommended anyway.
2023-07-26 21:56:08 -07:00
Chris Sauer
64f9c5a61a Switch internal includes to quoted relative
This makes project integration more flexible, allowing the drag-contents-of-directory project integration contemplated in the readme and allowing use via -iquote
2023-07-26 21:40:38 -07:00
Chris Sauer
a55c96a2ba Minor: seperated typo 2023-07-26 21:28:52 -07:00
Chris Sauer
aaaf381d9d Improvements to preprocessor conditions for falling back to std::filesystem
- Supports more Apple platforms, including future ones, which will always support std::filesystem, like with visionOS
- Simplifies cases.  Undefined preprocessor values are guaranteed to default evaluate to 0
- Moves <Availability.h> include inside conditional, avoiding the include where not needed.
- Removes reference to wchar for std headers on windows, which seemed to be out of date, since the define it might have been referring to was commented
- (And some other small things.)
2023-07-26 21:26:33 -07:00
Steffen Schuemann
72a76d774e head version bumped to wip version 2023-05-18 10:39:25 +02:00
Steffen Schuemann
e5ae1bd3e3 refs #166, ".." does not have extension ." 2023-05-17 07:18:52 +02:00
Steffen Schuemann
8a2edd6d92 Version bump to v1.5.14 2023-03-05 13:06:50 +01:00
gulrak
e9e32f8830
Merge pull request #161 from stilllman/cmake-alias-target
[cmake] Define alias ghcFilesystem::ghc_filesystem unconditionally
2023-03-05 12:22:04 +01:00
gulrak
9f61ee0eb5
Merge branch 'master' into cmake-alias-target 2023-03-05 11:17:55 +01:00
Steffen Schuemann
d1f0d79054 updated README.md 2023-03-04 16:42:22 +01:00
Steffen Schuemann
61176cd82a Merge branch 'feature-146-added-EINTR-handling' 2023-03-04 16:39:33 +01:00
Steffen Schuemann
78b746d901 update README.md 2023-03-04 15:19:18 +01:00
Steffen Schuemann
9df22d5396 refs #157, suppress unavoidable warning at cast for GetProcAddress on MSVC 2023-03-04 15:17:13 +01:00
Steffen Schuemann
9ffca3839f Updated README.md 2023-03-04 12:52:41 +01:00
Steffen Schuemann
2a81c2c355 refs #160, only enable install target by default if not subproject as documented 2023-03-04 12:43:22 +01:00
Steffen Schuemann
e3341b2f64 refs #146, fix mingw build issue 2023-03-04 12:03:12 +01:00
Steffen Schuemann
6a94e84da4 refs #151, stop throwing on fs:🇩🇪:refresh for broken symlinks, and added test 2023-03-04 09:59:16 +01:00
Steffen Schuemann
a7a6d930fb Updated README.md 2023-03-03 23:43:08 +01:00
Steffen Schuemann
7da9be91c9 test for permission copying 2023-03-03 23:42:44 +01:00
gulrak
e6b34e29bf
Merge pull request #149 from dvzrv/declare_version
Declare and export version from CMake
2023-03-03 17:49:35 +01:00
gulrak
b1ff2ce95e
Changed version to in-between releases version 1.5.13
As the master version is on that number it avoids confusion.
2023-03-03 17:48:35 +01:00
gulrak
3afbd9c315
Merge pull request #144 from actboy168/patch-2
copy_file also copies permissions
2023-03-03 17:35:47 +01:00
gulrak
de64decd91
Merge pull request #143 from actboy168/patch-1
Fixes skip_existing on fs::copy
2023-03-03 17:31:15 +01:00
gulrak
f3c1058928
Update CMakeLists.txt
The projects compatibility rule is that minor changes can be api changes, so I changed it to SameMinorVersion.
2023-03-03 06:53:13 +01:00
Steffen Schuemann
f3033c29fb refs #146, added EINTR handling to directory iteration and file copying 2023-03-03 06:44:58 +01:00
Steffen Schuemann
4041174f96 Disabled the defunct drone build. 2023-03-02 19:46:12 +01:00
Steffen Schuemann
c8113e14b1 Updated readme, bumped to wip version as preparation of upcoming release. 2023-03-02 19:19:22 +01:00
Steffen Schuemann
b6d302f5b9 Merge branch 'feature-156-posix-issue-stem-filename-extension' 2023-03-02 19:01:15 +01:00
Steffen Schuemann
efc077f553 refs #156: Windows path handling artifact bled into POSIX 2023-03-02 08:20:18 +01:00
gulrak
bc05cc59f4
Merge pull request #163 from Begasus/haiku
filesystem.hpp, add support for Haiku
2023-02-20 07:35:34 +01:00
begasus
a9c18e0880 Fix Haiku build 2023-02-19 14:17:05 +01:00
begasus
9afb43851d filesystem.hpp, add support for Haiku 2023-02-18 10:21:53 +01:00
gulrak
c57242b4bc
Merge pull request #154 from sthibaul/master
Fix build on GNU/Hurd
2023-02-17 17:29:41 +01:00
gulrak
3337cc252a
Merge pull request #153 from kkaefer/last_write_time-ios
Fix `ghc::filesystem::last_write_time()` setter on iOS/tvOS/watchOS
2023-02-17 17:27:12 +01:00
gulrak
655b0b354a
Merge pull request #162 from Qrox/patch-1
Fix directory iterator treating all files subsequent to a symlink as symlink on Windows
2023-02-17 17:23:38 +01:00
Jianxiang Wang (王健翔)
f0caeb7d58
Update filesystem.hpp
Fix directory iterator treating all files subsequent to a symlink as symlink on Windows
2023-02-16 13:38:48 +08:00
Luc Touraille
6c6f2c2ec0 [cmake] Define alias ghcFilesystem::ghc_filesystem unconditionally
This alias is needed whether or not the install rules of `ghcfilesystem`
are enabled. It allows projects to use the same target regardless of
where `ghcfilesystem` comes from, `add_subdirectory` or `find_package`.
2023-01-11 09:10:27 +01:00
gulrak
3e5b930d96
Merge pull request #145 from CookiePLMonster/y2038-fix
Fix a Y2038 bug in timeToFILETIME
2022-11-18 09:27:04 +01:00
Samuel Thibault
d3d968e583 Fix build on GNU/Hurd
There is no path length limitation there, even via pathconf.  But glibc
provides a getcwd function that allocates the buffer dynamically so we can
just leverage that.
2022-08-16 20:29:54 +02:00
Konstantin Käfer
404c57f1b0 Fix ghc::filesystem::last_write_time() setter on iOS/tvOS/watchOS
The previous implementation tried to detect old deployment targets for macOS that doesn't have the newer `utimensat` call. Unfortunately, it would just detect macOS, and didn't check for the corresponding iOS/tvOS/watchOS version numbers. On those platforms, last_write_time() was effectively a no-op, failing silently and not modifying the mtime of the file.

This patch adds detection for these platforms. It also removes the special casing when newer versions of macOS/iOS/tvOS/watchOS are used as the deployment targets, and instead folds it into the default POSIX branch.
2022-07-27 18:31:16 +02:00
David Runge
4c33b91fe9
Write ghc_filesystem-config-version.cmake file
CMakeLists.txt:
Write a ghc_filesystem-config-version.cmake file and install it, so that
other projects may rely on the exact version of ghc_filesystem.
The compatibility mode implies, that any version of ghc_filesystem with
the same major version is feature compatible.
2022-06-10 16:42:01 +02:00
David Runge
089ef64aa3
Declare version in cmake project() call
CMakeLists.txt:
Declare the project's version in the cmake project() call so that it may
be exported to the project's cmake integration (used by other projects).
2022-06-10 15:59:22 +02:00
Silent
4f0824fd76
Fix a Y2038 bug in timeToFILETIME
The old code truncated time_t to a 32-bit value
when using Int32x32To64. This example code has been fixed
on MSDN a while ago, so this change only updates it to
the current version.

More on this issue:
https://cookieplmonster.github.io/2022/02/17/year-2038-problem/
2022-05-25 19:56:56 +02:00
actboy168
28f7c929e0
fixes 2022-04-08 11:43:15 +08:00
actboy168
ab8a78d806
copy_file also copies permissions 2022-04-08 11:18:01 +08:00
actboy168
f6d7d5b826
Fixes skip_existing 2022-04-08 10:32:41 +08:00
Steffen Schuemann
cd6805e94d Version bump release v1.5.12
Took 30 minutes
2022-04-03 11:40:58 +02:00
Steffen Schuemann
6cc60fb687 Updated README.md
Took 45 seconds
2022-04-02 19:37:43 +02:00
Steffen Schuemann
fb4bb2b764 refs #138, ensure PATH_MAX exists on POSIX backend, wip version bump
Took 4 minutes
2022-04-02 19:36:58 +02:00
Steffen Schuemann
c4907cc681 Merge branch 'master' of github.com:gulrak/filesystem
# Conflicts:
#	test/CMakeLists.txt

Took 30 minutes
2022-04-02 19:33:55 +02:00
gulrak
5d1d579048
Merge pull request #140 from phprus/cxx20-deprecated
refs #140, disable ``deprecated-declarations`` warning in tests (C++20)
2022-04-02 19:24:23 +02:00
Steffen Schuemann
7fa1bde113 Merge branch 'feature-142-dirent-on-solaris' 2022-04-02 19:06:30 +02:00
Steffen Schuemann
7a53650e73 refs #142, switch Centos 8 source
Took 4 minutes
2022-04-02 16:29:03 +02:00
Steffen Schuemann
1ae0195287 refs #142, fix windows workflow
Took 5 minutes
2022-04-02 15:08:04 +02:00
Steffen Schuemann
e5bbc754e7 refs #142, fix tests
Took 2 minutes
2022-04-02 13:55:10 +02:00
Steffen Schuemann
977e5d6284 refs #142, solaris support for tests
Took 2 minutes
2022-04-02 13:53:16 +02:00
Steffen Schuemann
723c787b9e refs #142, solaris support for tests
Took 3 minutes
2022-04-02 13:51:20 +02:00
Steffen Schuemann
91e71f7f54 refs #142, solaris support for tests
Took 51 minutes
2022-04-02 13:47:16 +02:00
Steffen Schuemann
c4b507e9d8 refs #142, autodetect dirent::d_type and add GHC_OS_SOLARIS detection
Took 3 hours 8 minutes
2022-04-02 11:40:50 +02:00
Vladislav Shchapov
e8a17c1319 Migrate to Centos 8 Stream 2022-02-07 19:42:09 +05:00
Vladislav Shchapov
d4e12344d6 Fix C++20 test errors 2022-02-07 18:42:49 +05:00
gulrak
f437344e79
Merge pull request #137 from chewi/master
Update Catch header to v2.13.7 to fix tests against glibc 2.34
2021-11-27 21:32:56 +01:00
James Le Cuirot
f0467f4384
Update Catch header to v2.13.7 to fix tests against glibc 2.34 2021-11-22 22:34:41 +00:00
Steffen Schuemann
a07ddedeae Adding macos-11 to the tested platforms.
Took 17 minutes
2021-10-24 09:27:42 +02:00
Steffen Schuemann
614bbe87b8 Release v1.5.10 version bump
Took 25 minutes
2021-10-23 16:08:12 +02:00
gulrak
09908b7241
Merge pull request #136 from phprus/win-smart-ptr
Performance optimization for Windows.
2021-10-23 15:50:33 +02:00
Владислав Щапов
1dbe2d9bec Replace std::shared_ptr<void> to unique_handle 2021-10-03 19:28:53 +05:00
Владислав Щапов
7b8cf519f2 Replace std::shared_ptr to std::unique_ptr 2021-10-03 19:28:53 +05:00
Владислав Щапов
d279a4f73d Apply clang-format 2021-10-03 18:15:55 +05:00
gulrak
97d7fa8d10
Merge pull request #135 from phprus/issue-132
Fix for issue #132
2021-10-01 07:42:52 +02:00
Владислав Щапов
1f3943b1c4 Fix ghc::filesystem::remove_all behavior if argument is symlink 2021-09-23 00:55:09 +05:00
Владислав Щапов
6a835afddf Update CI 2021-09-23 00:55:09 +05:00
gulrak
7bc5c17305
Merge pull request #133 from musicinmybrain/space-overflow
Cast to uintmax_t *before* multiplying in space calculations
2021-07-31 00:11:22 +02:00
Benjamin A. Beasley
924d84acf0 Cast to uintmax_t *before* multiplying in space calculations
This ensures that all cases where the result actually does fit in a
uintmax_t are correctly handled. Before, the multiplication could be
performed in a smaller type, leading to an incorrect result or, worse,
undefined behavior due to signed integer overflow.

This fixes a test failure that was actually observed on an i686 Linux
system.
2021-07-30 17:14:23 -04:00
Steffen Schuemann
d87ac130cf Squashed commit of the following:
commit 2bef80eec1fe16a23e34143b9a5a32b04d612ed2
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 20:11:36 2021 +0200

    wip

commit e8c063d7ea66d2bdcbd1535b12dac1ca24afc7b9
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 20:05:04 2021 +0200

    wip

commit aafdebf274cafacfd6e1472621b015e48d547412
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 19:50:39 2021 +0200

    wip

commit b36f13655a09c3bac62afc6079ba010eb934493d
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 18:05:35 2021 +0200

    wip

commit eee191875c0d6816022342d341eaa43f5f83c4ff
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 17:32:35 2021 +0200

    more wip

commit 0ff949ab5f21055298aee8d7fcdda3a10f61a69c
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 17:12:18 2021 +0200

    wip

commit ca68861cb4c4e14079bb3ab2e0c9725b0a3aece8
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 16:31:32 2021 +0200

    wip

commit e188a3d2cca4f4bb84c3fa8f49e5de34ec731713
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 16:21:51 2021 +0200

    wip

commit b8383ac22cdb5bab3a4f527a1c46dafd009b2f11
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 16:15:42 2021 +0200

    Workflow wip...

commit 162416fe2cf2922382c7c7fd34c648b4782d48be
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 15:57:31 2021 +0200

    Workflow wip...

commit 891be4cdd72b23ec86bdc0935d9201841c2c07bc
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 15:52:24 2021 +0200

    Workflow wip...

commit 5c2ee653f41a38858cfaf602df639276ae1c7fbb
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 15:44:59 2021 +0200

    Workflow wip...

commit bca8df081885aed67ce0952f20aa2e4a96072a04
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 15:40:23 2021 +0200

    Workflow wip...

commit d94d8de098d954bffae65aec789d72c5c0b1301b
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sun Jul 4 15:34:16 2021 +0200

    Workflow wip...

commit 19f301992b733e699054050fdf552c982fea300c
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sat Jul 3 21:54:11 2021 +0200

    Workflow wip...

commit 495457726fc844d014e49b56acd6367160f4322b
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sat Jul 3 18:38:04 2021 +0200

    workflow wip

commit fde42cd4a5f865807703ff6814d9d0e8dfbde030
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sat Jul 3 18:34:47 2021 +0200

    Testing more generic workflow.

commit ead40cc153814e23ef3ddcb654ed8c57c10f54a6
Author: Steffen Schuemann <s.schuemann@pobox.com>
Date:   Sat Jul 3 16:51:25 2021 +0200

    Work on using GitHub workflows.
2021-07-04 20:24:13 +02:00
Steffen Schuemann
1d3d5f5d7d Version bump and updated readme. 2021-06-14 22:16:54 +02:00
Steffen Schümann
6fad24ecb9 Updated readme. 2021-06-14 21:36:44 +02:00
Steffen Schümann
b3d9a50bb5 Removed unwanted generation of temp strings. 2021-06-14 21:34:37 +02:00
Steffen Schümann
cd68567543 Bump wip version 2021-06-14 21:31:44 +02:00
Steffen Schümann
15e814e820 refs #125, fix broken windows long path test and broken create_directories with prefixed long paths 2021-06-10 01:21:07 +02:00
Steffen Schuemann
4e21ab3057 Version bump and updated readme. 2021-05-24 10:09:27 +02:00
Steffen Schuemann
a0e5e43c90 Merge branch 'feature-116-better-support-for-systems-without-dirent-d_type' 2021-05-24 10:03:20 +02:00
Steffen Schuemann
c029736d27 Updated readme. 2021-05-24 09:55:50 +02:00
Steffen Schuemann
19d0c63c29 refs #116, systems without d_type can now use GHC_NO_DIRENT_D_TYPE to compile, experimental QNX support 2021-05-24 09:30:42 +02:00
Steffen Schuemann
e402bad9b8 Merge branch 'master' of github.com:gulrak/filesystem 2021-05-23 16:31:57 +02:00
Steffen Schümann
51d62f88bb Fix for merge error and failing impl_test compile. 2021-05-23 16:27:54 +02:00
Steffen Schuemann
231b64fec0 Merge branch 'feature-122-recursive-iterator-follows-dead-symlinks'
# Conflicts:
#	README.md
2021-05-23 16:21:08 +02:00
Steffen Schuemann
31665c040a Updated readme. 2021-05-23 16:19:37 +02:00
Steffen Schümann
70cf2f03ba Merge branch 'feature-124-mapped-volumes-wrongly-handled-as-symlinks' 2021-05-23 16:06:13 +02:00
Steffen Schümann
d0b13bbc8e Merge branch 'feature-121-remove-handling-of-read-only-entires' 2021-05-23 15:58:55 +02:00
Steffen Schümann
05a41f6dae refs #123, build tests with WIN32_LEAN_AND_MEAN to ensure this keeps working 2021-05-23 15:55:47 +02:00
Steffen Schümann
9c6ff202e7 refs #121, fix for mingw compile issue 2021-05-23 11:29:04 +02:00
Steffen Schümann
a697b05dd7 refs #121, allow fs::remove on read-only entries in windows too 2021-05-23 10:53:58 +02:00
Steffen Schümann
cf4e05d42f refs #124, fix for mingw compile issue 2021-05-23 10:05:47 +02:00
Steffen Schümann
e51e6ee46b refs #124, mapped folder/volumes where wrongly handled as symlinks, failing fs::canonical 2021-05-23 08:46:50 +02:00
Steffen Schuemann
873a55addf refs #122, fix for dead symlink iteration error 2021-05-22 07:14:47 +02:00
Steffen Schümann
7e009bcf6f refs #122: added test that iterates over dead symlinks 2021-05-22 06:37:52 +02:00
Steffen Schuemann
e65a6baf76 Updated readme. 2021-05-02 23:14:52 +02:00
Steffen Schuemann
37442cc5ea refs #119, add additional tests and missing character literal types support 2021-05-02 01:46:08 +02:00
gulrak
134dffdcbd
Merge pull request #117 from phprus/gcc-libstdcxx-version
libstdc++ version check.
2021-04-26 18:43:57 +02:00
gulrak
777e3c9a34
Merge pull request #118 from phprus/test-root-unix
Disable some tests if running on root.
2021-04-26 18:42:24 +02:00
Владислав Щапов
22d1133ea5 Disable some tests if running on root. 2021-04-24 01:41:07 +05:00
Владислав Щапов
b9faee7f5d libstdc++ version check. 2021-04-24 01:08:48 +05:00
gulrak
7fb50217da
Merge pull request #115 from phprus/experimental-string_view
Improved string_view support (v2)
2021-04-20 22:29:20 +02:00
Владислав Щапов
6ab0cb2844 - Detect libstdc++ from gcc-5 and never. 2021-04-18 20:41:50 +05:00
Steffen Schuemann
fc875735dd Updated readme. 2021-04-06 12:09:32 +02:00
Steffen Schuemann
6dc4ece24b refs #114, use Availability.h in supporting headers 2021-04-03 12:24:48 +02:00
Steffen Schuemann
494e751709 refs #113, removed square brackets from test names to fix ctest/catch2 issue 2021-03-27 14:26:55 +01:00
Steffen Schuemann
76c3966df4 refs #113, switched to tag based comments and test names instead of C++17 paragraph numbers to become more standard version agnostic 2021-03-27 09:22:04 +01:00
18 changed files with 7306 additions and 2539 deletions

View File

@ -1,6 +1,6 @@
freebsd_task:
freebsd_instance:
image_family: freebsd-12-1
image_family: freebsd-14-0
install_script: |
pkg install -y cmake
pw groupadd testgrp
@ -11,25 +11,24 @@ freebsd_task:
test_script: |
sudo -u testuser .ci/unix-test.sh
centos7_task:
rockylinux8_task:
container:
image: centos:7
image: docker.io/rockylinux:8
install_script: |
yum install -y centos-release-scl
yum install -y devtoolset-9
curl -L https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-Linux-x86_64.tar.gz | tar xzvf - -C /usr/local --strip-components 1
dnf group install -y "Development Tools"
dnf install cmake -y
build_script: |
source /opt/rh/devtoolset-9/enable && PATH=$PATH:/usr/local/bin .ci/unix-build.sh
.ci/unix-build.sh
test_script: |
PATH=$PATH:/usr/local/bin .ci/unix-test.sh
.ci/unix-test.sh
centos8_task:
rockylinux9_task:
container:
image: centos:8
image: docker.io/rockylinux:9
install_script: |
yum group install -y "Development Tools"
curl -L https://github.com/Kitware/CMake/releases/download/v3.16.4/cmake-3.16.4-Linux-x86_64.tar.gz | tar xzvf - -C /usr/local --strip-components 1
dnf group install -y "Development Tools"
dnf install cmake -y
build_script: |
PATH=$PATH:/usr/local/bin .ci/unix-build.sh
.ci/unix-build.sh
test_script: |
PATH=$PATH:/usr/local/bin .ci/unix-test.sh
.ci/unix-test.sh

170
.github/workflows/build_cmake.yml vendored Normal file
View File

@ -0,0 +1,170 @@
name: CMake Build Matrix
on: [ push, pull_request ]
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- name: "Ubuntu 22.04 GCC 11"
os: ubuntu-22.04
build_type: Release
packages: ninja-build
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: gcc
cxx: g++
- name: "Ubuntu 22.04 Clang 13.0"
os: ubuntu-22.04
build_type: Release
packages: ninja-build libc++-13-dev libc++abi-13-dev
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: clang-13
cxx: clang++-13
- name: "Ubuntu 22.04 Clang 15.0"
os: ubuntu-22.04
build_type: Release
packages: ninja-build libc++-15-dev libc++abi-15-dev
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: clang-15
cxx: clang++-15
- name: "Ubuntu 22.04 GCC 11 coverage"
os: ubuntu-22.04
build_type: Debug
packages: ninja-build lcov
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: gcc
cxx: g++
- name: "Ubuntu 20.04 GCC 9.3"
os: ubuntu-20.04
build_type: Release
packages: ninja-build
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: gcc
cxx: g++
- name: "Ubuntu 20.04 Clang 10.0"
os: ubuntu-20.04
build_type: Release
packages: ninja-build
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: clang-10
cxx: clang++-10
- name: "Ubuntu 20.04 Clang 11.0"
os: ubuntu-20.04
build_type: Release
packages: ninja-build clang-11 libc++-11-dev libc++abi-11-dev
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: clang-11
cxx: clang++-11
- name: "Ubuntu 20.04 GCC 9.3 coverage"
os: ubuntu-20.04
build_type: Debug
packages: ninja-build lcov
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: gcc
cxx: g++
- name: "Windows MSVC 2019"
os: windows-2019
build_type: Release
packages: ninja
generator: "Visual Studio 16 2019"
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: cl
cxx: cl
- name: "macOS 13 AppleClang"
os: macos-13
build_type: Release
packages: ninja
generator: Ninja
compatibility: "cxx_std_11;cxx_std_17;cxx_std_20"
cc: clang
cxx: clang++
steps:
- uses: actions/checkout@v2
- name: print environment
run: |
echo github.event.action: ${{ github.event.action }}
echo github.event_name: ${{ github.event_name }}
- name: Install dependencies on Ubuntu
if: startsWith(matrix.config.os, 'ubuntu')
shell: bash
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
sudo apt update
sudo apt install ${{ matrix.config.packages }}
- name: Install dependencies on windows
if: startsWith(matrix.config.os, 'windows')
run: |
choco install ${{ matrix.config.packages }}
- name: Install dependencies on macOS
if: startsWith(matrix.config.os, 'macos')
run: |
brew install ${{ matrix.config.packages }}
- name: Configure project
shell: bash
run: |
export CC=${{ matrix.config.cc }}
export CXX=${{ matrix.config.cxx }}
ninja --version
cmake --version
mkdir build
mkdir install
if [[ "${{ matrix.config.build_type }}" == "Debug" ]]; then
cmake -G "${{ matrix.config.generator }}" -S . -B build -DCMAKE_BUILD_TYPE=Debug -DGHC_COVERAGE=ON -DGHC_FILESYSTEM_TEST_COMPILE_FEATURES="${{ matrix.config.compatibility }}" -DCMAKE_INSTALL_PREFIX:PATH=install
else
cmake -G "${{ matrix.config.generator }}" -S . -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DGHC_FILESYSTEM_TEST_COMPILE_FEATURES="${{ matrix.config.compatibility }}" -DCMAKE_INSTALL_PREFIX:PATH=install
fi
- name: Build project
shell: bash
run: |
cmake --build build --config ${{ matrix.config.build_type }}
- name: Run tests
run: |
cd build && ctest -C ${{ matrix.config.build_type }}
- name: Collect coverage info
if: startsWith(matrix.config.build_type, 'Debug')
run: |
cd build
lcov --compat-libtool --directory . --capture --output-file coverage_output.info
lcov --remove coverage_output.info '/usr/*' '*/c++/*' '*.h' '*/catch.hpp' -o coverage.info
# sed -i 's|SF:/.*/filesystem/|SF:../|g' coverage.info
- name: Upload coverage info
if: startsWith(matrix.config.build_type, 'Debug')
env:
COVERALLS_DEBUG: true
NODE_COVERALLS_DEBUG: 1
uses: coverallsapp/github-action@master
with:
path-to-lcov: ${{ github.workspace }}/build/coverage.info
github-token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,100 +0,0 @@
language: cpp
dist: xenial # default distribution
os: linux # default os
sudo: false
matrix:
fast_finish: true
include:
- env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["g++-5"], sources: ["ubuntu-toolchain-r-test"] } }
- env: MATRIX_EVAL="CC=gcc-6 && CXX=g++-6 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["g++-6"], sources: ["ubuntu-toolchain-r-test"] } }
- env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["g++-7"], sources: ["ubuntu-toolchain-r-test"] } }
- env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7 && GENERATOR='Unix Makefiles' && CONFIG=Debug && GHC_COVERAGE=1"
addons: { apt: { packages: ["g++-7", "lcov"], sources: ["ubuntu-toolchain-r-test"] } }
- env: MATRIX_EVAL="CC=gcc-8 && CXX=g++-8 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["g++-8"], sources: ["ubuntu-toolchain-r-test"] } }
- env: MATRIX_EVAL="CC=gcc-9 && CXX=g++-9 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["g++-9"], sources: ["ubuntu-toolchain-r-test"] } }
- env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["clang-5.0"] } }
- env: MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["clang-6.0"] } }
- env: MATRIX_EVAL="CC=clang-7 && CXX=clang++-7 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["clang-7", "libc++-7-dev", "libc++abi-7-dev"], sources: ["llvm-toolchain-xenial-7"] } }
- env: MATRIX_EVAL="CC=clang-8 && CXX=clang++-8 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["clang-8", "libc++-8-dev", "libc++abi-8-dev"], sources: ["llvm-toolchain-xenial-8"] } }
- env: MATRIX_EVAL="CC=clang-9 && CXX=clang++-9 && GENERATOR='Unix Makefiles' && CONFIG=Release"
addons: { apt: { packages: ["clang-9", "libc++-9-dev", "libc++abi-9-dev"], sources: [{sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main', key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'}] } }
- os: osx
env: MATRIX_EVAL="CC=clang && CXX=clang++ && GENERATOR=Xcode && CONFIG=Release"
osx_image: xcode9.2
- os: osx
env: MATRIX_EVAL="CC=clang && CXX=clang++ && GENERATOR=Xcode && CONFIG=Release"
osx_image: xcode10.1
- os: osx
env: MATRIX_EVAL="CC=clang && CXX=clang++ && GENERATOR=Xcode && CONFIG=Release"
osx_image: xcode11.3
install:
- eval "${MATRIX_EVAL}"
- |
if [ "${GHC_COVERAGE}" = "1" ]; then
gem install coveralls-lcov
fi
- $CC --version
- $CXX --version
- cmake --version
before_script:
- eval "${MATRIX_EVAL}"
- mkdir build
- cd build
- export VERBOSE=1
- |
if [ "${CONFIG}" = "Debug" ]; then
cmake -G"${GENERATOR}" -DCMAKE_CXX_COMPILER=${CXX} -DCMAKE_C_COMPILER=${CC} -DCMAKE_BUILD_TYPE=${CONFIG} -DGHC_COVERAGE=ON ..
else
cmake -G"${GENERATOR}" -DCMAKE_CXX_COMPILER=${CXX} -DCMAKE_C_COMPILER=${CC} -DCMAKE_BUILD_TYPE=${CONFIG} ..
fi
script:
- export VERBOSE=1
- cmake --build . --config ${CONFIG} --target filesystem_test
- |
if [ "${GHC_COVERAGE}" = "1" ]; then
cmake --build . --config ${CONFIG} --target filesystem_test
test/filesystem_test
else
cmake --build . --config ${CONFIG}
ctest -C ${CONFIG} -E Windows
if [ -f "test/std_filesystem_test" ]; then
test/std_filesystem_test || true
fi
fi
after_success:
- |
if [ "${GHC_COVERAGE}" = "1" ]; then
lcov --compat-libtool --directory . --capture --output-file coverage_output.info
lcov --remove coverage_output.info '/usr/*' '*/c++/*' '*.h' '*/catch.hpp' -o coverage.info
sed -i 's|SF:/.*/filesystem/|SF:../|g' coverage.info
coveralls-lcov coverage.info
fi

View File

@ -1,5 +1,8 @@
cmake_minimum_required(VERSION 3.7.2)
project(ghcfilesystem)
project(
ghcfilesystem,
VERSION 1.5.15
)
if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
@ -15,7 +18,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
else()
option(GHC_FILESYSTEM_BUILD_EXAMPLES "Build examples" OFF)
option(GHC_FILESYSTEM_BUILD_TESTING "Enable tests" OFF)
option(GHC_FILESYSTEM_WITH_INSTALL "With install target" ON)
option(GHC_FILESYSTEM_WITH_INSTALL "With install target" OFF)
endif()
option(GHC_FILESYSTEM_BUILD_STD_TESTING "Enable STD tests" ${GHC_FILESYSTEM_BUILD_TESTING})
if(NOT DEFINED GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
@ -32,8 +35,14 @@ endif()
if(CMAKE_CXX_STANDARD LESS 11)
message(FATAL_ERROR "CMAKE_CXX_STANDARD is less than 11, ghc::filesystem only works with C++11 and above.")
endif()
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
message(STATUS "System name: ${CMAKE_SYSTEM_NAME}")
message(STATUS "Compiler ID: ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "CMAKE_CXX_COMPILE_FEATURES: ${CMAKE_CXX_COMPILE_FEATURES}")
endif()
add_library(ghc_filesystem INTERFACE)
add_library(ghcFilesystem::ghc_filesystem ALIAS ghc_filesystem)
target_include_directories(ghc_filesystem INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
@ -67,7 +76,15 @@ if(GHC_FILESYSTEM_WITH_INSTALL)
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem"
PATH_VARS CMAKE_INSTALL_INCLUDEDIR)
install(FILES "${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem")
add_library(ghcFilesystem::ghc_filesystem ALIAS ghc_filesystem)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config-version.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMinorVersion
)
install(
FILES
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config.cmake"
"${PROJECT_BINARY_DIR}/cmake/ghc_filesystem-config-version.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ghc_filesystem"
)
endif()

412
README.md
View File

@ -1,23 +1,56 @@
![Supported Platforms](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows%20%7C%20FreeBSD-blue.svg)
![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
[![Build Status](https://travis-ci.org/gulrak/filesystem.svg?branch=master)](https://travis-ci.org/gulrak/filesystem)
[![CMake Build Matrix](https://github.com/gulrak/filesystem/actions/workflows/build_cmake.yml/badge.svg?branch=master)](https://github.com/gulrak/filesystem/actions/workflows/build_cmake.yml)
[![Build Status](https://ci.appveyor.com/api/projects/status/t07wp3k2cddo0hpo/branch/master?svg=true)](https://ci.appveyor.com/project/gulrak/filesystem)
[![Build Status](https://api.cirrus-ci.com/github/gulrak/filesystem.svg?branch=master)](https://cirrus-ci.com/github/gulrak/filesystem)
[![Build Status](https://cloud.drone.io/api/badges/gulrak/filesystem/status.svg?ref=refs/heads/master)](https://cloud.drone.io/gulrak/filesystem)
[![Coverage Status](https://coveralls.io/repos/github/gulrak/filesystem/badge.svg?branch=master)](https://coveralls.io/github/gulrak/filesystem?branch=master)
[![Latest Release Tag](https://img.shields.io/github/tag/gulrak/filesystem.svg)](https://github.com/gulrak/filesystem/tree/v1.5.4)
[![Latest Release Tag](https://img.shields.io/github/tag/gulrak/filesystem.svg)](https://github.com/gulrak/filesystem/tree/v1.5.14)
<!-- [![Build Status](https://cloud.drone.io/api/badges/gulrak/filesystem/status.svg?ref=refs/heads/master)](https://cloud.drone.io/gulrak/filesystem) -->
<!-- TOC -->
* [Filesystem](#filesystem)
* [Motivation](#motivation)
* [Why the namespace GHC?](#why-the-namespace-ghc)
* [Platforms](#platforms)
* [Tests](#tests)
* [Usage](#usage)
* [Downloads](#downloads)
* [Using it as Single-File-Header](#using-it-as-single-file-header)
* [Using it as Forwarding-/Implementation-Header](#using-it-as-forwarding-implementation-header)
* [Git Submodule and CMake](#git-submodule-and-cmake)
* [Versioning](#versioning)
* [Documentation](#documentation)
* [`ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream`](#ghcfilesystemifstream--ghcfilesystemofstream--ghcfilesystemfstream)
* [`ghc::filesystem::u8arguments`](#ghcfilesystemu8arguments)
* [Differences](#differences)
* [LWG Defects](#lwg-defects)
* [Not Implemented on C++ before C++17](#not-implemented-on-c-before-c17)
* [Differences in API](#differences-in-api)
* [Differences of Specific Interfaces](#differences-of-specific-interfaces)
* [Differences in Behavior](#differences-in-behavior)
* [fs.path (ref)](#fspath--ref-)
* [Open Issues](#open-issues)
* [Windows](#windows)
* [Symbolic Links on Windows](#symbolic-links-on-windows)
* [Permissions](#permissions)
* [Release Notes](#release-notes)
<!-- TOC -->
# Filesystem
This is a header-only single-file `std::filesystem` compatible helper library,
based on the C++17 and C++20 specs, but implemented for C++11, C++14, C++17 or C++20
(tightly following the C++17 standard with very few documented exceptions). It is currently tested on
macOS 10.12/10.14/10.15, Windows 10, Ubuntu 18.04, CentOS 7, CentOS 8, FreeBSD 12
and Alpine ARM/ARM64 Linux but should work on other systems too, as long as you have
macOS 10.12/10.14/10.15/11.6, Windows 10, Ubuntu 18.04, Ubuntu 20.04, CentOS 7, CentOS 8, FreeBSD 12,
Alpine ARM/ARM64 Linux and Solaris 10 but should work on other systems too, as long as you have
at least a C++11 compatible compiler. It should work with Android NDK, Emscripten and I even
had reports of it being used on iOS (within sandboxing constraints).
It is of course in its own namespace `ghc::filesystem` to not interfere with a regular `std::filesystem` should you use it in a mixed C++17
environment (which is possible).
had reports of it being used on iOS (within sandboxing constraints) and with v1.5.6 there
is experimental support for QNX. The support of Android NDK, Emscripten, QNX, and since 1.5.14
GNU/Hurd and Haiku is not backed up by automated testing but PRs and bug reports are welcome
for those too and they are reported to work.
It is of course in its own namespace `ghc::filesystem` to not interfere with a regular `std::filesystem`
should you use it in a mixed C++17 environment (which is possible).
*Test coverage is well above 90%, and starting with v1.3.6 and in v1.5.0
more time was invested in benchmarking and optimizing parts of the library. I'll try
@ -58,15 +91,15 @@ to do with Haskell**, sorry for the name clash).
## Platforms
`ghc::filesystem` is developed on macOS but CI tested on macOS, Windows,
various Linux Distributions and FreeBSD. It should work on any of these with a C++11-capable
compiler. Also there are some checks to hopefully better work on Android, but
as I currently don't test with the Android NDK, I wouldn't call it a
supported platform yet, same is valid for using it with Emscripten. It is now
part of the detected platforms, I fixed the obvious issues and ran some tests with
it, so it should be fine. All in all, I don't see it replacing `std::filesystem`
where full C++17 or C++20 is available, it doesn't try to be a "better"
`std::filesystem`, just an almost drop-in if you can't use it (with the exception
of the UTF-8 preference).
various Linux Distributions, FreeBSD and starting with v1.5.12 on Solaris.
It should work on any of these with a C++11-capable compiler. Also there are some
checks to hopefully better work on Android, but as I currently don't test with the
Android NDK, I wouldn't call it a supported platform yet, same is valid for using
it with Emscripten. It is now part of the detected platforms, I fixed the obvious
issues and ran some tests with it, so it should be fine. All in all, I don't see it
replacing `std::filesystem` where full C++17 or C++20 is available, it doesn't try
to be a "better" `std::filesystem`, just an almost drop-in if you can't use it
(with the exception of the UTF-8 preference).
:information_source: **Important:** _This implementation is following the ["UTF-8 Everywhere" philosophy](https://utf8everywhere.org/) in that all
`std::string` instances will be interpreted the same as `std::u8string` encoding
@ -75,11 +108,13 @@ for more information._
Unit tests are currently run with:
* macOS 10.12: Xcode 9.2 (clang-900.0.39.2), GCC 9.2, Clang 9.0, macOS 10.13: Xcode 10.1, macOS 10.14: Xcode 11.2, macOS 10.15: Xcode 11.6
* macOS 10.12: Xcode 9.2 (clang-900.0.39.2), GCC 9.2, Clang 9.0, macOS 10.13: Xcode 10.1, macOS 10.14: Xcode 11.2, macOS 10.15: Xcode 11.6, Xcode 12.4
* Windows: Visual Studio 2017, Visual Studio 2015, Visual Studio 2019, MinGW GCC 6.3 (Win32), GCC 7.2 (Win64), Cygwin GCC 10.2 (no CI yet)
* Linux (Ubuntu): GCC (5.5, 6.5, 7.4, 8.3, 9.2), Clang (5.0, 6.0, 7.1, 8.0, 9.0)
* Linux (Alpine ARM/ARM64): GCC 9.2.0
* ~~Linux (Alpine ARM/ARM64): GCC 9.2.0~~ (The Drone build scripts stopped working,
as they where a contribution, I couldn't figure out what went wrong, any help appreciated.)
* FreeBSD: Clang 8.0
* Solaris: GCC 5.5
## Tests
@ -119,8 +154,8 @@ in the standard, and there might be issues in these implementations too.
### Downloads
The latest release version is [v1.5.4](https://github.com/gulrak/filesystem/tree/v1.5.4) and
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.5.4).
The latest release version is [v1.5.14](https://github.com/gulrak/filesystem/tree/v1.5.14) and
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.5.14).
The latest pre-native-backend version is [v1.4.0](https://github.com/gulrak/filesystem/tree/v1.4.0) and
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.4.0).
@ -141,63 +176,97 @@ Everything is in the namespace `ghc::filesystem`, so one way to use it only as
a fallback could be:
```cpp
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs = std::filesystem;
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#endif
#ifndef GHC_USE_STD_FS
#include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem;
#ifdef GHC_USE_STD_FS
#include <filesystem>
namespace fs = std::filesystem;
#else
#include "filesystem.hpp"
namespace fs = ghc::filesystem;
#endif
```
**Note that this code uses a two-stage preprocessor condition because Visual Studio 2015
doesn't like the `(<...>)` syntax, even if it could cut evaluation early before. This code also
used the minimum deployment target to detect if `std::filesystem` really is available on macOS
compilation.**
**Note also, this detection now works on MSVC versions prior to 15.7 on, or without setting
the `/Zc:__cplusplus` compile switch that would fix `__cplusplus` on MSVC. (Without the switch
the compiler always reports `199711L`
([see](https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/)),
but `_MSVC_LANG` works without it.**
If you want to also use the `fstream` wrapper with `path` support as fallback,
you might use:
```cpp
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
using ifstream = std::ifstream;
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#endif
#ifndef GHC_USE_STD_FS
#include <ghc/filesystem.hpp>
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
using ofstream = ghc::filesystem::ofstream;
using fstream = ghc::filesystem::fstream;
}
#ifdef GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
using ifstream = std::ifstream;
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#else
#include "filesystem.hpp"
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
using ofstream = ghc::filesystem::ofstream;
using fstream = ghc::filesystem::fstream;
}
#endif
```
Now you have e.g. `fs::ofstream out(somePath);` and it is either the wrapper or
the C++17 `std::ofstream`.
**Be aware, as a header-only library, it is not hiding the fact, that it
:information_source: **Be aware, as a header-only library, it is not hiding the fact, that it
uses system includes, so they "pollute" your global namespace. Use the
forwarding-/implementation-header based approach (see below) to avoid this.**
forwarding-/implementation-header based approach (see below) to avoid this.
For Windows it needs `Windows.h` and it might be a good idea to define
`WIN32_LEAN_AND_MEAN` or `NOMINMAX` prior to including `filesystem.hpp` or
`fs_std.hpp` headers to reduce pollution of your global namespace and compile
time. They are not defined by `ghc::filesystem` to allow combination with contexts
where the full `Windows.h`is needed, e.g. for UI elements.**
:information_source: **Hint:** There is an additional header named `ghc/fs_std.hpp` that implements this
dynamic selection of a filesystem implementation, that you can include
@ -211,8 +280,8 @@ Alternatively, starting from v1.1.0 `ghc::filesystem` can also be used by
including one of two additional wrapper headers. These allow to include
a forwarded version in most places (`ghc/fs_fwd.hpp`) while hiding the
implementation details in a single cpp file that includes `ghc/fs_impl.hpp` to
implement the needed code. That way system includes are only visible from
inside the cpp file, all other places are clean.
implement the needed code. Using `ghc::filesystem` this way makes sure
system includes are only visible from inside the cpp file, all other places are clean.
Be aware, that it is currently not supported to hide the implementation
into a Windows-DLL, as a DLL interface with C++ standard templates in interfaces
@ -223,26 +292,46 @@ If you use the forwarding/implementation approach, you can still use the dynamic
switching like this:
```cpp
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
using ifstream = std::ifstream;
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#endif
#ifndef GHC_USE_STD_FS
#include <ghc/fs-fwd.hpp>
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
using ofstream = ghc::filesystem::ofstream;
using fstream = ghc::filesystem::fstream;
}
#ifdef GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
using ifstream = std::ifstream;
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#else
#include "fs_fwd.hpp"
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
using ofstream = ghc::filesystem::ofstream;
using fstream = ghc::filesystem::fstream;
}
#endif
```
@ -250,22 +339,38 @@ and in the implementation hiding cpp, you might use (before any include that inc
to take precedence:
```cpp
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#endif
#if _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| __IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| __TV_OS_VERSION_MIN_REQUIRED && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| __WATCH_OS_VERSION_MAX_ALLOWED && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#ifndef GHC_USE_STD_FS
#define GHC_FILESYSTEM_IMPLEMENTATION
#include <ghc/filesystem.hpp>
#include "fs_impl.hpp"
#endif
```
:information_source: **Hint:** There are additional helper headers, named `ghc/fs_std_fwd.hpp` and
`ghc/fs_std_impl.hpp` that use this technique, so you can simply include them
if you want to dynamically select the filesystem implementation. they also
enable the `wchar_t` support on `ghc::filesystem` on Windows, so the resulting
implementation in the `fs` namespace will be compatible.
if you want to dynamically select the filesystem implementation.
@ -292,6 +397,10 @@ The `CMakeLists.txt` offers a few options to customize its behavior:
`CMAKE_CXX_COMPILE_FEATURES` when the detection of C++17 or C++20 for additional tests
is not working (e.g. `cxx_std_20` to enforce building a `filesystem_test_cpp20` with C++20).
### Bazel
Please use [hedronvision/bazel-cc-filesystem-backport](https://github.com/hedronvision/bazel-cc-filesystem-backport), which will automatically set everything up for you.
### Versioning
There is a version macro `GHC_FILESYSTEM_VERSION` defined in case future changes
@ -357,7 +466,7 @@ int main(int argc, char* argv[])
exit(EXIT_FAILURE);
}
// now use argc/argv as usual, they have utf-8 enconding on windows
// now use argc/argv as usual, they have utf-8 encoding on windows
// ...
return 0;
@ -522,7 +631,7 @@ the standard.
As symbolic links on Windows, while being supported more or less since
Windows Vista (with some strict security constraints) and fully since some earlier
build of Windows 10, when "Developer Mode" is activated, are at time of writing
(2018) rarely used, still they are supported with this implementation.
(2018) rarely used, still they are supported wiit th this implementation.
#### Permissions
@ -537,9 +646,114 @@ to the expected behavior.
## Release Notes
### v1.5.15 (wip)
* Fix for [#166](https://github.com/gulrak/filesystem/issues/166),
`extension()` did return non empty result for the directory name
`".."`
### [v1.5.14](https://github.com/gulrak/filesystem/releases/tag/v1.5.14)
* Pull request [#163](https://github.com/gulrak/filesystem/pull/163), build
support for Haiku (also fixes [#159](https://github.com/gulrak/filesystem/issues/159))
* Pull request [#162](https://github.com/gulrak/filesystem/pull/162), fix for
directory iterator treating all files subsequent to a symlink as symlink
on Windows
* Pull request [#161](https://github.com/gulrak/filesystem/pull/161), the
CMake alias `ghcFilesystem::ghc_filesystem` is now set unconditionally
* Fix for [#160](https://github.com/gulrak/filesystem/issues/160), the cmake
config now only sets install targets by default if the project is no
subproject, as documented
* Fix for [#157](https://github.com/gulrak/filesystem/issues/157), suppress
C4191 warning on MSVC for GetProcAddress casts
* Fix for [#156](https://github.com/gulrak/filesystem/issues/156), on POSIX
`stem()`, `filename()` and `extension()` of `fs::path` would return wrong
result if a colon was in the filename
* Pull request [#154](https://github.com/gulrak/filesystem/pull/145), build
support for GNU/Hurd
* Pull request [#153](https://github.com/gulrak/filesystem/pull/153), fixed
`fs::last_write_time(path, time, ec)` setter on iOS, tvOS and watchOS
* Fix for [#151](https://github.com/gulrak/filesystem/issues/156),
`fs::directory_entry::refresh()` now, consistently with `status()` will not
throw on symlinks to non-existing targets, but make the entry have
`file_type::not_found` as the type
* Pull request [#149](https://github.com/gulrak/filesystem/pull/149), add
version to CMake project and export it
* Fix for [#146](https://github.com/gulrak/filesystem/issues/146), handle `EINTR`
on POSIX directory iteration and file copy to avoid errors on network
filesystems
* Pull request [#145](https://github.com/gulrak/filesystem/pull/145), fix for
Y2038 bug in timeToFILETIME on Windows
* Pull request [#144](https://github.com/gulrak/filesystem/pull/144), `fs::copy_file()`
now also copies the permissions
* Pull request [#143](https://github.com/gulrak/filesystem/pull/143), fix
for `fs::copy_file()` ignoring the `skip_existing` option.
### [v1.5.12](https://github.com/gulrak/filesystem/releases/tag/v1.5.12)
* Fix for [#142](https://github.com/gulrak/filesystem/issues/142), removed need
for `GHC_NO_DIRENT_D_TYPE` on systems that don't support `dirent::d_type` and
fixed build configuration and tests to support Solaris as new platform.
* Pull request [#138](https://github.com/gulrak/filesystem/pull/138), if the
platform uses the POSIX backend and has no `PATH_MAX`, one is defined.
* Pull request [#137](https://github.com/gulrak/filesystem/pull/137), update
of Catch2 to version v2.13.7
* Added macOS 11 to the automatically tested platforms.
### [v1.5.10](https://github.com/gulrak/filesystem/releases/tag/v1.5.10)
* Pull request [#136](https://github.com/gulrak/filesystem/pull/136), the Windows
implementation used some unnecessary expensive shared pointer for resource
management and these where replaced by a dedicated code.
* Fix for [#132](https://github.com/gulrak/filesystem/issues/132), pull request
[#135](https://github.com/gulrak/filesystem/pull/135), `fs::remove_all` now
just deletes symbolic links instead of following them.
* Pull request [#133](https://github.com/gulrak/filesystem/pull/133), fix for
`fs::space` where a numerical overflow could happen in a multiplication.
* Replaced _travis-ci.org_ with GitHub Workflow for the configurations:
Ubuntu 20.04: GCC 9.3, Ubuntu 18.04: GCC 7.5, GCC 8.4, macOS 10.15: Xcode 12.4,
Windows 10: Visual Studio 2019
### [v1.5.8](https://github.com/gulrak/filesystem/releases/tag/v1.5.8)
* Fix for [#125](https://github.com/gulrak/filesystem/issues/124), where
`fs::create_directories` on Windows no longer breaks on long filenames.
### [v1.5.6](https://github.com/gulrak/filesystem/releases/tag/v1.5.6)
* Fix for [#124](https://github.com/gulrak/filesystem/issues/124),
`ghc::filesystem` treated mounted folder/volumes erroneously as symlinks,
leading `fs::canonical` to fail on paths containing those.
* Fix for [#122](https://github.com/gulrak/filesystem/issues/122), incrementing
the `recursive_directory_iterator` will not try to enter dead symlinks.
* Fix for [#121](https://github.com/gulrak/filesystem/issues/121), on Windows
backend the `fs::remove` failed when the path pointed to a read-only entry,
see also ([microsoft/STL#1511](https://github.com/microsoft/STL/issues/1511))
for the corresponding issue in `std::fs` on windows.
* Fix for [#119](https://github.com/gulrak/filesystem/issues/119), added missing
support for char16_t and char32_t and on C++20 char8_t literals.
* Pull request [#118](https://github.com/gulrak/filesystem/pull/118), when
running tests as root, disable tests that would not work.
* Pull request [#117](https://github.com/gulrak/filesystem/pull/117), added
checks to tests to detect the clang/libstdc++ combination.
* Fix for [#116](https://github.com/gulrak/filesystem/issues/116), internal
macro `GHC_NO_DIRENT_D_TYPE` allows os detection to support systems without
the `dirent.d_type` member, experimental first QNX compile support as
initial use case, fixed issue with filesystems returning DT_UNKNOWN
(e.g. reiserfs).
* Pull request [#115](https://github.com/gulrak/filesystem/pull/115), added
`string_view` support when clang with libstdc++ is detected.
* Fix for [#114](https://github.com/gulrak/filesystem/issues/114), for macOS
the pre-Catalina deployment target detection worked only if `<Availability.h>`
was included before `<ghc/fs_std.hpp>` or `<ghc/fs_std_fwd.hpp>`/`<ghc/fs_std_impl.hpp>`.
* Fix for [#113](https://github.com/gulrak/filesystem/issues/113), the use of
standard chapter numbers was misleading since C++17 and C++20 `std::filesystem`
features are supported, and was replaced by the tag-like chapter names that
stay (mostly) consistent over the versions.
### [v1.5.4](https://github.com/gulrak/filesystem/releases/tag/v1.5.4)
* Pull request [#112](https://github.com/gulrak/filesystem/issues/112), lots
* Pull request [#112](https://github.com/gulrak/filesystem/pull/112), lots
of cleanup work on the readme, thanks!
* Enhancement for [#111](https://github.com/gulrak/filesystem/issues/111),
further optimization of directory iteration, performance for
@ -550,15 +764,15 @@ to the expected behavior.
made to allow the tests to compile and run successfully (tested with GCC
10.2.0), feedback and additional PRs welcome as it is currently not
part of the CI configuration.
* Pull request [#109](https://github.com/gulrak/filesystem/issues/109), various
* Pull request [#109](https://github.com/gulrak/filesystem/pull/109), various
spelling errors in error messages and comments fixed.
* Pull request [#108](https://github.com/gulrak/filesystem/issues/108), old
* Pull request [#108](https://github.com/gulrak/filesystem/pull/108), old
style casts removed.
* Fix for [#107](https://github.com/gulrak/filesystem/issues/107), the error
handling for status calls was suppressing errors on symlink targets.
* Pull request [#106](https://github.com/gulrak/filesystem/issues/106), fixed
* Pull request [#106](https://github.com/gulrak/filesystem/pull/106), fixed
detection of AppleClang for compile options.
* Pull request [#105](https://github.com/gulrak/filesystem/issues/105), added
* Pull request [#105](https://github.com/gulrak/filesystem/pull/105), added
option `GHC_FILESYSTEM_BUILD_STD_TESTING` to override additional build of
`std::filesystem` versions of the tests for comparison and the possibility
to use `GHC_FILESYSTEM_TEST_COMPILE_FEATURES` to prefill the used compile

View File

@ -1,6 +1,5 @@
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 ("${CMAKE_CXX_COMPILER_ID}" MATCHES "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)
@ -20,6 +19,12 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION
target_link_libraries(${targetName} -stdlib=libc++)
endif()
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
target_link_libraries(filesystem_test xnet)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
target_link_libraries(filesystem_test network)
endif()
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
endif()
@ -29,6 +34,12 @@ if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 O
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
target_link_libraries(${targetName} -lstdc++fs)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
target_link_libraries(${targetName} xnet)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
target_link_libraries(${targetName} network)
endif()
target_compile_options(${targetName} PRIVATE $<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
endif()
@ -47,12 +58,19 @@ macro(AddTestExecutableWithStdCpp cppStd)
add_executable(filesystem_test_cpp${cppStd} ${ARGN})
set_property(TARGET filesystem_test_cpp${cppStd} PROPERTY CXX_STANDARD ${cppStd})
target_link_libraries(filesystem_test_cpp${cppStd} ghc_filesystem)
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
target_link_libraries(filesystem_test_cpp${cppStd} xnet)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
target_link_libraries(filesystem_test_cpp${cppStd} network)
endif()
target_compile_options(filesystem_test_cpp${cppStd} PRIVATE
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror -Wno-error=deprecated-declarations>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror -Wno-error=deprecated-declarations>
$<$<CXX_COMPILER_ID:MSVC>:/WX /wd4996>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>
$<$<BOOL:${GHC_COVERAGE}>:--coverage>)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
target_compile_definitions(filesystem_test_cpp${cppStd} PRIVATE _CRT_SECURE_NO_WARNINGS)
endif()

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
// fs_fwd.hpp - The forwarding header for the header/implementation seperated usage of
// fs_fwd.hpp - The forwarding header for the header/implementation separated usage of
// ghc::filesystem.
// This file can be include at any place, where ghc::filesystem api is needed while
// not bleeding implementation details (e.g. system includes) into the global namespace,
@ -34,5 +34,5 @@
#ifndef GHC_FILESYSTEM_FWD_H
#define GHC_FILESYSTEM_FWD_H
#define GHC_FILESYSTEM_FWD
#include <ghc/filesystem.hpp>
#include "filesystem.hpp"
#endif // GHC_FILESYSTEM_FWD_H

View File

@ -25,11 +25,11 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
// fs_impl.hpp - The implementation header for the header/implementation seperated usage of
// fs_impl.hpp - The implementation header for the header/implementation separated usage of
// ghc::filesystem.
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
// The cpp has to include this before including fs_fwd.hpp directly or via a different
// header to work.
//---------------------------------------------------------------------------------------
#define GHC_FILESYSTEM_IMPLEMENTATION
#include <ghc/filesystem.hpp>
#include "filesystem.hpp"

View File

@ -30,27 +30,48 @@
// namespace fs.
//---------------------------------------------------------------------------------------
#ifndef GHC_FILESYSTEM_STD_H
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
using ifstream = std::ifstream;
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#endif
#endif
#ifndef GHC_USE_STD_FS
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
#include <ghc/filesystem.hpp>
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
using ofstream = ghc::filesystem::ofstream;
using fstream = ghc::filesystem::fstream;
}
#endif
#endif // GHC_FILESYSTEM_STD_H
#define GHC_FILESYSTEM_STD_H
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#ifdef GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
using ifstream = std::ifstream;
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#else
#include "filesystem.hpp"
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
using ofstream = ghc::filesystem::ofstream;
using fstream = ghc::filesystem::fstream;
}
#endif
#endif // GHC_FILESYSTEM_STD_H

View File

@ -25,7 +25,7 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
// fs_std_fwd.hpp - The forwarding header for the header/implementation seperated usage of
// fs_std_fwd.hpp - The forwarding header for the header/implementation separated usage of
// ghc::filesystem that uses std::filesystem if it detects it.
// This file can be include at any place, where fs::filesystem api is needed while
// not bleeding implementation details (e.g. system includes) into the global namespace,
@ -33,28 +33,47 @@
//---------------------------------------------------------------------------------------
#ifndef GHC_FILESYSTEM_STD_FWD_H
#define GHC_FILESYSTEM_STD_FWD_H
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
using ifstream = std::ifstream;
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#endif
#endif
#ifndef GHC_USE_STD_FS
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
#define GHC_FILESYSTEM_FWD
#include <ghc/filesystem.hpp>
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
using ofstream = ghc::filesystem::ofstream;
using fstream = ghc::filesystem::fstream;
}
#endif
#endif // GHC_FILESYSTEM_STD_FWD_H
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#ifdef GHC_USE_STD_FS
#include <filesystem>
namespace fs {
using namespace std::filesystem;
using ifstream = std::ifstream;
using ofstream = std::ofstream;
using fstream = std::fstream;
}
#else
#include "fs_fwd.hpp"
namespace fs {
using namespace ghc::filesystem;
using ifstream = ghc::filesystem::ifstream;
using ofstream = ghc::filesystem::ofstream;
using fstream = ghc::filesystem::fstream;
}
#endif
#endif // GHC_FILESYSTEM_STD_FWD_H

View File

@ -25,19 +25,36 @@
// SOFTWARE.
//
//---------------------------------------------------------------------------------------
// fs_std_impl.hpp - The implementation header for the header/implementation seperated usage of
// fs_std_impl.hpp - The implementation header for the header/implementation separated usage of
// ghc::filesystem that does nothing if std::filesystem is detected.
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
// The cpp has to include this before including fs_std_fwd.hpp directly or via a different
// header to work.
//---------------------------------------------------------------------------------------
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS
#endif
#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include)
// ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus
// _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
#if __has_include(<filesystem>) // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html
#define GHC_USE_STD_FS
// Old Apple OSs don't support std::filesystem, though the header is available at compile
// time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0,
// and watchOS 6.0.
#ifdef __APPLE__
#include <Availability.h>
// Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS
// released after std::filesystem, where std::filesystem is always available.
// (All other __<platform>_VERSION_MIN_REQUIREDs will be undefined and thus 0.)
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \
|| defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \
|| defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000
#undef GHC_USE_STD_FS
#endif
#endif
#endif
#endif
#ifndef GHC_USE_STD_FS
//#define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE
#define GHC_FILESYSTEM_IMPLEMENTATION
#include <ghc/filesystem.hpp>
#include "fs_impl.hpp"
#endif

View File

@ -3,6 +3,20 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
set(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS ON)
include(ParseAndAddCatchTests)
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" AND UNIX AND NOT APPLE AND NOT BSD)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
set(CMAKE_EXE_LINKER_FLAGS "-lc++abi")
endif()
function(SetTestCompileOptions target_name)
target_compile_options(${target_name} PRIVATE
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror -Wno-deprecated-declarations>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror -Wno-deprecated-declarations>
$<$<CXX_COMPILER_ID:MSVC>:/WX /wd4996>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
endfunction()
if(GHC_COVERAGE)
message("Generating test runner for coverage run...")
set(CMAKE_EXE_LINKER_FLAGS "${CMCMAKE_EXE_LINKER_FLAGS} --coverage")
@ -13,18 +27,31 @@ if(GHC_COVERAGE)
target_compile_options(filesystem_test PUBLIC --coverage)
endif()
target_link_libraries(filesystem_test PUBLIC ghc_filesystem --coverage)
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
target_link_libraries(filesystem_test PUBLIC xnet)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
target_link_libraries(filesystem_test PUBLIC network)
endif()
if("cxx_std_17" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
AddTestExecutableWithStdCpp(17 filesystem_test.cpp catch.hpp)
endif()
if("cxx_std_20" IN_LIST GHC_FILESYSTEM_TEST_COMPILE_FEATURES)
AddTestExecutableWithStdCpp(20 filesystem_test.cpp catch.hpp)
endif()
else()
message("Generating test runner for normal test...")
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>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-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>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
target_link_libraries(filesystem_test xnet)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
target_link_libraries(filesystem_test network)
endif()
SetTestCompileOptions(filesystem_test)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS)
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
endif()
if(EMSCRIPTEN)
set_target_properties(filesystem_test PROPERTIES LINK_FLAGS "-g4 -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1")
@ -36,10 +63,7 @@ else()
if(WIN32)
add_executable(filesystem_test_char filesystem_test.cpp catch.hpp)
target_link_libraries(filesystem_test_char ghc_filesystem)
target_compile_options(filesystem_test_char PRIVATE
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Werror>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Werror>
$<$<CXX_COMPILER_ID:MSVC>:/WX>)
SetTestCompileOptions(filesystem_test_char)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
target_compile_definitions(filesystem_test_char PRIVATE _CRT_SECURE_NO_WARNINGS GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE)
else()
@ -61,14 +85,15 @@ add_test(multifile_test multifile_test)
add_executable(fwd_impl_test fwd_test.cpp impl_test.cpp)
target_link_libraries(fwd_impl_test ghc_filesystem)
target_compile_options(fwd_impl_test PRIVATE
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-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>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
if(${CMAKE_SYSTEM_NAME} MATCHES "(SunOS|Solaris)")
target_link_libraries(fwd_impl_test xnet)
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
target_link_libraries(fwd_impl_test network)
endif()
SetTestCompileOptions(fwd_impl_test)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
target_compile_definitions(fwd_impl_test PRIVATE _CRT_SECURE_NO_WARNINGS)
target_compile_definitions(fwd_impl_test PRIVATE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN NOMINMAX)
endif()
add_test(fwd_impl_test fwd_impl_test)
@ -77,9 +102,4 @@ if(NOT MSVC)
target_compile_options(exception PRIVATE -fno-exceptions)
endif()
target_include_directories(exception PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include)
target_compile_options(exception PRIVATE
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-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>
$<$<BOOL:${CYGWIN}>:-Wa,-mbig-obj>)
SetTestCompileOptions(exception)

File diff suppressed because it is too large Load Diff

View File

@ -76,6 +76,7 @@ using fstream = ghc::filesystem::fstream;
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#endif
#ifndef GHC_FILESYSTEM_FWD_TEST
@ -98,7 +99,7 @@ using fstream = ghc::filesystem::fstream;
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template <typename TP>
std::time_t to_time_t(TP tp)
static std::time_t to_time_t(TP tp)
{
using namespace std::chrono;
auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now() + system_clock::now());
@ -106,7 +107,7 @@ std::time_t to_time_t(TP tp)
}
template <typename TP>
TP from_time_t(std::time_t t)
static TP from_time_t(std::time_t t)
{
using namespace std::chrono;
auto sctp = system_clock::from_time_t(t);
@ -213,7 +214,8 @@ static void generateFile(const fs::path& pathname, int withSize = -1)
}
#ifdef GHC_OS_WINDOWS
inline bool isWow64Proc()
#if !defined(_WIN64) && defined(KEY_WOW64_64KEY)
static bool isWow64Proc()
{
typedef BOOL(WINAPI * IsWow64Process_t)(HANDLE, PBOOL);
BOOL bIsWow64 = FALSE;
@ -225,6 +227,7 @@ inline bool isWow64Proc()
}
return bIsWow64 == TRUE;
}
#endif
static bool is_symlink_creation_supported()
{
@ -302,13 +305,13 @@ public:
};
template <class T, class U>
bool operator==(TestAllocator<T> const&, TestAllocator<U> const&) noexcept
static bool operator==(TestAllocator<T> const&, TestAllocator<U> const&) noexcept
{
return true;
}
template <class T, class U>
bool operator!=(TestAllocator<T> const& x, TestAllocator<U> const& y) noexcept
static bool operator!=(TestAllocator<T> const& x, TestAllocator<U> const& y) noexcept
{
return !(x == y);
}
@ -362,7 +365,7 @@ TEST_CASE("fs::detail::toUtf8", "[filesystem][fs.detail.utf8]")
}
#endif
TEST_CASE("30.10.8.1 path::preferred_separator", "[filesystem][path][fs.path.generic]")
TEST_CASE("fs.path.generic - path::preferred_separator", "[filesystem][path][fs.path.generic]")
{
#ifdef GHC_OS_WINDOWS
CHECK(fs::path::preferred_separator == '\\');
@ -372,7 +375,7 @@ TEST_CASE("30.10.8.1 path::preferred_separator", "[filesystem][path][fs.path.gen
}
#ifndef GHC_OS_WINDOWS
TEST_CASE("30.10.8.1 path(\"//host\").has_root_name()", "[filesystem][path][fs.path.generic]")
TEST_CASE("fs.path.generic - path(\"//host\").has_root_name()", "[filesystem][path][fs.path.generic]")
{
if (!has_host_root_name_support()) {
WARN("This implementation doesn't support path(\"//host\").has_root_name() == true [C++17 30.12.8.1 par. 4] on this platform, tests based on this are skipped. (Should be okay.)");
@ -380,15 +383,26 @@ TEST_CASE("30.10.8.1 path(\"//host\").has_root_name()", "[filesystem][path][fs.p
}
#endif
TEST_CASE("30.10.8.4.1 path constructors and destructor", "[filesystem][path][fs.path.construct]")
TEST_CASE("fs.path.construct - path constructors and destructor", "[filesystem][path][fs.path.construct]")
{
CHECK("/usr/local/bin" == fs::path("/usr/local/bin").generic_string());
std::string str = "/usr/local/bin";
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
std::u8string u8str = u8"/usr/local/bin";
#endif
std::u16string u16str = u"/usr/local/bin";
std::u32string u32str = U"/usr/local/bin";
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
CHECK(u8str == fs::path(u8str).generic_u8string());
#endif
CHECK(u16str == fs::path(u16str).generic_u16string());
CHECK(u32str == fs::path(u32str).generic_u32string());
CHECK(str == fs::path(str, fs::path::format::generic_format));
CHECK(str == fs::path(str.begin(), str.end()));
CHECK(fs::path(std::wstring(3, 67)) == "CCC");
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
CHECK(str == fs::path(u8str.begin(), u8str.end()));
#endif
CHECK(str == fs::path(u16str.begin(), u16str.end()));
CHECK(str == fs::path(u32str.begin(), u32str.end()));
#ifdef GHC_FILESYSTEM_VERSION
@ -405,7 +419,7 @@ TEST_CASE("30.10.8.4.1 path constructors and destructor", "[filesystem][path][fs
CHECK("//host/foo/bar" == fs::path("//host/foo/bar"));
}
#if !defined(GHC_OS_WINDOWS) && !(defined(GCC_VERSION) && GCC_VERSION < 80100) && !defined(USE_STD_FS)
#if !defined(GHC_OS_WINDOWS) && !(defined(__GLIBCXX__) && !(defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE >= 8))) && !defined(USE_STD_FS)
std::locale loc;
bool testUTF8Locale = false;
try {
@ -432,7 +446,7 @@ TEST_CASE("30.10.8.4.1 path constructors and destructor", "[filesystem][path][fs
#endif
}
TEST_CASE("30.10.8.4.2 path assignments", "[filesystem][path][fs.path.assign]")
TEST_CASE("fs.path.assign - path assignments", "[filesystem][path][fs.path.assign]")
{
fs::path p1{"/foo/bar"};
fs::path p2{"/usr/local"};
@ -467,7 +481,7 @@ TEST_CASE("30.10.8.4.2 path assignments", "[filesystem][path][fs.path.assign]")
REQUIRE(p2 == p3);
}
TEST_CASE("30.10.8.4.3 path appends", "[filesystem][path][fs.path.append]")
TEST_CASE("fs.path.append - path appends", "[filesystem][path][fs.path.append]")
{
#ifdef GHC_OS_WINDOWS
CHECK(fs::path("foo") / "c:/bar" == "c:/bar");
@ -493,7 +507,7 @@ TEST_CASE("30.10.8.4.3 path appends", "[filesystem][path][fs.path.append]")
// TODO: append(first, last)
}
TEST_CASE("30.10.8.4.4 path concatenation", "[filesystem][path][fs.path.concat]")
TEST_CASE("fs.path.concat - path concatenation", "[filesystem][path][fs.path.concat]")
{
CHECK((fs::path("foo") += fs::path("bar")) == "foobar");
CHECK((fs::path("foo") += fs::path("/bar")) == "foo/bar");
@ -532,7 +546,7 @@ TEST_CASE("30.10.8.4.4 path concatenation", "[filesystem][path][fs.path.concat]"
// TODO: contat(first, last)
}
TEST_CASE("30.10.8.4.5 path modifiers", "[filesystem][path][fs.path.modifiers]")
TEST_CASE("fs.path.modifiers - path modifiers", "[filesystem][path][fs.path.modifiers]")
{
fs::path p = fs::path("/foo/bar");
p.clear();
@ -571,7 +585,7 @@ TEST_CASE("30.10.8.4.5 path modifiers", "[filesystem][path][fs.path.modifiers]")
CHECK(p2 == "foo");
}
TEST_CASE("30.10.8.4.6 path native format observers", "[filesystem][path][fs.path.native.obs]")
TEST_CASE("fs.path.native.obs - path native format observers", "[filesystem][path][fs.path.native.obs]")
{
#ifdef GHC_OS_WINDOWS
#if defined(IS_WCHAR_PATH) || defined(GHC_USE_WCHAR_T)
@ -609,7 +623,7 @@ TEST_CASE("30.10.8.4.6 path native format observers", "[filesystem][path][fs.pat
#endif
}
TEST_CASE("30.10.8.4.7 path generic format observers", "[filesystem][path][fs.path.generic.obs]")
TEST_CASE("fs.path.generic.obs - path generic format observers", "[filesystem][path][fs.path.generic.obs]")
{
#ifdef GHC_OS_WINDOWS
#ifndef IS_WCHAR_PATH
@ -644,7 +658,7 @@ TEST_CASE("30.10.8.4.7 path generic format observers", "[filesystem][path][fs.pa
#endif
}
TEST_CASE("30.10.8.4.8 path compare", "[filesystem][path][fs.path.compare]")
TEST_CASE("fs.path.compare - path compare", "[filesystem][path][fs.path.compare]")
{
CHECK(fs::path("/foo/b").compare("/foo/a") > 0);
CHECK(fs::path("/foo/b").compare("/foo/b") == 0);
@ -670,7 +684,7 @@ TEST_CASE("30.10.8.4.8 path compare", "[filesystem][path][fs.path.compare]")
#endif // LWG_2936_BEHAVIOUR
}
TEST_CASE("30.10.8.4.9 path decomposition", "[filesystem][path][fs.path.decompose]")
TEST_CASE("fs.path.decompose - path decomposition", "[filesystem][path][fs.path.decompose]")
{
// root_name()
CHECK(fs::path("").root_name() == "");
@ -778,6 +792,9 @@ TEST_CASE("30.10.8.4.9 path decomposition", "[filesystem][path][fs.path.decompos
CHECK(fs::path("C:/foo").filename() == "foo");
CHECK(fs::path("C:\\foo").filename() == "foo");
CHECK(fs::path("C:foo").filename() == "foo");
CHECK(fs::path("t:est.txt").filename() == "est.txt");
#else
CHECK(fs::path("t:est.txt").filename() == "t:est.txt");
#endif
// stem()
@ -795,6 +812,13 @@ TEST_CASE("30.10.8.4.9 path decomposition", "[filesystem][path][fs.path.decompos
CHECK(fs::path("/foo/.profile").stem() == ".profile");
CHECK(fs::path(".bar").stem() == ".bar");
CHECK(fs::path("..bar").stem() == ".");
#ifdef GHC_OS_WINDOWS
CHECK(fs::path("t:est.txt").stem() == "est");
#else
CHECK(fs::path("t:est.txt").stem() == "t:est");
#endif
CHECK(fs::path("/foo/.").stem() == ".");
CHECK(fs::path("/foo/..").stem() == "..");
// extension()
CHECK(fs::path("/foo/bar.txt").extension() == ".txt");
@ -802,6 +826,9 @@ TEST_CASE("30.10.8.4.9 path decomposition", "[filesystem][path][fs.path.decompos
CHECK(fs::path("/foo/.profile").extension() == "");
CHECK(fs::path(".bar").extension() == "");
CHECK(fs::path("..bar").extension() == ".bar");
CHECK(fs::path("t:est.txt").extension() == ".txt");
CHECK(fs::path("/foo/.").extension() == "");
CHECK(fs::path("/foo/..").extension() == "");
if (has_host_root_name_support()) {
// //host-based root-names
@ -820,7 +847,7 @@ TEST_CASE("30.10.8.4.9 path decomposition", "[filesystem][path][fs.path.decompos
}
}
TEST_CASE("30.10.8.4.10 path query", "[fielsystem][path][fs.path.query]")
TEST_CASE("fs.path.query - path query", "[fielsystem][path][fs.path.query]")
{
// empty
CHECK(fs::path("").empty());
@ -918,7 +945,7 @@ TEST_CASE("30.10.8.4.10 path query", "[fielsystem][path][fs.path.query]")
}
}
TEST_CASE("30.10.8.4.11 path generation", "[filesystem][path][fs.path.gen]")
TEST_CASE("fs.path.gen - path generation", "[filesystem][path][fs.path.gen]")
{
// lexically_normal()
CHECK(fs::path("foo/./bar/..").lexically_normal() == "foo/");
@ -938,6 +965,10 @@ TEST_CASE("30.10.8.4.11 path generation", "[filesystem][path][fs.path.gen]")
// lexically_relative()
CHECK(fs::path("/a/d").lexically_relative("/a/b/c") == "../../d");
CHECK(fs::path("/a/b/c").lexically_relative("/a/d") == "../b/c");
CHECK(fs::path("/a/b/c").lexically_relative("/a/b/c/d/..") == ".");
CHECK(fs::path("/a/b/c/").lexically_relative("/a/b/c/d/..") == ".");
CHECK(fs::path("").lexically_relative("/a/..") == "");
CHECK(fs::path("").lexically_relative("a/..") == ".");
CHECK(fs::path("a/b/c").lexically_relative("a") == "b/c");
CHECK(fs::path("a/b/c").lexically_relative("a/b/c/x/y") == "../..");
CHECK(fs::path("a/b/c").lexically_relative("a/b/c") == ".");
@ -1005,7 +1036,7 @@ static std::string reverseIterateResult(const fs::path& path)
return result.str();
}
TEST_CASE("30.10.8.5 path iterators", "[filesystem][path][fs.path.itr]")
TEST_CASE("fs.path.itr - path iterators", "[filesystem][path][fs.path.itr]")
{
CHECK(iterateResult(fs::path()).empty());
CHECK("." == iterateResult(fs::path(".")));
@ -1088,7 +1119,7 @@ TEST_CASE("30.10.8.5 path iterators", "[filesystem][path][fs.path.itr]")
}
}
TEST_CASE("30.10.8.6 path non-member functions", "[filesystem][path][fs.path.nonmember]")
TEST_CASE("fs.path.nonmember - path non-member functions", "[filesystem][path][fs.path.nonmember]")
{
fs::path p1("foo/bar");
fs::path p2("some/other");
@ -1110,7 +1141,7 @@ TEST_CASE("30.10.8.6 path non-member functions", "[filesystem][path][fs.path.non
CHECK(p1 / p2 == "some/other/foo/bar");
}
TEST_CASE("30.10.8.6.1 path inserter and extractor", "[filesystem][path][fs.path.io]")
TEST_CASE("fs.path.io - path inserter and extractor", "[filesystem][path][fs.path.io]")
{
{
std::ostringstream os;
@ -1160,7 +1191,7 @@ TEST_CASE("30.10.8.6.1 path inserter and extractor", "[filesystem][path][fs.path
}
}
TEST_CASE("30.10.8.6.2 path factory functions", "[filesystem][path][fs.path.factory]")
TEST_CASE("fs.path.factory - path factory functions", "[filesystem][path][fs.path.factory]")
{
CHECK(fs::u8path("foo/bar") == fs::path("foo/bar"));
CHECK(fs::u8path("foo/bar") == fs::path("foo/bar"));
@ -1168,7 +1199,7 @@ TEST_CASE("30.10.8.6.2 path factory functions", "[filesystem][path][fs.path.fact
CHECK(fs::u8path(str.begin(), str.end()) == str);
}
TEST_CASE("30.10.9 class filesystem_error", "[filesystem][filesystem_error][fs.class.filesystem_error]")
TEST_CASE("fs.class.filesystem_error - class filesystem_error", "[filesystem][filesystem_error][fs.class.filesystem_error]")
{
std::error_code ec(1, std::system_category());
fs::filesystem_error fse("None", std::error_code());
@ -1187,12 +1218,12 @@ TEST_CASE("30.10.9 class filesystem_error", "[filesystem][filesystem_error][fs.c
CHECK(fse.path2() == "some/other");
}
constexpr fs::perms constExprOwnerAll()
static constexpr fs::perms constExprOwnerAll()
{
return fs::perms::owner_read | fs::perms::owner_write | fs::perms::owner_exec;
}
TEST_CASE("30.10.10.4 enum class perms", "[filesystem][enum][fs.enum]")
TEST_CASE("fs.enum - enum class perms", "[filesystem][enum][fs.enum]")
{
static_assert(constExprOwnerAll() == fs::perms::owner_all, "constexpr didn't result in owner_all");
CHECK((fs::perms::owner_read | fs::perms::owner_write | fs::perms::owner_exec) == fs::perms::owner_all);
@ -1202,7 +1233,7 @@ TEST_CASE("30.10.10.4 enum class perms", "[filesystem][enum][fs.enum]")
CHECK((fs::perms::all | fs::perms::set_uid | fs::perms::set_gid | fs::perms::sticky_bit) == fs::perms::mask);
}
TEST_CASE("30.10.11 class file_status", "[filesystem][file_status][fs.class.file_status]")
TEST_CASE("fs.class.file_status - class file_status", "[filesystem][file_status][fs.class.file_status]")
{
{
fs::file_status fs;
@ -1250,7 +1281,7 @@ TEST_CASE("30.10.11 class file_status", "[filesystem][file_status][fs.class.file
#endif
}
TEST_CASE("30.10.12 class directory_entry", "[filesystem][directory_entry][fs.dir.entry]")
TEST_CASE("fs.dir.entry - class directory_entry", "[filesystem][directory_entry][fs.dir.entry]")
{
TemporaryDirectory t;
std::error_code ec;
@ -1365,9 +1396,19 @@ TEST_CASE("30.10.12 class directory_entry", "[filesystem][directory_entry][fs.di
CHECK(!(d2 != d2));
CHECK(d1 == d1);
CHECK(!(d1 == d2));
if(is_symlink_creation_supported()) {
fs::create_symlink(t.path() / "nonexistent", t.path() / "broken");
for (auto d3 : fs::directory_iterator(t.path())) {
CHECK_NOTHROW(d3.symlink_status());
CHECK_NOTHROW(d3.status());
CHECK_NOTHROW(d3.refresh());
}
fs::directory_entry entry(t.path() / "broken");
CHECK_NOTHROW(entry.refresh());
}
}
TEST_CASE("30.10.13 class directory_iterator", "[filesystem][directory_iterator][fs.class.directory_iterator]")
TEST_CASE("fs.class.directory_iterator - class directory_iterator", "[filesystem][directory_iterator][fs.class.directory_iterator]")
{
{
TemporaryDirectory t;
@ -1428,7 +1469,7 @@ TEST_CASE("30.10.13 class directory_iterator", "[filesystem][directory_iterator]
}
}
TEST_CASE("30.10.14 class recursive_directory_iterator", "[filesystem][recursive_directory_iterator][fs.class.rec.dir.itr]")
TEST_CASE("fs.class.rec.dir.itr - class recursive_directory_iterator", "[filesystem][recursive_directory_iterator][fs.class.rec.dir.itr]")
{
{
auto iter = fs::recursive_directory_iterator(".");
@ -1584,9 +1625,40 @@ TEST_CASE("30.10.14 class recursive_directory_iterator", "[filesystem][recursive
}
CHECK(os.str() == "[./a,0],[./d1,0],[./d1/d2,1],[./e,0],");
}
if (is_symlink_creation_supported()) {
TemporaryDirectory t(TempOpt::change_path);
fs::create_directory("d1");
generateFile("d1/a");
fs::create_directory("d2");
generateFile("d2/b");
fs::create_directory_symlink("../d1", "d2/ds1");
fs::create_directory_symlink("d3", "d2/ds2");
std::multiset<std::string> result;
REQUIRE_NOTHROW([&](){
for (const auto& de : fs::recursive_directory_iterator("d2", fs::directory_options::follow_directory_symlink)) {
result.insert(de.path().generic_string());
}
}());
std::stringstream os;
for(const auto& p : result) {
os << p << ",";
}
CHECK(os.str() == "d2/b,d2/ds1,d2/ds1/a,d2/ds2,");
os.str("");
result.clear();
REQUIRE_NOTHROW([&](){
for (const auto& de : fs::recursive_directory_iterator("d2")) {
result.insert(de.path().generic_string());
}
}());
for(const auto& p : result) {
os << p << ",";
}
CHECK(os.str() == "d2/b,d2/ds1,d2/ds2,");
}
}
TEST_CASE("30.10.15.1 absolute", "[filesystem][operations][fs.op.absolute]")
TEST_CASE("fs.op.absolute - absolute", "[filesystem][operations][fs.op.absolute]")
{
CHECK(fs::absolute("") == fs::current_path() / "");
CHECK(fs::absolute(fs::current_path()) == fs::current_path());
@ -1600,7 +1672,7 @@ TEST_CASE("30.10.15.1 absolute", "[filesystem][operations][fs.op.absolute]")
CHECK(!ec);
}
TEST_CASE("30.10.15.2 canonical", "[filesystem][operations][fs.op.canonical]")
TEST_CASE("fs.op.canonical - canonical", "[filesystem][operations][fs.op.canonical]")
{
CHECK_THROWS_AS(fs::canonical(""), fs::filesystem_error);
{
@ -1643,7 +1715,7 @@ TEST_CASE("30.10.15.2 canonical", "[filesystem][operations][fs.op.canonical]")
}
}
TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
TEST_CASE("fs.op.copy - copy", "[filesystem][operations][fs.op.copy]")
{
{
TemporaryDirectory t(TempOpt::change_path);
@ -1712,7 +1784,7 @@ TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
#endif
}
TEST_CASE("30.10.15.4 copy_file", "[filesystem][operations][fs.op.copy_file]")
TEST_CASE("fs.op.copy_file - copy_file", "[filesystem][operations][fs.op.copy_file]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -1735,9 +1807,22 @@ TEST_CASE("30.10.15.4 copy_file", "[filesystem][operations][fs.op.copy_file]")
CHECK_NOTHROW(fs::copy_file("foobar", "foobar2", ec));
CHECK(ec);
CHECK(!fs::exists("foobar"));
fs::path file1("temp1.txt");
fs::path file2("temp2.txt");
generateFile(file1, 200);
generateFile(file2, 200);
auto allWrite = fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write;
CHECK_NOTHROW(fs::permissions(file1, allWrite, fs::perm_options::remove));
CHECK((fs::status(file1).permissions() & fs::perms::owner_write) != fs::perms::owner_write);
CHECK_NOTHROW(fs::permissions(file2, allWrite, fs::perm_options::add));
CHECK((fs::status(file2).permissions() & fs::perms::owner_write) == fs::perms::owner_write);
fs::copy_file(file1, file2, fs::copy_options::overwrite_existing);
CHECK((fs::status(file2).permissions() & fs::perms::owner_write) != fs::perms::owner_write);
CHECK_NOTHROW(fs::permissions(file1, allWrite, fs::perm_options::add));
CHECK_NOTHROW(fs::permissions(file2, allWrite, fs::perm_options::add));
}
TEST_CASE("30.10.15.5 copy_symlink", "[filesystem][operations][fs.op.copy_symlink]")
TEST_CASE("fs.op.copy_symlink - copy_symlink", "[filesystem][operations][fs.op.copy_symlink]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -1762,7 +1847,7 @@ TEST_CASE("30.10.15.5 copy_symlink", "[filesystem][operations][fs.op.copy_symlin
CHECK(ec);
}
TEST_CASE("30.10.15.6 create_directories", "[filesystem][operations][fs.op.create_directories]")
TEST_CASE("fs.op.create_directories - create_directories", "[filesystem][operations][fs.op.create_directories]")
{
TemporaryDirectory t;
fs::path p = t.path() / "testdir";
@ -1809,7 +1894,7 @@ TEST_CASE("30.10.15.6 create_directories", "[filesystem][operations][fs.op.creat
#endif
}
TEST_CASE("30.10.15.7 create_directory", "[filesystem][operations][fs.op.create_directory]")
TEST_CASE("fs.op.create_directory - create_directory", "[filesystem][operations][fs.op.create_directory]")
{
TemporaryDirectory t;
fs::path p = t.path() / "testdir";
@ -1856,7 +1941,7 @@ TEST_CASE("30.10.15.7 create_directory", "[filesystem][operations][fs.op.create_
#endif
}
TEST_CASE("30.10.15.8 create_directory_symlink", "[filesystem][operations][fs.op.create_directory_symlink]")
TEST_CASE("fs.op.create_directory_symlink - create_directory_symlink", "[filesystem][operations][fs.op.create_directory_symlink]")
{
if (is_symlink_creation_supported()) {
TemporaryDirectory t;
@ -1875,7 +1960,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]")
TEST_CASE("fs.op.create_hard_link - create_hard_link", "[filesystem][operations][fs.op.create_hard_link]")
{
#ifndef GHC_OS_WEB
TemporaryDirectory t(TempOpt::change_path);
@ -1894,7 +1979,7 @@ TEST_CASE("30.10.15.9 create_hard_link", "[filesystem][operations][fs.op.create_
#endif
}
TEST_CASE("30.10.15.10 create_symlink", "[filesystem][operations][fs.op.create_symlink]")
TEST_CASE("fs.op.create_symlink - create_symlink", "[filesystem][operations][fs.op.create_symlink]")
{
if (is_symlink_creation_supported()) {
TemporaryDirectory t;
@ -1913,7 +1998,7 @@ TEST_CASE("30.10.15.10 create_symlink", "[filesystem][operations][fs.op.create_s
}
}
TEST_CASE("30.10.15.11 current_path", "[filesystem][operations][fs.op.current_path]")
TEST_CASE("fs.op.current_path - current_path", "[filesystem][operations][fs.op.current_path]")
{
TemporaryDirectory t;
std::error_code ec;
@ -1928,7 +2013,7 @@ TEST_CASE("30.10.15.11 current_path", "[filesystem][operations][fs.op.current_pa
CHECK(ec);
}
TEST_CASE("30.10.15.12 equivalent", "[filesystem][operations][fs.op.equivalent]")
TEST_CASE("fs.op.equivalent - equivalent", "[filesystem][operations][fs.op.equivalent]")
{
TemporaryDirectory t(TempOpt::change_path);
generateFile("foo", 1234);
@ -1982,7 +2067,7 @@ TEST_CASE("30.10.15.12 equivalent", "[filesystem][operations][fs.op.equivalent]"
#endif
}
TEST_CASE("30.10.15.13 exists", "[filesystem][operations][fs.op.exists]")
TEST_CASE("fs.op.exists - exists", "[filesystem][operations][fs.op.exists]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -1992,6 +2077,9 @@ TEST_CASE("30.10.15.13 exists", "[filesystem][operations][fs.op.exists]")
CHECK(!ec);
ec = std::error_code(42, std::system_category());
CHECK(!fs::exists("foo", ec));
#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API)
CHECK(!fs::exists(u8"foo"));
#endif
CHECK(!ec);
ec.clear();
CHECK(fs::exists(t.path()));
@ -2007,7 +2095,7 @@ TEST_CASE("30.10.15.13 exists", "[filesystem][operations][fs.op.exists]")
#endif
}
TEST_CASE("30.10.15.14 file_size", "[filesystem][operations][fs.op.file_size]")
TEST_CASE("fs.op.file_size - file_size", "[filesystem][operations][fs.op.file_size]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2038,7 +2126,7 @@ static uintmax_t getHardlinkCount(const fs::path& p)
}
#endif
TEST_CASE("30.10.15.15 hard_link_count", "[filesystem][operations][fs.op.hard_link_count]")
TEST_CASE("fs.op.hard_link_count - hard_link_count", "[filesystem][operations][fs.op.hard_link_count]")
{
#ifndef GHC_OS_WEB
TemporaryDirectory t(TempOpt::change_path);
@ -2117,6 +2205,7 @@ public:
fs::path character_path() const
{
#ifndef GHC_OS_SOLARIS
std::error_code ec;
if (fs::exists("/dev/null", ec)) {
return "/dev/null";
@ -2124,6 +2213,7 @@ public:
else if (fs::exists("NUL", ec)) {
return "NUL";
}
#endif
return fs::path();
}
fs::path temp_path() const { return _t.path(); }
@ -2134,7 +2224,7 @@ private:
bool _hasSocket;
};
TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.16 is_block_file", "[filesystem][operations][fs.op.is_block_file]")
TEST_CASE_METHOD(FileTypeMixFixture, "fs.op.is_block_file - is_block_file", "[filesystem][operations][fs.op.is_block_file]")
{
std::error_code ec;
CHECK(!fs::is_block_file("directory"));
@ -2163,7 +2253,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.16 is_block_file", "[filesystem][
CHECK(!fs::is_block_file(fs::file_status(fs::file_type::unknown)));
}
TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.17 is_character_file", "[filesystem][operations][fs.op.is_character_file]")
TEST_CASE_METHOD(FileTypeMixFixture, "fs.op.is_character_file - is_character_file", "[filesystem][operations][fs.op.is_character_file]")
{
std::error_code ec;
CHECK(!fs::is_character_file("directory"));
@ -2192,7 +2282,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.17 is_character_file", "[filesyst
CHECK(!fs::is_character_file(fs::file_status(fs::file_type::unknown)));
}
TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.18 is_directory", "[filesystem][operations][fs.op.is_directory]")
TEST_CASE_METHOD(FileTypeMixFixture, "fs.op.is_directory - is_directory", "[filesystem][operations][fs.op.is_directory]")
{
std::error_code ec;
CHECK(fs::is_directory("directory"));
@ -2221,7 +2311,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.18 is_directory", "[filesystem][o
CHECK(!fs::is_directory(fs::file_status(fs::file_type::unknown)));
}
TEST_CASE("30.10.15.19 is_empty", "[filesystem][operations][fs.op.is_empty]")
TEST_CASE("fs.op.is_empty - is_empty", "[filesystem][operations][fs.op.is_empty]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2243,7 +2333,7 @@ TEST_CASE("30.10.15.19 is_empty", "[filesystem][operations][fs.op.is_empty]")
CHECK(ec);
}
TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.20 is_fifo", "[filesystem][operations][fs.op.is_fifo]")
TEST_CASE_METHOD(FileTypeMixFixture, "fs.op.is_fifo - is_fifo", "[filesystem][operations][fs.op.is_fifo]")
{
std::error_code ec;
CHECK(!fs::is_fifo("directory"));
@ -2272,7 +2362,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.20 is_fifo", "[filesystem][operat
CHECK(!fs::is_fifo(fs::file_status(fs::file_type::unknown)));
}
TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.21 is_other", "[filesystem][operations][fs.op.is_other]")
TEST_CASE_METHOD(FileTypeMixFixture, "fs.op.is_other - is_other", "[filesystem][operations][fs.op.is_other]")
{
std::error_code ec;
CHECK(!fs::is_other("directory"));
@ -2301,7 +2391,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.21 is_other", "[filesystem][opera
CHECK(fs::is_other(fs::file_status(fs::file_type::unknown)));
}
TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.22 is_regular_file", "[filesystem][operations][fs.op.is_regular_file]")
TEST_CASE_METHOD(FileTypeMixFixture, "fs.op.is_regular_file - is_regular_file", "[filesystem][operations][fs.op.is_regular_file]")
{
std::error_code ec;
CHECK(!fs::is_regular_file("directory"));
@ -2330,7 +2420,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.22 is_regular_file", "[filesystem
CHECK(!fs::is_regular_file(fs::file_status(fs::file_type::unknown)));
}
TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.23 is_socket", "[filesystem][operations][fs.op.is_socket]")
TEST_CASE_METHOD(FileTypeMixFixture, "fs.op.is_socket - is_socket", "[filesystem][operations][fs.op.is_socket]")
{
std::error_code ec;
CHECK(!fs::is_socket("directory"));
@ -2359,7 +2449,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.23 is_socket", "[filesystem][oper
CHECK(!fs::is_socket(fs::file_status(fs::file_type::unknown)));
}
TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.24 is_symlink", "[filesystem][operations][fs.op.is_symlink]")
TEST_CASE_METHOD(FileTypeMixFixture, "fs.op.is_symlink - is_symlink", "[filesystem][operations][fs.op.is_symlink]")
{
std::error_code ec;
CHECK(!fs::is_symlink("directory"));
@ -2402,7 +2492,7 @@ static fs::file_time_type timeFromString(const std::string& str)
}
#endif
TEST_CASE("30.10.15.25 last_write_time", "[filesystem][operations][fs.op.last_write_time]")
TEST_CASE("fs.op.last_write_time - last_write_time", "[filesystem][operations][fs.op.last_write_time]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2437,7 +2527,7 @@ TEST_CASE("30.10.15.25 last_write_time", "[filesystem][operations][fs.op.last_wr
#endif
}
TEST_CASE("30.10.15.26 permissions", "[filesystem][operations][fs.op.permissions]")
TEST_CASE("fs.op.permissions - permissions", "[filesystem][operations][fs.op.permissions]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2445,8 +2535,13 @@ TEST_CASE("30.10.15.26 permissions", "[filesystem][operations][fs.op.permissions
auto allWrite = fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write;
CHECK_NOTHROW(fs::permissions("foo", allWrite, fs::perm_options::remove));
CHECK((fs::status("foo").permissions() & fs::perms::owner_write) != fs::perms::owner_write);
CHECK_THROWS_AS(fs::resize_file("foo", 1024), fs::filesystem_error);
CHECK(fs::file_size("foo") == 512);
#if !defined(GHC_OS_WINDOWS)
if (geteuid() != 0)
#endif
{
CHECK_THROWS_AS(fs::resize_file("foo", 1024), fs::filesystem_error);
CHECK(fs::file_size("foo") == 512);
}
CHECK_NOTHROW(fs::permissions("foo", fs::perms::owner_write, fs::perm_options::add));
CHECK((fs::status("foo").permissions() & fs::perms::owner_write) == fs::perms::owner_write);
CHECK_NOTHROW(fs::resize_file("foo", 2048));
@ -2457,7 +2552,7 @@ TEST_CASE("30.10.15.26 permissions", "[filesystem][operations][fs.op.permissions
CHECK_THROWS_AS(fs::permissions("bar", fs::perms::owner_write, static_cast<fs::perm_options>(0)), fs::filesystem_error);
}
TEST_CASE("30.10.15.27 proximate", "[filesystem][operations][fs.op.proximate]")
TEST_CASE("fs.op.proximate - proximate", "[filesystem][operations][fs.op.proximate]")
{
std::error_code ec;
CHECK(fs::proximate("/a/d", "/a/b/c") == "../../d");
@ -2487,7 +2582,7 @@ TEST_CASE("30.10.15.27 proximate", "[filesystem][operations][fs.op.proximate]")
#endif
}
TEST_CASE("30.10.15.28 read_symlink", "[filesystem][operations][fs.op.read_symlink]")
TEST_CASE("fs.op.read_symlink - read_symlink", "[filesystem][operations][fs.op.read_symlink]")
{
if (is_symlink_creation_supported()) {
TemporaryDirectory t(TempOpt::change_path);
@ -2503,7 +2598,7 @@ TEST_CASE("30.10.15.28 read_symlink", "[filesystem][operations][fs.op.read_symli
}
}
TEST_CASE("30.10.15.29 relative", "[filesystem][operations][fs.op.relative]")
TEST_CASE("fs.op.relative - relative", "[filesystem][operations][fs.op.relative]")
{
CHECK(fs::relative("/a/d", "/a/b/c") == "../../d");
CHECK(fs::relative("/a/b/c", "/a/d") == "../b/c");
@ -2516,7 +2611,7 @@ TEST_CASE("30.10.15.29 relative", "[filesystem][operations][fs.op.relative]")
CHECK(!ec);
}
TEST_CASE("30.10.15.30 remove", "[filesystem][operations][fs.op.remove]")
TEST_CASE("fs.op.remove - remove", "[filesystem][operations][fs.op.remove]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2540,7 +2635,7 @@ TEST_CASE("30.10.15.30 remove", "[filesystem][operations][fs.op.remove]")
CHECK(!ec);
}
TEST_CASE("30.10.15.31 remove_all", "[filesystem][operations][fs.op.remove_all]")
TEST_CASE("fs.op.remove_all - remove_all", "[filesystem][operations][fs.op.remove_all]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2556,11 +2651,15 @@ TEST_CASE("30.10.15.31 remove_all", "[filesystem][operations][fs.op.remove_all]"
CHECK_NOTHROW(fs::remove_all("dir1/non-existing", ec));
CHECK(!ec);
CHECK(fs::remove_all("dir1/non-existing", ec) == 0);
if (is_symlink_creation_supported()) {
fs::create_directory_symlink("dir1", "dir1link");
CHECK(fs::remove_all("dir1link") == 1);
}
CHECK(fs::remove_all("dir1") == 5);
CHECK(fs::directory_iterator(t.path()) == fs::directory_iterator());
}
TEST_CASE("30.10.15.32 rename", "[filesystem][operations][fs.op.rename]")
TEST_CASE("fs.op.rename - rename", "[filesystem][operations][fs.op.rename]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2584,7 +2683,7 @@ TEST_CASE("30.10.15.32 rename", "[filesystem][operations][fs.op.rename]")
CHECK(!fs::exists("barfoo"));
}
TEST_CASE("30.10.15.33 resize_file", "[filesystem][operations][fs.op.resize_file]")
TEST_CASE("fs.op.resize_file - resize_file", "[filesystem][operations][fs.op.resize_file]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2602,7 +2701,7 @@ TEST_CASE("30.10.15.33 resize_file", "[filesystem][operations][fs.op.resize_file
CHECK(!fs::exists("bar"));
}
TEST_CASE("30.10.15.34 space", "[filesystem][operations][fs.op.space]")
TEST_CASE("fs.op.space - space", "[filesystem][operations][fs.op.space]")
{
{
fs::space_info si;
@ -2634,7 +2733,7 @@ TEST_CASE("30.10.15.34 space", "[filesystem][operations][fs.op.space]")
#endif
}
TEST_CASE("30.10.15.35 status", "[filesystem][operations][fs.op.status]")
TEST_CASE("fs.op.status - status", "[filesystem][operations][fs.op.status]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2662,7 +2761,7 @@ TEST_CASE("30.10.15.35 status", "[filesystem][operations][fs.op.status]")
}
}
TEST_CASE("30.10.15.36 status_known", "[filesystem][operations][fs.op.status_known]")
TEST_CASE("fs.op.status_known - status_known", "[filesystem][operations][fs.op.status_known]")
{
CHECK(!fs::status_known(fs::file_status()));
CHECK(fs::status_known(fs::file_status(fs::file_type::not_found)));
@ -2675,7 +2774,7 @@ TEST_CASE("30.10.15.36 status_known", "[filesystem][operations][fs.op.status_kno
CHECK(fs::status_known(fs::file_status(fs::file_type::unknown)));
}
TEST_CASE("30.10.15.37 symlink_status", "[filesystem][operations][fs.op.symlink_status]")
TEST_CASE("fs.op.symlink_status - symlink_status", "[filesystem][operations][fs.op.symlink_status]")
{
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
@ -2702,7 +2801,7 @@ TEST_CASE("30.10.15.37 symlink_status", "[filesystem][operations][fs.op.symlink_
}
}
TEST_CASE("30.10.15.38 temporary_directory_path", "[filesystem][operations][fs.op.temp_dir_path]")
TEST_CASE("fs.op.temp_dir_path - temporary_directory_path", "[filesystem][operations][fs.op.temp_dir_path]")
{
std::error_code ec;
CHECK_NOTHROW(fs::exists(fs::temp_directory_path()));
@ -2711,7 +2810,7 @@ TEST_CASE("30.10.15.38 temporary_directory_path", "[filesystem][operations][fs.o
CHECK(!ec);
}
TEST_CASE("30.10.15.39 weakly_canonical", "[filesystem][operations][fs.op.weakly_canonical]")
TEST_CASE("fs.op.weakly_canonical - weakly_canonical", "[filesystem][operations][fs.op.weakly_canonical]")
{
INFO("This might fail on std::implementations that return fs::current_path() for fs::canonical(\"\")");
CHECK(fs::weakly_canonical("") == ".");
@ -2803,13 +2902,15 @@ TEST_CASE("Windows: Long filename support", "[filesystem][path][fs.path.win.long
CHECK_NOTHROW(fs::create_directory(dir));
CHECK(fs::exists(dir));
generateFile(dir / "f0");
CHECK(fs::exists(dir / "f0"));
auto native = dir.u8string();
if (native.substr(0, 4) == u8"\\\\?\\") {
break;
}
REQUIRE(fs::exists(dir / "f0"));
}
CHECK(c <= 'Z');
CHECK(c > 'Z');
fs::remove_all(fs::current_path() / std::string(16, 'A'));
CHECK(!fs::exists(fs::current_path() / std::string(16, 'A')));
CHECK_NOTHROW(fs::create_directories(dir));
CHECK(fs::exists(dir));
generateFile(dir / "f0");
CHECK(fs::exists(dir / "f0"));
#else
WARN("Windows specific tests are empty on non-Windows systems.");
#endif
@ -2869,3 +2970,31 @@ TEST_CASE("Windows: path namespace handling", "[filesystem][path][fs.path.win.na
WARN("Windows specific tests are empty on non-Windows systems.");
#endif
}
TEST_CASE("Windows: Mapped folders handling ", "[filesystem][fs.win][fs.win.mapped]")
{
#ifdef GHC_OS_WINDOWS
// this test expects a mapped volume on C:\\fs-test as is the case on the development test system
// does nothing on other systems
if (fs::exists("C:\\fs-test")) {
CHECK(fs::canonical("C:\\fs-test\\Test.txt").string() == "C:\\fs-test\\Test.txt");
}
#else
WARN("Windows specific tests are empty on non-Windows systems.");
#endif
}
TEST_CASE("Windows: Deletion of Read-only Files", "[filesystem][fs.win][fs.win.remove]")
{
#ifdef GHC_OS_WINDOWS
TemporaryDirectory t(TempOpt::change_path);
std::error_code ec;
generateFile("foo", 512);
auto allWrite = fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write;
CHECK_NOTHROW(fs::permissions("foo", allWrite, fs::perm_options::remove));
CHECK_NOTHROW(fs::remove("foo"));
CHECK(!fs::exists("foo"));
#else
WARN("Windows specific tests are empty on non-Windows systems.");
#endif
}

View File

@ -3,7 +3,6 @@
// where exactly one cpp includes fs_impl.hpp and all others use
// fs_fwd.hpp (to test this with maximum functionality, the unit tests
// are included here, signaling they should only include the fs_fwd.hpp)
#define NOMINMAX
#include <ghc/fs_impl.hpp>
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

View File

@ -27,7 +27,7 @@
#include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem;
// This test and the one in multi2.cpp doesn't actualy test relevant functionality,
// This test and the one in multi2.cpp doesn't actually test relevant functionality,
// it is just used to check that it is possible to include filesystem.h in multiple
// source files.
TEST_CASE("Multifile-test 1", "[multi]")