diff --git a/internal/config/load.go b/internal/config/load.go index 478f90c..e59c3ed 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -66,6 +66,19 @@ func LoadConfigWithHost(host string) (*Config, error) { // getDefaultConfigPathInternal is the actual implementation for GetDefaultConfigPath. func getDefaultConfigPathInternal() (string, error) { + // RALPH_CONFIG takes precedence over the XDG path. If set, the file must + // exist; we fail loudly rather than silently falling back to the default. + if envPath := os.Getenv("RALPH_CONFIG"); envPath != "" { + expanded, err := ExpandPath(envPath) + if err != nil { + return "", fmt.Errorf("RALPH_CONFIG=%s: %w", envPath, err) + } + if _, err := os.Stat(expanded); err != nil { + return "", fmt.Errorf("RALPH_CONFIG=%s: %w", envPath, err) + } + return expanded, nil + } + xdgConfigHome := os.Getenv("XDG_CONFIG_HOME") if xdgConfigHome == "" { homeDir, err := os.UserHomeDir() diff --git a/internal/config/load_test.go b/internal/config/load_test.go index 28fdffe..4ab2c01 100644 --- a/internal/config/load_test.go +++ b/internal/config/load_test.go @@ -381,7 +381,52 @@ func TestLoadConfig_WithEnableField(t *testing.T) { } } +func TestGetDefaultConfigPath_RalphConfigEnv(t *testing.T) { + t.Run("RALPH_CONFIG points to an existing file", func(t *testing.T) { + cfgPath, cleanup := createTempConfigFile(t, "") + defer cleanup() + + t.Setenv("RALPH_CONFIG", cfgPath) + + got, err := GetDefaultConfigPath() + if err != nil { + t.Fatalf("GetDefaultConfigPath() error = %v", err) + } + if got != cfgPath { + t.Errorf("GetDefaultConfigPath() = %v, want %v", got, cfgPath) + } + }) + + t.Run("RALPH_CONFIG points to a nonexistent file", func(t *testing.T) { + missing := filepath.Join(t.TempDir(), "does-not-exist.toml") + t.Setenv("RALPH_CONFIG", missing) + + if _, err := GetDefaultConfigPath(); err == nil { + t.Fatal("GetDefaultConfigPath() expected error for missing RALPH_CONFIG file, got nil") + } + }) + + t.Run("RALPH_CONFIG takes precedence over XDG_CONFIG_HOME", func(t *testing.T) { + cfgPath, cleanup := createTempConfigFile(t, "") + defer cleanup() + + t.Setenv("XDG_CONFIG_HOME", "/tmp/custom_xdg_config") + t.Setenv("RALPH_CONFIG", cfgPath) + + got, err := GetDefaultConfigPath() + if err != nil { + t.Fatalf("GetDefaultConfigPath() error = %v", err) + } + if got != cfgPath { + t.Errorf("GetDefaultConfigPath() = %v, want %v", got, cfgPath) + } + }) +} + func TestGetDefaultConfigPath(t *testing.T) { + // Ensure RALPH_CONFIG doesn't leak in and override the XDG-based logic. + t.Setenv("RALPH_CONFIG", "") + homeDir, err := os.UserHomeDir() if err != nil { t.Fatalf("Failed to get user home dir: %v", err)