diff --git a/src/basic_memory/config.py b/src/basic_memory/config.py index 998c7c6b..d8cfae0c 100644 --- a/src/basic_memory/config.py +++ b/src/basic_memory/config.py @@ -180,7 +180,14 @@ class ConfigManager: if self.config_file.exists(): try: data = json.loads(self.config_file.read_text(encoding="utf-8")) - return BasicMemoryConfig(**data) + config = BasicMemoryConfig(**data) + + # Allow BASIC_MEMORY_HOME environment variable to override the main project path + env_home = os.getenv("BASIC_MEMORY_HOME") + if env_home: + config.projects["main"] = str(Path(env_home)) + + return config except Exception as e: # pragma: no cover logger.error(f"Failed to load config: {e}") config = BasicMemoryConfig() diff --git a/tests/test_config.py b/tests/test_config.py index 6c03fbc0..f0e0cf1e 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,6 +1,7 @@ """Test configuration management.""" -from basic_memory.config import BasicMemoryConfig +import json +from basic_memory.config import BasicMemoryConfig, ConfigManager class TestBasicMemoryConfig: @@ -76,3 +77,71 @@ class TestBasicMemoryConfig: # The default_factory should override with BASIC_MEMORY_HOME value # Note: This tests the current behavior where default_factory takes precedence assert config.projects["main"] == original_path + + +class TestConfigManager: + """Test ConfigManager behavior with BASIC_MEMORY_HOME environment variable.""" + + def test_load_config_respects_basic_memory_home_with_existing_file(self, config_home, monkeypatch): + """Test that ConfigManager.load_config respects BASIC_MEMORY_HOME even when config file exists.""" + # Set up a custom path via environment variable + custom_path = str(config_home / "custom" / "env" / "path") + monkeypatch.setenv("BASIC_MEMORY_HOME", custom_path) + + # Create a config manager with a temporary config directory + config_dir = config_home / ".basic-memory" + config_dir.mkdir(parents=True, exist_ok=True) + config_file = config_dir / "config.json" + + # Create a config file with a different main project path + file_config = { + "projects": { + "main": str(config_home / "file" / "path") + }, + "default_project": "main" + } + config_file.write_text(json.dumps(file_config)) + + # Mock the ConfigManager to use our temporary config directory + monkeypatch.setattr("basic_memory.config.ConfigManager.config_dir", config_dir) + monkeypatch.setattr("basic_memory.config.ConfigManager.config_file", config_file) + + # Create ConfigManager and load config + config_manager = ConfigManager() + config_manager.config_dir = config_dir + config_manager.config_file = config_file + + loaded_config = config_manager.load_config() + + # The environment variable should override the file-based configuration + assert loaded_config.projects["main"] == custom_path + + def test_load_config_without_basic_memory_home_uses_file_config(self, config_home, monkeypatch): + """Test that ConfigManager.load_config uses file config when BASIC_MEMORY_HOME is not set.""" + # Ensure BASIC_MEMORY_HOME is not set + monkeypatch.delenv("BASIC_MEMORY_HOME", raising=False) + + # Create a config manager with a temporary config directory + config_dir = config_home / ".basic-memory" + config_dir.mkdir(parents=True, exist_ok=True) + config_file = config_dir / "config.json" + + # Create a config file with a specific main project path + file_path = str(config_home / "file" / "path") + file_config = { + "projects": { + "main": file_path + }, + "default_project": "main" + } + config_file.write_text(json.dumps(file_config)) + + # Create ConfigManager and load config + config_manager = ConfigManager() + config_manager.config_dir = config_dir + config_manager.config_file = config_file + + loaded_config = config_manager.load_config() + + # Should use the file-based configuration + assert loaded_config.projects["main"] == file_path