[llvm] [clang-repl] Support XDG state directory for history (PR #223037)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 23:05:05 PDT 2026


https://github.com/RohanOnKeys updated https://github.com/llvm/llvm-project/pull/223037

>From a3c107f77e97476a2b89cc4d3b809092e890d0ba Mon Sep 17 00:00:00 2001
From: rohan <rohanpxquantum at gmail.com>
Date: Fri, 11 Sep 2026 19:49:56 +0000
Subject: [PATCH] [clang-repl] Support XDG state directory for history

Signed-off-by: rohan <rohanpxquantum at gmail.com>
---
 llvm/lib/LineEditor/LineEditor.cpp       | 29 +++++++--
 llvm/unittests/LineEditor/LineEditor.cpp | 81 ++++++++++++++++++++++++
 2 files changed, 106 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/LineEditor/LineEditor.cpp b/llvm/lib/LineEditor/LineEditor.cpp
index 3e4004313acf2..d0f3215f3678f 100644
--- a/llvm/lib/LineEditor/LineEditor.cpp
+++ b/llvm/lib/LineEditor/LineEditor.cpp
@@ -10,7 +10,9 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Config/config.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cassert>
@@ -24,11 +26,30 @@ using namespace llvm;
 
 std::string LineEditor::getDefaultHistoryPath(StringRef ProgName) {
   SmallString<32> Path;
-  if (sys::path::home_directory(Path)) {
-    sys::path::append(Path, "." + ProgName + "-history");
-    return std::string(Path);
+  if (!sys::path::home_directory(Path))
+    return std::string();
+
+#ifdef __linux__
+  SmallString<32> LegacyPath(Path);
+  sys::path::append(LegacyPath, "." + ProgName + "-history");
+
+  if (sys::fs::exists(LegacyPath))
+    return std::string(LegacyPath);
+
+  if (auto StateHome = sys::Process::GetEnv("XDG_STATE_HOME")) {
+    Path = *StateHome;
+  } else {
+    sys::path::append(Path, ".local", "state");
   }
-  return std::string();
+
+  (void)sys::fs::create_directories(Path);
+
+  sys::path::append(Path, ProgName + "-history");
+  return std::string(Path);
+#else
+  sys::path::append(Path, "." + ProgName + "-history");
+  return std::string(Path);
+#endif
 }
 
 LineEditor::CompleterConcept::~CompleterConcept() = default;
diff --git a/llvm/unittests/LineEditor/LineEditor.cpp b/llvm/unittests/LineEditor/LineEditor.cpp
index 42e5c6c3c01f5..ea024d78753ae 100644
--- a/llvm/unittests/LineEditor/LineEditor.cpp
+++ b/llvm/unittests/LineEditor/LineEditor.cpp
@@ -80,3 +80,84 @@ TEST_F(LineEditorTest, ListCompleters) {
   EXPECT_EQ(LineEditor::CompletionAction::AK_Insert, CA.Kind);
   EXPECT_EQ("f", CA.Text);
 }
+
+
+#ifdef __linux__
+
+#include <cstdlib>
+
+TEST(LineEditorDefaultHistoryPath, DefaultHistoryPathUsesXDGStateHome) {
+  SmallString<128> TempDir;
+  ASSERT_FALSE(sys::fs::createUniqueDirectory("xdg-state", TempDir));
+
+  setenv("XDG_STATE_HOME", TempDir.c_str(), 1);
+
+  std::string Path = LineEditor::getDefaultHistoryPath("clang-repl");
+
+  EXPECT_EQ((TempDir + "/clang-repl-history").str().str(), Path);
+
+  unsetenv("XDG_STATE_HOME");
+  sys::fs::remove_directories(TempDir);
+}
+
+#endif
+
+#ifdef __linux__
+
+TEST(LineEditorDefaultHistoryPath, ExistingLegacyHistoryTakesPrecedence) {
+  SmallString<128> HomeDir;
+  ASSERT_FALSE(sys::fs::createUniqueDirectory("lineeditor-home", HomeDir));
+
+  SmallString<128> Legacy(HomeDir);
+  sys::path::append(Legacy, ".clang-repl-history");
+
+  std::error_code EC;
+  raw_fd_ostream OS(Legacy, EC);
+  ASSERT_FALSE(EC);
+  OS.close();
+
+  setenv("HOME", HomeDir.c_str(), 1);
+
+  SmallString<128> XDGDir;
+  ASSERT_FALSE(sys::fs::createUniqueDirectory("xdg-state", XDGDir));
+  setenv("XDG_STATE_HOME", XDGDir.c_str(), 1);
+
+  EXPECT_EQ(Legacy.str(), LineEditor::getDefaultHistoryPath("clang-repl"));
+
+  unsetenv("HOME");
+  unsetenv("XDG_STATE_HOME");
+  sys::fs::remove_directories(HomeDir);
+  sys::fs::remove_directories(XDGDir);
+}
+
+#endif
+
+#ifdef __linux__
+
+TEST(LineEditorDefaultHistoryPath, ExistingLegacyHistoryTakesPrecedence) {
+  SmallString<128> HomeDir;
+  ASSERT_FALSE(sys::fs::createUniqueDirectory("lineeditor-home", HomeDir));
+
+  SmallString<128> Legacy(HomeDir);
+  sys::path::append(Legacy, ".clang-repl-history");
+
+  std::error_code EC;
+  raw_fd_ostream OS(Legacy, EC);
+  ASSERT_FALSE(EC);
+  OS.close();
+
+  setenv("HOME", HomeDir.c_str(), 1);
+
+  SmallString<128> XDGDir;
+  ASSERT_FALSE(sys::fs::createUniqueDirectory("xdg-state", XDGDir));
+  setenv("XDG_STATE_HOME", XDGDir.c_str(), 1);
+
+  EXPECT_EQ(Legacy.str(), LineEditor::getDefaultHistoryPath("clang-repl"));
+
+  unsetenv("HOME");
+  unsetenv("XDG_STATE_HOME");
+  sys::fs::remove_directories(HomeDir);
+  sys::fs::remove_directories(XDGDir);
+}
+
+#endif



More information about the llvm-commits mailing list