Files
dolt/go/libraries/doltcore/env/config.go
T
Maximilian Hoffman 8a5f3f54be config, clone, backups refactor (#2196)
* shittiest read replica imaginable is kind of working

* import cycle progress

* delete unecessary files and fix  db type switch bug

* Add bats test

* delete comments

* fix working set updates for cli

* [ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh

* clean comments

* comment racy server test

* move env variables to local dolt config

* refactor clone, fix multienv test

* cleanup comments

* missing copyright

* brian's comments, add compile time checks for config interfaces

* format

* fix windows filepaths issue

* file:/// with three slashes should work on windows

* more windows problems

* three slashes didn't work for clone, do chdir to ref local dolt db

Co-authored-by: max-hoffman <max-hoffman@users.noreply.github.com>
2021-09-29 19:10:37 -07:00

215 lines
5.9 KiB
Go

// Copyright 2019 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package env
import (
"errors"
"path/filepath"
"strings"
"github.com/dolthub/dolt/go/libraries/doltcore/dbfactory"
"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
"github.com/dolthub/dolt/go/libraries/utils/config"
"github.com/dolthub/dolt/go/libraries/utils/filesys"
"github.com/dolthub/dolt/go/libraries/utils/set"
)
const (
localConfigName = "local"
globalConfigName = "global"
UserEmailKey = "user.email"
UserNameKey = "user.name"
// should be able to have remote specific creds?
UserCreds = "user.creds"
DoltEditor = "core.editor"
InitBranchName = "init.defaultbranch"
RemotesApiHostKey = "remotes.default_host"
RemotesApiHostPortKey = "remotes.default_port"
AddCredsUrlKey = "creds.add_url"
MetricsDisabled = "metrics.disabled"
MetricsHost = "metrics.host"
MetricsPort = "metrics.port"
MetricsInsecure = "metrics.insecure"
)
var LocalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey})
var GlobalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey})
// DoltConfigElement is an enum representing the elements that make up the ConfigHierarchy
type DoltConfigElement int
const (
// LocalConfig is the repository's local config portion of the ConfigHierarchy
LocalConfig DoltConfigElement = iota
// GlobalConfig is the user's global config portion of the ConfigHierarchy
GlobalConfig
)
// String gives the string name of an element that was used when it was added to the ConfigHierarchy, which is the
// same name that is used to retrieve that element of the string hierarchy.
func (ce DoltConfigElement) String() string {
switch ce {
case LocalConfig:
return localConfigName
case GlobalConfig:
return globalConfigName
}
return ""
}
// DoltCliConfig is the config for the cli
type DoltCliConfig struct {
config.ReadableConfig
ch *config.ConfigHierarchy
fs filesys.ReadWriteFS
}
var _ config.ReadableConfig = &DoltCliConfig{}
func loadDoltCliConfig(hdp HomeDirProvider, fs filesys.ReadWriteFS) (*DoltCliConfig, error) {
ch := config.NewConfigHierarchy()
gPath, err := getGlobalCfgPath(hdp)
if err != nil {
return nil, err
}
lPath := getLocalConfigPath()
gCfg, err := ensureGlobalConfig(gPath, fs)
if err != nil {
return nil, err
}
ch.AddConfig(globalConfigName, gCfg)
if exists, _ := fs.Exists(lPath); exists {
lCfg, err := config.FromFile(lPath, fs)
if err == nil {
ch.AddConfig(localConfigName, lCfg)
}
}
return &DoltCliConfig{ch, ch, fs}, nil
}
func ensureGlobalConfig(path string, fs filesys.ReadWriteFS) (config.ReadWriteConfig, error) {
if exists, isDir := fs.Exists(path); exists {
if isDir {
return nil, errors.New("A directory exists where this file should be. path: " + path)
}
return config.FromFile(path, fs)
}
return config.NewFileConfig(path, fs, map[string]string{})
}
// CreateLocalConfig creates a new repository local config file. The current directory must have already been initialized
// as a data repository before a local config can be created.
func (dcc *DoltCliConfig) CreateLocalConfig(vals map[string]string) error {
return dcc.createLocalConfigAt(".", vals)
}
func (dcc *DoltCliConfig) createLocalConfigAt(dir string, vals map[string]string) error {
doltDir := filepath.Join(dir, dbfactory.DoltDir)
if exists, isDir := dcc.fs.Exists(doltDir); !exists {
return errors.New(dbfactory.DoltDir + " directory not found. Is the current directory a repository directory?")
} else if !isDir {
return errors.New("A file exists with the name \"" + dbfactory.DoltDir + "\". This is not a valid file within a data repository directory.")
}
path := filepath.Join(dir, getLocalConfigPath())
cfg, err := config.NewFileConfig(path, dcc.fs, vals)
if err != nil {
return err
}
dcc.ch.AddConfig(localConfigName, cfg)
return nil
}
// GetConfig retrieves a specific element of the config hierarchy.
func (dcc *DoltCliConfig) GetConfig(element DoltConfigElement) (config.ReadWriteConfig, bool) {
return dcc.ch.GetConfig(element.String())
}
// GetStringOrDefault retrieves a string from the config hierarchy and returns it if available. Otherwise it returns
// the default string value
func (dcc *DoltCliConfig) GetStringOrDefault(key, defStr string) string {
return GetStringOrDefault(dcc.ch, key, defStr)
}
// IfEmptyUseConfig looks at a strings value and if it is an empty string will try to return a value from the config
// hierarchy. If it is missing in the config a pointer to an empty string will be returned.
func (dcc *DoltCliConfig) IfEmptyUseConfig(val, key string) string {
if len(strings.TrimSpace(val)) > 0 {
return val
}
cfgVal, err := dcc.ch.GetString(key)
if err != nil {
s := ""
return s
}
return cfgVal
}
func GetStringOrDefault(cfg config.ReadableConfig, key, defStr string) string {
val, err := cfg.GetString(key)
if err != nil {
return defStr
}
return val
}
// GetNameAndEmail returns the name and email from the supplied config
func GetNameAndEmail(cfg config.ReadableConfig) (string, string, error) {
name, err := cfg.GetString(UserNameKey)
if err == config.ErrConfigParamNotFound {
return "", "", doltdb.ErrNameNotConfigured
} else if err != nil {
return "", "", err
}
email, err := cfg.GetString(UserEmailKey)
if err == config.ErrConfigParamNotFound {
return "", "", doltdb.ErrEmailNotConfigured
} else if err != nil {
return "", "", err
}
return name, email, nil
}