Incorrect handling of ../..
zmeyc opened this issue · comments
Describe the bug
With ../..
only 1 dir is unrolled.
To Reproduce
const char *path = "ab/cd/ef/../../qw";
ghc::filesystem::path srcPath = ghc::filesystem::u8path(path);
std::string destPath = srcPath.lexically_normal().u8string();
Expected behavior
Should produce ab/qw
, produces ab/cd/qw
.
Attached is a test project.
UPD:
More test cases:
"\\/\\///\\/"
produces //////
, expected /
.
"a/b/..\\//..///\\/../c\\\\/"
produces a/b/c///
, expected ../c/
.
"a/b/../../../c"
produces a/c
, expected ../c
.
"..a/b/..\\//..///\\/../c\\\\/"
produces ..a/b/c///
, expected ../c/
.
The testcase "ab/cd/ef/../../qw" is indeed wrong, and indeed sequences of ".." are handled wrong. Sadly I didn't have one of those in my tests.
Concerning the additional cases what is the operating system, this is run? The bash.sh looked like Linux but the backslashes look like Windows?
Sorry, I forgot that I had an extra step replacing \ with / in additional test cases.
The code was compiled in VS 2017 in C++17 mode:
std::cout << std::filesystem::u8path("\\/\\///\\/").lexically_normal().u8string() << std::endl;
std::cout << std::filesystem::u8path("ab/cd/ef/../../qw").lexically_normal().u8string() << std::endl;
std::cout << std::filesystem::u8path("a/b/..\\//..///\\/../c\\\\/").lexically_normal().u8string() << std::endl;
std::cout << std::filesystem::u8path("a/b/../../../c").lexically_normal().u8string() << std::endl;
std::cout << std::filesystem::u8path("..a/b/..\\//..///\\/../c\\\\/").lexically_normal().u8string() << std::endl;
Output:
\
ab\qw
..\c\
..\c
..\c\
FIxed on master, will be part of the upcomming bugfix release v1.1.2
Awesome, thank you!
#ifdef GHC_OS_WINDOWS
CHECK(fs::path("\\/\\///\\/").lexically_normal() == "/");
CHECK(fs::path("a/b/..\\//..///\\/../c\\\\/").lexically_normal() == "../c/");
CHECK(fs::path("..a/b/..\\//..///\\/../c\\\\/").lexically_normal() == "../c/");
#endif
These should probably have backslashes on Windows if compatibility with std::filesystem is needed? I.e. "\"
and "..\\c\\"
You are very wellcome!
Actually no need to use backslashes on the right hand side, as lexically_normal() returns an fs::path and the operator==(path, path) that is triggered will lead to implicit conversion of the right hand side string to a fs::path, so the actual comparison is on path level, working with ghc::filesystem and with MSVCs C++17 implementation of std::filesystem, and I ran the tests against both locally before closing the issue.
Released with v1.1.2