mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
get_filename_component: Cache the actual case of path components
get_filename_component(ABSOLUTE|REALPATH) queried the disk for the actual case of every path component on every call. Remember the actual case of components found to exist until files may have been removed or renamed, as for source file lookups.
This commit is contained in:
5 files changed
+50
-11
No files matched your search
@@ -8,6 +8,7 @@
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmValue.h"
|
||||
#include "cmake.h"
|
||||
|
||||
// cmGetFilenameComponentCommand
|
||||
bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
|
||||
@@ -113,7 +114,8 @@ bool cmGetFilenameComponentCommand(std::vector<std::string> const& args,
|
||||
// Resolve symlinks if possible
|
||||
result = cmSystemTools::GetRealPath(result);
|
||||
}
|
||||
result = cmSystemTools::GetActualCaseForPath(result);
|
||||
result = cmSystemTools::GetActualCaseForPath(
|
||||
result, status.GetMakefile().GetCMakeInstance()->GetActualCaseCache());
|
||||
} else {
|
||||
std::string err = "unknown component " + args[2];
|
||||
status.SetError(err);
|
||||
|
||||
@@ -2047,7 +2047,8 @@ std::string cmSystemTools::RelativeIfUnder(std::string const& top,
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string cmSystemTools::GetActualCaseForPath(std::string const& p)
|
||||
std::string cmSystemTools::GetActualCaseForPath(
|
||||
std::string const& p, std::unordered_map<std::string, std::string>* cache)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::string casePath;
|
||||
@@ -2101,15 +2102,32 @@ std::string cmSystemTools::GetActualCaseForPath(std::string const& p)
|
||||
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);
|
||||
// Only components found to exist are cached, so that a path
|
||||
// created later is still converted.
|
||||
std::string const* cached = nullptr;
|
||||
if (cache) {
|
||||
auto it = cache->find(test_str);
|
||||
if (it != cache->end()) {
|
||||
cached = &it->second;
|
||||
}
|
||||
}
|
||||
if (cached) {
|
||||
path_components[idx] = *cached;
|
||||
} else {
|
||||
converting = false;
|
||||
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);
|
||||
::FindClose(hFind);
|
||||
if (cache) {
|
||||
cache->emplace(std::move(test_str), case_file_name);
|
||||
}
|
||||
path_components[idx] = std::move(case_file_name);
|
||||
} else {
|
||||
converting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2118,6 +2136,7 @@ std::string cmSystemTools::GetActualCaseForPath(std::string const& p)
|
||||
}
|
||||
return casePath;
|
||||
#else
|
||||
static_cast<void>(cache);
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
+10
-1
@@ -11,6 +11,7 @@
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/optional>
|
||||
@@ -433,7 +434,15 @@ public:
|
||||
static std::string RelativeIfUnder(std::string const& top,
|
||||
std::string const& in);
|
||||
|
||||
static std::string GetActualCaseForPath(std::string const& p);
|
||||
/**
|
||||
* Get the path with the actual case of all existing components on disk.
|
||||
* If a cache is given, it is used to remember the actual case of
|
||||
* components found to exist, to avoid querying the disk again for
|
||||
* paths sharing the same directories.
|
||||
*/
|
||||
static std::string GetActualCaseForPath(
|
||||
std::string const& p,
|
||||
std::unordered_map<std::string, std::string>* cache = nullptr);
|
||||
|
||||
static cm::optional<std::string> GetEnvVar(std::string const& var);
|
||||
static std::vector<std::string> GetEnvPathNormalized(std::string const& var);
|
||||
|
||||
@@ -2577,6 +2577,7 @@ int cmake::Configure()
|
||||
|
||||
void cmake::InvalidateFileSystemCaches()
|
||||
{
|
||||
this->ActualCaseCache.clear();
|
||||
if (this->GlobalGenerator) {
|
||||
this->GlobalGenerator->ClearSourceFileExistsCache();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -476,6 +477,12 @@ public:
|
||||
return *this->GeneratorExpressionParseCache;
|
||||
}
|
||||
|
||||
//! Cache for cmSystemTools::GetActualCaseForPath.
|
||||
std::unordered_map<std::string, std::string>* GetActualCaseCache()
|
||||
{
|
||||
return &this->ActualCaseCache;
|
||||
}
|
||||
|
||||
//! Forget what is known about the file system, e.g. after files may
|
||||
//! have been removed or renamed.
|
||||
void InvalidateFileSystemCaches();
|
||||
@@ -830,6 +837,7 @@ private:
|
||||
std::unique_ptr<cmFileTimeCache> FileTimeCache;
|
||||
std::unique_ptr<cmGeneratorExpressionParseCache>
|
||||
GeneratorExpressionParseCache;
|
||||
std::unordered_map<std::string, std::string> ActualCaseCache;
|
||||
std::string GraphVizFile;
|
||||
InstalledFilesMap InstalledFiles;
|
||||
#ifndef CMAKE_BOOTSTRAP
|
||||
|
||||
Reference in new issue
Block a user