Skip to content

Commit

Permalink
cmd/go/internal/modcmd: skip files with the "ignore" constraint in 'g…
Browse files Browse the repository at this point in the history
…o mod vendor'

'go mod vendor' already drops test files and testdata directories, so
users should not expect the vendored module to include unnecessary
files in general.

Files tagged "ignore" are typically only used to refresh or regenerate
source files within the module to be vendored, so users of that module
do not need them.

Fixes #31088

Change-Id: I1ce9545e9b37c8e779a1826a9d494ac29d2cbfb8
Reviewed-on: https://go-review.googlesource.com/c/go/+/172978
Run-TryBot: Bryan C. Mills <[email protected]>
Reviewed-by: Brad Fitzpatrick <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
Bryan C. Mills committed Apr 19, 2019
1 parent bdd7bb5 commit 7f16126
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 7 deletions.
38 changes: 31 additions & 7 deletions src/cmd/go/internal/modcmd/vendor.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/imports"
"cmd/go/internal/modload"
"cmd/go/internal/module"
)
Expand Down Expand Up @@ -100,7 +101,7 @@ func vendorPkg(vdir, pkg string) {
if src == "" {
fmt.Fprintf(os.Stderr, "internal error: no pkg for %s -> %s\n", pkg, realPath)
}
copyDir(dst, src, matchNonTest)
copyDir(dst, src, matchPotentialSourceFile)
if m := modload.PackageModule(realPath); m.Path != "" {
copyMetadata(m.Path, realPath, dst, src)
}
Expand Down Expand Up @@ -153,7 +154,7 @@ var metaPrefixes = []string{
}

// matchMetadata reports whether info is a metadata file.
func matchMetadata(info os.FileInfo) bool {
func matchMetadata(dir string, info os.FileInfo) bool {
name := info.Name()
for _, p := range metaPrefixes {
if strings.HasPrefix(name, p) {
Expand All @@ -163,13 +164,36 @@ func matchMetadata(info os.FileInfo) bool {
return false
}

// matchNonTest reports whether info is any non-test file (including non-Go files).
func matchNonTest(info os.FileInfo) bool {
return !strings.HasSuffix(info.Name(), "_test.go")
var anyTagsExceptIgnore = map[string]bool{"*": true}

// matchPotentialSourceFile reports whether info may be relevant to a build operation.
func matchPotentialSourceFile(dir string, info os.FileInfo) bool {
if strings.HasSuffix(info.Name(), "_test.go") {
return false
}
if strings.HasSuffix(info.Name(), ".go") {
f, err := os.Open(filepath.Join(dir, info.Name()))
if err != nil {
base.Fatalf("go mod vendor: %v", err)
}
defer f.Close()

content, err := imports.ReadImports(f, false, nil)
if err == nil && !imports.ShouldBuild(content, anyTagsExceptIgnore) {
// The file is explicitly tagged "ignore", so it can't affect the build.
// Leave it out.
return false
}
return true
}

// We don't know anything about this file, so optimistically assume that it is
// needed.
return true
}

// copyDir copies all regular files satisfying match(info) from src to dst.
func copyDir(dst, src string, match func(os.FileInfo) bool) {
func copyDir(dst, src string, match func(dir string, info os.FileInfo) bool) {
files, err := ioutil.ReadDir(src)
if err != nil {
base.Fatalf("go mod vendor: %v", err)
Expand All @@ -178,7 +202,7 @@ func copyDir(dst, src string, match func(os.FileInfo) bool) {
base.Fatalf("go mod vendor: %v", err)
}
for _, file := range files {
if file.IsDir() || !file.Mode().IsRegular() || !match(file) {
if file.IsDir() || !file.Mode().IsRegular() || !match(src, file) {
continue
}
r, err := os.Open(filepath.Join(src, file.Name()))
Expand Down
9 changes: 9 additions & 0 deletions src/cmd/go/testdata/script/mod_vendor.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ stdout 'src[\\/]w'
stderr 'src[\\/]vendor[\\/]w'

! exists vendor/x/testdata
! exists vendor/a/foo/bar/b/ignored.go
! exists vendor/a/foo/bar/b/main_test.go

exists vendor/a/foo/AUTHORS.txt
Expand Down Expand Up @@ -102,6 +103,14 @@ replace (

-- a/foo/bar/b/main.go --
package b
-- a/foo/bar/b/ignored.go --
// This file is intended for use with "go run"; it isn't really part of the package.

// +build ignore

package main

func main() {}
-- a/foo/bar/b/main_test.go --
package b

Expand Down

0 comments on commit 7f16126

Please sign in to comment.