From 031914d9cc68f9ddc0d017be2716be570554c333 Mon Sep 17 00:00:00 2001 From: lingcoder Date: Tue, 20 Jan 2026 14:21:56 +0800 Subject: [PATCH] fix(cmd/gf): fix gf env and gf build --dumpEnv command error (#4469) When go env outputs warning messages (e.g., "go: stripping unprintable characters from GOPROXY") and returns non-zero exit code, the gf env command would fail. Changes: - Only fail when go env returns empty output, allow non-zero exit code with valid output - Skip lines that don't match key=value format instead of failing - Add debug log for skipped lines - Add unit tests for env command --- .gitignore | 3 +- cmd/gf/internal/cmd/cmd_env.go | 14 ++-- cmd/gf/internal/cmd/cmd_z_unit_env_test.go | 84 ++++++++++++++++++++++ 3 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 cmd/gf/internal/cmd/cmd_z_unit_env_test.go diff --git a/.gitignore b/.gitignore index 964d5fdd0dd..be381afce8e 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ node_modules .docusaurus output .example/ -.golangci.bck.yml \ No newline at end of file +.golangci.bck.yml +*.exe \ No newline at end of file diff --git a/cmd/gf/internal/cmd/cmd_env.go b/cmd/gf/internal/cmd/cmd_env.go index 8c48be62e31..52153badebe 100644 --- a/cmd/gf/internal/cmd/cmd_env.go +++ b/cmd/gf/internal/cmd/cmd_env.go @@ -37,11 +37,13 @@ type cEnvInput struct { type cEnvOutput struct{} func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err error) { - result, err := gproc.ShellExec(ctx, "go env") - if err != nil { - mlog.Fatal(err) - } + result, execErr := gproc.ShellExec(ctx, "go env") + // Note: go env may return non-zero exit code when there are warnings (e.g., invalid characters in env vars), + // but it still outputs valid environment variables. So we only fail if result is empty. if result == "" { + if execErr != nil { + mlog.Fatal(execErr) + } mlog.Fatal(`retrieving Golang environment variables failed, did you install Golang?`) } var ( @@ -59,7 +61,9 @@ func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err err } match, _ := gregex.MatchString(`(.+?)=(.*)`, line) if len(match) < 3 { - mlog.Fatalf(`invalid Golang environment variable: "%s"`, line) + // Skip lines that don't match key=value format (e.g., warning messages from go env) + mlog.Debugf(`invalid Golang environment variable: "%s"`, line) + continue } array = append(array, []string{gstr.Trim(match[1]), gstr.Trim(match[2])}) } diff --git a/cmd/gf/internal/cmd/cmd_z_unit_env_test.go b/cmd/gf/internal/cmd/cmd_z_unit_env_test.go new file mode 100644 index 00000000000..cecb67edc60 --- /dev/null +++ b/cmd/gf/internal/cmd/cmd_z_unit_env_test.go @@ -0,0 +1,84 @@ +// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package cmd + +import ( + "testing" + + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/text/gregex" + "github.com/gogf/gf/v2/text/gstr" +) + +func Test_Env_Index(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + // Test that env command runs without error + _, err := Env.Index(ctx, cEnvInput{}) + t.AssertNil(err) + }) +} + +func Test_Env_ParseGoEnvOutput(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + // Test parsing normal go env output + lines := []string{ + "set GOPATH=C:\\Users\\test\\go", + "set GOROOT=C:\\Go", + "set GOOS=windows", + "GOARCH=amd64", // Unix format without "set " prefix + "CGO_ENABLED=0", + } + + for _, line := range lines { + line = gstr.Trim(line) + if gstr.Pos(line, "set ") == 0 { + line = line[4:] + } + match, _ := gregex.MatchString(`(.+?)=(.*)`, line) + t.Assert(len(match) >= 3, true) + } + }) +} + +func Test_Env_ParseGoEnvOutput_WithWarnings(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + // Test parsing go env output that contains warning messages + // These lines should be skipped without causing errors + lines := []string{ + "go: stripping unprintable or unescapable characters from %\"GOPROXY\"%", + "go: warning: some warning message", + "# this is a comment", + "", + "set GOPATH=C:\\Users\\test\\go", + "set GOOS=windows", + } + + array := make([][]string, 0) + for _, line := range lines { + line = gstr.Trim(line) + if line == "" { + continue + } + if gstr.Pos(line, "set ") == 0 { + line = line[4:] + } + match, _ := gregex.MatchString(`(.+?)=(.*)`, line) + if len(match) < 3 { + // Skip lines that don't match key=value format (e.g., warning messages) + continue + } + array = append(array, []string{gstr.Trim(match[1]), gstr.Trim(match[2])}) + } + + // Should have parsed 2 valid environment variables + t.Assert(len(array), 2) + t.Assert(array[0][0], "GOPATH") + t.Assert(array[0][1], "C:\\Users\\test\\go") + t.Assert(array[1][0], "GOOS") + t.Assert(array[1][1], "windows") + }) +}