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