package configs import ( "encoding/json" "errors" "fmt" "io" "ocl/portainer-devtool/utils" "os" ) const ( ConfigFileName string = ".devtool" ) var ( ErrConfigNotInitialized error = errors.New("Config file is not initialized") ) type Config struct { // ProjectPath is the location on your host where all dev relevant folders will be stored to ProjectPath string // VolumePath is where all the persisitant data will be stored VolumePath string // Credentials for UI login LoginCredential LoginCredential // key is repository name, for example, "repository-ee" 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") } } // initializeConfig will set up the mandatory dev information for the first time. // such as devtool path, login credential // The configuration also can be updated later func initializeConfig(w io.WriteCloser) (*Config, error) { config := &Config{} config.ProjectPath = utils.Prompt("Specify Git Project Root Path") // analyze all the repositories in the project root path // add the parsed information to RepositoryConfig config.configureRepositories() // generate volume path automatically config.VolumePath = utils.Prompt("Specify Volume Path") config.configureLoginCredential() // 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) }