Skip to content

Commit

Permalink
cmd/go/internal/modcmd: remove unused modules during -sync
Browse files Browse the repository at this point in the history
Fixes golang/go#24101.

Change-Id: I3900502372281515b49e98ed1465c2aa8d9a016b
Reviewed-on: https://go-review.googlesource.com/118877
Reviewed-by: Bryan C. Mills <bcmills@google.com>
  • Loading branch information
rsc committed Jun 15, 2018
1 parent 49c7bd7 commit 184f864
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
23 changes: 21 additions & 2 deletions vendor/cmd/go/internal/modcmd/mod.go
Expand Up @@ -236,15 +236,34 @@ func runMod(cmd *base.Command, args []string) {
needBuildList := *modFix

if *modSync || *modVendor || needBuildList {
var pkgs []string
if *modSync || *modVendor {
fmt.Println(vgo.ImportPaths([]string{"ALL"}))
pkgs = vgo.ImportPaths([]string{"ALL"})
} else {
vgo.LoadBuildList()
}
if *modSync {
// ImportPaths(ALL) already added missing modules.
// Remove unused modules.
panic("TODO sync unused")
used := map[module.Version]bool{vgo.Target: true}
for _, pkg := range pkgs {
used[vgo.PackageModule(pkg)] = true
}

inGoMod := make(map[string]bool)
for _, r := range vgo.ModFile().Require {
inGoMod[r.Mod.Path] = true
}

var keep []module.Version
for _, m := range vgo.BuildList() {
if used[m] {
keep = append(keep, m)
} else if *modV && inGoMod[m.Path] {
fmt.Fprintf(os.Stderr, "unused %s\n", m.Path)
}
}
vgo.SetBuildList(keep)
}
vgo.WriteGoMod()
if *modVendor {
Expand Down
6 changes: 6 additions & 0 deletions vendor/cmd/go/internal/vgo/load.go
Expand Up @@ -85,6 +85,12 @@ func BuildList() []module.Version {
return buildList
}

// SetBuildList sets the module build list.
// The caller is responsible for ensuring that the list is valid.
func SetBuildList(list []module.Version) {
buildList = list
}

// ImportMap returns the actual package import path
// for an import path found in source code.
// If the given import path does not appear in the source code
Expand Down
76 changes: 76 additions & 0 deletions vendor/cmd/go/vgo_test.go
Expand Up @@ -363,6 +363,82 @@ func TestVgoBadDomain(t *testing.T) {
tg.grepStderr("tcp.*nonexistent.rsc.io", "expected error for nonexistent.rsc.io")
}

func TestVgoSync(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()

write := func(name, text string) {
name = tg.path(name)
dir := filepath.Dir(name)
tg.must(os.MkdirAll(dir, 0777))
tg.must(ioutil.WriteFile(name, []byte(text), 0666))
}

write("m/go.mod", `
module m
require (
x.1 v1.0.0
y.1 v1.0.0
w.1 v1.2.0
)
replace x.1 v1.0.0 => ../x
replace y.1 v1.0.0 => ../y
replace z.1 v1.1.0 => ../z
replace z.1 v1.2.0 => ../z
replace w.1 v1.1.0 => ../w
replace w.1 v1.2.0 => ../w
`)
write("m/m.go", `
package m
import _ "x.1"
import _ "z.1/sub"
`)

write("w/go.mod", `
module w
`)
write("w/w.go", `
package w
`)

write("x/go.mod", `
module x
require w.1 v1.1.0
require z.1 v1.1.0
`)
write("x/x.go", `
package x
import _ "w.1"
`)

write("y/go.mod", `
module y
require z.1 v1.2.0
`)

write("z/go.mod", `
module z
`)
write("z/sub/sub.go", `
package sub
`)

tg.cd(tg.path("m"))
tg.run("-vgo", "mod", "-sync", "-v")
tg.grepStderr(`^unused y.1`, "need y.1 unused")
tg.grepStderrNot(`^unused [^y]`, "only y.1 should be unused")

tg.run("-vgo", "list", "-m")
tg.grepStdoutNot(`^y.1`, "y should be gone")
tg.grepStdout(`^w.1\s+v1.2.0`, "need w.1 to stay at v1.2.0")
tg.grepStdout(`^z.1\s+v1.2.0`, "need z.1 to stay at v1.2.0 even though y is gone")
}

func TestVgoVendor(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
Expand Down

0 comments on commit 184f864

Please sign in to comment.