diff --git a/engine/e2e-test/cli/common/test_create_log_folder.py b/engine/e2e-test/cli/common/test_create_log_folder.py index 7ad6ee452..e7b18ab77 100644 --- a/engine/e2e-test/cli/common/test_create_log_folder.py +++ b/engine/e2e-test/cli/common/test_create_log_folder.py @@ -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() @@ -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") diff --git a/engine/utils/file_manager_utils.cc b/engine/utils/file_manager_utils.cc index 743c6a641..b5713456a 100644 --- a/engine/utils/file_manager_utils.cc +++ b/engine/utils/file_manager_utils.cc @@ -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 @@ -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; } @@ -150,11 +165,20 @@ cpp::result 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) @@ -204,6 +228,10 @@ cpp::result 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(); @@ -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)) { @@ -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)) {