init.go

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