gulrak / filesystem

An implementation of C++17 std::filesystem for C++11 /C++14/C++17/C++20 on Windows, macOS, Linux and FreeBSD.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

filesystem_test.zip

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