From e2c675ea5aacedf4968dd0042caddd0ea64f360a Mon Sep 17 00:00:00 2001 From: Vladimir Vivien Date: Fri, 8 Nov 2024 07:09:45 -0800 Subject: [PATCH] Examples fix (#58) * Fix build example * Update TODO.md doc * Update module Go version * Fix for flaky Vars/Envs methods tests --- TODO.md | 4 +++- examples/build/main.go | 2 +- functions.go | 4 ++-- go.mod | 2 +- vars/variables.go | 28 +++++++++++++++++----------- vars/variables_test.go | 14 +++++++------- 6 files changed, 31 insertions(+), 23 deletions(-) diff --git a/TODO.md b/TODO.md index 022f44d..fd3014d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,8 +1,10 @@ -# Important tasks +# TODOs The following are high-level tasks that will be considered for upcoming release cycles. +## Top features/tasks * [ ] Support and test on Windows platform (#27) * [ ] Ability to map and access program flags (#20) +* [ ] Support for SSH/SCP * [x] Provide a simple API to submit HTTP requests and retrieve HTTP documents (think of wget/curl) * [x] Support for scatter/gather exec commands * [x] Support for concurrent exec of os commands diff --git a/examples/build/main.go b/examples/build/main.go index 149e6fe..0517557 100644 --- a/examples/build/main.go +++ b/examples/build/main.go @@ -15,7 +15,7 @@ func main() { for _, opsys := range []string{"darwin", "linux"} { gexe.SetVar("arch", arch).SetVar("os", opsys) gexe.SetVar("binpath", fmt.Sprintf("build/%s/%s/mybinary", arch, opsys)) - result := gexe.Envs("CGO_ENABLED=0 GOOS=$os GOARCH=$arch").Run("go build -o $binpath .") + result := gexe.Envs("CGO_ENABLED=0", "GOOS=$os", "GOARCH=$arch").Run("go build -o $binpath .") if result != "" { fmt.Printf("Build for %s/%s failed: %s\n", arch, opsys, result) os.Exit(1) diff --git a/functions.go b/functions.go index 00e0cea..cf1563d 100644 --- a/functions.go +++ b/functions.go @@ -23,8 +23,8 @@ func Variables() *vars.Variables { // // Environment vars can be used in string values // using Eval("building for os=$GOOS") -func Envs(val string) *Echo { - return DefaultEcho.Envs(val) +func Envs(val ...string) *Echo { + return DefaultEcho.Envs(val...) } // SetEnv sets a process environment variable. diff --git a/go.mod b/go.mod index 7cbc01b..b3f7d24 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/vladimirvivien/gexe -go 1.22 +go 1.23 diff --git a/vars/variables.go b/vars/variables.go index db900b6..c42e3e6 100644 --- a/vars/variables.go +++ b/vars/variables.go @@ -12,6 +12,12 @@ var ( varsRegex = regexp.MustCompile(`([A-Za-z0-9_]+)=["']?([^"']*?\$\{[A-Za-z0-9_\.\s]+\}[^"']*?|[^"']*)["']?`) ) +// varmap is used to store parsed variables +type varmap struct { + key string + value string +} + // Variables stores a variable map that used for variable expansion // in parsed commands and other parsed strings. type Variables struct { @@ -48,9 +54,9 @@ func (v *Variables) Envs(variables ...string) *Variables { if len(variables) == 0 { return v } - vars := v.parseVars(variables...) - for key, value := range vars { - v.SetEnv(key, value) + varmaps := v.parseVars(variables...) + for _, parsedVar := range varmaps { + v.SetEnv(parsedVar.key, parsedVar.value) } return v } @@ -76,11 +82,11 @@ func (v *Variables) Vars(variables ...string) *Variables { return v } - vars := v.parseVars(variables...) + varmaps := v.parseVars(variables...) // set variables - for key, value := range vars { - v.SetVar(key, value) + for _, parsedVar := range varmaps { + v.SetVar(parsedVar.key, parsedVar.value) } return v } @@ -120,12 +126,12 @@ func (v *Variables) Eval(str string) string { return v.ExpandVar(str, v.Val) } -// parseVars parses each var line and maps each key to value into map[string]string result. +// parseVars parses each var line and maps each key to value into []varmap result. // This method does not do variable expansion. -func (v *Variables) parseVars(lines ...string) map[string]string { - result := make(map[string]string) +func (v *Variables) parseVars(lines ...string) []varmap { + var result []varmap if len(lines) == 0 { - return result + return []varmap{} } // each line should contain ()=() pair @@ -133,7 +139,7 @@ func (v *Variables) parseVars(lines ...string) map[string]string { for _, line := range lines { matches := varsRegex.FindStringSubmatch(line) if len(matches) >= 3 { - result[matches[1]] = matches[2] + result = append(result, varmap{key: matches[1], value: matches[2]}) } } return result diff --git a/vars/variables_test.go b/vars/variables_test.go index fc3fa19..d454312 100644 --- a/vars/variables_test.go +++ b/vars/variables_test.go @@ -35,7 +35,7 @@ func TestParseVars(t *testing.T) { { name: "unclosed quote error", vars: []string{"foo=bar", "bazz='booz", "dazz=jazz"}, - expectedVars: map[string]string{"foo": "bar", "dazz": "jazz"}, + expectedVars: map[string]string{"foo": "bar", "bazz": "booz", "dazz": "jazz"}, }, { name: "multiple items", @@ -52,10 +52,10 @@ func TestParseVars(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { vars := New() - kvPair := vars.parseVars(test.vars...) - for key, val := range test.expectedVars { - if strings.TrimSpace(kvPair[key]) != strings.TrimSpace(val) { - t.Errorf("unexpected var: %s=%s (want %s=%s)", key, val, key, kvPair[key]) + varmaps := vars.parseVars(test.vars...) + for _, parsedVar := range varmaps { + if strings.TrimSpace(test.expectedVars[parsedVar.key]) != strings.TrimSpace(parsedVar.value) { + t.Errorf("unexpected var: %s=%s (want %s=%s)", parsedVar.key, parsedVar.value, parsedVar.key, test.expectedVars[parsedVar.key]) } } }) @@ -93,7 +93,7 @@ func TestVariables_Vars(t *testing.T) { { name: "unclosed quote error", vars: []string{"foo=bar", "bazz='booz", "dazz=jazz"}, - expectedVars: map[string]string{"foo": "bar", "dazz": "jazz"}, + expectedVars: map[string]string{"foo": "bar", "bazz": "booz", "dazz": "jazz"}, shouldFail: true, }, { @@ -116,7 +116,7 @@ func TestVariables_Vars(t *testing.T) { for key, val := range test.expectedVars { if v, ok := vars.vars[key]; !ok || v != val { - t.Errorf("unexpected var: %s=%s (needs %s=%s)", key, val, key, v) + t.Errorf("unexpected var: %s=%s (want %s=%s)", key, v, key, val) } }