<commit_before>package buildkite

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/oleiade/reflections"
	"os"
	"reflect"
	"strconv"
	"strings"
)

func LoadConfiguration(obj interface{}, c *cli.Context) error {
	configFileMap := map[string]string{}

	var pathToConfigFile string

	// If a config file was passed, load it into a map
	if c.String("config") != "" {
		pathToConfigFile = os.ExpandEnv(c.String("config"))
	} else {
		// If no config was passed, look at the default locations to
		// try and find one that exists
		pathToConfigFile = findDefaultConfiguration()
	}

	// If we need to load from a config file
	if pathToConfigFile != "" {
		loadedConfigFileMap, err := readFile(pathToConfigFile)
		if err != nil {
			return errors.New(fmt.Sprintf("Failed to load config file: %s", err))
		}

		configFileMap = loadedConfigFileMap

		// Store the loaded file in the configuration object
		_ = reflections.SetField(obj, "File", pathToConfigFile)
	}

	// Get all the fields from the configuration interface
	var fields []string
	fields, _ = reflections.Fields(obj)

	for _, name := range fields {
		// Check if the value needs to be loaded from the cli.Context
		cliName, err := reflections.GetFieldTag(obj, name, "cli")
		if err != nil || cliName == "" {
			continue
		}

		// Get the kind of field we need to set
		fieldKind, err := reflections.GetFieldKind(obj, name)
		if err != nil {
			return errors.New(fmt.Sprintf("Failed to get the type of struct field \"%s\"", name))
		}

		var value interface{}

		// Start by defaulting the value to what ever was provided by
		// the CLI, or the ENV
		if fieldKind == reflect.String {
			value = c.String(cliName)
		} else if fieldKind == reflect.Slice {
			value = c.StringSlice(cliName)
		} else if fieldKind == reflect.Bool {
			value = c.Bool(cliName)
		} else {
			return errors.New(fmt.Sprintf("Unable to handle type: %s", fieldKind))
		}

		// Now, override with what ever is in the conf file (if one has
		// been provided)
		if configFileValue, ok := configFileMap[cliName]; ok {
			// Convert the config file value to it's correct type
			if fieldKind == reflect.String {
				value = configFileValue
			} else if fieldKind == reflect.Slice {
				value = strings.Split(configFileValue, ",")
			} else if fieldKind == reflect.Bool {
				value, _ = strconv.ParseBool(configFileValue)
			} else {
				return errors.New(fmt.Sprintf("Unable to convert string to type %s", fieldKind))
			}
		}

		// Set the value if we've found data for it
		if value != nil {
			err = reflections.SetField(obj, name, value)
			if err != nil {
				return errors.New(fmt.Sprintf("Failed to set a value to struct field \"%s\"", name))
			}
		}
	}

	return nil
}

func findDefaultConfiguration() string {
	var paths []string

	if MachineIsWindows() {<commit_msg>Use the config file as a default, and ENV and cli override.<commit_after>package buildkite

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/oleiade/reflections"
	"os"
	"reflect"
	"strconv"
	"strings"
)

func LoadConfiguration(obj interface{}, c *cli.Context) error {
	configFileMap := map[string]string{}

	var pathToConfigFile string

	// If a config file was passed, load it into a map
	if c.String("config") != "" {
		pathToConfigFile = os.ExpandEnv(c.String("config"))
	} else {
		// If no config was passed, look at the default locations to
		// try and find one that exists
		pathToConfigFile = findDefaultConfiguration()
	}

	// If we need to load from a config file
	if pathToConfigFile != "" {
		loadedConfigFileMap, err := readFile(pathToConfigFile)
		if err != nil {
			return errors.New(fmt.Sprintf("Failed to load config file: %s", err))
		}

		configFileMap = loadedConfigFileMap

		// Store the loaded file in the configuration object
		_ = reflections.SetField(obj, "File", pathToConfigFile)
	}

	// Get all the fields from the configuration interface
	var fields []string
	fields, _ = reflections.Fields(obj)

	for _, name := range fields {
		// Check if the value needs to be loaded from the cli.Context
		cliName, err := reflections.GetFieldTag(obj, name, "cli")
		if err != nil || cliName == "" {
			continue
		}

		// Get the kind of field we need to set
		fieldKind, err := reflections.GetFieldKind(obj, name)
		if err != nil {
			return errors.New(fmt.Sprintf("Failed to get the type of struct field \"%s\"", name))
		}

		var value interface{}

		// Start by defaulting the value to what ever was provided by
		// the configuration file
		if configFileValue, ok := configFileMap[cliName]; ok {
			// Convert the config file value to it's correct type
			if fieldKind == reflect.String {
				value = configFileValue
			} else if fieldKind == reflect.Slice {
				value = strings.Split(configFileValue, ",")
			} else if fieldKind == reflect.Bool {
				value, _ = strconv.ParseBool(configFileValue)
			} else {
				return errors.New(fmt.Sprintf("Unable to convert string to type %s", fieldKind))
			}
		}

		// Now, override with what ever is in the cli or the ENV
		if c.IsSet(cliName) {
			if fieldKind == reflect.String {
				value = c.String(cliName)
			} else if fieldKind == reflect.Slice {
				value = c.StringSlice(cliName)
			} else if fieldKind == reflect.Bool {
				value = c.Bool(cliName)
			} else {
				return errors.New(fmt.Sprintf("Unable to handle type: %s", fieldKind))
			}
		}

		// Set the value if we've found data for it
		if value != nil {
			err = reflections.SetField(obj, name, value)
			if err != nil {
				return errors.New(fmt.Sprintf("Failed to set a value to struct field \"%s\"", name))
			}
		}
	}

	return nil
}

func findDefaultConfiguration() string {
	var paths []string

	if MachineIsWindows() {
{'fraction_non_alphanumeric': 0.11416564524601645, 'fraction_numerical': 0.0, 'mean_word_length': 3.3703136954858453, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4196299', 'n_tokens_mistral': 1985, 'n_tokens_neox': 1769, 'n_words': 610}