Fix lexically_normal() to correctly preserve unresolved parent components in relative paths

This commit is contained in:
Steffen Schümann 2026-07-11 09:58:07 +02:00
parent 8ae8ec1582
commit 87157acd6c
3 changed files with 17 additions and 5 deletions

View File

@ -651,6 +651,9 @@ to the expected behavior.
* Fix for [#203](https://github.com/gulrak/filesystem/issues/203), directory * Fix for [#203](https://github.com/gulrak/filesystem/issues/203), directory
iteration and `proximate()` are available in builds without exception iteration and `proximate()` are available in builds without exception
support, with iteration errors terminating the process. support, with iteration errors terminating the process.
* Fix for [#185](https://github.com/gulrak/filesystem/issues/185),
`lexically_normal()` now preserves unresolved parent components in relative
paths.
* Pull requests [#198](https://github.com/gulrak/filesystem/pull/198) and * Pull requests [#198](https://github.com/gulrak/filesystem/pull/198) and
[#199](https://github.com/gulrak/filesystem/pull/199), updated CI for current [#199](https://github.com/gulrak/filesystem/pull/199), updated CI for current
runners and compiler toolchains, retaining legacy compiler and MSVC v142 runners and compiler toolchains, retaining legacy compiler and MSVC v142

View File

@ -3269,12 +3269,18 @@ GHC_INLINE path path::lexically_normal() const
if (dest == root) { if (dest == root) {
continue; continue;
} }
else if (*(--dest.end()) != "..") { else {
if (dest._path.back() == preferred_separator) { auto last = --dest.end();
dest._path.pop_back(); if (last->empty() && last != dest.begin()) {
--last;
}
if (!last->empty() && *last != "..") {
if (dest._path.back() == preferred_separator) {
dest._path.pop_back();
}
dest.remove_filename();
continue;
} }
dest.remove_filename();
continue;
} }
} }
if (!(s.empty() && lastDotDot)) { if (!(s.empty() && lastDotDot)) {

View File

@ -956,6 +956,9 @@ TEST_CASE("fs.path.gen - path generation", "[filesystem][path][fs.path.gen]")
CHECK(fs::path("ab/cd/ef/../../qw").lexically_normal() == "ab/qw"); CHECK(fs::path("ab/cd/ef/../../qw").lexically_normal() == "ab/qw");
CHECK(fs::path("a/b/../../../c").lexically_normal() == "../c"); CHECK(fs::path("a/b/../../../c").lexically_normal() == "../c");
CHECK(fs::path("../").lexically_normal() == ".."); CHECK(fs::path("../").lexically_normal() == "..");
CHECK(fs::path("./../foo/../bar").lexically_normal() == "../bar");
CHECK(fs::path("./../foo/../../bar").lexically_normal() == "../../bar");
CHECK(fs::path("../../foo/../bar").lexically_normal() == "../../bar");
#ifdef GHC_OS_WINDOWS #ifdef GHC_OS_WINDOWS
CHECK(fs::path("\\/\\///\\/").lexically_normal() == "/"); CHECK(fs::path("\\/\\///\\/").lexically_normal() == "/");
CHECK(fs::path("a/b/..\\//..///\\/../c\\\\/").lexically_normal() == "../c/"); CHECK(fs::path("a/b/..\\//..///\\/../c\\\\/").lexically_normal() == "../c/");