From e5004cd3493e8b1d665e3d68eb3a758db9f1d703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hock=20Isaza?= Date: Sun, 21 Dec 2014 11:27:36 -0500 Subject: [PATCH 1/3] Support multiple environment flags This adds support for multiple environment files via multiple `-e` flags. Closes #13 --- fixtures/envs/.env1 | 1 + fixtures/envs/.env2 | 1 + start.go | 50 +++++++++++++++++++++++++++++++++++++++------ start_test.go | 17 +++++++++++++++ 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 fixtures/envs/.env1 create mode 100644 fixtures/envs/.env2 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/start.go b/start.go index 63ebba3..80021d0 100644 --- a/start.go +++ b/start.go @@ -14,9 +14,21 @@ import ( const shutdownGraceTime = 3 * time.Second +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 +} + var flagPort int var flagConcurrency string var flagRestart bool +var envs envFiles var cmdStart = &Command{ Run: runStart, @@ -35,7 +47,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") @@ -179,20 +191,46 @@ func (f *Forego) startProcess(idx, procNum int, proc ProcfileEntry, env Env, of }() } -func runStart(cmd *Command, args []string) { +func fullPath(file string) string { root := filepath.Dir(flagProcfile) + return filepath.Join(root, file) +} - if flagEnv == "" { - flagEnv = filepath.Join(root, ".env") +func parseEnvironment(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 runStart(cmd *Command, args []string) { pf, err := ReadProcfile(flagProcfile) handleError(err) - env, err := ReadEnv(flagEnv) + concurrency, err := parseConcurrency(flagConcurrency) handleError(err) - concurrency, err := parseConcurrency(flagConcurrency) + env, err := parseEnvironment(envs) handleError(err) of := NewOutletFactory() diff --git a/start_test.go b/start_test.go index 0808dd2..560465b 100644 --- a/start_test.go +++ b/start_test.go @@ -106,3 +106,20 @@ func TestParseConcurrencyFlagNoValue(t *testing.T) { } } + +func TestMultipleEnvironmentFiles(t *testing.T) { + envs := []string{"fixtures/envs/.env1", "fixtures/envs/.env2"} + env, err := parseEnvironment(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") + } +} From 656dbf434d06d2dffdf2abab1592caa5d17a9275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hock=20Isaza?= Date: Mon, 22 Dec 2014 19:30:02 -0500 Subject: [PATCH 2/3] Move loading multiple environments to env.go This way all the env related code is in the same place. --- env.go | 27 +++++++++++++++++++++++++++ env_test.go | 20 ++++++++++++++++++++ start.go | 31 ++----------------------------- start_test.go | 17 ----------------- 4 files changed, 49 insertions(+), 46 deletions(-) create mode 100644 env_test.go diff --git a/env.go b/env.go index c162fd1..6c48af5 100644 --- a/env.go +++ b/env.go @@ -11,6 +11,33 @@ var envEntryRegexp = regexp.MustCompile("^([A-Za-z_0-9]+)=(.*)$") type Env map[string]string +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/start.go b/start.go index 80021d0..224b9d8 100644 --- a/start.go +++ b/start.go @@ -192,37 +192,10 @@ func (f *Forego) startProcess(idx, procNum int, proc ProcfileEntry, env Env, of } func fullPath(file string) string { - root := filepath.Dir(flagProcfile) + root := filepath.Dir(".") return filepath.Join(root, file) } -func parseEnvironment(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 runStart(cmd *Command, args []string) { pf, err := ReadProcfile(flagProcfile) handleError(err) @@ -230,7 +203,7 @@ func runStart(cmd *Command, args []string) { concurrency, err := parseConcurrency(flagConcurrency) handleError(err) - env, err := parseEnvironment(envs) + env, err := loadEnvs(envs) handleError(err) of := NewOutletFactory() diff --git a/start_test.go b/start_test.go index 560465b..0808dd2 100644 --- a/start_test.go +++ b/start_test.go @@ -106,20 +106,3 @@ func TestParseConcurrencyFlagNoValue(t *testing.T) { } } - -func TestMultipleEnvironmentFiles(t *testing.T) { - envs := []string{"fixtures/envs/.env1", "fixtures/envs/.env2"} - env, err := parseEnvironment(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") - } -} From 294ed6c9ec5a9be668f43ff29fee58dce59683f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hock=20Isaza?= Date: Mon, 22 Dec 2014 19:41:47 -0500 Subject: [PATCH 3/3] Support multiple environment files on `forego run` --- env.go | 17 +++++++++++++++++ run.go | 10 ++++------ start.go | 16 ---------------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/env.go b/env.go index 6c48af5..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,22 @@ 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")) 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 224b9d8..b1d7e3b 100644 --- a/start.go +++ b/start.go @@ -14,17 +14,6 @@ import ( const shutdownGraceTime = 3 * time.Second -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 -} - var flagPort int var flagConcurrency string var flagRestart bool @@ -191,11 +180,6 @@ func (f *Forego) startProcess(idx, procNum int, proc ProcfileEntry, env Env, of }() } -func fullPath(file string) string { - root := filepath.Dir(".") - return filepath.Join(root, file) -} - func runStart(cmd *Command, args []string) { pf, err := ReadProcfile(flagProcfile) handleError(err)