Skip to content

Commit 4460b0f

Browse files
committed
modules: Improve error checking
1. Validate combination of module path and version 2. Capture and display error messages from JSON sent to stdout 3. Remove invalid semver from mod_vendor__versions.txt testscript Closes #14010
1 parent 9943c1b commit 4460b0f

File tree

4 files changed

+78
-13
lines changed

4 files changed

+78
-13
lines changed

‎modules/client.go‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -717,12 +717,13 @@ func (c *Client) runGo(
717717
return nil
718718
}
719719

720-
stderr := new(bytes.Buffer)
720+
stdErrBuf := new(bytes.Buffer)
721+
stdOutBuf := new(bytes.Buffer)
721722

722723
argsv := collections.StringSliceToInterfaceSlice(args)
723724
argsv = append(argsv, hexec.WithEnviron(c.environ))
724-
argsv = append(argsv, hexec.WithStderr(goOutputReplacerWriter{w: io.MultiWriter(stderr, os.Stderr)}))
725-
argsv = append(argsv, hexec.WithStdout(stdout))
725+
argsv = append(argsv, hexec.WithStderr(goOutputReplacerWriter{w: io.MultiWriter(stdErrBuf, os.Stderr)}))
726+
argsv = append(argsv, hexec.WithStdout(goOutputReplacerWriter{w: io.MultiWriter(stdOutBuf, stdout)}))
726727
argsv = append(argsv, hexec.WithDir(c.ccfg.WorkingDir))
727728
argsv = append(argsv, hexec.WithContext(ctx))
728729

@@ -737,7 +738,15 @@ func (c *Client) runGo(
737738
return nil
738739
}
739740

740-
if strings.Contains(stderr.String(), "invalid version: unknown revision") {
741+
var stdOutMap map[string]any
742+
err2 := json.Unmarshal(stdOutBuf.Bytes(), &stdOutMap)
743+
if err2 == nil {
744+
if stdOutMap["Error"] != "" {
745+
return fmt.Errorf("%s", stdOutMap["Error"])
746+
}
747+
}
748+
749+
if strings.Contains(stdErrBuf.String(), "invalid version: unknown revision") {
741750
// See https://github.com/gohugoio/hugo/issues/6825
742751
c.logger.Println(`An unknown revision most likely means that someone has deleted the remote ref (e.g. with a force push to GitHub).
743752
To resolve this, you need to manually edit your go.mod file and replace the version for the module in question with a valid ref.
@@ -755,12 +764,12 @@ If you then run 'hugo mod graph' it should resolve itself to the most recent ver
755764
}
756765

757766
// Too old Go version
758-
if strings.Contains(stderr.String(), "flag provided but not defined") {
767+
if strings.Contains(stdErrBuf.String(), "flag provided but not defined") {
759768
c.goBinaryStatus = goBinaryStatusTooOld
760769
return nil
761770
}
762771

763-
return fmt.Errorf("go command failed: %s", stderr)
772+
return fmt.Errorf("go command failed: %s", stdErrBuf.String())
764773

765774
}
766775

‎modules/collect.go‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,14 @@ func (c *collector) addAndRecurse(owner *moduleAdapter) error {
371371
continue
372372
}
373373

374+
// Validate the combination of module path and version.
375+
if moduleImport.Version != "" {
376+
err := module.Check(moduleImport.Path, moduleImport.Version)
377+
if err != nil {
378+
return err
379+
}
380+
}
381+
374382
// Prevent cyclic references.
375383
if v := c.isPathSeen(moduleImport.Path, owner); v != nil && v != owner {
376384
continue

‎modules/modules_integration_test.go‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
package modules_test
1515

1616
import (
17+
"strings"
1718
"testing"
1819

20+
qt "github.com/frankban/quicktest"
1921
"github.com/gohugoio/hugo/hugolib"
2022
)
2123

@@ -48,3 +50,49 @@ Deps: {{ range hugo.Deps}}{{ printf "%s@%s" .Path .Version }}|{{ end }}$
4850
b.AssertFileContent("public/blog/music/autumn-leaves/index.html", "Autumn Leaves is a popular jazz standard") // v0.2.0
4951
b.AssertFileContent("public/v1/blog/music/autumn-leaves/index.html", "Lorem markdownum, placidi peremptis") // v0.1.0
5052
}
53+
54+
// Issue 14010
55+
func TestModuleImportErrors(t *testing.T) {
56+
t.Parallel()
57+
58+
files := `
59+
-- hugo.toml --
60+
[[module.imports]]
61+
PATH
62+
VERSION
63+
`
64+
f := strings.NewReplacer("PATH", "", "VERSION", "").Replace(files)
65+
b, err := hugolib.TestE(t, f)
66+
b.Assert(err, qt.IsNotNil)
67+
b.Assert(err, qt.ErrorMatches, `^failed to load modules: module "" not found.*`)
68+
69+
f = strings.NewReplacer("PATH", "path = 'foo'", "VERSION", "").Replace(files)
70+
b, err = hugolib.TestE(t, f)
71+
b.Assert(err, qt.IsNotNil)
72+
b.Assert(err, qt.ErrorMatches, `^failed to load modules: module "foo" not found.*`)
73+
74+
f = strings.NewReplacer("PATH", "path = 'foo'", "VERSION", "version = 'badSemVer'").Replace(files)
75+
b, err = hugolib.TestE(t, f)
76+
b.Assert(err, qt.IsNotNil)
77+
b.Assert(err, qt.ErrorMatches, `failed to load modules: malformed module path "foo": missing dot in first path element`)
78+
79+
f = strings.NewReplacer("PATH", "path = 'foo.bar'", "VERSION", "version = 'badSemVer'").Replace(files)
80+
b, err = hugolib.TestE(t, f)
81+
b.Assert(err, qt.IsNotNil)
82+
b.Assert(err, qt.ErrorMatches, `failed to load modules: foo.bar@badSemVer: invalid version: not a semantic version`)
83+
84+
f = strings.NewReplacer("PATH", "path = 'foo.bar'", "VERSION", "version = 'v6.7.42'").Replace(files)
85+
b, err = hugolib.TestE(t, f)
86+
b.Assert(err, qt.IsNotNil)
87+
b.Assert(err, qt.ErrorMatches, `failed to load modules: foo.bar@v6.7.42: invalid version: should be v0 or v1, not v6`)
88+
89+
f = strings.NewReplacer("PATH", "path = 'foo.bar/v2'", "VERSION", "version = 'v6.7.42'").Replace(files)
90+
b, err = hugolib.TestE(t, f)
91+
b.Assert(err, qt.IsNotNil)
92+
b.Assert(err, qt.ErrorMatches, `failed to load modules: foo.bar/v2@v6.7.42: invalid version: should be v2, not v6`)
93+
94+
f = strings.NewReplacer("PATH", "path = 'github.com/bep/hugo-mod-misc/dummy-content/v99'", "VERSION", "version = 'v99.0.0'").Replace(files)
95+
b, err = hugolib.TestE(t, f)
96+
b.Assert(err, qt.IsNotNil)
97+
b.Assert(err, qt.ErrorMatches, `failed to load modules: failed to download module github.com/bep/hugo-mod-misc/dummy-content/v99@v99.0.0: github.com/bep/hugo-mod-misc/dummy-content/v99@v99.0.0: invalid version: unknown revision dummy-content/v99.0.0`)
98+
}

‎testscripts/commands/mod_vendor__versions.txt‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ dostounix golden/vendor.txt
33
hugo mod vendor
44
cmp _vendor/modules.txt golden/vendor.txt
55
lsr _vendor
6-
stdout 'github.com/bep/hugo-mod-misc/dummy-content@%3C%3Dv0.1.0/config.toml'
6+
stdout 'github.com/bep/hugo-mod-misc/dummy-content@v0.1.0/config.toml'
77
stdout 'github.com/bep/hugo-mod-misc/dummy-content@v0.2.0/config.toml'
88
stdout 'github.com/bep/hugo-mod-misc/dummy-content@v0.2.0/content/blog/music/all-of-me/index.md'
99
stdout 'github.com/bep/hugo-mod-misc/dummy-content@v0.2.0/content/blog/music/blue-bossa/index.md'
10-
stdout 'github.com/bep/hugo-mod-misc/dummy-content@%3C%3Dv0.1.0/content/blog/music/all-of-me/index.md'
11-
! stdout 'github.com/bep/hugo-mod-misc/dummy-content@%3C%3Dv0.1.0/content/blog/music/blue-bossa/index.md' # not mounted
10+
stdout 'github.com/bep/hugo-mod-misc/dummy-content@v0.1.0/content/blog/music/all-of-me/index.md'
11+
! stdout 'github.com/bep/hugo-mod-misc/dummy-content@v0.1.0/content/blog/music/blue-bossa/index.md' # not mounted
1212

1313
hugo mod graph
14-
stdout 'project github.com/bep/hugo-mod-misc/dummy-content@v0.2.0'
14+
stdout 'project github.com/bep/hugo-mod-misc/dummy-content@v0.2.0'
1515
stdout 'project github.com/bep/hugo-mod-misc/dummy-content@v0.1.0'
1616

1717
hugo config mounts
@@ -24,7 +24,7 @@ path = "github.com/bep/hugo-mod-misc/dummy-content"
2424
version = "v0.2.0"
2525
[[module.imports]]
2626
path = "github.com/bep/hugo-mod-misc/dummy-content"
27-
version = "<=v0.1.0"
27+
version = "v0.1.0"
2828
[[module.imports.mounts]]
2929
source = "content/blog/music/all-of-me"
3030
target = "content/all"
@@ -35,7 +35,7 @@ Deps: {{ range hugo.Deps}}{{ printf "%s@%s" .Path .Version }}|{{ end }}$
3535

3636
-- golden/vendor.txt --
3737
# github.com/bep/hugo-mod-misc/dummy-content@v0.2.0 v0.2.0
38-
# github.com/bep/hugo-mod-misc/dummy-content@%3C%3Dv0.1.0 v0.1.0
38+
# github.com/bep/hugo-mod-misc/dummy-content@v0.1.0 v0.1.0
3939
-- golden/mounts.json --
4040
{
4141
"path": "project",
@@ -92,7 +92,7 @@ Deps: {{ range hugo.Deps}}{{ printf "%s@%s" .Path .Version }}|{{ end }}$
9292
"version": "v0.1.0",
9393
"time": "0001-01-01T00:00:00Z",
9494
"owner": "project",
95-
"dir": "$WORK/_vendor/github.com/bep/hugo-mod-misc/dummy-content@%3C%3Dv0.1.0/",
95+
"dir": "$WORK/_vendor/github.com/bep/hugo-mod-misc/dummy-content@v0.1.0/",
9696
"mounts": [
9797
{
9898
"source": "content/blog/music/all-of-me",

0 commit comments

Comments
 (0)