From: Bjørn Erik Pedersen Date: Mon, 20 Apr 2026 15:47:12 +0000 (+0200) Subject: modules: Ignore non-require blocks in go.mod rewrite X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=4169c1f70fc24a9f18fedc9f77ec33c53856e23b;p=brevno-suite%2Fhugo modules: Ignore non-require blocks in go.mod rewrite The Go 1.24 tool directive uses single-token entries inside a tool ( ... ) block. The previous splitter treated any tab-indented line as a require entry, causing an index out of range panic when running hugo mod tidy on a module with a tool block. Track the require block state explicitly so other blocks (tool, replace, exclude, retract) are left untouched. Fixes #14783 --- diff --git a/modules/client.go b/modules/client.go index 2d111229c..2e2f65b19 100644 --- a/modules/client.go +++ b/modules/client.go @@ -1045,18 +1045,32 @@ func (modules goModules) GetMain() *goModule { func getModlineSplitter(isGoMod bool) func(line string) []string { if isGoMod { + var inRequireBlock bool return func(line string) []string { if strings.HasPrefix(line, "require (") { + inRequireBlock = true return nil } - if !strings.HasPrefix(line, "require") && !strings.HasPrefix(line, "\t") { + if inRequireBlock { + if strings.HasPrefix(line, ")") { + inRequireBlock = false + return nil + } + if !strings.HasPrefix(line, "\t") { + return nil + } + } else if !strings.HasPrefix(line, "require ") { return nil } line = strings.TrimPrefix(line, "require") line = strings.TrimSpace(line) line = strings.TrimSuffix(line, "// indirect") - return strings.Fields(line) + parts := strings.Fields(line) + if len(parts) < 2 { + return nil + } + return parts } } diff --git a/modules/client_test.go b/modules/client_test.go index 54e36be3a..188646c1f 100644 --- a/modules/client_test.go +++ b/modules/client_test.go @@ -210,14 +210,27 @@ func TestGetModlineSplitter(t *testing.T) { gomodSplitter := getModlineSplitter(true) + c.Assert(gomodSplitter("require ("), qt.IsNil) c.Assert(gomodSplitter("\tgithub.com/BurntSushi/toml v0.3.1"), qt.DeepEquals, []string{"github.com/BurntSushi/toml", "v0.3.1"}) c.Assert(gomodSplitter("\tgithub.com/cpuguy83/go-md2man v1.0.8 // indirect"), qt.DeepEquals, []string{"github.com/cpuguy83/go-md2man", "v1.0.8"}) - c.Assert(gomodSplitter("require ("), qt.IsNil) gosumSplitter := getModlineSplitter(false) c.Assert(gosumSplitter("github.com/BurntSushi/toml v0.3.1"), qt.DeepEquals, []string{"github.com/BurntSushi/toml", "v0.3.1"}) } +// Issue 14783 +func TestGetModlineSplitterIgnoresToolBlockIssue14783(t *testing.T) { + c := qt.New(t) + + gomodSplitter := getModlineSplitter(true) + + c.Assert(gomodSplitter("tool ("), qt.IsNil) + c.Assert(gomodSplitter("\tgithub.com/gohugoio/hugo"), qt.IsNil) + c.Assert(gomodSplitter(")"), qt.IsNil) + c.Assert(gomodSplitter("require ("), qt.IsNil) + c.Assert(gomodSplitter("\tgithub.com/foo/bar v1.2.3"), qt.DeepEquals, []string{"github.com/foo/bar", "v1.2.3"}) +} + func TestClientConfigToEnv(t *testing.T) { c := qt.New(t) diff --git a/testscripts/commands/mod_tidy.txt b/testscripts/commands/mod_tidy.txt index 1a250f370..13331a1b6 100644 --- a/testscripts/commands/mod_tidy.txt +++ b/testscripts/commands/mod_tidy.txt @@ -11,9 +11,17 @@ go 1.19 require github.com/bep/empty-hugo-module v1.0.0 +tool ( + github.com/gohugoio/hugo +) + module github.com/gohugoio/testmod -- golden/go.mod.cleaned -- go 1.19 +tool ( + github.com/gohugoio/hugo +) + module github.com/gohugoio/testmod