1
0
mirror of https://github.com/golang/go synced 2024-09-28 19:34:28 -06:00

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 <bcmills@google.com>
Auto-Submit: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
This commit is contained in:
Russ Cox 2023-06-01 14:13:20 -04:00 committed by Gopher Robot
parent 40c7be9b0f
commit c71cbd544e
8 changed files with 42 additions and 22 deletions

View File

@ -60,6 +60,7 @@ var Startup struct {
type TooNewError struct {
What string
GoVersion string
Toolchain string // for callers if they want to use it, but not printed
}
func (e *TooNewError) Error() string {

View File

@ -541,7 +541,10 @@ func (mg *ModuleGraph) allRootsSelected() bool {
// LoadModGraph need only be called if LoadPackages is not,
// typically in commands that care about modules but no particular package.
func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) {
rs := LoadModFile(ctx)
rs, err := loadModFile(ctx, nil)
if err != nil {
return nil, err
}
if goVersion != "" {
v, _ := rs.rootSelected("go")

View File

@ -731,12 +731,16 @@ func UpdateWorkFile(wf *modfile.WorkFile) {
// it for global consistency. Most callers outside of the modload package should
// use LoadModGraph instead.
func LoadModFile(ctx context.Context) *Requirements {
return loadModFile(ctx, nil)
rs, err := loadModFile(ctx, nil)
if err != nil {
base.Fatal(err)
}
return rs
}
func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
func loadModFile(ctx context.Context, opts *PackageOpts) (*Requirements, error) {
if requirements != nil {
return requirements
return requirements, nil
}
Init()
@ -745,7 +749,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
var err error
workFile, modRoots, err = loadWorkFile(workFilePath)
if err != nil {
base.Fatalf("reading go.work: %v", err)
return nil, fmt.Errorf("reading go.work: %w", err)
}
for _, modRoot := range modRoots {
sumFile := strings.TrimSuffix(modFilePath(modRoot), ".mod") + ".sum"
@ -796,22 +800,23 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
// with no dependencies.
requirements.initVendor(nil)
}
return requirements
return requirements, nil
}
var modFiles []*modfile.File
var mainModules []module.Version
var indices []*modFileIndex
var errs []error
for _, modroot := range modRoots {
gomod := modFilePath(modroot)
var fixed bool
data, f, err := ReadModFile(gomod, fixVersion(ctx, &fixed))
if err != nil {
if inWorkspaceMode() {
base.Fatalf("go: cannot load module %s listed in go.work file: %v", base.ShortPath(gomod), err)
} else {
base.Fatalf("go: %v", err)
err = fmt.Errorf("cannot load module %s listed in go.work file: %w", base.ShortPath(gomod), err)
}
errs = append(errs, err)
continue
}
modFiles = append(modFiles, f)
@ -823,9 +828,12 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
if pathErr, ok := err.(*module.InvalidPathError); ok {
pathErr.Kind = "module"
}
base.Fatalf("go: %v", err)
errs = append(errs, err)
}
}
if len(errs) > 0 {
return nil, errors.Join(errs...)
}
MainModules = makeMainModules(mainModules, modRoots, modFiles, indices, workFile)
setDefaultBuildMod() // possibly enable automatic vendoring
@ -835,7 +843,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
// We don't need to do anything for vendor or update the mod file so
// return early.
requirements = rs
return rs
return rs, nil
}
mainModule := MainModules.mustGetSingleMainModule()
@ -855,7 +863,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
var err error
rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
if err != nil {
base.Fatal(err)
return nil, err
}
}
@ -880,7 +888,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
var err error
rs, err = convertPruning(ctx, rs, pruned)
if err != nil {
base.Fatal(err)
return nil, err
}
}
} else {
@ -889,7 +897,7 @@ func loadModFile(ctx context.Context, opts *PackageOpts) *Requirements {
}
requirements = rs
return requirements
return requirements, nil
}
// CreateModFile initializes a new module by creating a go.mod file.

View File

@ -341,7 +341,10 @@ func LoadPackages(ctx context.Context, opts PackageOpts, patterns ...string) (ma
}
}
initialRS := loadModFile(ctx, &opts)
initialRS, err := loadModFile(ctx, &opts)
if err != nil {
base.Fatal(err)
}
ld := loadFromRoots(ctx, loaderParams{
PackageOpts: opts,

View File

@ -30,6 +30,7 @@ import (
// ReadModFile reads and parses the mod file at gomod. ReadModFile properly applies the
// overlay, locks the file while reading, and applies fix, if applicable.
func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfile.File, err error) {
gomod = base.ShortPath(gomod) // use short path in any errors
if gomodActual, ok := fsys.OverlayPath(gomod); ok {
// Don't lock go.mod if it's part of the overlay.
// 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
f, err = modfile.Parse(gomod, data, fix)
if err != nil {
// Errors returned by modfile.Parse begin with file:line.
return nil, nil, fmt.Errorf("errors parsing go.mod:\n%s\n", err)
return nil, nil, fmt.Errorf("errors parsing %s:\n%w", gomod, err)
}
if f.Go != nil && gover.Compare(f.Go.Version, gover.Local()) > 0 && cfg.CmdName != "mod edit" {
base.Fatalf("go: %v", &gover.TooNewError{What: base.ShortPath(gomod), GoVersion: f.Go.Version})
if f.Go != nil && gover.Compare(f.Go.Version, gover.Local()) > 0 {
toolchain := ""
if f.Toolchain != nil {
toolchain = f.Toolchain.Name
}
return nil, nil, &gover.TooNewError{What: gomod, GoVersion: f.Go.Version, Toolchain: toolchain}
}
if f.Module == nil {
// No module declaration. Must add module path.
return nil, nil, errors.New("no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod")
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)
}
return data, f, err

View File

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

View File

@ -3,7 +3,7 @@
# Test that go list fails on a go.mod with no module declaration.
cd $WORK/gopath/src/mod
! go list .
stderr '^go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod$'
stderr '^go: error reading go.mod: missing module declaration. To specify the module path:\n\tgo mod edit -module=example.com/mod$'
# Test that go mod init in GOPATH doesn't add a module declaration
# with a path that can't possibly be a module path, because

View File

@ -50,7 +50,7 @@ cd outside
stderr 'go: example.com@v0.0.0 \(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'
cd ..
! go list -m golang.org/x/text
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'
stderr '^go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
# A pseudo-version with fewer than 12 digits of SHA-1 prefix is invalid.
cp go.mod.orig go.mod