From d28e4467aae44db2b15a785e6f061917798cfcd4 Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Wed, 14 Sep 2016 09:38:50 -0400 Subject: [PATCH] KWSys 2016-09-14 (c4049689) Code extracted from: http://public.kitware.com/KWSys.git at commit c4049689d1ff6e3b9f59358023aebb1a7e0fd149 (master). Upstream Shortlog ----------------- Brad King (2): 0504dcaf SystemTools: Fix path comparison in test case c4049689 SystemTools: Teach GetActualCaseForPath to convert as much as possible --- SystemTools.cxx | 68 ++++++++++++++++++++++++--------------------- SystemTools.hxx.in | 9 +++--- testSystemTools.cxx | 4 +-- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/SystemTools.cxx b/SystemTools.cxx index 1a73b164b..4281c3885 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -3982,16 +3982,16 @@ std::string SystemTools::RelativePath(const std::string& local, const std::strin } #ifdef _WIN32 -static int GetCasePathName(const std::string & pathIn, - std::string & casePath) +static std::string GetCasePathName(std::string const& pathIn) { + std::string casePath; std::vector path_components; SystemTools::SplitPath(pathIn, path_components); if(path_components[0].empty()) // First component always exists. { // Relative paths cannot be converted. - casePath = ""; - return 0; + casePath = pathIn; + return casePath; } // Start with root component. @@ -4015,38 +4015,45 @@ static int GetCasePathName(const std::string & pathIn, sep = "/"; } + // Convert case of all components that exist. + bool converting = true; for(; idx < path_components.size(); idx++) { casePath += sep; sep = "/"; - std::string test_str = casePath; - test_str += path_components[idx]; - // If path component contains wildcards, we skip matching - // because these filenames are not allowed on windows, - // and we do not want to match a different file. - if(path_components[idx].find('*') != std::string::npos || - path_components[idx].find('?') != std::string::npos) + if (converting) { - casePath = ""; - return 0; + // If path component contains wildcards, we skip matching + // because these filenames are not allowed on windows, + // and we do not want to match a different file. + if(path_components[idx].find('*') != std::string::npos || + path_components[idx].find('?') != std::string::npos) + { + converting = false; + } + else + { + std::string test_str = casePath; + test_str += path_components[idx]; + WIN32_FIND_DATAW findData; + HANDLE hFind = ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), + &findData); + if (INVALID_HANDLE_VALUE != hFind) + { + path_components[idx] = Encoding::ToNarrow(findData.cFileName); + ::FindClose(hFind); + } + else + { + converting = false; + } + } } - WIN32_FIND_DATAW findData; - HANDLE hFind = ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), - &findData); - if (INVALID_HANDLE_VALUE != hFind) - { - casePath += Encoding::ToNarrow(findData.cFileName); - ::FindClose(hFind); - } - else - { - casePath = ""; - return 0; - } + casePath += path_components[idx]; } - return (int)casePath.size(); + return casePath; } #endif @@ -4065,11 +4072,10 @@ std::string SystemTools::GetActualCaseForPath(const std::string& p) { return i->second; } - std::string casePath; - int len = GetCasePathName(p, casePath); - if(len == 0 || len > MAX_PATH+1) + std::string casePath = GetCasePathName(p); + if (casePath.size() > MAX_PATH) { - return p; + return casePath; } (*SystemTools::PathCaseMap)[p] = casePath; return casePath; diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in index 28ff0b39e..5849145d4 100644 --- a/SystemTools.hxx.in +++ b/SystemTools.hxx.in @@ -374,10 +374,11 @@ public: static const char* GetExecutableExtension(); /** - * Given a path that exists on a windows machine, return the - * actuall case of the path as it was created. If the file - * does not exist path is returned unchanged. This does nothing - * on unix but return path. + * Given a path on a Windows machine, return the actual case of + * the path as it exists on disk. Path components that do not + * exist on disk are returned unchanged. Relative paths are always + * returned unchanged. Drive letters are always made upper case. + * This does nothing on non-Windows systems but return the path. */ static std::string GetActualCaseForPath(const std::string& path); diff --git a/testSystemTools.cxx b/testSystemTools.cxx index 9252ea6e3..880b46e8b 100644 --- a/testSystemTools.cxx +++ b/testSystemTools.cxx @@ -940,7 +940,7 @@ static bool CheckRelativePath( const std::string& expected) { std::string result = kwsys::SystemTools::RelativePath(local, remote); - if(expected != result) + if (!kwsys::SystemTools::ComparePath(expected, result)) { std::cerr << "RelativePath(" << local << ", " << remote << ") yielded " << result << " instead of " << expected << std::endl; @@ -965,7 +965,7 @@ static bool CheckCollapsePath( const std::string& expected) { std::string result = kwsys::SystemTools::CollapseFullPath(path); - if(expected != result) + if (!kwsys::SystemTools::ComparePath(expected, result)) { std::cerr << "CollapseFullPath(" << path << ") yielded " << result << " instead of " << expected << std::endl;