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

Enhancement: Use XDG Directory Specification by default on Linux #2035

Merged
merged 6 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions engine/e2e-test/cli/common/test_create_log_folder.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@
from utils.test_runner import start_server, stop_server


def get_root_path():
if platform.system() == "Linux":
# For Linux, use the XDG base directory.
# Here we use XDG_DATA_HOME if set, otherwise default to ~/.local/share.
return Path(os.environ.get("XDG_DATA_HOME", Path.home() / ".local" / "share"))
else:
return Path.home()

class TestCreateLogFolder:
@pytest.fixture(autouse=True)
def setup_and_teardown(self):
# Setup
stop_server()
root = Path.home()
root = get_root_path()
if os.path.exists(root / "cortexcpp" / "logs"):
shutil.rmtree(root / "cortexcpp" / "logs")
success = start_server()
Expand All @@ -24,7 +32,7 @@ def setup_and_teardown(self):
stop_server()

def test_create_log_folder_run_successfully(self):
root = Path.home()
root = get_root_path()
assert (
os.path.exists(root / "cortexcpp" / "logs")
or os.path.exists(root / "cortexcpp-beta" / "logs")
Expand Down
41 changes: 40 additions & 1 deletion engine/utils/file_manager_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ std::filesystem::path GetHomeDirectoryPath() {
return std::filesystem::path(homeDir);
}

// Helper function to get XDG base directory, falling back to default if not set
std::filesystem::path GetXDGDirectoryPath(const std::string& envVar,
const std::string& defaultPath) {
if (const char* envValue = std::getenv(envVar.c_str());
envValue && std::strlen(envValue) > 0) {
return std::filesystem::path(envValue);
}
return GetHomeDirectoryPath() / defaultPath;
}

std::filesystem::path GetConfigurationPath() {
#ifndef CORTEX_CONFIG_FILE_PATH
#define CORTEX_CONFIG_FILE_PATH kDefaultConfigurationPath
Expand Down Expand Up @@ -113,9 +123,14 @@ std::filesystem::path GetConfigurationPath() {
std::string config_file_name{kCortexConfigurationFileName};
config_file_name.append(env_postfix);
// CTL_INF("Config file name: " + config_file_name);

#if defined(__linux__)
auto config_base_path =
GetXDGDirectoryPath("XDG_CONFIG_HOME", ".config") / kCortexFolderName;
auto configuration_path = config_base_path / config_file_name;
#else
auto home_path = GetHomeDirectoryPath();
auto configuration_path = home_path / config_file_name;
#endif
return configuration_path;
}

Expand Down Expand Up @@ -150,11 +165,20 @@ cpp::result<void, std::string> UpdateCortexConfig(
config_yaml_utils::CortexConfig GetDefaultConfig() {
auto config_path = GetConfigurationPath();
auto default_data_folder_name = GetDefaultDataFolderName();
#if defined(__linux__)
auto default_data_folder_path =
cortex_data_folder_path.empty()
? file_manager_utils::GetXDGDirectoryPath("XDG_DATA_HOME",
".local/share") /
default_data_folder_name
: std::filesystem::path(cortex_data_folder_path);
#else
auto default_data_folder_path =
cortex_data_folder_path.empty()
? file_manager_utils::GetHomeDirectoryPath() /
default_data_folder_name
: std::filesystem::path(cortex_data_folder_path);
#endif

return config_yaml_utils::CortexConfig{
#if defined(_WIN32)
Expand Down Expand Up @@ -204,6 +228,10 @@ cpp::result<void, std::string> CreateConfigFileIfNotExist() {
// already exists, no need to create
return {};
}
if (!std::filesystem::exists(config_path.parent_path())) {
// Ensure the configuration directory exists
std::filesystem::create_directories(config_path.parent_path());
}

CLI_LOG("Config file not found. Creating one at " + config_path.string());
auto config = GetDefaultConfig();
Expand Down Expand Up @@ -236,8 +264,13 @@ std::filesystem::path GetCortexDataPath() {
data_folder_path = std::filesystem::path(config.dataFolderPath);
#endif
} else {
#if defined(__linux__)
auto data_base_path = GetXDGDirectoryPath("XDG_DATA_HOME", ".local/share");
data_folder_path = data_base_path / GetDefaultDataFolderName();
#else
auto home_path = GetHomeDirectoryPath();
data_folder_path = home_path / kCortexFolderName;
#endif
}

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

// currently we will store cortex data at ~/cortexcpp
// On linux, we follow the xdg directory specification
auto config = GetCortexConfig();
std::filesystem::path log_folder_path;
if (!config.logFolderPath.empty()) {
log_folder_path = std::filesystem::path(config.logFolderPath);
} else {
#if defined(__linux__)
auto data_base_path = GetXDGDirectoryPath("XDG_DATA_HOME", ".local/share");
log_folder_path = data_base_path / GetDefaultDataFolderName() / "logs";
#else
auto home_path = GetHomeDirectoryPath();
log_folder_path = home_path / kCortexFolderName;
#endif
}

if (!std::filesystem::exists(log_folder_path)) {
Expand Down
Loading