Skip to content

Commit c71cbd5

Browse files
rscgopherbot
authored andcommitted
cmd/go: return more errors from ReadModFile, loadModFile
Return more errors instead of base.Fatalf, so we can handle them in the callers. For #57001. Change-Id: If3e63d3f64188148f5d750991f9cb1175790d89d Reviewed-on: https://go-review.googlesource.com/c/go/+/499983 Reviewed-by: Bryan Mills <[email protected]> Auto-Submit: Russ Cox <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Russ Cox <[email protected]>
1 parent 40c7be9 commit c71cbd5

File tree

8 files changed

+42
-22
lines changed

8 files changed

+42
-22
lines changed

src/cmd/go/internal/gover/toolchain.go

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ var Startup struct {
6060
type TooNewError struct {
6161
What string
6262
GoVersion string
63+
Toolchain string // for callers if they want to use it, but not printed
6364
}
6465

6566
func (e *TooNewError) Error() string {

src/cmd/go/internal/modload/buildlist.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,10 @@ func (mg *ModuleGraph) allRootsSelected() bool {
541541
// LoadModGraph need only be called if LoadPackages is not,
542542
// typically in commands that care about modules but no particular package.
543543
func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) {
544-
rs := LoadModFile(ctx)
544+
rs, err := loadModFile(ctx, nil)
545+
if err != nil {
546+
return nil, err
547+
}
545548

546549
if goVersion != "" {
547550
v, _ := rs.rootSelected("go")

src/cmd/go/internal/modload/init.go

+21-13
Original file line numberDiff line numberDiff line change
@@ -731,12 +731,16 @@ func UpdateWorkFile(wf *modfile.WorkFile) {
731731
// it for global consistency. Most callers outside of the modload package should
732732
// use LoadModGraph instead.
733733
func LoadModFile(ctx context.Context) *Requirements {
734-
return loadModFile(ctx, nil)
734+
rs, err := loadModFile(ctx, nil)
735+
if err != nil {
736+
base.Fatal(err)
737+
}
738+
return rs
735739
}
736740

737-
func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
741+
func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) {
738742
if requirements != nil {
739-
return requirements
743+
return requirements, nil
740744
}
741745

742746
Init()
@@ -745,7 +749,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
745749
var err error
746750
workFile, modRoots, err = loadWorkFile(workFilePath)
747751
if err != nil {
748-
base.Fatalf("reading go.work: %v", err)
752+
return nil, fmt.Errorf("reading go.work: %w", err)
749753
}
750754
for _, modRoot := range modRoots {
751755
sumFile := strings.TrimSuffix(modFilePath(modRoot), ".mod") + ".sum"
@@ -796,22 +800,23 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
796800
// with no dependencies.
797801
requirements.initVendor(nil)
798802
}
799-
return requirements
803+
return requirements, nil
800804
}
801805

802806
var modFiles []*modfile.File
803807
var mainModules []module.Version
804808
var indices []*modFileIndex
809+
var errs []error
805810
for _, modroot := range modRoots {
806811
gomod := modFilePath(modroot)
807812
var fixed bool
808813
data, f, err := ReadModFile(gomod, fixVersion(ctx, &fixed))
809814
if err != nil {
810815
if inWorkspaceMode() {
811-
base.Fatalf("go: cannot load module %s listed in go.work file: %v", base.ShortPath(gomod), err)
812-
} else {
813-
base.Fatalf("go: %v", err)
816+
err = fmt.Errorf("cannot load module %s listed in go.work file: %w", base.ShortPath(gomod), err)
814817
}
818+
errs = append(errs, err)
819+
continue
815820
}
816821

817822
modFiles = append(modFiles, f)
@@ -823,9 +828,12 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
823828
if pathErr, ok := err.(*module.InvalidPathError); ok {
824829
pathErr.Kind = "module"
825830
}
826-
base.Fatalf("go: %v", err)
831+
errs = append(errs, err)
827832
}
828833
}
834+
if len(errs) > 0 {
835+
return nil, errors.Join(errs...)
836+
}
829837

830838
MainModules = makeMainModules(mainModules, modRoots, modFiles, indices, workFile)
831839
setDefaultBuildMod() // possibly enable automatic vendoring
@@ -835,7 +843,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
835843
// We don't need to do anything for vendor or update the mod file so
836844
// return early.
837845
requirements = rs
838-
return rs
846+
return rs, nil
839847
}
840848

841849
mainModule := MainModules.mustGetSingleMainModule()
@@ -855,7 +863,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
855863
var err error
856864
rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
857865
if err != nil {
858-
base.Fatal(err)
866+
return nil, err
859867
}
860868
}
861869

@@ -880,7 +888,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
880888
var err error
881889
rs, err = convertPruning(ctx, rs, pruned)
882890
if err != nil {
883-
base.Fatal(err)
891+
return nil, err
884892
}
885893
}
886894
} else {
@@ -889,7 +897,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
889897
}
890898

891899
requirements = rs
892-
return requirements
900+
return requirements, nil
893901
}
894902

895903
// CreateModFile initializes a new module by creating a go.mod file.

src/cmd/go/internal/modload/load.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,10 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
341341
}
342342
}
343343

344-
initialRS := loadModFile(ctx, &opts)
344+
initialRS, err := loadModFile(ctx, &opts)
345+
if err != nil {
346+
base.Fatal(err)
347+
}
345348

346349
ld := loadFromRoots(ctx, loaderParams{
347350
PackageOpts: opts,

src/cmd/go/internal/modload/modfile.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
// ReadModFile reads and parses the mod file at gomod. ReadModFile properly applies the
3131
// overlay, locks the file while reading, and applies fix, if applicable.
3232
func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfile.File, err error) {
33+
gomod = base.ShortPath(gomod) // use short path in any errors
3334
if gomodActual, ok := fsys.OverlayPath(gomod); ok {
3435
// Don't lock go.mod if it's part of the overlay.
3536
// On Plan 9, locking requires chmod, and we don't want to modify any file
@@ -45,14 +46,18 @@ func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfil
4546
f, err = modfile.Parse(gomod, data, fix)
4647
if err != nil {
4748
// Errors returned by modfile.Parse begin with file:line.
48-
return nil, nil, fmt.Errorf("errors parsing go.mod:\n%s\n", err)
49+
return nil, nil, fmt.Errorf("errors parsing %s:\n%w", gomod, err)
4950
}
50-
if f.Go != nil && gover.Compare(f.Go.Version, gover.Local()) > 0 && cfg.CmdName != "mod edit" {
51-
base.Fatalf("go: %v", &gover.TooNewError{What: base.ShortPath(gomod), GoVersion: f.Go.Version})
51+
if f.Go != nil && gover.Compare(f.Go.Version, gover.Local()) > 0 {
52+
toolchain := ""
53+
if f.Toolchain != nil {
54+
toolchain = f.Toolchain.Name
55+
}
56+
return nil, nil, &gover.TooNewError{What: gomod, GoVersion: f.Go.Version, Toolchain: toolchain}
5257
}
5358
if f.Module == nil {
5459
// No module declaration. Must add module path.
55-
return nil, nil, errors.New("no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod")
60+
return nil, nil, fmt.Errorf("error reading %s: missing module declaration. To specify the module path:\n\tgo mod edit -module=example.com/mod", gomod)
5661
}
5762

5863
return data, f, err

src/cmd/go/testdata/script/mod_goline_too_new.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ stderr '^go: go.mod requires go >= 1.99999 \(running go 1\..+\)$'
88
# go.mod referenced from go.work too new
99
cp go.work.old go.work
1010
! go build .
11-
stderr '^go: go.mod requires go >= 1.99999 \(running go 1\..+\)$'
11+
stderr '^go: cannot load module go.mod listed in go.work file: go.mod requires go >= 1.99999 \(running go 1\..+\)$'
1212

1313
# go.work too new
1414
cp go.work.new go.work

src/cmd/go/testdata/script/mod_invalid_path.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Test that go list fails on a go.mod with no module declaration.
44
cd $WORK/gopath/src/mod
55
! go list .
6-
stderr '^go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod$'
6+
stderr '^go: error reading go.mod: missing module declaration. To specify the module path:\n\tgo mod edit -module=example.com/mod$'
77

88
# Test that go mod init in GOPATH doesn't add a module declaration
99
# with a path that can't possibly be a module path, because

src/cmd/go/testdata/script/mod_invalid_version.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ cd outside
5050
stderr 'go: [email protected] \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
5151
cd ..
5252
! go list -m golang.org/x/text
53-
stderr $WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
53+
stderr '^go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
5454

5555
# A pseudo-version with fewer than 12 digits of SHA-1 prefix is invalid.
5656
cp go.mod.orig go.mod

0 commit comments

Comments
 (0)