github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/cli/settings.go (about) 1 package cli 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "runtime" 11 "strings" 12 13 "github.com/evergreen-ci/evergreen/model" 14 "github.com/evergreen-ci/evergreen/util" 15 "github.com/kardianos/osext" 16 homedir "github.com/mitchellh/go-homedir" 17 "github.com/pkg/errors" 18 "gopkg.in/yaml.v2" 19 ) 20 21 // prompt writes a prompt to the user on stdout, reads a newline-terminated response from stdin, 22 // and returns the result as a string. 23 func prompt(message string) string { 24 reader := bufio.NewReader(os.Stdin) 25 fmt.Print(message + " ") 26 text, _ := reader.ReadString('\n') 27 return strings.TrimSpace(text) 28 } 29 30 // confirm asks the user a yes/no question and returns true/false if they reply with y/yes/n/no. 31 // if defaultYes is true, allows user to just hit enter without typing an explicit yes. 32 func confirm(message string, defaultYes bool) bool { 33 var reply string 34 35 yes := []string{"y", "yes"} 36 no := []string{"n", "no"} 37 38 if defaultYes { 39 yes = append(yes, "") 40 } 41 42 for { 43 reply = prompt(message) 44 if util.SliceContains(yes, strings.ToLower(reply)) { 45 return true 46 } 47 if util.SliceContains(no, strings.ToLower(reply)) { 48 return false 49 } 50 } 51 } 52 53 // LoadSettings attempts to load the settings file 54 func LoadSettings(opts *Options) (*model.CLISettings, error) { 55 confPath := opts.ConfFile 56 if confPath == "" { 57 userHome, err := homedir.Dir() 58 if err != nil { 59 // workaround for cygwin if we're on windows but couldn't get a homedir 60 if runtime.GOOS == "windows" && len(os.Getenv("HOME")) > 0 { 61 userHome = os.Getenv("HOME") 62 } else { 63 return nil, err 64 } 65 } 66 confPath = filepath.Join(userHome, ".evergreen.yml") 67 } 68 var f io.ReadCloser 69 var err, extErr, extOpenErr error 70 f, err = os.Open(confPath) 71 if err != nil { 72 // if we can't find the yml file in the home directory, 73 // try to find it in the same directory as where the binary is being run from. 74 // If we fail to determine that location, just return the first (outer) error. 75 var currentBinPath string 76 currentBinPath, extErr = osext.Executable() 77 if extErr != nil { 78 return nil, err 79 } 80 f, extOpenErr = os.Open(filepath.Join(filepath.Dir(currentBinPath), ".evergreen.yml")) 81 if extOpenErr != nil { 82 return nil, err 83 } 84 } 85 86 settings := &model.CLISettings{} 87 err = util.ReadYAMLInto(f, settings) 88 if err != nil { 89 return nil, err 90 } 91 settings.LoadedFrom = confPath 92 return settings, nil 93 } 94 95 type Options struct { 96 ConfFile string `short:"c" long:"config" description:"path to config file (defaults to ~/.evergreen.yml)"` 97 } 98 99 func WriteSettings(s *model.CLISettings, opts *Options) error { 100 confPath := opts.ConfFile 101 if confPath == "" { 102 if s.LoadedFrom != "" { 103 confPath = s.LoadedFrom 104 } 105 } 106 if confPath == "" { 107 return errors.New("can't determine output location for settings file") 108 } 109 yamlData, err := yaml.Marshal(s) 110 if err != nil { 111 return err 112 } 113 return ioutil.WriteFile(confPath, yamlData, 0644) 114 }