6
0
mirror of https://github.com/grdl/git-get.git synced 2026-02-04 15:39:46 +00:00
Files
git-get/pkg/cfg/config.go
2020-06-19 16:39:26 +02:00

151 lines
4.1 KiB
Go

package cfg
import (
"fmt"
"path"
"strings"
"github.com/go-git/go-git/v5/config"
plumbing "github.com/go-git/go-git/v5/plumbing/format/config"
"github.com/mitchellh/go-homedir"
"github.com/spf13/viper"
)
// GitgetPrefix is the name of the gitconfig section name and the env var prefix.
const GitgetPrefix = "gitget"
// CLI flag keys and their default values.
const (
KeyBranch = "branch"
DefBranch = "master"
KeyDump = "dump"
KeyDefaultHost = "host"
DefDefaultHost = "github.com"
KeyFetch = "fetch"
KeyOutput = "out"
DefOutput = OutTree
KeyPrivateKey = "privateKey"
DefPrivateKey = "id_rsa"
KeyReposRoot = "root"
DefReposRoot = "repositories"
)
// Values for the --out flag.
const (
OutDump = "dump"
OutFlat = "flat"
OutSmart = "smart"
OutTree = "tree"
)
// AllowedOut are allowed values for the --out flag.
var AllowedOut = []string{OutDump, OutFlat, OutSmart, OutTree}
// Version metadata set by ldflags during the build.
var (
version string
commit string
date string
)
// Version returns a string with version metadata: version number, git sha and build date.
// It returns "development" if version variables are not set during the build.
func Version() string {
if version == "" {
return "development"
}
return fmt.Sprintf("%s - revision %s built at %s", version, commit[:6], date)
}
// gitconfig provides methods for looking up configiration values inside .gitconfig file
type gitconfig struct {
*config.Config
}
// Init initializes viper config registry. Values are looked up in the following order: cli flag, env variable, gitconfig file, default value
// Viper doesn't support gitconfig file format so it can't find missing values there automatically. They need to be specified in setMissingValues func.
//
// Because it reads the cli flags it needs to be called after the cmd.Execute().
func Init() {
viper.SetEnvPrefix(strings.ToUpper(GitgetPrefix))
viper.AutomaticEnv()
cfg := loadGitconfig()
setMissingValues(cfg)
}
// loadGitconfig loads configuration from a gitconfig file.
// We ignore errors when gitconfig file can't be found, opened or parsed. In those cases viper will provide default config values.
func loadGitconfig() *gitconfig {
// TODO: load system scope
cfg, _ := config.LoadConfig(config.GlobalScope)
return &gitconfig{
Config: cfg,
}
}
// setMissingValues checks if config values are provided by flags or env vars. If not, it tries loading them from gitconfig file.
// If that fails, the default values are used.
func setMissingValues(cfg *gitconfig) {
if isUnsetOrEmpty(KeyReposRoot) {
viper.Set(KeyReposRoot, cfg.get(KeyReposRoot, path.Join(home(), DefReposRoot)))
}
if isUnsetOrEmpty(KeyDefaultHost) {
viper.Set(KeyDefaultHost, cfg.get(KeyDefaultHost, DefDefaultHost))
}
if isUnsetOrEmpty(KeyPrivateKey) {
viper.Set(KeyPrivateKey, cfg.get(KeyPrivateKey, path.Join(home(), ".ssh", DefPrivateKey)))
}
}
// get looks up the value for a given key in gitconfig file.
// It returns the default value when gitconfig is missing, or it doesn't contain a gitget section,
// or if the section is empty, or if it doesn't contain a valid value for the key.
func (c *gitconfig) get(key string, def string) string {
if c == nil || c.Config == nil {
return def
}
gitget := c.findGitconfigSection(GitgetPrefix)
if gitget == nil {
return def
}
opt := gitget.Option(key)
if strings.TrimSpace(opt) == "" {
return def
}
return opt
}
func (c *gitconfig) findGitconfigSection(name string) *plumbing.Section {
for _, s := range c.Raw.Sections {
if strings.ToLower(s.Name) == strings.ToLower(name) {
return s
}
}
return nil
}
// home returns path to a home directory or empty string if can't be found.
// Using empty string means that in the unlikely situation where home dir can't be found
// and there's no reposRoot specified by any of the config methods, the current dir will be used as repos root.
func home() string {
home, err := homedir.Dir()
if err != nil {
return ""
}
return home
}
func isUnsetOrEmpty(key string) bool {
return !viper.IsSet(key) || strings.TrimSpace(viper.GetString(key)) == ""
}