Skip to content

Commit 5e58ae4

Browse files
author
Jay Conrod
committed
cmd/go: report changes and resolved versions in 'go get'
Fixes #33284 Change-Id: I33daa5eb518985bc7308f29655e04c57e244b479 Reviewed-on: https://go-review.googlesource.com/c/go/+/269018 Run-TryBot: Jay Conrod <jayconrod@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Jay Conrod <jayconrod@google.com> Reviewed-by: Bryan C. Mills <bcmills@google.com>
1 parent 012efc6 commit 5e58ae4

File tree

2 files changed

+145
-50
lines changed

2 files changed

+145
-50
lines changed

src/cmd/go/internal/modget/get.go

Lines changed: 75 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ import (
4545
"cmd/go/internal/search"
4646
"cmd/go/internal/work"
4747

48+
"golang.org/x/mod/modfile"
4849
"golang.org/x/mod/module"
50+
"golang.org/x/mod/semver"
4951
)
5052

5153
var CmdGet = &base.Command{
@@ -462,10 +464,19 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) {
462464
// what's changing and gives more examples.
463465
}
464466

467+
if !modload.HasModRoot() {
468+
return
469+
}
470+
465471
// Everything succeeded. Update go.mod.
472+
oldReqs := reqsFromGoMod(modload.ModFile())
473+
466474
modload.AllowWriteGoMod()
467475
modload.WriteGoMod()
468476
modload.DisallowWriteGoMod()
477+
478+
newReqs := reqsFromGoMod(modload.ModFile())
479+
r.reportChanges(oldReqs, newReqs)
469480
}
470481

471482
// parseArgs parses command-line arguments and reports errors.
@@ -1563,63 +1574,69 @@ func (r *resolver) checkPackagesAndRetractions(ctx context.Context, pkgPatterns
15631574
}
15641575
}
15651576

1566-
// reportChanges logs resolved version changes to os.Stderr.
1567-
func (r *resolver) reportChanges(queries []*query) {
1568-
for _, q := range queries {
1569-
if q.version == "none" {
1570-
continue
1571-
}
1572-
1573-
if q.pattern == "all" {
1574-
// To reduce noise for "all", describe module version changes rather than
1575-
// package versions.
1576-
seen := make(map[module.Version]bool)
1577-
for _, m := range q.resolved {
1578-
if seen[m] {
1579-
continue
1580-
}
1581-
seen[m] = true
1582-
1583-
before := r.initialSelected(m.Path)
1584-
if before == m.Version {
1585-
continue // m was resolved, but not changed
1586-
}
1577+
// reportChanges logs version changes to os.Stderr.
1578+
//
1579+
// reportChanges only logs changes to modules named on the command line and to
1580+
// explicitly required modules in go.mod. Most changes to indirect requirements
1581+
// are not relevant to the user and are not logged.
1582+
//
1583+
// reportChanges should be called after WriteGoMod.
1584+
func (r *resolver) reportChanges(oldReqs, newReqs []module.Version) {
1585+
type change struct {
1586+
path, old, new string
1587+
}
1588+
changes := make(map[string]change)
15871589

1588-
was := ""
1589-
if before != "" {
1590-
was = fmt.Sprintf(" (was %s)", before)
1591-
}
1592-
fmt.Fprintf(os.Stderr, "go: %v added %s %s%s\n", q, m.Path, m.Version, was)
1593-
}
1594-
continue
1590+
// Collect changes in modules matched by command line arguments.
1591+
for path, reason := range r.resolvedVersion {
1592+
old := r.initialVersion[path]
1593+
new := reason.version
1594+
if old != new && (old != "" || new != "none") {
1595+
changes[path] = change{path, old, new}
15951596
}
1597+
}
15961598

1597-
for _, m := range q.resolved {
1598-
before := r.initialSelected(m.Path)
1599-
if before == m.Version {
1600-
continue // m was resolved, but not changed
1601-
}
1599+
// Collect changes to explicit requirements in go.mod.
1600+
for _, req := range oldReqs {
1601+
path := req.Path
1602+
old := req.Version
1603+
new := r.buildListVersion[path]
1604+
if old != new {
1605+
changes[path] = change{path, old, new}
1606+
}
1607+
}
1608+
for _, req := range newReqs {
1609+
path := req.Path
1610+
old := r.initialVersion[path]
1611+
new := req.Version
1612+
if old != new {
1613+
changes[path] = change{path, old, new}
1614+
}
1615+
}
16021616

1603-
was := ""
1604-
if before != "" {
1605-
was = fmt.Sprintf(" (was %s)", before)
1606-
}
1607-
switch {
1608-
case q.isWildcard():
1609-
if q.matchesPath(m.Path) {
1610-
fmt.Fprintf(os.Stderr, "go: matched %v as %s %s%s\n", q, m.Path, m.Version, was)
1611-
} else {
1612-
fmt.Fprintf(os.Stderr, "go: matched %v in %s %s%s\n", q, m.Path, m.Version, was)
1613-
}
1614-
case q.matchesPackages:
1615-
fmt.Fprintf(os.Stderr, "go: found %v in %s %s%s\n", q, m.Path, m.Version, was)
1616-
default:
1617-
fmt.Fprintf(os.Stderr, "go: found %v in %s %s%s\n", q, m.Path, m.Version, was)
1618-
}
1617+
sortedChanges := make([]change, 0, len(changes))
1618+
for _, c := range changes {
1619+
sortedChanges = append(sortedChanges, c)
1620+
}
1621+
sort.Slice(sortedChanges, func(i, j int) bool {
1622+
return sortedChanges[i].path < sortedChanges[j].path
1623+
})
1624+
for _, c := range sortedChanges {
1625+
if c.old == "" {
1626+
fmt.Fprintf(os.Stderr, "go get: added %s %s\n", c.path, c.new)
1627+
} else if c.new == "none" || c.new == "" {
1628+
fmt.Fprintf(os.Stderr, "go get: removed %s %s\n", c.path, c.old)
1629+
} else if semver.Compare(c.new, c.old) > 0 {
1630+
fmt.Fprintf(os.Stderr, "go get: upgraded %s %s => %s\n", c.path, c.old, c.new)
1631+
} else {
1632+
fmt.Fprintf(os.Stderr, "go get: downgraded %s %s => %s\n", c.path, c.old, c.new)
16191633
}
16201634
}
16211635

1622-
// TODO(#33284): Also print relevant upgrades.
1636+
// TODO(golang.org/issue/33284): attribute changes to command line arguments.
1637+
// For modules matched by command line arguments, this probably isn't
1638+
// necessary, but it would be useful for unmatched direct dependencies of
1639+
// the main module.
16231640
}
16241641

16251642
// resolve records that module m must be at its indicated version (which may be
@@ -1700,6 +1717,14 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi
17001717
return true
17011718
}
17021719

1720+
func reqsFromGoMod(f *modfile.File) []module.Version {
1721+
reqs := make([]module.Version, len(f.Require))
1722+
for i, r := range f.Require {
1723+
reqs[i] = r.Mod
1724+
}
1725+
return reqs
1726+
}
1727+
17031728
// isNoSuchModuleVersion reports whether err indicates that the requested module
17041729
// does not exist at the requested version, either because the module does not
17051730
// exist at all or because it does not include that specific version.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# When adding a requirement, 'go get' prints a message for the requirement
2+
# and for changed explicit dependencies. 'go get' does not print messages
3+
# for changed indirect dependencies.
4+
go list -m all
5+
! stdout golang.org/x/text
6+
go get -d rsc.io/quote@v1.5.2
7+
stderr '^go get: added rsc.io/quote v1.5.2$'
8+
stderr '^go get: upgraded rsc.io/sampler v1.0.0 => v1.3.0$'
9+
! stderr '^go get.*golang.org/x/text'
10+
go list -m all
11+
stdout golang.org/x/text
12+
cmp go.mod go.mod.upgrade
13+
14+
# When removing a requirement, 'go get' prints a message for the requiremnent
15+
# and for changed explicit dependencies. 'go get' does not print messages
16+
# for changed indirect dependencies.
17+
go get -d rsc.io/sampler@none
18+
stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.3.0$'
19+
stderr '^go get: removed rsc.io/sampler v1.3.0$'
20+
! stderr '^go get.*golang.org/x/text'
21+
cmp go.mod go.mod.downgrade
22+
23+
# When removing or downgrading a requirement, 'go get' also prints a message
24+
# for explicit dependencies removed as a consequence.
25+
cp go.mod.usequote go.mod
26+
go get -d rsc.io/quote@v1.5.1
27+
stderr '^go get: downgraded rsc.io/quote v1.5.2 => v1.5.1$'
28+
stderr '^go get: removed usequote v0.0.0$'
29+
30+
-- go.mod --
31+
module m
32+
33+
go 1.16
34+
35+
require rsc.io/sampler v1.0.0
36+
-- go.sum --
37+
rsc.io/sampler v1.0.0 h1:SRJnjyQ07sAtq6G4RcfJEmz8JxqLyj3PoGXG2VhbDWo=
38+
rsc.io/sampler v1.0.0/go.mod h1:cqxpM3ZVz9VtirqxZPmrWzkQ+UkiNiGtkrN+B+i8kx8=
39+
-- go.mod.upgrade --
40+
module m
41+
42+
go 1.16
43+
44+
require (
45+
rsc.io/quote v1.5.2 // indirect
46+
rsc.io/sampler v1.3.0
47+
)
48+
-- go.mod.downgrade --
49+
module m
50+
51+
go 1.16
52+
53+
require (
54+
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
55+
rsc.io/quote v1.3.0 // indirect
56+
)
57+
-- go.mod.usequote --
58+
module m
59+
60+
go 1.16
61+
62+
require usequote v0.0.0
63+
64+
replace usequote => ./usequote
65+
-- usequote/go.mod --
66+
module usequote
67+
68+
go 1.16
69+
70+
require rsc.io/quote v1.5.2

0 commit comments

Comments
 (0)