Load configuration with priority support. Priority order (highest to lowest): 1. Environment variables (always highest priority) 2. Local .env file (ONLY in per-repo mode or when CGC_LOAD_PROJECT_ENV=1) 3. Global ~/.codegraphcontext/.env BUG FIX: In global/named context
()
| 338 | |
| 339 | |
| 340 | def load_config() -> Dict[str, str]: |
| 341 | """ |
| 342 | Load configuration with priority support. |
| 343 | Priority order (highest to lowest): |
| 344 | 1. Environment variables (always highest priority) |
| 345 | 2. Local .env file (ONLY in per-repo mode or when CGC_LOAD_PROJECT_ENV=1) |
| 346 | 3. Global ~/.codegraphcontext/.env |
| 347 | |
| 348 | BUG FIX: In global/named context mode, local repo .env files are now properly ignored |
| 349 | to prevent silent database redirection when working inside cloned repositories. |
| 350 | |
| 351 | Note: Does NOT create config directory - caller must call ensure_config_dir() first if needed. |
| 352 | """ |
| 353 | # Start with defaults |
| 354 | config = DEFAULT_CONFIG.copy() |
| 355 | |
| 356 | # Load global config |
| 357 | if CONFIG_FILE.exists(): |
| 358 | try: |
| 359 | with open(CONFIG_FILE, "r", encoding="utf-8") as f: |
| 360 | for line in f: |
| 361 | line = line.strip() |
| 362 | if line and not line.startswith("#") and "=" in line: |
| 363 | key, value = line.split("=", 1) |
| 364 | config[key.strip()] = value.strip() |
| 365 | except Exception as e: |
| 366 | console.print(f"[red]Error loading global config: {e}[/red]") |
| 367 | |
| 368 | # Load local .env file ONLY if should_apply_project_dotenv() returns True |
| 369 | # This respects context mode (per-repo vs global/named) and environment overrides |
| 370 | local_env = find_local_env() |
| 371 | if local_env and local_env.exists(): |
| 372 | try: |
| 373 | with open(local_env, "r", encoding="utf-8") as f: |
| 374 | for line in f: |
| 375 | line = line.strip() |
| 376 | if line and not line.startswith("#") and "=" in line: |
| 377 | key, value = line.split("=", 1) |
| 378 | key = key.strip() |
| 379 | value = value.strip() |
| 380 | |
| 381 | # In per-repo mode: allow all config keys to be overridden |
| 382 | # In global/named mode: local .env should not be loaded at all (find_local_env returns None) |
| 383 | # But if it somehow gets through, only allow non-DB-path keys for safety |
| 384 | if key in DB_PATH_ENV_KEYS: |
| 385 | # CRITICAL: Never let local .env override DB paths in global mode |
| 386 | # This prevents silent database redirection |
| 387 | continue |
| 388 | |
| 389 | if key in DEFAULT_CONFIG or key in DATABASE_CREDENTIAL_KEYS: |
| 390 | config[key] = value |
| 391 | except Exception as e: |
| 392 | console.print(f"[yellow]Warning: Error loading local .env: {e}[/yellow]") |
| 393 | |
| 394 | # Environment variables have highest priority - always override everything |
| 395 | for key in DEFAULT_CONFIG.keys(): |
| 396 | env_value = os.getenv(key) |
| 397 | if env_value is not None: |
no test coverage detected