Browse Source

Merge topic 'normalize-input-paths'

799602b983 cmQtAutoMocUic: Remove now-unnecessary mutex around CollapseFullPath
5ca6234d13 KWSys: Remove path translation map settings for build within CMake
74c497ca65 Merge branch 'upstream-KWSys' into normalize-input-paths
10a381e446 KWSys 2024-11-04 (bef1f021)
73dddffe32 KWSys: Disable the path translation map for build within CMake
b378781c5d cmSystemTools: Cache ToNormalizedPathOnDisk actual-case lookups
622596c6b2 cmSystemTools: Re-implement ToNormalizedPathOnDisk without translation map
5aed3ee49d cmSystemTools: Add GetLogicalWorkingDirectory

Acked-by: Kitware Robot <[email protected]>
Merge-request: !9969
Brad King 1 year ago
parent
commit
384dbef61e

+ 6 - 5
Source/CPack/cpack.cxx

@@ -113,7 +113,7 @@ int main(int argc, char const* const* argv)
   log.SetOutputPrefix("CPack: ");
   log.SetVerbosePrefix("CPack Verbose: ");
 
-  if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
+  if (cmSystemTools::GetLogicalWorkingDirectory().empty()) {
     cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
                 "Current working directory cannot be established.\n");
     return 1;
@@ -255,7 +255,7 @@ int main(int argc, char const* const* argv)
 
   // Set up presets
   if (!preset.empty() || listPresets) {
-    const auto workingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+    const auto workingDirectory = cmSystemTools::GetLogicalWorkingDirectory();
 
     auto const presetGeneratorsPresent =
       [&generators](const cmCMakePresetsGraph::PackagePreset& p) {
@@ -350,7 +350,8 @@ int main(int argc, char const* const* argv)
       return 1;
     }
 
-    cmSystemTools::ChangeDirectory(expandedConfigurePreset->BinaryDir);
+    cmSystemTools::SetLogicalWorkingDirectory(
+      expandedConfigurePreset->BinaryDir);
 
     auto presetEnvironment = expandedPreset->Environment;
     for (auto const& var : presetEnvironment) {
@@ -408,7 +409,7 @@ int main(int argc, char const* const* argv)
   if (!cpackConfigFile.empty()) {
     cpackConfigFile = cmSystemTools::ToNormalizedPathOnDisk(cpackConfigFile);
   } else {
-    cpackConfigFile = cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(),
+    cpackConfigFile = cmStrCat(cmSystemTools::GetLogicalWorkingDirectory(),
                                "/CPackConfig.cmake");
     cpackConfigFileSpecified = false;
   }
@@ -488,7 +489,7 @@ int main(int argc, char const* const* argv)
         cpackProjectDirectory = cmSystemTools::CollapseFullPath(*pd);
       } else {
         // Default to the current working directory.
-        cpackProjectDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+        cpackProjectDirectory = cmSystemTools::GetLogicalWorkingDirectory();
       }
     }
     globalMF.AddDefinition("CPACK_PACKAGE_DIRECTORY", cpackProjectDirectory);

+ 1 - 1
Source/CTest/cmCTestLaunchReporter.cxx

@@ -25,7 +25,7 @@ cmCTestLaunchReporter::cmCTestLaunchReporter()
   this->Passthru = true;
   this->Status.Finished = true;
   this->ExitCode = 1;
-  this->CWD = cmSystemTools::GetCurrentWorkingDirectory();
+  this->CWD = cmSystemTools::GetLogicalWorkingDirectory();
 
   this->ComputeFileNames();
 

+ 1 - 1
Source/CTest/cmCTestScriptHandler.cxx

@@ -188,7 +188,7 @@ void cmCTestScriptHandler::CreateCMake()
     cm::make_unique<cmGlobalGenerator>(this->CMake.get());
 
   cmStateSnapshot snapshot = this->CMake->GetCurrentSnapshot();
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+  std::string cwd = cmSystemTools::GetLogicalWorkingDirectory();
   snapshot.GetDirectory().SetCurrentSource(cwd);
   snapshot.GetDirectory().SetCurrentBinary(cwd);
   this->Makefile =

+ 0 - 3
Source/CTest/cmCTestStartCommand.cxx

@@ -85,9 +85,6 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
     return false;
   }
 
-  cmSystemTools::AddKeepPath(*src_dir);
-  cmSystemTools::AddKeepPath(*bld_dir);
-
   this->CTest->EmptyCTestConfiguration();
 
   std::string sourceDir = cmSystemTools::CollapseFullPath(*src_dir);

+ 5 - 5
Source/CTest/cmCTestTestHandler.cxx

@@ -128,7 +128,7 @@ bool cmCTestSubdirCommand(std::vector<std::string> const& args,
     status.SetError("called with incorrect number of arguments");
     return false;
   }
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+  std::string cwd = cmSystemTools::GetLogicalWorkingDirectory();
   for (std::string const& arg : args) {
     std::string fname;
 
@@ -154,7 +154,7 @@ bool cmCTestAddSubdirectoryCommand(std::vector<std::string> const& args,
   }
 
   std::string fname =
-    cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), '/', args[0]);
+    cmStrCat(cmSystemTools::GetLogicalWorkingDirectory(), '/', args[0]);
 
   return ReadSubdirectory(std::move(fname), status);
 }
@@ -354,7 +354,7 @@ int cmCTestTestHandler::ProcessHandler()
   cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
                      (this->MemCheck ? "Memory check" : "Test")
                        << " project "
-                       << cmSystemTools::GetCurrentWorkingDirectory()
+                       << cmSystemTools::GetLogicalWorkingDirectory()
                        << std::endl,
                      this->Quiet);
   if (!this->PreProcessHandler()) {
@@ -2385,7 +2385,7 @@ bool cmCTestTestHandler::SetDirectoryProperties(
     }
     std::string const& val = *it;
     for (cmCTestTestProperties& rt : this->TestList) {
-      std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+      std::string cwd = cmSystemTools::GetLogicalWorkingDirectory();
       if (cwd == rt.Directory) {
         if (key == "LABELS"_s) {
           cmList DirectoryLabels{ val };
@@ -2449,7 +2449,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
   cmCTestTestProperties test;
   test.Name = testname;
   test.Args = args;
-  test.Directory = cmSystemTools::GetCurrentWorkingDirectory();
+  test.Directory = cmSystemTools::GetLogicalWorkingDirectory();
   cmCTestOptionalLog(this->CTest, DEBUG,
                      "Set test directory: " << test.Directory << std::endl,
                      this->Quiet);

+ 1 - 1
Source/CursesDialog/ccmake.cxx

@@ -101,7 +101,7 @@ int main(int argc, char const* const* argv)
     }
   }
 
-  std::string cacheDir = cmSystemTools::GetCurrentWorkingDirectory();
+  std::string cacheDir = cmSystemTools::GetLogicalWorkingDirectory();
   for (i = 1; i < args.size(); ++i) {
     std::string const& arg = args[i];
     if (cmHasPrefix(arg, "-B")) {

+ 1 - 1
Source/QtDialog/CMakeSetup.cxx

@@ -243,7 +243,7 @@ int main(int argc, char** argv)
       } else if (cmSystemTools::FileExists(srcFilePath.c_str())) {
         dialog.setSourceDirectory(QString::fromStdString(filePath));
         dialog.setBinaryDirectory(
-          QString::fromStdString(cmSystemTools::GetCurrentWorkingDirectory()));
+          QString::fromStdString(cmSystemTools::GetLogicalWorkingDirectory()));
       }
     }
   }

+ 4 - 4
Source/cmCTest.cxx

@@ -574,7 +574,7 @@ bool cmCTest::UpdateCTestConfiguration()
   if (!this->GetCTestConfiguration("BuildDirectory").empty()) {
     this->Impl->BinaryDir = this->GetCTestConfiguration("BuildDirectory");
     if (this->Impl->TestDir.empty()) {
-      cmSystemTools::ChangeDirectory(this->Impl->BinaryDir);
+      cmSystemTools::SetLogicalWorkingDirectory(this->Impl->BinaryDir);
     }
   }
   this->Impl->TimeOut =
@@ -705,7 +705,7 @@ int cmCTest::ProcessSteps()
   this->Impl->Verbose = true;
   this->Impl->ProduceXML = true;
 
-  const std::string currDir = cmSystemTools::GetCurrentWorkingDirectory();
+  const std::string currDir = cmSystemTools::GetLogicalWorkingDirectory();
   std::string workDir = currDir;
   if (!this->Impl->TestDir.empty()) {
     workDir = cmSystemTools::ToNormalizedPathOnDisk(this->Impl->TestDir);
@@ -1555,7 +1555,7 @@ bool cmCTest::AddVariableDefinition(const std::string& arg)
 bool cmCTest::SetArgsFromPreset(const std::string& presetName,
                                 bool listPresets)
 {
-  const auto workingDirectory = cmSystemTools::GetCurrentWorkingDirectory();
+  const auto workingDirectory = cmSystemTools::GetLogicalWorkingDirectory();
 
   cmCMakePresetsGraph settingsFile;
   auto result = settingsFile.ReadProjectPresets(workingDirectory);
@@ -2668,7 +2668,7 @@ int cmCTest::ExecuteTests()
   this->Impl->ExtraVerbose = this->Impl->Verbose;
   this->Impl->Verbose = true;
 
-  const std::string currDir = cmSystemTools::GetCurrentWorkingDirectory();
+  const std::string currDir = cmSystemTools::GetLogicalWorkingDirectory();
   std::string workDir = currDir;
   if (!this->Impl->TestDir.empty()) {
     workDir = cmSystemTools::ToNormalizedPathOnDisk(this->Impl->TestDir);

+ 1 - 1
Source/cmFileCommand.cxx

@@ -3847,7 +3847,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
 
       if (!cmSystemTools::FileIsFullPath(inFile)) {
         inFile =
-          cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), "/", inFile);
+          cmStrCat(cmSystemTools::GetLogicalWorkingDirectory(), "/", inFile);
       }
     }
 

+ 1 - 1
Source/cmInstallScriptHandler.cxx

@@ -133,7 +133,7 @@ int cmInstallScriptHandler::install(unsigned int j)
 InstallScript::InstallScript(const std::vector<std::string>& cmd)
 {
   this->name = cmSystemTools::RelativePath(
-    cmSystemTools::GetCurrentWorkingDirectory(), cmd.back());
+    cmSystemTools::GetLogicalWorkingDirectory(), cmd.back());
   this->command = cmd;
 }
 

+ 5 - 22
Source/cmQtAutoMocUic.cxx

@@ -7,7 +7,6 @@
 #include <cstddef>
 #include <limits>
 #include <map>
-#include <mutex>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -561,7 +560,6 @@ public:
   std::string AbsoluteIncludePath(cm::string_view relativePath) const;
   template <class JOBTYPE>
   void CreateParseJobs(SourceFileMapT const& sourceMap);
-  std::string CollapseFullPathTS(std::string const& path) const;
 
 private:
   // -- Abstract processing interface
@@ -595,8 +593,6 @@ private:
   // -- Worker thread pool
   std::atomic<bool> JobError_{ false };
   cmWorkerPool WorkerPool_;
-  // -- Concurrent processing
-  mutable std::mutex CMakeLibMutex_;
 };
 
 cmQtAutoMocUicT::IncludeKeyT::IncludeKeyT(std::string const& key,
@@ -1494,8 +1490,9 @@ bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
                      &headerHandle](std::string const& basePath) -> bool {
     bool found = false;
     for (std::string const& ext : this->BaseConst().HeaderExtensions) {
-      std::string const testPath =
-        this->Gen()->CollapseFullPathTS(cmStrCat(basePath, '.', ext));
+      std::string const testPath = cmSystemTools::CollapseFullPath(
+        cmStrCat(basePath, '.', ext),
+        this->Gen()->ProjectDirs().CurrentSource);
       cmFileTime fileTime;
       if (!fileTime.Load(testPath)) {
         // File not found
@@ -1682,7 +1679,8 @@ bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
   this->SearchLocations.clear();
 
   auto findUi = [this](std::string const& testPath) -> bool {
-    std::string const fullPath = this->Gen()->CollapseFullPathTS(testPath);
+    std::string const fullPath = cmSystemTools::CollapseFullPath(
+      testPath, this->Gen()->ProjectDirs().CurrentSource);
     cmFileTime fileTime;
     if (!fileTime.Load(fullPath)) {
       this->SearchLocations.emplace_back(cmQtAutoGen::ParentDir(fullPath));
@@ -2885,17 +2883,6 @@ void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)
   }
 }
 
-/** Concurrently callable implementation of cmSystemTools::CollapseFullPath */
-std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const
-{
-  std::lock_guard<std::mutex> guard(this->CMakeLibMutex_);
-#if defined(__NVCOMPILER) || defined(__LCC__)
-  static_cast<void>(guard); // convince compiler var is used
-#endif
-  return cmSystemTools::CollapseFullPath(path,
-                                         this->ProjectDirs().CurrentSource);
-}
-
 void cmQtAutoMocUicT::InitJobs()
 {
   // Add moc_predefs.h job
@@ -3130,10 +3117,6 @@ bool cmQtAutoMocUicT::CreateDirectories()
 std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(
   const char* filePath)
 {
-  std::lock_guard<std::mutex> guard(this->CMakeLibMutex_);
-#if defined(__NVCOMPILER) || defined(__LCC__)
-  static_cast<void>(guard); // convince compiler var is used
-#endif
   auto const content = cmReadGccDepfile(filePath);
   if (!content || content->empty()) {
     return {};

+ 150 - 10
Source/cmSystemTools.cxx

@@ -22,6 +22,10 @@
 
 #include <iterator>
 
+#ifdef _WIN32
+#  include <unordered_map>
+#endif
+
 #include <cm/optional>
 #include <cmext/algorithm>
 #include <cmext/string_view>
@@ -31,6 +35,7 @@
 #include "cmDuration.h"
 #include "cmELF.h"
 #include "cmMessageMetadata.h"
+#include "cmPathResolver.h"
 #include "cmProcessOutput.h"
 #include "cmRange.h"
 #include "cmStringAlgorithms.h"
@@ -128,6 +133,116 @@ cmSystemTools::MessageCallback s_MessageCallback;
 cmSystemTools::OutputCallback s_StderrCallback;
 cmSystemTools::OutputCallback s_StdoutCallback;
 
+#ifdef _WIN32
+std::string GetDosDriveWorkingDirectory(char letter)
+{
+  // The Windows command processor tracks a per-drive working
+  // directory for compatibility with MS-DOS by using special
+  // environment variables named "=C:".
+  // https://web.archive.org/web/20100522040616/
+  // https://blogs.msdn.com/oldnewthing/archive/2010/05/06/10008132.aspx
+  return cmSystemTools::GetEnvVar(cmStrCat('=', letter, ':'))
+    .value_or(std::string());
+}
+
+cmsys::Status ReadNameOnDisk(std::string const& path, std::string& name)
+{
+  std::wstring wp = cmsys::Encoding::ToWide(path);
+  HANDLE h = CreateFileW(
+    wp.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
+    FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+  if (h == INVALID_HANDLE_VALUE) {
+    return cmsys::Status::Windows_GetLastError();
+  }
+
+  WCHAR local_fni[((sizeof(FILE_NAME_INFO) - 1) / sizeof(WCHAR)) + 1024];
+  size_t fni_size = sizeof(local_fni);
+  auto* fni = reinterpret_cast<FILE_NAME_INFO*>(local_fni);
+  if (!GetFileInformationByHandleEx(h, FileNameInfo, fni, fni_size)) {
+    DWORD e = GetLastError();
+    if (e != ERROR_MORE_DATA) {
+      CloseHandle(h);
+      return cmsys::Status::Windows(e);
+    }
+    fni_size = fni->FileNameLength;
+    fni = static_cast<FILE_NAME_INFO*>(malloc(fni_size));
+    if (!fni) {
+      e = ERROR_NOT_ENOUGH_MEMORY;
+      CloseHandle(h);
+      return cmsys::Status::Windows(e);
+    }
+    if (!GetFileInformationByHandleEx(h, FileNameInfo, fni, fni_size)) {
+      e = GetLastError();
+      free(fni);
+      CloseHandle(h);
+      return cmsys::Status::Windows(e);
+    }
+  }
+
+  std::wstring wn{ fni->FileName, fni->FileNameLength / sizeof(WCHAR) };
+  std::string nn = cmsys::Encoding::ToNarrow(wn);
+  std::string::size_type last_slash = nn.find_last_of("/\\");
+  if (last_slash != std::string::npos) {
+    name = nn.substr(last_slash + 1);
+  }
+  if (fni != reinterpret_cast<FILE_NAME_INFO*>(local_fni)) {
+    free(fni);
+  }
+  CloseHandle(h);
+  return cmsys::Status::Success();
+}
+#endif
+
+class RealSystem : public cm::PathResolver::System
+{
+public:
+  ~RealSystem() override = default;
+  cmsys::Status ReadSymlink(std::string const& path,
+                            std::string& link) override
+  {
+    return cmSystemTools::ReadSymlink(path, link);
+  }
+  bool PathExists(std::string const& path) override
+  {
+    return cmSystemTools::PathExists(path);
+  }
+  std::string GetWorkingDirectory() override
+  {
+    return cmSystemTools::GetLogicalWorkingDirectory();
+  }
+#ifdef _WIN32
+  std::string GetWorkingDirectoryOnDrive(char letter) override
+  {
+    return GetDosDriveWorkingDirectory(letter);
+  }
+
+  struct NameOnDisk
+  {
+    cmsys::Status Status;
+    std::string Name;
+  };
+  using NameOnDiskMap = std::unordered_map<std::string, NameOnDisk>;
+  NameOnDiskMap CachedNameOnDisk;
+
+  cmsys::Status ReadName(std::string const& path, std::string& name) override
+  {
+    // Cache results to avoid repeated filesystem access.
+    // We assume any files created by our own process keep their case.
+    // Index the cache by lower-case paths to make it case-insensitive.
+    std::string path_lower = cmSystemTools::LowerCase(path);
+    auto i = this->CachedNameOnDisk.find(path_lower);
+    if (i == this->CachedNameOnDisk.end()) {
+      i = this->CachedNameOnDisk.emplace(path_lower, NameOnDisk()).first;
+      i->second.Status = ReadNameOnDisk(path, i->second.Name);
+    }
+    name = i->second.Name;
+    return i->second.Status;
+  }
+#endif
+};
+
+RealSystem RealOS;
+
 } // namespace
 
 #if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
@@ -1662,11 +1777,10 @@ std::vector<std::string> cmSystemTools::SplitEnvPathNormalized(
 
 std::string cmSystemTools::ToNormalizedPathOnDisk(std::string p)
 {
-  p = cmSystemTools::CollapseFullPath(p);
-  cmSystemTools::ConvertToUnixSlashes(p);
-#ifdef _WIN32
-  p = cmSystemTools::GetActualCaseForPathCached(p);
-#endif
+  using namespace cm::PathResolver;
+  // IWYU pragma: no_forward_declare cm::PathResolver::Policies::LogicalPath
+  static const Resolver<Policies::LogicalPath> resolver(RealOS);
+  resolver.Resolve(std::move(p), p);
   return p;
 }
 
@@ -1916,12 +2030,12 @@ bool cmSystemTools::CreateTar(const std::string& outFileName,
                               std::string const& format, int compressionLevel)
 {
 #if !defined(CMAKE_BOOTSTRAP)
-  cmWorkingDirectory workdir(cmSystemTools::GetCurrentWorkingDirectory());
+  cmWorkingDirectory workdir(cmSystemTools::GetLogicalWorkingDirectory());
   if (!workingDirectory.empty()) {
     workdir.SetDirectory(workingDirectory);
   }
 
-  const std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+  const std::string cwd = cmSystemTools::GetLogicalWorkingDirectory();
   cmsys::ofstream fout(outFileName.c_str(), std::ios::out | std::ios::binary);
   if (!fout) {
     std::string e = cmStrCat("Cannot open output file \"", outFileName,
@@ -2555,6 +2669,24 @@ unsigned int cmSystemTools::RandomSeed()
 #endif
 }
 
+namespace {
+std::string InitLogicalWorkingDirectory()
+{
+  std::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory();
+  std::string pwd;
+  if (cmSystemTools::GetEnv("PWD", pwd)) {
+    std::string const pwd_real = cmSystemTools::GetRealPath(pwd);
+    if (pwd_real == cwd) {
+      cwd = std::move(pwd);
+    }
+  }
+  return cwd;
+}
+
+std::string cmSystemToolsLogicalWorkingDirectory =
+  InitLogicalWorkingDirectory();
+}
+
 static std::string cmSystemToolsCMakeCommand;
 static std::string cmSystemToolsCTestCommand;
 static std::string cmSystemToolsCPackCommand;
@@ -2779,10 +2911,18 @@ cm::optional<std::string> cmSystemTools::GetCMakeConfigDirectory()
   return config;
 }
 
-std::string cmSystemTools::GetCurrentWorkingDirectory()
+std::string const& cmSystemTools::GetLogicalWorkingDirectory()
 {
-  return cmSystemTools::ToNormalizedPathOnDisk(
-    cmsys::SystemTools::GetCurrentWorkingDirectory());
+  return cmSystemToolsLogicalWorkingDirectory;
+}
+
+cmsys::Status cmSystemTools::SetLogicalWorkingDirectory(std::string const& lwd)
+{
+  cmsys::Status status = cmSystemTools::ChangeDirectory(lwd);
+  if (status) {
+    cmSystemToolsLogicalWorkingDirectory = lwd;
+  }
+  return status;
 }
 
 void cmSystemTools::MakefileColorEcho(int color, const char* message,

+ 11 - 2
Source/cmSystemTools.h

@@ -404,6 +404,12 @@ public:
   static std::vector<std::string> SplitEnvPath(cm::string_view in);
   static std::vector<std::string> SplitEnvPathNormalized(cm::string_view in);
 
+  /** Convert an input path to an absolute path with no '/..' components.
+      Backslashes in the input path are converted to forward slashes.
+      Relative paths are interpreted w.r.t. GetLogicalWorkingDirectory.
+      On Windows, the on-disk capitalization is loaded for existing paths.
+      This is similar to 'realpath', but preserves symlinks that are
+      not erased by '../' components.  */
   static std::string ToNormalizedPathOnDisk(std::string p);
 
 #ifndef CMAKE_BOOTSTRAP
@@ -534,8 +540,11 @@ public:
   static cm::optional<std::string> GetSystemConfigDirectory();
   static cm::optional<std::string> GetCMakeConfigDirectory();
 
-  /** Get the CWD mapped through the KWSys translation map.  */
-  static std::string GetCurrentWorkingDirectory();
+  static std::string const& GetLogicalWorkingDirectory();
+
+  /** The logical working directory may contain symlinks but must not
+      contain any '../' path components.  */
+  static cmsys::Status SetLogicalWorkingDirectory(std::string const& lwd);
 
   /** Echo a message in color using KWSys's Terminal cprintf.  */
   static void MakefileColorEcho(int color, const char* message, bool newLine,

+ 2 - 2
Source/cmWorkingDirectory.cxx

@@ -7,7 +7,7 @@
 
 cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir)
 {
-  this->OldDir = cmSystemTools::GetCurrentWorkingDirectory();
+  this->OldDir = cmSystemTools::GetLogicalWorkingDirectory();
   this->SetDirectory(newdir);
 }
 
@@ -18,7 +18,7 @@ cmWorkingDirectory::~cmWorkingDirectory()
 
 bool cmWorkingDirectory::SetDirectory(std::string const& newdir)
 {
-  cmsys::Status status = cmSystemTools::ChangeDirectory(newdir);
+  cmsys::Status status = cmSystemTools::SetLogicalWorkingDirectory(newdir);
   if (status) {
     this->Error.clear();
     return true;

+ 17 - 43
Source/cmake.cxx

@@ -286,7 +286,7 @@ cmDocumentationEntry cmake::CMAKE_STANDARD_OPTIONS_TABLE[18] = {
 };
 
 cmake::cmake(Role role, cmState::Mode mode, cmState::ProjectKind projectKind)
-  : CMakeWorkingDirectory(cmSystemTools::GetCurrentWorkingDirectory())
+  : CMakeWorkingDirectory(cmSystemTools::GetLogicalWorkingDirectory())
   , FileTimeCache(cm::make_unique<cmFileTimeCache>())
 #ifndef CMAKE_BOOTSTRAP
   , VariableWatch(cm::make_unique<cmVariableWatch>())
@@ -637,8 +637,8 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
     // Documented behavior of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be
     // set to $PWD for -P mode.
     state->SetWorkingMode(SCRIPT_MODE);
-    state->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
-    state->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+    state->SetHomeDirectory(cmSystemTools::GetLogicalWorkingDirectory());
+    state->SetHomeOutputDirectory(cmSystemTools::GetLogicalWorkingDirectory());
     state->ReadListFile(args, path);
     return true;
   };
@@ -792,16 +792,16 @@ void cmake::ReadListFile(const std::vector<std::string>& args,
 
 bool cmake::FindPackage(const std::vector<std::string>& args)
 {
-  this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
-  this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+  this->SetHomeDirectory(cmSystemTools::GetLogicalWorkingDirectory());
+  this->SetHomeOutputDirectory(cmSystemTools::GetLogicalWorkingDirectory());
 
   this->SetGlobalGenerator(cm::make_unique<cmGlobalGenerator>(this));
 
   cmStateSnapshot snapshot = this->GetCurrentSnapshot();
   snapshot.GetDirectory().SetCurrentBinary(
-    cmSystemTools::GetCurrentWorkingDirectory());
+    cmSystemTools::GetLogicalWorkingDirectory());
   snapshot.GetDirectory().SetCurrentSource(
-    cmSystemTools::GetCurrentWorkingDirectory());
+    cmSystemTools::GetLogicalWorkingDirectory());
   // read in the list file to fill the cache
   snapshot.SetDefaultDefinitions();
   auto mfu = cm::make_unique<cmMakefile>(this->GetGlobalGenerator(), snapshot);
@@ -1471,10 +1471,10 @@ void cmake::SetArgs(const std::vector<std::string>& args)
   }
 
   if (!haveSourceDir) {
-    this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+    this->SetHomeDirectory(cmSystemTools::GetLogicalWorkingDirectory());
   }
   if (!haveBinaryDir) {
-    this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+    this->SetHomeOutputDirectory(cmSystemTools::GetLogicalWorkingDirectory());
   }
 
 #if !defined(CMAKE_BOOTSTRAP)
@@ -1839,12 +1839,12 @@ bool cmake::SetDirectoriesFromFile(const std::string& arg)
       this->SetHomeDirectoryViaCommandLine(listPath);
       if (no_build_tree) {
         this->SetHomeOutputDirectory(
-          cmSystemTools::GetCurrentWorkingDirectory());
+          cmSystemTools::GetLogicalWorkingDirectory());
       }
     } else if (no_source_tree && no_build_tree) {
       this->SetHomeDirectory(listPath);
       this->SetHomeOutputDirectory(
-        cmSystemTools::GetCurrentWorkingDirectory());
+        cmSystemTools::GetLogicalWorkingDirectory());
     } else if (no_build_tree) {
       this->SetHomeOutputDirectory(listPath);
     }
@@ -1861,7 +1861,7 @@ bool cmake::SetDirectoriesFromFile(const std::string& arg)
       // We didn't find a CMakeCache.txt and it wasn't specified
       // with -B. Assume the current working directory as the build tree.
       this->SetHomeOutputDirectory(
-        cmSystemTools::GetCurrentWorkingDirectory());
+        cmSystemTools::GetLogicalWorkingDirectory());
       used_provided_path = false;
     }
   }
@@ -2362,7 +2362,6 @@ int cmake::Configure()
 int cmake::ActualConfigure()
 {
   // Construct right now our path conversion table before it's too late:
-  this->UpdateConversionPathTable();
   this->CleanupCommandsAndMacros();
 
   cmSystemTools::RemoveADirectory(this->GetHomeOutputDirectory() +
@@ -3203,31 +3202,6 @@ void cmake::PrintGeneratorList()
 #endif
 }
 
-void cmake::UpdateConversionPathTable()
-{
-  // Update the path conversion table with any specified file:
-  cmValue tablepath =
-    this->State->GetInitializedCacheValue("CMAKE_PATH_TRANSLATION_FILE");
-
-  if (tablepath) {
-    cmsys::ifstream table(tablepath->c_str());
-    if (!table) {
-      cmSystemTools::Error("CMAKE_PATH_TRANSLATION_FILE set to " + *tablepath +
-                           ". CMake can not open file.");
-      cmSystemTools::ReportLastSystemError("CMake can not open file.");
-    } else {
-      std::string a;
-      std::string b;
-      while (!table.eof()) {
-        // two entries per line
-        table >> a;
-        table >> b;
-        cmSystemTools::AddTranslationPath(a, b);
-      }
-    }
-  }
-}
-
 int cmake::CheckBuildSystem()
 {
   // We do not need to rerun CMake.  Check dependency integrity.
@@ -3468,7 +3442,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
 {
   // so create the directory
   std::string resultFile;
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+  std::string cwd = cmSystemTools::GetLogicalWorkingDirectory();
   std::string destPath = cwd + "/__cmake_systeminformation";
   cmSystemTools::RemoveADirectory(destPath);
   if (!cmSystemTools::MakeDirectory(destPath)) {
@@ -3606,8 +3580,8 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
 
 #if !defined(CMAKE_BOOTSTRAP)
   if (!presetName.empty() || listPresets) {
-    this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
-    this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+    this->SetHomeDirectory(cmSystemTools::GetLogicalWorkingDirectory());
+    this->SetHomeOutputDirectory(cmSystemTools::GetLogicalWorkingDirectory());
 
     cmCMakePresetsGraph settingsFile;
     auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
@@ -3952,8 +3926,8 @@ int cmake::Workflow(const std::string& presetName,
                     WorkflowListPresets listPresets, WorkflowFresh fresh)
 {
 #ifndef CMAKE_BOOTSTRAP
-  this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
-  this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+  this->SetHomeDirectory(cmSystemTools::GetLogicalWorkingDirectory());
+  this->SetHomeOutputDirectory(cmSystemTools::GetLogicalWorkingDirectory());
 
   cmCMakePresetsGraph settingsFile;
   auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());

+ 0 - 2
Source/cmake.h

@@ -805,8 +805,6 @@ private:
 
   std::unique_ptr<cmGlobalGenerator> GlobalGenerator;
 
-  void UpdateConversionPathTable();
-
   //! Print a list of valid generators to stderr.
   void PrintGeneratorList();
 

+ 1 - 1
Source/cmakemain.cxx

@@ -219,7 +219,7 @@ std::function<bool(std::string const& value)> getShowCachedCallback(
 
 int do_cmake(int ac, char const* const* av)
 {
-  if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
+  if (cmSystemTools::GetLogicalWorkingDirectory().empty()) {
     std::cerr << "Current working directory cannot be established."
               << std::endl;
     return 1;

+ 2 - 1
Source/cmcldeps.cxx

@@ -24,6 +24,7 @@
 #include <windows.h>
 
 #include "cmsys/Encoding.hxx"
+#include "cmsys/SystemTools.hxx"
 
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
@@ -151,7 +152,7 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile,
   // FIXME should this be fatal or not? delete obj? delete d?
   if (!out)
     return;
-  std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+  std::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory();
   replaceAll(cwd, "/", "\\");
   cwd += "\\";
 

+ 1 - 1
Source/ctest.cxx

@@ -182,7 +182,7 @@ int main(int argc, char const* const* argv)
     return cmCTestLaunch::Main(argc, argv);
   }
 
-  if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
+  if (cmSystemTools::GetLogicalWorkingDirectory().empty()) {
     std::cerr << "Current working directory cannot be established.\n";
     return 1;
   }

+ 0 - 8
Source/kwsys/CMakeLists.txt

@@ -410,14 +410,6 @@ if(KWSYS_USE_DynamicLoader)
 endif()
 
 if(KWSYS_USE_SystemTools)
-  if (NOT DEFINED KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP)
-    set(KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP 1)
-  endif ()
-  if (KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP)
-    set(KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP 1)
-  else ()
-    set(KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP 0)
-  endif ()
   KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_SETENV
     "Checking whether CXX compiler has setenv" DIRECT)
   KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UNSETENV

+ 0 - 5
Source/kwsys/Configure.hxx.in

@@ -11,9 +11,6 @@
 /* Whether <ext/stdio_filebuf.h> is available. */
 #define @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H                         \
   @KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H@
-/* Whether the translation map is available or not. */
-#define @KWSYS_NAMESPACE@_SYSTEMTOOLS_USE_TRANSLATION_MAP                     \
-  @KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP@
 
 #if defined(__SUNPRO_CC) && __SUNPRO_CC > 0x5130 && defined(__has_attribute)
 #  define @KWSYS_NAMESPACE@_has_cpp_attribute(x) __has_attribute(x)
@@ -58,8 +55,6 @@
 #  define KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H                                   \
     @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
 #  define KWSYS_FALLTHROUGH @KWSYS_NAMESPACE@_FALLTHROUGH
-#  define KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP                               \
-    @KWSYS_NAMESPACE@_SYSTEMTOOLS_USE_TRANSLATION_MAP
 #endif
 
 #endif

+ 0 - 139
Source/kwsys/SystemTools.cxx

@@ -535,14 +535,6 @@ struct SystemToolsPathCaseEqual
 class SystemToolsStatic
 {
 public:
-  using StringMap = std::map<std::string, std::string>;
-#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP
-  /**
-   * Path translation table from dir to refdir
-   * Each time 'dir' will be found it will be replace by 'refdir'
-   */
-  StringMap TranslationMap;
-#endif
 #ifdef _WIN32
   static std::string GetCasePathName(std::string const& pathIn,
                                      bool const cache);
@@ -556,9 +548,6 @@ public:
     PathCaseMap;
   std::map<std::string, std::string> EnvMap;
 #endif
-#ifdef __CYGWIN__
-  StringMap Cyg2Win32Map;
-#endif
 
   /**
    * Actual implementation of ReplaceString.
@@ -3494,72 +3483,6 @@ bool SystemTools::FindProgramPath(const char* argv0, std::string& pathOut,
   return true;
 }
 
-#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP
-void SystemTools::AddTranslationPath(const std::string& a,
-                                     const std::string& b)
-{
-  std::string path_a = a;
-  std::string path_b = b;
-  SystemTools::ConvertToUnixSlashes(path_a);
-  SystemTools::ConvertToUnixSlashes(path_b);
-  // First check this is a directory path, since we don't want the table to
-  // grow too fat
-  if (SystemTools::FileIsDirectory(path_a)) {
-    // Make sure the path is a full path and does not contain no '..'
-    // Ken--the following code is incorrect. .. can be in a valid path
-    // for example  /home/martink/MyHubba...Hubba/Src
-    if (SystemTools::FileIsFullPath(path_b) &&
-        path_b.find("..") == std::string::npos) {
-      // Before inserting make sure path ends with '/'
-      if (!path_a.empty() && path_a.back() != '/') {
-        path_a += '/';
-      }
-      if (!path_b.empty() && path_b.back() != '/') {
-        path_b += '/';
-      }
-      if (!(path_a == path_b)) {
-        SystemToolsStatics->TranslationMap.insert(
-          SystemToolsStatic::StringMap::value_type(std::move(path_a),
-                                                   std::move(path_b)));
-      }
-    }
-  }
-}
-
-void SystemTools::AddKeepPath(const std::string& dir)
-{
-  std::string cdir;
-  Realpath(SystemTools::CollapseFullPath(dir), cdir);
-  SystemTools::AddTranslationPath(cdir, dir);
-}
-
-void SystemTools::CheckTranslationPath(std::string& path)
-{
-  // Do not translate paths that are too short to have meaningful
-  // translations.
-  if (path.size() < 2) {
-    return;
-  }
-
-  // Always add a trailing slash before translation.  It does not
-  // matter if this adds an extra slash, but we do not want to
-  // translate part of a directory (like the foo part of foo-dir).
-  path += '/';
-
-  // In case a file was specified we still have to go through this:
-  // Now convert any path found in the table back to the one desired:
-  for (auto const& pair : SystemToolsStatics->TranslationMap) {
-    // We need to check of the path is a substring of the other path
-    if (path.compare(0, pair.first.size(), pair.first) == 0) {
-      path = path.replace(0, pair.first.size(), pair.second);
-    }
-  }
-
-  // Remove the trailing slash we added before.
-  path.pop_back();
-}
-#endif
-
 static void SystemToolsAppendComponents(
   std::vector<std::string>& out_components,
   std::vector<std::string>::iterator first,
@@ -3622,23 +3545,6 @@ std::string CollapseFullPathImpl(std::string const& in_path,
   // Transform the path back to a string.
   std::string newPath = SystemTools::JoinPath(out_components);
 
-#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP
-  // Update the translation table with this potentially new path.  I am not
-  // sure why this line is here, it seems really questionable, but yet I
-  // would put good money that if I remove it something will break, basically
-  // from what I can see it created a mapping from the collapsed path, to be
-  // replaced by the input path, which almost completely does the opposite of
-  // this function, the only thing preventing this from happening a lot is
-  // that if the in_path has a .. in it, then it is not added to the
-  // translation table. So for most calls this either does nothing due to the
-  // ..  or it adds a translation between identical paths as nothing was
-  // collapsed, so I am going to try to comment it out, and see what hits the
-  // fan, hopefully quickly.
-  // Commented out line below:
-  // SystemTools::AddTranslationPath(newPath, in_path);
-
-  SystemTools::CheckTranslationPath(newPath);
-#endif
 #ifdef _WIN32
   SystemTools::ConvertToUnixSlashes(newPath);
 #endif
@@ -4969,51 +4875,6 @@ void SystemTools::ClassInitialize()
 
   // Create statics singleton instance
   SystemToolsStatics = new SystemToolsStatic;
-
-#if KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP
-// Add some special translation paths for unix.  These are not added
-// for windows because drive letters need to be maintained.  Also,
-// there are not sym-links and mount points on windows anyway.
-#  if !defined(_WIN32) || defined(__CYGWIN__)
-  // The tmp path is frequently a logical path so always keep it:
-  SystemTools::AddKeepPath("/tmp/");
-
-  // If the current working directory is a logical path then keep the
-  // logical name.
-  std::string pwd_str;
-  if (SystemTools::GetEnv("PWD", pwd_str)) {
-    char buf[2048];
-    if (const char* cwd = Getcwd(buf, 2048)) {
-      // The current working directory may be a logical path.  Find
-      // the shortest logical path that still produces the correct
-      // physical path.
-      std::string cwd_changed;
-      std::string pwd_changed;
-
-      // Test progressively shorter logical-to-physical mappings.
-      std::string cwd_str = cwd;
-      std::string pwd_path;
-      Realpath(pwd_str, pwd_path);
-      while (cwd_str == pwd_path && cwd_str != pwd_str) {
-        // The current pair of paths is a working logical mapping.
-        cwd_changed = cwd_str;
-        pwd_changed = pwd_str;
-
-        // Strip off one directory level and see if the logical
-        // mapping still works.
-        pwd_str = SystemTools::GetFilenamePath(pwd_str);
-        cwd_str = SystemTools::GetFilenamePath(cwd_str);
-        Realpath(pwd_str, pwd_path);
-      }
-
-      // Add the translation to keep the logical path name.
-      if (!cwd_changed.empty() && !pwd_changed.empty()) {
-        SystemTools::AddTranslationPath(cwd_changed, pwd_changed);
-      }
-    }
-  }
-#  endif
-#endif
 }
 
 void SystemTools::ClassFinalize()

+ 0 - 26
Source/kwsys/SystemTools.hxx.in

@@ -985,25 +985,6 @@ public:
    */
   static int GetTerminalWidth();
 
-#if @KWSYS_NAMESPACE@_SYSTEMTOOLS_USE_TRANSLATION_MAP
-  /**
-   * Add an entry in the path translation table.
-   */
-  static void AddTranslationPath(const std::string& dir,
-                                 const std::string& refdir);
-
-  /**
-   * If dir is different after CollapseFullPath is called,
-   * Then insert it into the path translation table
-   */
-  static void AddKeepPath(const std::string& dir);
-
-  /**
-   * Update path by going through the Path Translation table;
-   */
-  static void CheckTranslationPath(std::string& path);
-#endif
-
   /**
    * Delay the execution for a specified amount of time specified
    * in milliseconds
@@ -1053,14 +1034,7 @@ public:
   static std::string DecodeURL(const std::string& url);
 
 private:
-  /**
-   * Allocate the stl map that serve as the Path Translation table.
-   */
   static void ClassInitialize();
-
-  /**
-   * Deallocate the stl map that serve as the Path Translation table.
-   */
   static void ClassFinalize();
 
   /**

+ 3 - 2
Tests/CMakeLib/testDebuggerAdapterPipe.cxx

@@ -20,9 +20,10 @@
 #include "cmVersionConfig.h"
 
 #ifdef _WIN32
+#  include "cmsys/SystemTools.hxx"
+
 #  include "cmCryptoHash.h"
 #  include "cmDebuggerWindowsPipeConnection.h"
-#  include "cmSystemTools.h"
 #else
 #  include "cmDebuggerPosixPipeConnection.h"
 #endif
@@ -69,7 +70,7 @@ bool testProtocolWithPipes()
 #ifdef _WIN32
   std::string namedPipe = R"(\\.\pipe\LOCAL\CMakeDebuggerPipe2_)" +
     cmCryptoHash(cmCryptoHash::AlgoSHA256)
-      .HashString(cmSystemTools::GetCurrentWorkingDirectory());
+      .HashString(cmsys::SystemTools::GetCurrentWorkingDirectory());
 #else
   std::string namedPipe = "CMakeDebuggerPipe2";
 #endif

+ 2 - 2
Tests/CMakeLib/testUVProcessChainHelper.cxx

@@ -7,7 +7,7 @@
 #include <string>
 #include <thread>
 
-#include "cmSystemTools.h"
+#include "cmsys/SystemTools.hxx"
 
 #ifdef _WIN32
 #  include <windows.h>
@@ -73,7 +73,7 @@ int main(int argc, char** argv)
 #endif
   }
   if (command == "pwd") {
-    std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+    std::string cwd = cmsys::SystemTools::GetCurrentWorkingDirectory();
     std::cout << cwd << std::flush;
     return 0;
   }

+ 0 - 2
bootstrap

@@ -844,7 +844,6 @@ cmake_kwsys_config_replace_string ()
               s/@KWSYS_NAME_IS_KWSYS@/${KWSYS_NAME_IS_KWSYS}/g;
               s/@KWSYS_STL_HAS_WSTRING@/${KWSYS_STL_HAS_WSTRING}/g;
               s/@KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H@/${KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H}/g;
-              s/@KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP@/${KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP}/g;
              }" "${INFILE}" >> "${OUTFILE}${_tmp}"
     if test -f "${OUTFILE}${_tmp}"; then
       if "${_diff}" "${OUTFILE}" "${OUTFILE}${_tmp}" > /dev/null 2> /dev/null ; then
@@ -1564,7 +1563,6 @@ KWSYS_CXX_HAS_UNSETENV=0
 KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=0
 KWSYS_CXX_HAS_UTIMENSAT=0
 KWSYS_CXX_HAS_UTIMES=0
-KWSYS_SYSTEMTOOLS_USE_TRANSLATION_MAP=1
 
 if cmake_try_run "${cmake_cxx_compiler}" \
   "${cmake_cxx_flags} ${cmake_ld_flags} -DTEST_KWSYS_CXX_HAS_SETENV" \