@@ -18,8 +18,10 @@ import (
18
18
"errors"
19
19
"fmt"
20
20
"io"
21
+ "io/ioutil"
21
22
"os"
22
23
"os/exec"
24
+ "path/filepath"
23
25
"regexp"
24
26
"sort"
25
27
"strconv"
@@ -28,6 +30,14 @@ import (
28
30
29
31
const doubleQuoteSpecialChars = "\\ \n \r \" !$`"
30
32
33
+ func stringSet (s []string ) map [string ]interface {} {
34
+ m := make (map [string ]interface {})
35
+ for _ , str := range s {
36
+ m [str ] = true
37
+ }
38
+ return m
39
+ }
40
+
31
41
// Load will read your env file(s) and load them into ENV for this process.
32
42
//
33
43
// Call this function as close as possible to the start of your program (ideally in main)
@@ -42,7 +52,46 @@ const doubleQuoteSpecialChars = "\\\n\r\"!$`"
42
52
func Load (filenames ... string ) (err error ) {
43
53
filenames = filenamesOrDefault (filenames )
44
54
45
- for _ , filename := range filenames {
55
+ filenamesMap := stringSet (filenames )
56
+
57
+ // We start in the current working directory and look up until we find all
58
+ // of our files or hit the root path.
59
+ currentDirectory , err := os .Getwd ()
60
+ if err != nil {
61
+ return err
62
+ }
63
+
64
+ filePaths := make ([]string , 0 )
65
+ for {
66
+ files , err := ioutil .ReadDir (currentDirectory )
67
+ if err != nil {
68
+ return err
69
+ }
70
+
71
+ // Check if any of our desired files are in the current directory.
72
+ for _ , directoryFile := range files {
73
+ for filename := range filenamesMap {
74
+ if filename == directoryFile .Name () {
75
+ filePaths = append (filePaths , currentDirectory + "/" + directoryFile .Name ())
76
+ delete (filenamesMap , directoryFile .Name ())
77
+ }
78
+
79
+ }
80
+ }
81
+ // We've found all of our files.
82
+ if len (filenamesMap ) == 0 {
83
+ break
84
+ }
85
+ parent := filepath .Dir (currentDirectory )
86
+
87
+ // We've hit the file system root.
88
+ if parent == currentDirectory {
89
+ break
90
+ }
91
+ currentDirectory = parent
92
+ }
93
+
94
+ for _ , filename := range filePaths {
46
95
err = loadFile (filename , false )
47
96
if err != nil {
48
97
return // return early on a spazout
@@ -187,8 +236,8 @@ func filenamesOrDefault(filenames []string) []string {
187
236
return filenames
188
237
}
189
238
190
- func loadFile (filename string , overload bool ) error {
191
- envMap , err := readFile (filename )
239
+ func loadFile (filePath string , overload bool ) error {
240
+ envMap , err := readFile (filePath )
192
241
if err != nil {
193
242
return err
194
243
}
@@ -209,8 +258,8 @@ func loadFile(filename string, overload bool) error {
209
258
return nil
210
259
}
211
260
212
- func readFile (filename string ) (envMap map [string ]string , err error ) {
213
- file , err := os .Open (filename )
261
+ func readFile (filePath string ) (envMap map [string ]string , err error ) {
262
+ file , err := os .Open (filePath )
214
263
if err != nil {
215
264
return
216
265
}
0 commit comments