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