Revert "[VFS] Allow multiple RealFileSystem instances with independent CWDs."
This reverts commit r351079, r351069 and r351050 as it broken the greendragon bots on macOS.

llvm-svn: 351091
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index f400a7c..360f8d0 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -228,28 +228,9 @@
 
 namespace {
 
-/// A file system according to your operating system.
-/// This may be linked to the process's working directory, or maintain its own.
-///
-/// Currently, its own working directory is emulated by storing the path and
-/// sending absolute paths to llvm::sys::fs:: functions.
-/// A more principled approach would be to push this down a level, modelling
-/// the working dir as an llvm::sys::fs::WorkingDir or similar.
-/// This would enable the use of openat()-style functions on some platforms.
+/// The file system according to your operating system.
 class RealFileSystem : public FileSystem {
 public:
-  explicit RealFileSystem(bool LinkCWDToProcess) {
-    if (!LinkCWDToProcess) {
-      SmallString<128> PWD, RealPWD;
-      if (llvm::sys::fs::current_path(PWD))
-        return; // Awful, but nothing to do here.
-      if (llvm::sys::fs::real_path(PWD, RealPWD))
-        WD = {PWD, PWD};
-      else
-        WD = {PWD, RealPWD};
-    }
-  }
-
   ErrorOr<Status> status(const Twine &Path) override;
   ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
   directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
@@ -261,32 +242,15 @@
                               SmallVectorImpl<char> &Output) const override;
 
 private:
-  // If this FS has its own working dir, use it to make Path absolute.
-  // The returned twine is safe to use as long as both Storage and Path live.
-  Twine adjustPath(const Twine &Path, SmallVectorImpl<char> &Storage) const {
-    if (!WD)
-      return Path;
-    Path.toVector(Storage);
-    sys::fs::make_absolute(WD->Resolved, Storage);
-    return Storage;
-  }
-
-  struct WorkingDirectory {
-    // The current working directory, without symlinks resolved. (echo $PWD).
-    SmallString<128> Specified;
-    // The current working directory, with links resolved. (readlink .).
-    SmallString<128> Resolved;
-  };
-  Optional<WorkingDirectory> WD;
+  mutable std::mutex CWDMutex;
+  mutable std::string CWDCache;
 };
 
 } // namespace
 
 ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
-  SmallString<256> Storage;
   sys::fs::file_status RealStatus;
-  if (std::error_code EC =
-          sys::fs::status(adjustPath(Path, Storage), RealStatus))
+  if (std::error_code EC = sys::fs::status(Path, RealStatus))
     return EC;
   return Status::copyWithNewName(RealStatus, Path.str());
 }
@@ -294,61 +258,56 @@
 ErrorOr<std::unique_ptr<File>>
 RealFileSystem::openFileForRead(const Twine &Name) {
   int FD;
-  SmallString<256> RealName, Storage;
-  if (std::error_code EC = sys::fs::openFileForRead(
-          adjustPath(Name, Storage), FD, sys::fs::OF_None, &RealName))
+  SmallString<256> RealName;
+  if (std::error_code EC =
+          sys::fs::openFileForRead(Name, FD, sys::fs::OF_None, &RealName))
     return EC;
   return std::unique_ptr<File>(new RealFile(FD, Name.str(), RealName.str()));
 }
 
 llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
-  if (WD)
-    return WD->Specified.str();
-
-  SmallString<128> Dir;
+  std::lock_guard<std::mutex> Lock(CWDMutex);
+  if (!CWDCache.empty())
+    return CWDCache;
+  SmallString<256> Dir;
   if (std::error_code EC = llvm::sys::fs::current_path(Dir))
     return EC;
-  return Dir.str();
+  CWDCache = Dir.str();
+  return CWDCache;
 }
 
 std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
-  if (!WD)
-    return llvm::sys::fs::set_current_path(Path);
+  // FIXME: chdir is thread hostile; on the other hand, creating the same
+  // behavior as chdir is complex: chdir resolves the path once, thus
+  // guaranteeing that all subsequent relative path operations work
+  // on the same path the original chdir resulted in. This makes a
+  // difference for example on network filesystems, where symlinks might be
+  // switched during runtime of the tool. Fixing this depends on having a
+  // file system abstraction that allows openat() style interactions.
+  if (auto EC = llvm::sys::fs::set_current_path(Path))
+    return EC;
 
-  SmallString<128> Absolute, Resolved, Storage;
-  adjustPath(Path, Storage).toVector(Absolute);
-  bool IsDir;
-  if (auto Err = llvm::sys::fs::is_directory(Absolute, IsDir))
-    return Err;
-  if (!IsDir)
-    return std::make_error_code(std::errc::not_a_directory);
-  if (auto Err = llvm::sys::fs::real_path(Absolute, Resolved))
-    return Err;
-  WD = {Absolute, Resolved};
+  // Invalidate cache.
+  std::lock_guard<std::mutex> Lock(CWDMutex);
+  CWDCache.clear();
   return std::error_code();
 }
 
 std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {
-  SmallString<256> Storage;
-  return llvm::sys::fs::is_local(adjustPath(Path, Storage), Result);
+  return llvm::sys::fs::is_local(Path, Result);
 }
 
 std::error_code
 RealFileSystem::getRealPath(const Twine &Path,
                             SmallVectorImpl<char> &Output) const {
-  SmallString<256> Storage;
-  return llvm::sys::fs::real_path(adjustPath(Path, Storage), Output);
+  return llvm::sys::fs::real_path(Path, Output);
 }
 
 IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
-  static IntrusiveRefCntPtr<FileSystem> FS(new RealFileSystem(true));
+  static IntrusiveRefCntPtr<FileSystem> FS = new RealFileSystem();
   return FS;
 }
 
-std::unique_ptr<FileSystem> vfs::createPhysicalFileSystem() {
-  return llvm::make_unique<RealFileSystem>(false);
-}
-
 namespace {
 
 class RealFSDirIter : public llvm::vfs::detail::DirIterImpl {
@@ -374,9 +333,7 @@
 
 directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
                                              std::error_code &EC) {
-  SmallString<128> Storage;
-  return directory_iterator(
-      std::make_shared<RealFSDirIter>(adjustPath(Dir, Storage), EC));
+  return directory_iterator(std::make_shared<RealFSDirIter>(Dir, EC));
 }
 
 //===-----------------------------------------------------------------------===/