1package config
2
3import (
4 "fmt"
5 "os"
6 "path/filepath"
7 "slices"
8 "strings"
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 instance atomic.Pointer[Config]
22
23func Init(workingDir, dataDir string, debug bool) (*Config, error) {
24 cfg, err := Load(workingDir, dataDir, debug)
25 if err != nil {
26 return nil, err
27 }
28 instance.Store(cfg)
29 return instance.Load(), nil
30}
31
32func Get() *Config {
33 cfg := instance.Load()
34 return cfg
35}
36
37func ProjectNeedsInitialization() (bool, error) {
38 cfg := Get()
39 if cfg == nil {
40 return false, fmt.Errorf("config not loaded")
41 }
42
43 flagFilePath := filepath.Join(cfg.Options.DataDirectory, InitFlagFilename)
44
45 _, err := os.Stat(flagFilePath)
46 if err == nil {
47 return false, nil
48 }
49
50 if !os.IsNotExist(err) {
51 return false, fmt.Errorf("failed to check init flag file: %w", err)
52 }
53
54 someContextFileExists, err := contextPathsExist(cfg.WorkingDir())
55 if err != nil {
56 return false, fmt.Errorf("failed to check for context files: %w", err)
57 }
58 if someContextFileExists {
59 return false, nil
60 }
61
62 return true, nil
63}
64
65func contextPathsExist(dir string) (bool, error) {
66 entries, err := os.ReadDir(dir)
67 if err != nil {
68 return false, err
69 }
70
71 // Create a slice of lowercase filenames for lookup with slices.Contains
72 var files []string
73 for _, entry := range entries {
74 if !entry.IsDir() {
75 files = append(files, strings.ToLower(entry.Name()))
76 }
77 }
78
79 // Check if any of the default context paths exist in the directory
80 for _, path := range defaultContextPaths {
81 // Extract just the filename from the path
82 _, filename := filepath.Split(path)
83 filename = strings.ToLower(filename)
84
85 if slices.Contains(files, filename) {
86 return true, nil
87 }
88 }
89
90 return false, nil
91}
92
93func MarkProjectInitialized() error {
94 cfg := Get()
95 if cfg == nil {
96 return fmt.Errorf("config not loaded")
97 }
98 flagFilePath := filepath.Join(cfg.Options.DataDirectory, InitFlagFilename)
99
100 file, err := os.Create(flagFilePath)
101 if err != nil {
102 return fmt.Errorf("failed to create init flag file: %w", err)
103 }
104 defer file.Close()
105
106 return nil
107}
108
109func HasInitialDataConfig() bool {
110 cfgPath := GlobalConfigData()
111 if _, err := os.Stat(cfgPath); err != nil {
112 return false
113 }
114 return Get().IsConfigured()
115}