From b7788313e943f95cbf23e75d740cb2a26ac53fef Mon Sep 17 00:00:00 2001
From: Vlad Didenko <git@didenko.com>
Date: Sat, 1 Aug 2015 19:37:27 -0500
Subject: [PATCH] Fixed #73

---
 viper.go      | 20 +++++++-----
 viper_test.go | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 8 deletions(-)

diff --git a/viper.go b/viper.go
index f2c09ce..76a4fe7 100644
--- a/viper.go
+++ b/viper.go
@@ -79,6 +79,16 @@ func (rce RemoteConfigError) Error() string {
 	return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
 }
 
+// Denotes failing to find configuration file.
+type ConfigFileNotFoundError struct {
+	name, locations string
+}
+
+// Returns the formatted configuration error.
+func (fnfe ConfigFileNotFoundError) Error() string {
+	return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
+}
+
 // Viper is a prioritized configuration registry. It
 // maintains a set of configuration sources, fetches
 // values to populate those, and provides them according
@@ -943,6 +953,7 @@ func (v *Viper) searchInPath(in string) (filename string) {
 // search all configPaths for any config file.
 // Returns the first path that exists (and is a config file)
 func (v *Viper) findConfigFile() (string, error) {
+
 	jww.INFO.Println("Searching for config in ", v.configPaths)
 
 	for _, cp := range v.configPaths {
@@ -951,14 +962,7 @@ func (v *Viper) findConfigFile() (string, error) {
 			return file, nil
 		}
 	}
-
-	// try the current working directory
-	wd, _ := os.Getwd()
-	file := v.searchInPath(wd)
-	if file != "" {
-		return file, nil
-	}
-	return "", fmt.Errorf("config file not found in: %s", v.configPaths)
+	return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)}
 }
 
 // Prints all configuration registries for debugging
diff --git a/viper_test.go b/viper_test.go
index 8d7d152..a5f2c52 100644
--- a/viper_test.go
+++ b/viper_test.go
@@ -8,7 +8,10 @@ package viper
 import (
 	"bytes"
 	"fmt"
+	"io/ioutil"
 	"os"
+	"path"
+	"reflect"
 	"sort"
 	"strings"
 	"testing"
@@ -126,6 +129,47 @@ func initTOML() {
 	marshalReader(r, v.config)
 }
 
+// make directories for testing
+func initDirs(t *testing.T) (string, string, func()) {
+
+	var (
+		testDirs = []string{`a a`, `b`, `c\c`, `D_`}
+		config   = `improbable`
+	)
+
+	root, err := ioutil.TempDir("", "")
+
+	cleanup := true
+	defer func() {
+		if cleanup {
+			os.Chdir("..")
+			os.RemoveAll(root)
+		}
+	}()
+
+	assert.Nil(t, err)
+
+	err = os.Chdir(root)
+	assert.Nil(t, err)
+
+	for _, dir := range testDirs {
+		err = os.Mkdir(dir, 0750)
+		assert.Nil(t, err)
+
+		err = ioutil.WriteFile(
+			path.Join(dir, config+".toml"),
+			[]byte("key = \"value is "+dir+"\"\n"),
+			0640)
+		assert.Nil(t, err)
+	}
+
+	cleanup = false
+	return root, config, func() {
+		os.Chdir("..")
+		os.RemoveAll(root)
+	}
+}
+
 //stubs for PFlag Values
 type stringValue string
 
@@ -557,3 +601,45 @@ func TestReadBufConfig(t *testing.T) {
 	assert.Equal(t, map[interface{}]interface{}{"jacket": "leather", "trousers": "denim", "pants": map[interface{}]interface{}{"size": "large"}}, v.Get("clothing"))
 	assert.Equal(t, 35, v.Get("age"))
 }
+
+func TestDirsSearch(t *testing.T) {
+
+	root, config, cleanup := initDirs(t)
+	defer cleanup()
+
+	v := New()
+	v.SetConfigName(config)
+	v.SetDefault(`key`, `default`)
+
+	entries, err := ioutil.ReadDir(root)
+	for _, e := range entries {
+		if e.IsDir() {
+			v.AddConfigPath(e.Name())
+		}
+	}
+
+	err = v.ReadInConfig()
+	assert.Nil(t, err)
+
+	assert.Equal(t, `value is `+path.Base(v.configPaths[0]), v.GetString(`key`))
+}
+
+func TestWrongDirsSearchNotFound(t *testing.T) {
+
+	_, config, cleanup := initDirs(t)
+	defer cleanup()
+
+	v := New()
+	v.SetConfigName(config)
+	v.SetDefault(`key`, `default`)
+
+	v.AddConfigPath(`whattayoutalkingbout`)
+	v.AddConfigPath(`thispathaintthere`)
+
+	err := v.ReadInConfig()
+	assert.Equal(t, reflect.TypeOf(UnsupportedConfigError("")), reflect.TypeOf(err))
+
+	// Even though config did not load and the error might have
+	// been ignored by the client, the default still loads
+	assert.Equal(t, `default`, v.GetString(`key`))
+}