Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.

Commit 0151617

Browse files
authored
Enhancement: Use XDG Directory Specification by default on Linux (#2035)
* Enhancement: Use XDG directory specification on Linux * Use C++ type safety and a bit refactoring * Ensure parent directory for config file exists in CreateConfigIfNotExist() * Set XDG helper function name to GetXDGDirectoryPath * E2E: Test XDG directory folder path on Linux * Remove extra empty line
1 parent 2691939 commit 0151617

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

engine/e2e-test/cli/common/test_create_log_folder.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,20 @@
66
from utils.test_runner import start_server, stop_server
77

88

9+
def get_root_path():
10+
if platform.system() == "Linux":
11+
# For Linux, use the XDG base directory.
12+
# Here we use XDG_DATA_HOME if set, otherwise default to ~/.local/share.
13+
return Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local" / "share"))
14+
else:
15+
return Path.home()
16+
917
class TestCreateLogFolder:
1018
@pytest.fixture(autouse=True)
1119
def setup_and_teardown(self):
1220
# Setup
1321
stop_server()
14-
root = Path.home()
22+
root = get_root_path()
1523
if os.path.exists(root / "cortexcpp" / "logs"):
1624
shutil.rmtree(root / "cortexcpp" / "logs")
1725
success = start_server()
@@ -24,7 +32,7 @@ def setup_and_teardown(self):
2432
stop_server()
2533

2634
def test_create_log_folder_run_successfully(self):
27-
root = Path.home()
35+
root = get_root_path()
2836
assert (
2937
os.path.exists(root / "cortexcpp" / "logs")
3038
or os.path.exists(root / "cortexcpp-beta" / "logs")

engine/utils/file_manager_utils.cc

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ std::filesystem::path GetHomeDirectoryPath() {
7878
return std::filesystem::path(homeDir);
7979
}
8080

81+
// Helper function to get XDG base directory, falling back to default if not set
82+
std::filesystem::path GetXDGDirectoryPath(const std::string& envVar,
83+
const std::string& defaultPath) {
84+
if (const char* envValue = std::getenv(envVar.c_str());
85+
envValue && std::strlen(envValue) > 0) {
86+
return std::filesystem::path(envValue);
87+
}
88+
return GetHomeDirectoryPath() / defaultPath;
89+
}
90+
8191
std::filesystem::path GetConfigurationPath() {
8292
#ifndef CORTEX_CONFIG_FILE_PATH
8393
#define CORTEX_CONFIG_FILE_PATH kDefaultConfigurationPath
@@ -113,9 +123,14 @@ std::filesystem::path GetConfigurationPath() {
113123
std::string config_file_name{kCortexConfigurationFileName};
114124
config_file_name.append(env_postfix);
115125
// CTL_INF("Config file name: " + config_file_name);
116-
126+
#if defined(__linux__)
127+
auto config_base_path =
128+
GetXDGDirectoryPath("XDG_CONFIG_HOME", ".config") / kCortexFolderName;
129+
auto configuration_path = config_base_path / config_file_name;
130+
#else
117131
auto home_path = GetHomeDirectoryPath();
118132
auto configuration_path = home_path / config_file_name;
133+
#endif
119134
return configuration_path;
120135
}
121136

@@ -150,11 +165,20 @@ cpp::result<void, std::string> UpdateCortexConfig(
150165
config_yaml_utils::CortexConfig GetDefaultConfig() {
151166
auto config_path = GetConfigurationPath();
152167
auto default_data_folder_name = GetDefaultDataFolderName();
168+
#if defined(__linux__)
169+
auto default_data_folder_path =
170+
cortex_data_folder_path.empty()
171+
? file_manager_utils::GetXDGDirectoryPath("XDG_DATA_HOME",
172+
".local/share") /
173+
default_data_folder_name
174+
: std::filesystem::path(cortex_data_folder_path);
175+
#else
153176
auto default_data_folder_path =
154177
cortex_data_folder_path.empty()
155178
? file_manager_utils::GetHomeDirectoryPath() /
156179
default_data_folder_name
157180
: std::filesystem::path(cortex_data_folder_path);
181+
#endif
158182

159183
return config_yaml_utils::CortexConfig{
160184
#if defined(_WIN32)
@@ -204,6 +228,10 @@ cpp::result<void, std::string> CreateConfigFileIfNotExist() {
204228
// already exists, no need to create
205229
return {};
206230
}
231+
if (!std::filesystem::exists(config_path.parent_path())) {
232+
// Ensure the configuration directory exists
233+
std::filesystem::create_directories(config_path.parent_path());
234+
}
207235

208236
CLI_LOG("Config file not found. Creating one at " + config_path.string());
209237
auto config = GetDefaultConfig();
@@ -236,8 +264,13 @@ std::filesystem::path GetCortexDataPath() {
236264
data_folder_path = std::filesystem::path(config.dataFolderPath);
237265
#endif
238266
} else {
267+
#if defined(__linux__)
268+
auto data_base_path = GetXDGDirectoryPath("XDG_DATA_HOME", ".local/share");
269+
data_folder_path = data_base_path / GetDefaultDataFolderName();
270+
#else
239271
auto home_path = GetHomeDirectoryPath();
240272
data_folder_path = home_path / kCortexFolderName;
273+
#endif
241274
}
242275

243276
if (!std::filesystem::exists(data_folder_path)) {
@@ -253,13 +286,19 @@ std::filesystem::path GetCortexLogPath() {
253286
// TODO: get the variant of cortex. As discussed, we will have: prod, beta, nightly
254287

255288
// currently we will store cortex data at ~/cortexcpp
289+
// On linux, we follow the xdg directory specification
256290
auto config = GetCortexConfig();
257291
std::filesystem::path log_folder_path;
258292
if (!config.logFolderPath.empty()) {
259293
log_folder_path = std::filesystem::path(config.logFolderPath);
260294
} else {
295+
#if defined(__linux__)
296+
auto data_base_path = GetXDGDirectoryPath("XDG_DATA_HOME", ".local/share");
297+
log_folder_path = data_base_path / GetDefaultDataFolderName() / "logs";
298+
#else
261299
auto home_path = GetHomeDirectoryPath();
262300
log_folder_path = home_path / kCortexFolderName;
301+
#endif
263302
}
264303

265304
if (!std::filesystem::exists(log_folder_path)) {

0 commit comments

Comments
 (0)