1717package cli
1818
1919import (
20+ "bytes"
2021 "fmt"
2122 "io"
2223 "os"
@@ -39,7 +40,7 @@ type ProjectOptions struct {
3940 WorkingDir string
4041 ConfigPaths []string
4142 Environment map [string ]string
42- EnvFile string
43+ EnvFiles [] string
4344 loadOptions []func (* loader.Options )
4445}
4546
@@ -187,9 +188,15 @@ func WithOsEnv(o *ProjectOptions) error {
187188}
188189
189190// WithEnvFile set an alternate env file
191+ // deprecated - use WithEnvFiles
190192func WithEnvFile (file string ) ProjectOptionsFn {
193+ return WithEnvFiles (file )
194+ }
195+
196+ // WithEnvFiles set alternate env files
197+ func WithEnvFiles (file ... string ) ProjectOptionsFn {
191198 return func (options * ProjectOptions ) error {
192- options .EnvFile = file
199+ options .EnvFiles = file
193200 return nil
194201 }
195202}
@@ -200,7 +207,7 @@ func WithDotEnv(o *ProjectOptions) error {
200207 if err != nil {
201208 return err
202209 }
203- envMap , err := GetEnvFromFile (o .Environment , wd , o .EnvFile )
210+ envMap , err := GetEnvFromFile (o .Environment , wd , o .EnvFiles )
204211 if err != nil {
205212 return err
206213 }
@@ -213,55 +220,48 @@ func WithDotEnv(o *ProjectOptions) error {
213220 return nil
214221}
215222
216- func GetEnvFromFile (currentEnv map [string ]string , workingDir string , filename string ) (map [string ]string , error ) {
223+ func GetEnvFromFile (currentEnv map [string ]string , workingDir string , filenames [] string ) (map [string ]string , error ) {
217224 envMap := make (map [string ]string )
218225
219- dotEnvFile := filename
220- if dotEnvFile == "" {
221- dotEnvFile = filepath .Join (workingDir , ".env" )
222- }
223- abs , err := filepath .Abs (dotEnvFile )
224- if err != nil {
225- return envMap , err
226+ dotEnvFiles := filenames
227+ if len (dotEnvFiles ) == 0 {
228+ dotEnvFiles = append (dotEnvFiles , filepath .Join (workingDir , ".env" ))
226229 }
227- dotEnvFile = abs
228-
229- s , err := os .Stat (dotEnvFile )
230- if os .IsNotExist (err ) {
231- if filename != "" {
232- return nil , errors .Errorf ("Couldn't find env file: %s" , filename )
230+ for _ , dotEnvFile := range dotEnvFiles {
231+ abs , err := filepath .Abs (dotEnvFile )
232+ if err != nil {
233+ return envMap , err
233234 }
234- return envMap , nil
235- }
236- if err != nil {
237- return envMap , err
238- }
235+ dotEnvFile = abs
239236
240- if s .IsDir () {
241- if filename == "" {
237+ b , err := os .ReadFile (dotEnvFile )
238+ if os .IsNotExist (err ) {
239+ if len (filenames ) > 0 {
240+ return nil , errors .Errorf ("Couldn't read env file: %s" , dotEnvFile )
241+ }
242242 return envMap , nil
243243 }
244- return envMap , errors .Errorf ("%s is a directory" , dotEnvFile )
245- }
246-
247- file , err := os .Open (dotEnvFile )
248- if err != nil {
249- return envMap , errors .Wrapf (err , "failed to read %s" , dotEnvFile )
250- }
251- defer file .Close ()
244+ if err != nil {
245+ return envMap , err
246+ }
252247
253- env , err := dotenv .ParseWithLookup (file , func (k string ) (string , bool ) {
254- v , ok := currentEnv [k ]
255- if ! ok {
256- return "" , false
248+ env , err := dotenv .ParseWithLookup (bytes .NewReader (b ), func (k string ) (string , bool ) {
249+ v , ok := envMap [k ]
250+ if ok {
251+ return v , true
252+ }
253+ v , ok = currentEnv [k ]
254+ if ! ok {
255+ return "" , false
256+ }
257+ return v , true
258+ })
259+ if err != nil {
260+ return envMap , errors .Wrapf (err , "failed to read %s" , dotEnvFile )
261+ }
262+ for k , v := range env {
263+ envMap [k ] = v
257264 }
258- return v , true
259- })
260- if err != nil {
261- return envMap , errors .Wrapf (err , "failed to read %s" , dotEnvFile )
262- }
263- for k , v := range env {
264- envMap [k ] = v
265265 }
266266
267267 return envMap , nil
0 commit comments