From d13580ff3d4db93b6f6502c23843607351a772c9 Mon Sep 17 00:00:00 2001 From: Akarshan Biswas Date: Tue, 25 Feb 2025 13:31:08 +0530 Subject: [PATCH 1/6] Enhancement: Use XDG directory specification on Linux --- engine/utils/file_manager_utils.cc | 39 +++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/engine/utils/file_manager_utils.cc b/engine/utils/file_manager_utils.cc index 743c6a641..0742f10ed 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 GetXDGDirectory(const char* envVar, + const char* defaultPath) { + const char* envValue = getenv(envVar); + if (envValue && *envValue) { // Check if envValue is not NULL and not empty + 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,19 @@ 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 = + GetXDGDirectory("XDG_CONFIG_HOME", ".config") / kCortexFolderName; + auto configuration_path = config_base_path / config_file_name; + if (!std::filesystem::exists(config_base_path)) { + CTL_INF("Cortex config folder not found. Create one: " + + config_base_path.string()); + std::filesystem::create_directory(config_base_path); + } +#else auto home_path = GetHomeDirectoryPath(); auto configuration_path = home_path / config_file_name; +#endif return configuration_path; } @@ -152,8 +172,14 @@ config_yaml_utils::CortexConfig GetDefaultConfig() { auto default_data_folder_name = GetDefaultDataFolderName(); auto default_data_folder_path = cortex_data_folder_path.empty() +#if defined(__linux__) + ? file_manager_utils::GetXDGDirectory("XDG_DATA_HOME", + ".local/share") / + default_data_folder_name +#else ? file_manager_utils::GetHomeDirectoryPath() / default_data_folder_name +#endif : std::filesystem::path(cortex_data_folder_path); return config_yaml_utils::CortexConfig{ @@ -236,8 +262,13 @@ std::filesystem::path GetCortexDataPath() { data_folder_path = std::filesystem::path(config.dataFolderPath); #endif } else { +#if defined(__linux__) + auto data_base_path = GetXDGDirectory("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 +284,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 = GetXDGDirectory("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)) { From 9b9c8b57a255a78c147a1cbf72d54b69409798b1 Mon Sep 17 00:00:00 2001 From: Akarshan Biswas Date: Wed, 26 Feb 2025 21:05:02 +0530 Subject: [PATCH 2/6] Use C++ type safety and a bit refactoring --- engine/utils/file_manager_utils.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/engine/utils/file_manager_utils.cc b/engine/utils/file_manager_utils.cc index 0742f10ed..827a3fc07 100644 --- a/engine/utils/file_manager_utils.cc +++ b/engine/utils/file_manager_utils.cc @@ -79,10 +79,10 @@ std::filesystem::path GetHomeDirectoryPath() { } // Helper function to get XDG base directory, falling back to default if not set -std::filesystem::path GetXDGDirectory(const char* envVar, - const char* defaultPath) { - const char* envValue = getenv(envVar); - if (envValue && *envValue) { // Check if envValue is not NULL and not empty +std::filesystem::path GetXDGDirectory(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; @@ -170,17 +170,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() -#if defined(__linux__) ? file_manager_utils::GetXDGDirectory("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 -#endif : std::filesystem::path(cortex_data_folder_path); +#endif return config_yaml_utils::CortexConfig{ #if defined(_WIN32) From 06398e5797cd9e12e1e6476a68875589c3cdffea Mon Sep 17 00:00:00 2001 From: Akarshan Biswas Date: Wed, 26 Feb 2025 21:56:02 +0530 Subject: [PATCH 3/6] Ensure parent directory for config file exists in CreateConfigIfNotExist() --- engine/utils/file_manager_utils.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/engine/utils/file_manager_utils.cc b/engine/utils/file_manager_utils.cc index 827a3fc07..f13548aae 100644 --- a/engine/utils/file_manager_utils.cc +++ b/engine/utils/file_manager_utils.cc @@ -127,11 +127,6 @@ std::filesystem::path GetConfigurationPath() { auto config_base_path = GetXDGDirectory("XDG_CONFIG_HOME", ".config") / kCortexFolderName; auto configuration_path = config_base_path / config_file_name; - if (!std::filesystem::exists(config_base_path)) { - CTL_INF("Cortex config folder not found. Create one: " + - config_base_path.string()); - std::filesystem::create_directory(config_base_path); - } #else auto home_path = GetHomeDirectoryPath(); auto configuration_path = home_path / config_file_name; @@ -233,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(); From 09767a76758c8ec15116bdc0ffa38396a2dfdf73 Mon Sep 17 00:00:00 2001 From: Akarshan Biswas Date: Thu, 27 Feb 2025 07:21:06 +0530 Subject: [PATCH 4/6] Set XDG helper function name to GetXDGDirectoryPath --- engine/utils/file_manager_utils.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/engine/utils/file_manager_utils.cc b/engine/utils/file_manager_utils.cc index f13548aae..b5713456a 100644 --- a/engine/utils/file_manager_utils.cc +++ b/engine/utils/file_manager_utils.cc @@ -79,7 +79,7 @@ std::filesystem::path GetHomeDirectoryPath() { } // Helper function to get XDG base directory, falling back to default if not set -std::filesystem::path GetXDGDirectory(const std::string& envVar, +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) { @@ -125,7 +125,7 @@ std::filesystem::path GetConfigurationPath() { // CTL_INF("Config file name: " + config_file_name); #if defined(__linux__) auto config_base_path = - GetXDGDirectory("XDG_CONFIG_HOME", ".config") / kCortexFolderName; + GetXDGDirectoryPath("XDG_CONFIG_HOME", ".config") / kCortexFolderName; auto configuration_path = config_base_path / config_file_name; #else auto home_path = GetHomeDirectoryPath(); @@ -168,7 +168,7 @@ config_yaml_utils::CortexConfig GetDefaultConfig() { #if defined(__linux__) auto default_data_folder_path = cortex_data_folder_path.empty() - ? file_manager_utils::GetXDGDirectory("XDG_DATA_HOME", + ? file_manager_utils::GetXDGDirectoryPath("XDG_DATA_HOME", ".local/share") / default_data_folder_name : std::filesystem::path(cortex_data_folder_path); @@ -265,7 +265,7 @@ std::filesystem::path GetCortexDataPath() { #endif } else { #if defined(__linux__) - auto data_base_path = GetXDGDirectory("XDG_DATA_HOME", ".local/share"); + auto data_base_path = GetXDGDirectoryPath("XDG_DATA_HOME", ".local/share"); data_folder_path = data_base_path / GetDefaultDataFolderName(); #else auto home_path = GetHomeDirectoryPath(); @@ -293,7 +293,7 @@ std::filesystem::path GetCortexLogPath() { log_folder_path = std::filesystem::path(config.logFolderPath); } else { #if defined(__linux__) - auto data_base_path = GetXDGDirectory("XDG_DATA_HOME", ".local/share"); + auto data_base_path = GetXDGDirectoryPath("XDG_DATA_HOME", ".local/share"); log_folder_path = data_base_path / GetDefaultDataFolderName() / "logs"; #else auto home_path = GetHomeDirectoryPath(); From 0b7fa0557fef936503ca937527f517bfc5f24e38 Mon Sep 17 00:00:00 2001 From: Akarshan Biswas Date: Thu, 27 Feb 2025 07:54:44 +0530 Subject: [PATCH 5/6] E2E: Test XDG directory folder path on Linux --- .../e2e-test/cli/common/test_create_log_folder.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) 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..110e746c7 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,21 @@ 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 +33,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") From f8418363d7d3df28d39488dd3a3945dee53aa741 Mon Sep 17 00:00:00 2001 From: Akarshan Biswas Date: Thu, 27 Feb 2025 10:10:10 +0530 Subject: [PATCH 6/6] Remove extra empty line --- engine/e2e-test/cli/common/test_create_log_folder.py | 1 - 1 file changed, 1 deletion(-) 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 110e746c7..e7b18ab77 100644 --- a/engine/e2e-test/cli/common/test_create_log_folder.py +++ b/engine/e2e-test/cli/common/test_create_log_folder.py @@ -14,7 +14,6 @@ def get_root_path(): else: return Path.home() - class TestCreateLogFolder: @pytest.fixture(autouse=True) def setup_and_teardown(self):