diff --git a/README.md b/README.md index f126dfd..8de7664 100644 --- a/README.md +++ b/README.md @@ -651,6 +651,9 @@ to the expected behavior. * Fix for [#203](https://github.com/gulrak/filesystem/issues/203), directory iteration and `proximate()` are available in builds without exception 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 [#199](https://github.com/gulrak/filesystem/pull/199), updated CI for current runners and compiler toolchains, retaining legacy compiler and MSVC v142 diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index 985472b..8f6529f 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -3269,12 +3269,18 @@ GHC_INLINE path path::lexically_normal() const if (dest == root) { continue; } - else if (*(--dest.end()) != "..") { - if (dest._path.back() == preferred_separator) { - dest._path.pop_back(); + else { + auto last = --dest.end(); + 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)) { diff --git a/test/filesystem_test.cpp b/test/filesystem_test.cpp index 7fe5b33..fc202fa 100644 --- a/test/filesystem_test.cpp +++ b/test/filesystem_test.cpp @@ -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("a/b/../../../c").lexically_normal() == "../c"); 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 CHECK(fs::path("\\/\\///\\/").lexically_normal() == "/"); CHECK(fs::path("a/b/..\\//..///\\/../c\\\\/").lexically_normal() == "../c/");