177 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package configs
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"path"
 | 
						|
)
 | 
						|
 | 
						|
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{}
 | 
						|
	fmt.Printf("Initialize devtool path:\n (Project path will store volumes and repositories)")
 | 
						|
	fmt.Scanf("%s", &(config.ProjectPath))
 | 
						|
 | 
						|
	// generate volume path automatically
 | 
						|
	config.VolumePath = path.Join(config.ProjectPath, "volumes")
 | 
						|
 | 
						|
	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)
 | 
						|
}
 |