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  }