mirror of
https://github.com/golang/go
synced 2024-11-17 16:44:44 -07:00
cmd/go: describe dependencies in build list error messages
mvs.BuildList reports errors with a chain of modules to make it clear why the module where the error occurred was part of the build. This is a little confusing with "go get -u" since there are edges in the module graph for requirements and for updates. With this change, we now print "requires" or "updates to" between each module version in the chain. Updates #30661 Change-Id: Ie689500ea86857e715b250b9e0cae0bc6686dc32 Reviewed-on: https://go-review.googlesource.com/c/go/+/171150 Run-TryBot: Jay Conrod <jayconrod@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
6997671d2e
commit
f7c9672592
@ -65,33 +65,41 @@ type Reqs interface {
|
|||||||
// while constructing a build list. BuildListError prints the chain
|
// while constructing a build list. BuildListError prints the chain
|
||||||
// of requirements to the module where the error occurred.
|
// of requirements to the module where the error occurred.
|
||||||
type BuildListError struct {
|
type BuildListError struct {
|
||||||
Err error
|
err error
|
||||||
Stack []module.Version
|
stack []buildListErrorElem
|
||||||
|
}
|
||||||
|
|
||||||
|
type buildListErrorElem struct {
|
||||||
|
m module.Version
|
||||||
|
|
||||||
|
// nextReason is the reason this module depends on the next module in the
|
||||||
|
// stack. Typically either "requires", or "upgraded to".
|
||||||
|
nextReason string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *BuildListError) Error() string {
|
func (e *BuildListError) Error() string {
|
||||||
b := &strings.Builder{}
|
b := &strings.Builder{}
|
||||||
errMsg := e.Err.Error()
|
errMsg := e.err.Error()
|
||||||
stack := e.Stack
|
stack := e.stack
|
||||||
|
|
||||||
// Don't print modules at the beginning of the chain without a
|
// Don't print modules at the beginning of the chain without a
|
||||||
// version. These always seem to be the main module or a
|
// version. These always seem to be the main module or a
|
||||||
// synthetic module ("target@").
|
// synthetic module ("target@").
|
||||||
for len(stack) > 0 && stack[len(stack)-1].Version == "" {
|
for len(stack) > 0 && stack[len(stack)-1].m.Version == "" {
|
||||||
stack = stack[:len(stack)-1]
|
stack = stack[:len(stack)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't print the last module if the error message already
|
// Don't print the last module if the error message already
|
||||||
// starts with module path and version.
|
// starts with module path and version.
|
||||||
if len(stack) > 0 && strings.HasPrefix(errMsg, fmt.Sprintf("%s@%s: ", stack[0].Path, stack[0].Version)) {
|
errMentionsLast := len(stack) > 0 && strings.HasPrefix(errMsg, fmt.Sprintf("%s@%s: ", stack[0].m.Path, stack[0].m.Version))
|
||||||
// error already mentions module
|
for i := len(stack) - 1; i >= 1; i-- {
|
||||||
stack = stack[1:]
|
fmt.Fprintf(b, "%s@%s %s\n\t", stack[i].m.Path, stack[i].m.Version, stack[i].nextReason)
|
||||||
}
|
}
|
||||||
|
if errMentionsLast || len(stack) == 0 {
|
||||||
for i := len(stack) - 1; i >= 0; i-- {
|
b.WriteString(errMsg)
|
||||||
fmt.Fprintf(b, "%s@%s ->\n\t", stack[i].Path, stack[i].Version)
|
} else {
|
||||||
|
fmt.Fprintf(b, "%s@%s: %s", stack[0].m.Path, stack[0].m.Version, errMsg)
|
||||||
}
|
}
|
||||||
b.WriteString(errMsg)
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,9 +176,16 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) mo
|
|||||||
q = q[1:]
|
q = q[1:]
|
||||||
|
|
||||||
if node.err != nil {
|
if node.err != nil {
|
||||||
err := &BuildListError{Err: node.err}
|
err := &BuildListError{
|
||||||
for n := node; n != nil; n = neededBy[n] {
|
err: node.err,
|
||||||
err.Stack = append(err.Stack, n.m)
|
stack: []buildListErrorElem{{m: node.m}},
|
||||||
|
}
|
||||||
|
for n, prev := neededBy[node], node; n != nil; n, prev = neededBy[n], n {
|
||||||
|
reason := "requires"
|
||||||
|
if n.upgrade == prev.m {
|
||||||
|
reason = "updating to"
|
||||||
|
}
|
||||||
|
err.stack = append(err.stack, buildListErrorElem{m: n.m, nextReason: reason})
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
24
src/cmd/go/testdata/script/mod_load_badchain.txt
vendored
24
src/cmd/go/testdata/script/mod_load_badchain.txt
vendored
@ -8,18 +8,18 @@ go mod download example.com/badchain/a@v1.1.0
|
|||||||
go mod download example.com/badchain/b@v1.1.0
|
go mod download example.com/badchain/b@v1.1.0
|
||||||
go mod download example.com/badchain/c@v1.1.0
|
go mod download example.com/badchain/c@v1.1.0
|
||||||
|
|
||||||
# Try to upgrade example.com/badchain/a (and its dependencies).
|
# Try to update example.com/badchain/a (and its dependencies).
|
||||||
! go get -u example.com/badchain/a
|
! go get -u example.com/badchain/a
|
||||||
cmp stderr upgrade-a-expected
|
cmp stderr update-a-expected
|
||||||
cmp go.mod go.mod.orig
|
cmp go.mod go.mod.orig
|
||||||
|
|
||||||
# Try to upgrade the main module. This upgrades everything, including
|
# Try to update the main module. This updates everything, including
|
||||||
# modules that aren't direct requirements, so the error stack is shorter.
|
# modules that aren't direct requirements, so the error stack is shorter.
|
||||||
! go get -u
|
! go get -u
|
||||||
cmp stderr upgrade-main-expected
|
cmp stderr update-main-expected
|
||||||
cmp go.mod go.mod.orig
|
cmp go.mod go.mod.orig
|
||||||
|
|
||||||
# Upgrade manually. Listing modules should produce an error.
|
# update manually. Listing modules should produce an error.
|
||||||
go mod edit -require=example.com/badchain/a@v1.1.0
|
go mod edit -require=example.com/badchain/a@v1.1.0
|
||||||
! go list -m
|
! go list -m
|
||||||
cmp stderr list-expected
|
cmp stderr list-expected
|
||||||
@ -28,14 +28,14 @@ cmp stderr list-expected
|
|||||||
module m
|
module m
|
||||||
|
|
||||||
require example.com/badchain/a v1.0.0
|
require example.com/badchain/a v1.0.0
|
||||||
-- upgrade-main-expected --
|
-- update-main-expected --
|
||||||
go get: example.com/badchain/c@v1.0.0 ->
|
go get: example.com/badchain/c@v1.0.0 updating to
|
||||||
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
||||||
-- upgrade-a-expected --
|
-- update-a-expected --
|
||||||
go get: example.com/badchain/a@v1.1.0 ->
|
go get: example.com/badchain/a@v1.1.0 requires
|
||||||
example.com/badchain/b@v1.1.0 ->
|
example.com/badchain/b@v1.1.0 requires
|
||||||
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
||||||
-- list-expected --
|
-- list-expected --
|
||||||
go: example.com/badchain/a@v1.1.0 ->
|
go: example.com/badchain/a@v1.1.0 requires
|
||||||
example.com/badchain/b@v1.1.0 ->
|
example.com/badchain/b@v1.1.0 requires
|
||||||
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
example.com/badchain/c@v1.1.0: parsing go.mod: unexpected module path "example.com/badchain/wrong"
|
||||||
|
Loading…
Reference in New Issue
Block a user