aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/cmd
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-07-27 22:27:54 -0700
committerIan Lance Taylor <iant@golang.org>2020-08-01 11:21:40 -0700
commitf75af8c1464e948b5e166cf5ab09ebf0d82fc253 (patch)
tree3ba3299859b504bdeb477727471216bd094a0191 /libgo/go/cmd
parent75a23e59031fe673fc3b2e60fd1fe5f4c70ecb85 (diff)
downloadgcc-f75af8c1464e948b5e166cf5ab09ebf0d82fc253.zip
gcc-f75af8c1464e948b5e166cf5ab09ebf0d82fc253.tar.gz
gcc-f75af8c1464e948b5e166cf5ab09ebf0d82fc253.tar.bz2
libgo: update to go1.15rc1
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/245157
Diffstat (limited to 'libgo/go/cmd')
-rw-r--r--libgo/go/cmd/cgo/doc.go11
-rw-r--r--libgo/go/cmd/cgo/gcc.go30
-rw-r--r--libgo/go/cmd/cgo/out.go47
-rw-r--r--libgo/go/cmd/go/alldocs.go166
-rw-r--r--libgo/go/cmd/go/go_test.go2440
-rw-r--r--libgo/go/cmd/go/help_test.go2
-rw-r--r--libgo/go/cmd/go/internal/auth/auth.go4
-rw-r--r--libgo/go/cmd/go/internal/base/base.go25
-rw-r--r--libgo/go/cmd/go/internal/base/env.go14
-rw-r--r--libgo/go/cmd/go/internal/base/goflags.go12
-rw-r--r--libgo/go/cmd/go/internal/cache/cache.go2
-rw-r--r--libgo/go/cmd/go/internal/cfg/cfg.go11
-rw-r--r--libgo/go/cmd/go/internal/clean/clean.go33
-rw-r--r--libgo/go/cmd/go/internal/cmdflag/flag.go203
-rw-r--r--libgo/go/cmd/go/internal/envcmd/env.go1
-rw-r--r--libgo/go/cmd/go/internal/fmtcmd/fmt.go7
-rw-r--r--libgo/go/cmd/go/internal/generate/generate.go33
-rw-r--r--libgo/go/cmd/go/internal/get/get.go33
-rw-r--r--libgo/go/cmd/go/internal/get/vcs.go2
-rw-r--r--libgo/go/cmd/go/internal/help/help.go2
-rw-r--r--libgo/go/cmd/go/internal/help/helpdoc.go97
-rw-r--r--libgo/go/cmd/go/internal/list/list.go4
-rw-r--r--libgo/go/cmd/go/internal/load/pkg.go291
-rw-r--r--libgo/go/cmd/go/internal/load/test.go11
-rw-r--r--libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go70
-rw-r--r--libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go98
-rw-r--r--libgo/go/cmd/go/internal/modcmd/download.go3
-rw-r--r--libgo/go/cmd/go/internal/modcmd/vendor.go5
-rw-r--r--libgo/go/cmd/go/internal/modcmd/verify.go55
-rw-r--r--libgo/go/cmd/go/internal/modconv/convert_test.go4
-rw-r--r--libgo/go/cmd/go/internal/modfetch/cache.go28
-rw-r--r--libgo/go/cmd/go/internal/modfetch/codehost/codehost.go10
-rw-r--r--libgo/go/cmd/go/internal/modfetch/codehost/git.go5
-rw-r--r--libgo/go/cmd/go/internal/modfetch/codehost/git_test.go1
-rw-r--r--libgo/go/cmd/go/internal/modfetch/codehost/shell.go3
-rw-r--r--libgo/go/cmd/go/internal/modfetch/coderepo.go27
-rw-r--r--libgo/go/cmd/go/internal/modfetch/coderepo_test.go2
-rw-r--r--libgo/go/cmd/go/internal/modfetch/fetch.go102
-rw-r--r--libgo/go/cmd/go/internal/modfetch/proxy.go129
-rw-r--r--libgo/go/cmd/go/internal/modfetch/pseudo.go4
-rw-r--r--libgo/go/cmd/go/internal/modfetch/sumdb.go99
-rw-r--r--libgo/go/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv5
-rw-r--r--libgo/go/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go2
-rw-r--r--libgo/go/cmd/go/internal/modget/get.go50
-rw-r--r--libgo/go/cmd/go/internal/modload/build.go30
-rw-r--r--libgo/go/cmd/go/internal/modload/help.go18
-rw-r--r--libgo/go/cmd/go/internal/modload/import.go118
-rw-r--r--libgo/go/cmd/go/internal/modload/init.go254
-rw-r--r--libgo/go/cmd/go/internal/modload/load.go658
-rw-r--r--libgo/go/cmd/go/internal/modload/modfile.go164
-rw-r--r--libgo/go/cmd/go/internal/modload/mvs.go259
-rw-r--r--libgo/go/cmd/go/internal/modload/query.go90
-rw-r--r--libgo/go/cmd/go/internal/modload/query_test.go5
-rw-r--r--libgo/go/cmd/go/internal/modload/search.go45
-rw-r--r--libgo/go/cmd/go/internal/modload/vendor.go217
-rw-r--r--libgo/go/cmd/go/internal/mvs/mvs.go23
-rw-r--r--libgo/go/cmd/go/internal/renameio/renameio_test.go6
-rw-r--r--libgo/go/cmd/go/internal/search/search.go231
-rw-r--r--libgo/go/cmd/go/internal/str/path.go2
-rw-r--r--libgo/go/cmd/go/internal/test/flagdefs.go34
-rw-r--r--libgo/go/cmd/go/internal/test/flagdefs_test.go34
-rw-r--r--libgo/go/cmd/go/internal/test/genflags.go90
-rw-r--r--libgo/go/cmd/go/internal/test/test.go168
-rw-r--r--libgo/go/cmd/go/internal/test/testflag.go480
-rw-r--r--libgo/go/cmd/go/internal/version/version.go6
-rw-r--r--libgo/go/cmd/go/internal/vet/vet.go8
-rw-r--r--libgo/go/cmd/go/internal/vet/vetflag.go163
-rw-r--r--libgo/go/cmd/go/internal/web/api.go17
-rw-r--r--libgo/go/cmd/go/internal/web/http.go40
-rw-r--r--libgo/go/cmd/go/internal/work/action.go2
-rw-r--r--libgo/go/cmd/go/internal/work/build.go5
-rw-r--r--libgo/go/cmd/go/internal/work/build_test.go2
-rw-r--r--libgo/go/cmd/go/internal/work/buildid.go4
-rw-r--r--libgo/go/cmd/go/internal/work/exec.go114
-rw-r--r--libgo/go/cmd/go/internal/work/gc.go27
-rw-r--r--libgo/go/cmd/go/internal/work/init.go37
-rw-r--r--libgo/go/cmd/go/internal/work/security.go3
-rw-r--r--libgo/go/cmd/go/internal/work/security_test.go2
-rw-r--r--libgo/go/cmd/go/internal/work/testgo.go33
-rw-r--r--libgo/go/cmd/go/main.go3
-rw-r--r--libgo/go/cmd/go/note_test.go4
-rw-r--r--libgo/go/cmd/go/proxy_test.go19
-rw-r--r--libgo/go/cmd/go/script_test.go483
-rw-r--r--libgo/go/cmd/go/testdata/example1_test.go23
-rw-r--r--libgo/go/cmd/go/testdata/example2_test.go21
-rw-r--r--libgo/go/cmd/go/testdata/generate/test1.go13
-rw-r--r--libgo/go/cmd/go/testdata/generate/test2.go10
-rw-r--r--libgo/go/cmd/go/testdata/generate/test3.go9
-rw-r--r--libgo/go/cmd/go/testdata/generate/test4.go10
-rw-r--r--libgo/go/cmd/go/testdata/mod/example.com_printversion_v0.1.0.txt6
-rw-r--r--libgo/go/cmd/go/testdata/mod/example.com_printversion_v1.0.0.txt6
-rw-r--r--libgo/go/cmd/go/testdata/norunexample/example_test.go11
-rw-r--r--libgo/go/cmd/go/testdata/norunexample/test_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/print_goroot.go14
-rw-r--r--libgo/go/cmd/go/testdata/rundir/sub/sub.go1
-rw-r--r--libgo/go/cmd/go/testdata/rundir/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/script/README24
-rw-r--r--libgo/go/cmd/go/testdata/script/build_gcflags.txt3
-rw-r--r--libgo/go/cmd/go/testdata/script/build_trimpath.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/cmd_import_error.txt2
-rw-r--r--libgo/go/cmd/go/testdata/script/gcflags_patterns.txt2
-rw-r--r--libgo/go/cmd/go/testdata/script/install_cross_gobin.txt9
-rw-r--r--libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/list_ambiguous_path.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/list_importmap.txt2
-rw-r--r--libgo/go/cmd/go/testdata/script/list_parse_err.txt36
-rw-r--r--libgo/go/cmd/go/testdata/script/list_test_imports.txt2
-rw-r--r--libgo/go/cmd/go/testdata/script/list_test_non_go_files.txt2
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_ambiguous_import.txt3
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_convert_dep.txt1
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_convert_git.txt17
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_dot.txt97
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_empty_err.txt8
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_fs_patterns.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_get_commit.txt3
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_get_main.txt15
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_get_tags.txt3
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_gonoproxy.txt15
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_goroot_errors.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_invalid_version.txt6
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_list_dir.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_list_replace_dir.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_list_std.txt10
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_proxy_list.txt14
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_readonly.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_replace_import.txt5
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_retention.txt12
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_sumdb_proxy.txt17
-rw-r--r--libgo/go/cmd/go/testdata/script/noncanonical_import.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/script_wait.txt7
-rw-r--r--libgo/go/cmd/go/testdata/script/test_cache_inputs.txt21
-rw-r--r--libgo/go/cmd/go/testdata/script/version.txt27
-rw-r--r--libgo/go/cmd/go/testdata/script/vet_flags.txt58
-rw-r--r--libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go1
-rw-r--r--libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go1
-rw-r--r--libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/cgotest/m.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/coverasm/p.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/coverasm/p.s2
-rw-r--r--libgo/go/cmd/go/testdata/src/coverasm/p_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/coverbad/p.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/coverbad/p1.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/coverbad/p_test.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdep/p.go6
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdep/p1/p1.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdep/p_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdep2/p1/p.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdep2/p1/p_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdep2/p2/p2.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdot1/p.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdot2/p.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/coverdot2/p_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkg/pkg.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtest/pkg.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtest/test_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgxtest/pkg.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/test/test_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/testxtest/test_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/testxtest/xtest_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/xtest/xtest_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/exclude/empty/x.txt0
-rw-r--r--libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/exclude/x.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/exclude/x_linux.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/failfast_test.go62
-rw-r--r--libgo/go/cmd/go/testdata/src/hello/hello.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/my.pkg/main/main.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/my.pkg/pkg.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/skipper/skip_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/testlist/bench_test.go14
-rw-r--r--libgo/go/cmd/go/testdata/src/testlist/example_test.go21
-rw-r--r--libgo/go/cmd/go/testdata/src/testlist/test_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/bad.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/dir1/dir1.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/good.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/hello/hello.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/hello/hello_test.go12
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/hello/hellox_test.go12
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/subdir/bad.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/subdir/good.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/vendor/p/p.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/vendor/q/q.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/vendor/strings/msg.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/x/invalid/invalid.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/x/vendor/p/p.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/x/vendor/p/p/p.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/x/vendor/r/r.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/vend/x/x.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/vetcycle/p.go13
-rw-r--r--libgo/go/cmd/go/testdata/src/vetfail/p1/p1.go9
-rw-r--r--libgo/go/cmd/go/testdata/src/vetfail/p2/p2.go6
-rw-r--r--libgo/go/cmd/go/testdata/src/vetfail/p2/p2_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/vetpkg/a_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/vetpkg/b.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/vetpkg/c.go9
-rw-r--r--libgo/go/cmd/go/testdata/src/xtestonly/f.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/xtestonly/f_test.go12
-rw-r--r--libgo/go/cmd/go/testdata/standalone_benchmark_test.go6
-rw-r--r--libgo/go/cmd/go/testdata/standalone_fail_sub_test.go8
-rw-r--r--libgo/go/cmd/go/testdata/standalone_main_normal_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/standalone_main_wrong_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/standalone_parallel_sub_test.go14
-rw-r--r--libgo/go/cmd/go/testdata/standalone_sub_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/standalone_test.go6
-rw-r--r--libgo/go/cmd/go/testdata/standalone_testmain_flag_test.go29
-rw-r--r--libgo/go/cmd/go/testdata/testcover/pkg1/a.go7
-rw-r--r--libgo/go/cmd/go/testdata/testcover/pkg2/a.go7
-rw-r--r--libgo/go/cmd/go/testdata/testcover/pkg2/a_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/testcover/pkg3/a.go7
-rw-r--r--libgo/go/cmd/go/testdata/testcover/pkg3/a_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/testcover/pkg4/a.go5
-rw-r--r--libgo/go/cmd/go/testdata/testcover/pkg4/a_test.go9
-rw-r--r--libgo/go/cmd/go/testdata/testimport/p.go3
-rw-r--r--libgo/go/cmd/go/testdata/testimport/p1/p1.go3
-rw-r--r--libgo/go/cmd/go/testdata/testimport/p2/p2.go3
-rw-r--r--libgo/go/cmd/go/testdata/testimport/p_test.go13
-rw-r--r--libgo/go/cmd/go/testdata/testimport/x_test.go15
-rw-r--r--libgo/go/cmd/go/testdata/testinternal/p.go3
-rw-r--r--libgo/go/cmd/go/testdata/testinternal2/p.go3
-rw-r--r--libgo/go/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go1
-rw-r--r--libgo/go/cmd/go/testdata/testinternal3/t.go3
-rw-r--r--libgo/go/cmd/go/testdata/testinternal4/src/p/p.go6
-rw-r--r--libgo/go/cmd/go/testdata/testinternal4/src/q/internal/x/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/testinternal4/src/q/j/j.go3
-rw-r--r--libgo/go/cmd/go/testdata/testonly/p_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/testonly2/t.go6
-rw-r--r--libgo/go/cmd/go/testdata/testvendor/src/p/p.go6
-rw-r--r--libgo/go/cmd/go/testdata/testvendor/src/q/vendor/x/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/testvendor/src/q/y/y.go3
-rw-r--r--libgo/go/cmd/go/testdata/testvendor/src/q/z/z.go3
-rw-r--r--libgo/go/cmd/go/testdata/testvendor2/src/p/p.go3
-rw-r--r--libgo/go/cmd/go/testdata/testvendor2/vendor/x/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/timeoutbench_test.go10
-rw-r--r--libgo/go/cmd/go/vendor_test.go412
-rw-r--r--libgo/go/cmd/gofmt/gofmt.go64
-rw-r--r--libgo/go/cmd/gofmt/internal.go8
-rw-r--r--libgo/go/cmd/internal/objabi/autotype.go2
-rw-r--r--libgo/go/cmd/internal/objabi/funcdata.go28
-rw-r--r--libgo/go/cmd/internal/objabi/head.go2
-rw-r--r--libgo/go/cmd/internal/objabi/reloctype.go2
-rw-r--r--libgo/go/cmd/internal/objabi/stack.go2
-rw-r--r--libgo/go/cmd/internal/objabi/symkind.go2
-rw-r--r--libgo/go/cmd/internal/objabi/symkind_string.go24
-rw-r--r--libgo/go/cmd/internal/objabi/util.go19
-rw-r--r--libgo/go/cmd/internal/sys/supported.go11
-rw-r--r--libgo/go/cmd/vet/main.go4
251 files changed, 4177 insertions, 5675 deletions
diff --git a/libgo/go/cmd/cgo/doc.go b/libgo/go/cmd/cgo/doc.go
index 8c3bf81..ca18c45 100644
--- a/libgo/go/cmd/cgo/doc.go
+++ b/libgo/go/cmd/cgo/doc.go
@@ -413,7 +413,7 @@ type in Go are instead represented by a uintptr. Those include:
jobjectArray
jweak
-3. The EGLDisplay type from the EGL API.
+3. The EGLDisplay and EGLConfig types from the EGL API.
These types are uintptr on the Go side because they would otherwise
confuse the Go garbage collector; they are sometimes not really
@@ -429,11 +429,16 @@ from Go 1.9 and earlier, use the cftype or jni rewrites in the Go fix tool:
It will replace nil with 0 in the appropriate places.
-The EGLDisplay case were introduced in Go 1.12. Use the egl rewrite
+The EGLDisplay case was introduced in Go 1.12. Use the egl rewrite
to auto-update code from Go 1.11 and earlier:
go tool fix -r egl <pkg>
+The EGLConfig case was introduced in Go 1.15. Use the eglconf rewrite
+to auto-update code from Go 1.14 and earlier:
+
+ go tool fix -r eglconf <pkg>
+
Using cgo directly
Usage:
@@ -985,7 +990,7 @@ produces a file named a.out, even if cmd/link does so by invoking the host
linker in external linking mode.
By default, cmd/link will decide the linking mode as follows: if the only
-packages using cgo are those on a whitelist of standard library
+packages using cgo are those on a list of known standard library
packages (net, os/user, runtime/cgo), cmd/link will use internal linking
mode. Otherwise, there are non-standard cgo packages involved, and cmd/link
will use external linking mode. The first rule means that a build of
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go
index e389729..249cfe4 100644
--- a/libgo/go/cmd/cgo/gcc.go
+++ b/libgo/go/cmd/cgo/gcc.go
@@ -200,6 +200,9 @@ func (p *Package) Translate(f *File) {
numTypedefs = len(p.typedefs)
// Also ask about any typedefs we've seen so far.
for _, info := range p.typedefList {
+ if f.Name[info.typedef] != nil {
+ continue
+ }
n := &Name{
Go: info.typedef,
C: info.typedef,
@@ -351,7 +354,7 @@ func (p *Package) guessKinds(f *File) []*Name {
// void __cgo_f_xxx_5(void) { static const char __cgo_undefined__5[] = (name); }
//
// If we see an error at not-declared:xxx, the corresponding name is not declared.
- // If we see an error at not-type:xxx, the corresponding name is a type.
+ // If we see an error at not-type:xxx, the corresponding name is not a type.
// If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
// If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
// If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
@@ -728,6 +731,9 @@ func (p *Package) prepareNames(f *File) {
}
}
p.mangleName(n)
+ if n.Kind == "type" && typedef[n.Mangle] == nil {
+ typedef[n.Mangle] = n.Type
+ }
}
}
@@ -1366,6 +1372,9 @@ func (p *Package) rewriteRef(f *File) {
if *godefs {
// Substitute definition for mangled type name.
+ if r.Name.Type != nil && r.Name.Kind == "type" {
+ expr = r.Name.Type.Go
+ }
if id, ok := expr.(*ast.Ident); ok {
if t := typedef[id.Name]; t != nil {
expr = t.Go
@@ -1431,9 +1440,7 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
r.Context = ctxType
if r.Name.Type == nil {
error_(r.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
- break
}
- expr = r.Name.Type.Go
break
}
error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
@@ -1490,9 +1497,7 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
// Okay - might be new(T)
if r.Name.Type == nil {
error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
- break
}
- expr = r.Name.Type.Go
case "var":
expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
case "macro":
@@ -1511,8 +1516,6 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
// Use of C.enum_x, C.struct_x or C.union_x without C definition.
// GCC won't raise an error when using pointers to such unknown types.
error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
- } else {
- expr = r.Name.Type.Go
}
default:
if r.Name.Kind == "func" {
@@ -3036,8 +3039,9 @@ func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool {
return ok && st.StructName == ""
}
-// badPointerTypedef reports whether t is a C typedef that should not be considered a pointer in Go.
-// A typedef is bad if C code sometimes stores non-pointers in this type.
+// badPointerTypedef reports whether dt is a C typedef that should not be
+// considered a pointer in Go. A typedef is bad if C code sometimes stores
+// non-pointers in this type.
// TODO: Currently our best solution is to find these manually and list them as
// they come up. A better solution is desired.
func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
@@ -3047,7 +3051,7 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
if c.badJNI(dt) {
return true
}
- if c.badEGLDisplay(dt) {
+ if c.badEGLType(dt) {
return true
}
return false
@@ -3186,11 +3190,11 @@ func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool {
return false
}
-func (c *typeConv) badEGLDisplay(dt *dwarf.TypedefType) bool {
- if dt.Name != "EGLDisplay" {
+func (c *typeConv) badEGLType(dt *dwarf.TypedefType) bool {
+ if dt.Name != "EGLDisplay" && dt.Name != "EGLConfig" {
return false
}
- // Check that the typedef is "typedef void *EGLDisplay".
+ // Check that the typedef is "typedef void *<name>".
if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
if _, ok := ptr.Type.(*dwarf.VoidType); ok {
return true
diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go
index 4d66e1b..a5a22c8 100644
--- a/libgo/go/cmd/cgo/out.go
+++ b/libgo/go/cmd/cgo/out.go
@@ -22,6 +22,7 @@ import (
"regexp"
"sort"
"strings"
+ "unicode"
)
var (
@@ -102,6 +103,11 @@ func (p *Package) writeDefs() {
typedefNames := make([]string, 0, len(typedef))
for name := range typedef {
+ if name == "_Ctype_void" {
+ // We provide an appropriate declaration for
+ // _Ctype_void below (#39877).
+ continue
+ }
typedefNames = append(typedefNames, name)
}
sort.Strings(typedefNames)
@@ -807,6 +813,28 @@ func (p *Package) packedAttribute() string {
return s + "))"
}
+// exportParamName returns the value of param as it should be
+// displayed in a c header file. If param contains any non-ASCII
+// characters, this function will return the character p followed by
+// the value of position; otherwise, this function will return the
+// value of param.
+func exportParamName(param string, position int) string {
+ if param == "" {
+ return fmt.Sprintf("p%d", position)
+ }
+
+ pname := param
+
+ for i := 0; i < len(param); i++ {
+ if param[i] > unicode.MaxASCII {
+ pname = fmt.Sprintf("p%d", position)
+ break
+ }
+ }
+
+ return pname
+}
+
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
@@ -920,42 +948,45 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
if i > 0 || fn.Recv != nil {
s += ", "
}
- s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i)
+ s += fmt.Sprintf("%s %s", p.cgoType(atype).C, exportParamName(aname, i))
})
s += ")"
if len(exp.Doc) > 0 {
fmt.Fprintf(fgcch, "\n%s", exp.Doc)
+ if !strings.HasSuffix(exp.Doc, "\n") {
+ fmt.Fprint(fgcch, "\n")
+ }
}
- fmt.Fprintf(fgcch, "\nextern %s;\n", s)
+ fmt.Fprintf(fgcch, "extern %s;\n", s)
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int, __SIZE_TYPE__);\n", cPrefix, exp.ExpName)
fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD")
fmt.Fprintf(fgcc, "\n%s\n", s)
fmt.Fprintf(fgcc, "{\n")
fmt.Fprintf(fgcc, "\t__SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done();\n")
- fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute())
+ fmt.Fprintf(fgcc, "\t%s %v _cgo_a;\n", ctype, p.packedAttribute())
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
}
if fn.Recv != nil {
- fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
+ fmt.Fprintf(fgcc, "\t_cgo_a.recv = recv;\n")
}
forFieldList(fntype.Params,
func(i int, aname string, atype ast.Expr) {
- fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
+ fmt.Fprintf(fgcc, "\t_cgo_a.p%d = %s;\n", i, exportParamName(aname, i))
})
fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
- fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off)
+ fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &_cgo_a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off)
fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n")
fmt.Fprintf(fgcc, "\t_cgo_release_context(_cgo_ctxt);\n")
if gccResult != "void" {
if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 {
- fmt.Fprintf(fgcc, "\treturn a.r0;\n")
+ fmt.Fprintf(fgcc, "\treturn _cgo_a.r0;\n")
} else {
forFieldList(fntype.Results,
func(i int, aname string, atype ast.Expr) {
- fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
+ fmt.Fprintf(fgcc, "\tr.r%d = _cgo_a.r%d;\n", i, i)
})
fmt.Fprintf(fgcc, "\treturn r;\n")
}
diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go
index c2678c3..68bad3c 100644
--- a/libgo/go/cmd/go/alldocs.go
+++ b/libgo/go/cmd/go/alldocs.go
@@ -35,23 +35,24 @@
//
// Additional help topics:
//
-// buildmode build modes
-// c calling between Go and C
-// cache build and test caching
-// environment environment variables
-// filetype file types
-// go.mod the go.mod file
-// gopath GOPATH environment variable
-// gopath-get legacy GOPATH go get
-// goproxy module proxy protocol
-// importpath import path syntax
-// modules modules, module versions, and more
-// module-get module-aware go get
-// module-auth module authentication using go.sum
-// module-private module configuration for non-public modules
-// packages package lists and patterns
-// testflag testing flags
-// testfunc testing functions
+// buildconstraint build constraints
+// buildmode build modes
+// c calling between Go and C
+// cache build and test caching
+// environment environment variables
+// filetype file types
+// go.mod the go.mod file
+// gopath GOPATH environment variable
+// gopath-get legacy GOPATH go get
+// goproxy module proxy protocol
+// importpath import path syntax
+// modules modules, module versions, and more
+// module-get module-aware go get
+// module-auth module authentication using go.sum
+// module-private module configuration for non-public modules
+// packages package lists and patterns
+// testflag testing flags
+// testfunc testing functions
//
// Use "go help <topic>" for more information about that topic.
//
@@ -547,6 +548,9 @@
// tag "generate" so that files may be examined by go generate but ignored
// during build.
//
+// For packages with invalid code, generate processes only source files with a
+// valid package clause.
+//
// If any generator returns an error exit status, "go generate" skips
// all further processing for that package.
//
@@ -657,7 +661,10 @@
// this automatically as well.
//
// The -insecure flag permits fetching from repositories and resolving
-// custom domains using insecure schemes such as HTTP. Use with caution.
+// custom domains using insecure schemes such as HTTP. Use with caution. The
+// GOINSECURE environment variable is usually a better alternative, since it
+// provides control over which modules may be retrieved using an insecure scheme.
+// See 'go help environment' for details.
//
// The second step is to download (if needed), build, and install
// the named packages.
@@ -1017,7 +1024,8 @@
//
// Download downloads the named modules, which can be module patterns selecting
// dependencies of the main module or module queries of the form path@version.
-// With no arguments, download applies to all dependencies of the main module.
+// With no arguments, download applies to all dependencies of the main module
+// (equivalent to 'go mod download all').
//
// The go command will automatically download modules as needed during ordinary
// execution. The "go mod download" command is useful mainly for pre-filling
@@ -1305,10 +1313,10 @@
// and its test source files to identify significant problems. If go vet
// finds any problems, go test reports those and does not run the test
// binary. Only a high-confidence subset of the default go vet checks are
-// used. That subset is: 'atomic', 'bool', 'buildtags', 'nilfunc', and
-// 'printf'. You can see the documentation for these and other vet tests
-// via "go doc cmd/vet". To disable the running of go vet, use the
-// -vet=off flag.
+// used. That subset is: 'atomic', 'bool', 'buildtags', 'errorsas',
+// 'ifaceassert', 'nilfunc', 'printf', and 'stringintconv'. You can see
+// the documentation for these and other vet tests via "go doc cmd/vet".
+// To disable the running of go vet, use the -vet=off flag.
//
// All test output and summary lines are printed to the go command's
// standard output, even if the test printed them to its own standard
@@ -1470,6 +1478,95 @@
// See also: go fmt, go fix.
//
//
+// Build constraints
+//
+// A build constraint, also known as a build tag, is a line comment that begins
+//
+// // +build
+//
+// that lists the conditions under which a file should be included in the package.
+// Constraints may appear in any kind of source file (not just Go), but
+// they must appear near the top of the file, preceded
+// only by blank lines and other line comments. These rules mean that in Go
+// files a build constraint must appear before the package clause.
+//
+// To distinguish build constraints from package documentation, a series of
+// build constraints must be followed by a blank line.
+//
+// A build constraint is evaluated as the OR of space-separated options.
+// Each option evaluates as the AND of its comma-separated terms.
+// Each term consists of letters, digits, underscores, and dots.
+// A term may be negated with a preceding !.
+// For example, the build constraint:
+//
+// // +build linux,386 darwin,!cgo
+//
+// corresponds to the boolean formula:
+//
+// (linux AND 386) OR (darwin AND (NOT cgo))
+//
+// A file may have multiple build constraints. The overall constraint is the AND
+// of the individual constraints. That is, the build constraints:
+//
+// // +build linux darwin
+// // +build amd64
+//
+// corresponds to the boolean formula:
+//
+// (linux OR darwin) AND amd64
+//
+// During a particular build, the following words are satisfied:
+//
+// - the target operating system, as spelled by runtime.GOOS, set with the
+// GOOS environment variable.
+// - the target architecture, as spelled by runtime.GOARCH, set with the
+// GOARCH environment variable.
+// - the compiler being used, either "gc" or "gccgo"
+// - "cgo", if the cgo command is supported (see CGO_ENABLED in
+// 'go help environment').
+// - a term for each Go major release, through the current version:
+// "go1.1" from Go version 1.1 onward, "go1.12" from Go 1.12, and so on.
+// - any additional tags given by the -tags flag (see 'go help build').
+//
+// There are no separate build tags for beta or minor releases.
+//
+// If a file's name, after stripping the extension and a possible _test suffix,
+// matches any of the following patterns:
+// *_GOOS
+// *_GOARCH
+// *_GOOS_GOARCH
+// (example: source_windows_amd64.go) where GOOS and GOARCH represent
+// any known operating system and architecture values respectively, then
+// the file is considered to have an implicit build constraint requiring
+// those terms (in addition to any explicit constraints in the file).
+//
+// Using GOOS=android matches build tags and files as for GOOS=linux
+// in addition to android tags and files.
+//
+// Using GOOS=illumos matches build tags and files as for GOOS=solaris
+// in addition to illumos tags and files.
+//
+// To keep a file from being considered for the build:
+//
+// // +build ignore
+//
+// (any other unsatisfied word will work as well, but "ignore" is conventional.)
+//
+// To build a file only when using cgo, and only on Linux and OS X:
+//
+// // +build linux,cgo darwin,cgo
+//
+// Such a file is usually paired with another file implementing the
+// default functionality for other systems, which in this case would
+// carry the constraint:
+//
+// // +build !linux,!darwin !cgo
+//
+// Naming a file dns_windows.go will cause it to be included only when
+// building the package for Windows; similarly, math_386.s will be included
+// only when building the package for 32-bit x86.
+//
+//
// Build modes
//
// The 'go build' and 'go install' commands take a -buildmode argument which
@@ -1603,6 +1700,8 @@
// GOCACHE
// The directory where the go command will store cached
// information for reuse in future builds.
+// GOMODCACHE
+// The directory where the go command will store downloaded modules.
// GODEBUG
// Enable various debugging facilities. See 'go doc runtime'
// for details.
@@ -1620,6 +1719,9 @@
// Comma-separated list of glob patterns (in the syntax of Go's path.Match)
// of module path prefixes that should always be fetched in an insecure
// manner. Only applies to dependencies that are being fetched directly.
+// Unlike the -insecure flag on 'go get', GOINSECURE does not disable
+// checksum database validation. GOPRIVATE or GONOSUMDB may be used
+// to achieve that.
// GOOS
// The operating system for which to compile code.
// Examples are linux, darwin, windows, netbsd.
@@ -2693,15 +2795,15 @@
// Go module mirror run by Google and fall back to a direct connection
// if the proxy reports that it does not have the module (HTTP error 404 or 410).
// See https://proxy.golang.org/privacy for the service's privacy policy.
-// If GOPROXY is set to the string "direct", downloads use a direct connection
-// to source control servers. Setting GOPROXY to "off" disallows downloading
-// modules from any source. Otherwise, GOPROXY is expected to be a comma-separated
-// list of the URLs of module proxies, in which case the go command will fetch
-// modules from those proxies. For each request, the go command tries each proxy
-// in sequence, only moving to the next if the current proxy returns a 404 or 410
-// HTTP response. The string "direct" may appear in the proxy list,
-// to cause a direct connection to be attempted at that point in the search.
-// Any proxies listed after "direct" are never consulted.
+//
+// If GOPROXY is set to the string "direct", downloads use a direct connection to
+// source control servers. Setting GOPROXY to "off" disallows downloading modules
+// from any source. Otherwise, GOPROXY is expected to be list of module proxy URLs
+// separated by either comma (,) or pipe (|) characters, which control error
+// fallback behavior. For each request, the go command tries each proxy in
+// sequence. If there is an error, the go command will try the next proxy in the
+// list if the error is a 404 or 410 HTTP response or if the current proxy is
+// followed by a pipe character, indicating it is safe to fall back on any error.
//
// The GOPRIVATE and GONOPROXY environment variables allow bypassing
// the proxy for selected modules. See 'go help module-private' for details.
diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go
index 40999f2..021930a 100644
--- a/libgo/go/cmd/go/go_test.go
+++ b/libgo/go/cmd/go/go_test.go
@@ -6,9 +6,9 @@ package main_test
import (
"bytes"
- "context"
"debug/elf"
"debug/macho"
+ "debug/pe"
"flag"
"fmt"
"go/format"
@@ -60,7 +60,7 @@ func init() {
canRun = false
case "darwin":
switch runtime.GOARCH {
- case "arm", "arm64":
+ case "arm64":
canRun = false
}
case "linux":
@@ -113,12 +113,6 @@ var testGo string
var testTmpDir string
var testBin string
-// testCtx is canceled when the test binary is about to time out.
-//
-// If https://golang.org/issue/28135 is accepted, uses of this variable in test
-// functions should be replaced by t.Context().
-var testCtx = context.Background()
-
// The TestMain function creates a go command for testing purposes and
// deletes it after the tests have been run.
func TestMain(m *testing.M) {
@@ -130,23 +124,9 @@ func TestMain(m *testing.M) {
fmt.Printf("SKIP\n")
return
}
- os.Unsetenv("GOROOT_FINAL")
flag.Parse()
- timeoutFlag := flag.Lookup("test.timeout")
- if timeoutFlag != nil {
- // TODO(golang.org/issue/28147): The go command does not pass the
- // test.timeout flag unless either -timeout or -test.timeout is explicitly
- // set on the command line.
- if d := timeoutFlag.Value.(flag.Getter).Get().(time.Duration); d != 0 {
- aBitShorter := d * 95 / 100
- var cancel context.CancelFunc
- testCtx, cancel = context.WithTimeout(testCtx, aBitShorter)
- defer cancel()
- }
- }
-
if *proxyAddr != "" {
StartProxy()
select {}
@@ -198,6 +178,12 @@ func TestMain(m *testing.M) {
return strings.TrimSpace(string(out))
}
testGOROOT = goEnv("GOROOT")
+ os.Setenv("TESTGO_GOROOT", testGOROOT)
+ // Ensure that GOROOT is set explicitly.
+ // Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
+ // yet been moved to its final location, programs that invoke runtime.GOROOT
+ // may accidentally use the wrong path.
+ os.Setenv("GOROOT", testGOROOT)
// The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
// toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
@@ -234,8 +220,10 @@ func TestMain(m *testing.M) {
}
testCC = strings.TrimSpace(string(out))
- if out, err := exec.Command(testGo, "env", "CGO_ENABLED").Output(); err != nil {
- fmt.Fprintf(os.Stderr, "running testgo failed: %v\n", err)
+ cmd := exec.Command(testGo, "env", "CGO_ENABLED")
+ cmd.Stderr = new(strings.Builder)
+ if out, err := cmd.Output(); err != nil {
+ fmt.Fprintf(os.Stderr, "running testgo failed: %v\n%s", err, cmd.Stderr)
canRun = false
} else {
canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out)))
@@ -317,7 +305,6 @@ var mtimeTick time.Duration = 1 * time.Second
type testgoData struct {
t *testing.T
temps []string
- wd string
env []string
tempdir string
ran bool
@@ -367,9 +354,6 @@ func (tg *testgoData) parallel() {
if tg.ran {
tg.t.Fatal("internal testsuite error: call to parallel after run")
}
- if tg.wd != "" {
- tg.t.Fatal("internal testsuite error: call to parallel after cd")
- }
for _, e := range tg.env {
if strings.HasPrefix(e, "GOROOT=") || strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "GOBIN=") {
val := e[strings.Index(e, "=")+1:]
@@ -392,24 +376,6 @@ func (tg *testgoData) pwd() string {
return wd
}
-// cd changes the current directory to the named directory. Note that
-// using this means that the test must not be run in parallel with any
-// other tests.
-func (tg *testgoData) cd(dir string) {
- tg.t.Helper()
- if tg.inParallel {
- tg.t.Fatal("internal testsuite error: changing directory when running in parallel")
- }
- if tg.wd == "" {
- tg.wd = tg.pwd()
- }
- abs, err := filepath.Abs(dir)
- tg.must(os.Chdir(dir))
- if err == nil {
- tg.setenv("PWD", abs)
- }
-}
-
// sleep sleeps for one tick, where a tick is a conservative estimate
// of how long it takes for a file modification to get a different
// mtime.
@@ -680,15 +646,6 @@ func (tg *testgoData) creatingTemp(path string) {
if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
}
- // If we have changed the working directory, make sure we have
- // an absolute path, because we are going to change directory
- // back before we remove the temporary.
- if !filepath.IsAbs(path) {
- if tg.wd == "" || strings.HasPrefix(tg.wd, testGOROOT) {
- tg.t.Fatalf("internal testsuite error: creatingTemp(%q) within GOROOT/src", path)
- }
- path = filepath.Join(tg.wd, path)
- }
tg.must(robustio.RemoveAll(path))
tg.temps = append(tg.temps, path)
}
@@ -788,21 +745,6 @@ func (tg *testgoData) wantExecutable(path, msg string) {
}
}
-// wantArchive fails if path is not an archive.
-func (tg *testgoData) wantArchive(path string) {
- tg.t.Helper()
- f, err := os.Open(path)
- if err != nil {
- tg.t.Fatal(err)
- }
- buf := make([]byte, 100)
- io.ReadFull(f, buf)
- f.Close()
- if !bytes.HasPrefix(buf, []byte("!<arch>\n")) {
- tg.t.Fatalf("file %s exists but is not an archive", path)
- }
-}
-
// isStale reports whether pkg is stale, and why
func (tg *testgoData) isStale(pkg string) (bool, string) {
tg.t.Helper()
@@ -857,16 +799,6 @@ var testWork = flag.Bool("testwork", false, "")
// cleanup cleans up a test that runs testgo.
func (tg *testgoData) cleanup() {
tg.t.Helper()
- if tg.wd != "" {
- wd, _ := os.Getwd()
- tg.t.Logf("ended in %s", wd)
-
- if err := os.Chdir(tg.wd); err != nil {
- // We are unlikely to be able to continue.
- fmt.Fprintln(os.Stderr, "could not restore working directory, crashing:", err)
- os.Exit(2)
- }
- }
if *testWork {
tg.t.Logf("TESTWORK=%s\n", tg.path("."))
return
@@ -883,10 +815,9 @@ func removeAll(dir string) error {
// module cache has 0444 directories;
// make them writable in order to remove content.
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return nil // ignore errors walking in file system
- }
- if info.IsDir() {
+ // chmod not only directories, but also things that we couldn't even stat
+ // due to permission errors: they may also be unreadable directories.
+ if err != nil || info.IsDir() {
os.Chmod(path, 0777)
}
return nil
@@ -1012,35 +943,6 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
}
-func TestInternalPackagesInGOROOTAreRespected(t *testing.T) {
- skipIfGccgo(t, "gccgo does not have GOROOT")
- tg := testgo(t)
- defer tg.cleanup()
- tg.runFail("build", "-v", "./testdata/testinternal")
- tg.grepBoth(`testinternal(\/|\\)p\.go\:3\:8\: use of internal package net/http/internal not allowed`, "wrong error message for testdata/testinternal")
-}
-
-func TestInternalPackagesOutsideGOROOTAreRespected(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.runFail("build", "-v", "./testdata/testinternal2")
- tg.grepBoth(`testinternal2(\/|\\)p\.go\:3\:8\: use of internal package .*internal/w not allowed`, "wrote error message for testdata/testinternal2")
-}
-
-func TestInternalPackageErrorsAreHandled(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("list", "./testdata/testinternal3")
-}
-
-func TestInternalCache(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testinternal4"))
- tg.runFail("build", "p")
- tg.grepStderr("internal", "did not fail to build p")
-}
-
// cmd/go: custom import path checking should not apply to Go packages without import comment.
func TestIssue10952(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
@@ -1128,6 +1030,7 @@ func TestGetGitDefaultBranch(t *testing.T) {
func TestAccidentalGitCheckout(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
testenv.MustHaveExecPath(t, "git")
+ testenv.MustHaveExecPath(t, "svn")
tg := testgo(t)
defer tg.cleanup()
@@ -1146,87 +1049,6 @@ func TestAccidentalGitCheckout(t *testing.T) {
}
}
-func TestRelativeImportsGoTest(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "./testdata/testimport")
-}
-
-func TestRelativeImportsGoTestDashI(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
-
- // don't let test -i overwrite runtime
- tg.wantNotStale("runtime", "", "must be non-stale before test -i")
-
- tg.run("test", "-i", "./testdata/testimport")
-}
-
-func TestRelativeImportsInCommandLinePackage(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- files, err := filepath.Glob("./testdata/testimport/*.go")
- tg.must(err)
- tg.run(append([]string{"test"}, files...)...)
-}
-
-func TestVersionControlErrorMessageIncludesCorrectDirectory(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/shadow/root1"))
- tg.runFail("get", "-u", "foo")
-
- // TODO(iant): We should not have to use strconv.Quote here.
- // The code in vcs.go should be changed so that it is not required.
- quoted := strconv.Quote(filepath.Join("testdata", "shadow", "root1", "src", "foo"))
- quoted = quoted[1 : len(quoted)-1]
-
- tg.grepStderr(regexp.QuoteMeta(quoted), "go get -u error does not mention shadow/root1/src/foo")
-}
-
-func TestInstallFailsWithNoBuildableFiles(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.setenv("CGO_ENABLED", "0")
- tg.runFail("install", "cgotest")
- tg.grepStderr("build constraints exclude all Go files", "go install cgotest did not report 'build constraints exclude all Go files'")
-}
-
-// Issue 21895
-func TestMSanAndRaceRequireCgo(t *testing.T) {
- if !canMSan && !canRace {
- t.Skip("skipping because both msan and the race detector are not supported")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempFile("triv.go", `package main; func main() {}`)
- tg.setenv("CGO_ENABLED", "0")
- if canRace {
- tg.runFail("install", "-race", "triv.go")
- tg.grepStderr("-race requires cgo", "did not correctly report that -race requires cgo")
- tg.grepStderrNot("-msan", "reported that -msan instead of -race requires cgo")
- }
- if canMSan {
- tg.runFail("install", "-msan", "triv.go")
- tg.grepStderr("-msan requires cgo", "did not correctly report that -msan requires cgo")
- tg.grepStderrNot("-race", "reported that -race instead of -msan requires cgo")
- }
-}
-
-func TestRelativeGOBINFail(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempFile("triv.go", `package main; func main() {}`)
- tg.cd(tg.path("."))
- tg.setenv("GOBIN", ".")
- tg.cd(tg.path("."))
- tg.runFail("install")
- tg.grepStderr("cannot install, GOBIN must be an absolute path", "go install must fail if $GOBIN is a relative path")
-}
-
func TestPackageMainTestCompilerFlags(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -1240,54 +1062,6 @@ func TestPackageMainTestCompilerFlags(t *testing.T) {
tg.grepStderr(`([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go`, "should have run compile -p p1 p1.go")
}
-// Issue 12690
-func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
- skipIfGccgo(t, "gccgo does not have GOROOT")
- tg := testgo(t)
- defer tg.cleanup()
-
- // Make sure the packages below are not stale.
- tg.wantNotStale("runtime", "", "must be non-stale before test runs")
- tg.wantNotStale("os", "", "must be non-stale before test runs")
- tg.wantNotStale("io", "", "must be non-stale before test runs")
-
- goroot := runtime.GOROOT()
- tg.setenv("GOROOT", goroot+"/")
-
- tg.wantNotStale("runtime", "", "with trailing slash in GOROOT, runtime listed as stale")
- tg.wantNotStale("os", "", "with trailing slash in GOROOT, os listed as stale")
- tg.wantNotStale("io", "", "with trailing slash in GOROOT, io listed as stale")
-}
-
-func TestGoGetNonPkg(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempDir("gobin")
- tg.setenv("GOPATH", tg.path("."))
- tg.setenv("GOBIN", tg.path("gobin"))
- tg.runFail("get", "-d", "golang.org/x/tools")
- tg.grepStderr("golang.org/x/tools: no Go files", "missing error")
- tg.runFail("get", "-d", "-u", "golang.org/x/tools")
- tg.grepStderr("golang.org/x/tools: no Go files", "missing error")
- tg.runFail("get", "-d", "golang.org/x/tools")
- tg.grepStderr("golang.org/x/tools: no Go files", "missing error")
-}
-
-func TestGoGetTestOnlyPkg(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempDir("gopath")
- tg.setenv("GOPATH", tg.path("gopath"))
- tg.run("get", "golang.org/x/tour/content...")
- tg.run("get", "-t", "golang.org/x/tour/content...")
-}
-
// Issue 4104.
func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
tooSlow(t)
@@ -1338,19 +1112,6 @@ func TestGoListCmdOnlyShowsCommands(t *testing.T) {
}
}
-func TestGoListDedupsPackages(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("list", "xtestonly", "./testdata/src/xtestonly/...")
- got := strings.TrimSpace(tg.getStdout())
- const want = "xtestonly"
- if got != want {
- t.Errorf("got %q; want %q", got, want)
- }
-}
-
func TestGoListDeps(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -1618,57 +1379,6 @@ func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
}
-// Issue 4186. go get cannot be used to download packages to $GOROOT.
-// Test that without GOPATH set, go get should fail.
-func TestGoGetIntoGOROOT(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.tempDir("src")
-
- // Fails because GOROOT=GOPATH
- tg.setenv("GOPATH", tg.path("."))
- tg.setenv("GOROOT", tg.path("."))
- tg.runFail("get", "-d", "github.com/golang/example/hello")
- tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
- tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
-
- // Fails because GOROOT=GOPATH after cleaning.
- tg.setenv("GOPATH", tg.path(".")+"/")
- tg.setenv("GOROOT", tg.path("."))
- tg.runFail("get", "-d", "github.com/golang/example/hello")
- tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
- tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
-
- tg.setenv("GOPATH", tg.path("."))
- tg.setenv("GOROOT", tg.path(".")+"/")
- tg.runFail("get", "-d", "github.com/golang/example/hello")
- tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
- tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
-
- // Fails because GOROOT=$HOME/go so default GOPATH unset.
- tg.tempDir("home/go")
- tg.setenv(homeEnvName(), tg.path("home"))
- tg.setenv("GOPATH", "")
- tg.setenv("GOROOT", tg.path("home/go"))
- tg.runFail("get", "-d", "github.com/golang/example/hello")
- tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
-
- tg.setenv(homeEnvName(), tg.path("home")+"/")
- tg.setenv("GOPATH", "")
- tg.setenv("GOROOT", tg.path("home/go"))
- tg.runFail("get", "-d", "github.com/golang/example/hello")
- tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
-
- tg.setenv(homeEnvName(), tg.path("home"))
- tg.setenv("GOPATH", "")
- tg.setenv("GOROOT", tg.path("home/go")+"/")
- tg.runFail("get", "-d", "github.com/golang/example/hello")
- tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
-}
-
func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
skipIfGccgo(t, "gccgo does not support -ldflags -X")
tooSlow(t)
@@ -1684,54 +1394,6 @@ func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
tg.grepStderr("^hello world", `ldflags -X "main.extern=hello world"' failed`)
}
-func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.makeTempdir()
- tg.cd(tg.path("."))
- tg.run("test", "-cpuprofile", "errors.prof", "errors")
- tg.wantExecutable("errors.test"+exeSuffix, "go test -cpuprofile did not create errors.test")
-}
-
-func TestGoTestCpuprofileDashOControlsBinaryLocation(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.makeTempdir()
- tg.cd(tg.path("."))
- tg.run("test", "-cpuprofile", "errors.prof", "-o", "myerrors.test"+exeSuffix, "errors")
- tg.wantExecutable("myerrors.test"+exeSuffix, "go test -cpuprofile -o myerrors.test did not create myerrors.test")
-}
-
-func TestGoTestMutexprofileLeavesBinaryBehind(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.makeTempdir()
- tg.cd(tg.path("."))
- tg.run("test", "-mutexprofile", "errors.prof", "errors")
- tg.wantExecutable("errors.test"+exeSuffix, "go test -mutexprofile did not create errors.test")
-}
-
-func TestGoTestMutexprofileDashOControlsBinaryLocation(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.makeTempdir()
- tg.cd(tg.path("."))
- tg.run("test", "-mutexprofile", "errors.prof", "-o", "myerrors.test"+exeSuffix, "errors")
- tg.wantExecutable("myerrors.test"+exeSuffix, "go test -mutexprofile -o myerrors.test did not create myerrors.test")
-}
-
func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
skipIfGccgo(t, "gccgo has no standard packages")
tooSlow(t)
@@ -1770,88 +1432,6 @@ func TestGoTestDashIDashOWritesBinary(t *testing.T) {
tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
}
-// Issue 4568.
-func TestSymlinksList(t *testing.T) {
- testenv.MustHaveSymlink(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.tempDir("src")
- tg.must(os.Symlink(tg.path("."), tg.path("src/dir1")))
- tg.tempFile("src/dir1/p.go", "package p")
- tg.setenv("GOPATH", tg.path("."))
- tg.cd(tg.path("src"))
- tg.run("list", "-f", "{{.Root}}", "dir1")
- if strings.TrimSpace(tg.getStdout()) != tg.path(".") {
- t.Error("confused by symlinks")
- }
-}
-
-// Issue 14054.
-func TestSymlinksVendor(t *testing.T) {
- testenv.MustHaveSymlink(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.tempDir("gopath/src/dir1/vendor/v")
- tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `v`\nfunc main(){}")
- tg.tempFile("gopath/src/dir1/vendor/v/v.go", "package v")
- tg.must(os.Symlink(tg.path("gopath/src/dir1"), tg.path("symdir1")))
- tg.setenv("GOPATH", tg.path("gopath"))
- tg.cd(tg.path("symdir1"))
- tg.run("list", "-f", "{{.Root}}", ".")
- if strings.TrimSpace(tg.getStdout()) != tg.path("gopath") {
- t.Error("list confused by symlinks")
- }
-
- // All of these should succeed, not die in vendor-handling code.
- tg.run("run", "p.go")
- tg.run("build")
- tg.run("install")
-}
-
-// Issue 15201.
-func TestSymlinksVendor15201(t *testing.T) {
- testenv.MustHaveSymlink(t)
-
- tg := testgo(t)
- defer tg.cleanup()
-
- tg.tempDir("gopath/src/x/y/_vendor/src/x")
- tg.must(os.Symlink("../../..", tg.path("gopath/src/x/y/_vendor/src/x/y")))
- tg.tempFile("gopath/src/x/y/w/w.go", "package w\nimport \"x/y/z\"\n")
- tg.must(os.Symlink("../_vendor/src", tg.path("gopath/src/x/y/w/vendor")))
- tg.tempFile("gopath/src/x/y/z/z.go", "package z\n")
-
- tg.setenv("GOPATH", tg.path("gopath/src/x/y/_vendor")+string(filepath.ListSeparator)+tg.path("gopath"))
- tg.cd(tg.path("gopath/src"))
- tg.run("list", "./...")
-}
-
-func TestSymlinksInternal(t *testing.T) {
- testenv.MustHaveSymlink(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempDir("gopath/src/dir1/internal/v")
- tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `dir1/internal/v`\nfunc main(){}")
- tg.tempFile("gopath/src/dir1/internal/v/v.go", "package v")
- tg.must(os.Symlink(tg.path("gopath/src/dir1"), tg.path("symdir1")))
- tg.setenv("GOPATH", tg.path("gopath"))
- tg.cd(tg.path("symdir1"))
- tg.run("list", "-f", "{{.Root}}", ".")
- if strings.TrimSpace(tg.getStdout()) != tg.path("gopath") {
- t.Error("list confused by symlinks")
- }
-
- // All of these should succeed, not die in internal-handling code.
- tg.run("run", "p.go")
- tg.run("build")
- tg.run("install")
-}
-
// Issue 4515.
func TestInstallWithTags(t *testing.T) {
tooSlow(t)
@@ -1880,52 +1460,6 @@ func TestInstallWithTags(t *testing.T) {
}
}
-// Issue 4773
-func TestCaseCollisions(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.tempDir("src/example/a/pkg")
- tg.tempDir("src/example/a/Pkg")
- tg.tempDir("src/example/b")
- tg.setenv("GOPATH", tg.path("."))
- tg.tempFile("src/example/a/a.go", `package p
- import (
- _ "example/a/pkg"
- _ "example/a/Pkg"
- )`)
- tg.tempFile("src/example/a/pkg/pkg.go", `package pkg`)
- tg.tempFile("src/example/a/Pkg/pkg.go", `package pkg`)
- tg.run("list", "-json", "example/a")
- tg.grepStdout("case-insensitive import collision", "go list -json example/a did not report import collision")
- tg.runFail("build", "example/a")
- tg.grepStderr("case-insensitive import collision", "go build example/a did not report import collision")
- tg.tempFile("src/example/b/file.go", `package b`)
- tg.tempFile("src/example/b/FILE.go", `package b`)
- f, err := os.Open(tg.path("src/example/b"))
- tg.must(err)
- names, err := f.Readdirnames(0)
- tg.must(err)
- tg.check(f.Close())
- args := []string{"list"}
- if len(names) == 2 {
- // case-sensitive file system, let directory read find both files
- args = append(args, "example/b")
- } else {
- // case-insensitive file system, list files explicitly on command line
- args = append(args, tg.path("src/example/b/file.go"), tg.path("src/example/b/FILE.go"))
- }
- tg.runFail(args...)
- tg.grepStderr("case-insensitive file name collision", "go list example/b did not report file name collision")
-
- tg.runFail("list", "example/a/pkg", "example/a/Pkg")
- tg.grepStderr("case-insensitive import collision", "go list example/a/pkg example/a/Pkg did not report import collision")
- tg.run("list", "-json", "-e", "example/a/pkg", "example/a/Pkg")
- tg.grepStdout("case-insensitive import collision", "go list -json -e example/a/pkg example/a/Pkg did not report import collision")
- tg.runFail("build", "example/a/pkg", "example/a/Pkg")
- tg.grepStderr("case-insensitive import collision", "go build example/a/pkg example/a/Pkg did not report import collision")
-}
-
// Issue 17451, 17662.
func TestSymlinkWarning(t *testing.T) {
tg := testgo(t)
@@ -1951,334 +1485,6 @@ func TestSymlinkWarning(t *testing.T) {
tg.grepStderr("ignoring symlink", "list should have reported symlink")
}
-// Issue 8181.
-func TestGoGetDashTIssue8181(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "-v", "-t", "github.com/rsc/go-get-issue-8181/a", "github.com/rsc/go-get-issue-8181/b")
- tg.run("list", "...")
- tg.grepStdout("x/build/gerrit", "missing expected x/build/gerrit")
-}
-
-func TestIssue11307(t *testing.T) {
- // go get -u was not working except in checkout directory
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "github.com/rsc/go-get-issue-11307")
- tg.run("get", "-u", "github.com/rsc/go-get-issue-11307") // was failing
-}
-
-func TestShadowingLogic(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tg := testgo(t)
- defer tg.cleanup()
- pwd := tg.pwd()
- sep := string(filepath.ListSeparator)
- tg.setenv("GOPATH", filepath.Join(pwd, "testdata", "shadow", "root1")+sep+filepath.Join(pwd, "testdata", "shadow", "root2"))
-
- // The math in root1 is not "math" because the standard math is.
- tg.run("list", "-f", "({{.ImportPath}}) ({{.ConflictDir}})", "./testdata/shadow/root1/src/math")
- pwdForwardSlash := strings.ReplaceAll(pwd, string(os.PathSeparator), "/")
- if !strings.HasPrefix(pwdForwardSlash, "/") {
- pwdForwardSlash = "/" + pwdForwardSlash
- }
- // The output will have makeImportValid applies, but we only
- // bother to deal with characters we might reasonably see.
- for _, r := range " :" {
- pwdForwardSlash = strings.ReplaceAll(pwdForwardSlash, string(r), "_")
- }
- want := "(_" + pwdForwardSlash + "/testdata/shadow/root1/src/math) (" + filepath.Join(runtime.GOROOT(), "src", "math") + ")"
- if strings.TrimSpace(tg.getStdout()) != want {
- t.Error("shadowed math is not shadowed; looking for", want)
- }
-
- // The foo in root1 is "foo".
- tg.run("list", "-f", "({{.ImportPath}}) ({{.ConflictDir}})", "./testdata/shadow/root1/src/foo")
- if strings.TrimSpace(tg.getStdout()) != "(foo) ()" {
- t.Error("unshadowed foo is shadowed")
- }
-
- // The foo in root2 is not "foo" because the foo in root1 got there first.
- tg.run("list", "-f", "({{.ImportPath}}) ({{.ConflictDir}})", "./testdata/shadow/root2/src/foo")
- want = "(_" + pwdForwardSlash + "/testdata/shadow/root2/src/foo) (" + filepath.Join(pwd, "testdata", "shadow", "root1", "src", "foo") + ")"
- if strings.TrimSpace(tg.getStdout()) != want {
- t.Error("shadowed foo is not shadowed; looking for", want)
- }
-
- // The error for go install should mention the conflicting directory.
- tg.runFail("install", "./testdata/shadow/root2/src/foo")
- want = "go install: no install location for " + filepath.Join(pwd, "testdata", "shadow", "root2", "src", "foo") + ": hidden by " + filepath.Join(pwd, "testdata", "shadow", "root1", "src", "foo")
- if strings.TrimSpace(tg.getStderr()) != want {
- t.Error("wrong shadowed install error; looking for", want)
- }
-}
-
-// Only succeeds if source order is preserved.
-func TestSourceFileNameOrderPreserved(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "testdata/example1_test.go", "testdata/example2_test.go")
-}
-
-// Check that coverage analysis works at all.
-// Don't worry about the exact numbers but require not 0.0%.
-func checkCoverage(tg *testgoData, data string) {
- tg.t.Helper()
- if regexp.MustCompile(`[^0-9]0\.0%`).MatchString(data) {
- tg.t.Error("some coverage results are 0.0%")
- }
-}
-
-func TestCoverageRuns(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-short", "-coverpkg=strings", "strings", "regexp")
- data := tg.getStdout() + tg.getStderr()
- tg.run("test", "-short", "-cover", "strings", "math", "regexp")
- data += tg.getStdout() + tg.getStderr()
- checkCoverage(tg, data)
-}
-
-func TestCoverageDotImport(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "-coverpkg=coverdot1,coverdot2", "coverdot2")
- data := tg.getStdout() + tg.getStderr()
- checkCoverage(tg, data)
-}
-
-func TestCoverageSyncAtomicImport(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "-short", "-cover", "-covermode=atomic", "-coverpkg=coverdep/p1", "coverdep")
-}
-
-func TestCoverageDepLoop(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- // coverdep2/p1's xtest imports coverdep2/p2 which imports coverdep2/p1.
- // Make sure that coverage on coverdep2/p2 recompiles coverdep2/p2.
- tg.run("test", "-short", "-cover", "coverdep2/p1")
- tg.grepStdout("coverage: 100.0% of statements", "expected 100.0% coverage")
-}
-
-func TestCoverageNoStatements(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-cover", "./testdata/testcover/pkg4")
- tg.grepStdout("[no statements]", "expected [no statements] for pkg4")
-}
-
-func TestCoverageErrorLine(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.setenv("GOTMPDIR", tg.tempdir)
-
- tg.runFail("test", "coverbad")
- tg.grepStderr(`coverbad[\\/]p\.go:4`, "did not find coverbad/p.go:4")
- if canCgo {
- tg.grepStderr(`coverbad[\\/]p1\.go:6`, "did not find coverbad/p1.go:6")
- }
- tg.grepStderrNot(regexp.QuoteMeta(tg.tempdir), "found temporary directory in error")
- stderr := tg.getStderr()
-
- tg.runFail("test", "-cover", "coverbad")
- stderr2 := tg.getStderr()
-
- // It's OK that stderr2 drops the character position in the error,
- // because of the //line directive (see golang.org/issue/22662).
- stderr = strings.ReplaceAll(stderr, "p.go:4:2:", "p.go:4:")
- if stderr != stderr2 {
- t.Logf("test -cover changed error messages:\nbefore:\n%s\n\nafter:\n%s", stderr, stderr2)
- t.Skip("golang.org/issue/22660")
- t.FailNow()
- }
-}
-
-func TestTestBuildFailureOutput(t *testing.T) {
- tooSlow(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- // Doesn't build, -x output should not claim to run test.
- tg.runFail("test", "-x", "coverbad")
- tg.grepStderrNot(`[\\/]coverbad\.test( |$)`, "claimed to run test")
-}
-
-func TestCoverageFunc(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- tg.run("test", "-outputdir="+tg.tempdir, "-coverprofile=cover.out", "coverasm")
- tg.run("tool", "cover", "-func="+tg.path("cover.out"))
- tg.grepStdout(`\tg\t*100.0%`, "did not find g 100% covered")
- tg.grepStdoutNot(`\tf\t*[0-9]`, "reported coverage for assembly function f")
-}
-
-// Issue 24588.
-func TestCoverageDashC(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "-c", "-o", tg.path("coverdep"), "-coverprofile="+tg.path("no/such/dir/cover.out"), "coverdep")
- tg.wantExecutable(tg.path("coverdep"), "go -test -c -coverprofile did not create executable")
-}
-
-func TestTestEmpty(t *testing.T) {
- if !canRace {
- t.Skip("no race detector")
- }
-
- wd, _ := os.Getwd()
- testdata := filepath.Join(wd, "testdata")
- for _, dir := range []string{"pkg", "test", "xtest", "pkgtest", "pkgxtest", "pkgtestxtest", "testxtest"} {
- t.Run(dir, func(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", testdata)
- tg.cd(filepath.Join(testdata, "src/empty/"+dir))
- tg.run("test", "-cover", "-coverpkg=.", "-race")
- })
- if testing.Short() {
- break
- }
- }
-}
-
-func TestNoGoError(t *testing.T) {
- wd, _ := os.Getwd()
- testdata := filepath.Join(wd, "testdata")
- for _, dir := range []string{"empty/test", "empty/xtest", "empty/testxtest", "exclude", "exclude/ignore", "exclude/empty"} {
- t.Run(dir, func(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", testdata)
- tg.cd(filepath.Join(testdata, "src"))
- tg.runFail("build", "./"+dir)
- var want string
- if strings.Contains(dir, "test") {
- want = "no non-test Go files in "
- } else if dir == "exclude" {
- want = "build constraints exclude all Go files in "
- } else {
- want = "no Go files in "
- }
- tg.grepStderr(want, "wrong reason for failure")
- })
- }
-}
-
-func TestTestRaceInstall(t *testing.T) {
- if !canRace {
- t.Skip("no race detector")
- }
- tooSlow(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- tg.tempDir("pkg")
- pkgdir := tg.path("pkg")
- tg.run("install", "-race", "-pkgdir="+pkgdir, "std")
- tg.run("test", "-race", "-pkgdir="+pkgdir, "-i", "-v", "empty/pkg")
- if tg.getStderr() != "" {
- t.Error("go test -i -race: rebuilds cached packages")
- }
-}
-
-func TestBuildDryRunWithCgo(t *testing.T) {
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempFile("foo.go", `package main
-
-/*
-#include <limits.h>
-*/
-import "C"
-
-func main() {
- println(C.INT_MAX)
-}`)
- tg.run("build", "-n", tg.path("foo.go"))
- tg.grepStderrNot(`os.Stat .* no such file or directory`, "unexpected stat of archive file")
-}
-
-func TestCgoDependsOnSyscall(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping test that removes $GOROOT/pkg/*_race in short mode")
- }
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
- if !canRace {
- t.Skip("skipping because race detector not supported")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
-
- files, err := filepath.Glob(filepath.Join(runtime.GOROOT(), "pkg", "*_race"))
- tg.must(err)
- for _, file := range files {
- tg.check(robustio.RemoveAll(file))
- }
- tg.tempFile("src/foo/foo.go", `
- package foo
- //#include <stdio.h>
- import "C"`)
- tg.setenv("GOPATH", tg.path("."))
- tg.run("build", "-race", "foo")
-}
-
func TestCgoShowsFullPathNames(t *testing.T) {
if !canCgo {
t.Skip("skipping because cgo not enabled")
@@ -2362,89 +1568,6 @@ func main() {
tg.run("run", tg.path("foo.go"))
}
-// "go test -c -test.bench=XXX errors" should not hang.
-// "go test -c" should also produce reproducible binaries.
-// "go test -c" should also appear to write a new binary every time,
-// even if it's really just updating the mtime on an existing up-to-date binary.
-func TestIssue6480(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.makeTempdir()
- tg.cd(tg.path("."))
- tg.run("test", "-c", "-test.bench=XXX", "errors")
- tg.run("test", "-c", "-o", "errors2.test", "errors")
-
- data1, err := ioutil.ReadFile("errors.test" + exeSuffix)
- tg.must(err)
- data2, err := ioutil.ReadFile("errors2.test") // no exeSuffix because -o above doesn't have it
- tg.must(err)
- if !bytes.Equal(data1, data2) {
- t.Fatalf("go test -c errors produced different binaries when run twice")
- }
-
- start := time.Now()
- tg.run("test", "-x", "-c", "-test.bench=XXX", "errors")
- tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly relinked up-to-date test binary")
- info, err := os.Stat("errors.test" + exeSuffix)
- if err != nil {
- t.Fatal(err)
- }
- start = truncateLike(start, info.ModTime())
- if info.ModTime().Before(start) {
- t.Fatalf("mtime of errors.test predates test -c command (%v < %v)", info.ModTime(), start)
- }
-
- start = time.Now()
- tg.run("test", "-x", "-c", "-o", "errors2.test", "errors")
- tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly relinked up-to-date test binary")
- info, err = os.Stat("errors2.test")
- if err != nil {
- t.Fatal(err)
- }
- start = truncateLike(start, info.ModTime())
- if info.ModTime().Before(start) {
- t.Fatalf("mtime of errors2.test predates test -c command (%v < %v)", info.ModTime(), start)
- }
-}
-
-// truncateLike returns the result of truncating t to the apparent precision of p.
-func truncateLike(t, p time.Time) time.Time {
- nano := p.UnixNano()
- d := 1 * time.Nanosecond
- for nano%int64(d) == 0 && d < 1*time.Second {
- d *= 10
- }
- for nano%int64(d) == 0 && d < 2*time.Second {
- d *= 2
- }
- return t.Truncate(d)
-}
-
-// cmd/cgo: undefined reference when linking a C-library using gccgo
-func TestIssue7573(t *testing.T) {
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
- testenv.MustHaveExecPath(t, "gccgo")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.tempFile("src/cgoref/cgoref.go", `
-package main
-// #cgo LDFLAGS: -L alibpath -lalib
-// void f(void) {}
-import "C"
-
-func main() { C.f() }`)
- tg.setenv("GOPATH", tg.path("."))
- tg.run("build", "-n", "-compiler", "gccgo", "cgoref")
- tg.grepStderr(`gccgo.*\-L [^ ]*alibpath \-lalib`, `no Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage`)
-}
-
func TestListTemplateContextFunction(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
@@ -2479,242 +1602,6 @@ func TestListTemplateContextFunction(t *testing.T) {
}
}
-func TestGoBuildTestOnly(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.tempFile("src/testonly/t_test.go", `package testonly`)
- tg.tempFile("src/testonly2/t.go", `package testonly2`)
- tg.cd(tg.path("src"))
-
- // Named explicitly, test-only packages should be reported as unbuildable/uninstallable,
- // even if there is a wildcard also matching.
- tg.runFail("build", "testonly", "testonly...")
- tg.grepStderr("no non-test Go files in", "go build ./xtestonly produced unexpected error")
- tg.runFail("install", "./testonly")
- tg.grepStderr("no non-test Go files in", "go install ./testonly produced unexpected error")
-
- // Named through a wildcards, the test-only packages should be silently ignored.
- tg.run("build", "testonly...")
- tg.run("install", "./testonly...")
-}
-
-func TestGoTestFooTestWorks(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "testdata/standalone_test.go")
-}
-
-func TestGoTestTestMainSeesTestingFlags(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "testdata/standalone_testmain_flag_test.go")
-}
-
-// Issue 22388
-func TestGoTestMainWithWrongSignature(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.runFail("test", "testdata/standalone_main_wrong_test.go")
- tg.grepStderr(`wrong signature for TestMain, must be: func TestMain\(m \*testing.M\)`, "detected wrong error message")
-}
-
-func TestGoTestMainAsNormalTest(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "testdata/standalone_main_normal_test.go")
- tg.grepBoth(okPattern, "go test did not say ok")
-}
-
-func TestGoTestXtestonlyWorks(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("clean", "-i", "xtestonly")
- tg.run("test", "xtestonly")
-}
-
-func TestGoTestBuildsAnXtestContainingOnlyNonRunnableExamples(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-v", "./testdata/norunexample")
- tg.grepStdout("File with non-runnable example was built.", "file with non-runnable example was not built")
-}
-
-func TestGoGenerateHandlesSimpleCommand(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("skipping because windows has no echo command")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("generate", "./testdata/generate/test1.go")
- tg.grepStdout("Success", "go generate ./testdata/generate/test1.go generated wrong output")
-}
-
-func TestGoGenerateHandlesCommandAlias(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("skipping because windows has no echo command")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("generate", "./testdata/generate/test2.go")
- tg.grepStdout("Now is the time for all good men", "go generate ./testdata/generate/test2.go generated wrong output")
-}
-
-func TestGoGenerateVariableSubstitution(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("skipping because windows has no echo command")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("generate", "./testdata/generate/test3.go")
- tg.grepStdout(runtime.GOARCH+" test3.go:7 pabc xyzp/test3.go/123", "go generate ./testdata/generate/test3.go generated wrong output")
-}
-
-func TestGoGenerateRunFlag(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("skipping because windows has no echo command")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("generate", "-run", "y.s", "./testdata/generate/test4.go")
- tg.grepStdout("yes", "go generate -run yes ./testdata/generate/test4.go did not select yes")
- tg.grepStdoutNot("no", "go generate -run yes ./testdata/generate/test4.go selected no")
-}
-
-func TestGoGenerateEnv(t *testing.T) {
- switch runtime.GOOS {
- case "plan9", "windows":
- t.Skipf("skipping because %s does not have the env command", runtime.GOOS)
- }
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.tempFile("env.go", "package main\n\n//go:generate env")
- tg.run("generate", tg.path("env.go"))
- for _, v := range []string{"GOARCH", "GOOS", "GOFILE", "GOLINE", "GOPACKAGE", "DOLLAR"} {
- tg.grepStdout("^"+v+"=", "go generate environment missing "+v)
- }
-}
-
-func TestGoGenerateXTestPkgName(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("skipping because windows has no echo command")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.tempFile("env_test.go", "package main_test\n\n//go:generate echo $GOPACKAGE")
- tg.run("generate", tg.path("env_test.go"))
- want := "main_test"
- if got := strings.TrimSpace(tg.getStdout()); got != want {
- t.Errorf("go generate in XTest file got package name %q; want %q", got, want)
- }
-}
-
-func TestGoGetCustomDomainWildcard(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "-u", "rsc.io/pdf/...")
- tg.wantExecutable(tg.path("bin/pdfpasswd"+exeSuffix), "did not build rsc/io/pdf/pdfpasswd")
-}
-
-func TestGoGetInternalWildcard(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- // used to fail with errors about internal packages
- tg.run("get", "github.com/rsc/go-get-issue-11960/...")
-}
-
-func TestGoVetWithExternalTests(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("vet", "vetpkg")
- tg.grepBoth("Printf", "go vet vetpkg did not find missing argument for Printf")
-}
-
-func TestGoVetWithTags(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("vet", "-tags", "tagtest", "vetpkg")
- tg.grepBoth(`c\.go.*Printf`, "go vet vetpkg did not run scan tagged file")
-}
-
-func TestGoVetWithFlagsOn(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("vet", "-printf", "vetpkg")
- tg.grepBoth("Printf", "go vet -printf vetpkg did not find missing argument for Printf")
-}
-
-func TestGoVetWithFlagsOff(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("vet", "-printf=false", "vetpkg")
-}
-
-// Issue 23395.
-func TestGoVetWithOnlyTestFiles(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.tempFile("src/p/p_test.go", "package p; import \"testing\"; func TestMe(*testing.T) {}")
- tg.setenv("GOPATH", tg.path("."))
- tg.run("vet", "p")
-}
-
-// Issue 24193.
-func TestVetWithOnlyCgoFiles(t *testing.T) {
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
- tooSlow(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.tempFile("src/p/p.go", "package p; import \"C\"; func F() {}")
- tg.setenv("GOPATH", tg.path("."))
- tg.run("vet", "p")
-}
-
-// Issue 9767, 19769.
-func TestGoGetDotSlashDownload(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempDir("src/rsc.io")
- tg.setenv("GOPATH", tg.path("."))
- tg.cd(tg.path("src/rsc.io"))
- tg.run("get", "./pprof_mac_fix")
-}
-
// Test that you cannot use a local import in a package
// accessed by a non-local import (found in a GOPATH/GOROOT).
// See golang.org/issue/17475.
@@ -2869,132 +1756,6 @@ func TestImportLocal(t *testing.T) {
tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
}
-func TestGoGetInsecure(t *testing.T) {
- test := func(t *testing.T, modules bool) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.failSSH()
-
- if modules {
- tg.setenv("GOPATH", tg.path("gp"))
- tg.tempFile("go.mod", "module m")
- tg.cd(tg.path("."))
- tg.setenv("GO111MODULE", "on")
- tg.setenv("GOPROXY", "")
- } else {
- tg.setenv("GOPATH", tg.path("."))
- tg.setenv("GO111MODULE", "off")
- }
-
- const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p"
-
- // Try go get -d of HTTP-only repo (should fail).
- tg.runFail("get", "-d", repo)
-
- // Try again with -insecure (should succeed).
- tg.run("get", "-d", "-insecure", repo)
-
- // Try updating without -insecure (should fail).
- tg.runFail("get", "-d", "-u", "-f", repo)
-
- if modules {
- tg.run("list", "-m", "...")
- tg.grepStdout("insecure.go-get-issue", "should find insecure module")
- }
- }
-
- t.Run("gopath", func(t *testing.T) { test(t, false) })
- t.Run("modules", func(t *testing.T) { test(t, true) })
-}
-
-func TestGoGetUpdateInsecure(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
-
- const repo = "github.com/golang/example"
-
- // Clone the repo via HTTP manually.
- cmd := exec.Command("git", "clone", "-q", "http://"+repo, tg.path("src/"+repo))
- if out, err := cmd.CombinedOutput(); err != nil {
- t.Fatalf("cloning %v repo: %v\n%s", repo, err, out)
- }
-
- // Update without -insecure should fail.
- // Update with -insecure should succeed.
- // We need -f to ignore import comments.
- const pkg = repo + "/hello"
- tg.runFail("get", "-d", "-u", "-f", pkg)
- tg.run("get", "-d", "-u", "-f", "-insecure", pkg)
-}
-
-func TestGoGetUpdateUnknownProtocol(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
-
- const repo = "github.com/golang/example"
-
- // Clone the repo via HTTPS manually.
- repoDir := tg.path("src/" + repo)
- cmd := exec.Command("git", "clone", "-q", "https://"+repo, repoDir)
- if out, err := cmd.CombinedOutput(); err != nil {
- t.Fatalf("cloning %v repo: %v\n%s", repo, err, out)
- }
-
- // Configure the repo to use a protocol unknown to cmd/go
- // that still actually works.
- cmd = exec.Command("git", "remote", "set-url", "origin", "xyz://"+repo)
- cmd.Dir = repoDir
- if out, err := cmd.CombinedOutput(); err != nil {
- t.Fatalf("git remote set-url: %v\n%s", err, out)
- }
- cmd = exec.Command("git", "config", "--local", "url.https://github.com/.insteadOf", "xyz://github.com/")
- cmd.Dir = repoDir
- if out, err := cmd.CombinedOutput(); err != nil {
- t.Fatalf("git config: %v\n%s", err, out)
- }
-
- // We need -f to ignore import comments.
- tg.run("get", "-d", "-u", "-f", repo+"/hello")
-}
-
-func TestGoGetInsecureCustomDomain(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
-
- const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p"
- tg.runFail("get", "-d", repo)
- tg.run("get", "-d", "-insecure", repo)
-}
-
-func TestGoRunDirs(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.cd("testdata/rundir")
- tg.runFail("run", "x.go", "sub/sub.go")
- tg.grepStderr("named files must all be in one directory; have ./ and sub/", "wrong output")
- tg.runFail("run", "sub/sub.go", "x.go")
- tg.grepStderr("named files must all be in one directory; have sub/ and ./", "wrong output")
-}
-
func TestGoInstallPkgdir(t *testing.T) {
skipIfGccgo(t, "gccgo has no standard packages")
tooSlow(t)
@@ -3012,294 +1773,6 @@ func TestGoInstallPkgdir(t *testing.T) {
tg.mustExist(filepath.Join(pkg, "sync/atomic.a"))
}
-func TestGoTestRaceInstallCgo(t *testing.T) {
- if !canRace {
- t.Skip("skipping because race detector not supported")
- }
-
- // golang.org/issue/10500.
- // This used to install a race-enabled cgo.
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("tool", "-n", "cgo")
- cgo := strings.TrimSpace(tg.stdout.String())
- old, err := os.Stat(cgo)
- tg.must(err)
-
- // For this test, we don't actually care whether 'go test -race -i' succeeds.
- // It may fail, for example, if GOROOT was installed from source as root and
- // is now read-only.
- // We only care that — regardless of whether it succeeds — it does not
- // overwrite cmd/cgo.
- runArgs := []string{"test", "-race", "-i", "runtime/race"}
- if status := tg.doRun(runArgs); status != nil {
- tg.t.Logf("go %v failure ignored: %v", runArgs, status)
- }
-
- new, err := os.Stat(cgo)
- tg.must(err)
- if !new.ModTime().Equal(old.ModTime()) {
- t.Fatalf("go test -i runtime/race reinstalled cmd/cgo")
- }
-}
-
-func TestGoGetUpdate(t *testing.T) {
- // golang.org/issue/9224.
- // The recursive updating was trying to walk to
- // former dependencies, not current ones.
-
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
-
- rewind := func() {
- tg.run("get", "github.com/rsc/go-get-issue-9224-cmd")
- cmd := exec.Command("git", "reset", "--hard", "HEAD~")
- cmd.Dir = tg.path("src/github.com/rsc/go-get-issue-9224-lib")
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("git: %v\n%s", err, out)
- }
- }
-
- rewind()
- tg.run("get", "-u", "github.com/rsc/go-get-issue-9224-cmd")
-
- // Again with -d -u.
- rewind()
- tg.run("get", "-d", "-u", "github.com/rsc/go-get-issue-9224-cmd")
-}
-
-// Issue #20512.
-func TestGoGetRace(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
- if !canRace {
- t.Skip("skipping because race detector not supported")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "-race", "github.com/rsc/go-get-issue-9224-cmd")
-}
-
-func TestGoGetDomainRoot(t *testing.T) {
- // golang.org/issue/9357.
- // go get foo.io (not foo.io/subdir) was not working consistently.
-
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
-
- // go-get-issue-9357.appspot.com is running
- // the code at github.com/rsc/go-get-issue-9357,
- // a trivial Go on App Engine app that serves a
- // <meta> tag for the domain root.
- tg.run("get", "-d", "go-get-issue-9357.appspot.com")
- tg.run("get", "go-get-issue-9357.appspot.com")
- tg.run("get", "-u", "go-get-issue-9357.appspot.com")
-
- tg.must(robustio.RemoveAll(tg.path("src/go-get-issue-9357.appspot.com")))
- tg.run("get", "go-get-issue-9357.appspot.com")
-
- tg.must(robustio.RemoveAll(tg.path("src/go-get-issue-9357.appspot.com")))
- tg.run("get", "-u", "go-get-issue-9357.appspot.com")
-}
-
-func TestGoInstallShadowedGOPATH(t *testing.T) {
- // golang.org/issue/3652.
- // go get foo.io (not foo.io/subdir) was not working consistently.
-
- testenv.MustHaveExternalNetwork(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("gopath1")+string(filepath.ListSeparator)+tg.path("gopath2"))
-
- tg.tempDir("gopath1/src/test")
- tg.tempDir("gopath2/src/test")
- tg.tempFile("gopath2/src/test/main.go", "package main\nfunc main(){}\n")
-
- tg.cd(tg.path("gopath2/src/test"))
- tg.runFail("install")
- tg.grepStderr("no install location for.*gopath2.src.test: hidden by .*gopath1.src.test", "missing error")
-}
-
-func TestGoBuildGOPATHOrder(t *testing.T) {
- // golang.org/issue/14176#issuecomment-179895769
- // golang.org/issue/14192
- // -I arguments to compiler could end up not in GOPATH order,
- // leading to unexpected import resolution in the compiler.
- // This is still not a complete fix (see golang.org/issue/14271 and next test)
- // but it is clearly OK and enough to fix both of the two reported
- // instances of the underlying problem. It will have to do for now.
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("p1")+string(filepath.ListSeparator)+tg.path("p2"))
-
- tg.tempFile("p1/src/foo/foo.go", "package foo\n")
- tg.tempFile("p2/src/baz/baz.go", "package baz\n")
- tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n")
- tg.tempFile("p1/src/bar/bar.go", `
- package bar
- import _ "baz"
- import _ "foo"
- `)
-
- tg.run("install", "-x", "bar")
-}
-
-func TestGoBuildGOPATHOrderBroken(t *testing.T) {
- // This test is known not to work.
- // See golang.org/issue/14271.
- t.Skip("golang.org/issue/14271")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
-
- tg.tempFile("p1/src/foo/foo.go", "package foo\n")
- tg.tempFile("p2/src/baz/baz.go", "package baz\n")
- tg.tempFile("p1/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/baz.a", "bad\n")
- tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n")
- tg.tempFile("p1/src/bar/bar.go", `
- package bar
- import _ "baz"
- import _ "foo"
- `)
-
- colon := string(filepath.ListSeparator)
- tg.setenv("GOPATH", tg.path("p1")+colon+tg.path("p2"))
- tg.run("install", "-x", "bar")
-
- tg.setenv("GOPATH", tg.path("p2")+colon+tg.path("p1"))
- tg.run("install", "-x", "bar")
-}
-
-func TestIssue11709(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempFile("run.go", `
- package main
- import "os"
- func main() {
- if os.Getenv("TERM") != "" {
- os.Exit(1)
- }
- }`)
- tg.unsetenv("TERM")
- tg.run("run", tg.path("run.go"))
-}
-
-func TestIssue12096(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempFile("test_test.go", `
- package main
- import ("os"; "testing")
- func TestEnv(t *testing.T) {
- if os.Getenv("TERM") != "" {
- t.Fatal("TERM is set")
- }
- }`)
- tg.unsetenv("TERM")
- tg.run("test", tg.path("test_test.go"))
-}
-
-func TestGoBuildOutput(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
-
- tg.makeTempdir()
- tg.cd(tg.path("."))
-
- nonExeSuffix := ".exe"
- if exeSuffix == ".exe" {
- nonExeSuffix = ""
- }
-
- tg.tempFile("x.go", "package main\nfunc main(){}\n")
- tg.run("build", "x.go")
- tg.wantExecutable("x"+exeSuffix, "go build x.go did not write x"+exeSuffix)
- tg.must(os.Remove(tg.path("x" + exeSuffix)))
- tg.mustNotExist("x" + nonExeSuffix)
-
- tg.run("build", "-o", "myprog", "x.go")
- tg.mustNotExist("x")
- tg.mustNotExist("x.exe")
- tg.wantExecutable("myprog", "go build -o myprog x.go did not write myprog")
- tg.mustNotExist("myprog.exe")
-
- tg.tempFile("p.go", "package p\n")
- tg.run("build", "p.go")
- tg.mustNotExist("p")
- tg.mustNotExist("p.a")
- tg.mustNotExist("p.o")
- tg.mustNotExist("p.exe")
-
- tg.run("build", "-o", "p.a", "p.go")
- tg.wantArchive("p.a")
-
- tg.run("build", "cmd/gofmt")
- tg.wantExecutable("gofmt"+exeSuffix, "go build cmd/gofmt did not write gofmt"+exeSuffix)
- tg.must(os.Remove(tg.path("gofmt" + exeSuffix)))
- tg.mustNotExist("gofmt" + nonExeSuffix)
-
- tg.run("build", "-o", "mygofmt", "cmd/gofmt")
- tg.wantExecutable("mygofmt", "go build -o mygofmt cmd/gofmt did not write mygofmt")
- tg.mustNotExist("mygofmt.exe")
- tg.mustNotExist("gofmt")
- tg.mustNotExist("gofmt.exe")
-
- tg.run("build", "sync/atomic")
- tg.mustNotExist("atomic")
- tg.mustNotExist("atomic.exe")
-
- tg.run("build", "-o", "myatomic.a", "sync/atomic")
- tg.wantArchive("myatomic.a")
- tg.mustNotExist("atomic")
- tg.mustNotExist("atomic.a")
- tg.mustNotExist("atomic.exe")
-
- tg.runFail("build", "-o", "whatever", "cmd/gofmt", "sync/atomic")
- tg.grepStderr("multiple packages", "did not reject -o with multiple packages")
-}
-
-func TestGoBuildARM(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping cross-compile in short mode")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
-
- tg.makeTempdir()
- tg.cd(tg.path("."))
-
- tg.setenv("GOARCH", "arm")
- tg.setenv("GOOS", "linux")
- tg.setenv("GOARM", "5")
- tg.tempFile("hello.go", `package main
- func main() {}`)
- tg.run("build", "hello.go")
- tg.grepStderrNot("unable to find math.a", "did not build math.a correctly")
-}
-
// For issue 14337.
func TestParallelTest(t *testing.T) {
tooSlow(t)
@@ -3321,50 +1794,6 @@ func TestParallelTest(t *testing.T) {
tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
}
-func TestCgoConsistentResults(t *testing.T) {
- tooSlow(t)
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
- switch runtime.GOOS {
- case "solaris", "illumos":
- testenv.SkipFlaky(t, 13247)
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- exe1 := tg.path("cgotest1" + exeSuffix)
- exe2 := tg.path("cgotest2" + exeSuffix)
- tg.run("build", "-o", exe1, "cgotest")
- tg.run("build", "-x", "-o", exe2, "cgotest")
- b1, err := ioutil.ReadFile(exe1)
- tg.must(err)
- b2, err := ioutil.ReadFile(exe2)
- tg.must(err)
-
- if !tg.doGrepMatch(`-fdebug-prefix-map=\$WORK`, &tg.stderr) {
- t.Skip("skipping because C compiler does not support -fdebug-prefix-map")
- }
- if !bytes.Equal(b1, b2) {
- t.Error("building cgotest twice did not produce the same output")
- }
-}
-
-// Issue 14444: go get -u .../ duplicate loads errors
-func TestGoGetUpdateAllDoesNotTryToLoadDuplicates(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "-u", ".../")
- tg.grepStderrNot("duplicate loads of", "did not remove old packages from cache")
-}
-
func TestBinaryOnlyPackages(t *testing.T) {
tooSlow(t)
@@ -3456,39 +1885,9 @@ func TestGenerateUsesBuildContext(t *testing.T) {
tg.grepStdout("linux amd64", "unexpected GOOS/GOARCH combination")
tg.setenv("GOOS", "darwin")
- tg.setenv("GOARCH", "386")
+ tg.setenv("GOARCH", "arm64")
tg.run("generate", "gen")
- tg.grepStdout("darwin 386", "unexpected GOOS/GOARCH combination")
-}
-
-// Issue 14450: go get -u .../ tried to import not downloaded package
-func TestGoGetUpdateWithWildcard(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- const aPkgImportPath = "github.com/tmwh/go-get-issue-14450/a"
- tg.run("get", aPkgImportPath)
- tg.runFail("get", "-u", ".../")
- tg.grepStderr("cannot find package.*d-dependency/e", "should have detected e missing")
-
- // Even though get -u failed, the source for others should be downloaded.
- var expectedPkgPaths = []string{
- "src/github.com/tmwh/go-get-issue-14450/b",
- "src/github.com/tmwh/go-get-issue-14450-b-dependency/c",
- "src/github.com/tmwh/go-get-issue-14450-b-dependency/d",
- }
-
- for _, importPath := range expectedPkgPaths {
- _, err := os.Stat(tg.path(importPath))
- tg.must(err)
- }
- const notExpectedPkgPath = "src/github.com/tmwh/go-get-issue-14450-c-dependency/e"
- tg.mustNotExist(tg.path(notExpectedPkgPath))
+ tg.grepStdout("darwin arm64", "unexpected GOOS/GOARCH combination")
}
func TestGoEnv(t *testing.T) {
@@ -3522,153 +1921,6 @@ const (
okPattern = `(?m)^ok`
)
-func TestMatchesNoTests(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.run("test", "-run", "ThisWillNotMatch", "testdata/standalone_test.go")
- tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
-}
-
-func TestMatchesNoBenchmarksIsOK(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.run("test", "-run", "^$", "-bench", "ThisWillNotMatch", "testdata/standalone_benchmark_test.go")
- tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
- tg.grepBoth(okPattern, "go test did not say ok")
-}
-
-func TestMatchesOnlyExampleIsOK(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.run("test", "-run", "Example", "testdata/example1_test.go")
- tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
- tg.grepBoth(okPattern, "go test did not say ok")
-}
-
-func TestMatchesOnlyBenchmarkIsOK(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.run("test", "-run", "^$", "-bench", ".", "testdata/standalone_benchmark_test.go")
- tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
- tg.grepBoth(okPattern, "go test did not say ok")
-}
-
-func TestBenchmarkLabelsOutsideGOPATH(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.run("test", "-run", "^$", "-bench", ".", "testdata/standalone_benchmark_test.go")
- tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos")
- tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch")
- tg.grepBothNot(`(?m)^pkg:`, "go test did say pkg:")
-}
-
-func TestMatchesOnlyTestIsOK(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.run("test", "-run", "Test", "testdata/standalone_test.go")
- tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
- tg.grepBoth(okPattern, "go test did not say ok")
-}
-
-func TestMatchesNoTestsWithSubtests(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-run", "ThisWillNotMatch", "testdata/standalone_sub_test.go")
- tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
-}
-
-func TestMatchesNoSubtestsMatch(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-run", "Test/ThisWillNotMatch", "testdata/standalone_sub_test.go")
- tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
-}
-
-func TestMatchesNoSubtestsDoesNotOverrideFailure(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.runFail("test", "-run", "TestThatFails/ThisWillNotMatch", "testdata/standalone_fail_sub_test.go")
- tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
- tg.grepBoth("FAIL", "go test did not say FAIL")
-}
-
-func TestMatchesOnlySubtestIsOK(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-run", "Test/Sub", "testdata/standalone_sub_test.go")
- tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
- tg.grepBoth(okPattern, "go test did not say ok")
-}
-
-func TestMatchesNoSubtestsParallel(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-run", "Test/Sub/ThisWillNotMatch", "testdata/standalone_parallel_sub_test.go")
- tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
-}
-
-func TestMatchesOnlySubtestParallelIsOK(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-run", "Test/Sub/Nested", "testdata/standalone_parallel_sub_test.go")
- tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
- tg.grepBoth(okPattern, "go test did not say ok")
-}
-
-// Issue 18845
-func TestBenchTimeout(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-bench", ".", "-timeout", "750ms", "testdata/timeoutbench_test.go")
-}
-
-// Issue 19394
-func TestWriteProfilesOnTimeout(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempDir("profiling")
- tg.tempFile("profiling/timeouttest_test.go", `package timeouttest_test
-import "testing"
-import "time"
-func TestSleep(t *testing.T) { time.Sleep(time.Second) }`)
- tg.cd(tg.path("profiling"))
- tg.runFail(
- "test",
- "-cpuprofile", tg.path("profiling/cpu.pprof"), "-memprofile", tg.path("profiling/mem.pprof"),
- "-timeout", "1ms")
- tg.mustHaveContent(tg.path("profiling/cpu.pprof"))
- tg.mustHaveContent(tg.path("profiling/mem.pprof"))
-}
-
-func TestLinkXImportPathEscape(t *testing.T) {
- // golang.org/issue/16710
- skipIfGccgo(t, "gccgo does not support -ldflags -X")
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- exe := tg.path("linkx" + exeSuffix)
- tg.creatingTemp(exe)
- tg.run("build", "-o", exe, "-ldflags", "-X=my.pkg.Text=linkXworked", "my.pkg/main")
- out, err := exec.Command(exe).CombinedOutput()
- if err != nil {
- tg.t.Fatal(err)
- }
- if string(out) != "linkXworked\n" {
- tg.t.Log(string(out))
- tg.t.Fatal(`incorrect output: expected "linkXworked\n"`)
- }
-}
-
// Issue 18044.
func TestLdBindNow(t *testing.T) {
tg := testgo(t)
@@ -3695,29 +1947,6 @@ GLOBL ·constants<>(SB),8,$8
tg.run("build", "p")
}
-// Issue 18778.
-func TestDotDotDotOutsideGOPATH(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
-
- tg.tempFile("pkgs/a.go", `package x`)
- tg.tempFile("pkgs/a_test.go", `package x_test
-import "testing"
-func TestX(t *testing.T) {}`)
-
- tg.tempFile("pkgs/a/a.go", `package a`)
- tg.tempFile("pkgs/a/a_test.go", `package a_test
-import "testing"
-func TestA(t *testing.T) {}`)
-
- tg.cd(tg.path("pkgs"))
- tg.run("build", "./...")
- tg.run("test", "./...")
- tg.run("list", "./...")
- tg.grepStdout("pkgs$", "expected package not listed")
- tg.grepStdout("pkgs/a", "expected package not listed")
-}
-
// Issue 18975.
func TestFFLAGS(t *testing.T) {
if !canCgo {
@@ -3790,17 +2019,6 @@ func main() {
tg.run("build", "-o", exe, "p")
}
-func TestBuildTagsNoComma(t *testing.T) {
- skipIfGccgo(t, "gccgo has no standard packages")
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("go"))
- tg.run("build", "-tags", "tag1 tag2", "math")
- tg.runFail("build", "-tags", "tag1,tag2 tag3", "math")
- tg.grepBoth("space-separated list contains comma", "-tags with a comma-separated list didn't error")
-}
-
func copyFile(src, dst string, perm os.FileMode) error {
sf, err := os.Open(src)
if err != nil {
@@ -3821,106 +2039,6 @@ func copyFile(src, dst string, perm os.FileMode) error {
return err2
}
-// TestExecutableGOROOT verifies that the cmd/go binary itself uses
-// os.Executable (when available) to locate GOROOT.
-func TestExecutableGOROOT(t *testing.T) {
- skipIfGccgo(t, "gccgo has no GOROOT")
-
- // Note: Must not call tg methods inside subtests: tg is attached to outer t.
- tg := testgo(t)
- tg.unsetenv("GOROOT")
- defer tg.cleanup()
-
- check := func(t *testing.T, exe, want string) {
- cmd := exec.Command(exe, "env", "GOROOT")
- cmd.Env = tg.env
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("%s env GOROOT: %v, %s", exe, err, out)
- }
- goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out)))
- if err != nil {
- t.Fatal(err)
- }
- want, err = filepath.EvalSymlinks(want)
- if err != nil {
- t.Fatal(err)
- }
- if !strings.EqualFold(goroot, want) {
- t.Errorf("go env GOROOT:\nhave %s\nwant %s", goroot, want)
- } else {
- t.Logf("go env GOROOT: %s", goroot)
- }
- }
-
- tg.makeTempdir()
- tg.tempDir("new/bin")
- newGoTool := tg.path("new/bin/go" + exeSuffix)
- tg.must(copyFile(tg.goTool(), newGoTool, 0775))
- newRoot := tg.path("new")
-
- t.Run("RelocatedExe", func(t *testing.T) {
- // Should fall back to default location in binary,
- // which is the GOROOT we used when building testgo.exe.
- check(t, newGoTool, testGOROOT)
- })
-
- // If the binary is sitting in a bin dir next to ../pkg/tool, that counts as a GOROOT,
- // so it should find the new tree.
- tg.tempDir("new/pkg/tool")
- t.Run("RelocatedTree", func(t *testing.T) {
- check(t, newGoTool, newRoot)
- })
-
- tg.tempDir("other/bin")
- symGoTool := tg.path("other/bin/go" + exeSuffix)
-
- // Symlink into go tree should still find go tree.
- t.Run("SymlinkedExe", func(t *testing.T) {
- testenv.MustHaveSymlink(t)
- if err := os.Symlink(newGoTool, symGoTool); err != nil {
- t.Fatal(err)
- }
- check(t, symGoTool, newRoot)
- })
-
- tg.must(robustio.RemoveAll(tg.path("new/pkg")))
-
- // Binaries built in the new tree should report the
- // new tree when they call runtime.GOROOT.
- t.Run("RuntimeGoroot", func(t *testing.T) {
- // Build a working GOROOT the easy way, with symlinks.
- testenv.MustHaveSymlink(t)
- if err := os.Symlink(filepath.Join(testGOROOT, "src"), tg.path("new/src")); err != nil {
- t.Fatal(err)
- }
- if err := os.Symlink(filepath.Join(testGOROOT, "pkg"), tg.path("new/pkg")); err != nil {
- t.Fatal(err)
- }
-
- cmd := exec.Command(newGoTool, "run", "testdata/print_goroot.go")
- cmd.Env = tg.env
- cmd.Stderr = os.Stderr
- out, err := cmd.Output()
- if err != nil {
- t.Fatalf("%s run testdata/print_goroot.go: %v, %s", newGoTool, err, out)
- }
- goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out)))
- if err != nil {
- t.Fatal(err)
- }
- want, err := filepath.EvalSymlinks(tg.path("new"))
- if err != nil {
- t.Fatal(err)
- }
- if !strings.EqualFold(goroot, want) {
- t.Errorf("go run testdata/print_goroot.go:\nhave %s\nwant %s", goroot, want)
- } else {
- t.Logf("go run testdata/print_goroot.go: %s", goroot)
- }
- })
-}
-
func TestNeedVersion(t *testing.T) {
skipIfGccgo(t, "gccgo does not use cmd/compile")
tg := testgo(t)
@@ -3933,47 +2051,6 @@ func TestNeedVersion(t *testing.T) {
tg.grepStderr("compile", "does not match go tool version")
}
-func TestCgoFlagContainsSpace(t *testing.T) {
- tooSlow(t)
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
- tg := testgo(t)
- defer tg.cleanup()
-
- tg.makeTempdir()
- tg.cd(tg.path("."))
- tg.tempFile("main.go", `package main
- // #cgo CFLAGS: -I"c flags"
- // #cgo LDFLAGS: -L"ld flags"
- import "C"
- func main() {}
- `)
- tg.run("run", "-x", "main.go")
- tg.grepStderr(`"-I[^"]+c flags"`, "did not find quoted c flags")
- tg.grepStderrNot(`"-I[^"]+c flags".*"-I[^"]+c flags"`, "found too many quoted c flags")
- tg.grepStderr(`"-L[^"]+ld flags"`, "did not find quoted ld flags")
- tg.grepStderrNot(`"-L[^"]+c flags".*"-L[^"]+c flags"`, "found too many quoted ld flags")
-}
-
-func TestListTests(t *testing.T) {
- tooSlow(t)
- var tg *testgoData
- testWith := func(listName, expected string) func(*testing.T) {
- return func(t *testing.T) {
- tg = testgo(t)
- defer tg.cleanup()
- tg.run("test", "./testdata/src/testlist/...", fmt.Sprintf("-list=%s", listName))
- tg.grepStdout(expected, fmt.Sprintf("-test.list=%s returned %q, expected %s", listName, tg.getStdout(), expected))
- }
- }
-
- t.Run("Test", testWith("Test", "TestSimple"))
- t.Run("Bench", testWith("Benchmark", "BenchmarkSimple"))
- t.Run("Example1", testWith("Example", "ExampleSimple"))
- t.Run("Example2", testWith("Example", "ExampleWithEmptyOutput"))
-}
-
func TestBuildmodePIE(t *testing.T) {
if testing.Short() && testenv.Builder() == "" {
t.Skipf("skipping in -short mode on non-builder")
@@ -3983,20 +2060,62 @@ func TestBuildmodePIE(t *testing.T) {
switch platform {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
"android/amd64", "android/arm", "android/arm64", "android/386",
- "freebsd/amd64":
+ "freebsd/amd64",
+ "windows/386", "windows/amd64", "windows/arm":
case "darwin/amd64":
default:
t.Skipf("skipping test because buildmode=pie is not supported on %s", platform)
}
+ t.Run("non-cgo", func(t *testing.T) {
+ testBuildmodePIE(t, false, true)
+ })
+ if canCgo {
+ switch runtime.GOOS {
+ case "darwin", "freebsd", "linux", "windows":
+ t.Run("cgo", func(t *testing.T) {
+ testBuildmodePIE(t, true, true)
+ })
+ }
+ }
+}
+
+func TestWindowsDefaultBuildmodIsPIE(t *testing.T) {
+ if testing.Short() && testenv.Builder() == "" {
+ t.Skipf("skipping in -short mode on non-builder")
+ }
+
+ if runtime.GOOS != "windows" {
+ t.Skip("skipping windows only test")
+ }
+
+ t.Run("non-cgo", func(t *testing.T) {
+ testBuildmodePIE(t, false, false)
+ })
+ if canCgo {
+ t.Run("cgo", func(t *testing.T) {
+ testBuildmodePIE(t, true, false)
+ })
+ }
+}
+func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
- tg.tempFile("main.go", `package main; func main() { print("hello") }`)
+ var s string
+ if useCgo {
+ s = `import "C";`
+ }
+ tg.tempFile("main.go", fmt.Sprintf(`package main;%s func main() { print("hello") }`, s))
src := tg.path("main.go")
- obj := tg.path("main")
- tg.run("build", "-buildmode=pie", "-o", obj, src)
+ obj := tg.path("main.exe")
+ args := []string{"build"}
+ if setBuildmodeToPIE {
+ args = append(args, "-buildmode=pie")
+ }
+ args = append(args, "-o", obj, src)
+ tg.run(args...)
switch runtime.GOOS {
case "linux", "android", "freebsd":
@@ -4020,6 +2139,33 @@ func TestBuildmodePIE(t *testing.T) {
if f.Flags&macho.FlagPIE == 0 {
t.Error("PIE must have PIE flag, but not")
}
+ case "windows":
+ f, err := pe.Open(obj)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ if f.Section(".reloc") == nil {
+ t.Error(".reloc section is not present")
+ }
+ if (f.FileHeader.Characteristics & pe.IMAGE_FILE_RELOCS_STRIPPED) != 0 {
+ t.Error("IMAGE_FILE_RELOCS_STRIPPED flag is set")
+ }
+ var dc uint16
+ switch oh := f.OptionalHeader.(type) {
+ case *pe.OptionalHeader32:
+ dc = oh.DllCharacteristics
+ case *pe.OptionalHeader64:
+ dc = oh.DllCharacteristics
+ if (dc & pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA) == 0 {
+ t.Error("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag is not set")
+ }
+ default:
+ t.Fatalf("unexpected optional header type of %T", f.OptionalHeader)
+ }
+ if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 {
+ t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set")
+ }
default:
panic("unreachable")
}
@@ -4034,93 +2180,6 @@ func TestBuildmodePIE(t *testing.T) {
}
}
-func TestExecBuildX(t *testing.T) {
- tooSlow(t)
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
-
- testenv.MustHaveExecPath(t, "/usr/bin/env")
- testenv.MustHaveExecPath(t, "bash")
-
- tg := testgo(t)
- defer tg.cleanup()
-
- tg.tempDir("cache")
- tg.setenv("GOCACHE", tg.path("cache"))
-
- // Before building our test main.go, ensure that an up-to-date copy of
- // runtime/cgo is present in the cache. If it isn't, the 'go build' step below
- // will fail with "can't open import". See golang.org/issue/29004.
- tg.run("build", "runtime/cgo")
-
- tg.tempFile("main.go", `package main; import "C"; func main() { print("hello") }`)
- src := tg.path("main.go")
- obj := tg.path("main")
- tg.run("build", "-x", "-o", obj, src)
- sh := tg.path("test.sh")
- cmds := tg.getStderr()
- err := ioutil.WriteFile(sh, []byte("set -e\n"+cmds), 0666)
- if err != nil {
- t.Fatal(err)
- }
-
- out, err := exec.Command(obj).CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
- if string(out) != "hello" {
- t.Fatalf("got %q; want %q", out, "hello")
- }
-
- err = os.Remove(obj)
- if err != nil {
- t.Fatal(err)
- }
-
- out, err = exec.Command("/usr/bin/env", "bash", "-x", sh).CombinedOutput()
- if err != nil {
- t.Fatalf("/bin/sh %s: %v\n%s", sh, err, out)
- }
- t.Logf("shell output:\n%s", out)
-
- out, err = exec.Command(obj).CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
- if string(out) != "hello" {
- t.Fatalf("got %q; want %q", out, "hello")
- }
-
- matches := regexp.MustCompile(`^WORK=(.*)\n`).FindStringSubmatch(cmds)
- if len(matches) == 0 {
- t.Fatal("no WORK directory")
- }
- tg.must(robustio.RemoveAll(matches[1]))
-}
-
-func TestParallelNumber(t *testing.T) {
- tooSlow(t)
- for _, n := range [...]string{"-1", "0"} {
- t.Run(n, func(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.runFail("test", "-parallel", n, "testdata/standalone_parallel_sub_test.go")
- tg.grepBoth("-parallel can only be given", "go test -parallel with N<1 did not error")
- })
- }
-}
-
-func TestWrongGOOSErrorBeforeLoadError(t *testing.T) {
- skipIfGccgo(t, "gccgo assumes cross-compilation is always possible")
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.setenv("GOOS", "windwos")
- tg.runFail("build", "exclude")
- tg.grepStderr("unsupported GOOS/GOARCH pair", "GOOS=windwos go build exclude did not report 'unsupported GOOS/GOARCH pair'")
-}
-
func TestUpxCompression(t *testing.T) {
if runtime.GOOS != "linux" ||
(runtime.GOARCH != "amd64" && runtime.GOARCH != "386") {
@@ -4304,30 +2363,6 @@ func TestTestCache(t *testing.T) {
tg.setenv("GOPATH", tg.tempdir)
tg.setenv("GOCACHE", tg.path("cache"))
- if runtime.Compiler != "gccgo" {
- // timeout here should not affect result being cached
- // or being retrieved later.
- tg.run("test", "-x", "-timeout=10s", "errors")
- tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler")
- tg.grepStderr(`[\\/]link|gccgo`, "did not run linker")
- tg.grepStderr(`errors\.test`, "did not run test")
-
- tg.run("test", "-x", "errors")
- tg.grepStdout(`ok \terrors\t\(cached\)`, "did not report cached result")
- tg.grepStderrNot(`[\\/]compile|gccgo`, "incorrectly ran compiler")
- tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly ran linker")
- tg.grepStderrNot(`errors\.test`, "incorrectly ran test")
- tg.grepStderrNot("DO NOT USE", "poisoned action status leaked")
-
- // Even very low timeouts do not disqualify cached entries.
- tg.run("test", "-timeout=1ns", "-x", "errors")
- tg.grepStderrNot(`errors\.test`, "incorrectly ran test")
-
- tg.run("clean", "-testcache")
- tg.run("test", "-x", "errors")
- tg.grepStderr(`errors\.test`, "did not run test")
- }
-
// The -p=1 in the commands below just makes the -x output easier to read.
t.Log("\n\nINITIAL\n\n")
@@ -4407,53 +2442,6 @@ func TestTestCache(t *testing.T) {
}
}
-func TestTestVet(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
-
- tg.tempFile("p1_test.go", `
- package p
- import "testing"
- func Test(t *testing.T) {
- t.Logf("%d") // oops
- }
- `)
-
- tg.runFail("test", tg.path("p1_test.go"))
- tg.grepStderr(`Logf format %d`, "did not diagnose bad Logf")
- tg.run("test", "-vet=off", tg.path("p1_test.go"))
- tg.grepStdout(`^ok`, "did not print test summary")
-
- tg.tempFile("p1.go", `
- package p
- import "fmt"
- func F() {
- fmt.Printf("%d") // oops
- }
- `)
- tg.runFail("test", tg.path("p1.go"))
- tg.grepStderr(`Printf format %d`, "did not diagnose bad Printf")
- tg.run("test", "-x", "-vet=shift", tg.path("p1.go"))
- tg.grepStderr(`[\\/]vet.*-shift`, "did not run vet with -shift")
- tg.grepStdout(`\[no test files\]`, "did not print test summary")
- tg.run("test", "-vet=off", tg.path("p1.go"))
- tg.grepStdout(`\[no test files\]`, "did not print test summary")
-
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "vetcycle") // must not fail; #22890
-
- tg.runFail("test", "vetfail/...")
- tg.grepStderr(`Printf format %d`, "did not diagnose bad Printf")
- tg.grepStdout(`ok\s+vetfail/p2`, "did not run vetfail/p2")
-
- // Use -a so that we need to recompute the vet-specific export data for
- // vetfail/p1.
- tg.run("test", "-a", "vetfail/p2")
- tg.grepStderrNot(`invalid.*constraint`, "did diagnose bad build constraint in vetxonly mode")
-}
-
func TestTestSkipVetAfterFailedBuild(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -4549,92 +2537,6 @@ func TestInstallDeps(t *testing.T) {
tg.mustExist(p1)
}
-func TestGoTestJSON(t *testing.T) {
- skipIfGccgo(t, "gccgo does not have standard packages")
- tooSlow(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOCACHE", tg.tempdir)
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- // It would be nice to test that the output is interlaced
- // but it seems to be impossible to do that in a short test
- // that isn't also flaky. Just check that we get JSON output.
- tg.run("test", "-json", "-short", "-v", "errors", "empty/pkg", "skipper")
- tg.grepStdout(`"Package":"errors"`, "did not see JSON output")
- tg.grepStdout(`"Action":"run"`, "did not see JSON output")
-
- tg.grepStdout(`"Action":"output","Package":"empty/pkg","Output":".*no test files`, "did not see no test files print")
- tg.grepStdout(`"Action":"skip","Package":"empty/pkg"`, "did not see skip")
-
- tg.grepStdout(`"Action":"output","Package":"skipper","Test":"Test","Output":"--- SKIP:`, "did not see SKIP output")
- tg.grepStdout(`"Action":"skip","Package":"skipper","Test":"Test"`, "did not see skip result for Test")
-
- tg.run("test", "-json", "-short", "-v", "errors")
- tg.grepStdout(`"Action":"output","Package":"errors","Output":".*\(cached\)`, "did not see no cached output")
-
- tg.run("test", "-json", "-bench=NONE", "-short", "-v", "errors")
- tg.grepStdout(`"Package":"errors"`, "did not see JSON output")
- tg.grepStdout(`"Action":"run"`, "did not see JSON output")
-
- tg.run("test", "-o", tg.path("errors.test.exe"), "-c", "errors")
- tg.run("tool", "test2json", "-p", "errors", tg.path("errors.test.exe"), "-test.v", "-test.short")
- tg.grepStdout(`"Package":"errors"`, "did not see JSON output")
- tg.grepStdout(`"Action":"run"`, "did not see JSON output")
- tg.grepStdout(`\{"Action":"pass","Package":"errors"\}`, "did not see final pass")
-}
-
-func TestFailFast(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
-
- tests := []struct {
- run string
- failfast bool
- nfail int
- }{
- {"TestFailingA", true, 1},
- {"TestFailing[AB]", true, 1},
- {"TestFailing[AB]", false, 2},
- // mix with non-failing tests:
- {"TestA|TestFailing[AB]", true, 1},
- {"TestA|TestFailing[AB]", false, 2},
- // mix with parallel tests:
- {"TestFailingB|TestParallelFailingA", true, 2},
- {"TestFailingB|TestParallelFailingA", false, 2},
- {"TestFailingB|TestParallelFailing[AB]", true, 3},
- {"TestFailingB|TestParallelFailing[AB]", false, 3},
- // mix with parallel sub-tests
- {"TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA", true, 3},
- {"TestFailingB|TestParallelFailing[AB]|TestParallelFailingSubtestsA", false, 5},
- {"TestParallelFailingSubtestsA", true, 1},
- // only parallels:
- {"TestParallelFailing[AB]", false, 2},
- // non-parallel subtests:
- {"TestFailingSubtestsA", true, 1},
- {"TestFailingSubtestsA", false, 2},
- // fatal test
- {"TestFatal[CD]", true, 1},
- {"TestFatal[CD]", false, 2},
- }
-
- for _, tt := range tests {
- t.Run(tt.run, func(t *testing.T) {
- tg.runFail("test", "./testdata/src/failfast_test.go", "-run="+tt.run, "-failfast="+strconv.FormatBool(tt.failfast))
-
- nfail := strings.Count(tg.getStdout(), "FAIL - ")
-
- if nfail != tt.nfail {
- t.Errorf("go test -run=%s -failfast=%t printed %d FAILs, want %d", tt.run, tt.failfast, nfail, tt.nfail)
- }
- })
- }
-}
-
// Issue 22986.
func TestImportPath(t *testing.T) {
tooSlow(t)
@@ -4723,7 +2625,7 @@ func TestBadCommandLines(t *testing.T) {
tg.tempFile("src/-x/x.go", "package x\n")
tg.setenv("GOPATH", tg.path("."))
tg.runFail("build", "--", "-x")
- tg.grepStderr("invalid input directory name \"-x\"", "did not reject -x directory")
+ tg.grepStderr("invalid import path \"-x\"", "did not reject -x import path")
tg.tempFile("src/-x/y/y.go", "package y\n")
tg.setenv("GOPATH", tg.path("."))
@@ -4731,118 +2633,6 @@ func TestBadCommandLines(t *testing.T) {
tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
}
-func TestBadCgoDirectives(t *testing.T) {
- if !canCgo {
- t.Skip("no cgo")
- }
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
-
- tg.tempFile("src/x/x.go", "package x\n")
- tg.setenv("GOPATH", tg.path("."))
-
- if runtime.Compiler == "gc" {
- tg.tempFile("src/x/x.go", `package x
-
- //go:cgo_ldflag "-fplugin=foo.so"
-
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("//go:cgo_ldflag .* only allowed in cgo-generated code", "did not reject //go:cgo_ldflag directive")
- }
-
- tg.must(os.Remove(tg.path("src/x/x.go")))
- tg.runFail("build", "x")
- tg.grepStderr("no Go files", "did not report missing source code")
- tg.tempFile("src/x/_cgo_yy.go", `package x
-
- //go:cgo_ldflag "-fplugin=foo.so"
-
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("no Go files", "did not report missing source code") // _* files are ignored...
-
- if runtime.Compiler == "gc" {
- tg.runFail("build", tg.path("src/x/_cgo_yy.go")) // ... but if forced, the comment is rejected
- // Actually, today there is a separate issue that _ files named
- // on the command line are ignored. Once that is fixed,
- // we want to see the cgo_ldflag error.
- tg.grepStderr("//go:cgo_ldflag only allowed in cgo-generated code|no Go files", "did not reject //go:cgo_ldflag directive")
- }
-
- tg.must(os.Remove(tg.path("src/x/_cgo_yy.go")))
-
- tg.tempFile("src/x/x.go", "package x\n")
- tg.tempFile("src/x/y.go", `package x
- // #cgo CFLAGS: -fplugin=foo.so
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("invalid flag in #cgo CFLAGS: -fplugin=foo.so", "did not reject -fplugin")
-
- tg.tempFile("src/x/y.go", `package x
- // #cgo CFLAGS: -Ibar -fplugin=foo.so
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("invalid flag in #cgo CFLAGS: -fplugin=foo.so", "did not reject -fplugin")
-
- tg.tempFile("src/x/y.go", `package x
- // #cgo pkg-config: -foo
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("invalid pkg-config package name: -foo", "did not reject pkg-config: -foo")
-
- tg.tempFile("src/x/y.go", `package x
- // #cgo pkg-config: @foo
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("invalid pkg-config package name: @foo", "did not reject pkg-config: -foo")
-
- tg.tempFile("src/x/y.go", `package x
- // #cgo CFLAGS: @foo
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("invalid flag in #cgo CFLAGS: @foo", "did not reject @foo flag")
-
- tg.tempFile("src/x/y.go", `package x
- // #cgo CFLAGS: -D
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("invalid flag in #cgo CFLAGS: -D without argument", "did not reject trailing -I flag")
-
- // Note that -I @foo is allowed because we rewrite it into -I /path/to/src/@foo
- // before the check is applied. There's no such rewrite for -D.
-
- tg.tempFile("src/x/y.go", `package x
- // #cgo CFLAGS: -D @foo
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("invalid flag in #cgo CFLAGS: -D @foo", "did not reject -D @foo flag")
-
- tg.tempFile("src/x/y.go", `package x
- // #cgo CFLAGS: -D@foo
- import "C"
- `)
- tg.runFail("build", "x")
- tg.grepStderr("invalid flag in #cgo CFLAGS: -D@foo", "did not reject -D@foo flag")
-
- tg.setenv("CGO_CFLAGS", "-D@foo")
- tg.tempFile("src/x/y.go", `package x
- import "C"
- `)
- tg.run("build", "-n", "x")
- tg.grepStderr("-D@foo", "did not find -D@foo in commands")
-}
-
func TestTwoPkgConfigs(t *testing.T) {
if !canCgo {
t.Skip("no cgo")
@@ -4978,52 +2768,6 @@ func TestLinkerTmpDirIsDeleted(t *testing.T) {
}
}
-func testCDAndGOPATHAreDifferent(tg *testgoData, cd, gopath string) {
- skipIfGccgo(tg.t, "gccgo does not support -ldflags -X")
- tg.setenv("GOPATH", gopath)
-
- tg.tempDir("dir")
- exe := tg.path("dir/a.exe")
-
- tg.cd(cd)
-
- tg.run("build", "-o", exe, "-ldflags", "-X=my.pkg.Text=linkXworked")
- out, err := exec.Command(exe).CombinedOutput()
- if err != nil {
- tg.t.Fatal(err)
- }
- if string(out) != "linkXworked\n" {
- tg.t.Errorf(`incorrect output with GOPATH=%q and CD=%q: expected "linkXworked\n", but have %q`, gopath, cd, string(out))
- }
-}
-
-func TestCDAndGOPATHAreDifferent(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
-
- gopath := filepath.Join(tg.pwd(), "testdata")
- cd := filepath.Join(gopath, "src/my.pkg/main")
-
- testCDAndGOPATHAreDifferent(tg, cd, gopath)
- if runtime.GOOS == "windows" {
- testCDAndGOPATHAreDifferent(tg, cd, strings.ReplaceAll(gopath, `\`, `/`))
- testCDAndGOPATHAreDifferent(tg, cd, strings.ToUpper(gopath))
- testCDAndGOPATHAreDifferent(tg, cd, strings.ToLower(gopath))
- }
-}
-
-// Issue 25579.
-func TestGoBuildDashODevNull(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("build", "-o", os.DevNull, filepath.Join(tg.pwd(), "testdata", "src", "hello", "hello.go"))
- tg.mustNotExist("hello")
- tg.mustNotExist("hello.exe")
-}
-
// Issue 25093.
func TestCoverpkgTestOnly(t *testing.T) {
skipIfGccgo(t, "gccgo has no cover tool")
diff --git a/libgo/go/cmd/go/help_test.go b/libgo/go/cmd/go/help_test.go
index 9bcab82..78d63ff 100644
--- a/libgo/go/cmd/go/help_test.go
+++ b/libgo/go/cmd/go/help_test.go
@@ -14,6 +14,8 @@ import (
)
func TestDocsUpToDate(t *testing.T) {
+ t.Parallel()
+
if !modload.Enabled() {
t.Skipf("help.Help in GOPATH mode is configured by main.main")
}
diff --git a/libgo/go/cmd/go/internal/auth/auth.go b/libgo/go/cmd/go/internal/auth/auth.go
index 12e3c74..fe5a89d 100644
--- a/libgo/go/cmd/go/internal/auth/auth.go
+++ b/libgo/go/cmd/go/internal/auth/auth.go
@@ -10,10 +10,12 @@ import "net/http"
// AddCredentials fills in the user's credentials for req, if any.
// The return value reports whether any matching credentials were found.
func AddCredentials(req *http.Request) (added bool) {
+ host := req.URL.Hostname()
+
// TODO(golang.org/issue/26232): Support arbitrary user-provided credentials.
netrcOnce.Do(readNetrc)
for _, l := range netrc {
- if l.machine == req.URL.Host {
+ if l.machine == host {
req.SetBasicAuth(l.login, l.password)
return true
}
diff --git a/libgo/go/cmd/go/internal/base/base.go b/libgo/go/cmd/go/internal/base/base.go
index 272da55..ab2f1bb 100644
--- a/libgo/go/cmd/go/internal/base/base.go
+++ b/libgo/go/cmd/go/internal/base/base.go
@@ -7,11 +7,8 @@
package base
import (
- "bytes"
- "errors"
"flag"
"fmt"
- "go/scanner"
"log"
"os"
"os/exec"
@@ -172,25 +169,3 @@ func RunStdin(cmdline []string) {
// Usage is the usage-reporting function, filled in by package main
// but here for reference by other packages.
var Usage func()
-
-// ExpandScanner expands a scanner.List error into all the errors in the list.
-// The default Error method only shows the first error
-// and does not shorten paths.
-func ExpandScanner(err error) error {
- // Look for parser errors.
- if err, ok := err.(scanner.ErrorList); ok {
- // Prepare error with \n before each message.
- // When printed in something like context: %v
- // this will put the leading file positions each on
- // its own line. It will also show all the errors
- // instead of just the first, as err.Error does.
- var buf bytes.Buffer
- for _, e := range err {
- e.Pos.Filename = ShortPath(e.Pos.Filename)
- buf.WriteString("\n")
- buf.WriteString(e.Error())
- }
- return errors.New(buf.String())
- }
- return err
-}
diff --git a/libgo/go/cmd/go/internal/base/env.go b/libgo/go/cmd/go/internal/base/env.go
index 077295e..5f2665d 100644
--- a/libgo/go/cmd/go/internal/base/env.go
+++ b/libgo/go/cmd/go/internal/base/env.go
@@ -4,12 +4,12 @@
package base
-// EnvForDir returns a modified environment suitable for running in the given
-// directory.
-// The environment is the supplied base environment but with an updated $PWD, so
-// that an os.Getwd in the child will be faster.
-func EnvForDir(dir string, base []string) []string {
- // Internally we only use rooted paths, so dir is rooted.
- // Even if dir is not rooted, no harm done.
+// AppendPWD returns the result of appending PWD=dir to the environment base.
+//
+// The resulting environment makes os.Getwd more efficient for a subprocess
+// running in dir.
+func AppendPWD(base []string, dir string) []string {
+ // Internally we only use absolute paths, so dir is absolute.
+ // Even if dir is not absolute, no harm done.
return append(base, "PWD="+dir)
}
diff --git a/libgo/go/cmd/go/internal/base/goflags.go b/libgo/go/cmd/go/internal/base/goflags.go
index 187c2a1..3476613 100644
--- a/libgo/go/cmd/go/internal/base/goflags.go
+++ b/libgo/go/cmd/go/internal/base/goflags.go
@@ -102,7 +102,7 @@ type boolFlag interface {
}
// SetFromGOFLAGS sets the flags in the given flag set using settings in $GOFLAGS.
-func SetFromGOFLAGS(flags flag.FlagSet) {
+func SetFromGOFLAGS(flags *flag.FlagSet) {
InitGOFLAGS()
// This loop is similar to flag.Parse except that it ignores
@@ -125,14 +125,18 @@ func SetFromGOFLAGS(flags flag.FlagSet) {
if f == nil {
continue
}
+
+ // Use flags.Set consistently (instead of f.Value.Set) so that a subsequent
+ // call to flags.Visit will correctly visit the flags that have been set.
+
if fb, ok := f.Value.(boolFlag); ok && fb.IsBoolFlag() {
if hasValue {
- if err := fb.Set(value); err != nil {
+ if err := flags.Set(f.Name, value); err != nil {
fmt.Fprintf(flags.Output(), "go: invalid boolean value %q for flag %s (from %s): %v\n", value, name, where, err)
flags.Usage()
}
} else {
- if err := fb.Set("true"); err != nil {
+ if err := flags.Set(f.Name, "true"); err != nil {
fmt.Fprintf(flags.Output(), "go: invalid boolean flag %s (from %s): %v\n", name, where, err)
flags.Usage()
}
@@ -142,7 +146,7 @@ func SetFromGOFLAGS(flags flag.FlagSet) {
fmt.Fprintf(flags.Output(), "go: flag needs an argument: %s (from %s)\n", name, where)
flags.Usage()
}
- if err := f.Value.Set(value); err != nil {
+ if err := flags.Set(f.Name, value); err != nil {
fmt.Fprintf(flags.Output(), "go: invalid value %q for flag %s (from %s): %v\n", value, name, where, err)
flags.Usage()
}
diff --git a/libgo/go/cmd/go/internal/cache/cache.go b/libgo/go/cmd/go/internal/cache/cache.go
index 8797398..15545ac 100644
--- a/libgo/go/cmd/go/internal/cache/cache.go
+++ b/libgo/go/cmd/go/internal/cache/cache.go
@@ -108,7 +108,7 @@ const (
// GODEBUG=gocacheverify=1.
var verify = false
-var errVerifyMode = errors.New("gocachverify=1")
+var errVerifyMode = errors.New("gocacheverify=1")
// DebugTest is set when GODEBUG=gocachetest=1 is in the environment.
var DebugTest = false
diff --git a/libgo/go/cmd/go/internal/cfg/cfg.go b/libgo/go/cmd/go/internal/cfg/cfg.go
index 61dc6bd..7f8f8e9 100644
--- a/libgo/go/cmd/go/internal/cfg/cfg.go
+++ b/libgo/go/cmd/go/internal/cfg/cfg.go
@@ -236,6 +236,7 @@ var (
GOROOTpkg = filepath.Join(GOROOT, "pkg")
GOROOTsrc = filepath.Join(GOROOT, "src")
GOROOT_FINAL = findGOROOT_FINAL()
+ GOMODCACHE = envOr("GOMODCACHE", gopathDir("pkg/mod"))
// Used in envcmd.MkEnv and build ID computations.
GOARM = envOr("GOARM", fmt.Sprint(objabi.GOARM))
@@ -253,6 +254,8 @@ var (
GOINSECURE = Getenv("GOINSECURE")
)
+var SumdbDir = gopathDir("pkg/sumdb")
+
// GetArchEnv returns the name and setting of the
// GOARCH-specific architecture environment variable.
// If the current architecture has no GOARCH-specific variable,
@@ -364,3 +367,11 @@ func isGOROOT(path string) bool {
}
return stat.IsDir()
}
+
+func gopathDir(rel string) string {
+ list := filepath.SplitList(BuildContext.GOPATH)
+ if len(list) == 0 || list[0] == "" {
+ return ""
+ }
+ return filepath.Join(list[0], rel)
+}
diff --git a/libgo/go/cmd/go/internal/clean/clean.go b/libgo/go/cmd/go/internal/clean/clean.go
index 69e1748..99704cb 100644
--- a/libgo/go/cmd/go/internal/clean/clean.go
+++ b/libgo/go/cmd/go/internal/clean/clean.go
@@ -137,20 +137,27 @@ func runClean(cmd *base.Command, args []string) {
if cfg.BuildN || cfg.BuildX {
b.Showcmd("", "rm -r %s", strings.Join(subdirs, " "))
}
- for _, d := range subdirs {
- // Only print the first error - there may be many.
- // This also mimics what os.RemoveAll(dir) would do.
- if err := os.RemoveAll(d); err != nil && !printedErrors {
- printedErrors = true
- base.Errorf("go clean -cache: %v", err)
+ if !cfg.BuildN {
+ for _, d := range subdirs {
+ // Only print the first error - there may be many.
+ // This also mimics what os.RemoveAll(dir) would do.
+ if err := os.RemoveAll(d); err != nil && !printedErrors {
+ printedErrors = true
+ base.Errorf("go clean -cache: %v", err)
+ }
}
}
}
logFile := filepath.Join(dir, "log.txt")
- if err := os.RemoveAll(logFile); err != nil && !printedErrors {
- printedErrors = true
- base.Errorf("go clean -cache: %v", err)
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd("", "rm -f %s", logFile)
+ }
+ if !cfg.BuildN {
+ if err := os.RemoveAll(logFile); err != nil && !printedErrors {
+ printedErrors = true
+ base.Errorf("go clean -cache: %v", err)
+ }
}
}
}
@@ -186,14 +193,14 @@ func runClean(cmd *base.Command, args []string) {
}
if cleanModcache {
- if modfetch.PkgMod == "" {
+ if cfg.GOMODCACHE == "" {
base.Fatalf("go clean -modcache: no module cache")
}
if cfg.BuildN || cfg.BuildX {
- b.Showcmd("", "rm -rf %s", modfetch.PkgMod)
+ b.Showcmd("", "rm -rf %s", cfg.GOMODCACHE)
}
if !cfg.BuildN {
- if err := modfetch.RemoveAll(modfetch.PkgMod); err != nil {
+ if err := modfetch.RemoveAll(cfg.GOMODCACHE); err != nil {
base.Errorf("go clean -modcache: %v", err)
}
}
@@ -232,7 +239,7 @@ func clean(p *load.Package) {
cleaned[p] = true
if p.Dir == "" {
- base.Errorf("can't load package: %v", p.Error)
+ base.Errorf("%v", p.Error)
return
}
dirs, err := ioutil.ReadDir(p.Dir)
diff --git a/libgo/go/cmd/go/internal/cmdflag/flag.go b/libgo/go/cmd/go/internal/cmdflag/flag.go
index 3f93432..8abb7e5 100644
--- a/libgo/go/cmd/go/internal/cmdflag/flag.go
+++ b/libgo/go/cmd/go/internal/cmdflag/flag.go
@@ -6,13 +6,10 @@
package cmdflag
import (
+ "errors"
"flag"
"fmt"
- "os"
- "strconv"
"strings"
-
- "cmd/go/internal/base"
)
// The flag handling part of go commands such as test is large and distracting.
@@ -20,141 +17,113 @@ import (
// our command line are for us, and some are for the binary we're running,
// and some are for both.
-// Defn defines a flag we know about.
-type Defn struct {
- Name string // Name on command line.
- BoolVar *bool // If it's a boolean flag, this points to it.
- Value flag.Value // The flag.Value represented.
- PassToTest bool // Pass to the test binary? Used only by go test.
- Present bool // Flag has been seen.
-}
+// ErrFlagTerminator indicates the distinguished token "--", which causes the
+// flag package to treat all subsequent arguments as non-flags.
+var ErrFlagTerminator = errors.New("flag terminator")
-// IsBool reports whether v is a bool flag.
-func IsBool(v flag.Value) bool {
- vv, ok := v.(interface {
- IsBoolFlag() bool
- })
- if ok {
- return vv.IsBoolFlag()
- }
- return false
+// A FlagNotDefinedError indicates a flag-like argument that does not correspond
+// to any registered flag in a FlagSet.
+type FlagNotDefinedError struct {
+ RawArg string // the original argument, like --foo or -foo=value
+ Name string
+ HasValue bool // is this the -foo=value or --foo=value form?
+ Value string // only provided if HasValue is true
}
-// SetBool sets the addressed boolean to the value.
-func SetBool(cmd string, flag *bool, value string) {
- x, err := strconv.ParseBool(value)
- if err != nil {
- SyntaxError(cmd, "illegal bool flag value "+value)
- }
- *flag = x
+func (e FlagNotDefinedError) Error() string {
+ return fmt.Sprintf("flag provided but not defined: -%s", e.Name)
}
-// SetInt sets the addressed integer to the value.
-func SetInt(cmd string, flag *int, value string) {
- x, err := strconv.Atoi(value)
- if err != nil {
- SyntaxError(cmd, "illegal int flag value "+value)
- }
- *flag = x
+// A NonFlagError indicates an argument that is not a syntactically-valid flag.
+type NonFlagError struct {
+ RawArg string
}
-// SyntaxError reports an argument syntax error and exits the program.
-func SyntaxError(cmd, msg string) {
- fmt.Fprintf(os.Stderr, "go %s: %s\n", cmd, msg)
- if cmd == "test" {
- fmt.Fprintf(os.Stderr, `run "go help %s" or "go help testflag" for more information`+"\n", cmd)
- } else {
- fmt.Fprintf(os.Stderr, `run "go help %s" for more information`+"\n", cmd)
- }
- base.SetExitStatus(2)
- base.Exit()
+func (e NonFlagError) Error() string {
+ return fmt.Sprintf("not a flag: %q", e.RawArg)
}
-// AddKnownFlags registers the flags in defns with base.AddKnownFlag.
-func AddKnownFlags(cmd string, defns []*Defn) {
- for _, f := range defns {
- base.AddKnownFlag(f.Name)
- base.AddKnownFlag(cmd + "." + f.Name)
- }
-}
+// ParseOne sees if args[0] is present in the given flag set and if so,
+// sets its value and returns the flag along with the remaining (unused) arguments.
+//
+// ParseOne always returns either a non-nil Flag or a non-nil error,
+// and always consumes at least one argument (even on error).
+//
+// Unlike (*flag.FlagSet).Parse, ParseOne does not log its own errors.
+func ParseOne(fs *flag.FlagSet, args []string) (f *flag.Flag, remainingArgs []string, err error) {
+ // This function is loosely derived from (*flag.FlagSet).parseOne.
-// Parse sees if argument i is present in the definitions and if so,
-// returns its definition, value, and whether it consumed an extra word.
-// If the flag begins (cmd.Name()+".") it is ignored for the purpose of this function.
-func Parse(cmd string, usage func(), defns []*Defn, args []string, i int) (f *Defn, value string, extra bool) {
- arg := args[i]
- if strings.HasPrefix(arg, "--") { // reduce two minuses to one
- arg = arg[1:]
+ raw, args := args[0], args[1:]
+ arg := raw
+ if strings.HasPrefix(arg, "--") {
+ if arg == "--" {
+ return nil, args, ErrFlagTerminator
+ }
+ arg = arg[1:] // reduce two minuses to one
}
+
switch arg {
case "-?", "-h", "-help":
- usage()
+ return nil, args, flag.ErrHelp
}
- if arg == "" || arg[0] != '-' {
- return
+ if len(arg) < 2 || arg[0] != '-' || arg[1] == '-' || arg[1] == '=' {
+ return nil, args, NonFlagError{RawArg: raw}
}
+
name := arg[1:]
- // If there's already a prefix such as "test.", drop it for now.
- name = strings.TrimPrefix(name, cmd+".")
- equals := strings.Index(name, "=")
- if equals >= 0 {
- value = name[equals+1:]
- name = name[:equals]
+ hasValue := false
+ value := ""
+ if i := strings.Index(name, "="); i >= 0 {
+ value = name[i+1:]
+ hasValue = true
+ name = name[0:i]
}
- for _, f = range defns {
- if name == f.Name {
- // Booleans are special because they have modes -x, -x=true, -x=false.
- if f.BoolVar != nil || IsBool(f.Value) {
- if equals < 0 { // Otherwise, it's been set and will be verified in SetBool.
- value = "true"
- } else {
- // verify it parses
- SetBool(cmd, new(bool), value)
- }
- } else { // Non-booleans must have a value.
- extra = equals < 0
- if extra {
- if i+1 >= len(args) {
- SyntaxError(cmd, "missing argument for flag "+f.Name)
- }
- value = args[i+1]
- }
- }
- if f.Present {
- SyntaxError(cmd, f.Name+" flag may be set only once")
- }
- f.Present = true
- return
+
+ f = fs.Lookup(name)
+ if f == nil {
+ return nil, args, FlagNotDefinedError{
+ RawArg: raw,
+ Name: name,
+ HasValue: hasValue,
+ Value: value,
}
}
- f = nil
- return
-}
-// FindGOFLAGS extracts and returns the flags matching defns from GOFLAGS.
-// Ideally the caller would mention that the flags were from GOFLAGS
-// when reporting errors, but that's too hard for now.
-func FindGOFLAGS(defns []*Defn) []string {
- var flags []string
- for _, flag := range base.GOFLAGS() {
- // Flags returned by base.GOFLAGS are well-formed, one of:
- // -x
- // --x
- // -x=value
- // --x=value
- if strings.HasPrefix(flag, "--") {
- flag = flag[1:]
+ // Use fs.Set instead of f.Value.Set below so that any subsequent call to
+ // fs.Visit will correctly visit the flags that have been set.
+
+ failf := func(format string, a ...interface{}) (*flag.Flag, []string, error) {
+ return f, args, fmt.Errorf(format, a...)
+ }
+
+ if fv, ok := f.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
+ if hasValue {
+ if err := fs.Set(name, value); err != nil {
+ return failf("invalid boolean value %q for -%s: %v", value, name, err)
+ }
+ } else {
+ if err := fs.Set(name, "true"); err != nil {
+ return failf("invalid boolean flag %s: %v", name, err)
+ }
}
- name := flag[1:]
- if i := strings.Index(name, "="); i >= 0 {
- name = name[:i]
+ } else {
+ // It must have a value, which might be the next argument.
+ if !hasValue && len(args) > 0 {
+ // value is the next arg
+ hasValue = true
+ value, args = args[0], args[1:]
}
- for _, f := range defns {
- if name == f.Name {
- flags = append(flags, flag)
- break
- }
+ if !hasValue {
+ return failf("flag needs an argument: -%s", name)
+ }
+ if err := fs.Set(name, value); err != nil {
+ return failf("invalid value %q for flag -%s: %v", value, name, err)
}
}
- return flags
+
+ return f, args, nil
+}
+
+type boolFlag interface {
+ IsBoolFlag() bool
}
diff --git a/libgo/go/cmd/go/internal/envcmd/env.go b/libgo/go/cmd/go/internal/envcmd/env.go
index d2d5ed9..252025d 100644
--- a/libgo/go/cmd/go/internal/envcmd/env.go
+++ b/libgo/go/cmd/go/internal/envcmd/env.go
@@ -77,6 +77,7 @@ func MkEnv() []cfg.EnvVar {
{Name: "GOHOSTARCH", Value: runtime.GOARCH},
{Name: "GOHOSTOS", Value: runtime.GOOS},
{Name: "GOINSECURE", Value: cfg.GOINSECURE},
+ {Name: "GOMODCACHE", Value: cfg.GOMODCACHE},
{Name: "GONOPROXY", Value: cfg.GONOPROXY},
{Name: "GONOSUMDB", Value: cfg.GONOSUMDB},
{Name: "GOOS", Value: cfg.Goos},
diff --git a/libgo/go/cmd/go/internal/fmtcmd/fmt.go b/libgo/go/cmd/go/internal/fmtcmd/fmt.go
index 408af52..d6894ed 100644
--- a/libgo/go/cmd/go/internal/fmtcmd/fmt.go
+++ b/libgo/go/cmd/go/internal/fmtcmd/fmt.go
@@ -6,11 +6,11 @@
package fmtcmd
import (
+ "errors"
"fmt"
"os"
"path/filepath"
"runtime"
- "strings"
"sync"
"cmd/go/internal/base"
@@ -72,11 +72,12 @@ func runFmt(cmd *base.Command, args []string) {
continue
}
if pkg.Error != nil {
- if strings.HasPrefix(pkg.Error.Err.Error(), "build constraints exclude all Go files") {
+ var nogo *load.NoGoError
+ if errors.As(pkg.Error, &nogo) && len(pkg.InternalAllGoFiles()) > 0 {
// Skip this error, as we will format
// all files regardless.
} else {
- base.Errorf("can't load package: %s", pkg.Error)
+ base.Errorf("%v", pkg.Error)
continue
}
}
diff --git a/libgo/go/cmd/go/internal/generate/generate.go b/libgo/go/cmd/go/internal/generate/generate.go
index 315db69..093b198 100644
--- a/libgo/go/cmd/go/internal/generate/generate.go
+++ b/libgo/go/cmd/go/internal/generate/generate.go
@@ -9,7 +9,10 @@ import (
"bufio"
"bytes"
"fmt"
+ "go/parser"
+ "go/token"
"io"
+ "io/ioutil"
"log"
"os"
"os/exec"
@@ -119,6 +122,9 @@ in the file, one at a time. The go generate tool also sets the build
tag "generate" so that files may be examined by go generate but ignored
during build.
+For packages with invalid code, generate processes only source files with a
+valid package clause.
+
If any generator returns an error exit status, "go generate" skips
all further processing for that package.
@@ -169,7 +175,7 @@ func runGenerate(cmd *base.Command, args []string) {
// Even if the arguments are .go files, this loop suffices.
printed := false
- for _, pkg := range load.Packages(args) {
+ for _, pkg := range load.PackagesAndErrors(args) {
if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main {
if !printed {
fmt.Fprintf(os.Stderr, "go: not generating in packages in dependency modules\n")
@@ -178,18 +184,14 @@ func runGenerate(cmd *base.Command, args []string) {
continue
}
- pkgName := pkg.Name
-
for _, file := range pkg.InternalGoFiles() {
- if !generate(pkgName, file) {
+ if !generate(file) {
break
}
}
- pkgName += "_test"
-
for _, file := range pkg.InternalXGoFiles() {
- if !generate(pkgName, file) {
+ if !generate(file) {
break
}
}
@@ -197,16 +199,23 @@ func runGenerate(cmd *base.Command, args []string) {
}
// generate runs the generation directives for a single file.
-func generate(pkg, absFile string) bool {
- fd, err := os.Open(absFile)
+func generate(absFile string) bool {
+ src, err := ioutil.ReadFile(absFile)
if err != nil {
log.Fatalf("generate: %s", err)
}
- defer fd.Close()
+
+ // Parse package clause
+ filePkg, err := parser.ParseFile(token.NewFileSet(), "", src, parser.PackageClauseOnly)
+ if err != nil {
+ // Invalid package clause - ignore file.
+ return true
+ }
+
g := &Generator{
- r: fd,
+ r: bytes.NewReader(src),
path: absFile,
- pkg: pkg,
+ pkg: filePkg.Name.String(),
commands: make(map[string][]string),
}
return g.run()
diff --git a/libgo/go/cmd/go/internal/get/get.go b/libgo/go/cmd/go/internal/get/get.go
index 500e3e0..d38350c 100644
--- a/libgo/go/cmd/go/internal/get/get.go
+++ b/libgo/go/cmd/go/internal/get/get.go
@@ -7,7 +7,6 @@ package get
import (
"fmt"
- "go/build"
"os"
"path/filepath"
"runtime"
@@ -194,12 +193,28 @@ func downloadPaths(patterns []string) []string {
for _, arg := range patterns {
if strings.Contains(arg, "@") {
base.Fatalf("go: cannot use path@version syntax in GOPATH mode")
+ continue
+ }
+
+ // Guard against 'go get x.go', a common mistake.
+ // Note that package and module paths may end with '.go', so only print an error
+ // if the argument has no slash or refers to an existing file.
+ if strings.HasSuffix(arg, ".go") {
+ if !strings.Contains(arg, "/") {
+ base.Errorf("go get %s: arguments must be package or module paths", arg)
+ continue
+ }
+ if fi, err := os.Stat(arg); err == nil && !fi.IsDir() {
+ base.Errorf("go get: %s exists as a file, but 'go get' requires package arguments", arg)
+ }
}
}
+ base.ExitIfErrors()
+
var pkgs []string
for _, m := range search.ImportPathsQuiet(patterns) {
- if len(m.Pkgs) == 0 && strings.Contains(m.Pattern, "...") {
- pkgs = append(pkgs, m.Pattern)
+ if len(m.Pkgs) == 0 && strings.Contains(m.Pattern(), "...") {
+ pkgs = append(pkgs, m.Pattern())
} else {
pkgs = append(pkgs, m.Pkgs...)
}
@@ -285,10 +300,16 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
// We delay this until after reloadPackage so that the old entry
// for p has been replaced in the package cache.
if wildcardOkay && strings.Contains(arg, "...") {
- if build.IsLocalImport(arg) {
- args = search.MatchPackagesInFS(arg).Pkgs
+ match := search.NewMatch(arg)
+ if match.IsLocal() {
+ match.MatchDirs()
+ args = match.Dirs
} else {
- args = search.MatchPackages(arg).Pkgs
+ match.MatchPackages()
+ args = match.Pkgs
+ }
+ for _, err := range match.Errs {
+ base.Errorf("%s", err)
}
isWildcard = true
}
diff --git a/libgo/go/cmd/go/internal/get/vcs.go b/libgo/go/cmd/go/internal/get/vcs.go
index 2e4d638..fd37fcb 100644
--- a/libgo/go/cmd/go/internal/get/vcs.go
+++ b/libgo/go/cmd/go/internal/get/vcs.go
@@ -430,7 +430,7 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
cmd := exec.Command(v.cmd, args...)
cmd.Dir = dir
- cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
+ cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
if cfg.BuildX {
fmt.Fprintf(os.Stderr, "cd %s\n", dir)
fmt.Fprintf(os.Stderr, "%s %s\n", v.cmd, strings.Join(args, " "))
diff --git a/libgo/go/cmd/go/internal/help/help.go b/libgo/go/cmd/go/internal/help/help.go
index edb4a2a..7a730fc 100644
--- a/libgo/go/cmd/go/internal/help/help.go
+++ b/libgo/go/cmd/go/internal/help/help.go
@@ -93,7 +93,7 @@ Use "go help{{with .LongName}} {{.}}{{end}} <command>" for more information abou
{{if eq (.UsageLine) "go"}}
Additional help topics:
{{range .Commands}}{{if and (not .Runnable) (not .Commands)}}
- {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+ {{.Name | printf "%-15s"}} {{.Short}}{{end}}{{end}}
Use "go help{{with .LongName}} {{.}}{{end}} <topic>" for more information about that topic.
{{end}}
diff --git a/libgo/go/cmd/go/internal/help/helpdoc.go b/libgo/go/cmd/go/internal/help/helpdoc.go
index 6a843f4..e1f0521 100644
--- a/libgo/go/cmd/go/internal/help/helpdoc.go
+++ b/libgo/go/cmd/go/internal/help/helpdoc.go
@@ -493,6 +493,8 @@ General-purpose environment variables:
GOCACHE
The directory where the go command will store cached
information for reuse in future builds.
+ GOMODCACHE
+ The directory where the go command will store downloaded modules.
GODEBUG
Enable various debugging facilities. See 'go doc runtime'
for details.
@@ -510,6 +512,9 @@ General-purpose environment variables:
Comma-separated list of glob patterns (in the syntax of Go's path.Match)
of module path prefixes that should always be fetched in an insecure
manner. Only applies to dependencies that are being fetched directly.
+ Unlike the -insecure flag on 'go get', GOINSECURE does not disable
+ checksum database validation. GOPRIVATE or GONOSUMDB may be used
+ to achieve that.
GOOS
The operating system for which to compile code.
Examples are linux, darwin, windows, netbsd.
@@ -762,3 +767,95 @@ GODEBUG=gocachetest=1 causes the go command to print details of its
decisions about whether to reuse a cached test result.
`,
}
+
+var HelpBuildConstraint = &base.Command{
+ UsageLine: "buildconstraint",
+ Short: "build constraints",
+ Long: `
+A build constraint, also known as a build tag, is a line comment that begins
+
+ // +build
+
+that lists the conditions under which a file should be included in the package.
+Constraints may appear in any kind of source file (not just Go), but
+they must appear near the top of the file, preceded
+only by blank lines and other line comments. These rules mean that in Go
+files a build constraint must appear before the package clause.
+
+To distinguish build constraints from package documentation, a series of
+build constraints must be followed by a blank line.
+
+A build constraint is evaluated as the OR of space-separated options.
+Each option evaluates as the AND of its comma-separated terms.
+Each term consists of letters, digits, underscores, and dots.
+A term may be negated with a preceding !.
+For example, the build constraint:
+
+ // +build linux,386 darwin,!cgo
+
+corresponds to the boolean formula:
+
+ (linux AND 386) OR (darwin AND (NOT cgo))
+
+A file may have multiple build constraints. The overall constraint is the AND
+of the individual constraints. That is, the build constraints:
+
+ // +build linux darwin
+ // +build amd64
+
+corresponds to the boolean formula:
+
+ (linux OR darwin) AND amd64
+
+During a particular build, the following words are satisfied:
+
+ - the target operating system, as spelled by runtime.GOOS, set with the
+ GOOS environment variable.
+ - the target architecture, as spelled by runtime.GOARCH, set with the
+ GOARCH environment variable.
+ - the compiler being used, either "gc" or "gccgo"
+ - "cgo", if the cgo command is supported (see CGO_ENABLED in
+ 'go help environment').
+ - a term for each Go major release, through the current version:
+ "go1.1" from Go version 1.1 onward, "go1.12" from Go 1.12, and so on.
+ - any additional tags given by the -tags flag (see 'go help build').
+
+There are no separate build tags for beta or minor releases.
+
+If a file's name, after stripping the extension and a possible _test suffix,
+matches any of the following patterns:
+ *_GOOS
+ *_GOARCH
+ *_GOOS_GOARCH
+(example: source_windows_amd64.go) where GOOS and GOARCH represent
+any known operating system and architecture values respectively, then
+the file is considered to have an implicit build constraint requiring
+those terms (in addition to any explicit constraints in the file).
+
+Using GOOS=android matches build tags and files as for GOOS=linux
+in addition to android tags and files.
+
+Using GOOS=illumos matches build tags and files as for GOOS=solaris
+in addition to illumos tags and files.
+
+To keep a file from being considered for the build:
+
+ // +build ignore
+
+(any other unsatisfied word will work as well, but "ignore" is conventional.)
+
+To build a file only when using cgo, and only on Linux and OS X:
+
+ // +build linux,cgo darwin,cgo
+
+Such a file is usually paired with another file implementing the
+default functionality for other systems, which in this case would
+carry the constraint:
+
+ // +build !linux,!darwin !cgo
+
+Naming a file dns_windows.go will cause it to be included only when
+building the package for Windows; similarly, math_386.s will be included
+only when building the package for 32-bit x86.
+`,
+}
diff --git a/libgo/go/cmd/go/internal/list/list.go b/libgo/go/cmd/go/internal/list/list.go
index 8d979e2..6ca1561 100644
--- a/libgo/go/cmd/go/internal/list/list.go
+++ b/libgo/go/cmd/go/internal/list/list.go
@@ -451,6 +451,7 @@ func runList(cmd *base.Command, args []string) {
pkgs = load.PackagesAndErrors(args)
} else {
pkgs = load.Packages(args)
+ base.ExitIfErrors()
}
if cache.Default() == nil {
@@ -471,9 +472,6 @@ func runList(cmd *base.Command, args []string) {
c := cache.Default()
// Add test binaries to packages to be listed.
for _, p := range pkgs {
- if p.Error != nil {
- continue
- }
if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 {
var pmain, ptest, pxtest *load.Package
var err error
diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go
index 06b6e23..e146e34 100644
--- a/libgo/go/cmd/go/internal/load/pkg.go
+++ b/libgo/go/cmd/go/internal/load/pkg.go
@@ -187,20 +187,17 @@ type PackageInternal struct {
Gccgoflags []string // -gccgoflags for this package
}
+// A NoGoError indicates that no Go files for the package were applicable to the
+// build for that package.
+//
+// That may be because there were no files whatsoever, or because all files were
+// excluded, or because all non-excluded files were test sources.
type NoGoError struct {
Package *Package
}
func (e *NoGoError) Error() string {
- // Count files beginning with _ and ., which we will pretend don't exist at all.
- dummy := 0
- for _, name := range e.Package.IgnoredGoFiles {
- if strings.HasPrefix(name, "_") || strings.HasPrefix(name, ".") {
- dummy++
- }
- }
-
- if len(e.Package.IgnoredGoFiles) > dummy {
+ if len(e.Package.constraintIgnoredGoFiles()) > 0 {
// Go files exist, but they were ignored due to build constraints.
return "build constraints exclude all Go files in " + e.Package.Dir
}
@@ -213,6 +210,77 @@ func (e *NoGoError) Error() string {
return "no Go files in " + e.Package.Dir
}
+// setLoadPackageDataError presents an error found when loading package data
+// as a *PackageError. It has special cases for some common errors to improve
+// messages shown to users and reduce redundancy.
+//
+// setLoadPackageDataError returns true if it's safe to load information about
+// imported packages, for example, if there was a parse error loading imports
+// in one file, but other files are okay.
+func (p *Package) setLoadPackageDataError(err error, path string, stk *ImportStack, importPos []token.Position) {
+ matchErr, isMatchErr := err.(*search.MatchError)
+ if isMatchErr && matchErr.Match.Pattern() == path {
+ if matchErr.Match.IsLiteral() {
+ // The error has a pattern has a pattern similar to the import path.
+ // It may be slightly different (./foo matching example.com/foo),
+ // but close enough to seem redundant.
+ // Unwrap the error so we don't show the pattern.
+ err = matchErr.Err
+ }
+ }
+
+ // Replace (possibly wrapped) *build.NoGoError with *load.NoGoError.
+ // The latter is more specific about the cause.
+ var nogoErr *build.NoGoError
+ if errors.As(err, &nogoErr) {
+ if p.Dir == "" && nogoErr.Dir != "" {
+ p.Dir = nogoErr.Dir
+ }
+ err = &NoGoError{Package: p}
+ }
+
+ // Report the error on the importing package if the problem is with the import declaration
+ // for example, if the package doesn't exist or if the import path is malformed.
+ // On the other hand, don't include a position if the problem is with the imported package,
+ // for example there are no Go files (NoGoError), or there's a problem in the imported
+ // package's source files themselves.
+ //
+ // TODO(matloob): Perhaps make each of those the errors in the first group
+ // (including modload.ImportMissingError, and the corresponding
+ // "cannot find package %q in any of" GOPATH-mode error
+ // produced in build.(*Context).Import; modload.AmbiguousImportError,
+ // and modload.PackageNotInModuleError; and the malformed module path errors
+ // produced in golang.org/x/mod/module.CheckMod) implement an interface
+ // to make it easier to check for them? That would save us from having to
+ // move the modload errors into this package to avoid a package import cycle,
+ // and from having to export an error type for the errors produced in build.
+ if !isMatchErr && nogoErr != nil {
+ stk.Push(path)
+ defer stk.Pop()
+ }
+
+ // Take only the first error from a scanner.ErrorList. PackageError only
+ // has room for one position, so we report the first error with a position
+ // instead of all of the errors without a position.
+ var pos string
+ if scanErr, ok := err.(scanner.ErrorList); ok && len(scanErr) > 0 {
+ scanPos := scanErr[0].Pos
+ scanPos.Filename = base.ShortPath(scanPos.Filename)
+ pos = scanPos.String()
+ err = errors.New(scanErr[0].Msg)
+ }
+
+ p.Error = &PackageError{
+ ImportStack: stk.Copy(),
+ Pos: pos,
+ Err: err,
+ }
+
+ if path != stk.Top() {
+ p = setErrorPos(p, importPos)
+ }
+}
+
// Resolve returns the resolved version of imports,
// which should be p.TestImports or p.XTestImports, NOT p.Imports.
// The imports in p.TestImports and p.XTestImports are not recursively
@@ -304,19 +372,16 @@ func (p *Package) copyBuild(pp *build.Package) {
// A PackageError describes an error loading information about a package.
type PackageError struct {
- ImportStack []string // shortest path from package named on command line to this one
- Pos string // position of error
- Err error // the error itself
- IsImportCycle bool // the error is an import cycle
- Hard bool // whether the error is soft or hard; soft errors are ignored in some places
+ ImportStack []string // shortest path from package named on command line to this one
+ Pos string // position of error
+ Err error // the error itself
+ IsImportCycle bool // the error is an import cycle
+ Hard bool // whether the error is soft or hard; soft errors are ignored in some places
+ alwaysPrintStack bool // whether to always print the ImportStack
}
func (p *PackageError) Error() string {
- // Import cycles deserve special treatment.
- if p.IsImportCycle {
- return fmt.Sprintf("%s\npackage %s\n", p.Err, strings.Join(p.ImportStack, "\n\timports "))
- }
- if p.Pos != "" {
+ if p.Pos != "" && (len(p.ImportStack) == 0 || !p.alwaysPrintStack) {
// Omit import stack. The full path to the file where the error
// is the most important thing.
return p.Pos + ": " + p.Err.Error()
@@ -328,17 +393,18 @@ func (p *PackageError) Error() string {
// last path on the stack, we don't omit the path. An error like
// "package A imports B: error loading C caused by B" would not be clearer
// if "imports B" were omitted.
- stack := p.ImportStack
- var ierr ImportPathError
- if len(stack) > 0 && errors.As(p.Err, &ierr) && ierr.ImportPath() == stack[len(stack)-1] {
- stack = stack[:len(stack)-1]
- }
- if len(stack) == 0 {
+ if len(p.ImportStack) == 0 {
return p.Err.Error()
}
- return "package " + strings.Join(stack, "\n\timports ") + ": " + p.Err.Error()
+ var optpos string
+ if p.Pos != "" {
+ optpos = "\n\t" + p.Pos
+ }
+ return "package " + strings.Join(p.ImportStack, "\n\timports ") + optpos + ": " + p.Err.Error()
}
+func (p *PackageError) Unwrap() error { return p.Err }
+
// PackageError implements MarshalJSON so that Err is marshaled as a string
// and non-essential fields are omitted.
func (p *PackageError) MarshalJSON() ([]byte, error) {
@@ -409,6 +475,13 @@ func (s *ImportStack) Copy() []string {
return append([]string{}, *s...)
}
+func (s *ImportStack) Top() string {
+ if len(*s) == 0 {
+ return ""
+ }
+ return (*s)[len(*s)-1]
+}
+
// shorterThan reports whether sp is shorter than t.
// We use this to record the shortest import sequence
// that leads to a particular package.
@@ -536,9 +609,6 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
panic("LoadImport called with empty package path")
}
- stk.Push(path)
- defer stk.Pop()
-
var parentPath, parentRoot string
parentIsStd := false
if parent != nil {
@@ -551,6 +621,11 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
pre.preloadImports(bp.Imports, bp)
}
if bp == nil {
+ if importErr, ok := err.(ImportPathError); !ok || importErr.ImportPath() != path {
+ // Only add path to the error's import stack if it's not already present on the error.
+ stk.Push(path)
+ defer stk.Pop()
+ }
return &Package{
PackagePublic: PackagePublic{
ImportPath: path,
@@ -565,7 +640,9 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
importPath := bp.ImportPath
p := packageCache[importPath]
if p != nil {
+ stk.Push(path)
p = reusePackage(p, stk)
+ stk.Pop()
} else {
p = new(Package)
p.Internal.Local = build.IsLocalImport(path)
@@ -575,17 +652,15 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
// Load package.
// loadPackageData may return bp != nil even if an error occurs,
// in order to return partial information.
- p.load(stk, bp, err)
- if p.Error != nil && p.Error.Pos == "" {
- p = setErrorPos(p, importPos)
- }
+ p.load(path, stk, importPos, bp, err)
if !cfg.ModulesEnabled && path != cleanImport(path) {
p.Error = &PackageError{
ImportStack: stk.Copy(),
- Err: fmt.Errorf("non-canonical import path: %q should be %q", path, pathpkg.Clean(path)),
+ Err: ImportErrorf(path, "non-canonical import path %q: should be %q", path, pathpkg.Clean(path)),
}
p.Incomplete = true
+ setErrorPos(p, importPos)
}
}
@@ -594,7 +669,7 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
return setErrorPos(perr, importPos)
}
if mode&ResolveImport != 0 {
- if perr := disallowVendor(srcDir, path, p, stk); perr != p {
+ if perr := disallowVendor(srcDir, path, parentPath, p, stk); perr != p {
return setErrorPos(perr, importPos)
}
}
@@ -1232,7 +1307,7 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p *
// as if it were generated into the testing directory tree
// (it's actually in a temporary directory outside any Go tree).
// This cleans up a former kludge in passing functionality to the testing package.
- if strings.HasPrefix(p.ImportPath, "testing/internal") && len(*stk) >= 2 && (*stk)[len(*stk)-2] == "testmain" {
+ if str.HasPathPrefix(p.ImportPath, "testing/internal") && importerPath == "testmain" {
return p
}
@@ -1254,11 +1329,10 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p *
return p
}
- // The stack includes p.ImportPath.
- // If that's the only thing on the stack, we started
+ // importerPath is empty: we started
// with a name given on the command line, not an
// import. Anything listed on the command line is fine.
- if len(*stk) == 1 {
+ if importerPath == "" {
return p
}
@@ -1307,8 +1381,9 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p *
// Internal is present, and srcDir is outside parent's tree. Not allowed.
perr := *p
perr.Error = &PackageError{
- ImportStack: stk.Copy(),
- Err: ImportErrorf(p.ImportPath, "use of internal package "+p.ImportPath+" not allowed"),
+ alwaysPrintStack: true,
+ ImportStack: stk.Copy(),
+ Err: ImportErrorf(p.ImportPath, "use of internal package "+p.ImportPath+" not allowed"),
}
perr.Incomplete = true
return &perr
@@ -1336,16 +1411,15 @@ func findInternal(path string) (index int, ok bool) {
// disallowVendor checks that srcDir is allowed to import p as path.
// If the import is allowed, disallowVendor returns the original package p.
// If not, it returns a new package containing just an appropriate error.
-func disallowVendor(srcDir string, path string, p *Package, stk *ImportStack) *Package {
- // The stack includes p.ImportPath.
- // If that's the only thing on the stack, we started
+func disallowVendor(srcDir string, path string, importerPath string, p *Package, stk *ImportStack) *Package {
+ // If the importerPath is empty, we started
// with a name given on the command line, not an
// import. Anything listed on the command line is fine.
- if len(*stk) == 1 {
+ if importerPath == "" {
return p
}
- if perr := disallowVendorVisibility(srcDir, p, stk); perr != p {
+ if perr := disallowVendorVisibility(srcDir, p, importerPath, stk); perr != p {
return perr
}
@@ -1368,12 +1442,12 @@ func disallowVendor(srcDir string, path string, p *Package, stk *ImportStack) *P
// is not subject to the rules, only subdirectories of vendor.
// This allows people to have packages and commands named vendor,
// for maximal compatibility with existing source trees.
-func disallowVendorVisibility(srcDir string, p *Package, stk *ImportStack) *Package {
- // The stack includes p.ImportPath.
- // If that's the only thing on the stack, we started
+func disallowVendorVisibility(srcDir string, p *Package, importerPath string, stk *ImportStack) *Package {
+ // The stack does not include p.ImportPath.
+ // If there's nothing on the stack, we started
// with a name given on the command line, not an
// import. Anything listed on the command line is fine.
- if len(*stk) == 1 {
+ if importerPath == "" {
return p
}
@@ -1517,7 +1591,8 @@ func (p *Package) DefaultExecName() string {
// load populates p using information from bp, err, which should
// be the result of calling build.Context.Import.
-func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
+// stk contains the import stack, not including path itself.
+func (p *Package) load(path string, stk *ImportStack, importPos []token.Position, bp *build.Package, err error) {
p.copyBuild(bp)
// The localPrefix is the path we interpret ./ imports relative to.
@@ -1535,21 +1610,22 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
ImportStack: stk.Copy(),
Err: err,
}
+
+ // Add the importer's position information if the import position exists, and
+ // the current package being examined is the importer.
+ // If we have not yet accepted package p onto the import stack,
+ // then the cause of the error is not within p itself: the error
+ // must be either in an explicit command-line argument,
+ // or on the importer side (indicated by a non-empty importPos).
+ if path != stk.Top() && len(importPos) > 0 {
+ p = setErrorPos(p, importPos)
+ }
}
}
if err != nil {
- if _, ok := err.(*build.NoGoError); ok {
- err = &NoGoError{Package: p}
- }
p.Incomplete = true
-
- setError(base.ExpandScanner(err))
- if _, isScanErr := err.(scanner.ErrorList); !isScanErr {
- return
- }
- // Fall through if there was an error parsing a file. 'go list -e' should
- // still report imports and other metadata.
+ p.setLoadPackageDataError(err, path, stk, importPos)
}
useBindir := p.Name == "main"
@@ -1563,6 +1639,8 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
if useBindir {
// Report an error when the old code.google.com/p/go.tools paths are used.
if InstallTargetDir(p) == StalePath {
+ // TODO(matloob): remove this branch, and StalePath itself. code.google.com/p/go is so
+ // old, even this code checking for it is stale now!
newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
e := ImportErrorf(p.ImportPath, "the %v command has moved; use %v instead.", p.ImportPath, newPath)
setError(e)
@@ -1671,6 +1749,23 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
}
}
+ // Check for case-insensitive collisions of import paths.
+ fold := str.ToFold(p.ImportPath)
+ if other := foldPath[fold]; other == "" {
+ foldPath[fold] = p.ImportPath
+ } else if other != p.ImportPath {
+ setError(ImportErrorf(p.ImportPath, "case-insensitive import collision: %q and %q", p.ImportPath, other))
+ return
+ }
+
+ if !SafeArg(p.ImportPath) {
+ setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
+ return
+ }
+
+ stk.Push(path)
+ defer stk.Pop()
+
// Check for case-insensitive collision of input files.
// To avoid problems on case-insensitive files, we reject any package
// where two different input files have equal names under a case-insensitive
@@ -1699,10 +1794,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
setError(fmt.Errorf("invalid input directory name %q", name))
return
}
- if !SafeArg(p.ImportPath) {
- setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
- return
- }
// Build list of imported packages and full dependency list.
imports := make([]*Package, 0, len(p.Imports))
@@ -1766,15 +1857,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
return
}
- // Check for case-insensitive collisions of import paths.
- fold := str.ToFold(p.ImportPath)
- if other := foldPath[fold]; other == "" {
- foldPath[fold] = p.ImportPath
- } else if other != p.ImportPath {
- setError(ImportErrorf(p.ImportPath, "case-insensitive import collision: %q and %q", p.ImportPath, other))
- return
- }
-
if cfg.ModulesEnabled && p.Error == nil {
mainPath := p.ImportPath
if p.Internal.CmdlineFiles {
@@ -1877,10 +1959,11 @@ func externalLinkingForced(p *Package) bool {
// Some targets must use external linking even inside GOROOT.
switch cfg.BuildContext.GOOS {
case "android":
- return true
+ if cfg.BuildContext.GOARCH != "arm64" {
+ return true
+ }
case "darwin":
- switch cfg.BuildContext.GOARCH {
- case "arm", "arm64":
+ if cfg.BuildContext.GOARCH == "arm64" {
return true
}
}
@@ -1938,13 +2021,22 @@ func (p *Package) InternalXGoFiles() []string {
// using absolute paths. "Possibly relevant" means that files are not excluded
// due to build tags, but files with names beginning with . or _ are still excluded.
func (p *Package) InternalAllGoFiles() []string {
- var extra []string
+ return p.mkAbs(str.StringList(p.constraintIgnoredGoFiles(), p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles))
+}
+
+// constraintIgnoredGoFiles returns the list of Go files ignored for reasons
+// other than having a name beginning with '.' or '_'.
+func (p *Package) constraintIgnoredGoFiles() []string {
+ if len(p.IgnoredGoFiles) == 0 {
+ return nil
+ }
+ files := make([]string, 0, len(p.IgnoredGoFiles))
for _, f := range p.IgnoredGoFiles {
- if f != "" && f[0] != '.' || f[0] != '_' {
- extra = append(extra, f)
+ if f != "" && f[0] != '.' && f[0] != '_' {
+ files = append(files, f)
}
}
- return p.mkAbs(str.StringList(extra, p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles))
+ return files
}
// usesSwig reports whether the package needs to run SWIG.
@@ -2038,7 +2130,7 @@ func Packages(args []string) []*Package {
var pkgs []*Package
for _, pkg := range PackagesAndErrors(args) {
if pkg.Error != nil {
- base.Errorf("can't load package: %s", pkg.Error)
+ base.Errorf("%v", pkg.Error)
continue
}
pkgs = append(pkgs, pkg)
@@ -2078,13 +2170,13 @@ func PackagesAndErrors(patterns []string) []*Package {
for _, m := range matches {
for _, pkg := range m.Pkgs {
if pkg == "" {
- panic(fmt.Sprintf("ImportPaths returned empty package for pattern %s", m.Pattern))
+ panic(fmt.Sprintf("ImportPaths returned empty package for pattern %s", m.Pattern()))
}
p := loadImport(pre, pkg, base.Cwd, nil, &stk, nil, 0)
- p.Match = append(p.Match, m.Pattern)
+ p.Match = append(p.Match, m.Pattern())
p.Internal.CmdlinePkg = true
- if m.Literal {
- // Note: do not set = m.Literal unconditionally
+ if m.IsLiteral() {
+ // Note: do not set = m.IsLiteral unconditionally
// because maybe we'll see p matching both
// a literal and also a non-literal pattern.
p.Internal.CmdlinePkgLiteral = true
@@ -2095,6 +2187,25 @@ func PackagesAndErrors(patterns []string) []*Package {
seenPkg[p] = true
pkgs = append(pkgs, p)
}
+
+ if len(m.Errs) > 0 {
+ // In addition to any packages that were actually resolved from the
+ // pattern, there was some error in resolving the pattern itself.
+ // Report it as a synthetic package.
+ p := new(Package)
+ p.ImportPath = m.Pattern()
+ // Pass an empty ImportStack and nil importPos: the error arose from a pattern, not an import.
+ var stk ImportStack
+ var importPos []token.Position
+ p.setLoadPackageDataError(m.Errs[0], m.Pattern(), &stk, importPos)
+ p.Incomplete = true
+ p.Match = append(p.Match, m.Pattern())
+ p.Internal.CmdlinePkg = true
+ if m.IsLiteral() {
+ p.Internal.CmdlinePkgLiteral = true
+ }
+ pkgs = append(pkgs, p)
+ }
}
// Now that CmdlinePkg is set correctly,
@@ -2130,7 +2241,7 @@ func PackagesForBuild(args []string) []*Package {
printed := map[*PackageError]bool{}
for _, pkg := range pkgs {
if pkg.Error != nil {
- base.Errorf("can't load package: %s", pkg.Error)
+ base.Errorf("%v", pkg.Error)
printed[pkg.Error] = true
}
for _, err := range pkg.DepsErrors {
@@ -2140,7 +2251,7 @@ func PackagesForBuild(args []string) []*Package {
// Only print each once.
if !printed[err] {
printed[err] = true
- base.Errorf("%s", err)
+ base.Errorf("%v", err)
}
}
}
@@ -2232,9 +2343,7 @@ func GoFilesPackage(gofiles []string) *Package {
pkg := new(Package)
pkg.Internal.Local = true
pkg.Internal.CmdlineFiles = true
- stk.Push("main")
- pkg.load(&stk, bp, err)
- stk.Pop()
+ pkg.load("command-line-arguments", &stk, nil, bp, err)
pkg.Internal.LocalPrefix = dirToImportPath(dir)
pkg.ImportPath = "command-line-arguments"
pkg.Target = ""
diff --git a/libgo/go/cmd/go/internal/load/test.go b/libgo/go/cmd/go/internal/load/test.go
index fefc7d2..6d251e8 100644
--- a/libgo/go/cmd/go/internal/load/test.go
+++ b/libgo/go/cmd/go/internal/load/test.go
@@ -6,7 +6,6 @@ package load
import (
"bytes"
- "cmd/go/internal/base"
"cmd/go/internal/str"
"errors"
"fmt"
@@ -26,6 +25,7 @@ import (
var TestMainDeps = []string{
// Dependencies for testmain.
"os",
+ "reflect",
"testing",
"testing/internal/testdeps",
}
@@ -55,7 +55,6 @@ func TestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Packag
}
if len(p1.DepsErrors) > 0 {
perr := p1.DepsErrors[0]
- perr.Pos = "" // show full import stack
err = perr
break
}
@@ -271,7 +270,7 @@ func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *
// afterward that gathers t.Cover information.
t, err := loadTestFuncs(ptest)
if err != nil && pmain.Error == nil {
- pmain.Error = &PackageError{Err: err}
+ pmain.setLoadPackageDataError(err, p.ImportPath, &stk, nil)
}
t.Cover = cover
if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
@@ -540,7 +539,7 @@ var testFileSet = token.NewFileSet()
func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
if err != nil {
- return base.ExpandScanner(err)
+ return err
}
for _, d := range f.Decls {
n, ok := d.(*ast.FuncDecl)
@@ -612,8 +611,9 @@ var testmainTmpl = lazytemplate.New("main", `
package main
import (
-{{if not .TestMain}}
"os"
+{{if .TestMain}}
+ "reflect"
{{end}}
"testing"
"testing/internal/testdeps"
@@ -704,6 +704,7 @@ func main() {
m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples)
{{with .TestMain}}
{{.Package}}.{{.Name}}(m)
+ os.Exit(int(reflect.ValueOf(m).Elem().FieldByName("exitCode").Int()))
{{else}}
os.Exit(m.Run())
{{end}}
diff --git a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go
index a14362b..c3e09bb 100644
--- a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go
+++ b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go
@@ -13,19 +13,19 @@
// or an F_OFD_SETLK command for 'fcntl', that allows for better concurrency and
// does not require per-inode bookkeeping in the application.
//
-// TODO(bcmills): If we add a build tag for Illumos (see golang.org/issue/20603)
-// then Illumos should use F_OFD_SETLK, and the resulting code would be as
-// simple as filelock_unix.go. We will still need the code in this file for AIX
-// or as long as Oracle Solaris provides only F_SETLK.
+// TODO(golang.org/issue/35618): add a syscall.Flock binding for Illumos and
+// switch it over to use filelock_unix.go.
package filelock
import (
"errors"
"io"
+ "math/rand"
"os"
"sync"
"syscall"
+ "time"
)
type lockType int16
@@ -93,7 +93,67 @@ func lock(f File, lt lockType) (err error) {
wait <- f
}
- err = setlkw(f.Fd(), lt)
+ // Spurious EDEADLK errors arise on platforms that compute deadlock graphs at
+ // the process, rather than thread, level. Consider processes P and Q, with
+ // threads P.1, P.2, and Q.3. The following trace is NOT a deadlock, but will be
+ // reported as a deadlock on systems that consider only process granularity:
+ //
+ // P.1 locks file A.
+ // Q.3 locks file B.
+ // Q.3 blocks on file A.
+ // P.2 blocks on file B. (This is erroneously reported as a deadlock.)
+ // P.1 unlocks file A.
+ // Q.3 unblocks and locks file A.
+ // Q.3 unlocks files A and B.
+ // P.2 unblocks and locks file B.
+ // P.2 unlocks file B.
+ //
+ // These spurious errors were observed in practice on AIX and Solaris in
+ // cmd/go: see https://golang.org/issue/32817.
+ //
+ // We work around this bug by treating EDEADLK as always spurious. If there
+ // really is a lock-ordering bug between the interacting processes, it will
+ // become a livelock instead, but that's not appreciably worse than if we had
+ // a proper flock implementation (which generally does not even attempt to
+ // diagnose deadlocks).
+ //
+ // In the above example, that changes the trace to:
+ //
+ // P.1 locks file A.
+ // Q.3 locks file B.
+ // Q.3 blocks on file A.
+ // P.2 spuriously fails to lock file B and goes to sleep.
+ // P.1 unlocks file A.
+ // Q.3 unblocks and locks file A.
+ // Q.3 unlocks files A and B.
+ // P.2 wakes up and locks file B.
+ // P.2 unlocks file B.
+ //
+ // We know that the retry loop will not introduce a *spurious* livelock
+ // because, according to the POSIX specification, EDEADLK is only to be
+ // returned when “the lock is blocked by a lock from another process”.
+ // If that process is blocked on some lock that we are holding, then the
+ // resulting livelock is due to a real deadlock (and would manifest as such
+ // when using, for example, the flock implementation of this package).
+ // If the other process is *not* blocked on some other lock that we are
+ // holding, then it will eventually release the requested lock.
+
+ nextSleep := 1 * time.Millisecond
+ const maxSleep = 500 * time.Millisecond
+ for {
+ err = setlkw(f.Fd(), lt)
+ if err != syscall.EDEADLK {
+ break
+ }
+ time.Sleep(nextSleep)
+
+ nextSleep += nextSleep
+ if nextSleep > maxSleep {
+ nextSleep = maxSleep
+ }
+ // Apply 10% jitter to avoid synchronizing collisions when we finally unblock.
+ nextSleep += time.Duration((0.1*rand.Float64() - 0.05) * float64(nextSleep))
+ }
if err != nil {
unlock(f)
diff --git a/libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go b/libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go
index 8f7a7d5..416c69d 100644
--- a/libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go
+++ b/libgo/go/cmd/go/internal/lockedfile/lockedfile_test.go
@@ -8,8 +8,11 @@
package lockedfile_test
import (
+ "fmt"
+ "internal/testenv"
"io/ioutil"
"os"
+ "os/exec"
"path/filepath"
"testing"
"time"
@@ -172,3 +175,98 @@ func TestCanLockExistingFile(t *testing.T) {
f.Close()
wait(t)
}
+
+// TestSpuriousEDEADLK verifies that the spurious EDEADLK reported in
+// https://golang.org/issue/32817 no longer occurs.
+func TestSpuriousEDEADLK(t *testing.T) {
+ // P.1 locks file A.
+ // Q.3 locks file B.
+ // Q.3 blocks on file A.
+ // P.2 blocks on file B. (Spurious EDEADLK occurs here.)
+ // P.1 unlocks file A.
+ // Q.3 unblocks and locks file A.
+ // Q.3 unlocks files A and B.
+ // P.2 unblocks and locks file B.
+ // P.2 unlocks file B.
+
+ testenv.MustHaveExec(t)
+
+ dirVar := t.Name() + "DIR"
+
+ if dir := os.Getenv(dirVar); dir != "" {
+ // Q.3 locks file B.
+ b, err := lockedfile.Edit(filepath.Join(dir, "B"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer b.Close()
+
+ if err := ioutil.WriteFile(filepath.Join(dir, "locked"), []byte("ok"), 0666); err != nil {
+ t.Fatal(err)
+ }
+
+ // Q.3 blocks on file A.
+ a, err := lockedfile.Edit(filepath.Join(dir, "A"))
+ // Q.3 unblocks and locks file A.
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer a.Close()
+
+ // Q.3 unlocks files A and B.
+ return
+ }
+
+ dir, remove := mustTempDir(t)
+ defer remove()
+
+ // P.1 locks file A.
+ a, err := lockedfile.Edit(filepath.Join(dir, "A"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ cmd := exec.Command(os.Args[0], "-test.run="+t.Name())
+ cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%s", dirVar, dir))
+
+ qDone := make(chan struct{})
+ waitQ := mustBlock(t, "Edit A and B in subprocess", func() {
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Errorf("%v:\n%s", err, out)
+ }
+ close(qDone)
+ })
+
+ // Wait until process Q has either failed or locked file B.
+ // Otherwise, P.2 might not block on file B as intended.
+locked:
+ for {
+ if _, err := os.Stat(filepath.Join(dir, "locked")); !os.IsNotExist(err) {
+ break locked
+ }
+ select {
+ case <-qDone:
+ break locked
+ case <-time.After(1 * time.Millisecond):
+ }
+ }
+
+ waitP2 := mustBlock(t, "Edit B", func() {
+ // P.2 blocks on file B. (Spurious EDEADLK occurs here.)
+ b, err := lockedfile.Edit(filepath.Join(dir, "B"))
+ // P.2 unblocks and locks file B.
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ // P.2 unlocks file B.
+ b.Close()
+ })
+
+ // P.1 unlocks file A.
+ a.Close()
+
+ waitQ(t)
+ waitP2(t)
+}
diff --git a/libgo/go/cmd/go/internal/modcmd/download.go b/libgo/go/cmd/go/internal/modcmd/download.go
index 7d5294d..5844349 100644
--- a/libgo/go/cmd/go/internal/modcmd/download.go
+++ b/libgo/go/cmd/go/internal/modcmd/download.go
@@ -24,7 +24,8 @@ var cmdDownload = &base.Command{
Long: `
Download downloads the named modules, which can be module patterns selecting
dependencies of the main module or module queries of the form path@version.
-With no arguments, download applies to all dependencies of the main module.
+With no arguments, download applies to all dependencies of the main module
+(equivalent to 'go mod download all').
The go command will automatically download modules as needed during ordinary
execution. The "go mod download" command is useful mainly for pre-filling
diff --git a/libgo/go/cmd/go/internal/modcmd/vendor.go b/libgo/go/cmd/go/internal/modcmd/vendor.go
index 0c00d12..8509ceb 100644
--- a/libgo/go/cmd/go/internal/modcmd/vendor.go
+++ b/libgo/go/cmd/go/internal/modcmd/vendor.go
@@ -123,6 +123,11 @@ func runVendor(cmd *base.Command, args []string) {
fmt.Fprintf(os.Stderr, "go: no dependencies to vendor\n")
return
}
+
+ if err := os.MkdirAll(vdir, 0777); err != nil {
+ base.Fatalf("go mod vendor: %v", err)
+ }
+
if err := ioutil.WriteFile(filepath.Join(vdir, "modules.txt"), buf.Bytes(), 0666); err != nil {
base.Fatalf("go mod vendor: %v", err)
}
diff --git a/libgo/go/cmd/go/internal/modcmd/verify.go b/libgo/go/cmd/go/internal/modcmd/verify.go
index ac3f135..b7fd7fa 100644
--- a/libgo/go/cmd/go/internal/modcmd/verify.go
+++ b/libgo/go/cmd/go/internal/modcmd/verify.go
@@ -10,6 +10,7 @@ import (
"fmt"
"io/ioutil"
"os"
+ "runtime"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
@@ -52,17 +53,41 @@ func runVerify(cmd *base.Command, args []string) {
base.Fatalf("go: cannot find main module; see 'go help modules'")
}
}
+
+ // Only verify up to GOMAXPROCS zips at once.
+ type token struct{}
+ sem := make(chan token, runtime.GOMAXPROCS(0))
+
+ // Use a slice of result channels, so that the output is deterministic.
+ mods := modload.LoadBuildList()[1:]
+ errsChans := make([]<-chan []error, len(mods))
+
+ for i, mod := range mods {
+ sem <- token{}
+ errsc := make(chan []error, 1)
+ errsChans[i] = errsc
+ mod := mod // use a copy to avoid data races
+ go func() {
+ errsc <- verifyMod(mod)
+ <-sem
+ }()
+ }
+
ok := true
- for _, mod := range modload.LoadBuildList()[1:] {
- ok = verifyMod(mod) && ok
+ for _, errsc := range errsChans {
+ errs := <-errsc
+ for _, err := range errs {
+ base.Errorf("%s", err)
+ ok = false
+ }
}
if ok {
fmt.Printf("all modules verified\n")
}
}
-func verifyMod(mod module.Version) bool {
- ok := true
+func verifyMod(mod module.Version) []error {
+ var errs []error
zip, zipErr := modfetch.CachePath(mod, "zip")
if zipErr == nil {
_, zipErr = os.Stat(zip)
@@ -73,10 +98,10 @@ func verifyMod(mod module.Version) bool {
if zipErr != nil && errors.Is(zipErr, os.ErrNotExist) &&
dirErr != nil && errors.Is(dirErr, os.ErrNotExist) {
// Nothing downloaded yet. Nothing to verify.
- return true
+ return nil
}
- base.Errorf("%s %s: missing ziphash: %v", mod.Path, mod.Version, err)
- return false
+ errs = append(errs, fmt.Errorf("%s %s: missing ziphash: %v", mod.Path, mod.Version, err))
+ return errs
}
h := string(bytes.TrimSpace(data))
@@ -85,11 +110,10 @@ func verifyMod(mod module.Version) bool {
} else {
hZ, err := dirhash.HashZip(zip, dirhash.DefaultHash)
if err != nil {
- base.Errorf("%s %s: %v", mod.Path, mod.Version, err)
- return false
+ errs = append(errs, fmt.Errorf("%s %s: %v", mod.Path, mod.Version, err))
+ return errs
} else if hZ != h {
- base.Errorf("%s %s: zip has been modified (%v)", mod.Path, mod.Version, zip)
- ok = false
+ errs = append(errs, fmt.Errorf("%s %s: zip has been modified (%v)", mod.Path, mod.Version, zip))
}
}
if dirErr != nil && errors.Is(dirErr, os.ErrNotExist) {
@@ -98,13 +122,12 @@ func verifyMod(mod module.Version) bool {
hD, err := dirhash.HashDir(dir, mod.Path+"@"+mod.Version, dirhash.DefaultHash)
if err != nil {
- base.Errorf("%s %s: %v", mod.Path, mod.Version, err)
- return false
+ errs = append(errs, fmt.Errorf("%s %s: %v", mod.Path, mod.Version, err))
+ return errs
}
if hD != h {
- base.Errorf("%s %s: dir has been modified (%v)", mod.Path, mod.Version, dir)
- ok = false
+ errs = append(errs, fmt.Errorf("%s %s: dir has been modified (%v)", mod.Path, mod.Version, dir))
}
}
- return ok
+ return errs
}
diff --git a/libgo/go/cmd/go/internal/modconv/convert_test.go b/libgo/go/cmd/go/internal/modconv/convert_test.go
index a2a2601..a04a13b 100644
--- a/libgo/go/cmd/go/internal/modconv/convert_test.go
+++ b/libgo/go/cmd/go/internal/modconv/convert_test.go
@@ -18,7 +18,6 @@ import (
"cmd/go/internal/cfg"
"cmd/go/internal/modfetch"
- "cmd/go/internal/modfetch/codehost"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
@@ -42,8 +41,7 @@ func testMain(m *testing.M) int {
log.Fatal(err)
}
defer os.RemoveAll(dir)
- modfetch.PkgMod = filepath.Join(dir, "pkg/mod")
- codehost.WorkRoot = filepath.Join(dir, "codework")
+ cfg.GOMODCACHE = filepath.Join(dir, "pkg/mod")
return m.Run()
}
diff --git a/libgo/go/cmd/go/internal/modfetch/cache.go b/libgo/go/cmd/go/internal/modfetch/cache.go
index d6ff068..e3074b7 100644
--- a/libgo/go/cmd/go/internal/modfetch/cache.go
+++ b/libgo/go/cmd/go/internal/modfetch/cache.go
@@ -26,17 +26,17 @@ import (
"golang.org/x/mod/semver"
)
-var PkgMod string // $GOPATH/pkg/mod; set by package modload
-
func cacheDir(path string) (string, error) {
- if PkgMod == "" {
- return "", fmt.Errorf("internal error: modfetch.PkgMod not set")
+ if cfg.GOMODCACHE == "" {
+ // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
+ // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
+ return "", fmt.Errorf("internal error: cfg.GOMODCACHE not set")
}
enc, err := module.EscapePath(path)
if err != nil {
return "", err
}
- return filepath.Join(PkgMod, "cache/download", enc, "/@v"), nil
+ return filepath.Join(cfg.GOMODCACHE, "cache/download", enc, "/@v"), nil
}
func CachePath(m module.Version, suffix string) (string, error) {
@@ -63,8 +63,10 @@ func CachePath(m module.Version, suffix string) (string, error) {
// along with the directory if the directory does not exist or if the directory
// is not completely populated.
func DownloadDir(m module.Version) (string, error) {
- if PkgMod == "" {
- return "", fmt.Errorf("internal error: modfetch.PkgMod not set")
+ if cfg.GOMODCACHE == "" {
+ // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
+ // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
+ return "", fmt.Errorf("internal error: cfg.GOMODCACHE not set")
}
enc, err := module.EscapePath(m.Path)
if err != nil {
@@ -81,7 +83,7 @@ func DownloadDir(m module.Version) (string, error) {
return "", err
}
- dir := filepath.Join(PkgMod, enc+"@"+encVer)
+ dir := filepath.Join(cfg.GOMODCACHE, enc+"@"+encVer)
if fi, err := os.Stat(dir); os.IsNotExist(err) {
return dir, err
} else if err != nil {
@@ -131,11 +133,13 @@ func lockVersion(mod module.Version) (unlock func(), err error) {
// user's working directory.
// If err is nil, the caller MUST eventually call the unlock function.
func SideLock() (unlock func(), err error) {
- if PkgMod == "" {
- base.Fatalf("go: internal error: modfetch.PkgMod not set")
+ if cfg.GOMODCACHE == "" {
+ // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
+ // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
+ base.Fatalf("go: internal error: cfg.GOMODCACHE not set")
}
- path := filepath.Join(PkgMod, "cache", "lock")
+ path := filepath.Join(cfg.GOMODCACHE, "cache", "lock")
if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
return nil, fmt.Errorf("failed to create cache directory: %w", err)
}
@@ -456,7 +460,7 @@ func readDiskStat(path, rev string) (file string, info *RevInfo, err error) {
// just to find out about a commit we already know about
// (and have cached under its pseudo-version).
func readDiskStatByHash(path, rev string) (file string, info *RevInfo, err error) {
- if PkgMod == "" {
+ if cfg.GOMODCACHE == "" {
// Do not download to current directory.
return "", nil, errNotCached
}
diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/codehost.go b/libgo/go/cmd/go/internal/modfetch/codehost/codehost.go
index 5867288..d85eddf 100644
--- a/libgo/go/cmd/go/internal/modfetch/codehost/codehost.go
+++ b/libgo/go/cmd/go/internal/modfetch/codehost/codehost.go
@@ -153,15 +153,11 @@ func ShortenSHA1(rev string) string {
return rev
}
-// WorkRoot is the root of the cached work directory.
-// It is set by cmd/go/internal/modload.InitMod.
-var WorkRoot string
-
// WorkDir returns the name of the cached work directory to use for the
// given repository type and name.
func WorkDir(typ, name string) (dir, lockfile string, err error) {
- if WorkRoot == "" {
- return "", "", fmt.Errorf("codehost.WorkRoot not set")
+ if cfg.GOMODCACHE == "" {
+ return "", "", fmt.Errorf("neither GOPATH nor GOMODCACHE are set")
}
// We name the work directory for the SHA256 hash of the type and name.
@@ -173,7 +169,7 @@ func WorkDir(typ, name string) (dir, lockfile string, err error) {
return "", "", fmt.Errorf("codehost.WorkDir: type cannot contain colon")
}
key := typ + ":" + name
- dir = filepath.Join(WorkRoot, fmt.Sprintf("%x", sha256.Sum256([]byte(key))))
+ dir = filepath.Join(cfg.GOMODCACHE, "cache/vcs", fmt.Sprintf("%x", sha256.Sum256([]byte(key))))
if cfg.BuildX {
fmt.Fprintf(os.Stderr, "mkdir -p %s # %s %s\n", filepath.Dir(dir), typ, name)
diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/git.go b/libgo/go/cmd/go/internal/modfetch/codehost/git.go
index f08df51..3192132 100644
--- a/libgo/go/cmd/go/internal/modfetch/codehost/git.go
+++ b/libgo/go/cmd/go/internal/modfetch/codehost/git.go
@@ -27,11 +27,6 @@ import (
"golang.org/x/mod/semver"
)
-// GitRepo returns the code repository at the given Git remote reference.
-func GitRepo(remote string) (Repo, error) {
- return newGitRepoCached(remote, false)
-}
-
// LocalGitRepo is like Repo but accepts both Git remote references
// and paths to repositories on the local file system.
func LocalGitRepo(remote string) (Repo, error) {
diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go b/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go
index cc32a1e..ba27c70 100644
--- a/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go
+++ b/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go
@@ -57,7 +57,6 @@ func testMain(m *testing.M) int {
log.Fatal(err)
}
defer os.RemoveAll(dir)
- WorkRoot = dir
if testenv.HasExternalNetwork() && testenv.HasExec() {
// Clone gitrepo1 into a local directory.
diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/shell.go b/libgo/go/cmd/go/internal/modfetch/codehost/shell.go
index 835bc53..2762c55 100644
--- a/libgo/go/cmd/go/internal/modfetch/codehost/shell.go
+++ b/libgo/go/cmd/go/internal/modfetch/codehost/shell.go
@@ -20,6 +20,7 @@ import (
"strings"
"time"
+ "cmd/go/internal/cfg"
"cmd/go/internal/modfetch/codehost"
)
@@ -29,7 +30,7 @@ func usage() {
}
func main() {
- codehost.WorkRoot = "/tmp/vcswork"
+ cfg.GOMODCACHE = "/tmp/vcswork"
log.SetFlags(0)
log.SetPrefix("shell: ")
flag.Usage = usage
diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo.go b/libgo/go/cmd/go/internal/modfetch/coderepo.go
index d1d24a40..d043903 100644
--- a/libgo/go/cmd/go/internal/modfetch/coderepo.go
+++ b/libgo/go/cmd/go/internal/modfetch/coderepo.go
@@ -563,7 +563,7 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
return err
}
if !t.Equal(info.Time.Truncate(time.Second)) {
- return fmt.Errorf("does not match version-control timestamp (%s)", info.Time.UTC().Format(time.RFC3339))
+ return fmt.Errorf("does not match version-control timestamp (expected %s)", info.Time.UTC().Format(pseudoVersionTimestampFormat))
}
tagPrefix := ""
@@ -1012,28 +1012,3 @@ func hasPathPrefix(s, prefix string) bool {
return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
}
}
-
-func isVendoredPackage(name string) bool {
- var i int
- if strings.HasPrefix(name, "vendor/") {
- i += len("vendor/")
- } else if j := strings.Index(name, "/vendor/"); j >= 0 {
- // This offset looks incorrect; this should probably be
- //
- // i = j + len("/vendor/")
- //
- // (See https://golang.org/issue/31562.)
- //
- // Unfortunately, we can't fix it without invalidating checksums.
- // Fortunately, the error appears to be strictly conservative: we'll retain
- // vendored packages that we should have pruned, but we won't prune
- // non-vendored packages that we should have retained.
- //
- // Since this defect doesn't seem to break anything, it's not worth fixing
- // for now.
- i += len("/vendor/")
- } else {
- return false
- }
- return strings.Contains(name[i:], "/")
-}
diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
index 3983094..f69c193b 100644
--- a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
+++ b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
@@ -44,7 +44,7 @@ func testMain(m *testing.M) int {
}
defer os.RemoveAll(dir)
- codehost.WorkRoot = dir
+ cfg.GOMODCACHE = dir
return m.Run()
}
diff --git a/libgo/go/cmd/go/internal/modfetch/fetch.go b/libgo/go/cmd/go/internal/modfetch/fetch.go
index aadf883..fd7a5ce 100644
--- a/libgo/go/cmd/go/internal/modfetch/fetch.go
+++ b/libgo/go/cmd/go/internal/modfetch/fetch.go
@@ -35,9 +35,10 @@ var downloadCache par.Cache
// local download cache and returns the name of the directory
// corresponding to the root of the module's file tree.
func Download(mod module.Version) (dir string, err error) {
- if PkgMod == "" {
- // Do not download to current directory.
- return "", fmt.Errorf("missing modfetch.PkgMod")
+ if cfg.GOMODCACHE == "" {
+ // modload.Init exits if GOPATH[0] is empty, and cfg.GOMODCACHE
+ // is set to GOPATH[0]/pkg/mod if GOMODCACHE is empty, so this should never happen.
+ base.Fatalf("go: internal error: cfg.GOMODCACHE not set")
}
// The par.Cache here avoids duplicate work.
@@ -57,11 +58,10 @@ func Download(mod module.Version) (dir string, err error) {
}
func download(mod module.Version) (dir string, err error) {
- // If the directory exists, and no .partial file exists,
- // the module has already been completely extracted.
- // .partial files may be created when future versions of cmd/go
- // extract module zip directories in place instead of extracting
- // to a random temporary directory and renaming.
+ // If the directory exists, and no .partial file exists, the module has
+ // already been completely extracted. .partial files may be created when a
+ // module zip directory is extracted in place instead of being extracted to a
+ // temporary directory and renamed.
dir, err = DownloadDir(mod)
if err == nil {
return dir, nil
@@ -115,31 +115,61 @@ func download(mod module.Version) (dir string, err error) {
return "", err
}
- // Extract the zip file to a temporary directory, then rename it to the
- // final path. That way, we can use the existence of the source directory to
- // signal that it has been extracted successfully, and if someone deletes
- // the entire directory (e.g. as an attempt to prune out file corruption)
- // the module cache will still be left in a recoverable state.
+ // Extract the module zip directory.
+ //
+ // By default, we extract to a temporary directory, then atomically rename to
+ // its final location. We use the existence of the source directory to signal
+ // that it has been extracted successfully (see DownloadDir). If someone
+ // deletes the entire directory (e.g., as an attempt to prune out file
+ // corruption), the module cache will still be left in a recoverable
+ // state.
+ //
+ // Unfortunately, os.Rename may fail with ERROR_ACCESS_DENIED on Windows if
+ // another process opens files in the temporary directory. This is partially
+ // mitigated by using robustio.Rename, which retries os.Rename for a short
+ // time.
+ //
+ // To avoid this error completely, if unzipInPlace is set, we instead create a
+ // .partial file (indicating the directory isn't fully extracted), then we
+ // extract the directory at its final location, then we delete the .partial
+ // file. This is not the default behavior because older versions of Go may
+ // simply stat the directory to check whether it exists without looking for a
+ // .partial file. If multiple versions run concurrently, the older version may
+ // assume a partially extracted directory is complete.
+ // TODO(golang.org/issue/36568): when these older versions are no longer
+ // supported, remove the old default behavior and the unzipInPlace flag.
if err := os.MkdirAll(parentDir, 0777); err != nil {
return "", err
}
- tmpDir, err := ioutil.TempDir(parentDir, tmpPrefix)
- if err != nil {
- return "", err
- }
- defer func() {
+
+ if unzipInPlace {
+ if err := ioutil.WriteFile(partialPath, nil, 0666); err != nil {
+ return "", err
+ }
+ if err := modzip.Unzip(dir, mod, zipfile); err != nil {
+ fmt.Fprintf(os.Stderr, "-> %s\n", err)
+ if rmErr := RemoveAll(dir); rmErr == nil {
+ os.Remove(partialPath)
+ }
+ return "", err
+ }
+ if err := os.Remove(partialPath); err != nil {
+ return "", err
+ }
+ } else {
+ tmpDir, err := ioutil.TempDir(parentDir, tmpPrefix)
if err != nil {
+ return "", err
+ }
+ if err := modzip.Unzip(tmpDir, mod, zipfile); err != nil {
+ fmt.Fprintf(os.Stderr, "-> %s\n", err)
RemoveAll(tmpDir)
+ return "", err
+ }
+ if err := robustio.Rename(tmpDir, dir); err != nil {
+ RemoveAll(tmpDir)
+ return "", err
}
- }()
-
- if err := modzip.Unzip(tmpDir, mod, zipfile); err != nil {
- fmt.Fprintf(os.Stderr, "-> %s\n", err)
- return "", err
- }
-
- if err := robustio.Rename(tmpDir, dir); err != nil {
- return "", err
}
if !cfg.ModCacheRW {
@@ -150,6 +180,17 @@ func download(mod module.Version) (dir string, err error) {
return dir, nil
}
+var unzipInPlace bool
+
+func init() {
+ for _, f := range strings.Split(os.Getenv("GODEBUG"), ",") {
+ if f == "modcacheunzipinplace=1" {
+ unzipInPlace = true
+ break
+ }
+ }
+}
+
var downloadZipCache par.Cache
// DownloadZip downloads the specific module version to the
@@ -321,7 +362,7 @@ func RemoveAll(dir string) error {
}
return nil
})
- return os.RemoveAll(dir)
+ return robustio.RemoveAll(dir)
}
var GoSumFile string // path to go.sum; set by package modload
@@ -416,7 +457,7 @@ func readGoSum(dst map[module.Version][]string, file string, data []byte) error
// checkMod checks the given module's checksum.
func checkMod(mod module.Version) {
- if PkgMod == "" {
+ if cfg.GOMODCACHE == "" {
// Do not use current directory.
return
}
@@ -473,6 +514,7 @@ func checkModSum(mod module.Version, h string) error {
goSum.mu.Lock()
inited, err := initGoSum()
if err != nil {
+ goSum.mu.Unlock()
return err
}
done := inited && haveModSumLocked(mod, h)
@@ -553,7 +595,7 @@ func checkSumDB(mod module.Version, h string) error {
// Sum returns the checksum for the downloaded copy of the given module,
// if present in the download cache.
func Sum(mod module.Version) string {
- if PkgMod == "" {
+ if cfg.GOMODCACHE == "" {
// Do not use current directory.
return ""
}
diff --git a/libgo/go/cmd/go/internal/modfetch/proxy.go b/libgo/go/cmd/go/internal/modfetch/proxy.go
index dcea71a..1c35d0b 100644
--- a/libgo/go/cmd/go/internal/modfetch/proxy.go
+++ b/libgo/go/cmd/go/internal/modfetch/proxy.go
@@ -101,27 +101,51 @@ cached module versions with GOPROXY=https://example.com/proxy.
var proxyOnce struct {
sync.Once
- list []string
+ list []proxySpec
err error
}
-func proxyURLs() ([]string, error) {
+type proxySpec struct {
+ // url is the proxy URL or one of "off", "direct", "noproxy".
+ url string
+
+ // fallBackOnError is true if a request should be attempted on the next proxy
+ // in the list after any error from this proxy. If fallBackOnError is false,
+ // the request will only be attempted on the next proxy if the error is
+ // equivalent to os.ErrNotFound, which is true for 404 and 410 responses.
+ fallBackOnError bool
+}
+
+func proxyList() ([]proxySpec, error) {
proxyOnce.Do(func() {
if cfg.GONOPROXY != "" && cfg.GOPROXY != "direct" {
- proxyOnce.list = append(proxyOnce.list, "noproxy")
+ proxyOnce.list = append(proxyOnce.list, proxySpec{url: "noproxy"})
}
- for _, proxyURL := range strings.Split(cfg.GOPROXY, ",") {
- proxyURL = strings.TrimSpace(proxyURL)
- if proxyURL == "" {
+
+ goproxy := cfg.GOPROXY
+ for goproxy != "" {
+ var url string
+ fallBackOnError := false
+ if i := strings.IndexAny(goproxy, ",|"); i >= 0 {
+ url = goproxy[:i]
+ fallBackOnError = goproxy[i] == '|'
+ goproxy = goproxy[i+1:]
+ } else {
+ url = goproxy
+ goproxy = ""
+ }
+
+ url = strings.TrimSpace(url)
+ if url == "" {
continue
}
- if proxyURL == "off" {
+ if url == "off" {
// "off" always fails hard, so can stop walking list.
- proxyOnce.list = append(proxyOnce.list, "off")
+ proxyOnce.list = append(proxyOnce.list, proxySpec{url: "off"})
break
}
- if proxyURL == "direct" {
- proxyOnce.list = append(proxyOnce.list, "direct")
+ if url == "direct" {
+ proxyOnce.list = append(proxyOnce.list, proxySpec{url: "direct"})
// For now, "direct" is the end of the line. We may decide to add some
// sort of fallback behavior for them in the future, so ignore
// subsequent entries for forward-compatibility.
@@ -131,18 +155,29 @@ func proxyURLs() ([]string, error) {
// Single-word tokens are reserved for built-in behaviors, and anything
// containing the string ":/" or matching an absolute file path must be a
// complete URL. For all other paths, implicitly add "https://".
- if strings.ContainsAny(proxyURL, ".:/") && !strings.Contains(proxyURL, ":/") && !filepath.IsAbs(proxyURL) && !path.IsAbs(proxyURL) {
- proxyURL = "https://" + proxyURL
+ if strings.ContainsAny(url, ".:/") && !strings.Contains(url, ":/") && !filepath.IsAbs(url) && !path.IsAbs(url) {
+ url = "https://" + url
}
// Check that newProxyRepo accepts the URL.
// It won't do anything with the path.
- _, err := newProxyRepo(proxyURL, "golang.org/x/text")
- if err != nil {
+ if _, err := newProxyRepo(url, "golang.org/x/text"); err != nil {
proxyOnce.err = err
return
}
- proxyOnce.list = append(proxyOnce.list, proxyURL)
+
+ proxyOnce.list = append(proxyOnce.list, proxySpec{
+ url: url,
+ fallBackOnError: fallBackOnError,
+ })
+ }
+
+ if len(proxyOnce.list) == 0 ||
+ len(proxyOnce.list) == 1 && proxyOnce.list[0].url == "noproxy" {
+ // There were no proxies, other than the implicit "noproxy" added when
+ // GONOPROXY is set. This can happen if GOPROXY is a non-empty string
+ // like "," or " ".
+ proxyOnce.err = fmt.Errorf("GOPROXY list is not the empty string, but contains no entries")
}
})
@@ -150,44 +185,60 @@ func proxyURLs() ([]string, error) {
}
// TryProxies iterates f over each configured proxy (including "noproxy" and
-// "direct" if applicable) until f returns an error that is not
-// equivalent to os.ErrNotExist.
+// "direct" if applicable) until f returns no error or until f returns an
+// error that is not equivalent to os.ErrNotExist on a proxy configured
+// not to fall back on errors.
//
// TryProxies then returns that final error.
//
// If GOPROXY is set to "off", TryProxies invokes f once with the argument
// "off".
func TryProxies(f func(proxy string) error) error {
- proxies, err := proxyURLs()
+ proxies, err := proxyList()
if err != nil {
return err
}
if len(proxies) == 0 {
- return f("off")
+ panic("GOPROXY list is empty")
}
- var lastAttemptErr error
+ // We try to report the most helpful error to the user. "direct" and "noproxy"
+ // errors are best, followed by proxy errors other than ErrNotExist, followed
+ // by ErrNotExist.
+ //
+ // Note that errProxyOff, errNoproxy, and errUseProxy are equivalent to
+ // ErrNotExist. errUseProxy should only be returned if "noproxy" is the only
+ // proxy. errNoproxy should never be returned, since there should always be a
+ // more useful error from "noproxy" first.
+ const (
+ notExistRank = iota
+ proxyRank
+ directRank
+ )
+ var bestErr error
+ bestErrRank := notExistRank
for _, proxy := range proxies {
- err = f(proxy)
- if !errors.Is(err, os.ErrNotExist) {
- lastAttemptErr = err
- break
+ err := f(proxy.url)
+ if err == nil {
+ return nil
+ }
+ isNotExistErr := errors.Is(err, os.ErrNotExist)
+
+ if proxy.url == "direct" || (proxy.url == "noproxy" && err != errUseProxy) {
+ bestErr = err
+ bestErrRank = directRank
+ } else if bestErrRank <= proxyRank && !isNotExistErr {
+ bestErr = err
+ bestErrRank = proxyRank
+ } else if bestErrRank == notExistRank {
+ bestErr = err
}
- // The error indicates that the module does not exist.
- // In general we prefer to report the last such error,
- // because it indicates the error that occurs after all other
- // options have been exhausted.
- //
- // However, for modules in the NOPROXY list, the most useful error occurs
- // first (with proxy set to "noproxy"), and the subsequent errors are all
- // errNoProxy (which is not particularly helpful). Do not overwrite a more
- // useful error with errNoproxy.
- if lastAttemptErr == nil || !errors.Is(err, errNoproxy) {
- lastAttemptErr = err
+ if !proxy.fallBackOnError && !isNotExistErr {
+ break
}
}
- return lastAttemptErr
+ return bestErr
}
type proxyRepo struct {
@@ -205,12 +256,12 @@ func newProxyRepo(baseURL, path string) (Repo, error) {
// ok
case "file":
if *base != (url.URL{Scheme: base.Scheme, Path: base.Path, RawPath: base.RawPath}) {
- return nil, fmt.Errorf("invalid file:// proxy URL with non-path elements: %s", web.Redacted(base))
+ return nil, fmt.Errorf("invalid file:// proxy URL with non-path elements: %s", base.Redacted())
}
case "":
- return nil, fmt.Errorf("invalid proxy URL missing scheme: %s", web.Redacted(base))
+ return nil, fmt.Errorf("invalid proxy URL missing scheme: %s", base.Redacted())
default:
- return nil, fmt.Errorf("invalid proxy URL scheme (must be https, http, file): %s", web.Redacted(base))
+ return nil, fmt.Errorf("invalid proxy URL scheme (must be https, http, file): %s", base.Redacted())
}
enc, err := module.EscapePath(path)
diff --git a/libgo/go/cmd/go/internal/modfetch/pseudo.go b/libgo/go/cmd/go/internal/modfetch/pseudo.go
index 57dee11..20c0b06 100644
--- a/libgo/go/cmd/go/internal/modfetch/pseudo.go
+++ b/libgo/go/cmd/go/internal/modfetch/pseudo.go
@@ -48,6 +48,8 @@ import (
var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`)
+const pseudoVersionTimestampFormat = "20060102150405"
+
// PseudoVersion returns a pseudo-version for the given major version ("v1")
// preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time,
// and revision identifier (usually a 12-byte commit hash prefix).
@@ -55,7 +57,7 @@ func PseudoVersion(major, older string, t time.Time, rev string) string {
if major == "" {
major = "v0"
}
- segment := fmt.Sprintf("%s-%s", t.UTC().Format("20060102150405"), rev)
+ segment := fmt.Sprintf("%s-%s", t.UTC().Format(pseudoVersionTimestampFormat), rev)
build := semver.Build(older)
older = semver.Canonical(older)
if older == "" {
diff --git a/libgo/go/cmd/go/internal/modfetch/sumdb.go b/libgo/go/cmd/go/internal/modfetch/sumdb.go
index 1ed71df..7973f47 100644
--- a/libgo/go/cmd/go/internal/modfetch/sumdb.go
+++ b/libgo/go/cmd/go/internal/modfetch/sumdb.go
@@ -26,6 +26,7 @@ import (
"cmd/go/internal/lockedfile"
"cmd/go/internal/str"
"cmd/go/internal/web"
+
"golang.org/x/mod/module"
"golang.org/x/mod/sumdb"
"golang.org/x/mod/sumdb/note"
@@ -130,7 +131,7 @@ func (c *dbClient) ReadRemote(path string) ([]byte, error) {
targ := web.Join(c.base, path)
data, err := web.GetBytes(targ)
if false {
- fmt.Fprintf(os.Stderr, "%.3fs %s\n", time.Since(start).Seconds(), web.Redacted(targ))
+ fmt.Fprintf(os.Stderr, "%.3fs %s\n", time.Since(start).Seconds(), targ.Redacted())
}
return data, err
}
@@ -146,49 +147,50 @@ func (c *dbClient) initBase() {
}
// Try proxies in turn until we find out how to connect to this database.
- urls, err := proxyURLs()
- if err != nil {
- c.baseErr = err
- return
- }
- for _, proxyURL := range urls {
- if proxyURL == "noproxy" {
- continue
- }
- if proxyURL == "direct" || proxyURL == "off" {
- break
- }
- proxy, err := url.Parse(proxyURL)
- if err != nil {
- c.baseErr = err
- return
- }
- // Quoting https://golang.org/design/25530-sumdb#proxying-a-checksum-database:
- //
- // Before accessing any checksum database URL using a proxy,
- // the proxy client should first fetch <proxyURL>/sumdb/<sumdb-name>/supported.
- // If that request returns a successful (HTTP 200) response, then the proxy supports
- // proxying checksum database requests. In that case, the client should use
- // the proxied access method only, never falling back to a direct connection to the database.
- // If the /sumdb/<sumdb-name>/supported check fails with a “not found” (HTTP 404)
- // or “gone” (HTTP 410) response, the proxy is unwilling to proxy the checksum database,
- // and the client should connect directly to the database.
- // Any other response is treated as the database being unavailable.
- _, err = web.GetBytes(web.Join(proxy, "sumdb/"+c.name+"/supported"))
- if err == nil {
+ //
+ // Before accessing any checksum database URL using a proxy, the proxy
+ // client should first fetch <proxyURL>/sumdb/<sumdb-name>/supported.
+ //
+ // If that request returns a successful (HTTP 200) response, then the proxy
+ // supports proxying checksum database requests. In that case, the client
+ // should use the proxied access method only, never falling back to a direct
+ // connection to the database.
+ //
+ // If the /sumdb/<sumdb-name>/supported check fails with a “not found” (HTTP
+ // 404) or “gone” (HTTP 410) response, or if the proxy is configured to fall
+ // back on errors, the client will try the next proxy. If there are no
+ // proxies left or if the proxy is "direct" or "off", the client should
+ // connect directly to that database.
+ //
+ // Any other response is treated as the database being unavailable.
+ //
+ // See https://golang.org/design/25530-sumdb#proxying-a-checksum-database.
+ err := TryProxies(func(proxy string) error {
+ switch proxy {
+ case "noproxy":
+ return errUseProxy
+ case "direct", "off":
+ return errProxyOff
+ default:
+ proxyURL, err := url.Parse(proxy)
+ if err != nil {
+ return err
+ }
+ if _, err := web.GetBytes(web.Join(proxyURL, "sumdb/"+c.name+"/supported")); err != nil {
+ return err
+ }
// Success! This proxy will help us.
- c.base = web.Join(proxy, "sumdb/"+c.name)
- return
- }
- // If the proxy serves a non-404/410, give up.
- if !errors.Is(err, os.ErrNotExist) {
- c.baseErr = err
- return
+ c.base = web.Join(proxyURL, "sumdb/"+c.name)
+ return nil
}
+ })
+ if errors.Is(err, os.ErrNotExist) {
+ // No proxies, or all proxies failed (with 404, 410, or were were allowed
+ // to fall back), or we reached an explicit "direct" or "off".
+ c.base = c.direct
+ } else if err != nil {
+ c.baseErr = err
}
-
- // No proxies, or all proxies said 404, or we reached an explicit "direct".
- c.base = c.direct
}
// ReadConfig reads the key from c.key
@@ -198,8 +200,10 @@ func (c *dbClient) ReadConfig(file string) (data []byte, err error) {
return []byte(c.key), nil
}
- // GOPATH/pkg is PkgMod/..
- targ := filepath.Join(PkgMod, "../sumdb/"+file)
+ if cfg.SumdbDir == "" {
+ return nil, errors.New("could not locate sumdb file: missing $GOPATH")
+ }
+ targ := filepath.Join(cfg.SumdbDir, file)
data, err = lockedfile.Read(targ)
if errors.Is(err, os.ErrNotExist) {
// Treat non-existent as empty, to bootstrap the "latest" file
@@ -215,7 +219,10 @@ func (*dbClient) WriteConfig(file string, old, new []byte) error {
// Should not happen.
return fmt.Errorf("cannot write key")
}
- targ := filepath.Join(PkgMod, "../sumdb/"+file)
+ if cfg.SumdbDir == "" {
+ return errors.New("could not locate sumdb file: missing $GOPATH")
+ }
+ targ := filepath.Join(cfg.SumdbDir, file)
os.MkdirAll(filepath.Dir(targ), 0777)
f, err := lockedfile.Edit(targ)
if err != nil {
@@ -245,7 +252,7 @@ func (*dbClient) WriteConfig(file string, old, new []byte) error {
// GOPATH/pkg/mod/cache/download/sumdb,
// which will be deleted by "go clean -modcache".
func (*dbClient) ReadCache(file string) ([]byte, error) {
- targ := filepath.Join(PkgMod, "cache/download/sumdb", file)
+ targ := filepath.Join(cfg.GOMODCACHE, "cache/download/sumdb", file)
data, err := lockedfile.Read(targ)
// lockedfile.Write does not atomically create the file with contents.
// There is a moment between file creation and locking the file for writing,
@@ -259,7 +266,7 @@ func (*dbClient) ReadCache(file string) ([]byte, error) {
// WriteCache updates cached lookups or tiles.
func (*dbClient) WriteCache(file string, data []byte) {
- targ := filepath.Join(PkgMod, "cache/download/sumdb", file)
+ targ := filepath.Join(cfg.GOMODCACHE, "cache/download/sumdb", file)
os.MkdirAll(filepath.Dir(targ), 0777)
lockedfile.Write(targ, bytes.NewReader(data), 0666)
}
diff --git a/libgo/go/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv b/libgo/go/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv
index 6eb8d7f..0906975 100644
--- a/libgo/go/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv
+++ b/libgo/go/cmd/go/internal/modfetch/zip_sum_test/testdata/zip_sums.csv
@@ -40,7 +40,6 @@ git.torproject.org/pluggable-transports/goptlib.git,v1.1.0,h1:LMQAA8pAho+QtYrrVN
gitee.com/nggs/util,v0.0.0-20190830024003-3e49d2efc84b,h1:6KQpPEs326uPrICQy9x/PxmR8U0v/XsFzpt0k1nFKcY=,a062c99c2b560a36168fe51eab8f17f4fadf5d534238881628e83d8d61e51c2a
github.com/1and1/oneandone-cloudserver-sdk-go,v1.0.1,h1:RMTyvS5bjvSWiUcfqfr/E2pxHEMrALvU+E12n6biymg=,7f068808fc0857d7de8c8f829cc380dce1c6611a3fc819daf4421e9bcb75a07c
github.com/99designs/gqlgen,v0.10.1,h1:1BgB6XKGTHq7uH4G1/PYyKe2Kz7/vw3AlvMZlD3TEEY=,04b9e7d8a3df6543cd870325b1140ce9ac3f4bbfd8c90ebecec4f908dd420d08
-github.com/AlexStocks/log4go,v1.0.5,h1:45boeHy0qh0NFBaEhrFT/pUKzQUGf7q2Ux1iQDr/f6o=,59371c2108f62aa9a2233ca8f7de57868ad2c64313b2d68434e0ed6a1748ce2c
github.com/AndreasBriese/bbloom,v0.0.0-20190306092124-e2d15f34fcf9,h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4=,6d7c1af06f8597fde1e86166f26416057392f1b0bdb84f2af555aa461282dd18
github.com/AsynkronIT/goconsole,v0.0.0-20160504192649-bfa12eebf716,h1:Pk/Kzi5O0T4QxfqvbaUsh8UklbJ9BklZ/ClZBptX5WU=,5a2507b89bb4436881718d785a0ef383652aa99782508b7444cf20255082dab9
github.com/Azure/azure-amqp-common-go,v1.1.4,h1:DmPXxmLZwi/71CgRTZIKR6yiKEW3eC42S4gSBhfG7y0=,4b800793ff4fefa86a427c445e3a4671b8d1dcd87a44075f6309cace6b0e01e2
@@ -243,7 +242,6 @@ github.com/beego/x2j,v0.0.0-20131220205130-a0352aadc542,h1:nYXb+3jF6Oq/j8R/y90Xr
github.com/beevik/etree,v1.1.0,h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=,614a33736f8b9262a809f101df5bf71f47777879b1191165b6247d6b67c7468c
github.com/beevik/guid,v0.0.0-20170504223318-d0ea8faecee0,h1:oLd/YLOTOgA4D4aAUhIE8vhl/LAP1ZJrj0mDQpl7GB8=,5add94fcade6c7afa236112c8da300d47ec499ad1789a5e805c8198062dd0749
github.com/beevik/ntp,v0.2.0,h1:sGsd+kAXzT0bfVfzJfce04g+dSRfrs+tbQW8lweuYgw=,42e14f30c23ba2f5ddaff76101016d87f0f0a0f1d96d3d20e42fd02842091c76
-github.com/belogik/goes,v0.0.0-20151229125003-e54d722c3aff,h1:/kO0p2RTGLB8R5gub7ps0GmYpB2O8LXEoPq8tzFDCUI=,f926f1040febe5318efa145541a6fc7898d32514bc13899e812185f05710c5db
github.com/beorn7/perks,v1.0.1,h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=,25bd9e2d94aca770e6dbc1f53725f84f6af4432f631d35dd2c46f96ef0512f1a
github.com/bep/debounce,v1.2.0,h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo=,ddc0a77e4819b6b826d69fdf1a5a153f3f867a31e030cfe28296355b670adf21
github.com/bep/gitmap,v1.1.1,h1:Nf8ySnC3I7/xPjuWeCwzukUFv185iTUQ6nOvLy9gCJA=,364163e67741ae331d164fd881964160f19fdbdfe094e0e762314cc37aac646a
@@ -1461,7 +1459,6 @@ github.com/opencontainers/runc,v0.1.1,h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJ
github.com/opencontainers/runtime-spec,v1.0.1,h1:wY4pOY8fBdSIvs9+IDHC55thBuEulhzfSgKeC1yFvzQ=,1958458b00ce912425f5c7d2ee836431b296a3f9320d565512d8c96b107fffbf
github.com/opencontainers/runtime-tools,v0.9.0,h1:FYgwVsKRI/H9hU32MJ/4MLOzXWodKK5zsQavY8NPMkU=,53c720dbb7452cfb2fd3945e37c26b5a0140cb1012d35a2b72a5e035f28a32c4
github.com/opencontainers/selinux,v1.3.0,h1:xsI95WzPZu5exzA6JzkLSfdr/DilzOhCJOqGe5TgR0g=,88286825b32cd46a0469e578f378a185032da2d5b03893623861ef3af59359d8
-github.com/openshift/api,v3.9.0+incompatible,h1:fJ/KsefYuZAjmrr3+5U9yZIZbTOpVkDDLDLFresAeYs=,fc087ac9809ce58bdd15614e04c13f8ecc4a17e71addbe6eb6b777c377b01243
github.com/openshift/client-go,v3.9.0+incompatible,h1:13k3Ok0B7TA2hA3bQW2aFqn6y04JaJWdk7ITTyg+Ek0=,661b7f28b4905f1936dd58e373374513d54663ec85aecafede1c7d9c260e9369
github.com/openshift/library-go,v0.0.0-20191101161407-e7c97b468b83,h1:wwR+laNaFKVGiizoIDL/cAKIZVoKXJ9jbjUoUlq2p5I=,c74f8134013f978ef154d6accf9b4b0c5126941f2d45e6eb223db7098f7ab2a4
github.com/opentracing-contrib/go-observer,v0.0.0-20170622124052-a52f23424492,h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU=,50023eee1ef04412410f43d8b5dcf3ef481c0fc39067add27799654705fa84b2
@@ -1882,7 +1879,6 @@ github.com/zondax/ledger-go,v0.9.0,h1:oTrtFqPFA4VdCPRvqMaN45mQnJxkPc0JxoVZfCoUpj
github.com/zquestz/grab,v0.0.0-20190224022517-abcee96e61b1,h1:1qKTeMTSIEvRIjvVYzgcRp0xVp0eoiRTTiHSncb5gD8=,4decd67f1252df4ee34968cb0cb4e7dc6010302b24ce8edd418f1c2520f1c351
gitlab.com/NebulousLabs/errors,v0.0.0-20171229012116-7ead97ef90b8,h1:gZfMjx7Jr6N8b7iJO4eUjDsn6xJqoyXg8D+ogdoAfKY=,b355474f1a2ef2722ae450ef6df7209d223188ae413706be122b472fcc053c48
gitlab.com/NebulousLabs/fastrand,v0.0.0-20181126182046-603482d69e40,h1:dizWJqTWjwyD8KGcMOwgrkqu1JIkofYgKkmDeNE7oAs=,a56acdda993c7a4795028fe38844d54de9b1877d22e8ae09f205e488ce2284bc
-gitlab.com/yumeko/MumbleEmu,v0.0.0-20170923112213-54c9892f02e9,h1:QSaGLacCEAlWXhL/xGZyS3+2aDVvBZe5jcmrDWwXhqs=,51cc295a04dc3b9c39b341f21b95fc42765e3bb61fe30ec2a59fe867c1b5e5ed
go.bug.st/serial.v1,v0.0.0-20180827123349-5f7892a7bb45,h1:mACY1anK6HNCZtm/DK2Rf2ZPHggVqeB0+7rY9Gl6wyI=,f0ea4cd4c51228f1a3cf14c6b92888169944f267e1ee778909512a4c8ac4762f
go.cryptoscope.co/luigi,v0.3.4,h1:eDrtCoUL5Vl2Atr5ty2dq0uFbzFCc6Pz1HEqU1e7I1I=,949612e92dcb2fc919e506740f36d0cfe0797c1f85579a98763aad0135a4580a
go.dedis.ch/fixbuf,v1.0.3,h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs=,dfa737543a5873b14cdfd0eec675c63044b16d3dbe481b2289c758ae4186ae95
@@ -2085,7 +2081,6 @@ layeh.com/radius,v0.0.0-20190322222518-890bc1058917,h1:BDXFaFzUt5EIqe/4wrTc4AcYZ
leb.io/aeshash,v0.0.0-20190627052759-9e6b40329b3b,h1:MG17Tc0pA3XmFTsPwklMMEfcos3pTFnVYM4A0YfVSbU=,a78b48ac18e98ea68dacce16cd94c9074688a0b125f824f047313a33b264ea88
leb.io/hashland,v0.0.0-20171003003232-07375b562dea,h1:s9IkzZTqYqw77voO6taUZHc0C1B096h4T/kQtujGApE=,0698177f24cbde0a7b45495e7fe976fe7623f2b9205995b7d91fd2e7b0f0e243
leb.io/hrff,v0.0.0-20170927164517-757f8bd43e20,h1:9CHS8LIq9MDwUsAaCHUsbUq7zb5lSjLQYWlJ/AbMZKg=,538008712599401a903a7982714c0a9ae745221042d3dfb1437bc508d8fb9e96
-llvm.org/llvm,v0.0.0-20191022153947-000000375505,h1:cncItmsQ0kcXFrnkQZv2TGle2ELPCEDi3Q36Kf2T3yg=,3f48da9846fc0f69ccc447ead4480f8c7f2b44b0c24b98a793d36d8cb2a572c0
modernc.org/cc,v1.0.0,h1:nPibNuDEx6tvYrUAtvDTTw98rx5juGsa5zuDnKwEEQQ=,24711e9b28b0d79dd32438eeb7debd86b850350f5f7749b7af640422ecf6b93b
modernc.org/golex,v1.0.0,h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE=,335133038991d7feaba5349ac2385db7b49601bba0904abf680803ee2d3c99df
modernc.org/mathutil,v1.0.0,h1:93vKjrJopTPrtTNpZ8XIovER7iCIH1QU7wNbOQXC60I=,766ad95195543fe1ac217ce9f54e1fb43119c25db2b89013b9ef5477ad2dd9d1
diff --git a/libgo/go/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go b/libgo/go/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
index 331d634..eac9b32 100644
--- a/libgo/go/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
+++ b/libgo/go/cmd/go/internal/modfetch/zip_sum_test/zip_sum_test.go
@@ -126,7 +126,7 @@ func TestZipSums(t *testing.T) {
test.m.Path = "" // mark for deletion
needUpdate = true
} else {
- t.Errorf("%s: could not download mdoule: %s", test.m, err)
+ t.Errorf("%s: could not download module: %s", test.m, err)
}
return
}
diff --git a/libgo/go/cmd/go/internal/modget/get.go b/libgo/go/cmd/go/internal/modget/get.go
index 2a0f634..4c69824 100644
--- a/libgo/go/cmd/go/internal/modget/get.go
+++ b/libgo/go/cmd/go/internal/modget/get.go
@@ -114,7 +114,10 @@ require downgrading other dependencies, and 'go get' does
this automatically as well.
The -insecure flag permits fetching from repositories and resolving
-custom domains using insecure schemes such as HTTP. Use with caution.
+custom domains using insecure schemes such as HTTP. Use with caution. The
+GOINSECURE environment variable is usually a better alternative, since it
+provides control over which modules may be retrieved using an insecure scheme.
+See 'go help environment' for details.
The second step is to download (if needed), build, and install
the named packages.
@@ -307,6 +310,20 @@ func runGet(cmd *base.Command, args []string) {
continue
}
+ // Guard against 'go get x.go', a common mistake.
+ // Note that package and module paths may end with '.go', so only print an error
+ // if the argument has no version and either has no slash or refers to an existing file.
+ if strings.HasSuffix(arg, ".go") && vers == "" {
+ if !strings.Contains(arg, "/") {
+ base.Errorf("go get %s: arguments must be package or module paths", arg)
+ continue
+ }
+ if fi, err := os.Stat(arg); err == nil && !fi.IsDir() {
+ base.Errorf("go get: %s exists as a file, but 'go get' requires package arguments", arg)
+ continue
+ }
+ }
+
// If no version suffix is specified, assume @upgrade.
// If -u=patch was specified, assume @patch instead.
if vers == "" {
@@ -326,15 +343,22 @@ func runGet(cmd *base.Command, args []string) {
// patterns like golang.org/x/tools/..., which can't be expanded
// during package loading until they're in the build list.
switch {
- case search.IsRelativePath(path):
- // Relative paths like ../../foo or ../../foo... are restricted to
- // matching packages in the main module. If the path is explicit and
- // contains no wildcards (...), check that it is a package in
- // the main module. If the path contains wildcards but matches no
- // packages, we'll warn after package loading.
+ case filepath.IsAbs(path) || search.IsRelativePath(path):
+ // Absolute paths like C:\foo and relative paths like ../foo...
+ // are restricted to matching packages in the main module. If the path
+ // is explicit and contains no wildcards (...), check that it is a
+ // package in the main module. If the path contains wildcards but
+ // matches no packages, we'll warn after package loading.
if !strings.Contains(path, "...") {
- pkgPath := modload.DirImportPath(filepath.FromSlash(path))
- if pkgs := modload.TargetPackages(pkgPath); len(pkgs) == 0 {
+ m := search.NewMatch(path)
+ if pkgPath := modload.DirImportPath(path); pkgPath != "." {
+ m = modload.TargetPackages(pkgPath)
+ }
+ if len(m.Pkgs) == 0 {
+ for _, err := range m.Errs {
+ base.Errorf("go get %s: %v", arg, err)
+ }
+
abs, err := filepath.Abs(path)
if err != nil {
abs = path
@@ -374,7 +398,7 @@ func runGet(cmd *base.Command, args []string) {
default:
// The argument is a package or module path.
if modload.HasModRoot() {
- if pkgs := modload.TargetPackages(path); len(pkgs) != 0 {
+ if m := modload.TargetPackages(path); len(m.Pkgs) != 0 {
// The path is in the main module. Nothing to query.
if vers != "upgrade" && vers != "patch" {
base.Errorf("go get %s: can't request explicit version of path in main module", arg)
@@ -520,8 +544,12 @@ func runGet(cmd *base.Command, args []string) {
// If the pattern did not match any packages, look up a new module.
// If the pattern doesn't match anything on the last iteration,
// we'll print a warning after the outer loop.
- if !search.IsRelativePath(arg.path) && !match.Literal && arg.path != "all" {
+ if !match.IsLocal() && !match.IsLiteral() && arg.path != "all" {
addQuery(&query{querySpec: querySpec{path: arg.path, vers: arg.vers}, arg: arg.raw})
+ } else {
+ for _, err := range match.Errs {
+ base.Errorf("go get: %v", err)
+ }
}
continue
}
diff --git a/libgo/go/cmd/go/internal/modload/build.go b/libgo/go/cmd/go/internal/modload/build.go
index 2a69d59..e7e7d56 100644
--- a/libgo/go/cmd/go/internal/modload/build.go
+++ b/libgo/go/cmd/go/internal/modload/build.go
@@ -205,6 +205,7 @@ func PackageBuildInfo(path string, deps []string) string {
if isStandardImportPath(path) || !Enabled() {
return ""
}
+
target := mustFindModule(path, path)
mdeps := make(map[module.Version]bool)
for _, dep := range deps {
@@ -221,26 +222,25 @@ func PackageBuildInfo(path string, deps []string) string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "path\t%s\n", path)
- tv := target.Version
- if tv == "" {
- tv = "(devel)"
- }
- fmt.Fprintf(&buf, "mod\t%s\t%s\t%s\n", target.Path, tv, modfetch.Sum(target))
- for _, mod := range mods {
- mv := mod.Version
+
+ writeEntry := func(token string, m module.Version) {
+ mv := m.Version
if mv == "" {
mv = "(devel)"
}
- r := Replacement(mod)
- h := ""
- if r.Path == "" {
- h = "\t" + modfetch.Sum(mod)
- }
- fmt.Fprintf(&buf, "dep\t%s\t%s%s\n", mod.Path, mv, h)
- if r.Path != "" {
- fmt.Fprintf(&buf, "=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r))
+ fmt.Fprintf(&buf, "%s\t%s\t%s", token, m.Path, mv)
+ if r := Replacement(m); r.Path == "" {
+ fmt.Fprintf(&buf, "\t%s\n", modfetch.Sum(m))
+ } else {
+ fmt.Fprintf(&buf, "\n=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r))
}
}
+
+ writeEntry("mod", target)
+ for _, mod := range mods {
+ writeEntry("dep", mod)
+ }
+
return buf.String()
}
diff --git a/libgo/go/cmd/go/internal/modload/help.go b/libgo/go/cmd/go/internal/modload/help.go
index bd19bb4..d80206b 100644
--- a/libgo/go/cmd/go/internal/modload/help.go
+++ b/libgo/go/cmd/go/internal/modload/help.go
@@ -363,15 +363,15 @@ variable (see 'go help env'). The default setting for GOPROXY is
Go module mirror run by Google and fall back to a direct connection
if the proxy reports that it does not have the module (HTTP error 404 or 410).
See https://proxy.golang.org/privacy for the service's privacy policy.
-If GOPROXY is set to the string "direct", downloads use a direct connection
-to source control servers. Setting GOPROXY to "off" disallows downloading
-modules from any source. Otherwise, GOPROXY is expected to be a comma-separated
-list of the URLs of module proxies, in which case the go command will fetch
-modules from those proxies. For each request, the go command tries each proxy
-in sequence, only moving to the next if the current proxy returns a 404 or 410
-HTTP response. The string "direct" may appear in the proxy list,
-to cause a direct connection to be attempted at that point in the search.
-Any proxies listed after "direct" are never consulted.
+
+If GOPROXY is set to the string "direct", downloads use a direct connection to
+source control servers. Setting GOPROXY to "off" disallows downloading modules
+from any source. Otherwise, GOPROXY is expected to be list of module proxy URLs
+separated by either comma (,) or pipe (|) characters, which control error
+fallback behavior. For each request, the go command tries each proxy in
+sequence. If there is an error, the go command will try the next proxy in the
+list if the error is a 404 or 410 HTTP response or if the current proxy is
+followed by a pipe character, indicating it is safe to fall back on any error.
The GOPRIVATE and GONOPROXY environment variables allow bypassing
the proxy for selected modules. See 'go help module-private' for details.
diff --git a/libgo/go/cmd/go/internal/modload/import.go b/libgo/go/cmd/go/internal/modload/import.go
index d7fca8f..4d2bc80 100644
--- a/libgo/go/cmd/go/internal/modload/import.go
+++ b/libgo/go/cmd/go/internal/modload/import.go
@@ -62,11 +62,15 @@ func (e *ImportMissingError) ImportPath() string {
// modules in the build list, or found in both the main module and its vendor
// directory.
type AmbiguousImportError struct {
- ImportPath string
+ importPath string
Dirs []string
Modules []module.Version // Either empty or 1:1 with Dirs.
}
+func (e *AmbiguousImportError) ImportPath() string {
+ return e.importPath
+}
+
func (e *AmbiguousImportError) Error() string {
locType := "modules"
if len(e.Modules) == 0 {
@@ -74,7 +78,7 @@ func (e *AmbiguousImportError) Error() string {
}
var buf strings.Builder
- fmt.Fprintf(&buf, "ambiguous import: found package %s in multiple %s:", e.ImportPath, locType)
+ fmt.Fprintf(&buf, "ambiguous import: found package %s in multiple %s:", e.importPath, locType)
for i, dir := range e.Dirs {
buf.WriteString("\n\t")
@@ -93,6 +97,8 @@ func (e *AmbiguousImportError) Error() string {
return buf.String()
}
+var _ load.ImportPathError = &AmbiguousImportError{}
+
// Import finds the module and directory in the build list
// containing the package with the given import path.
// The answer must be unique: Import returns an error
@@ -120,7 +126,9 @@ func Import(path string) (m module.Version, dir string, err error) {
pathIsStd := search.IsStandardImportPath(path)
if pathIsStd && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
if targetInGorootSrc {
- if dir, ok := dirInModule(path, targetPrefix, ModRoot(), true); ok {
+ if dir, ok, err := dirInModule(path, targetPrefix, ModRoot(), true); err != nil {
+ return module.Version{}, dir, err
+ } else if ok {
return Target, dir, nil
}
}
@@ -131,10 +139,10 @@ func Import(path string) (m module.Version, dir string, err error) {
// -mod=vendor is special.
// Everything must be in the main module or the main module's vendor directory.
if cfg.BuildMod == "vendor" {
- mainDir, mainOK := dirInModule(path, targetPrefix, ModRoot(), true)
- vendorDir, vendorOK := dirInModule(path, "", filepath.Join(ModRoot(), "vendor"), false)
+ mainDir, mainOK, mainErr := dirInModule(path, targetPrefix, ModRoot(), true)
+ vendorDir, vendorOK, _ := dirInModule(path, "", filepath.Join(ModRoot(), "vendor"), false)
if mainOK && vendorOK {
- return module.Version{}, "", &AmbiguousImportError{ImportPath: path, Dirs: []string{mainDir, vendorDir}}
+ return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: []string{mainDir, vendorDir}}
}
// Prefer to return main directory if there is one,
// Note that we're not checking that the package exists.
@@ -142,6 +150,9 @@ func Import(path string) (m module.Version, dir string, err error) {
if !vendorOK && mainDir != "" {
return Target, mainDir, nil
}
+ if mainErr != nil {
+ return module.Version{}, "", mainErr
+ }
readVendorList()
return vendorPkgModule[path], vendorDir, nil
}
@@ -164,8 +175,9 @@ func Import(path string) (m module.Version, dir string, err error) {
// not ambiguous.
return module.Version{}, "", err
}
- dir, ok := dirInModule(path, m.Path, root, isLocal)
- if ok {
+ if dir, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil {
+ return module.Version{}, "", err
+ } else if ok {
mods = append(mods, m)
dirs = append(dirs, dir)
}
@@ -174,7 +186,7 @@ func Import(path string) (m module.Version, dir string, err error) {
return mods[0], dirs[0], nil
}
if len(mods) > 0 {
- return module.Version{}, "", &AmbiguousImportError{ImportPath: path, Dirs: dirs, Modules: mods}
+ return module.Version{}, "", &AmbiguousImportError{importPath: path, Dirs: dirs, Modules: mods}
}
// Look up module containing the package, for addition to the build list.
@@ -241,8 +253,9 @@ func Import(path string) (m module.Version, dir string, err error) {
// Report fetch error as above.
return module.Version{}, "", err
}
- _, ok := dirInModule(path, m.Path, root, isLocal)
- if ok {
+ if _, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil {
+ return m, "", err
+ } else if ok {
return m, "", &ImportMissingError{Path: path, Module: m}
}
}
@@ -313,19 +326,29 @@ func maybeInModule(path, mpath string) bool {
len(path) > len(mpath) && path[len(mpath)] == '/' && path[:len(mpath)] == mpath
}
-var haveGoModCache, haveGoFilesCache par.Cache
+var (
+ haveGoModCache par.Cache // dir → bool
+ haveGoFilesCache par.Cache // dir → goFilesEntry
+)
+
+type goFilesEntry struct {
+ haveGoFiles bool
+ err error
+}
// dirInModule locates the directory that would hold the package named by the given path,
// if it were in the module with module path mpath and root mdir.
// If path is syntactically not within mpath,
// or if mdir is a local file tree (isLocal == true) and the directory
// that would hold path is in a sub-module (covered by a go.mod below mdir),
-// dirInModule returns "", false.
+// dirInModule returns "", false, nil.
//
// Otherwise, dirInModule returns the name of the directory where
// Go source files would be expected, along with a boolean indicating
// whether there are in fact Go source files in that directory.
-func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFiles bool) {
+// A non-nil error indicates that the existence of the directory and/or
+// source files could not be determined, for example due to a permission error.
+func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFiles bool, err error) {
// Determine where to expect the package.
if path == mpath {
dir = mdir
@@ -334,7 +357,7 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
} else if len(path) > len(mpath) && path[len(mpath)] == '/' && path[:len(mpath)] == mpath {
dir = filepath.Join(mdir, path[len(mpath)+1:])
} else {
- return "", false
+ return "", false, nil
}
// Check that there aren't other modules in the way.
@@ -351,7 +374,7 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
}).(bool)
if haveGoMod {
- return "", false
+ return "", false, nil
}
parent := filepath.Dir(d)
if parent == d {
@@ -368,23 +391,58 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
// Are there Go source files in the directory?
// We don't care about build tags, not even "+build ignore".
// We're just looking for a plausible directory.
- haveGoFiles = haveGoFilesCache.Do(dir, func() interface{} {
- f, err := os.Open(dir)
- if err != nil {
- return false
+ res := haveGoFilesCache.Do(dir, func() interface{} {
+ ok, err := isDirWithGoFiles(dir)
+ return goFilesEntry{haveGoFiles: ok, err: err}
+ }).(goFilesEntry)
+
+ return dir, res.haveGoFiles, res.err
+}
+
+func isDirWithGoFiles(dir string) (bool, error) {
+ f, err := os.Open(dir)
+ if err != nil {
+ if os.IsNotExist(err) {
+ return false, nil
+ }
+ return false, err
+ }
+ defer f.Close()
+
+ names, firstErr := f.Readdirnames(-1)
+ if firstErr != nil {
+ if fi, err := f.Stat(); err == nil && !fi.IsDir() {
+ return false, nil
}
- defer f.Close()
- names, _ := f.Readdirnames(-1)
- for _, name := range names {
- if strings.HasSuffix(name, ".go") {
- info, err := os.Stat(filepath.Join(dir, name))
- if err == nil && info.Mode().IsRegular() {
- return true
+
+ // Rewrite the error from ReadDirNames to include the path if not present.
+ // See https://golang.org/issue/38923.
+ var pe *os.PathError
+ if !errors.As(firstErr, &pe) {
+ firstErr = &os.PathError{Op: "readdir", Path: dir, Err: firstErr}
+ }
+ }
+
+ for _, name := range names {
+ if strings.HasSuffix(name, ".go") {
+ info, err := os.Stat(filepath.Join(dir, name))
+ if err == nil && info.Mode().IsRegular() {
+ // If any .go source file exists, the package exists regardless of
+ // errors for other source files. Leave further error reporting for
+ // later.
+ return true, nil
+ }
+ if firstErr == nil {
+ if os.IsNotExist(err) {
+ // If the file was concurrently deleted, or was a broken symlink,
+ // convert the error to an opaque error instead of one matching
+ // os.IsNotExist.
+ err = errors.New(err.Error())
}
+ firstErr = err
}
}
- return false
- }).(bool)
+ }
- return dir, haveGoFiles
+ return false, firstErr
}
diff --git a/libgo/go/cmd/go/internal/modload/init.go b/libgo/go/cmd/go/internal/modload/init.go
index 61cbdf2..664a2a1 100644
--- a/libgo/go/cmd/go/internal/modload/init.go
+++ b/libgo/go/cmd/go/internal/modload/init.go
@@ -26,7 +26,6 @@ import (
"cmd/go/internal/lockedfile"
"cmd/go/internal/modconv"
"cmd/go/internal/modfetch"
- "cmd/go/internal/modfetch/codehost"
"cmd/go/internal/mvs"
"cmd/go/internal/search"
@@ -59,27 +58,6 @@ var (
allowMissingModuleImports bool
)
-var modFile *modfile.File
-
-// A modFileIndex is an index of data corresponding to a modFile
-// at a specific point in time.
-type modFileIndex struct {
- data []byte
- dataNeedsFix bool // true if fixVersion applied a change while parsing data
- module module.Version
- goVersion string
- require map[module.Version]requireMeta
- replace map[module.Version]module.Version
- exclude map[module.Version]bool
-}
-
-// index is the index of the go.mod file as of when it was last read or written.
-var index *modFileIndex
-
-type requireMeta struct {
- indirect bool
-}
-
// ModFile returns the parsed go.mod file.
//
// Note that after calling ImportPaths or LoadBuildList,
@@ -199,17 +177,6 @@ func Init() {
base.Fatalf("$GOPATH/go.mod exists but should not")
}
- oldSrcMod := filepath.Join(list[0], "src/mod")
- pkgMod := filepath.Join(list[0], "pkg/mod")
- infoOld, errOld := os.Stat(oldSrcMod)
- _, errMod := os.Stat(pkgMod)
- if errOld == nil && infoOld.IsDir() && errMod != nil && os.IsNotExist(errMod) {
- os.Rename(oldSrcMod, pkgMod)
- }
-
- modfetch.PkgMod = pkgMod
- codehost.WorkRoot = filepath.Join(pkgMod, "cache/vcs")
-
cfg.ModulesEnabled = true
load.ModBinDir = BinDir
load.ModLookup = Lookup
@@ -246,13 +213,6 @@ func Init() {
func init() {
load.ModInit = Init
-
- // Set modfetch.PkgMod and codehost.WorkRoot unconditionally,
- // so that go clean -modcache and go mod download can run even without modules enabled.
- if list := filepath.SplitList(cfg.BuildContext.GOPATH); len(list) > 0 && list[0] != "" {
- modfetch.PkgMod = filepath.Join(list[0], "pkg/mod")
- codehost.WorkRoot = filepath.Join(list[0], "pkg/mod/cache/vcs")
- }
}
// WillBeEnabled checks whether modules should be enabled but does not
@@ -555,101 +515,6 @@ func setDefaultBuildMod() {
}
}
-// checkVendorConsistency verifies that the vendor/modules.txt file matches (if
-// go 1.14) or at least does not contradict (go 1.13 or earlier) the
-// requirements and replacements listed in the main module's go.mod file.
-func checkVendorConsistency() {
- readVendorList()
-
- pre114 := false
- if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, "v1.14") < 0 {
- // Go versions before 1.14 did not include enough information in
- // vendor/modules.txt to check for consistency.
- // If we know that we're on an earlier version, relax the consistency check.
- pre114 = true
- }
-
- vendErrors := new(strings.Builder)
- vendErrorf := func(mod module.Version, format string, args ...interface{}) {
- detail := fmt.Sprintf(format, args...)
- if mod.Version == "" {
- fmt.Fprintf(vendErrors, "\n\t%s: %s", mod.Path, detail)
- } else {
- fmt.Fprintf(vendErrors, "\n\t%s@%s: %s", mod.Path, mod.Version, detail)
- }
- }
-
- for _, r := range modFile.Require {
- if !vendorMeta[r.Mod].Explicit {
- if pre114 {
- // Before 1.14, modules.txt did not indicate whether modules were listed
- // explicitly in the main module's go.mod file.
- // However, we can at least detect a version mismatch if packages were
- // vendored from a non-matching version.
- if vv, ok := vendorVersion[r.Mod.Path]; ok && vv != r.Mod.Version {
- vendErrorf(r.Mod, fmt.Sprintf("is explicitly required in go.mod, but vendor/modules.txt indicates %s@%s", r.Mod.Path, vv))
- }
- } else {
- vendErrorf(r.Mod, "is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt")
- }
- }
- }
-
- describe := func(m module.Version) string {
- if m.Version == "" {
- return m.Path
- }
- return m.Path + "@" + m.Version
- }
-
- // We need to verify *all* replacements that occur in modfile: even if they
- // don't directly apply to any module in the vendor list, the replacement
- // go.mod file can affect the selected versions of other (transitive)
- // dependencies
- for _, r := range modFile.Replace {
- vr := vendorMeta[r.Old].Replacement
- if vr == (module.Version{}) {
- if pre114 && (r.Old.Version == "" || vendorVersion[r.Old.Path] != r.Old.Version) {
- // Before 1.14, modules.txt omitted wildcard replacements and
- // replacements for modules that did not have any packages to vendor.
- } else {
- vendErrorf(r.Old, "is replaced in go.mod, but not marked as replaced in vendor/modules.txt")
- }
- } else if vr != r.New {
- vendErrorf(r.Old, "is replaced by %s in go.mod, but marked as replaced by %s in vendor/modules.txt", describe(r.New), describe(vr))
- }
- }
-
- for _, mod := range vendorList {
- meta := vendorMeta[mod]
- if meta.Explicit {
- if _, inGoMod := index.require[mod]; !inGoMod {
- vendErrorf(mod, "is marked as explicit in vendor/modules.txt, but not explicitly required in go.mod")
- }
- }
- }
-
- for _, mod := range vendorReplaced {
- r := Replacement(mod)
- if r == (module.Version{}) {
- vendErrorf(mod, "is marked as replaced in vendor/modules.txt, but not replaced in go.mod")
- continue
- }
- if meta := vendorMeta[mod]; r != meta.Replacement {
- vendErrorf(mod, "is marked as replaced by %s in vendor/modules.txt, but replaced by %s in go.mod", describe(meta.Replacement), describe(r))
- }
- }
-
- if vendErrors.Len() > 0 {
- base.Fatalf("go: inconsistent vendoring in %s:%s\n\nrun 'go mod vendor' to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory", modRoot, vendErrors)
- }
-}
-
-// Allowed reports whether module m is allowed (not excluded) by the main module's go.mod.
-func Allowed(m module.Version) bool {
- return index == nil || !index.exclude[m]
-}
-
func legacyModInit() {
if modFile == nil {
path, err := findModulePath(modRoot)
@@ -740,13 +605,14 @@ func findAltConfig(dir string) (root, name string) {
panic("dir not set")
}
dir = filepath.Clean(dir)
+ if rel := search.InDir(dir, cfg.BuildContext.GOROOT); rel != "" {
+ // Don't suggest creating a module from $GOROOT/.git/config
+ // or a config file found in any parent of $GOROOT (see #34191).
+ return "", ""
+ }
for {
for _, name := range altConfigs {
if fi, err := os.Stat(filepath.Join(dir, name)); err == nil && !fi.IsDir() {
- if rel := search.InDir(dir, cfg.BuildContext.GOROOT); rel == "." {
- // Don't suggest creating a module from $GOROOT/.git/config.
- return "", ""
- }
return dir, name
}
}
@@ -983,113 +849,3 @@ func WriteGoMod() {
base.Fatalf("go: updating go.mod: %v", err)
}
}
-
-// indexModFile rebuilds the index of modFile.
-// If modFile has been changed since it was first read,
-// modFile.Cleanup must be called before indexModFile.
-func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileIndex {
- i := new(modFileIndex)
- i.data = data
- i.dataNeedsFix = needsFix
-
- i.module = module.Version{}
- if modFile.Module != nil {
- i.module = modFile.Module.Mod
- }
-
- i.goVersion = ""
- if modFile.Go != nil {
- i.goVersion = modFile.Go.Version
- }
-
- i.require = make(map[module.Version]requireMeta, len(modFile.Require))
- for _, r := range modFile.Require {
- i.require[r.Mod] = requireMeta{indirect: r.Indirect}
- }
-
- i.replace = make(map[module.Version]module.Version, len(modFile.Replace))
- for _, r := range modFile.Replace {
- if prev, dup := i.replace[r.Old]; dup && prev != r.New {
- base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v", r.Old, prev, r.New)
- }
- i.replace[r.Old] = r.New
- }
-
- i.exclude = make(map[module.Version]bool, len(modFile.Exclude))
- for _, x := range modFile.Exclude {
- i.exclude[x.Mod] = true
- }
-
- return i
-}
-
-// modFileIsDirty reports whether the go.mod file differs meaningfully
-// from what was indexed.
-// If modFile has been changed (even cosmetically) since it was first read,
-// modFile.Cleanup must be called before modFileIsDirty.
-func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool {
- if i == nil {
- return modFile != nil
- }
-
- if i.dataNeedsFix {
- return true
- }
-
- if modFile.Module == nil {
- if i.module != (module.Version{}) {
- return true
- }
- } else if modFile.Module.Mod != i.module {
- return true
- }
-
- if modFile.Go == nil {
- if i.goVersion != "" {
- return true
- }
- } else if modFile.Go.Version != i.goVersion {
- if i.goVersion == "" && cfg.BuildMod == "readonly" {
- // go.mod files did not always require a 'go' version, so do not error out
- // if one is missing — we may be inside an older module in the module
- // cache, and should bias toward providing useful behavior.
- } else {
- return true
- }
- }
-
- if len(modFile.Require) != len(i.require) ||
- len(modFile.Replace) != len(i.replace) ||
- len(modFile.Exclude) != len(i.exclude) {
- return true
- }
-
- for _, r := range modFile.Require {
- if meta, ok := i.require[r.Mod]; !ok {
- return true
- } else if r.Indirect != meta.indirect {
- if cfg.BuildMod == "readonly" {
- // The module's requirements are consistent; only the "// indirect"
- // comments that are wrong. But those are only guaranteed to be accurate
- // after a "go mod tidy" — it's a good idea to run those before
- // committing a change, but it's certainly not mandatory.
- } else {
- return true
- }
- }
- }
-
- for _, r := range modFile.Replace {
- if r.New != i.replace[r.Old] {
- return true
- }
- }
-
- for _, x := range modFile.Exclude {
- if !i.exclude[x.Mod] {
- return true
- }
- }
-
- return false
-}
diff --git a/libgo/go/cmd/go/internal/modload/load.go b/libgo/go/cmd/go/internal/modload/load.go
index 7a8391d..f5f74ba 100644
--- a/libgo/go/cmd/go/internal/modload/load.go
+++ b/libgo/go/cmd/go/internal/modload/load.go
@@ -6,30 +6,25 @@ package modload
import (
"bytes"
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/imports"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/mvs"
+ "cmd/go/internal/par"
+ "cmd/go/internal/search"
+ "cmd/go/internal/str"
"errors"
"fmt"
"go/build"
- "io/ioutil"
"os"
"path"
pathpkg "path"
"path/filepath"
"sort"
"strings"
- "sync"
- "cmd/go/internal/base"
- "cmd/go/internal/cfg"
- "cmd/go/internal/imports"
- "cmd/go/internal/modfetch"
- "cmd/go/internal/mvs"
- "cmd/go/internal/par"
- "cmd/go/internal/search"
- "cmd/go/internal/str"
-
- "golang.org/x/mod/modfile"
"golang.org/x/mod/module"
- "golang.org/x/mod/semver"
)
// buildList is the list of modules to use for building packages.
@@ -65,23 +60,13 @@ func ImportPaths(patterns []string) []*search.Match {
// packages. The build tags should typically be imports.Tags() or
// imports.AnyTags(); a nil map has no special meaning.
func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
- var fsDirs [][]string
updateMatches := func(matches []*search.Match, iterating bool) {
- for i, m := range matches {
+ for _, m := range matches {
switch {
- case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern):
+ case m.IsLocal():
// Evaluate list of file system directories on first iteration.
- if fsDirs == nil {
- fsDirs = make([][]string, len(matches))
- }
- if fsDirs[i] == nil {
- var dirs []string
- if m.Literal {
- dirs = []string{m.Pattern}
- } else {
- dirs = search.MatchPackagesInFS(m.Pattern).Pkgs
- }
- fsDirs[i] = dirs
+ if m.Dirs == nil {
+ matchLocalDirs(m)
}
// Make a copy of the directory list and translate to import paths.
@@ -90,102 +75,53 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
// from not being in the build list to being in it and back as
// the exact version of a particular module increases during
// the loader iterations.
- m.Pkgs = str.StringList(fsDirs[i])
- pkgs := m.Pkgs
m.Pkgs = m.Pkgs[:0]
- for _, pkg := range pkgs {
- var dir string
- if !filepath.IsAbs(pkg) {
- dir = filepath.Join(base.Cwd, pkg)
- } else {
- dir = filepath.Clean(pkg)
- }
+ for _, dir := range m.Dirs {
+ pkg, err := resolveLocalPackage(dir)
+ if err != nil {
+ if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) {
+ continue // Don't include "builtin" or GOROOT/src in wildcard patterns.
+ }
- // golang.org/issue/32917: We should resolve a relative path to a
- // package path only if the relative path actually contains the code
- // for that package.
- if !dirContainsPackage(dir) {
// If we're outside of a module, ensure that the failure mode
// indicates that.
ModRoot()
- // If the directory is local but does not exist, don't return it
- // while loader is iterating, since this might trigger a fetch.
- // After loader is done iterating, we still need to return the
- // path, so that "go list -e" produces valid output.
if !iterating {
- // We don't have a valid path to resolve to, so report the
- // unresolved path.
- m.Pkgs = append(m.Pkgs, pkg)
+ m.AddError(err)
}
continue
}
-
- // Note: The checks for @ here are just to avoid misinterpreting
- // the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).
- // It's not strictly necessary but helpful to keep the checks.
- if modRoot != "" && dir == modRoot {
- pkg = targetPrefix
- } else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") {
- suffix := filepath.ToSlash(dir[len(modRoot):])
- if strings.HasPrefix(suffix, "/vendor/") {
- // TODO getmode vendor check
- pkg = strings.TrimPrefix(suffix, "/vendor/")
- } else if targetInGorootSrc && Target.Path == "std" {
- // Don't add the prefix "std/" to packages in the "std" module.
- // It's the one module path that isn't a prefix of its packages.
- pkg = strings.TrimPrefix(suffix, "/")
- if pkg == "builtin" {
- // "builtin" is a pseudo-package with a real source file.
- // It's not included in "std", so it shouldn't be included in
- // "./..." within module "std" either.
- continue
- }
- } else {
- modPkg := targetPrefix + suffix
- if _, ok := dirInModule(modPkg, targetPrefix, modRoot, true); ok {
- pkg = modPkg
- } else if !iterating {
- ModRoot()
- base.Errorf("go: directory %s is outside main module", base.ShortPath(dir))
- }
- }
- } else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {
- pkg = filepath.ToSlash(sub)
- } else if path := pathInModuleCache(dir); path != "" {
- pkg = path
- } else {
- pkg = ""
- if !iterating {
- ModRoot()
- base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
- }
- }
m.Pkgs = append(m.Pkgs, pkg)
}
- case strings.Contains(m.Pattern, "..."):
- m.Pkgs = matchPackages(m.Pattern, loaded.tags, true, buildList)
+ case m.IsLiteral():
+ m.Pkgs = []string{m.Pattern()}
+
+ case strings.Contains(m.Pattern(), "..."):
+ m.Errs = m.Errs[:0]
+ matchPackages(m, loaded.tags, includeStd, buildList)
- case m.Pattern == "all":
+ case m.Pattern() == "all":
loaded.testAll = true
if iterating {
// Enumerate the packages in the main module.
// We'll load the dependencies as we find them.
- m.Pkgs = matchPackages("...", loaded.tags, false, []module.Version{Target})
+ m.Errs = m.Errs[:0]
+ matchPackages(m, loaded.tags, omitStd, []module.Version{Target})
} else {
// Starting with the packages in the main module,
// enumerate the full list of "all".
m.Pkgs = loaded.computePatternAll(m.Pkgs)
}
- case search.IsMetaPackage(m.Pattern): // std, cmd
- if len(m.Pkgs) == 0 {
- m.Pkgs = search.MatchPackages(m.Pattern).Pkgs
+ case m.Pattern() == "std" || m.Pattern() == "cmd":
+ if m.Pkgs == nil {
+ m.MatchPackages() // Locate the packages within GOROOT/src.
}
default:
- m.Pkgs = []string{m.Pattern}
+ panic(fmt.Sprintf("internal error: modload missing case for pattern %s", m.Pattern()))
}
}
}
@@ -194,10 +130,7 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
var matches []*search.Match
for _, pattern := range search.CleanPatterns(patterns) {
- matches = append(matches, &search.Match{
- Pattern: pattern,
- Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern),
- })
+ matches = append(matches, search.NewMatch(pattern))
}
loaded = newLoader(tags)
@@ -238,6 +171,139 @@ func checkMultiplePaths() {
base.ExitIfErrors()
}
+// matchLocalDirs is like m.MatchDirs, but tries to avoid scanning directories
+// outside of the standard library and active modules.
+func matchLocalDirs(m *search.Match) {
+ if !m.IsLocal() {
+ panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern()))
+ }
+
+ if i := strings.Index(m.Pattern(), "..."); i >= 0 {
+ // The pattern is local, but it is a wildcard. Its packages will
+ // only resolve to paths if they are inside of the standard
+ // library, the main module, or some dependency of the main
+ // module. Verify that before we walk the filesystem: a filesystem
+ // walk in a directory like /var or /etc can be very expensive!
+ dir := filepath.Dir(filepath.Clean(m.Pattern()[:i+3]))
+ absDir := dir
+ if !filepath.IsAbs(dir) {
+ absDir = filepath.Join(base.Cwd, dir)
+ }
+ if search.InDir(absDir, cfg.GOROOTsrc) == "" && search.InDir(absDir, ModRoot()) == "" && pathInModuleCache(absDir) == "" {
+ m.Dirs = []string{}
+ m.AddError(fmt.Errorf("directory prefix %s outside available modules", base.ShortPath(absDir)))
+ return
+ }
+ }
+
+ m.MatchDirs()
+}
+
+// resolveLocalPackage resolves a filesystem path to a package path.
+func resolveLocalPackage(dir string) (string, error) {
+ var absDir string
+ if filepath.IsAbs(dir) {
+ absDir = filepath.Clean(dir)
+ } else {
+ absDir = filepath.Join(base.Cwd, dir)
+ }
+
+ bp, err := cfg.BuildContext.ImportDir(absDir, 0)
+ if err != nil && (bp == nil || len(bp.IgnoredGoFiles) == 0) {
+ // golang.org/issue/32917: We should resolve a relative path to a
+ // package path only if the relative path actually contains the code
+ // for that package.
+ //
+ // If the named directory does not exist or contains no Go files,
+ // the package does not exist.
+ // Other errors may affect package loading, but not resolution.
+ if _, err := os.Stat(absDir); err != nil {
+ if os.IsNotExist(err) {
+ // Canonicalize OS-specific errors to errDirectoryNotFound so that error
+ // messages will be easier for users to search for.
+ return "", &os.PathError{Op: "stat", Path: absDir, Err: errDirectoryNotFound}
+ }
+ return "", err
+ }
+ if _, noGo := err.(*build.NoGoError); noGo {
+ // A directory that does not contain any Go source files — even ignored
+ // ones! — is not a Go package, and we can't resolve it to a package
+ // path because that path could plausibly be provided by some other
+ // module.
+ //
+ // Any other error indicates that the package “exists” (at least in the
+ // sense that it cannot exist in any other module), but has some other
+ // problem (such as a syntax error).
+ return "", err
+ }
+ }
+
+ if modRoot != "" && absDir == modRoot {
+ if absDir == cfg.GOROOTsrc {
+ return "", errPkgIsGorootSrc
+ }
+ return targetPrefix, nil
+ }
+
+ // Note: The checks for @ here are just to avoid misinterpreting
+ // the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).
+ // It's not strictly necessary but helpful to keep the checks.
+ if modRoot != "" && strings.HasPrefix(absDir, modRoot+string(filepath.Separator)) && !strings.Contains(absDir[len(modRoot):], "@") {
+ suffix := filepath.ToSlash(absDir[len(modRoot):])
+ if strings.HasPrefix(suffix, "/vendor/") {
+ if cfg.BuildMod != "vendor" {
+ return "", fmt.Errorf("without -mod=vendor, directory %s has no package path", absDir)
+ }
+
+ readVendorList()
+ pkg := strings.TrimPrefix(suffix, "/vendor/")
+ if _, ok := vendorPkgModule[pkg]; !ok {
+ return "", fmt.Errorf("directory %s is not a package listed in vendor/modules.txt", absDir)
+ }
+ return pkg, nil
+ }
+
+ if targetPrefix == "" {
+ pkg := strings.TrimPrefix(suffix, "/")
+ if pkg == "builtin" {
+ // "builtin" is a pseudo-package with a real source file.
+ // It's not included in "std", so it shouldn't resolve from "."
+ // within module "std" either.
+ return "", errPkgIsBuiltin
+ }
+ return pkg, nil
+ }
+
+ pkg := targetPrefix + suffix
+ if _, ok, err := dirInModule(pkg, targetPrefix, modRoot, true); err != nil {
+ return "", err
+ } else if !ok {
+ return "", &PackageNotInModuleError{Mod: Target, Pattern: pkg}
+ }
+ return pkg, nil
+ }
+
+ if sub := search.InDir(absDir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {
+ pkg := filepath.ToSlash(sub)
+ if pkg == "builtin" {
+ return "", errPkgIsBuiltin
+ }
+ return pkg, nil
+ }
+
+ pkg := pathInModuleCache(absDir)
+ if pkg == "" {
+ return "", fmt.Errorf("directory %s outside available modules", base.ShortPath(absDir))
+ }
+ return pkg, nil
+}
+
+var (
+ errDirectoryNotFound = errors.New("directory not found")
+ errPkgIsGorootSrc = errors.New("GOROOT/src is not an importable package")
+ errPkgIsBuiltin = errors.New(`"builtin" is a pseudo-package, not an importable package`)
+)
+
// pathInModuleCache returns the import path of the directory dir,
// if dir is in the module cache copy of a module in our build list.
func pathInModuleCache(dir string) string {
@@ -267,32 +333,6 @@ func pathInModuleCache(dir string) string {
return ""
}
-var dirContainsPackageCache sync.Map // absolute dir → bool
-
-func dirContainsPackage(dir string) bool {
- isPkg, ok := dirContainsPackageCache.Load(dir)
- if !ok {
- _, err := cfg.BuildContext.ImportDir(dir, 0)
- if err == nil {
- isPkg = true
- } else {
- if fi, statErr := os.Stat(dir); statErr != nil || !fi.IsDir() {
- // A non-directory or inaccessible directory is not a Go package.
- isPkg = false
- } else if _, noGo := err.(*build.NoGoError); noGo {
- // A directory containing no Go source files is not a Go package.
- isPkg = false
- } else {
- // An error other than *build.NoGoError indicates that the package exists
- // but has some other problem (such as a syntax error).
- isPkg = true
- }
- }
- isPkg, _ = dirContainsPackageCache.LoadOrStore(dir, isPkg)
- }
- return isPkg.(bool)
-}
-
// ImportFromFiles adds modules to the build list as needed
// to satisfy the imports in the named Go source files.
func ImportFromFiles(gofiles []string) {
@@ -386,7 +426,7 @@ func loadAll(testAll bool) []string {
loaded.testRoots = true
}
all := TargetPackages("...")
- loaded.load(func() []string { return all })
+ loaded.load(func() []string { return all.Pkgs })
checkMultiplePaths()
WriteGoMod()
@@ -398,6 +438,9 @@ func loadAll(testAll bool) []string {
}
paths = append(paths, pkg.path)
}
+ for _, err := range all.Errs {
+ base.Errorf("%v", err)
+ }
base.ExitIfErrors()
return paths
}
@@ -405,12 +448,14 @@ func loadAll(testAll bool) []string {
// TargetPackages returns the list of packages in the target (top-level) module
// matching pattern, which may be relative to the working directory, under all
// build tag settings.
-func TargetPackages(pattern string) []string {
+func TargetPackages(pattern string) *search.Match {
// TargetPackages is relative to the main module, so ensure that the main
// module is a thing that can contain packages.
ModRoot()
- return matchPackages(pattern, imports.AnyTags(), false, []module.Version{Target})
+ m := search.NewMatch(pattern)
+ matchPackages(m, imports.AnyTags(), omitStd, []module.Version{Target})
+ return m
}
// BuildList returns the module build list,
@@ -655,13 +700,13 @@ func (ld *loader) load(roots func() []string) {
if err.newMissingVersion != "" {
base.Fatalf("go: %s: package provided by %s at latest version %s but not at required version %s", pkg.stackText(), err.Module.Path, err.Module.Version, err.newMissingVersion)
}
+ fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, err.Module.Path, err.Module.Version)
if added[pkg.path] {
base.Fatalf("go: %s: looping trying to add package", pkg.stackText())
}
added[pkg.path] = true
numAdded++
if !haveMod[err.Module] {
- fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, err.Module.Path, err.Module.Version)
haveMod[err.Module] = true
modAddedBy[err.Module] = pkg
buildList = append(buildList, err.Module)
@@ -761,7 +806,7 @@ func (ld *loader) doPkg(item interface{}) {
// Leave for error during load.
return
}
- if build.IsLocalImport(pkg.path) {
+ if build.IsLocalImport(pkg.path) || filepath.IsAbs(pkg.path) {
// Leave for error during load.
// (Module mode does not allow local imports.)
return
@@ -996,354 +1041,3 @@ func WhyDepth(path string) int {
}
return n
}
-
-// Replacement returns the replacement for mod, if any, from go.mod.
-// If there is no replacement for mod, Replacement returns
-// a module.Version with Path == "".
-func Replacement(mod module.Version) module.Version {
- if index != nil {
- if r, ok := index.replace[mod]; ok {
- return r
- }
- if r, ok := index.replace[module.Version{Path: mod.Path}]; ok {
- return r
- }
- }
- return module.Version{}
-}
-
-// mvsReqs implements mvs.Reqs for module semantic versions,
-// with any exclusions or replacements applied internally.
-type mvsReqs struct {
- buildList []module.Version
- cache par.Cache
- versions sync.Map
-}
-
-// Reqs returns the current module requirement graph.
-// Future calls to SetBuildList do not affect the operation
-// of the returned Reqs.
-func Reqs() mvs.Reqs {
- r := &mvsReqs{
- buildList: buildList,
- }
- return r
-}
-
-func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
- type cached struct {
- list []module.Version
- err error
- }
-
- c := r.cache.Do(mod, func() interface{} {
- list, err := r.required(mod)
- if err != nil {
- return cached{nil, err}
- }
- for i, mv := range list {
- if index != nil {
- for index.exclude[mv] {
- mv1, err := r.next(mv)
- if err != nil {
- return cached{nil, err}
- }
- if mv1.Version == "none" {
- return cached{nil, fmt.Errorf("%s(%s) depends on excluded %s(%s) with no newer version available", mod.Path, mod.Version, mv.Path, mv.Version)}
- }
- mv = mv1
- }
- }
- list[i] = mv
- }
-
- return cached{list, nil}
- }).(cached)
-
- return c.list, c.err
-}
-
-var vendorOnce sync.Once
-
-type vendorMetadata struct {
- Explicit bool
- Replacement module.Version
-}
-
-var (
- vendorList []module.Version // modules that contribute packages to the build, in order of appearance
- vendorReplaced []module.Version // all replaced modules; may or may not also contribute packages
- vendorVersion map[string]string // module path → selected version (if known)
- vendorPkgModule map[string]module.Version // package → containing module
- vendorMeta map[module.Version]vendorMetadata
-)
-
-// readVendorList reads the list of vendored modules from vendor/modules.txt.
-func readVendorList() {
- vendorOnce.Do(func() {
- vendorList = nil
- vendorPkgModule = make(map[string]module.Version)
- vendorVersion = make(map[string]string)
- vendorMeta = make(map[module.Version]vendorMetadata)
- data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt"))
- if err != nil {
- if !errors.Is(err, os.ErrNotExist) {
- base.Fatalf("go: %s", err)
- }
- return
- }
-
- var mod module.Version
- for _, line := range strings.Split(string(data), "\n") {
- if strings.HasPrefix(line, "# ") {
- f := strings.Fields(line)
-
- if len(f) < 3 {
- continue
- }
- if semver.IsValid(f[2]) {
- // A module, but we don't yet know whether it is in the build list or
- // only included to indicate a replacement.
- mod = module.Version{Path: f[1], Version: f[2]}
- f = f[3:]
- } else if f[2] == "=>" {
- // A wildcard replacement found in the main module's go.mod file.
- mod = module.Version{Path: f[1]}
- f = f[2:]
- } else {
- // Not a version or a wildcard replacement.
- // We don't know how to interpret this module line, so ignore it.
- mod = module.Version{}
- continue
- }
-
- if len(f) >= 2 && f[0] == "=>" {
- meta := vendorMeta[mod]
- if len(f) == 2 {
- // File replacement.
- meta.Replacement = module.Version{Path: f[1]}
- vendorReplaced = append(vendorReplaced, mod)
- } else if len(f) == 3 && semver.IsValid(f[2]) {
- // Path and version replacement.
- meta.Replacement = module.Version{Path: f[1], Version: f[2]}
- vendorReplaced = append(vendorReplaced, mod)
- } else {
- // We don't understand this replacement. Ignore it.
- }
- vendorMeta[mod] = meta
- }
- continue
- }
-
- // Not a module line. Must be a package within a module or a metadata
- // directive, either of which requires a preceding module line.
- if mod.Path == "" {
- continue
- }
-
- if strings.HasPrefix(line, "## ") {
- // Metadata. Take the union of annotations across multiple lines, if present.
- meta := vendorMeta[mod]
- for _, entry := range strings.Split(strings.TrimPrefix(line, "## "), ";") {
- entry = strings.TrimSpace(entry)
- if entry == "explicit" {
- meta.Explicit = true
- }
- // All other tokens are reserved for future use.
- }
- vendorMeta[mod] = meta
- continue
- }
-
- if f := strings.Fields(line); len(f) == 1 && module.CheckImportPath(f[0]) == nil {
- // A package within the current module.
- vendorPkgModule[f[0]] = mod
-
- // Since this module provides a package for the build, we know that it
- // is in the build list and is the selected version of its path.
- // If this information is new, record it.
- if v, ok := vendorVersion[mod.Path]; !ok || semver.Compare(v, mod.Version) < 0 {
- vendorList = append(vendorList, mod)
- vendorVersion[mod.Path] = mod.Version
- }
- }
- }
- })
-}
-
-func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version {
- list := make([]module.Version, 0, len(f.Require))
- for _, r := range f.Require {
- list = append(list, r.Mod)
- }
- return list
-}
-
-// required returns a unique copy of the requirements of mod.
-func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
- if mod == Target {
- if modFile != nil && modFile.Go != nil {
- r.versions.LoadOrStore(mod, modFile.Go.Version)
- }
- return append([]module.Version(nil), r.buildList[1:]...), nil
- }
-
- if cfg.BuildMod == "vendor" {
- // For every module other than the target,
- // return the full list of modules from modules.txt.
- readVendorList()
- return append([]module.Version(nil), vendorList...), nil
- }
-
- origPath := mod.Path
- if repl := Replacement(mod); repl.Path != "" {
- if repl.Version == "" {
- // TODO: need to slip the new version into the tags list etc.
- dir := repl.Path
- if !filepath.IsAbs(dir) {
- dir = filepath.Join(ModRoot(), dir)
- }
- gomod := filepath.Join(dir, "go.mod")
- data, err := ioutil.ReadFile(gomod)
- if err != nil {
- return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
- }
- f, err := modfile.ParseLax(gomod, data, nil)
- if err != nil {
- return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
- }
- if f.Go != nil {
- r.versions.LoadOrStore(mod, f.Go.Version)
- }
- return r.modFileToList(f), nil
- }
- mod = repl
- }
-
- if mod.Version == "none" {
- return nil, nil
- }
-
- if !semver.IsValid(mod.Version) {
- // Disallow the broader queries supported by fetch.Lookup.
- base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version)
- }
-
- data, err := modfetch.GoMod(mod.Path, mod.Version)
- if err != nil {
- return nil, err
- }
- f, err := modfile.ParseLax("go.mod", data, nil)
- if err != nil {
- return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: %v", err))
- }
-
- if f.Module == nil {
- return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line"))
- }
- if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
- return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod:
- module declares its path as: %s
- but was required as: %s`, mpath, mod.Path))
- }
- if f.Go != nil {
- r.versions.LoadOrStore(mod, f.Go.Version)
- }
-
- return r.modFileToList(f), nil
-}
-
-func (*mvsReqs) Max(v1, v2 string) string {
- if v1 != "" && semver.Compare(v1, v2) == -1 {
- return v2
- }
- return v1
-}
-
-// Upgrade is a no-op, here to implement mvs.Reqs.
-// The upgrade logic for go get -u is in ../modget/get.go.
-func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) {
- return m, nil
-}
-
-func versions(path string) ([]string, error) {
- // Note: modfetch.Lookup and repo.Versions are cached,
- // so there's no need for us to add extra caching here.
- var versions []string
- err := modfetch.TryProxies(func(proxy string) error {
- repo, err := modfetch.Lookup(proxy, path)
- if err == nil {
- versions, err = repo.Versions("")
- }
- return err
- })
- return versions, err
-}
-
-// Previous returns the tagged version of m.Path immediately prior to
-// m.Version, or version "none" if no prior version is tagged.
-func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
- list, err := versions(m.Path)
- if err != nil {
- return module.Version{}, err
- }
- i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 })
- if i > 0 {
- return module.Version{Path: m.Path, Version: list[i-1]}, nil
- }
- return module.Version{Path: m.Path, Version: "none"}, nil
-}
-
-// next returns the next version of m.Path after m.Version.
-// It is only used by the exclusion processing in the Required method,
-// not called directly by MVS.
-func (*mvsReqs) next(m module.Version) (module.Version, error) {
- list, err := versions(m.Path)
- if err != nil {
- return module.Version{}, err
- }
- i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 })
- if i < len(list) {
- return module.Version{Path: m.Path, Version: list[i]}, nil
- }
- return module.Version{Path: m.Path, Version: "none"}, nil
-}
-
-// fetch downloads the given module (or its replacement)
-// and returns its location.
-//
-// The isLocal return value reports whether the replacement,
-// if any, is local to the filesystem.
-func fetch(mod module.Version) (dir string, isLocal bool, err error) {
- if mod == Target {
- return ModRoot(), true, nil
- }
- if r := Replacement(mod); r.Path != "" {
- if r.Version == "" {
- dir = r.Path
- if !filepath.IsAbs(dir) {
- dir = filepath.Join(ModRoot(), dir)
- }
- // Ensure that the replacement directory actually exists:
- // dirInModule does not report errors for missing modules,
- // so if we don't report the error now, later failures will be
- // very mysterious.
- if _, err := os.Stat(dir); err != nil {
- if os.IsNotExist(err) {
- // Semantically the module version itself “exists” — we just don't
- // have its source code. Remove the equivalence to os.ErrNotExist,
- // and make the message more concise while we're at it.
- err = fmt.Errorf("replacement directory %s does not exist", r.Path)
- } else {
- err = fmt.Errorf("replacement directory %s: %w", r.Path, err)
- }
- return dir, true, module.VersionError(mod, err)
- }
- return dir, true, nil
- }
- mod = r
- }
-
- dir, err = modfetch.Download(mod)
- return dir, false, err
-}
diff --git a/libgo/go/cmd/go/internal/modload/modfile.go b/libgo/go/cmd/go/internal/modload/modfile.go
new file mode 100644
index 0000000..9f4ec5a
--- /dev/null
+++ b/libgo/go/cmd/go/internal/modload/modfile.go
@@ -0,0 +1,164 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modload
+
+import (
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+
+ "golang.org/x/mod/modfile"
+ "golang.org/x/mod/module"
+)
+
+var modFile *modfile.File
+
+// A modFileIndex is an index of data corresponding to a modFile
+// at a specific point in time.
+type modFileIndex struct {
+ data []byte
+ dataNeedsFix bool // true if fixVersion applied a change while parsing data
+ module module.Version
+ goVersion string
+ require map[module.Version]requireMeta
+ replace map[module.Version]module.Version
+ exclude map[module.Version]bool
+}
+
+// index is the index of the go.mod file as of when it was last read or written.
+var index *modFileIndex
+
+type requireMeta struct {
+ indirect bool
+}
+
+// Allowed reports whether module m is allowed (not excluded) by the main module's go.mod.
+func Allowed(m module.Version) bool {
+ return index == nil || !index.exclude[m]
+}
+
+// Replacement returns the replacement for mod, if any, from go.mod.
+// If there is no replacement for mod, Replacement returns
+// a module.Version with Path == "".
+func Replacement(mod module.Version) module.Version {
+ if index != nil {
+ if r, ok := index.replace[mod]; ok {
+ return r
+ }
+ if r, ok := index.replace[module.Version{Path: mod.Path}]; ok {
+ return r
+ }
+ }
+ return module.Version{}
+}
+
+// indexModFile rebuilds the index of modFile.
+// If modFile has been changed since it was first read,
+// modFile.Cleanup must be called before indexModFile.
+func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileIndex {
+ i := new(modFileIndex)
+ i.data = data
+ i.dataNeedsFix = needsFix
+
+ i.module = module.Version{}
+ if modFile.Module != nil {
+ i.module = modFile.Module.Mod
+ }
+
+ i.goVersion = ""
+ if modFile.Go != nil {
+ i.goVersion = modFile.Go.Version
+ }
+
+ i.require = make(map[module.Version]requireMeta, len(modFile.Require))
+ for _, r := range modFile.Require {
+ i.require[r.Mod] = requireMeta{indirect: r.Indirect}
+ }
+
+ i.replace = make(map[module.Version]module.Version, len(modFile.Replace))
+ for _, r := range modFile.Replace {
+ if prev, dup := i.replace[r.Old]; dup && prev != r.New {
+ base.Fatalf("go: conflicting replacements for %v:\n\t%v\n\t%v", r.Old, prev, r.New)
+ }
+ i.replace[r.Old] = r.New
+ }
+
+ i.exclude = make(map[module.Version]bool, len(modFile.Exclude))
+ for _, x := range modFile.Exclude {
+ i.exclude[x.Mod] = true
+ }
+
+ return i
+}
+
+// modFileIsDirty reports whether the go.mod file differs meaningfully
+// from what was indexed.
+// If modFile has been changed (even cosmetically) since it was first read,
+// modFile.Cleanup must be called before modFileIsDirty.
+func (i *modFileIndex) modFileIsDirty(modFile *modfile.File) bool {
+ if i == nil {
+ return modFile != nil
+ }
+
+ if i.dataNeedsFix {
+ return true
+ }
+
+ if modFile.Module == nil {
+ if i.module != (module.Version{}) {
+ return true
+ }
+ } else if modFile.Module.Mod != i.module {
+ return true
+ }
+
+ if modFile.Go == nil {
+ if i.goVersion != "" {
+ return true
+ }
+ } else if modFile.Go.Version != i.goVersion {
+ if i.goVersion == "" && cfg.BuildMod == "readonly" {
+ // go.mod files did not always require a 'go' version, so do not error out
+ // if one is missing — we may be inside an older module in the module
+ // cache, and should bias toward providing useful behavior.
+ } else {
+ return true
+ }
+ }
+
+ if len(modFile.Require) != len(i.require) ||
+ len(modFile.Replace) != len(i.replace) ||
+ len(modFile.Exclude) != len(i.exclude) {
+ return true
+ }
+
+ for _, r := range modFile.Require {
+ if meta, ok := i.require[r.Mod]; !ok {
+ return true
+ } else if r.Indirect != meta.indirect {
+ if cfg.BuildMod == "readonly" {
+ // The module's requirements are consistent; only the "// indirect"
+ // comments that are wrong. But those are only guaranteed to be accurate
+ // after a "go mod tidy" — it's a good idea to run those before
+ // committing a change, but it's certainly not mandatory.
+ } else {
+ return true
+ }
+ }
+ }
+
+ for _, r := range modFile.Replace {
+ if r.New != i.replace[r.Old] {
+ return true
+ }
+ }
+
+ for _, x := range modFile.Exclude {
+ if !i.exclude[x.Mod] {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/libgo/go/cmd/go/internal/modload/mvs.go b/libgo/go/cmd/go/internal/modload/mvs.go
new file mode 100644
index 0000000..5dd009d
--- /dev/null
+++ b/libgo/go/cmd/go/internal/modload/mvs.go
@@ -0,0 +1,259 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modload
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "sort"
+ "sync"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/lockedfile"
+ "cmd/go/internal/modfetch"
+ "cmd/go/internal/mvs"
+ "cmd/go/internal/par"
+
+ "golang.org/x/mod/modfile"
+ "golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
+)
+
+// mvsReqs implements mvs.Reqs for module semantic versions,
+// with any exclusions or replacements applied internally.
+type mvsReqs struct {
+ buildList []module.Version
+ cache par.Cache
+ versions sync.Map
+}
+
+// Reqs returns the current module requirement graph.
+// Future calls to SetBuildList do not affect the operation
+// of the returned Reqs.
+func Reqs() mvs.Reqs {
+ r := &mvsReqs{
+ buildList: buildList,
+ }
+ return r
+}
+
+func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) {
+ type cached struct {
+ list []module.Version
+ err error
+ }
+
+ c := r.cache.Do(mod, func() interface{} {
+ list, err := r.required(mod)
+ if err != nil {
+ return cached{nil, err}
+ }
+ for i, mv := range list {
+ if index != nil {
+ for index.exclude[mv] {
+ mv1, err := r.next(mv)
+ if err != nil {
+ return cached{nil, err}
+ }
+ if mv1.Version == "none" {
+ return cached{nil, fmt.Errorf("%s(%s) depends on excluded %s(%s) with no newer version available", mod.Path, mod.Version, mv.Path, mv.Version)}
+ }
+ mv = mv1
+ }
+ }
+ list[i] = mv
+ }
+
+ return cached{list, nil}
+ }).(cached)
+
+ return c.list, c.err
+}
+
+func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version {
+ list := make([]module.Version, 0, len(f.Require))
+ for _, r := range f.Require {
+ list = append(list, r.Mod)
+ }
+ return list
+}
+
+// required returns a unique copy of the requirements of mod.
+func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
+ if mod == Target {
+ if modFile != nil && modFile.Go != nil {
+ r.versions.LoadOrStore(mod, modFile.Go.Version)
+ }
+ return append([]module.Version(nil), r.buildList[1:]...), nil
+ }
+
+ if cfg.BuildMod == "vendor" {
+ // For every module other than the target,
+ // return the full list of modules from modules.txt.
+ readVendorList()
+ return append([]module.Version(nil), vendorList...), nil
+ }
+
+ origPath := mod.Path
+ if repl := Replacement(mod); repl.Path != "" {
+ if repl.Version == "" {
+ // TODO: need to slip the new version into the tags list etc.
+ dir := repl.Path
+ if !filepath.IsAbs(dir) {
+ dir = filepath.Join(ModRoot(), dir)
+ }
+ gomod := filepath.Join(dir, "go.mod")
+ data, err := lockedfile.Read(gomod)
+ if err != nil {
+ return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
+ }
+ f, err := modfile.ParseLax(gomod, data, nil)
+ if err != nil {
+ return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
+ }
+ if f.Go != nil {
+ r.versions.LoadOrStore(mod, f.Go.Version)
+ }
+ return r.modFileToList(f), nil
+ }
+ mod = repl
+ }
+
+ if mod.Version == "none" {
+ return nil, nil
+ }
+
+ if !semver.IsValid(mod.Version) {
+ // Disallow the broader queries supported by fetch.Lookup.
+ base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version)
+ }
+
+ data, err := modfetch.GoMod(mod.Path, mod.Version)
+ if err != nil {
+ return nil, err
+ }
+ f, err := modfile.ParseLax("go.mod", data, nil)
+ if err != nil {
+ return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: %v", err))
+ }
+
+ if f.Module == nil {
+ return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line"))
+ }
+ if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
+ return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod:
+ module declares its path as: %s
+ but was required as: %s`, mpath, origPath))
+ }
+ if f.Go != nil {
+ r.versions.LoadOrStore(mod, f.Go.Version)
+ }
+
+ return r.modFileToList(f), nil
+}
+
+// Max returns the maximum of v1 and v2 according to semver.Compare.
+//
+// As a special case, the version "" is considered higher than all other
+// versions. The main module (also known as the target) has no version and must
+// be chosen over other versions of the same module in the module dependency
+// graph.
+func (*mvsReqs) Max(v1, v2 string) string {
+ if v1 != "" && semver.Compare(v1, v2) == -1 {
+ return v2
+ }
+ return v1
+}
+
+// Upgrade is a no-op, here to implement mvs.Reqs.
+// The upgrade logic for go get -u is in ../modget/get.go.
+func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) {
+ return m, nil
+}
+
+func versions(path string) ([]string, error) {
+ // Note: modfetch.Lookup and repo.Versions are cached,
+ // so there's no need for us to add extra caching here.
+ var versions []string
+ err := modfetch.TryProxies(func(proxy string) error {
+ repo, err := modfetch.Lookup(proxy, path)
+ if err == nil {
+ versions, err = repo.Versions("")
+ }
+ return err
+ })
+ return versions, err
+}
+
+// Previous returns the tagged version of m.Path immediately prior to
+// m.Version, or version "none" if no prior version is tagged.
+func (*mvsReqs) Previous(m module.Version) (module.Version, error) {
+ list, err := versions(m.Path)
+ if err != nil {
+ return module.Version{}, err
+ }
+ i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 })
+ if i > 0 {
+ return module.Version{Path: m.Path, Version: list[i-1]}, nil
+ }
+ return module.Version{Path: m.Path, Version: "none"}, nil
+}
+
+// next returns the next version of m.Path after m.Version.
+// It is only used by the exclusion processing in the Required method,
+// not called directly by MVS.
+func (*mvsReqs) next(m module.Version) (module.Version, error) {
+ list, err := versions(m.Path)
+ if err != nil {
+ return module.Version{}, err
+ }
+ i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 })
+ if i < len(list) {
+ return module.Version{Path: m.Path, Version: list[i]}, nil
+ }
+ return module.Version{Path: m.Path, Version: "none"}, nil
+}
+
+// fetch downloads the given module (or its replacement)
+// and returns its location.
+//
+// The isLocal return value reports whether the replacement,
+// if any, is local to the filesystem.
+func fetch(mod module.Version) (dir string, isLocal bool, err error) {
+ if mod == Target {
+ return ModRoot(), true, nil
+ }
+ if r := Replacement(mod); r.Path != "" {
+ if r.Version == "" {
+ dir = r.Path
+ if !filepath.IsAbs(dir) {
+ dir = filepath.Join(ModRoot(), dir)
+ }
+ // Ensure that the replacement directory actually exists:
+ // dirInModule does not report errors for missing modules,
+ // so if we don't report the error now, later failures will be
+ // very mysterious.
+ if _, err := os.Stat(dir); err != nil {
+ if os.IsNotExist(err) {
+ // Semantically the module version itself “exists” — we just don't
+ // have its source code. Remove the equivalence to os.ErrNotExist,
+ // and make the message more concise while we're at it.
+ err = fmt.Errorf("replacement directory %s does not exist", r.Path)
+ } else {
+ err = fmt.Errorf("replacement directory %s: %w", r.Path, err)
+ }
+ return dir, true, module.VersionError(mod, err)
+ }
+ return dir, true, nil
+ }
+ mod = r
+ }
+
+ dir, err = modfetch.Download(mod)
+ return dir, false, err
+}
diff --git a/libgo/go/cmd/go/internal/modload/query.go b/libgo/go/cmd/go/internal/modload/query.go
index 031e459..acc886b 100644
--- a/libgo/go/cmd/go/internal/modload/query.go
+++ b/libgo/go/cmd/go/internal/modload/query.go
@@ -381,7 +381,8 @@ type QueryResult struct {
// module and only the version "latest", without checking for other possible
// modules.
func QueryPackage(path, query string, allowed func(module.Version) bool) ([]QueryResult, error) {
- if search.IsMetaPackage(path) || strings.Contains(path, "...") {
+ m := search.NewMatch(path)
+ if m.IsLocal() || !m.IsLiteral() {
return nil, fmt.Errorf("pattern %s is not an importable package", path)
}
return QueryPattern(path, query, allowed)
@@ -402,30 +403,42 @@ func QueryPackage(path, query string, allowed func(module.Version) bool) ([]Quer
// possible modules.
func QueryPattern(pattern, query string, allowed func(module.Version) bool) ([]QueryResult, error) {
base := pattern
- var match func(m module.Version, root string, isLocal bool) (pkgs []string)
+
+ firstError := func(m *search.Match) error {
+ if len(m.Errs) == 0 {
+ return nil
+ }
+ return m.Errs[0]
+ }
+
+ var match func(mod module.Version, root string, isLocal bool) *search.Match
if i := strings.Index(pattern, "..."); i >= 0 {
base = pathpkg.Dir(pattern[:i+3])
- match = func(m module.Version, root string, isLocal bool) []string {
- return matchPackages(pattern, imports.AnyTags(), false, []module.Version{m})
+ match = func(mod module.Version, root string, isLocal bool) *search.Match {
+ m := search.NewMatch(pattern)
+ matchPackages(m, imports.AnyTags(), omitStd, []module.Version{mod})
+ return m
}
} else {
- match = func(m module.Version, root string, isLocal bool) []string {
- prefix := m.Path
- if m == Target {
+ match = func(mod module.Version, root string, isLocal bool) *search.Match {
+ m := search.NewMatch(pattern)
+ prefix := mod.Path
+ if mod == Target {
prefix = targetPrefix
}
- if _, ok := dirInModule(pattern, prefix, root, isLocal); ok {
- return []string{pattern}
- } else {
- return nil
+ if _, ok, err := dirInModule(pattern, prefix, root, isLocal); err != nil {
+ m.AddError(err)
+ } else if ok {
+ m.Pkgs = []string{pattern}
}
+ return m
}
}
if HasModRoot() {
- pkgs := match(Target, modRoot, true)
- if len(pkgs) > 0 {
+ m := match(Target, modRoot, true)
+ if len(m.Pkgs) > 0 {
if query != "latest" {
return nil, fmt.Errorf("can't query specific version for package %s in the main module (%s)", pattern, Target.Path)
}
@@ -435,9 +448,12 @@ func QueryPattern(pattern, query string, allowed func(module.Version) bool) ([]Q
return []QueryResult{{
Mod: Target,
Rev: &modfetch.RevInfo{Version: Target.Version},
- Packages: pkgs,
+ Packages: m.Pkgs,
}}, nil
}
+ if err := firstError(m); err != nil {
+ return nil, err
+ }
}
var (
@@ -445,13 +461,18 @@ func QueryPattern(pattern, query string, allowed func(module.Version) bool) ([]Q
candidateModules = modulePrefixesExcludingTarget(base)
)
if len(candidateModules) == 0 {
- return nil, fmt.Errorf("package %s is not in the main module (%s)", pattern, Target.Path)
+ return nil, &PackageNotInModuleError{
+ Mod: Target,
+ Query: query,
+ Pattern: pattern,
+ }
}
err := modfetch.TryProxies(func(proxy string) error {
queryModule := func(path string) (r QueryResult, err error) {
+ current := findCurrentVersion(path)
r.Mod.Path = path
- r.Rev, err = queryProxy(proxy, path, query, "", allowed)
+ r.Rev, err = queryProxy(proxy, path, query, current, allowed)
if err != nil {
return r, err
}
@@ -460,8 +481,12 @@ func QueryPattern(pattern, query string, allowed func(module.Version) bool) ([]Q
if err != nil {
return r, err
}
- r.Packages = match(r.Mod, root, isLocal)
+ m := match(r.Mod, root, isLocal)
+ r.Packages = m.Pkgs
if len(r.Packages) == 0 {
+ if err := firstError(m); err != nil {
+ return r, err
+ }
return r, &PackageNotInModuleError{
Mod: r.Mod,
Replacement: Replacement(r.Mod),
@@ -503,6 +528,15 @@ func modulePrefixesExcludingTarget(path string) []string {
return prefixes
}
+func findCurrentVersion(path string) string {
+ for _, m := range buildList {
+ if m.Path == path {
+ return m.Version
+ }
+ }
+ return ""
+}
+
type prefixResult struct {
QueryResult
err error
@@ -541,7 +575,9 @@ func queryPrefixModules(candidateModules []string, queryModule func(path string)
case nil:
found = append(found, r.QueryResult)
case *PackageNotInModuleError:
- if noPackage == nil {
+ // Given the option, prefer to attribute “package not in module”
+ // to modules other than the main one.
+ if noPackage == nil || noPackage.Mod == Target {
noPackage = rErr
}
case *NoMatchingVersionError:
@@ -626,6 +662,13 @@ type PackageNotInModuleError struct {
}
func (e *PackageNotInModuleError) Error() string {
+ if e.Mod == Target {
+ if strings.Contains(e.Pattern, "...") {
+ return fmt.Sprintf("main module (%s) does not contain packages matching %s", Target.Path, e.Pattern)
+ }
+ return fmt.Sprintf("main module (%s) does not contain package %s", Target.Path, e.Pattern)
+ }
+
found := ""
if r := e.Replacement; r.Path != "" {
replacement := r.Path
@@ -647,14 +690,21 @@ func (e *PackageNotInModuleError) Error() string {
return fmt.Sprintf("module %s@%s found%s, but does not contain package %s", e.Mod.Path, e.Query, found, e.Pattern)
}
+func (e *PackageNotInModuleError) ImportPath() string {
+ if !strings.Contains(e.Pattern, "...") {
+ return e.Pattern
+ }
+ return ""
+}
+
// ModuleHasRootPackage returns whether module m contains a package m.Path.
func ModuleHasRootPackage(m module.Version) (bool, error) {
root, isLocal, err := fetch(m)
if err != nil {
return false, err
}
- _, ok := dirInModule(m.Path, m.Path, root, isLocal)
- return ok, nil
+ _, ok, err := dirInModule(m.Path, m.Path, root, isLocal)
+ return ok, err
}
func versionHasGoMod(m module.Version) (bool, error) {
diff --git a/libgo/go/cmd/go/internal/modload/query_test.go b/libgo/go/cmd/go/internal/modload/query_test.go
index 15470e2..247e4c4 100644
--- a/libgo/go/cmd/go/internal/modload/query_test.go
+++ b/libgo/go/cmd/go/internal/modload/query_test.go
@@ -15,8 +15,6 @@ import (
"testing"
"cmd/go/internal/cfg"
- "cmd/go/internal/modfetch"
- "cmd/go/internal/modfetch/codehost"
"golang.org/x/mod/module"
)
@@ -36,8 +34,7 @@ func testMain(m *testing.M) int {
os.Setenv("GOPATH", dir)
cfg.BuildContext.GOPATH = dir
- modfetch.PkgMod = filepath.Join(dir, "pkg/mod")
- codehost.WorkRoot = filepath.Join(dir, "codework")
+ cfg.GOMODCACHE = filepath.Join(dir, "pkg/mod")
return m.Run()
}
diff --git a/libgo/go/cmd/go/internal/modload/search.go b/libgo/go/cmd/go/internal/modload/search.go
index a303f51..146c94a 100644
--- a/libgo/go/cmd/go/internal/modload/search.go
+++ b/libgo/go/cmd/go/internal/modload/search.go
@@ -8,9 +8,9 @@ import (
"fmt"
"os"
"path/filepath"
+ "runtime"
"strings"
- "cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/imports"
"cmd/go/internal/search"
@@ -18,14 +18,24 @@ import (
"golang.org/x/mod/module"
)
-// matchPackages returns a list of packages in the list of modules
-// matching the pattern. Package loading assumes the given set of tags.
-func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []module.Version) []string {
- match := func(string) bool { return true }
+type stdFilter int8
+
+const (
+ omitStd = stdFilter(iota)
+ includeStd
+)
+
+// matchPackages is like m.MatchPackages, but uses a local variable (rather than
+// a global) for tags, can include or exclude packages in the standard library,
+// and is restricted to the given list of modules.
+func matchPackages(m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) {
+ m.Pkgs = []string{}
+
+ isMatch := func(string) bool { return true }
treeCanMatch := func(string) bool { return true }
- if !search.IsMetaPackage(pattern) {
- match = search.MatchPattern(pattern)
- treeCanMatch = search.TreeCanMatchPattern(pattern)
+ if !m.IsMeta() {
+ isMatch = search.MatchPattern(m.Pattern())
+ treeCanMatch = search.TreeCanMatchPattern(m.Pattern())
}
have := map[string]bool{
@@ -34,7 +44,6 @@ func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []
if !cfg.BuildContext.CgoEnabled {
have["runtime/cgo"] = true // ignore during walk
}
- var pkgs []string
type pruning int8
const (
@@ -44,8 +53,9 @@ func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []
walkPkgs := func(root, importPathRoot string, prune pruning) {
root = filepath.Clean(root)
- filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
+ err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
if err != nil {
+ m.AddError(err)
return nil
}
@@ -94,9 +104,9 @@ func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []
if !have[name] {
have[name] = true
- if match(name) {
+ if isMatch(name) {
if _, _, err := scanDir(path, tags); err != imports.ErrNoGo {
- pkgs = append(pkgs, name)
+ m.Pkgs = append(m.Pkgs, name)
}
}
}
@@ -106,9 +116,12 @@ func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []
}
return nil
})
+ if err != nil {
+ m.AddError(err)
+ }
}
- if useStd {
+ if filter == includeStd && runtime.Compiler != "gccgo" {
walkPkgs(cfg.GOROOTsrc, "", pruneGoMod)
if treeCanMatch("cmd") {
walkPkgs(filepath.Join(cfg.GOROOTsrc, "cmd"), "cmd", pruneGoMod)
@@ -120,7 +133,7 @@ func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []
walkPkgs(ModRoot(), targetPrefix, pruneGoMod|pruneVendor)
walkPkgs(filepath.Join(ModRoot(), "vendor"), "", pruneVendor)
}
- return pkgs
+ return
}
for _, mod := range modules {
@@ -143,7 +156,7 @@ func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []
var err error
root, isLocal, err = fetch(mod)
if err != nil {
- base.Errorf("go: %v", err)
+ m.AddError(err)
continue
}
modPrefix = mod.Path
@@ -156,5 +169,5 @@ func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []
walkPkgs(root, modPrefix, prune)
}
- return pkgs
+ return
}
diff --git a/libgo/go/cmd/go/internal/modload/vendor.go b/libgo/go/cmd/go/internal/modload/vendor.go
new file mode 100644
index 0000000..71f68ef
--- /dev/null
+++ b/libgo/go/cmd/go/internal/modload/vendor.go
@@ -0,0 +1,217 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package modload
+
+import (
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+
+ "cmd/go/internal/base"
+
+ "golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
+)
+
+var (
+ vendorOnce sync.Once
+ vendorList []module.Version // modules that contribute packages to the build, in order of appearance
+ vendorReplaced []module.Version // all replaced modules; may or may not also contribute packages
+ vendorVersion map[string]string // module path → selected version (if known)
+ vendorPkgModule map[string]module.Version // package → containing module
+ vendorMeta map[module.Version]vendorMetadata
+)
+
+type vendorMetadata struct {
+ Explicit bool
+ Replacement module.Version
+}
+
+// readVendorList reads the list of vendored modules from vendor/modules.txt.
+func readVendorList() {
+ vendorOnce.Do(func() {
+ vendorList = nil
+ vendorPkgModule = make(map[string]module.Version)
+ vendorVersion = make(map[string]string)
+ vendorMeta = make(map[module.Version]vendorMetadata)
+ data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt"))
+ if err != nil {
+ if !errors.Is(err, os.ErrNotExist) {
+ base.Fatalf("go: %s", err)
+ }
+ return
+ }
+
+ var mod module.Version
+ for _, line := range strings.Split(string(data), "\n") {
+ if strings.HasPrefix(line, "# ") {
+ f := strings.Fields(line)
+
+ if len(f) < 3 {
+ continue
+ }
+ if semver.IsValid(f[2]) {
+ // A module, but we don't yet know whether it is in the build list or
+ // only included to indicate a replacement.
+ mod = module.Version{Path: f[1], Version: f[2]}
+ f = f[3:]
+ } else if f[2] == "=>" {
+ // A wildcard replacement found in the main module's go.mod file.
+ mod = module.Version{Path: f[1]}
+ f = f[2:]
+ } else {
+ // Not a version or a wildcard replacement.
+ // We don't know how to interpret this module line, so ignore it.
+ mod = module.Version{}
+ continue
+ }
+
+ if len(f) >= 2 && f[0] == "=>" {
+ meta := vendorMeta[mod]
+ if len(f) == 2 {
+ // File replacement.
+ meta.Replacement = module.Version{Path: f[1]}
+ vendorReplaced = append(vendorReplaced, mod)
+ } else if len(f) == 3 && semver.IsValid(f[2]) {
+ // Path and version replacement.
+ meta.Replacement = module.Version{Path: f[1], Version: f[2]}
+ vendorReplaced = append(vendorReplaced, mod)
+ } else {
+ // We don't understand this replacement. Ignore it.
+ }
+ vendorMeta[mod] = meta
+ }
+ continue
+ }
+
+ // Not a module line. Must be a package within a module or a metadata
+ // directive, either of which requires a preceding module line.
+ if mod.Path == "" {
+ continue
+ }
+
+ if strings.HasPrefix(line, "## ") {
+ // Metadata. Take the union of annotations across multiple lines, if present.
+ meta := vendorMeta[mod]
+ for _, entry := range strings.Split(strings.TrimPrefix(line, "## "), ";") {
+ entry = strings.TrimSpace(entry)
+ if entry == "explicit" {
+ meta.Explicit = true
+ }
+ // All other tokens are reserved for future use.
+ }
+ vendorMeta[mod] = meta
+ continue
+ }
+
+ if f := strings.Fields(line); len(f) == 1 && module.CheckImportPath(f[0]) == nil {
+ // A package within the current module.
+ vendorPkgModule[f[0]] = mod
+
+ // Since this module provides a package for the build, we know that it
+ // is in the build list and is the selected version of its path.
+ // If this information is new, record it.
+ if v, ok := vendorVersion[mod.Path]; !ok || semver.Compare(v, mod.Version) < 0 {
+ vendorList = append(vendorList, mod)
+ vendorVersion[mod.Path] = mod.Version
+ }
+ }
+ }
+ })
+}
+
+// checkVendorConsistency verifies that the vendor/modules.txt file matches (if
+// go 1.14) or at least does not contradict (go 1.13 or earlier) the
+// requirements and replacements listed in the main module's go.mod file.
+func checkVendorConsistency() {
+ readVendorList()
+
+ pre114 := false
+ if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, "v1.14") < 0 {
+ // Go versions before 1.14 did not include enough information in
+ // vendor/modules.txt to check for consistency.
+ // If we know that we're on an earlier version, relax the consistency check.
+ pre114 = true
+ }
+
+ vendErrors := new(strings.Builder)
+ vendErrorf := func(mod module.Version, format string, args ...interface{}) {
+ detail := fmt.Sprintf(format, args...)
+ if mod.Version == "" {
+ fmt.Fprintf(vendErrors, "\n\t%s: %s", mod.Path, detail)
+ } else {
+ fmt.Fprintf(vendErrors, "\n\t%s@%s: %s", mod.Path, mod.Version, detail)
+ }
+ }
+
+ for _, r := range modFile.Require {
+ if !vendorMeta[r.Mod].Explicit {
+ if pre114 {
+ // Before 1.14, modules.txt did not indicate whether modules were listed
+ // explicitly in the main module's go.mod file.
+ // However, we can at least detect a version mismatch if packages were
+ // vendored from a non-matching version.
+ if vv, ok := vendorVersion[r.Mod.Path]; ok && vv != r.Mod.Version {
+ vendErrorf(r.Mod, fmt.Sprintf("is explicitly required in go.mod, but vendor/modules.txt indicates %s@%s", r.Mod.Path, vv))
+ }
+ } else {
+ vendErrorf(r.Mod, "is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt")
+ }
+ }
+ }
+
+ describe := func(m module.Version) string {
+ if m.Version == "" {
+ return m.Path
+ }
+ return m.Path + "@" + m.Version
+ }
+
+ // We need to verify *all* replacements that occur in modfile: even if they
+ // don't directly apply to any module in the vendor list, the replacement
+ // go.mod file can affect the selected versions of other (transitive)
+ // dependencies
+ for _, r := range modFile.Replace {
+ vr := vendorMeta[r.Old].Replacement
+ if vr == (module.Version{}) {
+ if pre114 && (r.Old.Version == "" || vendorVersion[r.Old.Path] != r.Old.Version) {
+ // Before 1.14, modules.txt omitted wildcard replacements and
+ // replacements for modules that did not have any packages to vendor.
+ } else {
+ vendErrorf(r.Old, "is replaced in go.mod, but not marked as replaced in vendor/modules.txt")
+ }
+ } else if vr != r.New {
+ vendErrorf(r.Old, "is replaced by %s in go.mod, but marked as replaced by %s in vendor/modules.txt", describe(r.New), describe(vr))
+ }
+ }
+
+ for _, mod := range vendorList {
+ meta := vendorMeta[mod]
+ if meta.Explicit {
+ if _, inGoMod := index.require[mod]; !inGoMod {
+ vendErrorf(mod, "is marked as explicit in vendor/modules.txt, but not explicitly required in go.mod")
+ }
+ }
+ }
+
+ for _, mod := range vendorReplaced {
+ r := Replacement(mod)
+ if r == (module.Version{}) {
+ vendErrorf(mod, "is marked as replaced in vendor/modules.txt, but not replaced in go.mod")
+ continue
+ }
+ if meta := vendorMeta[mod]; r != meta.Replacement {
+ vendErrorf(mod, "is marked as replaced by %s in vendor/modules.txt, but replaced by %s in go.mod", describe(meta.Replacement), describe(r))
+ }
+ }
+
+ if vendErrors.Len() > 0 {
+ base.Fatalf("go: inconsistent vendoring in %s:%s\n\nrun 'go mod vendor' to sync, or use -mod=mod or -mod=readonly to ignore the vendor directory", modRoot, vendErrors)
+ }
+}
diff --git a/libgo/go/cmd/go/internal/mvs/mvs.go b/libgo/go/cmd/go/internal/mvs/mvs.go
index dd3b3cc..1f8eaa1 100644
--- a/libgo/go/cmd/go/internal/mvs/mvs.go
+++ b/libgo/go/cmd/go/internal/mvs/mvs.go
@@ -115,7 +115,21 @@ func (e *BuildListError) Error() string {
}
// BuildList returns the build list for the target module.
-// The first element is the target itself, with the remainder of the list sorted by path.
+//
+// target is the root vertex of a module requirement graph. For cmd/go, this is
+// typically the main module, but note that this algorithm is not intended to
+// be Go-specific: module paths and versions are treated as opaque values.
+//
+// reqs describes the module requirement graph and provides an opaque method
+// for comparing versions.
+//
+// BuildList traverses the graph and returns a list containing the highest
+// version for each visited module. The first element of the returned list is
+// target itself; reqs.Max requires target.Version to compare higher than all
+// other versions, so no other version can be selected. The remaining elements
+// of the list are sorted by path.
+//
+// See https://research.swtch.com/vgo-mvs for details.
func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) {
return buildList(target, reqs, nil)
}
@@ -220,10 +234,9 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m
// The final list is the minimum version of each module found in the graph.
if v := min[target.Path]; v != target.Version {
- // TODO(jayconrod): there is a special case in modload.mvsReqs.Max
- // that prevents us from selecting a newer version of a module
- // when the module has no version. This may only be the case for target.
- // Should we always panic when target has a version?
+ // target.Version will be "" for modload, the main client of MVS.
+ // "" denotes the main module, which has no version. However, MVS treats
+ // version strings as opaque, so "" is not a special value here.
// See golang.org/issue/31491, golang.org/issue/29773.
panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target)) // TODO: Don't panic.
}
diff --git a/libgo/go/cmd/go/internal/renameio/renameio_test.go b/libgo/go/cmd/go/internal/renameio/renameio_test.go
index ee2f3ba..df8ddab 100644
--- a/libgo/go/cmd/go/internal/renameio/renameio_test.go
+++ b/libgo/go/cmd/go/internal/renameio/renameio_test.go
@@ -9,11 +9,13 @@ package renameio
import (
"encoding/binary"
"errors"
+ "internal/testenv"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"runtime"
+ "strings"
"sync"
"sync/atomic"
"syscall"
@@ -24,6 +26,10 @@ import (
)
func TestConcurrentReadsAndWrites(t *testing.T) {
+ if runtime.GOOS == "darwin" && strings.HasSuffix(testenv.Builder(), "-10_14") {
+ testenv.SkipFlaky(t, 33041)
+ }
+
dir, err := ioutil.TempDir("", "renameio")
if err != nil {
t.Fatal(err)
diff --git a/libgo/go/cmd/go/internal/search/search.go b/libgo/go/cmd/go/internal/search/search.go
index ad33e60a..4efef24 100644
--- a/libgo/go/cmd/go/internal/search/search.go
+++ b/libgo/go/cmd/go/internal/search/search.go
@@ -9,7 +9,6 @@ import (
"cmd/go/internal/cfg"
"fmt"
"go/build"
- "log"
"os"
"path"
"path/filepath"
@@ -19,25 +18,97 @@ import (
// A Match represents the result of matching a single package pattern.
type Match struct {
- Pattern string // the pattern itself
- Literal bool // whether it is a literal (no wildcards)
- Pkgs []string // matching packages (dirs or import paths)
+ pattern string // the pattern itself
+ Dirs []string // if the pattern is local, directories that potentially contain matching packages
+ Pkgs []string // matching packages (import paths)
+ Errs []error // errors matching the patterns to packages, NOT errors loading those packages
+
+ // Errs may be non-empty even if len(Pkgs) > 0, indicating that some matching
+ // packages could be located but results may be incomplete.
+ // If len(Pkgs) == 0 && len(Errs) == 0, the pattern is well-formed but did not
+ // match any packages.
}
-// MatchPackages returns all the packages that can be found
-// under the $GOPATH directories and $GOROOT matching pattern.
-// The pattern is either "all" (all packages), "std" (standard packages),
-// "cmd" (standard commands), or a path including "...".
-func MatchPackages(pattern string) *Match {
- m := &Match{
- Pattern: pattern,
- Literal: false,
+// NewMatch returns a Match describing the given pattern,
+// without resolving its packages or errors.
+func NewMatch(pattern string) *Match {
+ return &Match{pattern: pattern}
+}
+
+// Pattern returns the pattern to be matched.
+func (m *Match) Pattern() string { return m.pattern }
+
+// AddError appends a MatchError wrapping err to m.Errs.
+func (m *Match) AddError(err error) {
+ m.Errs = append(m.Errs, &MatchError{Match: m, Err: err})
+}
+
+// Literal reports whether the pattern is free of wildcards and meta-patterns.
+//
+// A literal pattern must match at most one package.
+func (m *Match) IsLiteral() bool {
+ return !strings.Contains(m.pattern, "...") && !m.IsMeta()
+}
+
+// Local reports whether the pattern must be resolved from a specific root or
+// directory, such as a filesystem path or a single module.
+func (m *Match) IsLocal() bool {
+ return build.IsLocalImport(m.pattern) || filepath.IsAbs(m.pattern)
+}
+
+// Meta reports whether the pattern is a “meta-package” keyword that represents
+// multiple packages, such as "std", "cmd", or "all".
+func (m *Match) IsMeta() bool {
+ return IsMetaPackage(m.pattern)
+}
+
+// IsMetaPackage checks if name is a reserved package name that expands to multiple packages.
+func IsMetaPackage(name string) bool {
+ return name == "std" || name == "cmd" || name == "all"
+}
+
+// A MatchError indicates an error that occurred while attempting to match a
+// pattern.
+type MatchError struct {
+ Match *Match
+ Err error
+}
+
+func (e *MatchError) Error() string {
+ if e.Match.IsLiteral() {
+ return fmt.Sprintf("%s: %v", e.Match.Pattern(), e.Err)
+ }
+ return fmt.Sprintf("pattern %s: %v", e.Match.Pattern(), e.Err)
+}
+
+func (e *MatchError) Unwrap() error {
+ return e.Err
+}
+
+// MatchPackages sets m.Pkgs to a non-nil slice containing all the packages that
+// can be found under the $GOPATH directories and $GOROOT that match the
+// pattern. The pattern must be either "all" (all packages), "std" (standard
+// packages), "cmd" (standard commands), or a path including "...".
+//
+// If any errors may have caused the set of packages to be incomplete,
+// MatchPackages appends those errors to m.Errs.
+func (m *Match) MatchPackages() {
+ m.Pkgs = []string{}
+ if m.IsLocal() {
+ m.AddError(fmt.Errorf("internal error: MatchPackages: %s is not a valid package pattern", m.pattern))
+ return
}
+
+ if m.IsLiteral() {
+ m.Pkgs = []string{m.pattern}
+ return
+ }
+
match := func(string) bool { return true }
treeCanMatch := func(string) bool { return true }
- if !IsMetaPackage(pattern) {
- match = MatchPattern(pattern)
- treeCanMatch = TreeCanMatchPattern(pattern)
+ if !m.IsMeta() {
+ match = MatchPattern(m.pattern)
+ treeCanMatch = TreeCanMatchPattern(m.pattern)
}
have := map[string]bool{
@@ -48,17 +119,20 @@ func MatchPackages(pattern string) *Match {
}
for _, src := range cfg.BuildContext.SrcDirs() {
- if (pattern == "std" || pattern == "cmd") && src != cfg.GOROOTsrc {
+ if (m.pattern == "std" || m.pattern == "cmd") && src != cfg.GOROOTsrc {
continue
}
src = filepath.Clean(src) + string(filepath.Separator)
root := src
- if pattern == "cmd" {
+ if m.pattern == "cmd" {
root += "cmd" + string(filepath.Separator)
}
- filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
- if err != nil || path == src {
- return nil
+ err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
+ if err != nil {
+ return err // Likely a permission error, which could interfere with matching.
+ }
+ if path == src {
+ return nil // GOROOT/src and GOPATH/src cannot contain packages.
}
want := true
@@ -69,7 +143,7 @@ func MatchPackages(pattern string) *Match {
}
name := filepath.ToSlash(path[len(src):])
- if pattern == "std" && (!IsStandardImportPath(name) || name == "cmd") {
+ if m.pattern == "std" && (!IsStandardImportPath(name) || name == "cmd") {
// The name "std" is only the standard library.
// If the name is cmd, it's the root of the command tree.
want = false
@@ -100,23 +174,30 @@ func MatchPackages(pattern string) *Match {
pkg, err := cfg.BuildContext.ImportDir(path, 0)
if err != nil {
if _, noGo := err.(*build.NoGoError); noGo {
+ // The package does not actually exist, so record neither the package
+ // nor the error.
return nil
}
+ // There was an error importing path, but not matching it,
+ // which is all that Match promises to do.
+ // Ignore the import error.
}
// If we are expanding "cmd", skip main
// packages under cmd/vendor. At least as of
// March, 2017, there is one there for the
// vendored pprof tool.
- if pattern == "cmd" && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" {
+ if m.pattern == "cmd" && pkg != nil && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" {
return nil
}
m.Pkgs = append(m.Pkgs, name)
return nil
})
+ if err != nil {
+ m.AddError(err)
+ }
}
- return m
}
var modRoot string
@@ -125,24 +206,31 @@ func SetModRoot(dir string) {
modRoot = dir
}
-// MatchPackagesInFS is like MatchPackages but is passed a pattern that
-// begins with an absolute path or "./" or "../". On Windows, the pattern may
-// use slash or backslash separators or a mix of both.
+// MatchDirs sets m.Dirs to a non-nil slice containing all directories that
+// potentially match a local pattern. The pattern must begin with an absolute
+// path, or "./", or "../". On Windows, the pattern may use slash or backslash
+// separators or a mix of both.
//
-// MatchPackagesInFS scans the tree rooted at the directory that contains the
-// first "..." wildcard and returns a match with packages that
-func MatchPackagesInFS(pattern string) *Match {
- m := &Match{
- Pattern: pattern,
- Literal: false,
+// If any errors may have caused the set of directories to be incomplete,
+// MatchDirs appends those errors to m.Errs.
+func (m *Match) MatchDirs() {
+ m.Dirs = []string{}
+ if !m.IsLocal() {
+ m.AddError(fmt.Errorf("internal error: MatchDirs: %s is not a valid filesystem pattern", m.pattern))
+ return
+ }
+
+ if m.IsLiteral() {
+ m.Dirs = []string{m.pattern}
+ return
}
// Clean the path and create a matching predicate.
// filepath.Clean removes "./" prefixes (and ".\" on Windows). We need to
// preserve these, since they are meaningful in MatchPattern and in
// returned import paths.
- cleanPattern := filepath.Clean(pattern)
- isLocal := strings.HasPrefix(pattern, "./") || (os.PathSeparator == '\\' && strings.HasPrefix(pattern, `.\`))
+ cleanPattern := filepath.Clean(m.pattern)
+ isLocal := strings.HasPrefix(m.pattern, "./") || (os.PathSeparator == '\\' && strings.HasPrefix(m.pattern, `.\`))
prefix := ""
if cleanPattern != "." && isLocal {
prefix = "./"
@@ -166,16 +254,20 @@ func MatchPackagesInFS(pattern string) *Match {
if modRoot != "" {
abs, err := filepath.Abs(dir)
if err != nil {
- base.Fatalf("go: %v", err)
+ m.AddError(err)
+ return
}
if !hasFilepathPrefix(abs, modRoot) {
- base.Fatalf("go: pattern %s refers to dir %s, outside module root %s", pattern, abs, modRoot)
- return nil
+ m.AddError(fmt.Errorf("directory %s is outside module root (%s)", abs, modRoot))
+ return
}
}
- filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
- if err != nil || !fi.IsDir() {
+ err := filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
+ if err != nil {
+ return err // Likely a permission error, which could interfere with matching.
+ }
+ if !fi.IsDir() {
return nil
}
top := false
@@ -218,15 +310,21 @@ func MatchPackagesInFS(pattern string) *Match {
// behavior means people miss serious mistakes.
// See golang.org/issue/11407.
if p, err := cfg.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) {
- if _, noGo := err.(*build.NoGoError); !noGo {
- log.Print(err)
+ if _, noGo := err.(*build.NoGoError); noGo {
+ // The package does not actually exist, so record neither the package
+ // nor the error.
+ return nil
}
- return nil
+ // There was an error importing path, but not matching it,
+ // which is all that Match promises to do.
+ // Ignore the import error.
}
- m.Pkgs = append(m.Pkgs, name)
+ m.Dirs = append(m.Dirs, name)
return nil
})
- return m
+ if err != nil {
+ m.AddError(err)
+ }
}
// TreeCanMatchPattern(pattern)(name) reports whether
@@ -316,8 +414,8 @@ func replaceVendor(x, repl string) string {
// WarnUnmatched warns about patterns that didn't match any packages.
func WarnUnmatched(matches []*Match) {
for _, m := range matches {
- if len(m.Pkgs) == 0 {
- fmt.Fprintf(os.Stderr, "go: warning: %q matched no packages\n", m.Pattern)
+ if len(m.Pkgs) == 0 && len(m.Errs) == 0 {
+ fmt.Fprintf(os.Stderr, "go: warning: %q matched no packages\n", m.pattern)
}
}
}
@@ -334,40 +432,30 @@ func ImportPaths(patterns []string) []*Match {
func ImportPathsQuiet(patterns []string) []*Match {
var out []*Match
for _, a := range CleanPatterns(patterns) {
- if IsMetaPackage(a) {
- out = append(out, MatchPackages(a))
- continue
- }
-
- if build.IsLocalImport(a) || filepath.IsAbs(a) {
- var m *Match
- if strings.Contains(a, "...") {
- m = MatchPackagesInFS(a)
- } else {
- m = &Match{Pattern: a, Literal: true, Pkgs: []string{a}}
- }
+ m := NewMatch(a)
+ if m.IsLocal() {
+ m.MatchDirs()
// Change the file import path to a regular import path if the package
// is in GOPATH or GOROOT. We don't report errors here; LoadImport
// (or something similar) will report them later.
- for i, dir := range m.Pkgs {
+ m.Pkgs = make([]string, len(m.Dirs))
+ for i, dir := range m.Dirs {
+ absDir := dir
if !filepath.IsAbs(dir) {
- dir = filepath.Join(base.Cwd, dir)
+ absDir = filepath.Join(base.Cwd, dir)
}
- if bp, _ := cfg.BuildContext.ImportDir(dir, build.FindOnly); bp.ImportPath != "" && bp.ImportPath != "." {
+ if bp, _ := cfg.BuildContext.ImportDir(absDir, build.FindOnly); bp.ImportPath != "" && bp.ImportPath != "." {
m.Pkgs[i] = bp.ImportPath
+ } else {
+ m.Pkgs[i] = dir
}
}
- out = append(out, m)
- continue
- }
-
- if strings.Contains(a, "...") {
- out = append(out, MatchPackages(a))
- continue
+ } else {
+ m.MatchPackages()
}
- out = append(out, &Match{Pattern: a, Literal: true, Pkgs: []string{a}})
+ out = append(out, m)
}
return out
}
@@ -419,11 +507,6 @@ func CleanPatterns(patterns []string) []string {
return out
}
-// IsMetaPackage checks if name is a reserved package name that expands to multiple packages.
-func IsMetaPackage(name string) bool {
- return name == "std" || name == "cmd" || name == "all"
-}
-
// hasPathPrefix reports whether the path s begins with the
// elements in prefix.
func hasPathPrefix(s, prefix string) bool {
diff --git a/libgo/go/cmd/go/internal/str/path.go b/libgo/go/cmd/go/internal/str/path.go
index a4ffc5f..95d91a3 100644
--- a/libgo/go/cmd/go/internal/str/path.go
+++ b/libgo/go/cmd/go/internal/str/path.go
@@ -10,7 +10,7 @@ import (
"strings"
)
-// HasPath reports whether the slash-separated path s
+// HasPathPrefix reports whether the slash-separated path s
// begins with the elements in prefix.
func HasPathPrefix(s, prefix string) bool {
if len(s) == len(prefix) {
diff --git a/libgo/go/cmd/go/internal/test/flagdefs.go b/libgo/go/cmd/go/internal/test/flagdefs.go
new file mode 100644
index 0000000..8a0a076
--- /dev/null
+++ b/libgo/go/cmd/go/internal/test/flagdefs.go
@@ -0,0 +1,34 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by genflags.go — DO NOT EDIT.
+
+package test
+
+// passFlagToTest contains the flags that should be forwarded to
+// the test binary with the prefix "test.".
+var passFlagToTest = map[string]bool{
+ "bench": true,
+ "benchmem": true,
+ "benchtime": true,
+ "blockprofile": true,
+ "blockprofilerate": true,
+ "count": true,
+ "coverprofile": true,
+ "cpu": true,
+ "cpuprofile": true,
+ "failfast": true,
+ "list": true,
+ "memprofile": true,
+ "memprofilerate": true,
+ "mutexprofile": true,
+ "mutexprofilefraction": true,
+ "outputdir": true,
+ "parallel": true,
+ "run": true,
+ "short": true,
+ "timeout": true,
+ "trace": true,
+ "v": true,
+}
diff --git a/libgo/go/cmd/go/internal/test/flagdefs_test.go b/libgo/go/cmd/go/internal/test/flagdefs_test.go
new file mode 100644
index 0000000..7562415
--- /dev/null
+++ b/libgo/go/cmd/go/internal/test/flagdefs_test.go
@@ -0,0 +1,34 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package test
+
+import (
+ "flag"
+ "strings"
+ "testing"
+)
+
+func TestPassFlagToTestIncludesAllTestFlags(t *testing.T) {
+ flag.VisitAll(func(f *flag.Flag) {
+ if !strings.HasPrefix(f.Name, "test.") {
+ return
+ }
+ name := strings.TrimPrefix(f.Name, "test.")
+ if name != "testlogfile" && !passFlagToTest[name] {
+ t.Errorf("passFlagToTest missing entry for %q (flag test.%s)", name, name)
+ t.Logf("(Run 'go generate cmd/go/internal/test' if it should be added.)")
+ }
+ })
+
+ for name := range passFlagToTest {
+ if flag.Lookup("test."+name) == nil {
+ t.Errorf("passFlagToTest contains %q, but flag -test.%s does not exist in test binary", name, name)
+ }
+
+ if CmdTest.Flag.Lookup(name) == nil {
+ t.Errorf("passFlagToTest contains %q, but flag -%s does not exist in 'go test' subcommand", name, name)
+ }
+ }
+}
diff --git a/libgo/go/cmd/go/internal/test/genflags.go b/libgo/go/cmd/go/internal/test/genflags.go
new file mode 100644
index 0000000..512fa16
--- /dev/null
+++ b/libgo/go/cmd/go/internal/test/genflags.go
@@ -0,0 +1,90 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+ "testing"
+ "text/template"
+)
+
+func main() {
+ if err := regenerate(); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func regenerate() error {
+ t := template.Must(template.New("fileTemplate").Parse(fileTemplate))
+ buf := bytes.NewBuffer(nil)
+ if err := t.Execute(buf, testFlags()); err != nil {
+ return err
+ }
+
+ f, err := os.Create("flagdefs.go")
+ if err != nil {
+ return err
+ }
+
+ cmd := exec.Command("gofmt")
+ cmd.Stdin = buf
+ cmd.Stdout = f
+ cmd.Stderr = os.Stderr
+ cmdErr := cmd.Run()
+
+ if err := f.Close(); err != nil {
+ return err
+ }
+ if cmdErr != nil {
+ os.Remove(f.Name())
+ return cmdErr
+ }
+
+ return nil
+}
+
+func testFlags() []string {
+ testing.Init()
+
+ var names []string
+ flag.VisitAll(func(f *flag.Flag) {
+ if !strings.HasPrefix(f.Name, "test.") {
+ return
+ }
+ name := strings.TrimPrefix(f.Name, "test.")
+
+ if name == "testlogfile" {
+ // test.testlogfile is “for use only by cmd/go”
+ } else {
+ names = append(names, name)
+ }
+ })
+
+ return names
+}
+
+const fileTemplate = `// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated by genflags.go — DO NOT EDIT.
+
+package test
+
+// passFlagToTest contains the flags that should be forwarded to
+// the test binary with the prefix "test.".
+var passFlagToTest = map[string]bool {
+{{- range .}}
+ "{{.}}": true,
+{{- end }}
+}
+`
diff --git a/libgo/go/cmd/go/internal/test/test.go b/libgo/go/cmd/go/internal/test/test.go
index 4ad142c..873a76a 100644
--- a/libgo/go/cmd/go/internal/test/test.go
+++ b/libgo/go/cmd/go/internal/test/test.go
@@ -73,10 +73,10 @@ As part of building a test binary, go test runs go vet on the package
and its test source files to identify significant problems. If go vet
finds any problems, go test reports those and does not run the test
binary. Only a high-confidence subset of the default go vet checks are
-used. That subset is: 'atomic', 'bool', 'buildtags', 'nilfunc', and
-'printf'. You can see the documentation for these and other vet tests
-via "go doc cmd/vet". To disable the running of go vet, use the
--vet=off flag.
+used. That subset is: 'atomic', 'bool', 'buildtags', 'errorsas',
+'ifaceassert', 'nilfunc', 'printf', and 'stringintconv'. You can see
+the documentation for these and other vet tests via "go doc cmd/vet".
+To disable the running of go vet, use the -vet=off flag.
All test output and summary lines are printed to the go command's
standard output, even if the test printed them to its own standard
@@ -466,37 +466,78 @@ See the documentation of the testing package for more information.
}
var (
- testC bool // -c flag
- testCover bool // -cover flag
- testCoverMode string // -covermode flag
- testCoverPaths []string // -coverpkg flag
- testCoverPkgs []*load.Package // -coverpkg flag
- testCoverProfile string // -coverprofile flag
- testOutputDir string // -outputdir flag
- testO string // -o flag
- testProfile string // profiling flag that limits test to one package
- testNeedBinary bool // profile needs to keep binary around
- testJSON bool // -json flag
- testV bool // -v flag
- testTimeout string // -timeout flag
- testArgs []string
- testBench bool
- testList bool
- testShowPass bool // show passing output
- testVetList string // -vet flag
- pkgArgs []string
- pkgs []*load.Package
-
- testActualTimeout = 10 * time.Minute // actual timeout which is passed to tests
- testKillTimeout = testActualTimeout + 1*time.Minute // backup alarm
- testCacheExpire time.Time // ignore cached test results before this time
+ testBench string // -bench flag
+ testC bool // -c flag
+ testCover bool // -cover flag
+ testCoverMode string // -covermode flag
+ testCoverPaths []string // -coverpkg flag
+ testCoverPkgs []*load.Package // -coverpkg flag
+ testCoverProfile string // -coverprofile flag
+ testJSON bool // -json flag
+ testList string // -list flag
+ testO string // -o flag
+ testOutputDir = base.Cwd // -outputdir flag
+ testTimeout time.Duration // -timeout flag
+ testV bool // -v flag
+ testVet = vetFlag{flags: defaultVetFlags} // -vet flag
)
-// testVetExplicit records whether testVetFlags were set by an explicit -vet.
-var testVetExplicit = false
+var (
+ testArgs []string
+ pkgArgs []string
+ pkgs []*load.Package
+
+ testHelp bool // -help option passed to test via -args
+
+ testKillTimeout = 100 * 365 * 24 * time.Hour // backup alarm; defaults to about a century if no timeout is set
+ testCacheExpire time.Time // ignore cached test results before this time
+
+ testBlockProfile, testCPUProfile, testMemProfile, testMutexProfile, testTrace string // profiling flag that limits test to one package
+)
+
+// testProfile returns the name of an arbitrary single-package profiling flag
+// that is set, if any.
+func testProfile() string {
+ switch {
+ case testBlockProfile != "":
+ return "-blockprofile"
+ case testCPUProfile != "":
+ return "-cpuprofile"
+ case testMemProfile != "":
+ return "-memprofile"
+ case testMutexProfile != "":
+ return "-mutexprofile"
+ case testTrace != "":
+ return "-trace"
+ default:
+ return ""
+ }
+}
+
+// testNeedBinary reports whether the test needs to keep the binary around.
+func testNeedBinary() bool {
+ switch {
+ case testBlockProfile != "":
+ return true
+ case testCPUProfile != "":
+ return true
+ case testMemProfile != "":
+ return true
+ case testMutexProfile != "":
+ return true
+ case testO != "":
+ return true
+ default:
+ return false
+ }
+}
+
+// testShowPass reports whether the output for a passing test should be shown.
+func testShowPass() bool {
+ return testV || (testList != "") || testHelp
+}
-// testVetFlags is the list of flags to pass to vet when invoked automatically during go test.
-var testVetFlags = []string{
+var defaultVetFlags = []string{
// TODO(rsc): Decide which tests are enabled by default.
// See golang.org/issue/18085.
// "-asmdecl",
@@ -509,12 +550,14 @@ var testVetFlags = []string{
// "-copylocks",
"-errorsas",
// "-httpresponse",
+ "-ifaceassert",
// "-lostcancel",
// "-methods",
"-nilfunc",
"-printf",
// "-rangeloops",
// "-shift",
+ "-stringintconv",
// "-structtags",
// "-tests",
// "-unreachable",
@@ -522,22 +565,16 @@ var testVetFlags = []string{
// "-unusedresult",
}
-func testCmdUsage() {
- fmt.Fprintf(os.Stderr, "usage: %s\n", CmdTest.UsageLine)
- fmt.Fprintf(os.Stderr, "Run 'go help %s' and 'go help %s' for details.\n", CmdTest.LongName(), HelpTestflag.LongName())
- os.Exit(2)
-}
-
func runTest(cmd *base.Command, args []string) {
modload.LoadTests = true
- pkgArgs, testArgs = testFlags(testCmdUsage, args)
+ pkgArgs, testArgs = testFlags(args)
work.FindExecCmd() // initialize cached result
work.BuildInit()
- work.VetFlags = testVetFlags
- work.VetExplicit = testVetExplicit
+ work.VetFlags = testVet.flags
+ work.VetExplicit = testVet.explicit
pkgs = load.PackagesForBuild(pkgArgs)
if len(pkgs) == 0 {
@@ -550,38 +587,20 @@ func runTest(cmd *base.Command, args []string) {
if testO != "" && len(pkgs) != 1 {
base.Fatalf("cannot use -o flag with multiple packages")
}
- if testProfile != "" && len(pkgs) != 1 {
- base.Fatalf("cannot use %s flag with multiple packages", testProfile)
+ if testProfile() != "" && len(pkgs) != 1 {
+ base.Fatalf("cannot use %s flag with multiple packages", testProfile())
}
initCoverProfile()
defer closeCoverProfile()
- // If a test timeout was given and is parseable, set our kill timeout
+ // If a test timeout is finite, set our kill timeout
// to that timeout plus one minute. This is a backup alarm in case
// the test wedges with a goroutine spinning and its background
// timer does not get a chance to fire.
- if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 {
- testActualTimeout = dt
- testKillTimeout = testActualTimeout + 1*time.Minute
- } else if err == nil && dt == 0 {
- // An explicit zero disables the test timeout.
- // No timeout is passed to tests.
- // Let it have one century (almost) before we kill it.
- testActualTimeout = -1
- testKillTimeout = 100 * 365 * 24 * time.Hour
- }
-
- // Pass timeout to tests if it exists.
- // Prepend rather than appending so that it appears before positional arguments.
- if testActualTimeout > 0 {
- testArgs = append([]string{"-test.timeout=" + testActualTimeout.String()}, testArgs...)
+ if testTimeout > 0 {
+ testKillTimeout = testTimeout + 1*time.Minute
}
- // show passing test output (after buffering) with -v flag.
- // must buffer because tests are running in parallel, and
- // otherwise the output will get mixed.
- testShowPass = testV || testList
-
// For 'go test -i -o x.test', we want to build x.test. Imply -c to make the logic easier.
if cfg.BuildI && testO != "" {
testC = true
@@ -755,7 +774,7 @@ func runTest(cmd *base.Command, args []string) {
}
// Force benchmarks to run in serial.
- if !testC && testBench {
+ if !testC && (testBench != "") {
// The first run must wait for all builds.
// Later runs must wait for the previous run's print.
for i, run := range runs {
@@ -839,7 +858,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
}
pmain.Dir = testDir
- pmain.Internal.OmitDebug = !testC && !testNeedBinary
+ pmain.Internal.OmitDebug = !testC && !testNeedBinary()
if !cfg.BuildN {
// writeTestmain writes _testmain.go,
@@ -887,7 +906,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
}
buildAction = a
var installAction, cleanAction *work.Action
- if testC || testNeedBinary {
+ if testC || testNeedBinary() {
// -c or profiling flag: create action to copy binary to ./test.out.
target := filepath.Join(base.Cwd, testBinary+cfg.ExeSuffix)
if testO != "" {
@@ -964,7 +983,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
}
func addTestVet(b *work.Builder, p *load.Package, runAction, installAction *work.Action) {
- if testVetList == "off" {
+ if testVet.off {
return
}
@@ -1067,7 +1086,7 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error {
}
var buf bytes.Buffer
- if len(pkgArgs) == 0 || testBench {
+ if len(pkgArgs) == 0 || (testBench != "") {
// Stream test output (no buffering) when no package has
// been given on the command line (implicit current directory)
// or when benchmarking.
@@ -1087,7 +1106,7 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error {
// possible even when multiple tests are being run: the JSON output
// events are attributed to specific package tests, so interlacing them
// is OK.
- if testShowPass && (len(pkgs) == 1 || cfg.BuildP == 1) || testJSON {
+ if testShowPass() && (len(pkgs) == 1 || cfg.BuildP == 1) || testJSON {
// Write both to stdout and buf, for possible saving
// to cache, and for looking for the "no tests to run" message.
stdout = io.MultiWriter(stdout, &buf)
@@ -1142,7 +1161,7 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error {
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = a.Package.Dir
- cmd.Env = base.EnvForDir(cmd.Dir, cfg.OrigEnv[:len(cfg.OrigEnv):len(cfg.OrigEnv)])
+ cmd.Env = base.AppendPWD(cfg.OrigEnv[:len(cfg.OrigEnv):len(cfg.OrigEnv)], cmd.Dir)
cmd.Stdout = stdout
cmd.Stderr = stdout
@@ -1209,7 +1228,7 @@ func (c *runCache) builderRunTest(b *work.Builder, a *work.Action) error {
if err == nil {
norun := ""
- if !testShowPass && !testJSON {
+ if !testShowPass() && !testJSON {
buf.Reset()
}
if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
@@ -1284,16 +1303,13 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo
"-test.parallel",
"-test.run",
"-test.short",
+ "-test.timeout",
"-test.v":
// These are cacheable.
// Note that this list is documented above,
// so if you add to this list, update the docs too.
cacheArgs = append(cacheArgs, arg)
- case "-test.timeout":
- // Special case: this is cacheable but ignored during the hash.
- // Do not add to cacheArgs.
-
default:
// nothing else is cacheable
if cache.DebugTest {
diff --git a/libgo/go/cmd/go/internal/test/testflag.go b/libgo/go/cmd/go/internal/test/testflag.go
index e214b15..1ff34f7 100644
--- a/libgo/go/cmd/go/internal/test/testflag.go
+++ b/libgo/go/cmd/go/internal/test/testflag.go
@@ -5,81 +5,197 @@
package test
import (
+ "errors"
"flag"
+ "fmt"
"os"
+ "path/filepath"
"strings"
+ "time"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/cmdflag"
- "cmd/go/internal/str"
"cmd/go/internal/work"
)
-const cmd = "test"
+//go:generate go run ./genflags.go
// The flag handling part of go test is large and distracting.
-// We can't use the flag package because some of the flags from
-// our command line are for us, and some are for 6.out, and
+// We can't use (*flag.FlagSet).Parse because some of the flags from
+// our command line are for us, and some are for the test binary, and
// some are for both.
-// testFlagDefn is the set of flags we process.
-var testFlagDefn = []*cmdflag.Defn{
- // local.
- {Name: "c", BoolVar: &testC},
- {Name: "i", BoolVar: &cfg.BuildI},
- {Name: "o"},
- {Name: "cover", BoolVar: &testCover},
- {Name: "covermode"},
- {Name: "coverpkg"},
- {Name: "exec"},
- {Name: "json", BoolVar: &testJSON},
- {Name: "vet"},
-
- // Passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
- {Name: "bench", PassToTest: true},
- {Name: "benchmem", BoolVar: new(bool), PassToTest: true},
- {Name: "benchtime", PassToTest: true},
- {Name: "blockprofile", PassToTest: true},
- {Name: "blockprofilerate", PassToTest: true},
- {Name: "count", PassToTest: true},
- {Name: "coverprofile", PassToTest: true},
- {Name: "cpu", PassToTest: true},
- {Name: "cpuprofile", PassToTest: true},
- {Name: "failfast", BoolVar: new(bool), PassToTest: true},
- {Name: "list", PassToTest: true},
- {Name: "memprofile", PassToTest: true},
- {Name: "memprofilerate", PassToTest: true},
- {Name: "mutexprofile", PassToTest: true},
- {Name: "mutexprofilefraction", PassToTest: true},
- {Name: "outputdir", PassToTest: true},
- {Name: "parallel", PassToTest: true},
- {Name: "run", PassToTest: true},
- {Name: "short", BoolVar: new(bool), PassToTest: true},
- {Name: "timeout", PassToTest: true},
- {Name: "trace", PassToTest: true},
- {Name: "v", BoolVar: &testV, PassToTest: true},
+func init() {
+ work.AddBuildFlags(CmdTest, work.OmitVFlag)
+
+ cf := CmdTest.Flag
+ cf.BoolVar(&testC, "c", false, "")
+ cf.BoolVar(&cfg.BuildI, "i", false, "")
+ cf.StringVar(&testO, "o", "", "")
+
+ cf.BoolVar(&testCover, "cover", false, "")
+ cf.Var(coverFlag{(*coverModeFlag)(&testCoverMode)}, "covermode", "")
+ cf.Var(coverFlag{commaListFlag{&testCoverPaths}}, "coverpkg", "")
+
+ cf.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "")
+ cf.BoolVar(&testJSON, "json", false, "")
+ cf.Var(&testVet, "vet", "")
+
+ // Register flags to be forwarded to the test binary. We retain variables for
+ // some of them so that cmd/go knows what to do with the test output, or knows
+ // to build the test in a way that supports the use of the flag.
+
+ cf.StringVar(&testBench, "bench", "", "")
+ cf.Bool("benchmem", false, "")
+ cf.String("benchtime", "", "")
+ cf.StringVar(&testBlockProfile, "blockprofile", "", "")
+ cf.String("blockprofilerate", "", "")
+ cf.Int("count", 0, "")
+ cf.Var(coverFlag{stringFlag{&testCoverProfile}}, "coverprofile", "")
+ cf.String("cpu", "", "")
+ cf.StringVar(&testCPUProfile, "cpuprofile", "", "")
+ cf.Bool("failfast", false, "")
+ cf.StringVar(&testList, "list", "", "")
+ cf.StringVar(&testMemProfile, "memprofile", "", "")
+ cf.String("memprofilerate", "", "")
+ cf.StringVar(&testMutexProfile, "mutexprofile", "", "")
+ cf.String("mutexprofilefraction", "", "")
+ cf.Var(outputdirFlag{&testOutputDir}, "outputdir", "")
+ cf.Int("parallel", 0, "")
+ cf.String("run", "", "")
+ cf.Bool("short", false, "")
+ cf.DurationVar(&testTimeout, "timeout", 10*time.Minute, "")
+ cf.StringVar(&testTrace, "trace", "", "")
+ cf.BoolVar(&testV, "v", false, "")
+
+ for name, _ := range passFlagToTest {
+ cf.Var(cf.Lookup(name).Value, "test."+name, "")
+ }
}
-// add build flags to testFlagDefn
-func init() {
- cmdflag.AddKnownFlags("test", testFlagDefn)
- var cmd base.Command
- work.AddBuildFlags(&cmd, work.DefaultBuildFlags)
- cmd.Flag.VisitAll(func(f *flag.Flag) {
- if f.Name == "v" {
- // test overrides the build -v flag
- return
+// A coverFlag is a flag.Value that also implies -cover.
+type coverFlag struct{ v flag.Value }
+
+func (f coverFlag) String() string { return f.v.String() }
+
+func (f coverFlag) Set(value string) error {
+ if err := f.v.Set(value); err != nil {
+ return err
+ }
+ testCover = true
+ return nil
+}
+
+type coverModeFlag string
+
+func (f *coverModeFlag) String() string { return string(*f) }
+func (f *coverModeFlag) Set(value string) error {
+ switch value {
+ case "", "set", "count", "atomic":
+ *f = coverModeFlag(value)
+ return nil
+ default:
+ return errors.New(`valid modes are "set", "count", or "atomic"`)
+ }
+}
+
+// A commaListFlag is a flag.Value representing a comma-separated list.
+type commaListFlag struct{ vals *[]string }
+
+func (f commaListFlag) String() string { return strings.Join(*f.vals, ",") }
+
+func (f commaListFlag) Set(value string) error {
+ if value == "" {
+ *f.vals = nil
+ } else {
+ *f.vals = strings.Split(value, ",")
+ }
+ return nil
+}
+
+// A stringFlag is a flag.Value representing a single string.
+type stringFlag struct{ val *string }
+
+func (f stringFlag) String() string { return *f.val }
+func (f stringFlag) Set(value string) error {
+ *f.val = value
+ return nil
+}
+
+// outputdirFlag implements the -outputdir flag.
+// It interprets an empty value as the working directory of the 'go' command.
+type outputdirFlag struct {
+ resolved *string
+}
+
+func (f outputdirFlag) String() string { return *f.resolved }
+func (f outputdirFlag) Set(value string) (err error) {
+ if value == "" {
+ // The empty string implies the working directory of the 'go' command.
+ *f.resolved = base.Cwd
+ } else {
+ *f.resolved, err = filepath.Abs(value)
+ }
+ return err
+}
+
+// vetFlag implements the special parsing logic for the -vet flag:
+// a comma-separated list, with a distinguished value "off" and
+// a boolean tracking whether it was set explicitly.
+type vetFlag struct {
+ explicit bool
+ off bool
+ flags []string // passed to vet when invoked automatically during 'go test'
+}
+
+func (f *vetFlag) String() string {
+ if f.off {
+ return "off"
+ }
+
+ var buf strings.Builder
+ for i, f := range f.flags {
+ if i > 0 {
+ buf.WriteByte(',')
}
- testFlagDefn = append(testFlagDefn, &cmdflag.Defn{
- Name: f.Name,
- Value: f.Value,
- })
- })
+ buf.WriteString(f)
+ }
+ return buf.String()
+}
+
+func (f *vetFlag) Set(value string) error {
+ if value == "" {
+ *f = vetFlag{flags: defaultVetFlags}
+ return nil
+ }
+
+ if value == "off" {
+ *f = vetFlag{
+ explicit: true,
+ off: true,
+ }
+ return nil
+ }
+
+ if strings.Contains(value, "=") {
+ return fmt.Errorf("-vet argument cannot contain equal signs")
+ }
+ if strings.Contains(value, " ") {
+ return fmt.Errorf("-vet argument is comma-separated list, cannot contain spaces")
+ }
+ *f = vetFlag{explicit: true}
+ for _, arg := range strings.Split(value, ",") {
+ if arg == "" {
+ return fmt.Errorf("-vet argument contains empty list element")
+ }
+ f.flags = append(f.flags, "-"+arg)
+ }
+ return nil
}
// testFlags processes the command line, grabbing -x and -c, rewriting known flags
-// to have "test" before them, and reading the command line for the 6.out.
+// to have "test" before them, and reading the command line for the test binary.
// Unfortunately for us, we need to do our own flag processing because go test
// grabs some flags but otherwise its command line is just a holding place for
// pkg.test's arguments.
@@ -87,117 +203,154 @@ func init() {
// to allow both
// go test fmt -custom-flag-for-fmt-test
// go test -x math
-func testFlags(usage func(), args []string) (packageNames, passToTest []string) {
- goflags := cmdflag.FindGOFLAGS(testFlagDefn)
- args = str.StringList(goflags, args)
- inPkg := false
- var explicitArgs []string
- for i := 0; i < len(args); i++ {
- if !strings.HasPrefix(args[i], "-") {
- if !inPkg && packageNames == nil {
- // First package name we've seen.
- inPkg = true
- }
- if inPkg {
- packageNames = append(packageNames, args[i])
- continue
+func testFlags(args []string) (packageNames, passToTest []string) {
+ base.SetFromGOFLAGS(&CmdTest.Flag)
+ addFromGOFLAGS := map[string]bool{}
+ CmdTest.Flag.Visit(func(f *flag.Flag) {
+ if short := strings.TrimPrefix(f.Name, "test."); passFlagToTest[short] {
+ addFromGOFLAGS[f.Name] = true
+ }
+ })
+
+ explicitArgs := make([]string, 0, len(args))
+ inPkgList := false
+ for len(args) > 0 {
+ f, remainingArgs, err := cmdflag.ParseOne(&CmdTest.Flag, args)
+
+ if errors.Is(err, flag.ErrHelp) {
+ exitWithUsage()
+ }
+
+ if errors.Is(err, cmdflag.ErrFlagTerminator) {
+ // 'go list' allows package arguments to be named either before or after
+ // the terminator, but 'go test' has historically allowed them only
+ // before. Preserve that behavior and treat all remaining arguments —
+ // including the terminator itself! — as arguments to the test.
+ explicitArgs = append(explicitArgs, args...)
+ break
+ }
+
+ if nf := (cmdflag.NonFlagError{}); errors.As(err, &nf) {
+ if !inPkgList && packageNames != nil {
+ // We already saw the package list previously, and this argument is not
+ // a flag, so it — and everything after it — must be a literal argument
+ // to the test binary.
+ explicitArgs = append(explicitArgs, args...)
+ break
}
+
+ inPkgList = true
+ packageNames = append(packageNames, nf.RawArg)
+ args = remainingArgs // Consume the package name.
+ continue
}
- if inPkg {
- // Found an argument beginning with "-"; end of package list.
- inPkg = false
+ if inPkgList {
+ // This argument is syntactically a flag, so if we were in the package
+ // list we're not anymore.
+ inPkgList = false
}
- f, value, extraWord := cmdflag.Parse(cmd, usage, testFlagDefn, args, i)
- if f == nil {
- // This is a flag we do not know; we must assume
- // that any args we see after this might be flag
- // arguments, not package names.
- inPkg = false
+ if nd := (cmdflag.FlagNotDefinedError{}); errors.As(err, &nd) {
+ // This is a flag we do not know. We must assume that any args we see
+ // after this might be flag arguments, not package names, so make
+ // packageNames non-nil to indicate that the package list is complete.
+ //
+ // (Actually, we only strictly need to assume that if the flag is not of
+ // the form -x=value, but making this more precise would be a breaking
+ // change in the command line API.)
if packageNames == nil {
- // make non-nil: we have seen the empty package list
packageNames = []string{}
}
- if args[i] == "-args" || args[i] == "--args" {
+
+ if nd.RawArg == "-args" || nd.RawArg == "--args" {
// -args or --args signals that everything that follows
// should be passed to the test.
- explicitArgs = args[i+1:]
+ explicitArgs = append(explicitArgs, remainingArgs...)
break
}
- passToTest = append(passToTest, args[i])
+
+ explicitArgs = append(explicitArgs, nd.RawArg)
+ args = remainingArgs
continue
}
- if i < len(goflags) {
- f.Present = false // Not actually present on the command line.
+
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ exitWithUsage()
}
- if f.Value != nil {
- if err := f.Value.Set(value); err != nil {
- base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
- }
- } else {
- // Test-only flags.
- // Arguably should be handled by f.Value, but aren't.
- switch f.Name {
- // bool flags.
- case "c", "i", "v", "cover", "json":
- cmdflag.SetBool(cmd, f.BoolVar, value)
- if f.Name == "json" && testJSON {
- passToTest = append(passToTest, "-test.v=true")
- }
- case "o":
- testO = value
- testNeedBinary = true
- case "exec":
- xcmd, err := str.SplitQuotedFields(value)
- if err != nil {
- base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
- }
- work.ExecCmd = xcmd
- case "bench":
- // record that we saw the flag; don't care about the value
- testBench = true
- case "list":
- testList = true
- case "timeout":
- testTimeout = value
- case "blockprofile", "cpuprofile", "memprofile", "mutexprofile":
- testProfile = "-" + f.Name
- testNeedBinary = true
- case "trace":
- testProfile = "-trace"
- case "coverpkg":
- testCover = true
- if value == "" {
- testCoverPaths = nil
- } else {
- testCoverPaths = strings.Split(value, ",")
- }
- case "coverprofile":
- testCover = true
- testCoverProfile = value
- case "covermode":
- switch value {
- case "set", "count", "atomic":
- testCoverMode = value
- default:
- base.Fatalf("invalid flag argument for -covermode: %q", value)
- }
- testCover = true
- case "outputdir":
- testOutputDir = value
- case "vet":
- testVetList = value
- }
+
+ if short := strings.TrimPrefix(f.Name, "test."); passFlagToTest[short] {
+ explicitArgs = append(explicitArgs, fmt.Sprintf("-test.%s=%v", short, f.Value))
+
+ // This flag has been overridden explicitly, so don't forward its implicit
+ // value from GOFLAGS.
+ delete(addFromGOFLAGS, short)
+ delete(addFromGOFLAGS, "test."+short)
}
- if extraWord {
- i++
+
+ args = remainingArgs
+ }
+
+ var injectedFlags []string
+ if testJSON {
+ // If converting to JSON, we need the full output in order to pipe it to
+ // test2json.
+ injectedFlags = append(injectedFlags, "-test.v=true")
+ delete(addFromGOFLAGS, "v")
+ delete(addFromGOFLAGS, "test.v")
+ }
+
+ // Inject flags from GOFLAGS before the explicit command-line arguments.
+ // (They must appear before the flag terminator or first non-flag argument.)
+ // Also determine whether flags with awkward defaults have already been set.
+ var timeoutSet, outputDirSet bool
+ CmdTest.Flag.Visit(func(f *flag.Flag) {
+ short := strings.TrimPrefix(f.Name, "test.")
+ if addFromGOFLAGS[f.Name] {
+ injectedFlags = append(injectedFlags, fmt.Sprintf("-test.%s=%v", short, f.Value))
+ }
+ switch short {
+ case "timeout":
+ timeoutSet = true
+ case "outputdir":
+ outputDirSet = true
}
- if f.PassToTest {
- passToTest = append(passToTest, "-test."+f.Name+"="+value)
+ })
+
+ // 'go test' has a default timeout, but the test binary itself does not.
+ // If the timeout wasn't set (and forwarded) explicitly, add the default
+ // timeout to the command line.
+ if testTimeout > 0 && !timeoutSet {
+ injectedFlags = append(injectedFlags, fmt.Sprintf("-test.timeout=%v", testTimeout))
+ }
+
+ // Similarly, the test binary defaults -test.outputdir to its own working
+ // directory, but 'go test' defaults it to the working directory of the 'go'
+ // command. Set it explicitly if it is needed due to some other flag that
+ // requests output.
+ if testProfile() != "" && !outputDirSet {
+ injectedFlags = append(injectedFlags, "-test.outputdir="+testOutputDir)
+ }
+
+ // If the user is explicitly passing -help or -h, show output
+ // of the test binary so that the help output is displayed
+ // even though the test will exit with success.
+ // This loop is imperfect: it will do the wrong thing for a case
+ // like -args -test.outputdir -help. Such cases are probably rare,
+ // and getting this wrong doesn't do too much harm.
+helpLoop:
+ for _, arg := range explicitArgs {
+ switch arg {
+ case "--":
+ break helpLoop
+ case "-h", "-help", "--help":
+ testHelp = true
+ break helpLoop
}
}
+ // Ensure that -race and -covermode are compatible.
if testCoverMode == "" {
testCoverMode = "set"
if cfg.BuildRace {
@@ -205,35 +358,18 @@ func testFlags(usage func(), args []string) (packageNames, passToTest []string)
testCoverMode = "atomic"
}
}
-
- testVetExplicit = testVetList != ""
- if testVetList != "" && testVetList != "off" {
- if strings.Contains(testVetList, "=") {
- base.Fatalf("-vet argument cannot contain equal signs")
- }
- if strings.Contains(testVetList, " ") {
- base.Fatalf("-vet argument is comma-separated list, cannot contain spaces")
- }
- list := strings.Split(testVetList, ",")
- for i, arg := range list {
- list[i] = "-" + arg
- }
- testVetFlags = list
- }
-
if cfg.BuildRace && testCoverMode != "atomic" {
base.Fatalf(`-covermode must be "atomic", not %q, when -race is enabled`, testCoverMode)
}
- // Tell the test what directory we're running in, so it can write the profiles there.
- if testProfile != "" && testOutputDir == "" {
- dir, err := os.Getwd()
- if err != nil {
- base.Fatalf("error from os.Getwd: %s", err)
- }
- passToTest = append(passToTest, "-test.outputdir", dir)
- }
+ // Forward any unparsed arguments (following --args) to the test binary.
+ return packageNames, append(injectedFlags, explicitArgs...)
+}
+
+func exitWithUsage() {
+ fmt.Fprintf(os.Stderr, "usage: %s\n", CmdTest.UsageLine)
+ fmt.Fprintf(os.Stderr, "Run 'go help %s' and 'go help %s' for details.\n", CmdTest.LongName(), HelpTestflag.LongName())
- passToTest = append(passToTest, explicitArgs...)
- return
+ base.SetExitStatus(2)
+ base.Exit()
}
diff --git a/libgo/go/cmd/go/internal/version/version.go b/libgo/go/cmd/go/internal/version/version.go
index 857548c..ac2ae50 100644
--- a/libgo/go/cmd/go/internal/version/version.go
+++ b/libgo/go/cmd/go/internal/version/version.go
@@ -53,6 +53,11 @@ var (
func runVersion(cmd *base.Command, args []string) {
if len(args) == 0 {
+ if *versionM || *versionV {
+ fmt.Fprintf(os.Stderr, "go version: flags can only be used with arguments\n")
+ base.SetExitStatus(2)
+ return
+ }
fmt.Printf("go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
return
}
@@ -61,6 +66,7 @@ func runVersion(cmd *base.Command, args []string) {
info, err := os.Stat(arg)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
+ base.SetExitStatus(1)
continue
}
if info.IsDir() {
diff --git a/libgo/go/cmd/go/internal/vet/vet.go b/libgo/go/cmd/go/internal/vet/vet.go
index 4e09c0f..4ec58de 100644
--- a/libgo/go/cmd/go/internal/vet/vet.go
+++ b/libgo/go/cmd/go/internal/vet/vet.go
@@ -13,8 +13,12 @@ import (
"path/filepath"
)
+// Break init loop.
+func init() {
+ CmdVet.Run = runVet
+}
+
var CmdVet = &base.Command{
- Run: runVet,
CustomFlags: true,
UsageLine: "go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]",
Short: "report likely mistakes in packages",
@@ -47,7 +51,7 @@ See also: go fmt, go fix.
func runVet(cmd *base.Command, args []string) {
modload.LoadTests = true
- vetFlags, pkgArgs := vetFlags(vetUsage, args)
+ vetFlags, pkgArgs := vetFlags(args)
work.BuildInit()
work.VetFlags = vetFlags
diff --git a/libgo/go/cmd/go/internal/vet/vetflag.go b/libgo/go/cmd/go/internal/vet/vetflag.go
index e3de48b..ef995ef 100644
--- a/libgo/go/cmd/go/internal/vet/vetflag.go
+++ b/libgo/go/cmd/go/internal/vet/vetflag.go
@@ -7,6 +7,7 @@ package vet
import (
"bytes"
"encoding/json"
+ "errors"
"flag"
"fmt"
"log"
@@ -17,7 +18,6 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cmdflag"
- "cmd/go/internal/str"
"cmd/go/internal/work"
)
@@ -39,37 +39,44 @@ import (
var vetTool string // -vettool
func init() {
+ work.AddBuildFlags(CmdVet, work.DefaultBuildFlags)
+ CmdVet.Flag.StringVar(&vetTool, "vettool", "", "")
+}
+
+func parseVettoolFlag(args []string) {
// Extract -vettool by ad hoc flag processing:
// its value is needed even before we can declare
// the flags available during main flag processing.
- for i, arg := range os.Args {
+ for i, arg := range args {
if arg == "-vettool" || arg == "--vettool" {
- if i+1 >= len(os.Args) {
+ if i+1 >= len(args) {
log.Fatalf("%s requires a filename", arg)
}
- vetTool = os.Args[i+1]
- break
+ vetTool = args[i+1]
+ return
} else if strings.HasPrefix(arg, "-vettool=") ||
strings.HasPrefix(arg, "--vettool=") {
vetTool = arg[strings.IndexByte(arg, '=')+1:]
- break
+ return
}
}
}
// vetFlags processes the command line, splitting it at the first non-flag
// into the list of flags and list of packages.
-func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
+func vetFlags(args []string) (passToVet, packageNames []string) {
+ parseVettoolFlag(args)
+
// Query the vet command for its flags.
- tool := vetTool
- if tool != "" {
+ var tool string
+ if vetTool == "" {
+ tool = base.Tool("vet")
+ } else {
var err error
- tool, err = filepath.Abs(tool)
+ tool, err = filepath.Abs(vetTool)
if err != nil {
log.Fatal(err)
}
- } else {
- tool = base.Tool("vet")
}
out := new(bytes.Buffer)
vetcmd := exec.Command(tool, "-flags")
@@ -90,95 +97,85 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
base.Exit()
}
- // Add vet's flags to vetflagDefn.
+ // Add vet's flags to CmdVet.Flag.
//
// Some flags, in particular -tags and -v, are known to vet but
- // also defined as build flags. This works fine, so we don't
- // define them here but use AddBuildFlags to init them.
+ // also defined as build flags. This works fine, so we omit duplicates here.
// However some, like -x, are known to the build but not to vet.
- var vetFlagDefn []*cmdflag.Defn
+ isVetFlag := make(map[string]bool, len(analysisFlags))
+ cf := CmdVet.Flag
for _, f := range analysisFlags {
- switch f.Name {
- case "tags", "v":
- continue
- }
- defn := &cmdflag.Defn{
- Name: f.Name,
- PassToTest: true,
- }
- if f.Bool {
- defn.BoolVar = new(bool)
+ isVetFlag[f.Name] = true
+ if cf.Lookup(f.Name) == nil {
+ if f.Bool {
+ cf.Bool(f.Name, false, "")
+ } else {
+ cf.String(f.Name, "", "")
+ }
}
- vetFlagDefn = append(vetFlagDefn, defn)
}
- // Add build flags to vetFlagDefn.
- var cmd base.Command
- work.AddBuildFlags(&cmd, work.DefaultBuildFlags)
- // This flag declaration is a placeholder:
- // -vettool is actually parsed by the init function above.
- cmd.Flag.StringVar(new(string), "vettool", "", "path to vet tool binary")
- cmd.Flag.VisitAll(func(f *flag.Flag) {
- vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{
- Name: f.Name,
- Value: f.Value,
- })
+ // Record the set of vet tool flags set by GOFLAGS. We want to pass them to
+ // the vet tool, but only if they aren't overridden by an explicit argument.
+ base.SetFromGOFLAGS(&CmdVet.Flag)
+ addFromGOFLAGS := map[string]bool{}
+ CmdVet.Flag.Visit(func(f *flag.Flag) {
+ if isVetFlag[f.Name] {
+ addFromGOFLAGS[f.Name] = true
+ }
})
- // Process args.
- goflags := cmdflag.FindGOFLAGS(vetFlagDefn)
- args = str.StringList(goflags, args)
- for i := 0; i < len(args); i++ {
- if !strings.HasPrefix(args[i], "-") {
- return args[:i], args[i:]
+ explicitFlags := make([]string, 0, len(args))
+ for len(args) > 0 {
+ f, remainingArgs, err := cmdflag.ParseOne(&CmdVet.Flag, args)
+
+ if errors.Is(err, flag.ErrHelp) {
+ exitWithUsage()
}
- f, value, extraWord := cmdflag.Parse("vet", usage, vetFlagDefn, args, i)
- if f == nil {
- fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
- fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
- base.SetExitStatus(2)
- base.Exit()
+ if errors.Is(err, cmdflag.ErrFlagTerminator) {
+ // All remaining args must be package names, but the flag terminator is
+ // not included.
+ packageNames = remainingArgs
+ break
}
- if i < len(goflags) {
- f.Present = false // Not actually present on the command line.
+
+ if nf := (cmdflag.NonFlagError{}); errors.As(err, &nf) {
+ // Everything from here on out — including the argument we just consumed —
+ // must be a package name.
+ packageNames = args
+ break
}
- if f.Value != nil {
- if err := f.Value.Set(value); err != nil {
- base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
- }
- keep := f.PassToTest
- if !keep {
- // A build flag, probably one we don't want to pass to vet.
- // Can whitelist.
- switch f.Name {
- case "tags", "v":
- keep = true
- }
- }
- if !keep {
- // Flags known to the build but not to vet, so must be dropped.
- if extraWord {
- args = append(args[:i], args[i+2:]...)
- extraWord = false
- } else {
- args = append(args[:i], args[i+1:]...)
- }
- i--
- }
+
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ exitWithUsage()
}
- if extraWord {
- i++
+
+ if isVetFlag[f.Name] {
+ // Forward the raw arguments rather than cleaned equivalents, just in
+ // case the vet tool parses them idiosyncratically.
+ explicitFlags = append(explicitFlags, args[:len(args)-len(remainingArgs)]...)
+
+ // This flag has been overridden explicitly, so don't forward its implicit
+ // value from GOFLAGS.
+ delete(addFromGOFLAGS, f.Name)
}
- }
- return args, nil
-}
-var vetUsage func()
+ args = remainingArgs
+ }
-func init() { vetUsage = usage } // break initialization cycle
+ // Prepend arguments from GOFLAGS before other arguments.
+ CmdVet.Flag.Visit(func(f *flag.Flag) {
+ if addFromGOFLAGS[f.Name] {
+ passToVet = append(passToVet, fmt.Sprintf("-%s=%s", f.Name, f.Value))
+ }
+ })
+ passToVet = append(passToVet, explicitFlags...)
+ return passToVet, packageNames
+}
-func usage() {
+func exitWithUsage() {
fmt.Fprintf(os.Stderr, "usage: %s\n", CmdVet.UsageLine)
fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", CmdVet.LongName())
diff --git a/libgo/go/cmd/go/internal/web/api.go b/libgo/go/cmd/go/internal/web/api.go
index 209ed68..5708188 100644
--- a/libgo/go/cmd/go/internal/web/api.go
+++ b/libgo/go/cmd/go/internal/web/api.go
@@ -89,7 +89,7 @@ func GetBytes(u *url.URL) ([]byte, error) {
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
- return nil, fmt.Errorf("reading %s: %v", Redacted(u), err)
+ return nil, fmt.Errorf("reading %s: %v", u.Redacted(), err)
}
return b, nil
}
@@ -183,21 +183,6 @@ func Get(security SecurityMode, u *url.URL) (*Response, error) {
return get(security, u)
}
-// Redacted returns a redacted string form of the URL,
-// suitable for printing in error messages.
-// The string form replaces any non-empty password
-// in the original URL with "[redacted]".
-func Redacted(u *url.URL) string {
- if u.User != nil {
- if _, ok := u.User.Password(); ok {
- redacted := *u
- redacted.User = url.UserPassword(u.User.Username(), "[redacted]")
- u = &redacted
- }
- }
- return u.String()
-}
-
// OpenBrowser attempts to open the requested URL in a web browser.
func OpenBrowser(url string) (opened bool) {
return openBrowser(url)
diff --git a/libgo/go/cmd/go/internal/web/http.go b/libgo/go/cmd/go/internal/web/http.go
index 5e4319b..e050980 100644
--- a/libgo/go/cmd/go/internal/web/http.go
+++ b/libgo/go/cmd/go/internal/web/http.go
@@ -13,6 +13,7 @@ package web
import (
"crypto/tls"
+ "errors"
"fmt"
"mime"
"net/http"
@@ -47,6 +48,13 @@ var securityPreservingHTTPClient = &http.Client{
lastHop := via[len(via)-1].URL
return fmt.Errorf("redirected from secure URL %s to insecure URL %s", lastHop, req.URL)
}
+
+ // Go's http.DefaultClient allows 10 redirects before returning an error.
+ // The securityPreservingHTTPClient also uses this default policy to avoid
+ // Go command hangs.
+ if len(via) >= 10 {
+ return errors.New("stopped after 10 redirects")
+ }
return nil
},
}
@@ -60,14 +68,14 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
if os.Getenv("TESTGOPROXY404") == "1" && url.Host == "proxy.golang.org" {
res := &Response{
- URL: Redacted(url),
+ URL: url.Redacted(),
Status: "404 testing",
StatusCode: 404,
Header: make(map[string][]string),
Body: http.NoBody,
}
if cfg.BuildX {
- fmt.Fprintf(os.Stderr, "# get %s: %v (%.3fs)\n", Redacted(url), res.Status, time.Since(start).Seconds())
+ fmt.Fprintf(os.Stderr, "# get %s: %v (%.3fs)\n", url.Redacted(), res.Status, time.Since(start).Seconds())
}
return res, nil
}
@@ -78,7 +86,7 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
// We print extra logging in -x mode instead, which traces what
// commands are executed.
if cfg.BuildX {
- fmt.Fprintf(os.Stderr, "# get %s\n", Redacted(url))
+ fmt.Fprintf(os.Stderr, "# get %s\n", url.Redacted())
}
req, err := http.NewRequest("GET", url.String(), nil)
@@ -111,7 +119,7 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
fetched, res, err = fetch(secure)
if err != nil {
if cfg.BuildX {
- fmt.Fprintf(os.Stderr, "# get %s: %v\n", Redacted(secure), err)
+ fmt.Fprintf(os.Stderr, "# get %s: %v\n", secure.Redacted(), err)
}
if security != Insecure || url.Scheme == "https" {
// HTTPS failed, and we can't fall back to plain HTTP.
@@ -126,9 +134,9 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
case "http":
if security == SecureOnly {
if cfg.BuildX {
- fmt.Fprintf(os.Stderr, "# get %s: insecure\n", Redacted(url))
+ fmt.Fprintf(os.Stderr, "# get %s: insecure\n", url.Redacted())
}
- return nil, fmt.Errorf("insecure URL: %s", Redacted(url))
+ return nil, fmt.Errorf("insecure URL: %s", url.Redacted())
}
case "":
if security != Insecure {
@@ -136,9 +144,9 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
}
default:
if cfg.BuildX {
- fmt.Fprintf(os.Stderr, "# get %s: unsupported\n", Redacted(url))
+ fmt.Fprintf(os.Stderr, "# get %s: unsupported\n", url.Redacted())
}
- return nil, fmt.Errorf("unsupported scheme: %s", Redacted(url))
+ return nil, fmt.Errorf("unsupported scheme: %s", url.Redacted())
}
insecure := new(urlpkg.URL)
@@ -146,15 +154,15 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
insecure.Scheme = "http"
if insecure.User != nil && security != Insecure {
if cfg.BuildX {
- fmt.Fprintf(os.Stderr, "# get %s: insecure credentials\n", Redacted(insecure))
+ fmt.Fprintf(os.Stderr, "# get %s: insecure credentials\n", insecure.Redacted())
}
- return nil, fmt.Errorf("refusing to pass credentials to insecure URL: %s", Redacted(insecure))
+ return nil, fmt.Errorf("refusing to pass credentials to insecure URL: %s", insecure.Redacted())
}
fetched, res, err = fetch(insecure)
if err != nil {
if cfg.BuildX {
- fmt.Fprintf(os.Stderr, "# get %s: %v\n", Redacted(insecure), err)
+ fmt.Fprintf(os.Stderr, "# get %s: %v\n", insecure.Redacted(), err)
}
// HTTP failed, and we already tried HTTPS if applicable.
// Report the error from the HTTP attempt.
@@ -165,11 +173,11 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
// Note: accepting a non-200 OK here, so people can serve a
// meta import in their http 404 page.
if cfg.BuildX {
- fmt.Fprintf(os.Stderr, "# get %s: %v (%.3fs)\n", Redacted(fetched), res.Status, time.Since(start).Seconds())
+ fmt.Fprintf(os.Stderr, "# get %s: %v (%.3fs)\n", fetched.Redacted(), res.Status, time.Since(start).Seconds())
}
r := &Response{
- URL: Redacted(fetched),
+ URL: fetched.Redacted(),
Status: res.Status,
StatusCode: res.StatusCode,
Header: map[string][]string(res.Header),
@@ -201,7 +209,7 @@ func getFile(u *urlpkg.URL) (*Response, error) {
if os.IsNotExist(err) {
return &Response{
- URL: Redacted(u),
+ URL: u.Redacted(),
Status: http.StatusText(http.StatusNotFound),
StatusCode: http.StatusNotFound,
Body: http.NoBody,
@@ -211,7 +219,7 @@ func getFile(u *urlpkg.URL) (*Response, error) {
if os.IsPermission(err) {
return &Response{
- URL: Redacted(u),
+ URL: u.Redacted(),
Status: http.StatusText(http.StatusForbidden),
StatusCode: http.StatusForbidden,
Body: http.NoBody,
@@ -224,7 +232,7 @@ func getFile(u *urlpkg.URL) (*Response, error) {
}
return &Response{
- URL: Redacted(u),
+ URL: u.Redacted(),
Status: http.StatusText(http.StatusOK),
StatusCode: http.StatusOK,
Body: f,
diff --git a/libgo/go/cmd/go/internal/work/action.go b/libgo/go/cmd/go/internal/work/action.go
index db422fd..b872928 100644
--- a/libgo/go/cmd/go/internal/work/action.go
+++ b/libgo/go/cmd/go/internal/work/action.go
@@ -42,7 +42,7 @@ type Builder struct {
IsCmdList bool // running as part of go list; set p.Stale and additional fields below
NeedError bool // list needs p.Error
NeedExport bool // list needs p.Export
- NeedCompiledGoFiles bool // list needs p.CompiledGoFIles
+ NeedCompiledGoFiles bool // list needs p.CompiledGoFiles
objdirSeq int // counter for NewObjdir
pkgSeq int
diff --git a/libgo/go/cmd/go/internal/work/build.go b/libgo/go/cmd/go/internal/work/build.go
index e3b25c9..7146c9c 100644
--- a/libgo/go/cmd/go/internal/work/build.go
+++ b/libgo/go/cmd/go/internal/work/build.go
@@ -232,6 +232,7 @@ const (
DefaultBuildFlags BuildFlagMask = 0
OmitModFlag BuildFlagMask = 1 << iota
OmitModCommonFlags
+ OmitVFlag
)
// AddBuildFlags adds the flags common to the build, clean, get,
@@ -240,7 +241,9 @@ func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) {
cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
- cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
+ if mask&OmitVFlag == 0 {
+ cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
+ }
cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
cmd.Flag.Var(&load.BuildAsmflags, "asmflags", "")
diff --git a/libgo/go/cmd/go/internal/work/build_test.go b/libgo/go/cmd/go/internal/work/build_test.go
index b60f4e2..c33de26 100644
--- a/libgo/go/cmd/go/internal/work/build_test.go
+++ b/libgo/go/cmd/go/internal/work/build_test.go
@@ -222,7 +222,7 @@ func pkgImportPath(pkgpath string) *load.Package {
func TestRespectSetgidDir(t *testing.T) {
switch runtime.GOOS {
case "darwin":
- if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
+ if runtime.GOARCH == "arm64" {
t.Skip("can't set SetGID bit with chmod on iOS")
}
case "windows", "plan9":
diff --git a/libgo/go/cmd/go/internal/work/buildid.go b/libgo/go/cmd/go/internal/work/buildid.go
index 7558a30..6613b6f 100644
--- a/libgo/go/cmd/go/internal/work/buildid.go
+++ b/libgo/go/cmd/go/internal/work/buildid.go
@@ -185,7 +185,7 @@ func (b *Builder) toolID(name string) string {
cmdline := str.StringList(cfg.BuildToolexec, path, "-V=full")
cmd := exec.Command(cmdline[0], cmdline[1:]...)
- cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
+ cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
@@ -244,7 +244,7 @@ func (b *Builder) gccgoToolID(name, language string) (string, error) {
// compile an empty file on standard input.
cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-")
cmd := exec.Command(cmdline[0], cmdline[1:]...)
- cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
+ cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
// Force untranslated output so that we see the string "version".
cmd.Env = append(cmd.Env, "LC_ALL=C")
out, err := cmd.CombinedOutput()
diff --git a/libgo/go/cmd/go/internal/work/exec.go b/libgo/go/cmd/go/internal/work/exec.go
index 764291b..d610410 100644
--- a/libgo/go/cmd/go/internal/work/exec.go
+++ b/libgo/go/cmd/go/internal/work/exec.go
@@ -8,11 +8,6 @@ package work
import (
"bytes"
- "cmd/go/internal/base"
- "cmd/go/internal/cache"
- "cmd/go/internal/cfg"
- "cmd/go/internal/load"
- "cmd/go/internal/str"
"encoding/json"
"errors"
"fmt"
@@ -30,6 +25,12 @@ import (
"strings"
"sync"
"time"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cache"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
)
// actionList returns the list of actions in the dag rooted at root
@@ -490,6 +491,10 @@ func (b *Builder) build(a *Action) (err error) {
return nil
}
+ if err := allowInstall(a); err != nil {
+ return err
+ }
+
// make target directory
dir, _ := filepath.Split(a.Target)
if dir != "" {
@@ -1194,6 +1199,10 @@ func (b *Builder) link(a *Action) (err error) {
return err
}
+ if err := allowInstall(a); err != nil {
+ return err
+ }
+
// make target directory
dir, _ := filepath.Split(a.Target)
if dir != "" {
@@ -1368,6 +1377,10 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
}
func (b *Builder) installShlibname(a *Action) error {
+ if err := allowInstall(a); err != nil {
+ return err
+ }
+
// TODO: BuildN
a1 := a.Deps[0]
err := ioutil.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666)
@@ -1418,6 +1431,10 @@ func (b *Builder) linkShared(a *Action) (err error) {
}
defer b.flushOutput(a)
+ if err := allowInstall(a); err != nil {
+ return err
+ }
+
if err := b.Mkdir(a.Objdir); err != nil {
return err
}
@@ -1483,8 +1500,12 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) {
// advertise it by touching the mtimes (usually the libraries are up
// to date).
if !a.buggyInstall && !b.IsCmdList {
- now := time.Now()
- os.Chtimes(a.Target, now, now)
+ if cfg.BuildN {
+ b.Showcmd("", "touch %s", a.Target)
+ } else if err := allowInstall(a); err == nil {
+ now := time.Now()
+ os.Chtimes(a.Target, now, now)
+ }
}
return nil
}
@@ -1495,6 +1516,9 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) {
a.built = a1.built
return nil
}
+ if err := allowInstall(a); err != nil {
+ return err
+ }
if err := b.Mkdir(a.Objdir); err != nil {
return err
@@ -1524,6 +1548,13 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) {
return b.moveOrCopyFile(a.Target, a1.built, perm, false)
}
+// allowInstall returns a non-nil error if this invocation of the go command is
+// allowed to install a.Target.
+//
+// (The build of cmd/go running under its own test is forbidden from installing
+// to its original GOROOT.)
+var allowInstall = func(*Action) error { return nil }
+
// cleanup removes a's object dir to keep the amount of
// on-disk garbage down in a large build. On an operating system
// with aggressive buffering, cleaning incrementally like
@@ -1687,6 +1718,10 @@ func (b *Builder) installHeader(a *Action) error {
return nil
}
+ if err := allowInstall(a); err != nil {
+ return err
+ }
+
dir, _ := filepath.Split(a.Target)
if dir != "" {
if err := b.Mkdir(dir); err != nil {
@@ -1927,7 +1962,7 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interfa
cleanup := passLongArgsInResponseFiles(cmd)
defer cleanup()
cmd.Dir = dir
- cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
+ cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
cmd.Env = append(cmd.Env, env...)
start := time.Now()
err := cmd.Run()
@@ -2134,9 +2169,41 @@ func (b *Builder) gfortran(a *Action, p *load.Package, workdir, out string, flag
func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []string, file string, compiler []string) error {
file = mkAbs(p.Dir, file)
desc := p.ImportPath
- if !filepath.IsAbs(outfile) {
- outfile = filepath.Join(p.Dir, outfile)
+ outfile = mkAbs(p.Dir, outfile)
+
+ // Elide source directory paths if -trimpath or GOROOT_FINAL is set.
+ // This is needed for source files (e.g., a .c file in a package directory).
+ // TODO(golang.org/issue/36072): cgo also generates files with #line
+ // directives pointing to the source directory. It should not generate those
+ // when -trimpath is enabled.
+ if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
+ if cfg.BuildTrimpath {
+ // Keep in sync with Action.trimpath.
+ // The trimmed paths are a little different, but we need to trim in the
+ // same situations.
+ var from, toPath string
+ if m := p.Module; m != nil {
+ from = m.Dir
+ toPath = m.Path + "@" + m.Version
+ } else {
+ from = p.Dir
+ toPath = p.ImportPath
+ }
+ // -fdebug-prefix-map requires an absolute "to" path (or it joins the path
+ // with the working directory). Pick something that makes sense for the
+ // target platform.
+ var to string
+ if cfg.BuildContext.GOOS == "windows" {
+ to = filepath.Join(`\\_\_`, toPath)
+ } else {
+ to = filepath.Join("/_", toPath)
+ }
+ flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+from+"="+to)
+ } else if p.Goroot && cfg.GOROOT_FINAL != cfg.GOROOT {
+ flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+cfg.GOROOT+"="+cfg.GOROOT_FINAL)
+ }
}
+
output, err := b.runOut(a, filepath.Dir(file), b.cCompilerEnv(), compiler, flags, "-o", outfile, "-c", filepath.Base(file))
if len(output) > 0 {
// On FreeBSD 11, when we pass -g to clang 3.8 it
@@ -2375,13 +2442,25 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
if b.flagCache == nil {
b.flagCache = make(map[[2]string]bool)
}
+
+ tmp := os.DevNull
+ if runtime.GOOS == "windows" {
+ f, err := ioutil.TempFile(b.WorkDir, "")
+ if err != nil {
+ return false
+ }
+ f.Close()
+ tmp = f.Name()
+ defer os.Remove(tmp)
+ }
+
// We used to write an empty C file, but that gets complicated with
// go build -n. We tried using a file that does not exist, but that
// fails on systems with GCC version 4.2.1; that is the last GPLv2
// version of GCC, so some systems have frozen on it.
// Now we pass an empty file on stdin, which should work at least for
// GCC and clang.
- cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", os.DevNull)
+ cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", tmp)
if cfg.BuildN || cfg.BuildX {
b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
if cfg.BuildN {
@@ -2390,7 +2469,7 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
}
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
cmd.Dir = b.WorkDir
- cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
+ cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
cmd.Env = append(cmd.Env, "LC_ALL=C")
out, _ := cmd.CombinedOutput()
// GCC says "unrecognized command line option".
@@ -2946,13 +3025,13 @@ func mkAbsFiles(dir string, files []string) []string {
return abs
}
-// passLongArgsInResponseFiles modifies cmd on Windows such that, for
+// passLongArgsInResponseFiles modifies cmd such that, for
// certain programs, long arguments are passed in "response files", a
// file on disk with the arguments, with one arg per line. An actual
// argument starting with '@' means that the rest of the argument is
// a filename of arguments to expand.
//
-// See Issue 18468.
+// See issues 18468 (Windows) and 37768 (Darwin).
func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) {
cleanup = func() {} // no cleanup by default
@@ -2990,11 +3069,6 @@ func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) {
}
func useResponseFile(path string, argLen int) bool {
- // Unless we're on Windows, don't use response files.
- if runtime.GOOS != "windows" {
- return false
- }
-
// Unless the program uses objabi.Flagparse, which understands
// response files, don't use response files.
// TODO: do we need more commands? asm? cgo? For now, no.
@@ -3007,6 +3081,8 @@ func useResponseFile(path string, argLen int) bool {
// Windows has a limit of 32 KB arguments. To be conservative and not
// worry about whether that includes spaces or not, just use 30 KB.
+ // Darwin's limit is less clear. The OS claims 256KB, but we've seen
+ // failures with arglen as small as 50KB.
if argLen > (30 << 10) {
return true
}
diff --git a/libgo/go/cmd/go/internal/work/gc.go b/libgo/go/cmd/go/internal/work/gc.go
index 7d17c0c..f1d08e0 100644
--- a/libgo/go/cmd/go/internal/work/gc.go
+++ b/libgo/go/cmd/go/internal/work/gc.go
@@ -37,6 +37,17 @@ func (gcToolchain) linker() string {
return base.Tool("link")
}
+func pkgPath(a *Action) string {
+ p := a.Package
+ ppath := p.ImportPath
+ if cfg.BuildBuildmode == "plugin" {
+ ppath = pluginPath(a)
+ } else if p.Name == "main" && !p.Internal.ForceLibrary {
+ ppath = "main"
+ }
+ return ppath
+}
+
func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
p := a.Package
objdir := a.Objdir
@@ -47,12 +58,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, s
ofile = objdir + out
}
- pkgpath := p.ImportPath
- if cfg.BuildBuildmode == "plugin" {
- pkgpath = pluginPath(a)
- } else if p.Name == "main" && !p.Internal.ForceLibrary {
- pkgpath = "main"
- }
+ pkgpath := pkgPath(a)
gcargs := []string{"-p", pkgpath}
if p.Module != nil && p.Module.GoVersion != "" && allowedVersion(p.Module.GoVersion) {
gcargs = append(gcargs, "-lang=go"+p.Module.GoVersion)
@@ -162,7 +168,7 @@ func gcBackendConcurrency(gcflags []string) int {
CheckFlags:
for _, flag := range gcflags {
// Concurrent compilation is presumed incompatible with any gcflags,
- // except for a small whitelist of commonly used flags.
+ // except for known commonly used flags.
// If the user knows better, they can manually add their own -c to the gcflags.
switch flag {
case "-N", "-l", "-S", "-B", "-C", "-I":
@@ -217,6 +223,10 @@ CheckFlags:
// trimpath returns the -trimpath argument to use
// when compiling the action.
func (a *Action) trimpath() string {
+ // Keep in sync with Builder.ccompile
+ // The trimmed paths are a little different, but we need to trim in the
+ // same situations.
+
// Strip the object directory entirely.
objdir := a.Objdir
if len(objdir) > 1 && objdir[len(objdir)-1] == filepath.Separator {
@@ -240,7 +250,8 @@ func (a *Action) trimpath() string {
func asmArgs(a *Action, p *load.Package) []interface{} {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(cfg.GOROOT, "pkg", "include")
- args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", a.trimpath(), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags}
+ pkgpath := pkgPath(a)
+ args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-p", pkgpath, "-trimpath", a.trimpath(), "-I", a.Objdir, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, forcedAsmflags, p.Internal.Asmflags}
if p.ImportPath == "runtime" && cfg.Goarch == "386" {
for _, arg := range forcedAsmflags {
if arg == "-dynlink" {
diff --git a/libgo/go/cmd/go/internal/work/init.go b/libgo/go/cmd/go/internal/work/init.go
index 9091f98..dad3b10 100644
--- a/libgo/go/cmd/go/internal/work/init.go
+++ b/libgo/go/cmd/go/internal/work/init.go
@@ -10,11 +10,13 @@ import (
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/load"
+ "cmd/internal/objabi"
"cmd/internal/sys"
"flag"
"fmt"
"os"
"path/filepath"
+ "runtime"
"strings"
)
@@ -34,6 +36,20 @@ func BuildInit() {
}
cfg.BuildPkgdir = p
}
+
+ // For each experiment that has been enabled in the toolchain, define a
+ // build tag with the same name but prefixed by "goexperiment." which can be
+ // used for compiling alternative files for the experiment. This allows
+ // changes for the experiment, like extra struct fields in the runtime,
+ // without affecting the base non-experiment code at all. [2:] strips the
+ // leading "X:" from objabi.Expstring().
+ exp := objabi.Expstring()[2:]
+ if exp != "none" {
+ experiments := strings.Split(exp, ",")
+ for _, expt := range experiments {
+ cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "goexperiment."+expt)
+ }
+ }
}
func instrumentInit() {
@@ -69,7 +85,12 @@ func instrumentInit() {
modeFlag := "-" + mode
if !cfg.BuildContext.CgoEnabled {
- fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag)
+ if runtime.GOOS != cfg.Goos || runtime.GOARCH != cfg.Goarch {
+ fmt.Fprintf(os.Stderr, "go %s: %s requires cgo\n", flag.Args()[0], modeFlag)
+ } else {
+ fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag)
+ }
+
base.SetExitStatus(2)
base.Exit()
}
@@ -102,7 +123,7 @@ func buildModeInit() {
switch cfg.Goos {
case "darwin":
switch cfg.Goarch {
- case "arm", "arm64":
+ case "arm64":
codegenArg = "-shared"
}
@@ -134,9 +155,11 @@ func buildModeInit() {
case "android":
codegenArg = "-shared"
ldBuildmode = "pie"
+ case "windows":
+ ldBuildmode = "pie"
case "darwin":
switch cfg.Goarch {
- case "arm", "arm64":
+ case "arm64":
codegenArg = "-shared"
}
fallthrough
@@ -161,8 +184,12 @@ func buildModeInit() {
}
if gccgo {
codegenArg = "-fPIE"
- } else if cfg.Goos != "aix" {
- codegenArg = "-shared"
+ } else {
+ switch cfg.Goos {
+ case "aix", "windows":
+ default:
+ codegenArg = "-shared"
+ }
}
ldBuildmode = "pie"
case "shared":
diff --git a/libgo/go/cmd/go/internal/work/security.go b/libgo/go/cmd/go/internal/work/security.go
index 0ce1664..3ee68ac 100644
--- a/libgo/go/cmd/go/internal/work/security.go
+++ b/libgo/go/cmd/go/internal/work/security.go
@@ -184,7 +184,9 @@ var validLinkerFlags = []*lazyregexp.Regexp{
re(`-Wl,--enable-new-dtags`),
re(`-Wl,--end-group`),
re(`-Wl,--(no-)?export-dynamic`),
+ re(`-Wl,-E`),
re(`-Wl,-framework,[^,@\-][^,]+`),
+ re(`-Wl,--hash-style=(sysv|gnu|both)`),
re(`-Wl,-headerpad_max_install_names`),
re(`-Wl,--no-undefined`),
re(`-Wl,-R([^@\-][^,@]*$)`),
@@ -200,6 +202,7 @@ var validLinkerFlags = []*lazyregexp.Regexp{
re(`-Wl,-undefined[=,]([^,@\-][^,]+)`),
re(`-Wl,-?-unresolved-symbols=[^,]+`),
re(`-Wl,--(no-)?warn-([^,]+)`),
+ re(`-Wl,-?-wrap[=,][^,@\-][^,]*`),
re(`-Wl,-z,(no)?execstack`),
re(`-Wl,-z,relro`),
diff --git a/libgo/go/cmd/go/internal/work/security_test.go b/libgo/go/cmd/go/internal/work/security_test.go
index 6b85c40b..11e74f2 100644
--- a/libgo/go/cmd/go/internal/work/security_test.go
+++ b/libgo/go/cmd/go/internal/work/security_test.go
@@ -131,6 +131,7 @@ var goodLinkerFlags = [][]string{
{"-mtune=happybirthday"},
{"-pic"},
{"-pthread"},
+ {"-Wl,--hash-style=both"},
{"-Wl,-rpath,foo"},
{"-Wl,-rpath,$ORIGIN/foo"},
{"-Wl,-R", "/foo"},
@@ -208,6 +209,7 @@ var badLinkerFlags = [][]string{
{"-Wl,-framework", "-Wl,@Home"},
{"-Wl,-framework", "@Home"},
{"-Wl,-framework,Chocolate,@Home"},
+ {"-Wl,--hash-style=foo"},
{"-x", "--c"},
{"-x", "@obj"},
{"-Wl,-rpath,@foo"},
diff --git a/libgo/go/cmd/go/internal/work/testgo.go b/libgo/go/cmd/go/internal/work/testgo.go
index 3e623c6..931f49a 100644
--- a/libgo/go/cmd/go/internal/work/testgo.go
+++ b/libgo/go/cmd/go/internal/work/testgo.go
@@ -8,10 +8,41 @@
package work
-import "os"
+import (
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/search"
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+)
func init() {
if v := os.Getenv("TESTGO_VERSION"); v != "" {
runtimeVersion = v
}
+
+ if testGOROOT := os.Getenv("TESTGO_GOROOT"); testGOROOT != "" {
+ // Disallow installs to the GOROOT from which testgo was built.
+ // Installs to other GOROOTs — such as one set explicitly within a test — are ok.
+ allowInstall = func(a *Action) error {
+ if cfg.BuildN {
+ return nil
+ }
+
+ rel := search.InDir(a.Target, testGOROOT)
+ if rel == "" {
+ return nil
+ }
+
+ callerPos := ""
+ if _, file, line, ok := runtime.Caller(1); ok {
+ if shortFile := search.InDir(file, filepath.Join(testGOROOT, "src")); shortFile != "" {
+ file = shortFile
+ }
+ callerPos = fmt.Sprintf("%s:%d: ", file, line)
+ }
+ return fmt.Errorf("%stestgo must not write to GOROOT (installing to %s)", callerPos, filepath.Join("GOROOT", rel))
+ }
+ }
}
diff --git a/libgo/go/cmd/go/main.go b/libgo/go/cmd/go/main.go
index bb442b5..11913d6 100644
--- a/libgo/go/cmd/go/main.go
+++ b/libgo/go/cmd/go/main.go
@@ -59,6 +59,7 @@ func init() {
version.CmdVersion,
vet.CmdVet,
+ help.HelpBuildConstraint,
help.HelpBuildmode,
help.HelpC,
help.HelpCache,
@@ -185,7 +186,7 @@ BigCmdLoop:
if cmd.CustomFlags {
args = args[1:]
} else {
- base.SetFromGOFLAGS(cmd.Flag)
+ base.SetFromGOFLAGS(&cmd.Flag)
cmd.Flag.Parse(args[1:])
args = cmd.Flag.Args()
}
diff --git a/libgo/go/cmd/go/note_test.go b/libgo/go/cmd/go/note_test.go
index e94e82b..b2d3179 100644
--- a/libgo/go/cmd/go/note_test.go
+++ b/libgo/go/cmd/go/note_test.go
@@ -20,6 +20,8 @@ func TestNoteReading(t *testing.T) {
// both in internal and external linking mode.
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
+
tg.tempFile("hello.go", `package main; func main() { print("hello, world\n") }`)
const buildID = "TestNoteReading-Build-ID"
tg.run("build", "-ldflags", "-buildid="+buildID, "-o", tg.path("hello.exe"), tg.path("hello.go"))
@@ -53,7 +55,7 @@ func TestNoteReading(t *testing.T) {
// we've had trouble reading the notes generated by gold.
err := tg.doRun([]string{"build", "-ldflags", "-buildid=" + buildID + " -linkmode=external -extldflags=-fuse-ld=gold", "-o", tg.path("hello3.exe"), tg.path("hello.go")})
if err != nil {
- if tg.grepCountBoth("(invalid linker|gold|cannot find 'ld')") > 0 {
+ if tg.grepCountBoth("(invalid linker|gold|cannot find [‘']ld[’'])") > 0 {
// It's not an error if gold isn't there. gcc claims it "cannot find 'ld'" if
// ld.gold is missing, see issue #22340.
t.Log("skipping gold test")
diff --git a/libgo/go/cmd/go/proxy_test.go b/libgo/go/cmd/go/proxy_test.go
index 8214488..2a4d293 100644
--- a/libgo/go/cmd/go/proxy_test.go
+++ b/libgo/go/cmd/go/proxy_test.go
@@ -174,6 +174,25 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
return
}
+ // Request for $GOPROXY/redirect/<count>/... goes to redirects.
+ if strings.HasPrefix(path, "redirect/") {
+ path = path[len("redirect/"):]
+ if j := strings.Index(path, "/"); j >= 0 {
+ count, err := strconv.Atoi(path[:j])
+ if err != nil {
+ return
+ }
+
+ // The last redirect.
+ if count <= 1 {
+ http.Redirect(w, r, fmt.Sprintf("/mod/%s", path[j+1:]), 302)
+ return
+ }
+ http.Redirect(w, r, fmt.Sprintf("/mod/redirect/%d/%s", count-1, path[j+1:]), 302)
+ return
+ }
+ }
+
// Request for $GOPROXY/sumdb/<name>/supported
// is checking whether it's OK to access sumdb via the proxy.
if path == "sumdb/"+testSumDBName+"/supported" {
diff --git a/libgo/go/cmd/go/script_test.go b/libgo/go/cmd/go/script_test.go
index ec498bb..2e8f18a 100644
--- a/libgo/go/cmd/go/script_test.go
+++ b/libgo/go/cmd/go/script_test.go
@@ -10,6 +10,7 @@ package main_test
import (
"bytes"
"context"
+ "errors"
"fmt"
"go/build"
"internal/testenv"
@@ -30,6 +31,7 @@ import (
"cmd/go/internal/robustio"
"cmd/go/internal/txtar"
"cmd/go/internal/work"
+ "cmd/internal/objabi"
"cmd/internal/sys"
)
@@ -76,15 +78,26 @@ type testScript struct {
stderr string // standard error from last 'go' command; for 'stderr' command
stopped bool // test wants to stop early
start time.Time // time phase started
- background []backgroundCmd // backgrounded 'exec' and 'go' commands
+ background []*backgroundCmd // backgrounded 'exec' and 'go' commands
}
type backgroundCmd struct {
- cmd *exec.Cmd
- wait <-chan struct{}
- neg bool // if true, cmd should fail
+ want simpleStatus
+ args []string
+ cancel context.CancelFunc
+ done <-chan struct{}
+ err error
+ stdout, stderr strings.Builder
}
+type simpleStatus string
+
+const (
+ success simpleStatus = ""
+ failure simpleStatus = "!"
+ successOrFailure simpleStatus = "?"
+)
+
var extraEnvKeys = []string{
"SYSTEMROOT", // must be preserved on Windows to find DLLs; golang.org/issue/25210
"WINDIR", // must be preserved on Windows to be able to run PowerShell command; golang.org/issue/30711
@@ -109,12 +122,16 @@ func (ts *testScript) setup() {
"CCACHE_DISABLE=1", // ccache breaks with non-existent HOME
"GOARCH=" + runtime.GOARCH,
"GOCACHE=" + testGOCACHE,
+ "GODEBUG=" + os.Getenv("GODEBUG"),
"GOEXE=" + cfg.ExeSuffix,
+ "GOEXPSTRING=" + objabi.Expstring()[2:],
"GOOS=" + runtime.GOOS,
"GOPATH=" + filepath.Join(ts.workdir, "gopath"),
"GOPROXY=" + proxyURL,
"GOPRIVATE=",
"GOROOT=" + testGOROOT,
+ "GOROOT_FINAL=" + os.Getenv("GOROOT_FINAL"), // causes spurious rebuilds and breaks the "stale" built-in if not propagated
+ "TESTGO_GOROOT=" + testGOROOT,
"GOSUMDB=" + testSumDBVerifierKey,
"GONOPROXY=",
"GONOSUMDB=",
@@ -181,10 +198,10 @@ func (ts *testScript) run() {
// before we print PASS. If we return early (e.g., due to a test failure),
// don't print anything about the processes that were still running.
for _, bg := range ts.background {
- interruptProcess(bg.cmd.Process)
+ bg.cancel()
}
for _, bg := range ts.background {
- <-bg.wait
+ <-bg.done
}
ts.background = nil
@@ -205,7 +222,7 @@ func (ts *testScript) run() {
// With -v or -testwork, start log with full environment.
if *testWork || testing.Verbose() {
// Display environment.
- ts.cmdEnv(false, nil)
+ ts.cmdEnv(success, nil)
fmt.Fprintf(&ts.log, "\n")
ts.mark = ts.log.Len()
}
@@ -245,7 +262,7 @@ Script:
// Parse input line. Ignore blanks entirely.
parsed := ts.parse(line)
if parsed.name == "" {
- if parsed.neg || len(parsed.conds) > 0 {
+ if parsed.want != "" || len(parsed.conds) > 0 {
ts.fatalf("missing command")
}
continue
@@ -324,7 +341,7 @@ Script:
if cmd == nil {
ts.fatalf("unknown command %q", parsed.name)
}
- cmd(ts, parsed.neg, parsed.args)
+ cmd(ts, parsed.want, parsed.args)
// Command can ask script to stop early.
if ts.stopped {
@@ -335,9 +352,9 @@ Script:
}
for _, bg := range ts.background {
- interruptProcess(bg.cmd.Process)
+ bg.cancel()
}
- ts.cmdWait(false, nil)
+ ts.cmdWait(success, nil)
// Final phase ended.
rewind()
@@ -352,7 +369,7 @@ Script:
//
// NOTE: If you make changes here, update testdata/script/README too!
//
-var scriptCmds = map[string]func(*testScript, bool, []string){
+var scriptCmds = map[string]func(*testScript, simpleStatus, []string){
"addcrlf": (*testScript).cmdAddcrlf,
"cc": (*testScript).cmdCc,
"cd": (*testScript).cmdCd,
@@ -385,7 +402,7 @@ var regexpCmd = map[string]bool{
}
// addcrlf adds CRLF line endings to the named files.
-func (ts *testScript) cmdAddcrlf(neg bool, args []string) {
+func (ts *testScript) cmdAddcrlf(want simpleStatus, args []string) {
if len(args) == 0 {
ts.fatalf("usage: addcrlf file...")
}
@@ -399,21 +416,21 @@ func (ts *testScript) cmdAddcrlf(neg bool, args []string) {
}
// cc runs the C compiler along with platform specific options.
-func (ts *testScript) cmdCc(neg bool, args []string) {
+func (ts *testScript) cmdCc(want simpleStatus, args []string) {
if len(args) < 1 || (len(args) == 1 && args[0] == "&") {
ts.fatalf("usage: cc args... [&]")
}
var b work.Builder
b.Init()
- ts.cmdExec(neg, append(b.GccCmd(".", ""), args...))
+ ts.cmdExec(want, append(b.GccCmd(".", ""), args...))
robustio.RemoveAll(b.WorkDir)
}
// cd changes to a different directory.
-func (ts *testScript) cmdCd(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! cd")
+func (ts *testScript) cmdCd(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v cd", want)
}
if len(args) != 1 {
ts.fatalf("usage: cd dir")
@@ -437,9 +454,9 @@ func (ts *testScript) cmdCd(neg bool, args []string) {
}
// chmod changes permissions for a file or directory.
-func (ts *testScript) cmdChmod(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! chmod")
+func (ts *testScript) cmdChmod(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v chmod", want)
}
if len(args) < 2 {
ts.fatalf("usage: chmod perm paths...")
@@ -459,10 +476,10 @@ func (ts *testScript) cmdChmod(neg bool, args []string) {
}
// cmp compares two files.
-func (ts *testScript) cmdCmp(neg bool, args []string) {
- if neg {
+func (ts *testScript) cmdCmp(want simpleStatus, args []string) {
+ if want != success {
// It would be strange to say "this file can have any content except this precise byte sequence".
- ts.fatalf("unsupported: ! cmp")
+ ts.fatalf("unsupported: %v cmp", want)
}
quiet := false
if len(args) > 0 && args[0] == "-q" {
@@ -476,9 +493,9 @@ func (ts *testScript) cmdCmp(neg bool, args []string) {
}
// cmpenv compares two files with environment variable substitution.
-func (ts *testScript) cmdCmpenv(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! cmpenv")
+func (ts *testScript) cmdCmpenv(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v cmpenv", want)
}
quiet := false
if len(args) > 0 && args[0] == "-q" {
@@ -524,7 +541,7 @@ func (ts *testScript) doCmdCmp(args []string, env, quiet bool) {
}
// cp copies files, maybe eventually directories.
-func (ts *testScript) cmdCp(neg bool, args []string) {
+func (ts *testScript) cmdCp(want simpleStatus, args []string) {
if len(args) < 2 {
ts.fatalf("usage: cp src... dst")
}
@@ -564,20 +581,21 @@ func (ts *testScript) cmdCp(neg bool, args []string) {
targ = filepath.Join(dst, filepath.Base(src))
}
err := ioutil.WriteFile(targ, data, mode)
- if neg {
+ switch want {
+ case failure:
if err == nil {
ts.fatalf("unexpected command success")
}
- } else {
+ case success:
ts.check(err)
}
}
}
// env displays or adds to the environment.
-func (ts *testScript) cmdEnv(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! env")
+func (ts *testScript) cmdEnv(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v env", want)
}
conv := func(s string) string { return s }
@@ -615,86 +633,96 @@ func (ts *testScript) cmdEnv(neg bool, args []string) {
}
// exec runs the given command.
-func (ts *testScript) cmdExec(neg bool, args []string) {
+func (ts *testScript) cmdExec(want simpleStatus, args []string) {
if len(args) < 1 || (len(args) == 1 && args[0] == "&") {
ts.fatalf("usage: exec program [args...] [&]")
}
- var err error
+ background := false
if len(args) > 0 && args[len(args)-1] == "&" {
- var cmd *exec.Cmd
- cmd, err = ts.execBackground(args[0], args[1:len(args)-1]...)
- if err == nil {
- wait := make(chan struct{})
- go func() {
- ctxWait(testCtx, cmd)
- close(wait)
- }()
- ts.background = append(ts.background, backgroundCmd{cmd, wait, neg})
- }
- ts.stdout, ts.stderr = "", ""
- } else {
- ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...)
- if ts.stdout != "" {
- fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
- }
- if ts.stderr != "" {
- fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
- }
- if err == nil && neg {
- ts.fatalf("unexpected command success")
- }
+ background = true
+ args = args[:len(args)-1]
}
+ bg, err := ts.startBackground(want, args[0], args[1:]...)
if err != nil {
- fmt.Fprintf(&ts.log, "[%v]\n", err)
- if testCtx.Err() != nil {
- ts.fatalf("test timed out while running command")
- } else if !neg {
- ts.fatalf("unexpected command failure")
- }
+ ts.fatalf("unexpected error starting command: %v", err)
+ }
+ if background {
+ ts.stdout, ts.stderr = "", ""
+ ts.background = append(ts.background, bg)
+ return
+ }
+
+ <-bg.done
+ ts.stdout = bg.stdout.String()
+ ts.stderr = bg.stderr.String()
+ if ts.stdout != "" {
+ fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout)
}
+ if ts.stderr != "" {
+ fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr)
+ }
+ if bg.err != nil {
+ fmt.Fprintf(&ts.log, "[%v]\n", bg.err)
+ }
+ ts.checkCmd(bg)
}
// exists checks that the list of files exists.
-func (ts *testScript) cmdExists(neg bool, args []string) {
- var readonly bool
- if len(args) > 0 && args[0] == "-readonly" {
- readonly = true
- args = args[1:]
+func (ts *testScript) cmdExists(want simpleStatus, args []string) {
+ if want == successOrFailure {
+ ts.fatalf("unsupported: %v exists", want)
+ }
+ var readonly, exec bool
+loop:
+ for len(args) > 0 {
+ switch args[0] {
+ case "-readonly":
+ readonly = true
+ args = args[1:]
+ case "-exec":
+ exec = true
+ args = args[1:]
+ default:
+ break loop
+ }
}
if len(args) == 0 {
- ts.fatalf("usage: exists [-readonly] file...")
+ ts.fatalf("usage: exists [-readonly] [-exec] file...")
}
for _, file := range args {
file = ts.mkabs(file)
info, err := os.Stat(file)
- if err == nil && neg {
+ if err == nil && want == failure {
what := "file"
if info.IsDir() {
what = "directory"
}
ts.fatalf("%s %s unexpectedly exists", what, file)
}
- if err != nil && !neg {
+ if err != nil && want == success {
ts.fatalf("%s does not exist", file)
}
- if err == nil && !neg && readonly && info.Mode()&0222 != 0 {
+ if err == nil && want == success && readonly && info.Mode()&0222 != 0 {
ts.fatalf("%s exists but is writable", file)
}
+ if err == nil && want == success && exec && runtime.GOOS != "windows" && info.Mode()&0111 == 0 {
+ ts.fatalf("%s exists but is not executable", file)
+ }
}
}
// go runs the go command.
-func (ts *testScript) cmdGo(neg bool, args []string) {
- ts.cmdExec(neg, append([]string{testGo}, args...))
+func (ts *testScript) cmdGo(want simpleStatus, args []string) {
+ ts.cmdExec(want, append([]string{testGo}, args...))
}
// mkdir creates directories.
-func (ts *testScript) cmdMkdir(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! mkdir")
+func (ts *testScript) cmdMkdir(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v mkdir", want)
}
if len(args) < 1 {
ts.fatalf("usage: mkdir dir...")
@@ -705,9 +733,9 @@ func (ts *testScript) cmdMkdir(neg bool, args []string) {
}
// rm removes files or directories.
-func (ts *testScript) cmdRm(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! rm")
+func (ts *testScript) cmdRm(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v rm", want)
}
if len(args) < 1 {
ts.fatalf("usage: rm file...")
@@ -720,20 +748,20 @@ func (ts *testScript) cmdRm(neg bool, args []string) {
}
// skip marks the test skipped.
-func (ts *testScript) cmdSkip(neg bool, args []string) {
+func (ts *testScript) cmdSkip(want simpleStatus, args []string) {
if len(args) > 1 {
ts.fatalf("usage: skip [msg]")
}
- if neg {
- ts.fatalf("unsupported: ! skip")
+ if want != success {
+ ts.fatalf("unsupported: %v skip", want)
}
// Before we mark the test as skipped, shut down any background processes and
// make sure they have returned the correct status.
for _, bg := range ts.background {
- interruptProcess(bg.cmd.Process)
+ bg.cancel()
}
- ts.cmdWait(false, nil)
+ ts.cmdWait(success, nil)
if len(args) == 1 {
ts.t.Skip(args[0])
@@ -742,15 +770,18 @@ func (ts *testScript) cmdSkip(neg bool, args []string) {
}
// stale checks that the named build targets are stale.
-func (ts *testScript) cmdStale(neg bool, args []string) {
+func (ts *testScript) cmdStale(want simpleStatus, args []string) {
if len(args) == 0 {
ts.fatalf("usage: stale target...")
}
- tmpl := "{{if .Error}}{{.ImportPath}}: {{.Error.Err}}{else}}"
- if neg {
+ tmpl := "{{if .Error}}{{.ImportPath}}: {{.Error.Err}}{{else}}"
+ switch want {
+ case failure:
tmpl += "{{if .Stale}}{{.ImportPath}} is unexpectedly stale{{end}}"
- } else {
+ case success:
tmpl += "{{if not .Stale}}{{.ImportPath}} is unexpectedly NOT stale{{end}}"
+ default:
+ ts.fatalf("unsupported: %v stale", want)
}
tmpl += "{{end}}"
goArgs := append([]string{"list", "-e", "-f=" + tmpl}, args...)
@@ -764,26 +795,30 @@ func (ts *testScript) cmdStale(neg bool, args []string) {
}
// stdout checks that the last go command standard output matches a regexp.
-func (ts *testScript) cmdStdout(neg bool, args []string) {
- scriptMatch(ts, neg, args, ts.stdout, "stdout")
+func (ts *testScript) cmdStdout(want simpleStatus, args []string) {
+ scriptMatch(ts, want, args, ts.stdout, "stdout")
}
// stderr checks that the last go command standard output matches a regexp.
-func (ts *testScript) cmdStderr(neg bool, args []string) {
- scriptMatch(ts, neg, args, ts.stderr, "stderr")
+func (ts *testScript) cmdStderr(want simpleStatus, args []string) {
+ scriptMatch(ts, want, args, ts.stderr, "stderr")
}
// grep checks that file content matches a regexp.
// Like stdout/stderr and unlike Unix grep, it accepts Go regexp syntax.
-func (ts *testScript) cmdGrep(neg bool, args []string) {
- scriptMatch(ts, neg, args, "", "grep")
+func (ts *testScript) cmdGrep(want simpleStatus, args []string) {
+ scriptMatch(ts, want, args, "", "grep")
}
// scriptMatch implements both stdout and stderr.
-func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
+func scriptMatch(ts *testScript, want simpleStatus, args []string, text, name string) {
+ if want == successOrFailure {
+ ts.fatalf("unsupported: %v %s", want, name)
+ }
+
n := 0
if len(args) >= 1 && strings.HasPrefix(args[0], "-count=") {
- if neg {
+ if want == failure {
ts.fatalf("cannot use -count= with negated match")
}
var err error
@@ -803,12 +838,12 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
}
extraUsage := ""
- want := 1
+ wantArgs := 1
if name == "grep" {
extraUsage = " file"
- want = 2
+ wantArgs = 2
}
- if len(args) != want {
+ if len(args) != wantArgs {
ts.fatalf("usage: %s [-count=N] 'pattern'%s", name, extraUsage)
}
@@ -829,14 +864,16 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
// Matching against workdir would be misleading.
text = strings.ReplaceAll(text, ts.workdir, "$WORK")
- if neg {
+ switch want {
+ case failure:
if re.MatchString(text) {
if isGrep && !quiet {
fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text)
}
ts.fatalf("unexpected match for %#q found in %s: %s", pattern, name, re.FindString(text))
}
- } else {
+
+ case success:
if !re.MatchString(text) {
if isGrep && !quiet {
fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text)
@@ -856,9 +893,9 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
}
// stop stops execution of the test (marking it passed).
-func (ts *testScript) cmdStop(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! stop")
+func (ts *testScript) cmdStop(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v stop", want)
}
if len(args) > 1 {
ts.fatalf("usage: stop [msg]")
@@ -872,9 +909,9 @@ func (ts *testScript) cmdStop(neg bool, args []string) {
}
// symlink creates a symbolic link.
-func (ts *testScript) cmdSymlink(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! symlink")
+func (ts *testScript) cmdSymlink(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v symlink", want)
}
if len(args) != 3 || args[1] != "->" {
ts.fatalf("usage: symlink file -> target")
@@ -885,9 +922,9 @@ func (ts *testScript) cmdSymlink(neg bool, args []string) {
}
// wait waits for background commands to exit, setting stderr and stdout to their result.
-func (ts *testScript) cmdWait(neg bool, args []string) {
- if neg {
- ts.fatalf("unsupported: ! wait")
+func (ts *testScript) cmdWait(want simpleStatus, args []string) {
+ if want != success {
+ ts.fatalf("unsupported: %v wait", want)
}
if len(args) > 0 {
ts.fatalf("usage: wait")
@@ -895,34 +932,24 @@ func (ts *testScript) cmdWait(neg bool, args []string) {
var stdouts, stderrs []string
for _, bg := range ts.background {
- <-bg.wait
+ <-bg.done
- args := append([]string{filepath.Base(bg.cmd.Args[0])}, bg.cmd.Args[1:]...)
- fmt.Fprintf(&ts.log, "[background] %s: %v\n", strings.Join(args, " "), bg.cmd.ProcessState)
+ args := append([]string{filepath.Base(bg.args[0])}, bg.args[1:]...)
+ fmt.Fprintf(&ts.log, "[background] %s: %v\n", strings.Join(args, " "), bg.err)
- cmdStdout := bg.cmd.Stdout.(*strings.Builder).String()
+ cmdStdout := bg.stdout.String()
if cmdStdout != "" {
fmt.Fprintf(&ts.log, "[stdout]\n%s", cmdStdout)
stdouts = append(stdouts, cmdStdout)
}
- cmdStderr := bg.cmd.Stderr.(*strings.Builder).String()
+ cmdStderr := bg.stderr.String()
if cmdStderr != "" {
fmt.Fprintf(&ts.log, "[stderr]\n%s", cmdStderr)
stderrs = append(stderrs, cmdStderr)
}
- if bg.cmd.ProcessState.Success() {
- if bg.neg {
- ts.fatalf("unexpected command success")
- }
- } else {
- if testCtx.Err() != nil {
- ts.fatalf("test timed out while running command")
- } else if !bg.neg {
- ts.fatalf("unexpected command failure")
- }
- }
+ ts.checkCmd(bg)
}
ts.stdout = strings.Join(stdouts, "")
@@ -950,58 +977,176 @@ func (ts *testScript) check(err error) {
}
}
+func (ts *testScript) checkCmd(bg *backgroundCmd) {
+ select {
+ case <-bg.done:
+ default:
+ panic("checkCmd called when not done")
+ }
+
+ if bg.err == nil {
+ if bg.want == failure {
+ ts.fatalf("unexpected command success")
+ }
+ return
+ }
+
+ if errors.Is(bg.err, context.DeadlineExceeded) {
+ ts.fatalf("test timed out while running command")
+ }
+
+ if errors.Is(bg.err, context.Canceled) {
+ // The process was still running at the end of the test.
+ // The test must not depend on its exit status.
+ if bg.want != successOrFailure {
+ ts.fatalf("unexpected background command remaining at test end")
+ }
+ return
+ }
+
+ if bg.want == success {
+ ts.fatalf("unexpected command failure")
+ }
+}
+
// exec runs the given command line (an actual subprocess, not simulated)
// in ts.cd with environment ts.env and then returns collected standard output and standard error.
func (ts *testScript) exec(command string, args ...string) (stdout, stderr string, err error) {
- cmd := exec.Command(command, args...)
- cmd.Dir = ts.cd
- cmd.Env = append(ts.env, "PWD="+ts.cd)
- var stdoutBuf, stderrBuf strings.Builder
- cmd.Stdout = &stdoutBuf
- cmd.Stderr = &stderrBuf
- if err = cmd.Start(); err == nil {
- err = ctxWait(testCtx, cmd)
+ bg, err := ts.startBackground(success, command, args...)
+ if err != nil {
+ return "", "", err
}
- return stdoutBuf.String(), stderrBuf.String(), err
+ <-bg.done
+ return bg.stdout.String(), bg.stderr.String(), bg.err
}
-// execBackground starts the given command line (an actual subprocess, not simulated)
+// startBackground starts the given command line (an actual subprocess, not simulated)
// in ts.cd with environment ts.env.
-func (ts *testScript) execBackground(command string, args ...string) (*exec.Cmd, error) {
+func (ts *testScript) startBackground(want simpleStatus, command string, args ...string) (*backgroundCmd, error) {
+ done := make(chan struct{})
+ bg := &backgroundCmd{
+ want: want,
+ args: append([]string{command}, args...),
+ done: done,
+ cancel: func() {},
+ }
+
+ ctx := context.Background()
+ gracePeriod := 100 * time.Millisecond
+ if deadline, ok := ts.t.Deadline(); ok {
+ timeout := time.Until(deadline)
+ // If time allows, increase the termination grace period to 5% of the
+ // remaining time.
+ if gp := timeout / 20; gp > gracePeriod {
+ gracePeriod = gp
+ }
+
+ // Send the first termination signal with two grace periods remaining.
+ // If it still hasn't finished after the first period has elapsed,
+ // we'll escalate to os.Kill with a second period remaining until the
+ // test deadline..
+ timeout -= 2 * gracePeriod
+
+ if timeout <= 0 {
+ // The test has less than the grace period remaining. There is no point in
+ // even starting the command, because it will be terminated immediately.
+ // Save the expense of starting it in the first place.
+ bg.err = context.DeadlineExceeded
+ close(done)
+ return bg, nil
+ }
+
+ ctx, bg.cancel = context.WithTimeout(ctx, timeout)
+ }
+
cmd := exec.Command(command, args...)
cmd.Dir = ts.cd
cmd.Env = append(ts.env, "PWD="+ts.cd)
- var stdoutBuf, stderrBuf strings.Builder
- cmd.Stdout = &stdoutBuf
- cmd.Stderr = &stderrBuf
- return cmd, cmd.Start()
-}
-
-// ctxWait is like cmd.Wait, but terminates cmd with os.Interrupt if ctx becomes done.
-//
-// This differs from exec.CommandContext in that it prefers os.Interrupt over os.Kill.
-// (See https://golang.org/issue/21135.)
-func ctxWait(ctx context.Context, cmd *exec.Cmd) error {
- errc := make(chan error, 1)
- go func() { errc <- cmd.Wait() }()
-
- select {
- case err := <-errc:
- return err
- case <-ctx.Done():
- interruptProcess(cmd.Process)
- return <-errc
+ cmd.Stdout = &bg.stdout
+ cmd.Stderr = &bg.stderr
+ if err := cmd.Start(); err != nil {
+ bg.cancel()
+ return nil, err
}
+
+ go func() {
+ bg.err = waitOrStop(ctx, cmd, stopSignal(), gracePeriod)
+ close(done)
+ }()
+ return bg, nil
}
-// interruptProcess sends os.Interrupt to p if supported, or os.Kill otherwise.
-func interruptProcess(p *os.Process) {
- if err := p.Signal(os.Interrupt); err != nil {
+// stopSignal returns the appropriate signal to use to request that a process
+// stop execution.
+func stopSignal() os.Signal {
+ if runtime.GOOS == "windows" {
// Per https://golang.org/pkg/os/#Signal, “Interrupt is not implemented on
// Windows; using it with os.Process.Signal will return an error.”
// Fall back to Kill instead.
- p.Kill()
+ return os.Kill
}
+ return os.Interrupt
+}
+
+// waitOrStop waits for the already-started command cmd by calling its Wait method.
+//
+// If cmd does not return before ctx is done, waitOrStop sends it the given interrupt signal.
+// If killDelay is positive, waitOrStop waits that additional period for Wait to return before sending os.Kill.
+//
+// This function is copied from the one added to x/playground/internal in
+// http://golang.org/cl/228438.
+func waitOrStop(ctx context.Context, cmd *exec.Cmd, interrupt os.Signal, killDelay time.Duration) error {
+ if cmd.Process == nil {
+ panic("waitOrStop called with a nil cmd.Process — missing Start call?")
+ }
+ if interrupt == nil {
+ panic("waitOrStop requires a non-nil interrupt signal")
+ }
+
+ errc := make(chan error)
+ go func() {
+ select {
+ case errc <- nil:
+ return
+ case <-ctx.Done():
+ }
+
+ err := cmd.Process.Signal(interrupt)
+ if err == nil {
+ err = ctx.Err() // Report ctx.Err() as the reason we interrupted.
+ } else if err.Error() == "os: process already finished" {
+ errc <- nil
+ return
+ }
+
+ if killDelay > 0 {
+ timer := time.NewTimer(killDelay)
+ select {
+ // Report ctx.Err() as the reason we interrupted the process...
+ case errc <- ctx.Err():
+ timer.Stop()
+ return
+ // ...but after killDelay has elapsed, fall back to a stronger signal.
+ case <-timer.C:
+ }
+
+ // Wait still hasn't returned.
+ // Kill the process harder to make sure that it exits.
+ //
+ // Ignore any error: if cmd.Process has already terminated, we still
+ // want to send ctx.Err() (or the error from the Interrupt call)
+ // to properly attribute the signal that may have terminated it.
+ _ = cmd.Process.Kill()
+ }
+
+ errc <- err
+ }()
+
+ waitErr := cmd.Wait()
+ if interruptErr := <-errc; interruptErr != nil {
+ return interruptErr
+ }
+ return waitErr
}
// expand applies environment variable expansion to the string s.
@@ -1044,7 +1189,7 @@ type condition struct {
// A command is a complete command parsed from a script.
type command struct {
- neg bool // if true, expect the command to fail
+ want simpleStatus
conds []condition // all must be satisfied
name string // the name of the command; must be non-empty
args []string // shell-expanded arguments following name
@@ -1079,11 +1224,13 @@ func (ts *testScript) parse(line string) command {
// Command prefix ! means negate the expectations about this command:
// go command should fail, match should not be found, etc.
- if arg == "!" {
- if cmd.neg {
- ts.fatalf("duplicated '!' token")
+ // Prefix ? means allow either success or failure.
+ switch want := simpleStatus(arg); want {
+ case failure, successOrFailure:
+ if cmd.want != "" {
+ ts.fatalf("duplicated '!' or '?' token")
}
- cmd.neg = true
+ cmd.want = want
return
}
@@ -1234,6 +1381,8 @@ var diffTests = []struct {
}
func TestDiff(t *testing.T) {
+ t.Parallel()
+
for _, tt := range diffTests {
// Turn spaces into \n.
text1 := strings.ReplaceAll(tt.text1, " ", "\n")
diff --git a/libgo/go/cmd/go/testdata/example1_test.go b/libgo/go/cmd/go/testdata/example1_test.go
deleted file mode 100644
index 87e6c0a..0000000
--- a/libgo/go/cmd/go/testdata/example1_test.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Make sure that go test runs Example_Z before Example_A, preserving source order.
-
-package p
-
-import "fmt"
-
-var n int
-
-func Example_Z() {
- n++
- fmt.Println(n)
- // Output: 1
-}
-
-func Example_A() {
- n++
- fmt.Println(n)
- // Output: 2
-}
diff --git a/libgo/go/cmd/go/testdata/example2_test.go b/libgo/go/cmd/go/testdata/example2_test.go
deleted file mode 100644
index 5d13426..0000000
--- a/libgo/go/cmd/go/testdata/example2_test.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Make sure that go test runs Example_Y before Example_B, preserving source order.
-
-package p
-
-import "fmt"
-
-func Example_Y() {
- n++
- fmt.Println(n)
- // Output: 3
-}
-
-func Example_B() {
- n++
- fmt.Println(n)
- // Output: 4
-}
diff --git a/libgo/go/cmd/go/testdata/generate/test1.go b/libgo/go/cmd/go/testdata/generate/test1.go
deleted file mode 100644
index 168cfb7..0000000
--- a/libgo/go/cmd/go/testdata/generate/test1.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Simple test for go generate.
-
-// We include a build tag that go generate should ignore.
-
-// +build ignore
-
-//go:generate echo Success
-
-package p
diff --git a/libgo/go/cmd/go/testdata/generate/test2.go b/libgo/go/cmd/go/testdata/generate/test2.go
deleted file mode 100644
index 829244a..0000000
--- a/libgo/go/cmd/go/testdata/generate/test2.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test that go generate handles command aliases.
-
-//go:generate -command run echo Now is the time
-//go:generate run for all good men
-
-package p
diff --git a/libgo/go/cmd/go/testdata/generate/test3.go b/libgo/go/cmd/go/testdata/generate/test3.go
deleted file mode 100644
index e950da5..0000000
--- a/libgo/go/cmd/go/testdata/generate/test3.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test go generate variable substitution.
-
-//go:generate echo $GOARCH $GOFILE:$GOLINE ${GOPACKAGE}abc xyz$GOPACKAGE/$GOFILE/123
-
-package p
diff --git a/libgo/go/cmd/go/testdata/generate/test4.go b/libgo/go/cmd/go/testdata/generate/test4.go
deleted file mode 100644
index 6dae048..0000000
--- a/libgo/go/cmd/go/testdata/generate/test4.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Test -run flag
-
-//go:generate echo oh yes my man
-//go:generate echo no, no, a thousand times no
-
-package p
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_printversion_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_printversion_v0.1.0.txt
index bae8b13..606322a 100644
--- a/libgo/go/cmd/go/testdata/mod/example.com_printversion_v0.1.0.txt
+++ b/libgo/go/cmd/go/testdata/mod/example.com_printversion_v0.1.0.txt
@@ -21,7 +21,13 @@ func main() {
info, _ := debug.ReadBuildInfo()
fmt.Fprintf(os.Stdout, "path is %s\n", info.Path)
fmt.Fprintf(os.Stdout, "main is %s %s\n", info.Main.Path, info.Main.Version)
+ if r := info.Main.Replace; r != nil {
+ fmt.Fprintf(os.Stdout, "\t(replaced by %s %s)\n", r.Path, r.Version)
+ }
for _, m := range info.Deps {
fmt.Fprintf(os.Stdout, "using %s %s\n", m.Path, m.Version)
+ if r := m.Replace; r != nil {
+ fmt.Fprintf(os.Stdout, "\t(replaced by %s %s)\n", r.Path, r.Version)
+ }
}
}
diff --git a/libgo/go/cmd/go/testdata/mod/example.com_printversion_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_printversion_v1.0.0.txt
index 2467418..b9b71e9 100644
--- a/libgo/go/cmd/go/testdata/mod/example.com_printversion_v1.0.0.txt
+++ b/libgo/go/cmd/go/testdata/mod/example.com_printversion_v1.0.0.txt
@@ -29,7 +29,13 @@ func main() {
info, _ := debug.ReadBuildInfo()
fmt.Fprintf(os.Stdout, "path is %s\n", info.Path)
fmt.Fprintf(os.Stdout, "main is %s %s\n", info.Main.Path, info.Main.Version)
+ if r := info.Main.Replace; r != nil {
+ fmt.Fprintf(os.Stdout, "\t(replaced by %s %s)\n", r.Path, r.Version)
+ }
for _, m := range info.Deps {
fmt.Fprintf(os.Stdout, "using %s %s\n", m.Path, m.Version)
+ if r := m.Replace; r != nil {
+ fmt.Fprintf(os.Stdout, "\t(replaced by %s %s)\n", r.Path, r.Version)
+ }
}
}
diff --git a/libgo/go/cmd/go/testdata/norunexample/example_test.go b/libgo/go/cmd/go/testdata/norunexample/example_test.go
deleted file mode 100644
index e158305..0000000
--- a/libgo/go/cmd/go/testdata/norunexample/example_test.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package pkg_test
-
-import "os"
-
-func init() {
- os.Stdout.Write([]byte("File with non-runnable example was built.\n"))
-}
-
-func Example_test() {
- // This test will not be run, it has no "Output:" comment.
-}
diff --git a/libgo/go/cmd/go/testdata/norunexample/test_test.go b/libgo/go/cmd/go/testdata/norunexample/test_test.go
deleted file mode 100644
index d2e9198..0000000
--- a/libgo/go/cmd/go/testdata/norunexample/test_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package pkg
-
-import (
- "os"
- "testing"
-)
-
-func TestBuilt(t *testing.T) {
- os.Stdout.Write([]byte("A normal test was executed.\n"))
-}
diff --git a/libgo/go/cmd/go/testdata/print_goroot.go b/libgo/go/cmd/go/testdata/print_goroot.go
deleted file mode 100644
index 91fbf7d..0000000
--- a/libgo/go/cmd/go/testdata/print_goroot.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
- "fmt"
- "runtime"
-)
-
-func main() {
- fmt.Println(runtime.GOROOT())
-}
diff --git a/libgo/go/cmd/go/testdata/rundir/sub/sub.go b/libgo/go/cmd/go/testdata/rundir/sub/sub.go
deleted file mode 100644
index 06ab7d0..0000000
--- a/libgo/go/cmd/go/testdata/rundir/sub/sub.go
+++ /dev/null
@@ -1 +0,0 @@
-package main
diff --git a/libgo/go/cmd/go/testdata/rundir/x.go b/libgo/go/cmd/go/testdata/rundir/x.go
deleted file mode 100644
index 06ab7d0..0000000
--- a/libgo/go/cmd/go/testdata/rundir/x.go
+++ /dev/null
@@ -1 +0,0 @@
-package main
diff --git a/libgo/go/cmd/go/testdata/script/README b/libgo/go/cmd/go/testdata/script/README
index 7dba6b3..76d6651 100644
--- a/libgo/go/cmd/go/testdata/script/README
+++ b/libgo/go/cmd/go/testdata/script/README
@@ -29,13 +29,17 @@ Scripts also have access to these other environment variables:
GOARCH=<target GOARCH>
GOCACHE=<actual GOCACHE being used outside the test>
GOEXE=<executable file suffix: .exe on Windows, empty on other systems>
+ GOEXPSTRING=<value of objabi.Expstring(), from GOEXPERIMENT when toolchain built>
GOOS=<target GOOS>
GOPATH=$WORK/gopath
GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
GOROOT=<actual GOROOT>
+ GOROOT_FINAL=<actual GOROOT_FINAL>
+ TESTGO_GOROOT=<GOROOT used to build cmd/go, for use in tests that may change GOROOT>
HOME=/no-home
PATH=<actual PATH>
TMPDIR=$WORK/tmp
+ GODEBUG=<actual GODEBUG>
devnull=<value of os.DevNull>
goversion=<current Go version; for example, 1.12>
:=<OS-specific path list separator>
@@ -65,6 +69,10 @@ The command prefix ! indicates that the command on the rest of the line
(typically go or a matching predicate) must fail, not succeed. Only certain
commands support this prefix. They are indicated below by [!] in the synopsis.
+The command prefix ? indicates that the command on the rest of the line
+may or may not succeed, but the test should continue regardless.
+Commands that support this prefix are indicated by [?].
+
The command prefix [cond] indicates that the command on the rest of the line
should only run when the condition is satisfied. The available conditions are:
@@ -88,7 +96,7 @@ are satisfied.
The commands are:
-- [!] cc args... [&]
+- [! | ?] cc args... [&]
Run the C compiler, the platform specific flags (i.e. `go env GOGCCFLAGS`) will be
added automatically before args.
@@ -110,7 +118,7 @@ The commands are:
Like cmp, but environment variables are substituted in the file contents
before the comparison. For example, $GOOS is replaced by the target GOOS.
-- [!] cp src... dst
+- [! | ?] cp src... dst
Copy the listed files to the target file or existing directory.
src can include "stdout" or "stderr" to use the standard output or standard error
from the most recent exec or go command.
@@ -122,7 +130,7 @@ The commands are:
The -r flag causes the values to be escaped using regexp.QuoteMeta
before being recorded.
-- [!] exec program [args...] [&]
+- [! | ?] exec program [args...] [&]
Run the given executable program with the arguments.
It must (or must not) succeed.
Note that 'exec' does not terminate the script (unlike in Unix shells).
@@ -131,14 +139,16 @@ The commands are:
output and standard error of the previous command is cleared, but the output
of the background process is buffered — and checking of its exit status is
delayed — until the next call to 'wait', 'skip', or 'stop' or the end of the
- test. At the end of the test, any remaining background processes are
- terminated using os.Interrupt (if supported) or os.Kill.
+ test. If any background processes remain at the end of the test, they
+ are terminated using os.Interrupt (if supported) or os.Kill and the test
+ must not depend upon their exit status.
-- [!] exists [-readonly] file...
+- [!] exists [-readonly] [-exec] file...
Each of the listed files or directories must (or must not) exist.
If -readonly is given, the files or directories must be unwritable.
+ If -exec is given, the files or directories must be executable.
-- [!] go args... [&]
+- [! | ?] go args... [&]
Run the (test copy of the) go command with the given arguments.
It must (or must not) succeed.
diff --git a/libgo/go/cmd/go/testdata/script/build_gcflags.txt b/libgo/go/cmd/go/testdata/script/build_gcflags.txt
index e0accb1..b472374 100644
--- a/libgo/go/cmd/go/testdata/script/build_gcflags.txt
+++ b/libgo/go/cmd/go/testdata/script/build_gcflags.txt
@@ -7,7 +7,8 @@ env GO111MODULE=off
[!linux] skip # test only works if c-archive implies -shared
[short] skip
-go build -x -buildmode=c-archive -gcflags=all=-shared=false ./override.go
+env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache.
+go build -x -n -buildmode=c-archive -gcflags=all=-shared=false ./override.go
stderr '^.*/compile (.* )?-shared (.* )?-shared=false'
-- override.go --
diff --git a/libgo/go/cmd/go/testdata/script/build_trimpath.txt b/libgo/go/cmd/go/testdata/script/build_trimpath.txt
index cfab807..ad78bcf 100644
--- a/libgo/go/cmd/go/testdata/script/build_trimpath.txt
+++ b/libgo/go/cmd/go/testdata/script/build_trimpath.txt
@@ -1,5 +1,9 @@
[short] skip
+# If GOROOT_FINAL is set, 'go build -trimpath' bakes that into the resulting
+# binary instead of GOROOT. Explicitly unset it here.
+env GOROOT_FINAL=
+
# Set up two identical directories that can be used as GOPATH.
env GO111MODULE=on
mkdir $WORK/a/src/paths $WORK/b/src/paths
diff --git a/libgo/go/cmd/go/testdata/script/cmd_import_error.txt b/libgo/go/cmd/go/testdata/script/cmd_import_error.txt
index 685c606..dea76f4 100644
--- a/libgo/go/cmd/go/testdata/script/cmd_import_error.txt
+++ b/libgo/go/cmd/go/testdata/script/cmd_import_error.txt
@@ -5,7 +5,7 @@ env GO111MODULE=on
# a clear error in module mode.
! go list cmd/unknown
-stderr '^can''t load package: package cmd/unknown is not in GOROOT \('$GOROOT'[/\\]src[/\\]cmd[/\\]unknown\)$'
+stderr '^package cmd/unknown is not in GOROOT \('$GOROOT'[/\\]src[/\\]cmd[/\\]unknown\)$'
go list -f '{{range .DepsErrors}}{{.Err}}{{end}}' x.go
stdout '^package cmd/unknown is not in GOROOT \('$GOROOT'[/\\]src[/\\]cmd[/\\]unknown\)$'
diff --git a/libgo/go/cmd/go/testdata/script/gcflags_patterns.txt b/libgo/go/cmd/go/testdata/script/gcflags_patterns.txt
index dce8e39..5374493 100644
--- a/libgo/go/cmd/go/testdata/script/gcflags_patterns.txt
+++ b/libgo/go/cmd/go/testdata/script/gcflags_patterns.txt
@@ -3,6 +3,8 @@ env GO111MODULE=off
[!gc] skip 'using -gcflags and -ldflags'
[short] skip
+env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache.
+
# -gcflags=-e applies to named packages, not dependencies
go build -n -v -gcflags=-e z1 z2
stderr 'compile.* -e.* -p z1'
diff --git a/libgo/go/cmd/go/testdata/script/install_cross_gobin.txt b/libgo/go/cmd/go/testdata/script/install_cross_gobin.txt
index 14cf722..8d38d7b 100644
--- a/libgo/go/cmd/go/testdata/script/install_cross_gobin.txt
+++ b/libgo/go/cmd/go/testdata/script/install_cross_gobin.txt
@@ -1,5 +1,5 @@
env GO111MODULE=off
-[!short] skip # rebuilds std for alternate architecture
+[short] skip # rebuilds std for alternate architecture
[gccgo] skip
cd mycmd
@@ -17,10 +17,9 @@ env GOBIN=$WORK/bin
! go install mycmd
! exists $GOBIN/linux_$GOARCH
-# installing standard command should still work
-# (should also be mtime update only if cmd/pack is up-to-date).
-! stale cmd/pack
-[!short] go install cmd/pack
+# The install directory for a cross-compiled standard command should include GOARCH.
+go list -f '{{.Target}}' cmd/pack
+stdout ${GOROOT}[/\\]pkg[/\\]tool[/\\]${GOOS}_${GOARCH}[/\\]pack$
-- mycmd/x.go --
package main
diff --git a/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt b/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt
index 03169bf..46b0ef4 100644
--- a/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt
+++ b/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt
@@ -12,10 +12,6 @@
# See: https://github.com/golang/go/issues/36739
[linux] [riscv64] skip
-# External linking is not supported on darwin/386 (10.14+).
-# See: https://github.com/golang/go/issues/31751
-[darwin] [386] skip
-
cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c
go build -ldflags='-linkmode=external' ./cmd/main.go
diff --git a/libgo/go/cmd/go/testdata/script/list_ambiguous_path.txt b/libgo/go/cmd/go/testdata/script/list_ambiguous_path.txt
index bdb7ffb..82dde45 100644
--- a/libgo/go/cmd/go/testdata/script/list_ambiguous_path.txt
+++ b/libgo/go/cmd/go/testdata/script/list_ambiguous_path.txt
@@ -17,10 +17,10 @@ stdout '^command-line-arguments$'
# A single typo-ed pattern for a Go file. This should
# treat the wrong pattern as if it were a package.
! go list ./foo.go/b.go
-stderr 'package ./foo.go/b.go: cannot find package "."'
+stderr '^stat .*[/\\]foo\.go[/\\]b\.go: directory not found$'
# Multiple patterns for Go files with a typo. This should
-# treat the wrong pattern as if it were a non-existint file.
+# treat the wrong pattern as if it were a nonexistent file.
! go list ./foo.go/a.go ./foo.go/b.go
[plan9] stderr 'stat ./foo.go/b.go: ''./foo.go/b.go'' does not exist'
[windows] stderr './foo.go/b.go: The system cannot find the file specified'
diff --git a/libgo/go/cmd/go/testdata/script/list_importmap.txt b/libgo/go/cmd/go/testdata/script/list_importmap.txt
index 52ee602..f424b98 100644
--- a/libgo/go/cmd/go/testdata/script/list_importmap.txt
+++ b/libgo/go/cmd/go/testdata/script/list_importmap.txt
@@ -16,7 +16,7 @@ go list -deps -test -f '{{.ImportPath}} MAP: {{.ImportMap}}{{"\n"}}{{.ImportPath
stdout '^flag \[fmt\.test\] MAP: map\[fmt:fmt \[fmt\.test\]\]'
stdout '^fmt\.test MAP: map\[(.* )?testing:testing \[fmt\.test\]'
! stdout '^fmt\.test MAP: map\[(.* )?os:'
-stdout '^fmt\.test IMPORT: \[fmt \[fmt\.test\] fmt_test \[fmt\.test\] os testing \[fmt\.test\] testing/internal/testdeps \[fmt\.test\]\]'
+stdout '^fmt\.test IMPORT: \[fmt \[fmt\.test\] fmt_test \[fmt\.test\] os reflect testing \[fmt\.test\] testing/internal/testdeps \[fmt\.test\]\]'
-- a/b/b.go --
diff --git a/libgo/go/cmd/go/testdata/script/list_parse_err.txt b/libgo/go/cmd/go/testdata/script/list_parse_err.txt
index 5aacaa8..3c53458 100644
--- a/libgo/go/cmd/go/testdata/script/list_parse_err.txt
+++ b/libgo/go/cmd/go/testdata/script/list_parse_err.txt
@@ -1,17 +1,45 @@
-# 'go list' should report imports, even if some files have parse errors
+# 'go list' without -e should fail and print errors on stderr.
+! go list ./p
+stderr '^p[/\\]b.go:2:2: expected ''package'', found ''EOF''$'
+! go list -f '{{range .Imports}}{{.}} {{end}}' ./p
+stderr '^p[/\\]b.go:2:2: expected ''package'', found ''EOF''$'
+! go list -test ./t
+stderr '^can''t load test package: t[/\\]t_test.go:8:1: expected declaration, found ʕ'
+! go list -test -f '{{range .Imports}}{{.}} {{end}}' ./t
+stderr '^can''t load test package: t[/\\]t_test.go:8:1: expected declaration, found ʕ'
+
+# 'go list -e' should report imports, even if some files have parse errors
# before the import block.
-go list -e -f '{{range .Imports}}{{.}} {{end}}'
+go list -e -f '{{range .Imports}}{{.}} {{end}}' ./p
stdout '^fmt '
+# 'go list' should report the position of the error if there's only one.
+go list -e -f '{{.Error.Pos}} => {{.Error.Err}}' ./p
+stdout 'b.go:[0-9:]+ => expected ''package'', found ''EOF'''
+
+# 'go test' should report the position of the error if there's only one.
+go list -e -test -f '{{if .Error}}{{.Error.Pos}} => {{.Error.Err}}{{end}}' ./t
+stdout 't_test.go:[0-9:]+ => expected declaration, found ʕ'
+
-- go.mod --
module m
go 1.13
--- a.go --
+-- p/a.go --
package a
import "fmt"
--- b.go --
+-- p/b.go --
// no package statement
+
+-- t/t_test.go --
+package t
+
+import "testing"
+
+func Test(t *testing.T) {}
+
+// scan error
+ʕ◔ϖ◔ʔ
diff --git a/libgo/go/cmd/go/testdata/script/list_test_imports.txt b/libgo/go/cmd/go/testdata/script/list_test_imports.txt
index b2a6bc45..0342eba 100644
--- a/libgo/go/cmd/go/testdata/script/list_test_imports.txt
+++ b/libgo/go/cmd/go/testdata/script/list_test_imports.txt
@@ -16,6 +16,6 @@ package b_test; import _ "a"
-- imports.txt --
a: b
b:
-b.test: b [b.test], b_test [b.test], os, testing, testing/internal/testdeps
+b.test: b [b.test], b_test [b.test], os, reflect, testing, testing/internal/testdeps
b [b.test]:
b_test [b.test]: a [b.test]
diff --git a/libgo/go/cmd/go/testdata/script/list_test_non_go_files.txt b/libgo/go/cmd/go/testdata/script/list_test_non_go_files.txt
index 16b98f4..6b2b633 100644
--- a/libgo/go/cmd/go/testdata/script/list_test_non_go_files.txt
+++ b/libgo/go/cmd/go/testdata/script/list_test_non_go_files.txt
@@ -5,7 +5,7 @@ go list -e -test -json -- c.c x.go
stdout '"Err": "named files must be .go files: c.c"'
! go list -test -json -- c.c x.go
-stderr 'can''t load package: named files must be .go files: c.c'
+stderr '^named files must be \.go files: c\.c$'
-- x.go --
package main
diff --git a/libgo/go/cmd/go/testdata/script/mod_ambiguous_import.txt b/libgo/go/cmd/go/testdata/script/mod_ambiguous_import.txt
index 61e632a..feaf5d2 100644
--- a/libgo/go/cmd/go/testdata/script/mod_ambiguous_import.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_ambiguous_import.txt
@@ -11,12 +11,11 @@ go build ./importy
# An import provided by both the main module and the vendor directory
# should be flagged as an error only when -mod=vendor is set.
-# TODO: This error message is a bit redundant.
mkdir vendor/example.com/m/importy
cp $WORK/importy/importy.go vendor/example.com/m/importy/importy.go
go build example.com/m/importy
! go build -mod=vendor example.com/m/importy
-stderr '^can.t load package: package example.com/m/importy: ambiguous import: found package example.com/m/importy in multiple directories:\n\t'$WORK'[/\\]importy\n\t'$WORK'[/\\]vendor[/\\]example.com[/\\]m[/\\]importy$'
+stderr '^ambiguous import: found package example.com/m/importy in multiple directories:\n\t'$WORK'[/\\]importy\n\t'$WORK'[/\\]vendor[/\\]example.com[/\\]m[/\\]importy$'
-- $WORK/go.mod --
module example.com/m
diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt b/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt
index 267c90e..ad22aca 100644
--- a/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt
@@ -20,7 +20,6 @@ cd $WORK/gopkgdir/x
! go list .
stderr 'cannot find main module'
! stderr 'Gopkg.lock'
-! stderr 'go mod init'
-- $WORK/test/Gopkg.lock --
-- $WORK/test/x/x.go --
diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_git.txt b/libgo/go/cmd/go/testdata/script/mod_convert_git.txt
index ece505a..6ff1eb5 100644
--- a/libgo/go/cmd/go/testdata/script/mod_convert_git.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_convert_git.txt
@@ -18,6 +18,23 @@ cd $GOROOT
! go list .
! stderr 'go mod init'
+# We should also not suggest creating a go.mod file in $GOROOT if its own
+# .git/config has been stripped away and we find one in a parent directory.
+# (https://golang.org/issue/34191)
+env GOROOT=$WORK/parent/goroot
+cd $GOROOT
+! go list .
+! stderr 'go mod init'
+
+cd $GOROOT/doc
+! go list .
+! stderr 'go mod init'
+
-- $WORK/test/.git/config --
-- $WORK/test/x/x.go --
package x // import "m/x"
+-- $WORK/parent/.git/config --
+-- $WORK/parent/goroot/README --
+This directory isn't really a GOROOT, but let's pretend that it is.
+-- $WORK/parent/goroot/doc/README --
+This is a subdirectory of our fake GOROOT.
diff --git a/libgo/go/cmd/go/testdata/script/mod_dot.txt b/libgo/go/cmd/go/testdata/script/mod_dot.txt
index c90074d..c220e99 100644
--- a/libgo/go/cmd/go/testdata/script/mod_dot.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_dot.txt
@@ -8,12 +8,12 @@ cd dir
stderr 'go get \.: path .* is not a package in module rooted at .*[/\\]dir$'
! go list
! stderr 'cannot find module providing package'
-stderr '^can.t load package: package \.: no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir$'
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir$'
cd subdir
! go list
! stderr 'cannot find module providing package'
-stderr '^can.t load package: package \.: no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir$'
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir$'
cd ..
# golang.org/issue/30590: if a package is found in the filesystem
@@ -22,7 +22,74 @@ cd ..
# to find a module providing the package.
! go list ./othermodule
! stderr 'cannot find module providing package'
-stderr 'go: directory othermodule is outside main module'
+stderr '^main module \(example\.com\) does not contain package example.com/othermodule$'
+
+# golang.org/issue/27122: 'go build' of a nonexistent directory should produce
+# a helpful "no Go files" error message, not a generic "unknown import path".
+! go list ./subdir
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]subdir$'
+
+# golang.org/issue/29280: 'go list -e' for a nonexistent directory should
+# report a nonexistent package with an error.
+go list -e -json ./subdir
+stdout '"Incomplete": true'
+
+# golang.org/issue/28155: 'go list ./testdata' should not synthesize underscores.
+go list ./testdata
+stdout '^example.com/testdata'
+
+# golang.org/issue/32921: vendor directories should only be accepted as directories
+# if the directory would actually be used to load the package.
+! go list ./vendor/nonexist
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]vendor[/\\]nonexist$'
+
+! go list ./vendor/pkg
+stderr '^without -mod=vendor, directory '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]vendor[/\\]pkg has no package path$'
+
+! go list -mod=vendor ./vendor/nonexist
+stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]vendor[/\\]nonexist$'
+
+! go list -mod=vendor ./vendor/unlisted
+stderr '^directory '$WORK'[/\\]gopath[/\\]src[/\\]dir[/\\]vendor[/\\]unlisted is not a package listed in vendor/modules.txt$'
+
+go list -mod=vendor ./vendor/pkg
+stdout '^pkg$'
+
+# Packages within GOROOT should resolve as in any other module,
+# except that -mod=vendor is implied by default.
+[!gccgo] cd $GOROOT/src
+[!gccgo] ! go list .
+[!gccgo] stderr '^no Go files in '$GOROOT'[/\\]src$'
+
+[!gccgo] ! go list ./builtin
+[!gccgo] stderr '^"builtin" is a pseudo-package, not an importable package$'
+
+[!gccgo] ! go list ./debug
+[!gccgo] ! stderr 'cannot find module providing package'
+[!gccgo] stderr '^no Go files in '$GOROOT'[/\\]src[/\\]debug$'
+
+[!gccgo] ! go list ./golang.org/x/tools/cmd/goimports
+[!gccgo] ! stderr 'cannot find module providing package'
+[!gccgo] stderr '^stat '$GOROOT'[/\\]src[/\\]golang.org[/\\]x[/\\]tools[/\\]cmd[/\\]goimports: directory not found'
+
+[!gccgo] go list ./vendor/golang.org/x/net/http2/hpack
+[!gccgo] stdout '^golang.org/x/net/http2/hpack$'
+
+# golang.org/issue/30756: packages in other GOROOTs should not get the special
+# prefixless treatment of GOROOT itself.
+cd $WORK/othergoroot/src
+! go list .
+stderr '^no Go files in '$WORK'[/\\]othergoroot[/\\]src$'
+
+go list ./builtin
+stdout '^std/builtin$' # Only the "std" in actual $GOROOT is special, and only its "builtin" is special.
+
+! go list ./bytes
+! stderr 'cannot find module providing package'
+stderr '^no Go files in '$WORK'[/\\]othergoroot[/\\]src[/\\]bytes$'
+
+! go list ./vendor/golang.org/x/net/http2/hpack
+stderr '^without -mod=vendor, directory '$WORK'[/\\]othergoroot[/\\]src[/\\]vendor[/\\]golang.org[/\\]x[/\\]net[/\\]http2[/\\]hpack has no package path$'
-- dir/go.mod --
module example.com
@@ -34,3 +101,27 @@ module example.com/othermodule
go 1.13
-- dir/othermodule/om.go --
package othermodule
+-- dir/testdata/td.go --
+package testdata
+-- dir/vendor/modules.txt --
+# pkg v0.0.0
+pkg
+-- dir/vendor/nonexist/README --
+There are no Go source files here either.
+-- dir/vendor/pkg/pkg.go --
+package pkg
+-- dir/vendor/unlisted/unlisted.go --
+package unlisted
+-- emptyroot/go.mod --
+module example.com/emptyroot
+-- emptyroot/pkg/pkg.go --
+package pkg
+-- $WORK/othergoroot/src/go.mod --
+module std
+go 1.13
+-- $WORK/othergoroot/src/builtin/builtin.go --
+package builtin
+-- $WORK/othergoroot/src/bytes/README --
+There are no Go source files in this directory.
+-- $WORK/othergoroot/src/vendor/golang.org/x/net/http2/hpack --
+package hpack
diff --git a/libgo/go/cmd/go/testdata/script/mod_empty_err.txt b/libgo/go/cmd/go/testdata/script/mod_empty_err.txt
index 729f848..982e6b2 100644
--- a/libgo/go/cmd/go/testdata/script/mod_empty_err.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_empty_err.txt
@@ -4,16 +4,16 @@ env GO111MODULE=on
cd $WORK
go list -e -f {{.Error}} .
-stdout 'package \.: no Go files in \$WORK'
+stdout 'no Go files in \$WORK'
go list -e -f {{.Error}} ./empty
-stdout 'package \./empty: no Go files in \$WORK[/\\]empty'
+stdout 'no Go files in \$WORK[/\\]empty'
go list -e -f {{.Error}} ./exclude
-stdout 'package \./exclude: build constraints exclude all Go files in \$WORK[/\\]exclude'
+stdout 'build constraints exclude all Go files in \$WORK[/\\]exclude'
go list -e -f {{.Error}} ./missing
-stdout 'package \./missing: cannot find package "." in:\s*\$WORK[/\\]missing'
+stdout 'stat '$WORK'[/\\]missing: directory not found'
# use 'go build -n' because 'go list' reports no error.
! go build -n ./testonly
diff --git a/libgo/go/cmd/go/testdata/script/mod_fs_patterns.txt b/libgo/go/cmd/go/testdata/script/mod_fs_patterns.txt
index 4911fbb..a20fefd 100644
--- a/libgo/go/cmd/go/testdata/script/mod_fs_patterns.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_fs_patterns.txt
@@ -33,11 +33,11 @@ stderr 'import lookup disabled'
! go build -mod=readonly ./nonexist
! stderr 'import lookup disabled'
-stderr '^can.t load package: package ./nonexist: cannot find package "." in:\n\t'$WORK'[/\\]gopath[/\\]src[/\\]x[/\\]nonexist$'
+stderr '^stat '$GOPATH'[/\\]src[/\\]x[/\\]nonexist: directory not found'
! go build -mod=readonly ./go.mod
! stderr 'import lookup disabled'
-stderr 'can.t load package: package ./go.mod: cannot find package'
+stderr 'main module \(m\) does not contain package m/go.mod'
# File system paths and patterns should allow the '@' character.
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_commit.txt b/libgo/go/cmd/go/testdata/script/mod_get_commit.txt
index a906bab..d108242 100644
--- a/libgo/go/cmd/go/testdata/script/mod_get_commit.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_get_commit.txt
@@ -14,6 +14,9 @@ go get -d golang.org/x/text@14c0d48
# dropping -d, we should see a build.
[short] skip
+
+env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache.
+
go get -x golang.org/x/text/language@14c0d48
stderr 'compile|cp|gccgo .*language\.a$'
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_main.txt b/libgo/go/cmd/go/testdata/script/mod_get_main.txt
index 403abcd..408a5b5 100644
--- a/libgo/go/cmd/go/testdata/script/mod_get_main.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_get_main.txt
@@ -1,9 +1,18 @@
env GO111MODULE=on
-[short] skip
+cp go.mod.orig go.mod
+
+# relative and absolute paths must be within the main module.
+! go get -d ..
+stderr '^go get \.\.: path '$WORK'[/\\]gopath is not a package in module rooted at '$WORK'[/\\]gopath[/\\]src$'
+! go get -d $WORK
+stderr '^go get '$WORK': path '$WORK' is not a package in module rooted at '$WORK'[/\\]gopath[/\\]src$'
+! go get -d ../...
+stderr '^go get: pattern \.\./\.\.\.: directory prefix \.\. outside available modules$'
+! go get -d $WORK/...
+stderr '^go get: pattern '$WORK'[/\\]\.\.\.: directory prefix \.\.[/\\]\.\. outside available modules$'
# @patch and @latest within the main module refer to the current version.
# The main module won't be upgraded, but missing dependencies will be added.
-cp go.mod.orig go.mod
go get -d rsc.io/x
grep 'rsc.io/quote v1.5.2' go.mod
go get -d rsc.io/x@upgrade
@@ -18,7 +27,7 @@ cp go.mod.orig go.mod
stderr '^go get rsc.io/x@latest: can.t request explicit version of path in main module$'
# The main module cannot be updated to a specific version.
-! go get rsc.io/x@v0.1.0
+! go get -d rsc.io/x@v0.1.0
stderr '^go get rsc.io/x@v0.1.0: can.t request explicit version of path in main module$'
! go get -d rsc.io/x@v0.1.0
stderr '^go get rsc.io/x@v0.1.0: can.t request explicit version of path in main module$'
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_tags.txt b/libgo/go/cmd/go/testdata/script/mod_get_tags.txt
index 603c769..e9869e3 100644
--- a/libgo/go/cmd/go/testdata/script/mod_get_tags.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_get_tags.txt
@@ -14,7 +14,8 @@ stdout 'rsc.io/quote v1.5.2'
[short] skip
# Packages that are only imported in excluded files should not be built.
-go get -x .
+env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache.
+go get -n -x .
stderr 'compile.* -p m '
! stderr 'compile.* -p example.com/version '
! stderr 'compile.* -p rsc.io/quote '
diff --git a/libgo/go/cmd/go/testdata/script/mod_gonoproxy.txt b/libgo/go/cmd/go/testdata/script/mod_gonoproxy.txt
index 2bd94cd..a9e0ca4 100644
--- a/libgo/go/cmd/go/testdata/script/mod_gonoproxy.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_gonoproxy.txt
@@ -10,7 +10,7 @@ env GOSUMDB=$sumdb' '$proxy/sumdb-wrong
! go get rsc.io/quote
stderr 'SECURITY ERROR'
-# but GONOSUMDB bypasses sumdb, for rsc.io/quote, rsc.io/sampler, golang.org/x/text
+# GONOSUMDB bypasses sumdb, for rsc.io/quote, rsc.io/sampler, golang.org/x/text
env GONOSUMDB='*/quote,*/*mple*,golang.org/x'
go get rsc.io/quote
rm go.sum
@@ -18,7 +18,18 @@ env GOPRIVATE='*/quote,*/*mple*,golang.org/x'
env GONOPROXY=none # that is, proxy all despite GOPRIVATE
go get rsc.io/quote
-# and GONOPROXY bypasses proxy
+# When GOPROXY is not empty but contains no entries, an error should be reported.
+env GOPROXY=','
+! go get golang.org/x/text
+stderr '^go get golang.org/x/text: GOPROXY list is not the empty string, but contains no entries$'
+
+# When GOPROXY=off, fetching modules not matched by GONOPROXY fails.
+env GONOPROXY=*/fortune
+env GOPROXY=off
+! go get golang.org/x/text
+stderr '^go get golang.org/x/text: module lookup disabled by GOPROXY=off$'
+
+# GONOPROXY bypasses proxy
[!net] skip
[!exec:git] skip
env GOPRIVATE=none
diff --git a/libgo/go/cmd/go/testdata/script/mod_goroot_errors.txt b/libgo/go/cmd/go/testdata/script/mod_goroot_errors.txt
index 2e08ae0..e340f18 100644
--- a/libgo/go/cmd/go/testdata/script/mod_goroot_errors.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_goroot_errors.txt
@@ -13,12 +13,12 @@ env GO111MODULE=on
! go build -mod=readonly nonexist
! stderr 'import lookup disabled'
! stderr 'missing dot'
-stderr '^can''t load package: package nonexist is not in GOROOT \('$GOROOT'[/\\]src[/\\]nonexist\)$'
+stderr '^package nonexist is not in GOROOT \('$GOROOT'[/\\]src[/\\]nonexist\)$'
! go build nonexist
! stderr 'import lookup disabled'
! stderr 'missing dot'
-stderr '^can''t load package: package nonexist is not in GOROOT \('$GOROOT'[/\\]src[/\\]nonexist\)$'
+stderr '^package nonexist is not in GOROOT \('$GOROOT'[/\\]src[/\\]nonexist\)$'
# Building a nonexistent std package indirectly should also fail usefully.
diff --git a/libgo/go/cmd/go/testdata/script/mod_invalid_version.txt b/libgo/go/cmd/go/testdata/script/mod_invalid_version.txt
index 76e0b43..7e1bc9e 100644
--- a/libgo/go/cmd/go/testdata/script/mod_invalid_version.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_invalid_version.txt
@@ -76,17 +76,17 @@ cp go.mod.orig go.mod
go mod edit -require golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c
cd outside
! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(2017-09-15T03:28:32Z\)'
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
cd ..
! go list -m golang.org/x/text
-stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(2017-09-15T03:28:32Z\)'
+stderr 'golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
# A 'replace' directive in the main module can replace an invalid timestamp
# with a valid one.
go mod edit -replace golang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c=golang.org/x/text@14c0d48ead0c
cd outside
! go list -m golang.org/x/text
-stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(2017-09-15T03:28:32Z\)'
+stderr 'go: example.com@v0.0.0 requires\n\tgolang.org/x/text@v0.1.1-0.20190915032832-14c0d48ead0c: invalid pseudo-version: does not match version-control timestamp \(expected 20170915032832\)'
cd ..
go list -m golang.org/x/text
stdout 'golang.org/x/text v0.1.1-0.20190915032832-14c0d48ead0c => golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c'
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_dir.txt b/libgo/go/cmd/go/testdata/script/mod_list_dir.txt
index f6994c1..6653435 100644
--- a/libgo/go/cmd/go/testdata/script/mod_list_dir.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_list_dir.txt
@@ -11,11 +11,7 @@ go list -f '{{.ImportPath}}' $GOROOT/src/math
stdout ^math$
go list -f '{{.ImportPath}}' .
stdout ^x$
-! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
-stderr '^can.t load package: package '$WORK'[/\\]gopath[/\\]pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2: can only use path@version syntax with .go get.'
-go list -e -f '{{with .Error}}{{.}}{{end}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
-stdout '^package '$WORK'[/\\]gopath[/\\]pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2: can only use path@version syntax with .go get.'
go mod download rsc.io/quote@v1.5.2
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
stdout '^rsc.io/quote$'
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_replace_dir.txt b/libgo/go/cmd/go/testdata/script/mod_list_replace_dir.txt
index d43bbe7..cad7fe2 100644
--- a/libgo/go/cmd/go/testdata/script/mod_list_replace_dir.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_list_replace_dir.txt
@@ -3,10 +3,10 @@
# Verifies golang.org/issue/29548
env GO111MODULE=on
-go mod download
+go mod download rsc.io/quote@v1.5.1 rsc.io/quote@v1.5.2
! go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
-stderr 'can only use path@version syntax with .go get.'
+stderr '^directory ..[/\\]pkg[/\\]mod[/\\]rsc.io[/\\]quote@v1.5.2 outside available modules$'
go list $GOPATH/pkg/mod/rsc.io/quote@v1.5.1
stdout 'rsc.io/quote'
diff --git a/libgo/go/cmd/go/testdata/script/mod_list_std.txt b/libgo/go/cmd/go/testdata/script/mod_list_std.txt
index 8552aeb..76a3b00 100644
--- a/libgo/go/cmd/go/testdata/script/mod_list_std.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_list_std.txt
@@ -14,6 +14,16 @@ go list cmd/...
stdout ^cmd/compile
! stdout ^cmd/vendor/golang\.org/x/arch/x86/x86asm
+# GOROOT/src/... should list the packages in std as if it were a module
+# dependency: omitting vendored dependencies and stopping at the 'cmd' module
+# boundary.
+
+go list $GOROOT/src/...
+stdout ^bytes$
+! stdout ^builtin$
+! stdout ^cmd/
+! stdout ^vendor/
+
# Within the std module, listing ./... should omit the 'std' prefix:
# the package paths should be the same via ./... or the 'std' meta-pattern.
diff --git a/libgo/go/cmd/go/testdata/script/mod_proxy_list.txt b/libgo/go/cmd/go/testdata/script/mod_proxy_list.txt
index a486228..849cf2c 100644
--- a/libgo/go/cmd/go/testdata/script/mod_proxy_list.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_proxy_list.txt
@@ -10,17 +10,25 @@ stderr '404 Not Found'
env GOPROXY=$proxy/404,$proxy/410,$proxy
go get rsc.io/quote@v1.1.0
-# get should not walk past other 4xx errors.
+# get should not walk past other 4xx errors if proxies are separated with ','.
env GOPROXY=$proxy/403,$proxy
! go get rsc.io/quote@v1.2.0
stderr 'reading.*/403/rsc.io/.*: 403 Forbidden'
-# get should not walk past non-4xx errors.
+# get should not walk past non-4xx errors if proxies are separated with ','.
env GOPROXY=$proxy/500,$proxy
! go get rsc.io/quote@v1.3.0
stderr 'reading.*/500/rsc.io/.*: 500 Internal Server Error'
-# get should return the final 404/410 if that's all we have.
+# get should walk past other 4xx errors if proxies are separated with '|'.
+env GOPROXY=$proxy/403|https://0.0.0.0|$proxy
+go get rsc.io/quote@v1.2.0
+
+# get should walk past non-4xx errors if proxies are separated with '|'.
+env GOPROXY=$proxy/500|https://0.0.0.0|$proxy
+go get rsc.io/quote@v1.3.0
+
+# get should return the final error if that's all we have.
env GOPROXY=$proxy/404,$proxy/410
! go get rsc.io/quote@v1.4.0
stderr 'reading.*/410/rsc.io/.*: 410 Gone'
diff --git a/libgo/go/cmd/go/testdata/script/mod_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_readonly.txt
index 751f6e6..ac58126 100644
--- a/libgo/go/cmd/go/testdata/script/mod_readonly.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_readonly.txt
@@ -6,7 +6,7 @@ env GOFLAGS=-mod=readonly
go mod edit -fmt
cp go.mod go.mod.empty
! go list all
-stderr '^can''t load package: x.go:2:8: cannot find module providing package rsc\.io/quote: import lookup disabled by -mod=readonly'
+stderr '^x.go:2:8: cannot find module providing package rsc\.io/quote: import lookup disabled by -mod=readonly'
! stderr '\(\)' # If we don't have a reason for -mod=readonly, don't log an empty one.
cmp go.mod go.mod.empty
@@ -14,7 +14,7 @@ cmp go.mod go.mod.empty
chmod 0400 go.mod
env GOFLAGS=
! go list all
-stderr '^can''t load package: x.go:2:8: cannot find module providing package rsc\.io/quote: import lookup disabled by -mod=readonly\n\t\(go.mod file is read-only\.\)$'
+stderr '^x.go:2:8: cannot find module providing package rsc\.io/quote: import lookup disabled by -mod=readonly\n\t\(go.mod file is read-only\.\)$'
chmod 0600 go.mod
env GOFLAGS=-mod=readonly
diff --git a/libgo/go/cmd/go/testdata/script/mod_replace_import.txt b/libgo/go/cmd/go/testdata/script/mod_replace_import.txt
index fd5b04a..54b1a12 100644
--- a/libgo/go/cmd/go/testdata/script/mod_replace_import.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_replace_import.txt
@@ -27,9 +27,8 @@ stdout 'example.com/v v1.12.0 => ./v12'
# module does not contain a package.
cd fail
! go list all
-stdout 'localhost.fail'
-stderr '^can''t load package: m.go:4:2: module w@latest found \(v0.0.0-00010101000000-000000000000, replaced by ../w\), but does not contain package w$'
-stderr '^can''t load package: m.go:5:2: nonexist@v0.1.0: replacement directory ../nonexist does not exist$'
+stderr '^m.go:4:2: module w@latest found \(v0.0.0-00010101000000-000000000000, replaced by ../w\), but does not contain package w$'
+stderr '^m.go:5:2: nonexist@v0.1.0: replacement directory ../nonexist does not exist$'
-- go.mod --
module example.com/m
diff --git a/libgo/go/cmd/go/testdata/script/mod_retention.txt b/libgo/go/cmd/go/testdata/script/mod_retention.txt
index bff4142..1d83e6c 100644
--- a/libgo/go/cmd/go/testdata/script/mod_retention.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_retention.txt
@@ -64,7 +64,7 @@ cmp go.mod go.mod.tidy
# However, that should not remove other redundant requirements.
cp go.mod.nogo go.mod
go list all
-cmp go.mod go.mod.redundant
+cmpenv go.mod go.mod.currentgo
-- go.mod.tidy --
@@ -133,3 +133,13 @@ require (
rsc.io/sampler v1.3.0 // indirect
rsc.io/testonly v1.0.0 // indirect
)
+-- go.mod.currentgo --
+module m
+
+go $goversion
+
+require (
+ rsc.io/quote v1.5.2
+ rsc.io/sampler v1.3.0 // indirect
+ rsc.io/testonly v1.0.0 // indirect
+)
diff --git a/libgo/go/cmd/go/testdata/script/mod_sumdb_proxy.txt b/libgo/go/cmd/go/testdata/script/mod_sumdb_proxy.txt
index 2816691..7bbc3f9 100644
--- a/libgo/go/cmd/go/testdata/script/mod_sumdb_proxy.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_sumdb_proxy.txt
@@ -46,5 +46,22 @@ stderr '503 Service Unavailable'
rm $GOPATH/pkg/mod/cache/download/sumdb
rm go.sum
+# the error from the last attempted proxy should be returned.
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb
+env GOPROXY=$proxy/sumdb-404,$proxy/sumdb-503
+! go get -d rsc.io/fortune@v1.0.0
+stderr '503 Service Unavailable'
+rm $GOPATH/pkg/mod/cache/download/sumdb
+rm go.sum
+
+# if proxies are separated with '|', fallback is allowed on any error.
+cp go.mod.orig go.mod
+env GOSUMDB=$sumdb
+env GOPROXY=$proxy/sumdb-503|https://0.0.0.0|$proxy
+go get -d rsc.io/fortune@v1.0.0
+rm $GOPATH/pkg/mod/cache/download/sumdb
+rm go.sum
+
-- go.mod.orig --
module m
diff --git a/libgo/go/cmd/go/testdata/script/noncanonical_import.txt b/libgo/go/cmd/go/testdata/script/noncanonical_import.txt
index 7fdc071..018cb01 100644
--- a/libgo/go/cmd/go/testdata/script/noncanonical_import.txt
+++ b/libgo/go/cmd/go/testdata/script/noncanonical_import.txt
@@ -1,9 +1,7 @@
env GO111MODULE=off
! go build canonical/d
-stderr 'package canonical/d'
-stderr 'imports canonical/b'
-stderr 'imports canonical/a/: non-canonical'
+stderr '^canonical[/\\]b[/\\]b.go:3:8: non-canonical import path "canonical/a/": should be "canonical/a"$'
-- canonical/a/a.go --
package a
diff --git a/libgo/go/cmd/go/testdata/script/script_wait.txt b/libgo/go/cmd/go/testdata/script/script_wait.txt
index 3cd4ded..acaccfe 100644
--- a/libgo/go/cmd/go/testdata/script/script_wait.txt
+++ b/libgo/go/cmd/go/testdata/script/script_wait.txt
@@ -19,6 +19,7 @@ wait
stdout 'foo\nbar'
# The end of the test should interrupt or kill any remaining background
-# programs.
-[!exec:sleep] skip
-! exec sleep 86400 &
+# programs, but that should not cause the test to fail if it does not
+# care about the exit status of those programs.
+[!exec:sleep] stop
+? exec sleep 86400 &
diff --git a/libgo/go/cmd/go/testdata/script/test_cache_inputs.txt b/libgo/go/cmd/go/testdata/script/test_cache_inputs.txt
index 46faca0..57602e9 100644
--- a/libgo/go/cmd/go/testdata/script/test_cache_inputs.txt
+++ b/libgo/go/cmd/go/testdata/script/test_cache_inputs.txt
@@ -29,6 +29,23 @@ go test testcache -run=TestLookupEnv
go test testcache -run=TestLookupEnv
stdout '\(cached\)'
+# Changes in arguments forwarded to the test should invalidate cached test
+# results.
+go test testcache -run=TestOSArgs -v hello
+! stdout '\(cached\)'
+stdout 'hello'
+go test testcache -run=TestOSArgs -v goodbye
+! stdout '\(cached\)'
+stdout 'goodbye'
+
+# golang.org/issue/36134: that includes the `-timeout` argument.
+go test testcache -run=TestOSArgs -timeout=20m -v
+! stdout '\(cached\)'
+stdout '-test\.timeout[= ]20m'
+go test testcache -run=TestOSArgs -timeout=5s -v
+! stdout '\(cached\)'
+stdout '-test\.timeout[= ]5s'
+
# If the test stats a file, changes to the file should invalidate the cache.
go test testcache -run=FileSize
go test testcache -run=FileSize
@@ -207,6 +224,10 @@ func TestExternalFile(t *testing.T) {
t.Fatal(err)
}
}
+
+func TestOSArgs(t *testing.T) {
+ t.Log(os.Args)
+}
-- mkold.go --
package main
diff --git a/libgo/go/cmd/go/testdata/script/version.txt b/libgo/go/cmd/go/testdata/script/version.txt
index 4252624..0123ac6 100644
--- a/libgo/go/cmd/go/testdata/script/version.txt
+++ b/libgo/go/cmd/go/testdata/script/version.txt
@@ -1,4 +1,16 @@
+# Without arguments, we just print Go's own version.
+go version
+stdout '^go version'
+
+# Flags without files, or paths to misisng files, should error.
+! go version missing.exe
+! go version -m
+stderr 'with arguments'
+! go version -v
+stderr 'with arguments'
+
env GO111MODULE=on
+# Skip the builds below if we are running in short mode.
[short] skip
# Check that 'go version' and 'go version -m' work on a binary built in module mode.
@@ -10,9 +22,7 @@ stdout '^\tpath\trsc.io/fortune'
stdout '^\tmod\trsc.io/fortune\tv1.0.0'
# Repeat the test with -buildmode=pie.
-# TODO(golang.org/issue/27144): don't skip after -buildmode=pie is implemented
-# on Windows.
-[windows] skip # -buildmode=pie not supported
+[!buildmode:pie] stop
go build -buildmode=pie -o external.exe rsc.io/fortune
go version external.exe
stdout '^external.exe: .+'
@@ -20,5 +30,16 @@ go version -m external.exe
stdout '^\tpath\trsc.io/fortune'
stdout '^\tmod\trsc.io/fortune\tv1.0.0'
+# Also test PIE with internal linking.
+# currently only supported on linux/amd64, linux/arm64 and windows/amd64.
+[!linux] [!windows] stop
+[!amd64] [!arm64] stop
+go build -buildmode=pie -ldflags=-linkmode=internal -o internal.exe rsc.io/fortune
+go version internal.exe
+stdout '^internal.exe: .+'
+go version -m internal.exe
+stdout '^\tpath\trsc.io/fortune'
+stdout '^\tmod\trsc.io/fortune\tv1.0.0'
+
-- go.mod --
module m
diff --git a/libgo/go/cmd/go/testdata/script/vet_flags.txt b/libgo/go/cmd/go/testdata/script/vet_flags.txt
index 2d790c1..b55dada 100644
--- a/libgo/go/cmd/go/testdata/script/vet_flags.txt
+++ b/libgo/go/cmd/go/testdata/script/vet_flags.txt
@@ -3,8 +3,8 @@ env GO111MODULE=on
# gccgo doesn't support vet on the standard library
[gccgo] skip
-# Regression test for issue 35837: "go vet -<analyzer> <std package>"
-# did not apply the requested analyzer.
+# Issue 35837: "go vet -<analyzer> <std package>" should use the requested
+# analyzers, not the default analyzers for 'go test'.
go vet -n -unreachable=false encoding/binary
stderr '-unreachable=false'
! stderr '-unsafeptr=false'
@@ -20,20 +20,54 @@ go vet -n -unsafeptr encoding/binary
stderr '-unsafeptr'
! stderr '-unsafeptr=false'
+# A flag terminator should be allowed before the package list.
+go vet -n -- .
+
[short] stop
+
+# Analyzer flags should be included from GOFLAGS, and should override
+# the defaults.
+go vet .
+env GOFLAGS='-tags=buggy'
+! go vet .
+stderr 'possible formatting directive'
+
+# Enabling one analyzer in GOFLAGS should disable the rest implicitly...
+env GOFLAGS='-tags=buggy -unsafeptr'
+go vet .
+
+# ...but enabling one on the command line should not disable the analyzers
+# enabled via GOFLAGS.
+env GOFLAGS='-tags=buggy -printf'
+! go vet -unsafeptr
+stderr 'possible formatting directive'
+
+# Analyzer flags don't exist unless we're running 'go vet',
+# and we shouldn't run the vet tool to discover them otherwise.
+# (Maybe someday we'll hard-code the analyzer flags for the default vet
+# tool to make this work, but not right now.)
+env GOFLAGS='-unsafeptr'
+! go list .
+stderr 'go: parsing \$GOFLAGS: unknown flag -unsafeptr'
+env GOFLAGS=
+
env GOCACHE=$WORK/gocache
-env GOTMPDIR=$WORK/tmp
-go env GOTMPDIR
-stdout '/tmp'
-# "go test" on a user package should by default enable an explicit whitelist of analyzers.
+# "go test" on a user package should by default enable an explicit list of analyzers.
go test -x -run=none .
stderr '[/\\]vet'$GOEXE'["]? .* -errorsas .* ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
-# "go test" on a standard package should by default disable an explicit blacklist.
+# An explicitly-empty -vet argument should imply the default analyzers.
+go test -x -vet= -run=none .
+stderr '[/\\]vet'$GOEXE'["]? .* -errorsas .* ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+
+# "go test" on a standard package should by default disable an explicit list.
go test -x -run=none encoding/binary
stderr '[/\\]vet'$GOEXE'["]? -unsafeptr=false ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+go test -x -vet= -run=none encoding/binary
+stderr '[/\\]vet'$GOEXE'["]? -unsafeptr=false ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
+
# Both should allow users to override via the -vet flag.
go test -x -vet=unreachable -run=none .
stderr '[/\\]vet'$GOEXE'["]? -unreachable ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
@@ -46,3 +80,13 @@ module example.com/x
package x
-- x_test.go --
package x
+-- x_tagged.go --
+// +build buggy
+
+package x
+
+import "fmt"
+
+func init() {
+ fmt.Sprint("%s") // oops!
+}
diff --git a/libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go b/libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go
deleted file mode 100644
index f52652b..0000000
--- a/libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go
+++ /dev/null
@@ -1 +0,0 @@
-package foo
diff --git a/libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go b/libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go
deleted file mode 100644
index c91c24e..0000000
--- a/libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go
+++ /dev/null
@@ -1 +0,0 @@
-package math
diff --git a/libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go b/libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go
deleted file mode 100644
index f52652b..0000000
--- a/libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go
+++ /dev/null
@@ -1 +0,0 @@
-package foo
diff --git a/libgo/go/cmd/go/testdata/src/cgotest/m.go b/libgo/go/cmd/go/testdata/src/cgotest/m.go
deleted file mode 100644
index 4d68307..0000000
--- a/libgo/go/cmd/go/testdata/src/cgotest/m.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package cgotest
-
-import "C"
-
-var _ C.int
diff --git a/libgo/go/cmd/go/testdata/src/coverasm/p.go b/libgo/go/cmd/go/testdata/src/coverasm/p.go
deleted file mode 100644
index ab0c300..0000000
--- a/libgo/go/cmd/go/testdata/src/coverasm/p.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p
-
-func f()
-
-func g() {
- println("g")
-}
diff --git a/libgo/go/cmd/go/testdata/src/coverasm/p.s b/libgo/go/cmd/go/testdata/src/coverasm/p.s
deleted file mode 100644
index 5e728f9..0000000
--- a/libgo/go/cmd/go/testdata/src/coverasm/p.s
+++ /dev/null
@@ -1,2 +0,0 @@
-// empty asm file,
-// so go test doesn't complain about declaration of f in p.go.
diff --git a/libgo/go/cmd/go/testdata/src/coverasm/p_test.go b/libgo/go/cmd/go/testdata/src/coverasm/p_test.go
deleted file mode 100644
index 3cb3bd5..0000000
--- a/libgo/go/cmd/go/testdata/src/coverasm/p_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p
-
-import "testing"
-
-func Test(t *testing.T) {
- g()
-}
diff --git a/libgo/go/cmd/go/testdata/src/coverbad/p.go b/libgo/go/cmd/go/testdata/src/coverbad/p.go
deleted file mode 100644
index 16504a4..0000000
--- a/libgo/go/cmd/go/testdata/src/coverbad/p.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package p
-
-func f() {
- g()
-}
diff --git a/libgo/go/cmd/go/testdata/src/coverbad/p1.go b/libgo/go/cmd/go/testdata/src/coverbad/p1.go
deleted file mode 100644
index 2d25c8e1..0000000
--- a/libgo/go/cmd/go/testdata/src/coverbad/p1.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p
-
-import "C"
-
-func h() {
- j()
-}
diff --git a/libgo/go/cmd/go/testdata/src/coverbad/p_test.go b/libgo/go/cmd/go/testdata/src/coverbad/p_test.go
deleted file mode 100644
index 3a876d6..0000000
--- a/libgo/go/cmd/go/testdata/src/coverbad/p_test.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package p
-
-import "testing"
-
-func Test(t *testing.T) {}
diff --git a/libgo/go/cmd/go/testdata/src/coverdep/p.go b/libgo/go/cmd/go/testdata/src/coverdep/p.go
deleted file mode 100644
index 6baf6d5..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdep/p.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package p
-
-import _ "coverdep/p1"
-
-func F() {
-}
diff --git a/libgo/go/cmd/go/testdata/src/coverdep/p1/p1.go b/libgo/go/cmd/go/testdata/src/coverdep/p1/p1.go
deleted file mode 100644
index 8ae793d..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdep/p1/p1.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p1
-
-import _ "errors"
diff --git a/libgo/go/cmd/go/testdata/src/coverdep/p_test.go b/libgo/go/cmd/go/testdata/src/coverdep/p_test.go
deleted file mode 100644
index 11a1434..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdep/p_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p
-
-import "testing"
-
-func Test(t *testing.T) {
- F()
-}
diff --git a/libgo/go/cmd/go/testdata/src/coverdep2/p1/p.go b/libgo/go/cmd/go/testdata/src/coverdep2/p1/p.go
deleted file mode 100644
index fd31527..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdep2/p1/p.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p1
-
-func F() int { return 1 }
diff --git a/libgo/go/cmd/go/testdata/src/coverdep2/p1/p_test.go b/libgo/go/cmd/go/testdata/src/coverdep2/p1/p_test.go
deleted file mode 100644
index c402568..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdep2/p1/p_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package p1_test
-
-import (
- "coverdep2/p2"
- "testing"
-)
-
-func Test(t *testing.T) {
- p2.F()
-}
diff --git a/libgo/go/cmd/go/testdata/src/coverdep2/p2/p2.go b/libgo/go/cmd/go/testdata/src/coverdep2/p2/p2.go
deleted file mode 100644
index 33561bb..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdep2/p2/p2.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p2
-
-import "coverdep2/p1"
-
-func F() {
- p1.F()
-}
diff --git a/libgo/go/cmd/go/testdata/src/coverdot1/p.go b/libgo/go/cmd/go/testdata/src/coverdot1/p.go
deleted file mode 100644
index cda364f..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdot1/p.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package coverdot1
-
-func F() {}
diff --git a/libgo/go/cmd/go/testdata/src/coverdot2/p.go b/libgo/go/cmd/go/testdata/src/coverdot2/p.go
deleted file mode 100644
index 80f79ae..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdot2/p.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package coverdot2
-
-import . "coverdot1"
-
-func G() { F() }
diff --git a/libgo/go/cmd/go/testdata/src/coverdot2/p_test.go b/libgo/go/cmd/go/testdata/src/coverdot2/p_test.go
deleted file mode 100644
index da66e3e..0000000
--- a/libgo/go/cmd/go/testdata/src/coverdot2/p_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package coverdot2
-
-import "testing"
-
-func TestG(t *testing.T) {
- G()
-}
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkg/pkg.go b/libgo/go/cmd/go/testdata/src/empty/pkg/pkg.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/pkg/pkg.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtest/pkg.go b/libgo/go/cmd/go/testdata/src/empty/pkgtest/pkg.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/pkgtest/pkg.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtest/test_test.go b/libgo/go/cmd/go/testdata/src/empty/pkgtest/test_test.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/pkgtest/test_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go
deleted file mode 100644
index 9b64e8e1a..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p_test
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgxtest/pkg.go b/libgo/go/cmd/go/testdata/src/empty/pkgxtest/pkg.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/pkgxtest/pkg.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go b/libgo/go/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go
deleted file mode 100644
index 9b64e8e1a..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p_test
diff --git a/libgo/go/cmd/go/testdata/src/empty/test/test_test.go b/libgo/go/cmd/go/testdata/src/empty/test/test_test.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/test/test_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/testxtest/test_test.go b/libgo/go/cmd/go/testdata/src/empty/testxtest/test_test.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/testxtest/test_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/testxtest/xtest_test.go b/libgo/go/cmd/go/testdata/src/empty/testxtest/xtest_test.go
deleted file mode 100644
index 9b64e8e1a..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/testxtest/xtest_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p_test
diff --git a/libgo/go/cmd/go/testdata/src/empty/xtest/xtest_test.go b/libgo/go/cmd/go/testdata/src/empty/xtest/xtest_test.go
deleted file mode 100644
index 9b64e8e1a..0000000
--- a/libgo/go/cmd/go/testdata/src/empty/xtest/xtest_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p_test
diff --git a/libgo/go/cmd/go/testdata/src/exclude/empty/x.txt b/libgo/go/cmd/go/testdata/src/exclude/empty/x.txt
deleted file mode 100644
index e69de29..0000000
--- a/libgo/go/cmd/go/testdata/src/exclude/empty/x.txt
+++ /dev/null
diff --git a/libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go b/libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go
deleted file mode 100644
index 823aafd..0000000
--- a/libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go
+++ /dev/null
@@ -1 +0,0 @@
-package x
diff --git a/libgo/go/cmd/go/testdata/src/exclude/x.go b/libgo/go/cmd/go/testdata/src/exclude/x.go
deleted file mode 100644
index 9affd21..0000000
--- a/libgo/go/cmd/go/testdata/src/exclude/x.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// +build linux,!linux
-
-package x
diff --git a/libgo/go/cmd/go/testdata/src/exclude/x_linux.go b/libgo/go/cmd/go/testdata/src/exclude/x_linux.go
deleted file mode 100644
index 41ef6e5..0000000
--- a/libgo/go/cmd/go/testdata/src/exclude/x_linux.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// +build windows
-
-package x
diff --git a/libgo/go/cmd/go/testdata/src/failfast_test.go b/libgo/go/cmd/go/testdata/src/failfast_test.go
deleted file mode 100644
index 6e64d73..0000000
--- a/libgo/go/cmd/go/testdata/src/failfast_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package failfast
-
-import "testing"
-
-func TestA(t *testing.T) {
- // Edge-case testing, mixing unparallel tests too
- t.Logf("LOG: %s", t.Name())
-}
-
-func TestFailingA(t *testing.T) {
- t.Errorf("FAIL - %s", t.Name())
-}
-
-func TestB(t *testing.T) {
- // Edge-case testing, mixing unparallel tests too
- t.Logf("LOG: %s", t.Name())
-}
-
-func TestParallelFailingA(t *testing.T) {
- t.Parallel()
- t.Errorf("FAIL - %s", t.Name())
-}
-
-func TestParallelFailingB(t *testing.T) {
- t.Parallel()
- t.Errorf("FAIL - %s", t.Name())
-}
-
-func TestParallelFailingSubtestsA(t *testing.T) {
- t.Parallel()
- t.Run("TestFailingSubtestsA1", func(t *testing.T) {
- t.Errorf("FAIL - %s", t.Name())
- })
- t.Run("TestFailingSubtestsA2", func(t *testing.T) {
- t.Errorf("FAIL - %s", t.Name())
- })
-}
-
-func TestFailingSubtestsA(t *testing.T) {
- t.Run("TestFailingSubtestsA1", func(t *testing.T) {
- t.Errorf("FAIL - %s", t.Name())
- })
- t.Run("TestFailingSubtestsA2", func(t *testing.T) {
- t.Errorf("FAIL - %s", t.Name())
- })
-}
-
-func TestFailingB(t *testing.T) {
- t.Errorf("FAIL - %s", t.Name())
-}
-
-func TestFatalC(t *testing.T) {
- t.Fatalf("FAIL - %s", t.Name())
-}
-
-func TestFatalD(t *testing.T) {
- t.Fatalf("FAIL - %s", t.Name())
-}
diff --git a/libgo/go/cmd/go/testdata/src/hello/hello.go b/libgo/go/cmd/go/testdata/src/hello/hello.go
deleted file mode 100644
index 73d83e64..0000000
--- a/libgo/go/cmd/go/testdata/src/hello/hello.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package main
-
-func main() {
- println("hello, world")
-}
diff --git a/libgo/go/cmd/go/testdata/src/my.pkg/main/main.go b/libgo/go/cmd/go/testdata/src/my.pkg/main/main.go
deleted file mode 100644
index c3e8de1..0000000
--- a/libgo/go/cmd/go/testdata/src/my.pkg/main/main.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package main
-
-import "my.pkg"
-
-func main() {
- println(pkg.Text)
-}
diff --git a/libgo/go/cmd/go/testdata/src/my.pkg/pkg.go b/libgo/go/cmd/go/testdata/src/my.pkg/pkg.go
deleted file mode 100644
index 17702a6..0000000
--- a/libgo/go/cmd/go/testdata/src/my.pkg/pkg.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package pkg
-
-var Text = "unset"
diff --git a/libgo/go/cmd/go/testdata/src/skipper/skip_test.go b/libgo/go/cmd/go/testdata/src/skipper/skip_test.go
deleted file mode 100644
index 58e6dc5..0000000
--- a/libgo/go/cmd/go/testdata/src/skipper/skip_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package skipper
-
-import "testing"
-
-func Test(t *testing.T) {
- t.Skip("skipping")
-}
diff --git a/libgo/go/cmd/go/testdata/src/testlist/bench_test.go b/libgo/go/cmd/go/testdata/src/testlist/bench_test.go
deleted file mode 100644
index 22f147b..0000000
--- a/libgo/go/cmd/go/testdata/src/testlist/bench_test.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package testlist
-
-import (
- "fmt"
- "testing"
-)
-
-func BenchmarkSimplefunc(b *testing.B) {
- b.StopTimer()
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- _ = fmt.Sprint("Test for bench")
- }
-}
diff --git a/libgo/go/cmd/go/testdata/src/testlist/example_test.go b/libgo/go/cmd/go/testdata/src/testlist/example_test.go
deleted file mode 100644
index 0298dfd..0000000
--- a/libgo/go/cmd/go/testdata/src/testlist/example_test.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package testlist
-
-import (
- "fmt"
-)
-
-func ExampleSimple() {
- fmt.Println("Test with Output.")
-
- // Output: Test with Output.
-}
-
-func ExampleWithEmptyOutput() {
- fmt.Println("")
-
- // Output:
-}
-
-func ExampleNoOutput() {
- _ = fmt.Sprint("Test with no output")
-}
diff --git a/libgo/go/cmd/go/testdata/src/testlist/test_test.go b/libgo/go/cmd/go/testdata/src/testlist/test_test.go
deleted file mode 100644
index bdc09f2..0000000
--- a/libgo/go/cmd/go/testdata/src/testlist/test_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package testlist
-
-import (
- "fmt"
- "testing"
-)
-
-func TestSimple(t *testing.T) {
- _ = fmt.Sprint("Test simple")
-}
diff --git a/libgo/go/cmd/go/testdata/src/vend/bad.go b/libgo/go/cmd/go/testdata/src/vend/bad.go
deleted file mode 100644
index 57cc595..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/bad.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package vend
-
-import _ "r"
diff --git a/libgo/go/cmd/go/testdata/src/vend/dir1/dir1.go b/libgo/go/cmd/go/testdata/src/vend/dir1/dir1.go
deleted file mode 100644
index b719ead..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/dir1/dir1.go
+++ /dev/null
@@ -1 +0,0 @@
-package dir1
diff --git a/libgo/go/cmd/go/testdata/src/vend/good.go b/libgo/go/cmd/go/testdata/src/vend/good.go
deleted file mode 100644
index 952ada3..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/good.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package vend
-
-import _ "p"
diff --git a/libgo/go/cmd/go/testdata/src/vend/hello/hello.go b/libgo/go/cmd/go/testdata/src/vend/hello/hello.go
deleted file mode 100644
index 41dc03e..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/hello/hello.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package main
-
-import (
- "fmt"
- "strings" // really ../vendor/strings
-)
-
-func main() {
- fmt.Printf("%s\n", strings.Msg)
-}
diff --git a/libgo/go/cmd/go/testdata/src/vend/hello/hello_test.go b/libgo/go/cmd/go/testdata/src/vend/hello/hello_test.go
deleted file mode 100644
index 7190f59..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/hello/hello_test.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package main
-
-import (
- "strings" // really ../vendor/strings
- "testing"
-)
-
-func TestMsgInternal(t *testing.T) {
- if strings.Msg != "hello, world" {
- t.Fatalf("unexpected msg: %v", strings.Msg)
- }
-}
diff --git a/libgo/go/cmd/go/testdata/src/vend/hello/hellox_test.go b/libgo/go/cmd/go/testdata/src/vend/hello/hellox_test.go
deleted file mode 100644
index 3f2165b..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/hello/hellox_test.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package main_test
-
-import (
- "strings" // really ../vendor/strings
- "testing"
-)
-
-func TestMsgExternal(t *testing.T) {
- if strings.Msg != "hello, world" {
- t.Fatalf("unexpected msg: %v", strings.Msg)
- }
-}
diff --git a/libgo/go/cmd/go/testdata/src/vend/subdir/bad.go b/libgo/go/cmd/go/testdata/src/vend/subdir/bad.go
deleted file mode 100644
index d0ddaac..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/subdir/bad.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package subdir
-
-import _ "r"
diff --git a/libgo/go/cmd/go/testdata/src/vend/subdir/good.go b/libgo/go/cmd/go/testdata/src/vend/subdir/good.go
deleted file mode 100644
index edd0454..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/subdir/good.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package subdir
-
-import _ "p"
diff --git a/libgo/go/cmd/go/testdata/src/vend/vendor/p/p.go b/libgo/go/cmd/go/testdata/src/vend/vendor/p/p.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/vendor/p/p.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/vend/vendor/q/q.go b/libgo/go/cmd/go/testdata/src/vend/vendor/q/q.go
deleted file mode 100644
index 946e6d9..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/vendor/q/q.go
+++ /dev/null
@@ -1 +0,0 @@
-package q
diff --git a/libgo/go/cmd/go/testdata/src/vend/vendor/strings/msg.go b/libgo/go/cmd/go/testdata/src/vend/vendor/strings/msg.go
deleted file mode 100644
index 438126b..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/vendor/strings/msg.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package strings
-
-var Msg = "hello, world"
diff --git a/libgo/go/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go b/libgo/go/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go
deleted file mode 100644
index 6fe35e9..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go
+++ /dev/null
@@ -1 +0,0 @@
-package dir2
diff --git a/libgo/go/cmd/go/testdata/src/vend/x/invalid/invalid.go b/libgo/go/cmd/go/testdata/src/vend/x/invalid/invalid.go
deleted file mode 100644
index e250d5b..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/x/invalid/invalid.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package invalid
-
-import "vend/x/invalid/vendor/foo"
diff --git a/libgo/go/cmd/go/testdata/src/vend/x/vendor/p/p.go b/libgo/go/cmd/go/testdata/src/vend/x/vendor/p/p.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/x/vendor/p/p.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/vend/x/vendor/p/p/p.go b/libgo/go/cmd/go/testdata/src/vend/x/vendor/p/p/p.go
deleted file mode 100644
index e12e12c..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/x/vendor/p/p/p.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-import _ "notfound"
diff --git a/libgo/go/cmd/go/testdata/src/vend/x/vendor/r/r.go b/libgo/go/cmd/go/testdata/src/vend/x/vendor/r/r.go
deleted file mode 100644
index 838c177..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/x/vendor/r/r.go
+++ /dev/null
@@ -1 +0,0 @@
-package r
diff --git a/libgo/go/cmd/go/testdata/src/vend/x/x.go b/libgo/go/cmd/go/testdata/src/vend/x/x.go
deleted file mode 100644
index bdcde57..0000000
--- a/libgo/go/cmd/go/testdata/src/vend/x/x.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package x
-
-import _ "p"
-import _ "q"
-import _ "r"
-import _ "vend/dir1" // not vendored
-import _ "vend/dir1/dir2" // vendored
diff --git a/libgo/go/cmd/go/testdata/src/vetcycle/p.go b/libgo/go/cmd/go/testdata/src/vetcycle/p.go
deleted file mode 100644
index 5b058e7..0000000
--- a/libgo/go/cmd/go/testdata/src/vetcycle/p.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package p
-
-type (
- _ interface{ m(B1) }
- A1 interface{ a(D1) }
- B1 interface{ A1 }
- C1 interface {
- B1 /* ERROR issue #18395 */
- }
- D1 interface{ C1 }
-)
-
-var _ A1 = C1 /* ERROR cannot use C1 */ (nil)
diff --git a/libgo/go/cmd/go/testdata/src/vetfail/p1/p1.go b/libgo/go/cmd/go/testdata/src/vetfail/p1/p1.go
deleted file mode 100644
index eaa9b18..0000000
--- a/libgo/go/cmd/go/testdata/src/vetfail/p1/p1.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build !foo-bar
-
-package p1
-
-import "fmt"
-
-func F() {
- fmt.Printf("%d", "hello") // causes vet error
-}
diff --git a/libgo/go/cmd/go/testdata/src/vetfail/p2/p2.go b/libgo/go/cmd/go/testdata/src/vetfail/p2/p2.go
deleted file mode 100644
index 88b1cc2..0000000
--- a/libgo/go/cmd/go/testdata/src/vetfail/p2/p2.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package p2
-
-import _ "vetfail/p1"
-
-func F() {
-}
diff --git a/libgo/go/cmd/go/testdata/src/vetfail/p2/p2_test.go b/libgo/go/cmd/go/testdata/src/vetfail/p2/p2_test.go
deleted file mode 100644
index fde0d1a..0000000
--- a/libgo/go/cmd/go/testdata/src/vetfail/p2/p2_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p2
-
-import "testing"
-
-func TestF(t *testing.T) {
- F()
-}
diff --git a/libgo/go/cmd/go/testdata/src/vetpkg/a_test.go b/libgo/go/cmd/go/testdata/src/vetpkg/a_test.go
deleted file mode 100644
index 9b64e8e1a..0000000
--- a/libgo/go/cmd/go/testdata/src/vetpkg/a_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p_test
diff --git a/libgo/go/cmd/go/testdata/src/vetpkg/b.go b/libgo/go/cmd/go/testdata/src/vetpkg/b.go
deleted file mode 100644
index 99e18f6..0000000
--- a/libgo/go/cmd/go/testdata/src/vetpkg/b.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p
-
-import "fmt"
-
-func f() {
- fmt.Printf("%d")
-}
diff --git a/libgo/go/cmd/go/testdata/src/vetpkg/c.go b/libgo/go/cmd/go/testdata/src/vetpkg/c.go
deleted file mode 100644
index ef5648f..0000000
--- a/libgo/go/cmd/go/testdata/src/vetpkg/c.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build tagtest
-
-package p
-
-import "fmt"
-
-func g() {
- fmt.Printf("%d", 3, 4)
-}
diff --git a/libgo/go/cmd/go/testdata/src/xtestonly/f.go b/libgo/go/cmd/go/testdata/src/xtestonly/f.go
deleted file mode 100644
index dac039e..0000000
--- a/libgo/go/cmd/go/testdata/src/xtestonly/f.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package xtestonly
-
-func F() int { return 42 }
diff --git a/libgo/go/cmd/go/testdata/src/xtestonly/f_test.go b/libgo/go/cmd/go/testdata/src/xtestonly/f_test.go
deleted file mode 100644
index 01f6e83..0000000
--- a/libgo/go/cmd/go/testdata/src/xtestonly/f_test.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package xtestonly_test
-
-import (
- "testing"
- "xtestonly"
-)
-
-func TestF(t *testing.T) {
- if x := xtestonly.F(); x != 42 {
- t.Errorf("f.F() = %d, want 42", x)
- }
-}
diff --git a/libgo/go/cmd/go/testdata/standalone_benchmark_test.go b/libgo/go/cmd/go/testdata/standalone_benchmark_test.go
deleted file mode 100644
index 4850f98..0000000
--- a/libgo/go/cmd/go/testdata/standalone_benchmark_test.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package standalone_benchmark
-
-import "testing"
-
-func Benchmark(b *testing.B) {
-}
diff --git a/libgo/go/cmd/go/testdata/standalone_fail_sub_test.go b/libgo/go/cmd/go/testdata/standalone_fail_sub_test.go
deleted file mode 100644
index ac483f9..0000000
--- a/libgo/go/cmd/go/testdata/standalone_fail_sub_test.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package standalone_fail_sub_test
-
-import "testing"
-
-func TestThatFails(t *testing.T) {
- t.Run("Sub", func(t *testing.T) {})
- t.Fail()
-}
diff --git a/libgo/go/cmd/go/testdata/standalone_main_normal_test.go b/libgo/go/cmd/go/testdata/standalone_main_normal_test.go
deleted file mode 100644
index 018ce75..0000000
--- a/libgo/go/cmd/go/testdata/standalone_main_normal_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package standalone_main_normal_test
-
-import "testing"
-
-func TestMain(t *testing.T) {
-}
diff --git a/libgo/go/cmd/go/testdata/standalone_main_wrong_test.go b/libgo/go/cmd/go/testdata/standalone_main_wrong_test.go
deleted file mode 100644
index 5999887..0000000
--- a/libgo/go/cmd/go/testdata/standalone_main_wrong_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package standalone_main_wrong_test
-
-import "testing"
-
-func TestMain(m *testing.Main) {
-}
diff --git a/libgo/go/cmd/go/testdata/standalone_parallel_sub_test.go b/libgo/go/cmd/go/testdata/standalone_parallel_sub_test.go
deleted file mode 100644
index d326de0..0000000
--- a/libgo/go/cmd/go/testdata/standalone_parallel_sub_test.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package standalone_parallel_sub_test
-
-import "testing"
-
-func Test(t *testing.T) {
- ch := make(chan bool, 1)
- t.Run("Sub", func(t *testing.T) {
- t.Parallel()
- <-ch
- t.Run("Nested", func(t *testing.T) {})
- })
- // Ensures that Sub will finish after its t.Run call already returned.
- ch <- true
-}
diff --git a/libgo/go/cmd/go/testdata/standalone_sub_test.go b/libgo/go/cmd/go/testdata/standalone_sub_test.go
deleted file mode 100644
index f6c31db..0000000
--- a/libgo/go/cmd/go/testdata/standalone_sub_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package standalone_sub_test
-
-import "testing"
-
-func Test(t *testing.T) {
- t.Run("Sub", func(t *testing.T) {})
-}
diff --git a/libgo/go/cmd/go/testdata/standalone_test.go b/libgo/go/cmd/go/testdata/standalone_test.go
deleted file mode 100644
index 59cf918..0000000
--- a/libgo/go/cmd/go/testdata/standalone_test.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package standalone_test
-
-import "testing"
-
-func Test(t *testing.T) {
-}
diff --git a/libgo/go/cmd/go/testdata/standalone_testmain_flag_test.go b/libgo/go/cmd/go/testdata/standalone_testmain_flag_test.go
deleted file mode 100644
index a59555b..0000000
--- a/libgo/go/cmd/go/testdata/standalone_testmain_flag_test.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package standalone_testmain_flag_test
-
-import (
- "flag"
- "fmt"
- "os"
- "testing"
-)
-
-func TestMain(m *testing.M) {
- // A TestMain should be able to access testing flags if it calls
- // flag.Parse without needing to use testing.Init.
- flag.Parse()
- found := false
- flag.VisitAll(func(f *flag.Flag) {
- if f.Name == "test.count" {
- found = true
- }
- })
- if !found {
- fmt.Println("testing flags not registered")
- os.Exit(1)
- }
- os.Exit(m.Run())
-}
diff --git a/libgo/go/cmd/go/testdata/testcover/pkg1/a.go b/libgo/go/cmd/go/testdata/testcover/pkg1/a.go
deleted file mode 100644
index e291611..0000000
--- a/libgo/go/cmd/go/testdata/testcover/pkg1/a.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package pkg1
-
-import "fmt"
-
-func F() {
- fmt.Println("pkg1")
-}
diff --git a/libgo/go/cmd/go/testdata/testcover/pkg2/a.go b/libgo/go/cmd/go/testdata/testcover/pkg2/a.go
deleted file mode 100644
index 7bd9bd4..0000000
--- a/libgo/go/cmd/go/testdata/testcover/pkg2/a.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package pkg2
-
-import "fmt"
-
-func F() {
- fmt.Println("pkg2")
-}
diff --git a/libgo/go/cmd/go/testdata/testcover/pkg2/a_test.go b/libgo/go/cmd/go/testdata/testcover/pkg2/a_test.go
deleted file mode 100644
index 4f791ad..0000000
--- a/libgo/go/cmd/go/testdata/testcover/pkg2/a_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package pkg2
diff --git a/libgo/go/cmd/go/testdata/testcover/pkg3/a.go b/libgo/go/cmd/go/testdata/testcover/pkg3/a.go
deleted file mode 100644
index bf86ed8..0000000
--- a/libgo/go/cmd/go/testdata/testcover/pkg3/a.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package pkg3
-
-import "fmt"
-
-func F() {
- fmt.Println("pkg3")
-}
diff --git a/libgo/go/cmd/go/testdata/testcover/pkg3/a_test.go b/libgo/go/cmd/go/testdata/testcover/pkg3/a_test.go
deleted file mode 100644
index 39c2c5a..0000000
--- a/libgo/go/cmd/go/testdata/testcover/pkg3/a_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package pkg3
-
-import "testing"
-
-func TestF(t *testing.T) {
- F()
-}
diff --git a/libgo/go/cmd/go/testdata/testcover/pkg4/a.go b/libgo/go/cmd/go/testdata/testcover/pkg4/a.go
deleted file mode 100644
index cf09e6f..0000000
--- a/libgo/go/cmd/go/testdata/testcover/pkg4/a.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package pkg4
-
-type T struct {
- X bool
-}
diff --git a/libgo/go/cmd/go/testdata/testcover/pkg4/a_test.go b/libgo/go/cmd/go/testdata/testcover/pkg4/a_test.go
deleted file mode 100644
index 12b8685..0000000
--- a/libgo/go/cmd/go/testdata/testcover/pkg4/a_test.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package pkg4
-
-import (
- "testing"
-)
-
-func TestT(t *testing.T) {
- _ = T{}
-}
diff --git a/libgo/go/cmd/go/testdata/testimport/p.go b/libgo/go/cmd/go/testdata/testimport/p.go
deleted file mode 100644
index f94d2cd..0000000
--- a/libgo/go/cmd/go/testdata/testimport/p.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-func F() int { return 1 }
diff --git a/libgo/go/cmd/go/testdata/testimport/p1/p1.go b/libgo/go/cmd/go/testdata/testimport/p1/p1.go
deleted file mode 100644
index fd31527..0000000
--- a/libgo/go/cmd/go/testdata/testimport/p1/p1.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p1
-
-func F() int { return 1 }
diff --git a/libgo/go/cmd/go/testdata/testimport/p2/p2.go b/libgo/go/cmd/go/testdata/testimport/p2/p2.go
deleted file mode 100644
index d488886..0000000
--- a/libgo/go/cmd/go/testdata/testimport/p2/p2.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p2
-
-func F() int { return 1 }
diff --git a/libgo/go/cmd/go/testdata/testimport/p_test.go b/libgo/go/cmd/go/testdata/testimport/p_test.go
deleted file mode 100644
index a3fb4a9..0000000
--- a/libgo/go/cmd/go/testdata/testimport/p_test.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package p
-
-import (
- "./p1"
-
- "testing"
-)
-
-func TestF(t *testing.T) {
- if F() != p1.F() {
- t.Fatal(F())
- }
-}
diff --git a/libgo/go/cmd/go/testdata/testimport/x_test.go b/libgo/go/cmd/go/testdata/testimport/x_test.go
deleted file mode 100644
index b253e3f..0000000
--- a/libgo/go/cmd/go/testdata/testimport/x_test.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package p_test
-
-import (
- . "../testimport"
-
- "./p2"
-
- "testing"
-)
-
-func TestF1(t *testing.T) {
- if F() != p2.F() {
- t.Fatal(F())
- }
-}
diff --git a/libgo/go/cmd/go/testdata/testinternal/p.go b/libgo/go/cmd/go/testdata/testinternal/p.go
deleted file mode 100644
index e3558a5..0000000
--- a/libgo/go/cmd/go/testdata/testinternal/p.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-import _ "net/http/internal"
diff --git a/libgo/go/cmd/go/testdata/testinternal2/p.go b/libgo/go/cmd/go/testdata/testinternal2/p.go
deleted file mode 100644
index c594f5c..0000000
--- a/libgo/go/cmd/go/testdata/testinternal2/p.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-import _ "./x/y/z/internal/w"
diff --git a/libgo/go/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go b/libgo/go/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go
deleted file mode 100644
index a796c0b..0000000
--- a/libgo/go/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go
+++ /dev/null
@@ -1 +0,0 @@
-package w
diff --git a/libgo/go/cmd/go/testdata/testinternal3/t.go b/libgo/go/cmd/go/testdata/testinternal3/t.go
deleted file mode 100644
index 8576a4b..0000000
--- a/libgo/go/cmd/go/testdata/testinternal3/t.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package t
-
-import _ "internal/does-not-exist"
diff --git a/libgo/go/cmd/go/testdata/testinternal4/src/p/p.go b/libgo/go/cmd/go/testdata/testinternal4/src/p/p.go
deleted file mode 100644
index 6bdee27..0000000
--- a/libgo/go/cmd/go/testdata/testinternal4/src/p/p.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package p
-
-import (
- _ "q/internal/x"
- _ "q/j"
-)
diff --git a/libgo/go/cmd/go/testdata/testinternal4/src/q/internal/x/x.go b/libgo/go/cmd/go/testdata/testinternal4/src/q/internal/x/x.go
deleted file mode 100644
index 823aafd..0000000
--- a/libgo/go/cmd/go/testdata/testinternal4/src/q/internal/x/x.go
+++ /dev/null
@@ -1 +0,0 @@
-package x
diff --git a/libgo/go/cmd/go/testdata/testinternal4/src/q/j/j.go b/libgo/go/cmd/go/testdata/testinternal4/src/q/j/j.go
deleted file mode 100644
index 9f07543..0000000
--- a/libgo/go/cmd/go/testdata/testinternal4/src/q/j/j.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package j
-
-import _ "q/internal/x"
diff --git a/libgo/go/cmd/go/testdata/testonly/p_test.go b/libgo/go/cmd/go/testdata/testonly/p_test.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/testonly/p_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/testonly2/t.go b/libgo/go/cmd/go/testdata/testonly2/t.go
deleted file mode 100644
index 82267d3..0000000
--- a/libgo/go/cmd/go/testdata/testonly2/t.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// This package is not a test-only package,
-// but it still matches the pattern ./testdata/testonly... when in cmd/go.
-
-package main
-
-func main() {}
diff --git a/libgo/go/cmd/go/testdata/testvendor/src/p/p.go b/libgo/go/cmd/go/testdata/testvendor/src/p/p.go
deleted file mode 100644
index e740715..0000000
--- a/libgo/go/cmd/go/testdata/testvendor/src/p/p.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package p
-
-import (
- _ "q/y"
- _ "q/z"
-)
diff --git a/libgo/go/cmd/go/testdata/testvendor/src/q/vendor/x/x.go b/libgo/go/cmd/go/testdata/testvendor/src/q/vendor/x/x.go
deleted file mode 100644
index 823aafd..0000000
--- a/libgo/go/cmd/go/testdata/testvendor/src/q/vendor/x/x.go
+++ /dev/null
@@ -1 +0,0 @@
-package x
diff --git a/libgo/go/cmd/go/testdata/testvendor/src/q/y/y.go b/libgo/go/cmd/go/testdata/testvendor/src/q/y/y.go
deleted file mode 100644
index 4f84223..0000000
--- a/libgo/go/cmd/go/testdata/testvendor/src/q/y/y.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package y
-
-import _ "x"
diff --git a/libgo/go/cmd/go/testdata/testvendor/src/q/z/z.go b/libgo/go/cmd/go/testdata/testvendor/src/q/z/z.go
deleted file mode 100644
index a8d4924..0000000
--- a/libgo/go/cmd/go/testdata/testvendor/src/q/z/z.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package z
-
-import _ "q/vendor/x"
diff --git a/libgo/go/cmd/go/testdata/testvendor2/src/p/p.go b/libgo/go/cmd/go/testdata/testvendor2/src/p/p.go
deleted file mode 100644
index 220b2b2..0000000
--- a/libgo/go/cmd/go/testdata/testvendor2/src/p/p.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-import "x"
diff --git a/libgo/go/cmd/go/testdata/testvendor2/vendor/x/x.go b/libgo/go/cmd/go/testdata/testvendor2/vendor/x/x.go
deleted file mode 100644
index 823aafd..0000000
--- a/libgo/go/cmd/go/testdata/testvendor2/vendor/x/x.go
+++ /dev/null
@@ -1 +0,0 @@
-package x
diff --git a/libgo/go/cmd/go/testdata/timeoutbench_test.go b/libgo/go/cmd/go/testdata/timeoutbench_test.go
deleted file mode 100644
index 57a8888..0000000
--- a/libgo/go/cmd/go/testdata/timeoutbench_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package timeoutbench_test
-
-import (
- "testing"
- "time"
-)
-
-func BenchmarkSleep1s(b *testing.B) {
- time.Sleep(1 * time.Second)
-}
diff --git a/libgo/go/cmd/go/vendor_test.go b/libgo/go/cmd/go/vendor_test.go
deleted file mode 100644
index 8b67de0..0000000
--- a/libgo/go/cmd/go/vendor_test.go
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Tests for vendoring semantics.
-
-package main_test
-
-import (
- "bytes"
- "fmt"
- "internal/testenv"
- "os"
- "path/filepath"
- "regexp"
- "strings"
- "testing"
-)
-
-func TestVendorImports(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...", "vend/vendor/...", "vend/x/vendor/...")
- want := `
- vend [vend/vendor/p r]
- vend/dir1 []
- vend/hello [fmt vend/vendor/strings]
- vend/subdir [vend/vendor/p r]
- vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2]
- vend/x/invalid [vend/x/invalid/vendor/foo]
- vend/vendor/p []
- vend/vendor/q []
- vend/vendor/strings []
- vend/vendor/vend/dir1/dir2 []
- vend/x/vendor/p []
- vend/x/vendor/p/p [notfound]
- vend/x/vendor/r []
- `
- want = strings.ReplaceAll(want+"\t", "\n\t\t", "\n")
- want = strings.TrimPrefix(want, "\n")
-
- have := tg.stdout.String()
-
- if have != want {
- t.Errorf("incorrect go list output:\n%s", diffSortedOutputs(have, want))
- }
-}
-
-func TestVendorBuild(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("build", "vend/x")
-}
-
-func TestVendorRun(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
- tg.run("run", "hello.go")
- tg.grepStdout("hello, world", "missing hello world output")
-}
-
-func TestVendorGOPATH(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- changeVolume := func(s string, f func(s string) string) string {
- vol := filepath.VolumeName(s)
- return f(vol) + s[len(vol):]
- }
- gopath := changeVolume(filepath.Join(tg.pwd(), "testdata"), strings.ToLower)
- tg.setenv("GOPATH", gopath)
- cd := changeVolume(filepath.Join(tg.pwd(), "testdata/src/vend/hello"), strings.ToUpper)
- tg.cd(cd)
- tg.run("run", "hello.go")
- tg.grepStdout("hello, world", "missing hello world output")
-}
-
-func TestVendorTest(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.cd(filepath.Join(tg.pwd(), "testdata/src/vend/hello"))
- tg.run("test", "-v")
- tg.grepStdout("TestMsgInternal", "missing use in internal test")
- tg.grepStdout("TestMsgExternal", "missing use in external test")
-}
-
-func TestVendorInvalid(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- tg.runFail("build", "vend/x/invalid")
- tg.grepStderr("must be imported as foo", "missing vendor import error")
-}
-
-func TestVendorImportError(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- tg.runFail("build", "vend/x/vendor/p/p")
-
- re := regexp.MustCompile(`cannot find package "notfound" in any of:
- .*[\\/]testdata[\\/]src[\\/]vend[\\/]x[\\/]vendor[\\/]notfound \(vendor tree\)
- .*[\\/]testdata[\\/]src[\\/]vend[\\/]vendor[\\/]notfound
- .*[\\/]src[\\/]notfound \(from \$GOROOT\)
- .*[\\/]testdata[\\/]src[\\/]notfound \(from \$GOPATH\)`)
-
- if !re.MatchString(tg.stderr.String()) {
- t.Errorf("did not find expected search list in error text")
- }
-}
-
-// diffSortedOutput prepares a diff of the already sorted outputs haveText and wantText.
-// The diff shows common lines prefixed by a tab, lines present only in haveText
-// prefixed by "unexpected: ", and lines present only in wantText prefixed by "missing: ".
-func diffSortedOutputs(haveText, wantText string) string {
- var diff bytes.Buffer
- have := splitLines(haveText)
- want := splitLines(wantText)
- for len(have) > 0 || len(want) > 0 {
- if len(want) == 0 || len(have) > 0 && have[0] < want[0] {
- fmt.Fprintf(&diff, "unexpected: %s\n", have[0])
- have = have[1:]
- continue
- }
- if len(have) == 0 || len(want) > 0 && want[0] < have[0] {
- fmt.Fprintf(&diff, "missing: %s\n", want[0])
- want = want[1:]
- continue
- }
- fmt.Fprintf(&diff, "\t%s\n", want[0])
- want = want[1:]
- have = have[1:]
- }
- return diff.String()
-}
-
-func splitLines(s string) []string {
- x := strings.Split(s, "\n")
- if x[len(x)-1] == "" {
- x = x[:len(x)-1]
- }
- return x
-}
-
-func TestVendorGet(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.tempFile("src/v/m.go", `
- package main
- import ("fmt"; "vendor.org/p")
- func main() {
- fmt.Println(p.C)
- }`)
- tg.tempFile("src/v/m_test.go", `
- package main
- import ("fmt"; "testing"; "vendor.org/p")
- func TestNothing(t *testing.T) {
- fmt.Println(p.C)
- }`)
- tg.tempFile("src/v/vendor/vendor.org/p/p.go", `
- package p
- const C = 1`)
- tg.setenv("GOPATH", tg.path("."))
- tg.cd(tg.path("src/v"))
- tg.run("run", "m.go")
- tg.run("test")
- tg.run("list", "-f", "{{.Imports}}")
- tg.grepStdout("v/vendor/vendor.org/p", "import not in vendor directory")
- tg.run("list", "-f", "{{.TestImports}}")
- tg.grepStdout("v/vendor/vendor.org/p", "test import not in vendor directory")
- tg.run("get", "-d")
- tg.run("get", "-t", "-d")
-}
-
-func TestVendorGetUpdate(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "github.com/rsc/go-get-issue-11864")
- tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
-}
-
-func TestVendorGetU(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
-}
-
-func TestVendorGetTU(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "-t", "-u", "github.com/rsc/go-get-issue-11864/...")
-}
-
-func TestVendorGetBadVendor(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- for _, suffix := range []string{"bad/imp", "bad/imp2", "bad/imp3", "..."} {
- t.Run(suffix, func(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.runFail("get", "-t", "-u", "github.com/rsc/go-get-issue-18219/"+suffix)
- tg.grepStderr("must be imported as", "did not find error about vendor import")
- tg.mustNotExist(tg.path("src/github.com/rsc/vendor"))
- })
- }
-}
-
-func TestGetSubmodules(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "-d", "github.com/rsc/go-get-issue-12612")
- tg.run("get", "-u", "-d", "github.com/rsc/go-get-issue-12612")
- tg.mustExist(tg.path("src/github.com/rsc/go-get-issue-12612/vendor/golang.org/x/crypto/.git"))
-}
-
-func TestVendorCache(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor"))
- tg.runFail("build", "p")
- tg.grepStderr("must be imported as x", "did not fail to build p")
-}
-
-func TestVendorTest2(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "github.com/rsc/go-get-issue-11864")
-
- // build -i should work
- tg.run("build", "-i", "github.com/rsc/go-get-issue-11864")
- tg.run("build", "-i", "github.com/rsc/go-get-issue-11864/t")
-
- // test -i should work like build -i (golang.org/issue/11988)
- tg.run("test", "-i", "github.com/rsc/go-get-issue-11864")
- tg.run("test", "-i", "github.com/rsc/go-get-issue-11864/t")
-
- // test should work too
- tg.run("test", "github.com/rsc/go-get-issue-11864")
- tg.run("test", "github.com/rsc/go-get-issue-11864/t")
-
- // external tests should observe internal test exports (golang.org/issue/11977)
- tg.run("test", "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2")
-}
-
-func TestVendorTest3(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "github.com/clsung/go-vendor-issue-14613")
-
- tg.run("build", "-o", tg.path("a.out"), "-i", "github.com/clsung/go-vendor-issue-14613")
-
- // test folder should work
- tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613")
- tg.run("test", "github.com/clsung/go-vendor-issue-14613")
-
- // test with specified _test.go should work too
- tg.cd(filepath.Join(tg.path("."), "src"))
- tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor_test.go")
- tg.run("test", "github.com/clsung/go-vendor-issue-14613/vendor_test.go")
-
- // test with imported and not used
- tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go")
- tg.runFail("test", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go")
- tg.grepStderr("imported and not used:", `should say "imported and not used"`)
-}
-
-func TestVendorList(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("."))
- tg.run("get", "github.com/rsc/go-get-issue-11864")
-
- tg.run("list", "-f", `{{join .TestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/t")
- tg.grepStdout("go-get-issue-11864/vendor/vendor.org/p", "did not find vendor-expanded p")
-
- tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/tx")
- tg.grepStdout("go-get-issue-11864/vendor/vendor.org/p", "did not find vendor-expanded p")
-
- tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2")
- tg.grepStdout("go-get-issue-11864/vendor/vendor.org/tx2", "did not find vendor-expanded tx2")
-
- tg.run("list", "-f", `{{join .XTestImports "\n"}}`, "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx3")
- tg.grepStdout("go-get-issue-11864/vendor/vendor.org/tx3", "did not find vendor-expanded tx3")
-}
-
-func TestVendor12156(t *testing.T) {
- // Former index out of range panic.
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/testvendor2"))
- tg.cd(filepath.Join(tg.pwd(), "testdata/testvendor2/src/p"))
- tg.runFail("build", "p.go")
- tg.grepStderrNot("panic", "panicked")
- tg.grepStderr(`cannot find package "x"`, "wrong error")
-}
-
-// Module legacy support does path rewriting very similar to vendoring.
-
-func TestLegacyMod(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/modlegacy"))
- tg.run("list", "-f", "{{.Imports}}", "old/p1")
- tg.grepStdout("new/p1", "old/p1 should import new/p1")
- tg.run("list", "-f", "{{.Imports}}", "new/p1")
- tg.grepStdout("new/p2", "new/p1 should import new/p2 (not new/v2/p2)")
- tg.grepStdoutNot("new/v2", "new/p1 should NOT import new/v2*")
- tg.grepStdout("new/sub/x/v1/y", "new/p1 should import new/sub/x/v1/y (not new/sub/v2/x/v1/y)")
- tg.grepStdoutNot("new/sub/v2", "new/p1 should NOT import new/sub/v2*")
- tg.grepStdout("new/sub/inner/x", "new/p1 should import new/sub/inner/x (no rewrites)")
- tg.run("build", "old/p1", "new/p1")
-}
-
-func TestLegacyModGet(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
- testenv.MustHaveExecPath(t, "git")
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOPATH", tg.path("d1"))
- tg.run("get", "vcs-test.golang.org/git/modlegacy1-old.git/p1")
- tg.run("list", "-f", "{{.Deps}}", "vcs-test.golang.org/git/modlegacy1-old.git/p1")
- tg.grepStdout("new.git/p2", "old/p1 should depend on new/p2")
- tg.grepStdoutNot("new.git/v2/p2", "old/p1 should NOT depend on new/v2/p2")
- tg.run("build", "vcs-test.golang.org/git/modlegacy1-old.git/p1", "vcs-test.golang.org/git/modlegacy1-new.git/p1")
-
- tg.setenv("GOPATH", tg.path("d2"))
-
- tg.must(os.RemoveAll(tg.path("d2")))
- tg.run("get", "github.com/rsc/vgotest5")
- tg.run("get", "github.com/rsc/vgotest4")
- tg.run("get", "github.com/myitcv/vgo_example_compat")
-
- if testing.Short() {
- return
- }
-
- tg.must(os.RemoveAll(tg.path("d2")))
- tg.run("get", "github.com/rsc/vgotest4")
- tg.run("get", "github.com/rsc/vgotest5")
- tg.run("get", "github.com/myitcv/vgo_example_compat")
-
- tg.must(os.RemoveAll(tg.path("d2")))
- tg.run("get", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5")
- tg.run("get", "github.com/myitcv/vgo_example_compat")
-
- tg.must(os.RemoveAll(tg.path("d2")))
- tg.run("get", "github.com/rsc/vgotest5", "github.com/rsc/vgotest4")
- tg.run("get", "github.com/myitcv/vgo_example_compat")
-
- tg.must(os.RemoveAll(tg.path("d2")))
- tg.run("get", "github.com/myitcv/vgo_example_compat")
- tg.run("get", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5")
-
- pkgs := []string{"github.com/myitcv/vgo_example_compat", "github.com/rsc/vgotest4", "github.com/rsc/vgotest5"}
- for i := 0; i < 3; i++ {
- for j := 0; j < 3; j++ {
- for k := 0; k < 3; k++ {
- if i == j || i == k || k == j {
- continue
- }
- tg.must(os.RemoveAll(tg.path("d2")))
- tg.run("get", pkgs[i], pkgs[j], pkgs[k])
- }
- }
- }
-}
diff --git a/libgo/go/cmd/gofmt/gofmt.go b/libgo/go/cmd/gofmt/gofmt.go
index 9e472b2..8c56af7 100644
--- a/libgo/go/cmd/gofmt/gofmt.go
+++ b/libgo/go/cmd/gofmt/gofmt.go
@@ -37,9 +37,16 @@ var (
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file")
)
+// Keep these in sync with go/format/format.go.
const (
tabWidth = 8
- printerMode = printer.UseSpaces | printer.TabIndent
+ printerMode = printer.UseSpaces | printer.TabIndent | printerNormalizeNumbers
+
+ // printerNormalizeNumbers means to canonicalize number literal prefixes
+ // and exponents while printing. See https://golang.org/doc/go1.13#gofmt.
+ //
+ // This value is defined in go/printer specifically for go/format and cmd/gofmt.
+ printerNormalizeNumbers = 1 << 30
)
var (
@@ -113,8 +120,6 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
simplify(file)
}
- ast.Inspect(file, normalizeNumbers)
-
res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth})
if err != nil {
return err
@@ -294,56 +299,3 @@ func backupFile(filename string, data []byte, perm os.FileMode) (string, error)
return bakname, err
}
-
-// normalizeNumbers rewrites base prefixes and exponents to
-// use lower-case letters, and removes leading 0's from
-// integer imaginary literals. It leaves hexadecimal digits
-// alone.
-func normalizeNumbers(n ast.Node) bool {
- lit, _ := n.(*ast.BasicLit)
- if lit == nil || (lit.Kind != token.INT && lit.Kind != token.FLOAT && lit.Kind != token.IMAG) {
- return true
- }
- if len(lit.Value) < 2 {
- return false // only one digit (common case) - nothing to do
- }
- // len(lit.Value) >= 2
-
- // We ignore lit.Kind because for lit.Kind == token.IMAG the literal may be an integer
- // or floating-point value, decimal or not. Instead, just consider the literal pattern.
- x := lit.Value
- switch x[:2] {
- default:
- // 0-prefix octal, decimal int, or float (possibly with 'i' suffix)
- if i := strings.LastIndexByte(x, 'E'); i >= 0 {
- x = x[:i] + "e" + x[i+1:]
- break
- }
- // remove leading 0's from integer (but not floating-point) imaginary literals
- if x[len(x)-1] == 'i' && strings.IndexByte(x, '.') < 0 && strings.IndexByte(x, 'e') < 0 {
- x = strings.TrimLeft(x, "0_")
- if x == "i" {
- x = "0i"
- }
- }
- case "0X":
- x = "0x" + x[2:]
- fallthrough
- case "0x":
- // possibly a hexadecimal float
- if i := strings.LastIndexByte(x, 'P'); i >= 0 {
- x = x[:i] + "p" + x[i+1:]
- }
- case "0O":
- x = "0o" + x[2:]
- case "0o":
- // nothing to do
- case "0B":
- x = "0b" + x[2:]
- case "0b":
- // nothing to do
- }
-
- lit.Value = x
- return false
-}
diff --git a/libgo/go/cmd/gofmt/internal.go b/libgo/go/cmd/gofmt/internal.go
index cbc6983..058158a 100644
--- a/libgo/go/cmd/gofmt/internal.go
+++ b/libgo/go/cmd/gofmt/internal.go
@@ -37,14 +37,14 @@ func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
// If this is a declaration list, make it a source file
// by inserting a package clause.
- // Insert using a ;, not a newline, so that the line numbers
+ // Insert using a ';', not a newline, so that the line numbers
// in psrc match the ones in src.
psrc := append([]byte("package p;"), src...)
file, err = parser.ParseFile(fset, filename, psrc, parserMode)
if err == nil {
sourceAdj = func(src []byte, indent int) []byte {
// Remove the package clause.
- // Gofmt has turned the ; into a \n.
+ // Gofmt has turned the ';' into a '\n'.
src = src[indent+len("package p\n"):]
return bytes.TrimSpace(src)
}
@@ -60,7 +60,7 @@ func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
// If this is a statement list, make it a source file
// by inserting a package clause and turning the list
// into a function body. This handles expressions too.
- // Insert using a ;, not a newline, so that the line numbers
+ // Insert using a ';', not a newline, so that the line numbers
// in fsrc match the ones in src. Add an extra '\n' before the '}'
// to make sure comments are flushed before the '}'.
fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '\n', '}')
@@ -72,7 +72,7 @@ func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
indent = 0
}
// Remove the wrapping.
- // Gofmt has turned the ; into a \n\n.
+ // Gofmt has turned the "; " into a "\n\n".
// There will be two non-blank lines with indent, hence 2*indent.
src = src[2*indent+len("package p\n\nfunc _() {"):]
// Remove only the "}\n" suffix: remaining whitespaces will be trimmed anyway
diff --git a/libgo/go/cmd/internal/objabi/autotype.go b/libgo/go/cmd/internal/objabi/autotype.go
index 1b46b0f..f9d17a3 100644
--- a/libgo/go/cmd/internal/objabi/autotype.go
+++ b/libgo/go/cmd/internal/objabi/autotype.go
@@ -1,5 +1,5 @@
// Derived from Inferno utils/6l/l.h and related files.
-// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
+// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
diff --git a/libgo/go/cmd/internal/objabi/funcdata.go b/libgo/go/cmd/internal/objabi/funcdata.go
index 08b75eb..d5bacb5 100644
--- a/libgo/go/cmd/internal/objabi/funcdata.go
+++ b/libgo/go/cmd/internal/objabi/funcdata.go
@@ -11,13 +11,14 @@ package objabi
// ../../../runtime/symtab.go.
const (
- PCDATA_RegMapIndex = 0
+ PCDATA_RegMapIndex = 0 // if !go115ReduceLiveness
+ PCDATA_UnsafePoint = 0 // if go115ReduceLiveness
PCDATA_StackMapIndex = 1
PCDATA_InlTreeIndex = 2
FUNCDATA_ArgsPointerMaps = 0
FUNCDATA_LocalsPointerMaps = 1
- FUNCDATA_RegPointerMaps = 2
+ FUNCDATA_RegPointerMaps = 2 // if !go115ReduceLiveness
FUNCDATA_StackObjects = 3
FUNCDATA_InlTree = 4
FUNCDATA_OpenCodedDeferInfo = 5
@@ -28,3 +29,26 @@ const (
// This value is generated by the compiler, assembler, or linker.
ArgsSizeUnknown = -0x80000000
)
+
+// Special PCDATA values.
+const (
+ // PCDATA_RegMapIndex values.
+ //
+ // Only if !go115ReduceLiveness.
+ PCDATA_RegMapUnsafe = -2 // Unsafe for async preemption
+
+ // PCDATA_UnsafePoint values.
+ PCDATA_UnsafePointSafe = -1 // Safe for async preemption
+ PCDATA_UnsafePointUnsafe = -2 // Unsafe for async preemption
+
+ // PCDATA_Restart1(2) apply on a sequence of instructions, within
+ // which if an async preemption happens, we should back off the PC
+ // to the start of the sequence when resuming.
+ // We need two so we can distinguish the start/end of the sequence
+ // in case that two sequences are next to each other.
+ PCDATA_Restart1 = -3
+ PCDATA_Restart2 = -4
+
+ // Like PCDATA_Restart1, but back to function entry if async preempted.
+ PCDATA_RestartAtEntry = -5
+)
diff --git a/libgo/go/cmd/internal/objabi/head.go b/libgo/go/cmd/internal/objabi/head.go
index 6836c33..95b8db3 100644
--- a/libgo/go/cmd/internal/objabi/head.go
+++ b/libgo/go/cmd/internal/objabi/head.go
@@ -1,5 +1,5 @@
// Derived from Inferno utils/6l/l.h and related files.
-// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
+// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
diff --git a/libgo/go/cmd/internal/objabi/reloctype.go b/libgo/go/cmd/internal/objabi/reloctype.go
index dc64828..f029a3c 100644
--- a/libgo/go/cmd/internal/objabi/reloctype.go
+++ b/libgo/go/cmd/internal/objabi/reloctype.go
@@ -1,5 +1,5 @@
// Derived from Inferno utils/6l/l.h and related files.
-// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
+// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
diff --git a/libgo/go/cmd/internal/objabi/stack.go b/libgo/go/cmd/internal/objabi/stack.go
index 7320dbf..05a1d4a 100644
--- a/libgo/go/cmd/internal/objabi/stack.go
+++ b/libgo/go/cmd/internal/objabi/stack.go
@@ -18,7 +18,7 @@ const (
)
// Initialize StackGuard and StackLimit according to target system.
-var StackGuard = 896*stackGuardMultiplier() + StackSystem
+var StackGuard = 928*stackGuardMultiplier() + StackSystem
var StackLimit = StackGuard - StackSystem - StackSmall
// stackGuardMultiplier returns a multiplier to apply to the default
diff --git a/libgo/go/cmd/internal/objabi/symkind.go b/libgo/go/cmd/internal/objabi/symkind.go
index 69f1528..374aaa6 100644
--- a/libgo/go/cmd/internal/objabi/symkind.go
+++ b/libgo/go/cmd/internal/objabi/symkind.go
@@ -1,5 +1,5 @@
// Derived from Inferno utils/6l/l.h and related files.
-// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
+// https://bitbucket.org/inferno-os/inferno-os/src/master/utils/6l/l.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
diff --git a/libgo/go/cmd/internal/objabi/symkind_string.go b/libgo/go/cmd/internal/objabi/symkind_string.go
index 2b9a908..919a666 100644
--- a/libgo/go/cmd/internal/objabi/symkind_string.go
+++ b/libgo/go/cmd/internal/objabi/symkind_string.go
@@ -4,9 +4,29 @@ package objabi
import "strconv"
-const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOCSDWARFMISCSABIALIAS"
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[Sxxx-0]
+ _ = x[STEXT-1]
+ _ = x[SRODATA-2]
+ _ = x[SNOPTRDATA-3]
+ _ = x[SDATA-4]
+ _ = x[SBSS-5]
+ _ = x[SNOPTRBSS-6]
+ _ = x[STLSBSS-7]
+ _ = x[SDWARFINFO-8]
+ _ = x[SDWARFRANGE-9]
+ _ = x[SDWARFLOC-10]
+ _ = x[SDWARFLINES-11]
+ _ = x[SABIALIAS-12]
+ _ = x[SLIBFUZZER_EXTRA_COUNTER-13]
+}
+
+const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOCSDWARFLINESSABIALIASSLIBFUZZER_EXTRA_COUNTER"
-var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81, 91, 100}
+var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81, 92, 101, 125}
func (i SymKind) String() string {
if i >= SymKind(len(_SymKind_index)-1) {
diff --git a/libgo/go/cmd/internal/objabi/util.go b/libgo/go/cmd/internal/objabi/util.go
index 0e7693e..30d9ac5 100644
--- a/libgo/go/cmd/internal/objabi/util.go
+++ b/libgo/go/cmd/internal/objabi/util.go
@@ -25,6 +25,7 @@ var (
GOARCH = envOr("GOARCH", defaultGOARCH)
GOOS = envOr("GOOS", defaultGOOS)
GO386 = envOr("GO386", defaultGO386)
+ GOAMD64 = goamd64()
GOARM = goarm()
GOMIPS = gomips()
GOMIPS64 = gomips64()
@@ -36,9 +37,15 @@ var (
const (
ElfRelocOffset = 256
- MachoRelocOffset = 2048 // reserve enough space for ELF relocations
+ MachoRelocOffset = 2048 // reserve enough space for ELF relocations
+ Go115AMD64 = "alignedjumps" // Should be "alignedjumps" or "normaljumps"; this replaces environment variable introduced in CL 219357.
)
+// TODO(1.16): assuming no issues in 1.15 release, remove this and related constant.
+func goamd64() string {
+ return Go115AMD64
+}
+
func goarm() int {
switch v := envOr("GOARM", defaultGOARM); v {
case "5":
@@ -127,7 +134,7 @@ func init() {
}
func Framepointer_enabled(goos, goarch string) bool {
- return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && goos == "linux")
+ return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && (goos == "linux" || goos == "darwin"))
}
func addexp(s string) {
@@ -152,9 +159,10 @@ func addexp(s string) {
}
var (
- framepointer_enabled int = 1
- Fieldtrack_enabled int
- Preemptibleloops_enabled int
+ framepointer_enabled int = 1
+ Fieldtrack_enabled int
+ Preemptibleloops_enabled int
+ Staticlockranking_enabled int
)
// Toolchain experiments.
@@ -168,6 +176,7 @@ var exper = []struct {
{"fieldtrack", &Fieldtrack_enabled},
{"framepointer", &framepointer_enabled},
{"preemptibleloops", &Preemptibleloops_enabled},
+ {"staticlockranking", &Staticlockranking_enabled},
}
var defaultExpstring = Expstring()
diff --git a/libgo/go/cmd/internal/sys/supported.go b/libgo/go/cmd/internal/sys/supported.go
index 02f833e..c27b3b9 100644
--- a/libgo/go/cmd/internal/sys/supported.go
+++ b/libgo/go/cmd/internal/sys/supported.go
@@ -35,9 +35,11 @@ func MSanSupported(goos, goarch string) bool {
func MustLinkExternal(goos, goarch string) bool {
switch goos {
case "android":
- return true
+ if goarch != "arm64" {
+ return true
+ }
case "darwin":
- if goarch == "arm" || goarch == "arm64" {
+ if goarch == "arm64" {
return true
}
}
@@ -67,7 +69,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool {
case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x",
"android/amd64", "android/arm", "android/arm64", "android/386",
"freebsd/amd64",
- "darwin/amd64", "darwin/386",
+ "darwin/amd64",
"windows/amd64", "windows/386":
return true
}
@@ -85,7 +87,8 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool {
"android/amd64", "android/arm", "android/arm64", "android/386",
"freebsd/amd64",
"darwin/amd64",
- "aix/ppc64":
+ "aix/ppc64",
+ "windows/386", "windows/amd64", "windows/arm":
return true
}
return false
diff --git a/libgo/go/cmd/vet/main.go b/libgo/go/cmd/vet/main.go
index 2a4f929..6381de8 100644
--- a/libgo/go/cmd/vet/main.go
+++ b/libgo/go/cmd/vet/main.go
@@ -15,12 +15,14 @@ import (
"golang.org/x/tools/go/analysis/passes/copylock"
"golang.org/x/tools/go/analysis/passes/errorsas"
"golang.org/x/tools/go/analysis/passes/httpresponse"
+ "golang.org/x/tools/go/analysis/passes/ifaceassert"
"golang.org/x/tools/go/analysis/passes/loopclosure"
"golang.org/x/tools/go/analysis/passes/lostcancel"
"golang.org/x/tools/go/analysis/passes/nilfunc"
"golang.org/x/tools/go/analysis/passes/printf"
"golang.org/x/tools/go/analysis/passes/shift"
"golang.org/x/tools/go/analysis/passes/stdmethods"
+ "golang.org/x/tools/go/analysis/passes/stringintconv"
"golang.org/x/tools/go/analysis/passes/structtag"
"golang.org/x/tools/go/analysis/passes/tests"
"golang.org/x/tools/go/analysis/passes/unmarshal"
@@ -43,12 +45,14 @@ func main() {
copylock.Analyzer,
errorsas.Analyzer,
httpresponse.Analyzer,
+ ifaceassert.Analyzer,
loopclosure.Analyzer,
lostcancel.Analyzer,
nilfunc.Analyzer,
printf.Analyzer,
shift.Analyzer,
stdmethods.Analyzer,
+ stringintconv.Analyzer,
structtag.Analyzer,
tests.Analyzer,
unmarshal.Analyzer,