fix(build): keep an existing toolchain line instead of adding a second one
make:*, plugin:add and new inserted toolchain go1.27.0 into go.mod and go.work whenever that exact line was missing. A file that already named another toolchain (go mod tidy and go work use write the running one) ended up with two toolchain lines, and Go refused to load it with "repeated toolchain statement". ensureToolchain now keeps an existing line, replaces it only when it names an older toolchain, and inserts one only when there is none.
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
|||||||
"go/format"
|
"go/format"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"go/version"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -555,6 +556,24 @@ func ensureToolchain(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
lines := strings.Split(string(data), "\n")
|
lines := strings.Split(string(data), "\n")
|
||||||
|
// A file may carry its own toolchain line (go mod tidy and go work use
|
||||||
|
// write the running toolchain). Go refuses a second one, so keep an
|
||||||
|
// existing line unless it names an older toolchain than ours.
|
||||||
|
want := strings.TrimSpace(strings.TrimPrefix(toolchainLine, "toolchain"))
|
||||||
|
for i, line := range lines {
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
if len(fields) != 2 || fields[0] != "toolchain" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if version.Compare(fields[1], want) >= 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
lines[i] = toolchainLine
|
||||||
|
if err := os.WriteFile(path, []byte(strings.Join(lines, "\n")), 0o644); err != nil {
|
||||||
|
return fmt.Errorf("build: write %s: %w", path, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
out := make([]string, 0, len(lines)+2)
|
out := make([]string, 0, len(lines)+2)
|
||||||
inserted := false
|
inserted := false
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
|
|||||||
58
internal/build/toolchain_test.go
Normal file
58
internal/build/toolchain_test.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnsureToolchain(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
in string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "missing line is added after go",
|
||||||
|
in: "go 1.27\n\nuse .\n",
|
||||||
|
want: "go 1.27\n\n" + toolchainLine + "\n\nuse .\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "our line is kept",
|
||||||
|
in: "go 1.27\n\n" + toolchainLine + "\n",
|
||||||
|
want: "go 1.27\n\n" + toolchainLine + "\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "newer toolchain is kept, not repeated",
|
||||||
|
in: "go 1.27\n\ntoolchain go1.99.2\n\nuse .\n",
|
||||||
|
want: "go 1.27\n\ntoolchain go1.99.2\n\nuse .\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "older toolchain is replaced",
|
||||||
|
in: "module x\n\ngo 1.25\n\ntoolchain go1.25.1\n",
|
||||||
|
want: "module x\n\ngo 1.25\n\n" + toolchainLine + "\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
path := filepath.Join(t.TempDir(), "go.work")
|
||||||
|
if err := os.WriteFile(path, []byte(tc.in), 0o644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := ensureToolchain(path); err != nil {
|
||||||
|
t.Fatalf("ensureToolchain: %v", err)
|
||||||
|
}
|
||||||
|
got, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if string(got) != tc.want {
|
||||||
|
t.Fatalf("got:\n%s\nwant:\n%s", got, tc.want)
|
||||||
|
}
|
||||||
|
if n := strings.Count(string(got), "\ntoolchain "); n != 1 {
|
||||||
|
t.Fatalf("got %d toolchain lines, want 1", n)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user