From 87b324ad723711b52f4d66fc29cd366aa5fdfbdb Mon Sep 17 00:00:00 2001 From: Silke Hofstra Date: Mon, 14 Aug 2023 11:13:16 +0200 Subject: [PATCH 1/4] Fix running in Go workspace When working with Go workspaces, `go list -m -json` will return multiple objects. For example: ```json { "Path": "golang.org/x/example/hello", "Main": true, "Dir": "/build/example/hello", "GoMod": "/build/example/hello/go.mod", "GoVersion": "1.19" } { "Path": "example.com/hello", "Main": true, "Dir": "/build/hello", "GoMod": "/build/hello/go.mod", "GoVersion": "1.21" } ``` Ensure that the JSON decoding can handle this output by stream-decoding the JSON and returning the first suitable module. --- testdata/src/go.work | 7 +++++++ utils.go | 24 ++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 testdata/src/go.work diff --git a/testdata/src/go.work b/testdata/src/go.work new file mode 100644 index 0000000..5595c7c --- /dev/null +++ b/testdata/src/go.work @@ -0,0 +1,7 @@ +go 1.18 + +use ( + ./builtins + ./custom + ./tests +) diff --git a/utils.go b/utils.go index 09b51a1..e12ebcd 100644 --- a/utils.go +++ b/utils.go @@ -1,8 +1,12 @@ package musttag import ( + "bytes" "encoding/json" + "errors" "fmt" + "io" + "os" "os/exec" "strings" ) @@ -22,9 +26,21 @@ func getMainModule() (string, error) { GoMod string `json:"GoMod"` GoVersion string `json:"GoVersion"` } - if err := json.Unmarshal(data, &module); err != nil { - return "", fmt.Errorf("decoding json: %w: %s", err, string(data)) - } - return module.Path, nil + cwd, _ := os.Getwd() + decoder := json.NewDecoder(bytes.NewBuffer(data)) + + for { + if err := decoder.Decode(&module); err != nil { + if errors.Is(err, io.EOF) { + return "", fmt.Errorf("no main module in: %s", string(data)) + } + + return "", fmt.Errorf("decoding json: %w: %s", err, string(data)) + } + + if module.Main && strings.HasPrefix(cwd, module.Dir) { + return module.Path, nil + } + } } From 6e7a680087185835a87c6e03b19d0c5fcd792e47 Mon Sep 17 00:00:00 2001 From: Tom <73077675+tmzane@users.noreply.github.com> Date: Wed, 16 Aug 2023 19:08:49 +0300 Subject: [PATCH 2/4] add tests --- utils.go | 37 ++++++++++++++++++++++--------------- utils_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 utils_test.go diff --git a/utils.go b/utils.go index e12ebcd..aa63723 100644 --- a/utils.go +++ b/utils.go @@ -1,7 +1,6 @@ package musttag import ( - "bytes" "encoding/json" "errors" "fmt" @@ -11,32 +10,40 @@ import ( "strings" ) +var ( + getwd = os.Getwd + + commandOutput = func(name string, args ...string) (string, error) { + output, err := exec.Command(name, args...).Output() + return string(output), err + } +) + func getMainModule() (string, error) { args := []string{"go", "list", "-m", "-json"} - data, err := exec.Command(args[0], args[1:]...).Output() + output, err := commandOutput(args[0], args[1:]...) if err != nil { return "", fmt.Errorf("running `%s`: %w", strings.Join(args, " "), err) } - var module struct { - Path string `json:"Path"` - Main bool `json:"Main"` - Dir string `json:"Dir"` - GoMod string `json:"GoMod"` - GoVersion string `json:"GoVersion"` - } - - cwd, _ := os.Getwd() - decoder := json.NewDecoder(bytes.NewBuffer(data)) + cwd, _ := getwd() + decoder := json.NewDecoder(strings.NewReader(output)) for { + // multiple JSON objects will be returned when using Go workspaces; see #63 for details. + var module struct { + Path string `json:"Path"` + Main bool `json:"Main"` + Dir string `json:"Dir"` + GoMod string `json:"GoMod"` + GoVersion string `json:"GoVersion"` + } if err := decoder.Decode(&module); err != nil { if errors.Is(err, io.EOF) { - return "", fmt.Errorf("no main module in: %s", string(data)) + return "", fmt.Errorf("main module not found\n%s", output) } - - return "", fmt.Errorf("decoding json: %w: %s", err, string(data)) + return "", fmt.Errorf("decoding json: %w\n%s", err, output) } if module.Main && strings.HasPrefix(cwd, module.Dir) { diff --git a/utils_test.go b/utils_test.go new file mode 100644 index 0000000..26eb643 --- /dev/null +++ b/utils_test.go @@ -0,0 +1,45 @@ +package musttag + +import ( + "testing" + + "go-simpler.org/assert" + . "go-simpler.org/assert/dotimport" +) + +func Test_getMainModule(t *testing.T) { + test := func(name, want, output string) { + t.Helper() + t.Run(name, func(t *testing.T) { + t.Helper() + getwd = func() (string, error) { + return "/path/to/module1/pkg", nil + } + commandOutput = func(name string, args ...string) (string, error) { + return output, nil + } + got, err := getMainModule() + assert.NoErr[F](t, err) + assert.Equal[E](t, got, want) + }) + } + + test("single module", "module1", ` +{ + "Path": "module1", + "Main": true, + "Dir": "/path/to/module1" +}`) + + test("multiple modules", "module1", ` +{ + "Path": "module1", + "Main": true, + "Dir": "/path/to/module1" +} +{ + "Path": "module2", + "Main": true, + "Dir": "/path/to/module2" +}`) +} From 00b6eed67e103f4dc911af951d0cc356516a6211 Mon Sep 17 00:00:00 2001 From: Tom <73077675+tmzane@users.noreply.github.com> Date: Wed, 16 Aug 2023 19:23:38 +0300 Subject: [PATCH 3/4] fix tests --- utils_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/utils_test.go b/utils_test.go index 26eb643..aa80671 100644 --- a/utils_test.go +++ b/utils_test.go @@ -12,12 +12,21 @@ func Test_getMainModule(t *testing.T) { t.Helper() t.Run(name, func(t *testing.T) { t.Helper() + + gwd := getwd + co := commandOutput + defer func() { + getwd = gwd + commandOutput = co + }() + getwd = func() (string, error) { return "/path/to/module1/pkg", nil } commandOutput = func(name string, args ...string) (string, error) { return output, nil } + got, err := getMainModule() assert.NoErr[F](t, err) assert.Equal[E](t, got, want) From db5b16ce756e1efde2f66499a226bffae4fbf645 Mon Sep 17 00:00:00 2001 From: Tom <73077675+tmzane@users.noreply.github.com> Date: Wed, 16 Aug 2023 19:39:47 +0300 Subject: [PATCH 4/4] check `os.Getwd` error --- utils.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utils.go b/utils.go index aa63723..673747f 100644 --- a/utils.go +++ b/utils.go @@ -27,7 +27,11 @@ func getMainModule() (string, error) { return "", fmt.Errorf("running `%s`: %w", strings.Join(args, " "), err) } - cwd, _ := getwd() + cwd, err := getwd() + if err != nil { + return "", fmt.Errorf("getting wd: %w", err) + } + decoder := json.NewDecoder(strings.NewReader(output)) for {