summary history files

config/config.go
package config

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	// DefaultDirName is the default name used for the config directory.
	DefaultDirName string
	viperConfig    *viper.Viper
)

// Config is the config for the application.
type Config struct {
	// The users Operating System.
	OS string
	// The name of the directory where the configuration file will be
	// stored.
	Dir string
	// The name of the directory which matches the name of the ct binary
	// used to append to the config directory name.
	DefaultDirName  string
	UserViperConfig *viper.Viper
	Persister       Persister
}

// NewConfig returns a Config.
func NewConfig(flags *pflag.FlagSet) (*Config, error) {

	dir := Dir()
	configName := "ct.json"
	configType := "json"

	if configFile, _ := flags.GetString("config-file"); configFile != "" {
		abs, err := filepath.Abs(configFile)
		if err != nil {
			return nil, err
		}
		if fmt.Sprintf("%s", filepath.Ext(abs)) != fmt.Sprintf(".%s", configType) {
			return nil, fmt.Errorf("File extension must be %s, %s", configType, configFile)
		}
		dir = filepath.Dir(abs)
		configName = filepath.Base(abs)
	}

	configFilePath := filepath.Join(dir, configName)
	viperConfig := viper.New()
	viperConfig.AddConfigPath(dir)
	viperConfig.SetConfigName(configName)
	viperConfig.SetConfigFile(configFilePath)
	viperConfig.SetConfigType(configType)
	viperConfig.ReadInConfig()

	return &Config{
		OS:              runtime.GOOS,
		Dir:             dir,
		DefaultDirName:  DefaultDirName,
		Persister:       FilePersister{Dir: dir, ConfigFilePath: configFilePath},
		UserViperConfig: viperConfig,
	}, nil
}

// SetDefaultDirName sets DefaultDirName.
func SetDefaultDirName(binaryName string) {
	binaryNameBase := filepath.Base(binaryName)
	// Rename binaryNameBase to ct when user runs cli via
	// `go run main.go`.
	if binaryNameBase == "main" {
		binaryNameBase = "ct"
	}
	DefaultDirName = strings.Replace(binaryNameBase, ".exe", "", 1)
}

// Dir returns the config dir.
func Dir() string {
	var dir string
	if runtime.GOOS == "windows" {
		dir = os.Getenv("APPDATA")
		if dir != "" {
			return filepath.Join(dir, DefaultDirName)
		}
	}

	dir = os.Getenv("CT_CONFIG_HOME")
	if dir != "" {
		return dir
	}

	dir = os.Getenv("XDG_CONFIG_HOME")
	if dir == "" {
		dir = filepath.Join(os.Getenv("HOME"), ".config")
	}
	if dir != "" {
		return filepath.Join(dir, DefaultDirName)
	}

	dir, _ = os.Getwd()
	return dir
}

// Save saves the config.
func (c Config) Save(basename string) error {
	return c.Persister.Save(c.UserViperConfig, basename)
}