From d7141c47edd5be158fb2d1e0f82cc95b8efb4a21 Mon Sep 17 00:00:00 2001 From: Silvio Date: Sat, 9 Jul 2022 14:18:02 +0200 Subject: [PATCH] Support absolute Win paths with forward slashes in common::FindFile Signed-off-by: Silvio Traversaro --- src/SystemPaths.cc | 47 +++++++++++++++++++++++------------------ src/SystemPaths_TEST.cc | 15 +++++++++++++ 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/SystemPaths.cc b/src/SystemPaths.cc index f809686c4..dc3f4ae39 100644 --- a/src/SystemPaths.cc +++ b/src/SystemPaths.cc @@ -400,38 +400,43 @@ std::string SystemPaths::FindFile(const std::string &_filename, if (filename.empty()) return path; - // Handle as URI - if (ignition::common::URI::Valid(filename)) - { - path = this->FindFileURI(ignition::common::URI(filename)); - } - // Handle as local absolute path - else if (filename[0] == '/') - { - path = filename; - } #ifdef _WIN32 - // Handle as Windows absolute path - else if (filename.length() >= 2 && filename[1] == ':') + // First of all, try if filename as a Windows absolute path exists + // The Windows absolute path is tried first as a Windows drive such as + // C:/ is also a valid URI scheme + if (filename.length() >= 2 && filename[1] == ':' && exists(filename)) { path = filename; } #endif // _WIN32 - // Try appending to local paths - else - { - auto cwdPath = joinPaths(cwd(), filename); - if (_searchLocalPath && exists(cwdPath)) + // If the filename is not an existing absolute Windows path, try others + if (path.empty()) { + // Handle as URI + if (ignition::common::URI::Valid(filename)) { - path = cwdPath; + path = this->FindFileURI(ignition::common::URI(filename)); } - else if ((filename[0] == '.' || _searchLocalPath) && exists(filename)) + // Handle as local absolute path + else if (filename[0] == '/') { path = filename; } - else if (this->dataPtr->findFileCB) + // Try appending to local paths + else { - path = this->dataPtr->findFileCB(filename); + auto cwdPath = joinPaths(cwd(), filename); + if (_searchLocalPath && exists(cwdPath)) + { + path = cwdPath; + } + else if ((filename[0] == '.' || _searchLocalPath) && exists(filename)) + { + path = filename; + } + else if (this->dataPtr->findFileCB) + { + path = this->dataPtr->findFileCB(filename); + } } } diff --git a/src/SystemPaths_TEST.cc b/src/SystemPaths_TEST.cc index a17950baa..e721ac727 100644 --- a/src/SystemPaths_TEST.cc +++ b/src/SystemPaths_TEST.cc @@ -359,6 +359,21 @@ TEST_F(SystemPathsFixture, FindFile) EXPECT_EQ("", sp.FindFile(uriBadDir)); } + // Windows path with only one forward slash +#ifdef _WIN32 + const auto tmpDirForwardSlash = "C:/Windows"; + const auto homeDirForwardSlash = "C:/Users"; + const auto badDirForwardSlash = "C:/bad"; + { + // We do not expect equality as sp.FindFile could normalize the + // path and return a different string + // The behaviour tested here is just that C:/Windows, C:/Users are found + EXPECT_NE("", sp.FindFile(tmpDirForwardSlash)); + EXPECT_NE("", sp.FindFile(homeDirForwardSlash)); + EXPECT_EQ("", sp.FindFile(badDirForwardSlash)); + } +#endif + // Custom callback { auto tmpCb = [tmpDir](const std::string &_s)