[Reproducer] Capture the debugger's working directory

This patch extends the reproducer to capture the debugger's current
working directory. This information will be used later to set the
current working directory of the VFS.

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@375059 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/Utility/Reproducer.h b/include/lldb/Utility/Reproducer.h
index 7fde9c3..1bc8d7a 100644
--- a/include/lldb/Utility/Reproducer.h
+++ b/include/lldb/Utility/Reproducer.h
@@ -132,6 +132,27 @@
   static char ID;
 };
 
+/// Provider for the LLDB current working directroy.
+///
+/// When the reproducer is kept, it writes lldb's current working directory to
+/// a file named cwd.txt in the reproducer root.
+class WorkingDirectoryProvider : public Provider<WorkingDirectoryProvider> {
+public:
+  WorkingDirectoryProvider(const FileSpec &directory) : Provider(directory) {
+    llvm::SmallString<128> cwd;
+    if (std::error_code EC = llvm::sys::fs::current_path(cwd))
+      return;
+    m_cwd = cwd.str();
+  }
+  struct Info {
+    static const char *name;
+    static const char *file;
+  };
+  void Keep() override;
+  std::string m_cwd;
+  static char ID;
+};
+
 class DataRecorder {
 public:
   DataRecorder(const FileSpec &filename, std::error_code &ec)
diff --git a/source/Utility/Reproducer.cpp b/source/Utility/Reproducer.cpp
index a8a581f..4777d75 100644
--- a/source/Utility/Reproducer.cpp
+++ b/source/Utility/Reproducer.cpp
@@ -144,7 +144,9 @@
 }
 
 Generator::Generator(FileSpec root)
-    : m_root(MakeAbsolute(std::move(root))), m_done(false) {}
+    : m_root(MakeAbsolute(std::move(root))), m_done(false) {
+  GetOrCreate<repro::WorkingDirectoryProvider>();
+}
 
 Generator::~Generator() {}
 
@@ -281,6 +283,15 @@
   os << m_version << "\n";
 }
 
+void WorkingDirectoryProvider::Keep() {
+  FileSpec file = GetRoot().CopyByAppendingPathComponent(Info::file);
+  std::error_code ec;
+  llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text);
+  if (ec)
+    return;
+  os << m_cwd << "\n";
+}
+
 llvm::raw_ostream *ProcessGDBRemoteProvider::GetHistoryStream() {
   FileSpec history_file = GetRoot().CopyByAppendingPathComponent(Info::file);
 
@@ -330,6 +341,7 @@
 char ProcessGDBRemoteProvider::ID = 0;
 char ProviderBase::ID = 0;
 char VersionProvider::ID = 0;
+char WorkingDirectoryProvider::ID = 0;
 const char *CommandProvider::Info::file = "command-interpreter.yaml";
 const char *CommandProvider::Info::name = "command-interpreter";
 const char *FileProvider::Info::file = "files.yaml";
@@ -338,3 +350,5 @@
 const char *ProcessGDBRemoteProvider::Info::name = "gdb-remote";
 const char *VersionProvider::Info::file = "version.txt";
 const char *VersionProvider::Info::name = "version";
+const char *WorkingDirectoryProvider::Info::file = "cwd.txt";
+const char *WorkingDirectoryProvider::Info::name = "cwd";
diff --git a/test/Shell/Reproducer/TestWorkingDir.test b/test/Shell/Reproducer/TestWorkingDir.test
new file mode 100644
index 0000000..eb0af84
--- /dev/null
+++ b/test/Shell/Reproducer/TestWorkingDir.test
@@ -0,0 +1,11 @@
+# This tests relative capture paths.
+
+# RUN: echo "CHECK: %t" > %t.check
+
+# RUN: rm -rf %t.repro
+# RUN: mkdir -p %t.repro
+# RUN: mkdir -p %t
+# RUN: cd %t
+# RUN: %clang %S/Inputs/simple.c -g -o %t/reproducer.out
+# RUN: %lldb -x -b -s %S/Inputs/FileCapture.in --capture --capture-path %t.repro %t/reproducer.out
+# RUN: cat %t.repro/cwd.txt | FileCheck %t.check