diff --git a/lib/path.cpp b/lib/path.cpp index 6770267cfda..91ccfabc213 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -449,9 +449,13 @@ bool Path::exists(const std::string &path, bool* isdir) return type == S_IFREG; } -std::string Path::join(const std::string& path1, const std::string& path2) { +std::string Path::join(std::string path1, std::string path2) +{ + path1 = fromNativeSeparators(std::move(path1)); + path2 = fromNativeSeparators(std::move(path2)); if (path1.empty() || path2.empty()) return path1 + path2; + // this matches the behavior of std::filesystem::path::operator/=() and os.path.join() if (path2.front() == '/') return path2; return ((path1.back() == '/') ? path1 : (path1 + "/")) + path2; diff --git a/lib/path.h b/lib/path.h index 9f13da09236..23db06c4e50 100644 --- a/lib/path.h +++ b/lib/path.h @@ -201,9 +201,11 @@ class CPPCHECKLIB Path { static bool exists(const std::string &path, bool* isdir = nullptr); /** - * join 2 paths with '/' separators + * @brief join 2 paths with '/' separators + * if path2 is an absolute path path1 will be dismissed. + * @return the joined path with normalized slashes */ - static std::string join(const std::string& path1, const std::string& path2); + static std::string join(std::string path1, std::string path2); }; /// @} diff --git a/test/testpath.cpp b/test/testpath.cpp index 44d5f10a30b..7c181e28afb 100644 --- a/test/testpath.cpp +++ b/test/testpath.cpp @@ -172,11 +172,36 @@ class TestPath : public TestFixture { } void join() const { + ASSERT_EQUALS("", Path::join("", "")); + ASSERT_EQUALS("b", Path::join("", "b")); + ASSERT_EQUALS("/b", Path::join("", "/b")); + ASSERT_EQUALS("/b", Path::join("", "\\b")); + ASSERT_EQUALS("a", Path::join("a", "")); - ASSERT_EQUALS("a", Path::join("", "a")); ASSERT_EQUALS("a/b", Path::join("a", "b")); - ASSERT_EQUALS("a/b", Path::join("a/", "b")); ASSERT_EQUALS("/b", Path::join("a", "/b")); + ASSERT_EQUALS("/b", Path::join("a", "\\b")); + + ASSERT_EQUALS("a/", Path::join("a/", "")); + ASSERT_EQUALS("a/b", Path::join("a/", "b")); + ASSERT_EQUALS("/b", Path::join("a/", "/b")); + ASSERT_EQUALS("/b", Path::join("a/", "\\b")); + + ASSERT_EQUALS("a/", Path::join("a\\", "")); + ASSERT_EQUALS("a/b", Path::join("a\\", "b")); + ASSERT_EQUALS("/b", Path::join("a\\", "/b")); + ASSERT_EQUALS("/b", Path::join("a\\", "\\b")); + + // TODO: how to absolute Windows path in path2? + //ASSERT_EQUALS("", Path::join("a", "s:/b")); + + //ASSERT_EQUALS("", Path::join("S:\\a", "S:/b")); + //ASSERT_EQUALS("", Path::join("S:\\a", "S:\\b")); + //ASSERT_EQUALS("", Path::join("S:\\a", "/b")); + + //ASSERT_EQUALS("", Path::join("S:/a", "S:/b")); + //ASSERT_EQUALS("", Path::join("S:/a", "S:\\b")); + //ASSERT_EQUALS("", Path::join("S:/a", "/b")); } void isDirectory() const {