package configs import ( "encoding/json" "errors" "fmt" "io" "os" ) const ( ConfigFileName string = ".devtool" ) var ( ErrConfigNotInitialized error = errors.New("Config file is not initialized") ) type Config struct { // ProjectPath is where all git repositories will be downloaded to ProjectPath string // VolumePath is where all the persisitant data will be saved to VolumePath string // LoginCredential LoginCredential // RepositoryConfig map[string]RepositoryConfig } // LoginCredential stores the user credential for API request type LoginCredential struct { Username string Password string Address string } type RepositoryConfig struct { Name string URL string Directory string Private bool GitUsername string GitPassword string } func GetConfig() (*Config, error) { file, err := getConfigFile(ConfigFileName) if err != nil { if err == ErrConfigNotInitialized { return initializeConfig(file) } return nil, err } defer file.Close() return getConfig(file) } func (config *Config) Summarize() { fmt.Printf("The project path is %s\nThe volume path is %s\n", config.ProjectPath, config.VolumePath) if config.LoginCredential.Username != "" && config.LoginCredential.Password != "" { fmt.Printf("Login credential [%s] is configured\n", config.LoginCredential.Username) } if len(config.RepositoryConfig) > 0 { for name := range config.RepositoryConfig { fmt.Printf("Repository [%s] is added\n", name) } } else { fmt.Println("No repository is added") } } func initializeConfig(w io.WriteCloser) (*Config, error) { config := &Config{} fmt.Printf("Set the project path: ") fmt.Scanf("%s", &(config.ProjectPath)) fmt.Printf("Set the volume path: ") fmt.Scanf("%s", &(config.VolumePath)) var loginCredential LoginCredential fmt.Printf("Set login credential username(admin): ") fmt.Scanf("%s", &(loginCredential.Username)) if loginCredential.Username == "" { loginCredential.Username = "admin" } for { fmt.Printf("Set login credential password(******): ") fmt.Scanf("%s", &(loginCredential.Password)) if loginCredential.Password != "" { break } fmt.Println("Login credential password must be provided") } fmt.Printf("Set login address(127.0.0.1): ") fmt.Scanf("%s", &(loginCredential.Address)) if loginCredential.Address == "" { loginCredential.Address = "http://127.0.0.1:9000/api/auth" } else { loginCredential.Address = fmt.Sprintf("http://%s:9000/api/auth", loginCredential.Address) } config.LoginCredential = loginCredential // able to configure multiple project // if utils.PromptConfirm("Do you want to configure the repository now?") { // // configure repository // } bytes, err := json.Marshal(config) if err != nil { return nil, err } _, err = w.Write(bytes) if err != nil { return nil, err } return config, nil } func getConfig(f *os.File) (*Config, error) { config := &Config{} info, err := f.Stat() if err != nil { return nil, err } bytes := make([]byte, info.Size()) n, err := f.Read(bytes) if err != nil { return nil, err } if n == 0 { // The file exists, but it's empty file, so we need to initalize return initializeConfig(f) } err = json.Unmarshal(bytes, &config) if err != nil { return nil, err } return config, nil } // getConfigFile get the config file handler func getConfigFile(name string) (*os.File, error) { _, err := os.Stat(name) if err != nil { if errors.Is(err, os.ErrNotExist) { //create file file, err := os.Create(name) if err != nil { return nil, fmt.Errorf("fail to create config file: %w", err) } // first set up the git project path and volume path // git credential return file, err } else { return nil, err } } return os.OpenFile(name, os.O_RDWR, 0644) }