init.go 2.3 KB

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