diff --git a/env.go b/env.go index c162fd1..db0a4d8 100644 --- a/env.go +++ b/env.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/subosito/gotenv" "os" + "path/filepath" "regexp" ) @@ -11,6 +12,49 @@ var envEntryRegexp = regexp.MustCompile("^([A-Za-z_0-9]+)=(.*)$") type Env map[string]string +type envFiles []string + +func (e *envFiles) String() string { + return fmt.Sprintf("%s", *e) +} + +func (e *envFiles) Set(value string) error { + *e = append(*e, fullPath(value)) + return nil +} + +func fullPath(file string) string { + root := filepath.Dir(".") + return filepath.Join(root, file) +} + +func loadEnvs(files []string) (Env, error) { + if len(files) == 0 { + env, err := ReadEnv(fullPath(".env")) + if err != nil { + return nil, err + } else { + return env, nil + } + } + + // Handle multiple environment files + env := make(Env) + for _, file := range files { + tmpEnv, err := ReadEnv(file) + + if err != nil { + return nil, err + } + + // Merge the file I just read into the env. + for k, v := range tmpEnv { + env[k] = v + } + } + return env, nil +} + func ReadEnv(filename string) (Env, error) { if _, err := os.Stat(filename); os.IsNotExist(err) { return make(Env), nil diff --git a/env_test.go b/env_test.go new file mode 100644 index 0000000..b52f44b --- /dev/null +++ b/env_test.go @@ -0,0 +1,20 @@ +package main + +import "testing" + +func TestMultipleEnvironmentFiles(t *testing.T) { + envs := []string{"fixtures/envs/.env1", "fixtures/envs/.env2"} + env, err := loadEnvs(envs) + + if err != nil { + t.Fatalf("Could not read environments: %s", err) + } + + if env["env1"] == "" { + t.Fatalf("$env1 should be present and is not") + } + + if env["env2"] == "" { + t.Fatalf("$env2 should be present and is not") + } +} diff --git a/fixtures/envs/.env1 b/fixtures/envs/.env1 new file mode 100644 index 0000000..7be8251 --- /dev/null +++ b/fixtures/envs/.env1 @@ -0,0 +1 @@ +env1=present diff --git a/fixtures/envs/.env2 b/fixtures/envs/.env2 new file mode 100644 index 0000000..8f6a088 --- /dev/null +++ b/fixtures/envs/.env2 @@ -0,0 +1 @@ +env2=present diff --git a/run.go b/run.go index 230428c..54b23ed 100644 --- a/run.go +++ b/run.go @@ -2,7 +2,6 @@ package main import ( "os" - "path/filepath" "strings" ) @@ -19,8 +18,10 @@ Examples: `, } +var runEnvs envFiles + func init() { - cmdRun.Flag.StringVar(&flagEnv, "e", ".env", "env") + cmdRun.Flag.Var(&runEnvs, "e", "env") } func runRun(cmd *Command, args []string) { @@ -32,11 +33,8 @@ func runRun(cmd *Command, args []string) { if err != nil { handleError(err) } - if flagEnv == "" { - flagEnv = filepath.Join(workDir, ".env") - } - env, err := ReadEnv(flagEnv) + env, err := loadEnvs(runEnvs) handleError(err) const interactive = true diff --git a/start.go b/start.go index 63ebba3..b1d7e3b 100644 --- a/start.go +++ b/start.go @@ -17,6 +17,7 @@ const shutdownGraceTime = 3 * time.Second var flagPort int var flagConcurrency string var flagRestart bool +var envs envFiles var cmdStart = &Command{ Run: runStart, @@ -35,7 +36,7 @@ Examples: func init() { cmdStart.Flag.StringVar(&flagProcfile, "f", "Procfile", "procfile") - cmdStart.Flag.StringVar(&flagEnv, "e", "", "env") + cmdStart.Flag.Var(&envs, "e", "env") cmdStart.Flag.IntVar(&flagPort, "p", 5000, "port") cmdStart.Flag.StringVar(&flagConcurrency, "c", "", "concurrency") cmdStart.Flag.BoolVar(&flagRestart, "r", false, "restart") @@ -180,19 +181,13 @@ func (f *Forego) startProcess(idx, procNum int, proc ProcfileEntry, env Env, of } func runStart(cmd *Command, args []string) { - root := filepath.Dir(flagProcfile) - - if flagEnv == "" { - flagEnv = filepath.Join(root, ".env") - } - pf, err := ReadProcfile(flagProcfile) handleError(err) - env, err := ReadEnv(flagEnv) + concurrency, err := parseConcurrency(flagConcurrency) handleError(err) - concurrency, err := parseConcurrency(flagConcurrency) + env, err := loadEnvs(envs) handleError(err) of := NewOutletFactory()