github.com/getgauge/gauge@v1.6.9/config/properties.go (about) 1 /*---------------------------------------------------------------- 2 * Copyright (c) ThoughtWorks, Inc. 3 * Licensed under the Apache License, Version 2.0 4 * See LICENSE in the project root for license information. 5 *----------------------------------------------------------------*/ 6 7 package config 8 9 import ( 10 "bufio" 11 "fmt" 12 "io" 13 "os" 14 "path/filepath" 15 "sort" 16 "strings" 17 18 "github.com/getgauge/common" 19 "github.com/getgauge/gauge/version" 20 logging "github.com/op/go-logging" 21 ) 22 23 var Log = logging.MustGetLogger("gauge") 24 25 const comment = `This file contains Gauge specific internal configurations. Do not delete` 26 27 type Property struct { 28 Key string `json:"key"` 29 Value string `json:"value"` 30 Description string 31 defaultValue string 32 } 33 34 type properties struct { 35 p map[string]*Property 36 } 37 38 func (p *properties) set(k, v string) error { 39 if _, ok := p.p[k]; ok { 40 p.p[k].Value = v 41 return nil 42 } 43 return fmt.Errorf("config '%s' doesn't exist", k) 44 } 45 46 func (p *properties) get(k string) (string, error) { 47 if _, ok := p.p[k]; ok { 48 return p.p[k].Value, nil 49 } 50 return "", fmt.Errorf("config '%s' doesn't exist", k) 51 } 52 53 func (p *properties) Format(f Formatter) (string, error) { 54 var all []Property 55 for _, v := range p.p { 56 all = append(all, *v) 57 } 58 return f.Format(all) 59 } 60 61 func (p *properties) String() (string, error) { 62 var buffer strings.Builder 63 _, err := buffer.WriteString(fmt.Sprintf("# Version %s\n# %s\n", version.FullVersion(), comment)) 64 if err != nil { 65 return "", err 66 } 67 var keys []string 68 for k := range p.p { 69 keys = append(keys, k) 70 } 71 sort.Strings(keys) 72 for _, k := range keys { 73 v := p.p[k] 74 _, err := buffer.WriteString(fmt.Sprintf("\n# %s\n%s = %s\n", v.Description, v.Key, v.Value)) 75 if err != nil { 76 return "", err 77 } 78 } 79 return buffer.String(), nil 80 } 81 82 func (p *properties) Write(w io.Writer) (int, error) { 83 s, err := p.String() 84 if err != nil { 85 return 0, err 86 } 87 return w.Write([]byte(s)) 88 } 89 90 func defaults() *properties { 91 return &properties{p: map[string]*Property{ 92 allowInsecureDownload: NewProperty(allowInsecureDownload, "false", "Allow Gauge to download template from insecure URLs."), 93 gaugeRepositoryURL: NewProperty(gaugeRepositoryURL, "https://downloads.gauge.org/plugin", "Url to get plugin versions"), 94 runnerConnectionTimeout: NewProperty(runnerConnectionTimeout, "30000", "Timeout in milliseconds for making a connection to the language runner."), 95 pluginConnectionTimeout: NewProperty(pluginConnectionTimeout, "10000", "Timeout in milliseconds for making a connection to plugins."), 96 pluginKillTimeOut: NewProperty(pluginKillTimeOut, "4000", "Timeout in milliseconds for a plugin to stop after a kill message has been sent."), 97 runnerRequestTimeout: NewProperty(runnerRequestTimeout, "30000", "Timeout in milliseconds for requests from the language runner."), 98 ideRequestTimeout: NewProperty(ideRequestTimeout, "30000", "Timeout in milliseconds for requests from runner when invoked for ide."), 99 checkUpdates: NewProperty(checkUpdates, "true", "Allow Gauge and its plugin updates to be notified."), 100 }} 101 } 102 103 func mergedProperties() (*properties, error) { 104 p := defaults() 105 config, err := common.GetGaugeConfigurationFor(common.GaugePropertiesFile) 106 if err != nil { 107 // if unable to get from gauge.properties, just return defaults. 108 return p, nil 109 } 110 for k, v := range config { 111 if _, ok := p.p[k]; ok { 112 err := p.set(k, v) 113 if err != nil { 114 return nil, err 115 } 116 } 117 } 118 return p, nil 119 } 120 121 func Update(name, value string) error { 122 p, err := mergedProperties() 123 if err != nil { 124 return err 125 } 126 err = p.set(name, value) 127 if err != nil { 128 return err 129 } 130 s, err := p.String() 131 if err != nil { 132 return err 133 } 134 return Write(s, common.GaugePropertiesFile) 135 } 136 137 func Merge() error { 138 v, err := GaugeVersionInPropertiesFile(common.GaugePropertiesFile) 139 if err != nil || version.CompareVersions(v, version.CurrentGaugeVersion, version.LesserThanFunc) { 140 mp, err := mergedProperties() 141 if err != nil { 142 return err 143 } 144 s, err := mp.String() 145 if err != nil { 146 return err 147 } 148 return Write(s, common.GaugePropertiesFile) 149 } 150 return nil 151 } 152 153 func GetProperty(name string) (string, error) { 154 mp, err := mergedProperties() 155 if err != nil { 156 return "", err 157 } 158 return mp.get(name) 159 } 160 161 func List(machineReadable bool) (string, error) { 162 var f Formatter 163 f = TextFormatter{Headers: []string{"Key", "Value"}} 164 if machineReadable { 165 f = &JsonFormatter{} 166 } 167 mp, err := mergedProperties() 168 if err != nil { 169 return "", err 170 } 171 return mp.Format(f) 172 } 173 174 func NewProperty(key, defaultValue, description string) *Property { 175 return &Property{ 176 Key: key, 177 defaultValue: defaultValue, 178 Description: description, 179 Value: defaultValue, 180 } 181 } 182 183 func Write(text, file string) error { 184 file, err := FilePath(file) 185 if err != nil { 186 return err 187 } 188 var f *os.File 189 if _, err = os.Stat(file); err != nil { 190 f, err = os.Create(file) 191 if err != nil { 192 return err 193 } 194 } else { 195 f, err = os.OpenFile(file, os.O_WRONLY, os.ModeExclusive) 196 if err != nil { 197 return err 198 } 199 } 200 defer f.Close() 201 _, err = f.Write([]byte(text)) 202 return err 203 } 204 205 func FilePath(name string) (string, error) { 206 dir, err := common.GetConfigurationDir() 207 if err != nil { 208 return "", err 209 } 210 return filepath.Join(dir, name), err 211 } 212 213 func GaugeVersionInPropertiesFile(name string) (*version.Version, error) { 214 var v *version.Version 215 pf, err := FilePath(name) 216 if err != nil { 217 return v, err 218 } 219 f, err := os.Open(pf) 220 if err != nil { 221 return v, err 222 } 223 defer f.Close() 224 r := bufio.NewReader(f) 225 l, _, err := r.ReadLine() 226 if err != nil { 227 return v, err 228 } 229 return version.ParseVersion(strings.TrimPrefix(string(l), "# Version ")) 230 } 231 232 var GetPropertyFromConfig = func(propertyName string) string { 233 config, err := common.GetGaugeConfiguration() 234 if err != nil { 235 APILog.Warningf("Failed to get configuration from Gauge properties file. Error: %s", err.Error()) 236 return "" 237 } 238 return config[propertyName] 239 }