init.go

  1package config
  2
  3import (
  4	"fmt"
  5	"log/slog"
  6	"os"
  7	"path/filepath"
  8	"strings"
  9	"sync"
 10	"sync/atomic"
 11)
 12
 13const (
 14	InitFlagFilename = "init"
 15)
 16
 17type ProjectInitFlag struct {
 18	Initialized bool `json:"initialized"`
 19}
 20
 21// TODO: we need to remove the global config instance keeping it now just until everything is migrated
 22var (
 23	instance atomic.Pointer[Config]
 24	cwd      string
 25	once     sync.Once // Ensures the initialization happens only once
 26)
 27
 28func Init(workingDir string, debug bool) (*Config, error) {
 29	var err error
 30	once.Do(func() {
 31		cwd = workingDir
 32		cfg, err := Load(cwd, debug)
 33		if err != nil {
 34			slog.Error("Failed to load config", "error", err)
 35		}
 36		instance.Store(cfg)
 37	})
 38
 39	return instance.Load(), err
 40}
 41
 42func Get() *Config {
 43	return instance.Load()
 44}
 45
 46func ProjectNeedsInitialization() (bool, error) {
 47	cfg := Get()
 48	if cfg == nil {
 49		return false, fmt.Errorf("config not loaded")
 50	}
 51
 52	flagFilePath := filepath.Join(cfg.Options.DataDirectory, InitFlagFilename)
 53
 54	_, err := os.Stat(flagFilePath)
 55	if err == nil {
 56		return false, nil
 57	}
 58
 59	if !os.IsNotExist(err) {
 60		return false, fmt.Errorf("failed to check init flag file: %w", err)
 61	}
 62
 63	crushExists, err := crushMdExists(cfg.WorkingDir())
 64	if err != nil {
 65		return false, fmt.Errorf("failed to check for CRUSH.md files: %w", err)
 66	}
 67	if crushExists {
 68		return false, nil
 69	}
 70
 71	return true, nil
 72}
 73
 74func crushMdExists(dir string) (bool, error) {
 75	entries, err := os.ReadDir(dir)
 76	if err != nil {
 77		return false, err
 78	}
 79
 80	for _, entry := range entries {
 81		if entry.IsDir() {
 82			continue
 83		}
 84
 85		name := strings.ToLower(entry.Name())
 86		if name == "crush.md" {
 87			return true, nil
 88		}
 89	}
 90
 91	return false, nil
 92}
 93
 94func MarkProjectInitialized() error {
 95	cfg := Get()
 96	if cfg == nil {
 97		return fmt.Errorf("config not loaded")
 98	}
 99	flagFilePath := filepath.Join(cfg.Options.DataDirectory, InitFlagFilename)
100
101	file, err := os.Create(flagFilePath)
102	if err != nil {
103		return fmt.Errorf("failed to create init flag file: %w", err)
104	}
105	defer file.Close()
106
107	return nil
108}