cmSystemTools: adopt the GetActualCaseForPath method from KWSys

No other project uses it and it simplifies KWSys.
This commit is contained in:
Ben Boeckel
2026-07-29 14:15:27 -04:00
committed by Brad King
parent bd2d6c8f39
commit 93c3793829
2 changed files with 77 additions and 0 deletions
+75
View File
@@ -2024,6 +2024,81 @@ std::string cmSystemTools::RelativeIfUnder(std::string const& top,
return out;
}
std::string cmSystemTools::GetActualCaseForPath(std::string const& p)
{
#ifdef _WIN32
std::string casePath;
// First check if the file is relative. We don't fix relative paths since the
// real case depends on the root directory and the given path fragment may
// have meaning elsewhere in the project.
if (!cmsys::SystemTools::FileIsFullPath(p)) {
// This looks unnecessary, but it allows for the return value optimization
// since all return paths return the same local variable.
casePath = p;
return casePath;
}
std::vector<std::string> path_components;
cmsys::SystemTools::SplitPath(p, path_components);
// Start with root component.
std::vector<std::string>::size_type idx = 0;
casePath = path_components[idx++];
// make sure drive letter is always upper case
if (casePath.size() > 1 && casePath[1] == ':') {
casePath[0] = cmsysString_toupper(casePath[0]);
}
char const* sep = "";
// If network path, fill casePath with server/share so FindFirstFile
// will work after that. Maybe someday call other APIs to get
// actual case of servers and shares.
if (path_components.size() > 2 && path_components[0] == "//") {
casePath += path_components[idx++];
casePath += '/';
casePath += path_components[idx++];
sep = "/";
}
// Convert case of all components that exist.
bool converting = true;
for (; idx < path_components.size(); idx++) {
casePath += sep;
sep = "/";
if (converting) {
// 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(
cmsys::Encoding::ToWide(test_str).c_str(), &findData);
if (INVALID_HANDLE_VALUE != hFind) {
auto case_file_name = cmsys::Encoding::ToNarrow(findData.cFileName);
path_components[idx] = std::move(case_file_name);
::FindClose(hFind);
} else {
converting = false;
}
}
}
casePath += path_components[idx];
}
return casePath;
#else
return p;
#endif
}
cm::optional<std::string> cmSystemTools::GetEnvVar(std::string const& var)
{
cm::optional<std::string> result;
+2
View File
@@ -426,6 +426,8 @@ public:
static std::string RelativeIfUnder(std::string const& top,
std::string const& in);
static std::string GetActualCaseForPath(std::string const& p);
static cm::optional<std::string> GetEnvVar(std::string const& var);
static std::vector<std::string> GetEnvPathNormalized(std::string const& var);