refactor(config): remove global config instance

Ayman Bagabas created

Change summary

internal/config/config.go | 15 +++++++++++++++
internal/config/init.go   | 22 +++++-----------------
internal/config/load.go   | 11 ++++-------
3 files changed, 24 insertions(+), 24 deletions(-)

Detailed changes

internal/config/config.go 🔗

@@ -577,3 +577,18 @@ func resolveEnvs(envs map[string]string) []string {
 	}
 	return res
 }
+
+type contextKey struct{}
+
+var configKey = contextKey{}
+
+// WithContext returns a copy of the provided context with the given config.
+func WithContext(ctx context.Context, cfg *Config) context.Context {
+	return context.WithValue(ctx, configKey, cfg)
+}
+
+// FromContextConfig retrieves the config from the context, if present.
+func FromContext(ctx context.Context) (*Config, bool) {
+	cfg, ok := ctx.Value(configKey).(*Config)
+	return cfg, ok
+}

internal/config/init.go 🔗

@@ -6,7 +6,6 @@ import (
 	"path/filepath"
 	"slices"
 	"strings"
-	"sync/atomic"
 )
 
 const (
@@ -17,25 +16,15 @@ type ProjectInitFlag struct {
 	Initialized bool `json:"initialized"`
 }
 
-// TODO: we need to remove the global config instance keeping it now just until everything is migrated
-var instance atomic.Pointer[Config]
-
 func Init(workingDir, dataDir string, debug bool) (*Config, error) {
 	cfg, err := Load(workingDir, dataDir, debug)
 	if err != nil {
 		return nil, err
 	}
-	instance.Store(cfg)
-	return instance.Load(), nil
-}
-
-func Get() *Config {
-	cfg := instance.Load()
-	return cfg
+	return cfg, nil
 }
 
-func ProjectNeedsInitialization() (bool, error) {
-	cfg := Get()
+func ProjectNeedsInitialization(cfg *Config) (bool, error) {
 	if cfg == nil {
 		return false, fmt.Errorf("config not loaded")
 	}
@@ -90,8 +79,7 @@ func contextPathsExist(dir string) (bool, error) {
 	return false, nil
 }
 
-func MarkProjectInitialized() error {
-	cfg := Get()
+func MarkProjectInitialized(cfg *Config) error {
 	if cfg == nil {
 		return fmt.Errorf("config not loaded")
 	}
@@ -106,10 +94,10 @@ func MarkProjectInitialized() error {
 	return nil
 }
 
-func HasInitialDataConfig() bool {
+func HasInitialDataConfig(cfg *Config) bool {
 	cfgPath := GlobalConfigData()
 	if _, err := os.Stat(cfgPath); err != nil {
 		return false
 	}
-	return Get().IsConfigured()
+	return cfg.IsConfigured()
 }

internal/config/load.go 🔗

@@ -18,7 +18,6 @@ import (
 	"github.com/charmbracelet/crush/internal/env"
 	"github.com/charmbracelet/crush/internal/fsext"
 	"github.com/charmbracelet/crush/internal/home"
-	"github.com/charmbracelet/crush/internal/log"
 	powernapConfig "github.com/charmbracelet/x/powernap/pkg/config"
 )
 
@@ -56,12 +55,6 @@ func Load(workingDir, dataDir string, debug bool) (*Config, error) {
 		cfg.Options.Debug = true
 	}
 
-	// Setup logs
-	log.Setup(
-		filepath.Join(cfg.Options.DataDirectory, "logs", fmt.Sprintf("%s.log", appName)),
-		cfg.Options.Debug,
-	)
-
 	// Load known providers, this loads the config from catwalk
 	providers, err := Providers(cfg)
 	if err != nil {
@@ -529,6 +522,10 @@ func lookupConfigs(cwd string) []string {
 		GlobalConfigData(),
 	}
 
+	if cwd == "" {
+		return configPaths
+	}
+
 	configNames := []string{appName + ".json", "." + appName + ".json"}
 
 	foundConfigs, err := fsext.Lookup(cwd, configNames...)