github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/env/config.go (about) 1 // Copyright 2019 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package env 16 17 import ( 18 "errors" 19 "path/filepath" 20 "strings" 21 22 "github.com/dolthub/dolt/go/libraries/doltcore/dbfactory" 23 24 "github.com/dolthub/dolt/go/libraries/utils/config" 25 "github.com/dolthub/dolt/go/libraries/utils/filesys" 26 "github.com/dolthub/dolt/go/libraries/utils/set" 27 ) 28 29 const ( 30 localConfigName = "local" 31 globalConfigName = "global" 32 33 UserEmailKey = "user.email" 34 UserNameKey = "user.name" 35 36 // should be able to have remote specific creds? 37 UserCreds = "user.creds" 38 39 DoltEditor = "core.editor" 40 41 RemotesApiHostKey = "remotes.default_host" 42 RemotesApiHostPortKey = "remotes.default_port" 43 44 AddCredsUrlKey = "creds.add_url" 45 46 MetricsDisabled = "metrics.disabled" 47 MetricsHost = "metrics.host" 48 MetricsPort = "metrics.port" 49 MetricsInsecure = "metrics.insecure" 50 ) 51 52 var LocalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) 53 var GlobalConfigWhitelist = set.NewStrSet([]string{UserNameKey, UserEmailKey}) 54 55 // DoltConfigElement is an enum representing the elements that make up the ConfigHierarchy 56 type DoltConfigElement int 57 58 const ( 59 // LocalConfig is the repository's local config portion of the ConfigHierarchy 60 LocalConfig DoltConfigElement = iota 61 62 // GlobalConfig is the user's global config portion of the ConfigHierarchy 63 GlobalConfig 64 ) 65 66 // String gives the string name of an element that was used when it was added to the ConfigHierarchy, which is the 67 // same name that is used to retrieve that element of the string hierarchy. 68 func (ce DoltConfigElement) String() string { 69 switch ce { 70 case LocalConfig: 71 return localConfigName 72 case GlobalConfig: 73 return globalConfigName 74 } 75 76 return "" 77 } 78 79 // DoltCliConfig is the config for the cli 80 type DoltCliConfig struct { 81 config.ReadableConfig 82 83 ch *config.ConfigHierarchy 84 fs filesys.ReadWriteFS 85 } 86 87 func loadDoltCliConfig(hdp HomeDirProvider, fs filesys.ReadWriteFS) (*DoltCliConfig, error) { 88 ch := config.NewConfigHierarchy() 89 90 gPath, err := getGlobalCfgPath(hdp) 91 if err != nil { 92 return nil, err 93 } 94 95 lPath := getLocalConfigPath() 96 97 gCfg, err := ensureGlobalConfig(gPath, fs) 98 if err != nil { 99 return nil, err 100 } 101 102 ch.AddConfig(globalConfigName, gCfg) 103 104 if exists, _ := fs.Exists(lPath); exists { 105 lCfg, err := config.FromFile(lPath, fs) 106 107 if err == nil { 108 ch.AddConfig(localConfigName, lCfg) 109 } 110 } 111 112 return &DoltCliConfig{ch, ch, fs}, nil 113 } 114 115 func ensureGlobalConfig(path string, fs filesys.ReadWriteFS) (config.ReadWriteConfig, error) { 116 if exists, isDir := fs.Exists(path); exists { 117 if isDir { 118 return nil, errors.New("A directory exists where this file should be. path: " + path) 119 } 120 121 return config.FromFile(path, fs) 122 } 123 124 return config.NewFileConfig(path, fs, map[string]string{}) 125 } 126 127 // CreateLocalConfig creates a new repository local config file. The current directory must have already been initialized 128 // as a data repository before a local config can be created. 129 func (dcc *DoltCliConfig) CreateLocalConfig(vals map[string]string) error { 130 return dcc.createLocalConfigAt(".", vals) 131 } 132 133 func (dcc *DoltCliConfig) createLocalConfigAt(dir string, vals map[string]string) error { 134 doltDir := filepath.Join(dir, dbfactory.DoltDir) 135 if exists, isDir := dcc.fs.Exists(doltDir); !exists { 136 return errors.New(dbfactory.DoltDir + " directory not found. Is the current directory a repository directory?") 137 } else if !isDir { 138 return errors.New("A file exists with the name \"" + dbfactory.DoltDir + "\". This is not a valid file within a data repository directory.") 139 } 140 141 path := filepath.Join(dir, getLocalConfigPath()) 142 cfg, err := config.NewFileConfig(path, dcc.fs, vals) 143 144 if err != nil { 145 return err 146 } 147 148 dcc.ch.AddConfig(localConfigName, cfg) 149 150 return nil 151 } 152 153 // GetConfig retrieves a specific element of the config hierarchy. 154 func (dcc *DoltCliConfig) GetConfig(element DoltConfigElement) (config.ReadWriteConfig, bool) { 155 return dcc.ch.GetConfig(element.String()) 156 } 157 158 // GetStringOrDefault retrieves a string from the config hierarchy and returns it if available. Otherwise it returns 159 // the default string value 160 func (dcc *DoltCliConfig) GetStringOrDefault(key, defStr string) *string { 161 val, err := dcc.ch.GetString(key) 162 163 if err != nil { 164 return &defStr 165 } 166 167 return &val 168 } 169 170 // IfEmptyUseConfig looks at a strings value and if it is an empty string will try to return a value from the config 171 // hierarchy. If it is missing in the config a pointer to an empty string will be returned. 172 func (dcc *DoltCliConfig) IfEmptyUseConfig(val, key string) string { 173 if len(strings.TrimSpace(val)) > 0 { 174 return val 175 } 176 177 cfgVal, err := dcc.ch.GetString(key) 178 179 if err != nil { 180 s := "" 181 return s 182 } 183 184 return cfgVal 185 }