mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-15 10:20:39 +08:00
libgo: update to Go 1.13beta1 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/193497 From-SVN: r275473
This commit is contained in:
parent
920ea3b8ba
commit
aa8901e9bb
@ -1,4 +1,4 @@
|
||||
ca0fdb4c7735a648b8f10f1248631adf9afb8454
|
||||
8f2b844acda70330f7c50b360f8c983d2676ecbb
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-09-06 Ian Lance Taylor <iant@golang.org>
|
||||
|
||||
* go.test/test/fixedbugs/bug369.go: Update to match libgo update
|
||||
to Go 1.13beta1.
|
||||
|
||||
2019-09-06 David Edelsohn <dje.gcc@gmail.com>
|
||||
|
||||
* gcc.dg/torture/inf-compare-1.c: Skip AIX.
|
||||
|
@ -38,6 +38,7 @@ func BenchmarkSlowNonASCII(b *testing.B) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
testing.Init()
|
||||
os.Args = []string{os.Args[0], "-test.benchtime=100ms"}
|
||||
flag.Parse()
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
2019-09-06 Ian Lance Taylor <iant@golang.org>
|
||||
|
||||
* Makefile.am (check-carchive-test): Just run "go test", not "go
|
||||
test carchive_test.go".
|
||||
* Makefile.in: Regenerate.
|
||||
|
||||
2019-05-27 Ian Lance Taylor <iant@golang.org>
|
||||
|
||||
* Makefile.am (check-go-tool): Only chmod check-go-dir if it
|
||||
|
@ -248,7 +248,7 @@ check-runtime: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc
|
||||
$(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles="$${files}" $(GOTESTFLAGS) -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v >> runtime-testlog 2>&1 || echo "--- $${fl}: go test runtime (0.00s)" >> runtime-testlog
|
||||
grep '^--- ' runtime-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
|
||||
|
||||
# check-cgo-test runs `go test misc/cgo/test` in our environment.
|
||||
# check-cgo-test runs `go test` in misc/cgo/test.
|
||||
check-cgo-test: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc
|
||||
rm -rf cgo-test-dir cgo-testlog
|
||||
$(MKDIR_P) cgo-test-dir/misc/cgo
|
||||
@ -261,18 +261,18 @@ check-cgo-test: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc
|
||||
(cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v) >> cgo-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/test (0.00s)" >> cgo-testlog
|
||||
grep '^--- ' cgo-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
|
||||
|
||||
# check-carchive-test runs `go test misc/cgo/testcarchive/carchive_test.go`
|
||||
# check-carchive-test runs `go test` in misc/cgo/testcarchive.
|
||||
# in our environment.
|
||||
check-carchive-test: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc
|
||||
rm -rf carchive-test-dir carchive-testlog
|
||||
$(MKDIR_P) carchive-test-dir/misc/cgo
|
||||
cp -r $(libgomiscdir)/cgo/testcarchive carchive-test-dir/misc/cgo/
|
||||
@abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
|
||||
echo "cd carchive-test-dir/misc/cgo/testcarchive && $(ECHO_ENV) LIBRARY_PATH=`echo $${abs_libgodir}/.libs` $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v carchive_test.go" > carchive-testlog
|
||||
echo "cd carchive-test-dir/misc/cgo/testcarchive && $(ECHO_ENV) LIBRARY_PATH=`echo $${abs_libgodir}/.libs` $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v" > carchive-testlog
|
||||
$(CHECK_ENV) \
|
||||
LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
|
||||
export LIBRARY_PATH; \
|
||||
(cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v carchive_test.go) >> carchive-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/testcarchive (0.00s)" >> carchive-testlog
|
||||
(cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v) >> carchive-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/testcarchive (0.00s)" >> carchive-testlog
|
||||
grep '^--- ' carchive-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
|
||||
|
||||
# check-vet runs `go test cmd/vet` in our environment.
|
||||
|
@ -919,7 +919,7 @@ mostlyclean-local:
|
||||
@NATIVE_TRUE@ $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles="$${files}" $(GOTESTFLAGS) -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v >> runtime-testlog 2>&1 || echo "--- $${fl}: go test runtime (0.00s)" >> runtime-testlog
|
||||
@NATIVE_TRUE@ grep '^--- ' runtime-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
|
||||
|
||||
# check-cgo-test runs `go test misc/cgo/test` in our environment.
|
||||
# check-cgo-test runs `go test` in misc/cgo/test.
|
||||
@NATIVE_TRUE@check-cgo-test: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc
|
||||
@NATIVE_TRUE@ rm -rf cgo-test-dir cgo-testlog
|
||||
@NATIVE_TRUE@ $(MKDIR_P) cgo-test-dir/misc/cgo
|
||||
@ -932,18 +932,18 @@ mostlyclean-local:
|
||||
@NATIVE_TRUE@ (cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v) >> cgo-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/test (0.00s)" >> cgo-testlog
|
||||
@NATIVE_TRUE@ grep '^--- ' cgo-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
|
||||
|
||||
# check-carchive-test runs `go test misc/cgo/testcarchive/carchive_test.go`
|
||||
# check-carchive-test runs `go test` in misc/cgo/testcarchive.
|
||||
# in our environment.
|
||||
@NATIVE_TRUE@check-carchive-test: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc
|
||||
@NATIVE_TRUE@ rm -rf carchive-test-dir carchive-testlog
|
||||
@NATIVE_TRUE@ $(MKDIR_P) carchive-test-dir/misc/cgo
|
||||
@NATIVE_TRUE@ cp -r $(libgomiscdir)/cgo/testcarchive carchive-test-dir/misc/cgo/
|
||||
@NATIVE_TRUE@ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
|
||||
@NATIVE_TRUE@ echo "cd carchive-test-dir/misc/cgo/testcarchive && $(ECHO_ENV) LIBRARY_PATH=`echo $${abs_libgodir}/.libs` $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v carchive_test.go" > carchive-testlog
|
||||
@NATIVE_TRUE@ echo "cd carchive-test-dir/misc/cgo/testcarchive && $(ECHO_ENV) LIBRARY_PATH=`echo $${abs_libgodir}/.libs` $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v" > carchive-testlog
|
||||
@NATIVE_TRUE@ $(CHECK_ENV) \
|
||||
@NATIVE_TRUE@ LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
|
||||
@NATIVE_TRUE@ export LIBRARY_PATH; \
|
||||
@NATIVE_TRUE@ (cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v carchive_test.go) >> carchive-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/testcarchive (0.00s)" >> carchive-testlog
|
||||
@NATIVE_TRUE@ (cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v) >> carchive-testlog 2>&1 || echo "--- $${fl}: go test misc/cgo/testcarchive (0.00s)" >> carchive-testlog
|
||||
@NATIVE_TRUE@ grep '^--- ' carchive-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/' | sort -k 2
|
||||
|
||||
# check-vet runs `go test cmd/vet` in our environment.
|
||||
|
@ -1,4 +1,4 @@
|
||||
ac02fdec7cd16ea8d3de1fc33def9cfabec5170d
|
||||
60f14fddfee107dedd76c0be6b422a3d8ccc841a
|
||||
|
||||
The first line of this file holds the git revision number of the
|
||||
last merge done from the master library sources.
|
||||
|
@ -187,6 +187,7 @@ toolexeclibgocrypto_DATA = \
|
||||
crypto/des.gox \
|
||||
crypto/dsa.gox \
|
||||
crypto/ecdsa.gox \
|
||||
crypto/ed25519.gox \
|
||||
crypto/elliptic.gox \
|
||||
crypto/hmac.gox \
|
||||
crypto/md5.gox \
|
||||
@ -399,8 +400,7 @@ toolexeclibgounicode_DATA = \
|
||||
# internal packages nothing will explicitly depend on them.
|
||||
# Force them to be built.
|
||||
noinst_DATA = \
|
||||
internal/x/net/internal/nettest.gox \
|
||||
internal/x/net/nettest.gox \
|
||||
golang.org/x/net/nettest.gox \
|
||||
internal/testenv.gox \
|
||||
internal/trace.gox \
|
||||
net/internal/socktest.gox \
|
||||
@ -482,7 +482,6 @@ s-version: Makefile
|
||||
echo " BigEndian = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) bigendian`" >> version.go.tmp
|
||||
echo " CacheLineSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) cachelinesize`" >> version.go.tmp
|
||||
echo " DefaultPhysPageSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) defaultphyspagesize`" >> version.go.tmp
|
||||
echo " HugePageSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) hugepagesize`" >> version.go.tmp
|
||||
echo " Int64Align = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) int64align`" >> version.go.tmp
|
||||
echo " MinFrameSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) minframesize`" >> version.go.tmp
|
||||
echo " PCQuantum = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) pcquantum`" >> version.go.tmp
|
||||
@ -516,14 +515,16 @@ s-objabi: Makefile
|
||||
rm -f objabi.go.tmp
|
||||
echo "package objabi" > objabi.go.tmp
|
||||
echo "import \"runtime\"" >> objabi.go.tmp
|
||||
echo 'func init() { defaultGOROOT = `$(prefix)` }' >> objabi.go.tmp
|
||||
echo 'func defaultGOROOTValue() string { return `$(prefix)` }' >> objabi.go.tmp
|
||||
echo 'const defaultGO386 = `sse2`' >> objabi.go.tmp
|
||||
echo 'const defaultGOARM = `5`' >> objabi.go.tmp
|
||||
echo 'const defaultGOMIPS = `hardfloat`' >> objabi.go.tmp
|
||||
echo 'const defaultGOMIPS64 = `hardfloat`' >> objabi.go.tmp
|
||||
echo 'const defaultGOPPC64 = `power8`' >> objabi.go.tmp
|
||||
echo 'const defaultGOOS = runtime.GOOS' >> objabi.go.tmp
|
||||
echo 'const defaultGOARCH = runtime.GOARCH' >> objabi.go.tmp
|
||||
echo 'const defaultGO_EXTLINK_ENABLED = ``' >> objabi.go.tmp
|
||||
echo 'const defaultGO_LDSO = ``' >> objabi.go.tmp
|
||||
echo 'const version = `'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'`' >> objabi.go.tmp
|
||||
echo 'const stackGuardMultiplierDefault = 1' >> objabi.go.tmp
|
||||
echo 'const goexperiment = ``' >> objabi.go.tmp
|
||||
@ -591,7 +592,7 @@ s-zstdpkglist: Makefile
|
||||
echo 'package goroot' > zstdpkglist.go.tmp
|
||||
echo "" >> zstdpkglist.go.tmp
|
||||
echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp
|
||||
echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_/]*_c\.lo||g' | sed 's|\([a-z0-9_/]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
|
||||
echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_./]*_c\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
|
||||
echo '}' >> zstdpkglist.go.tmp
|
||||
$(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
|
||||
$(STAMP) $@
|
||||
@ -692,13 +693,14 @@ libgo_go_objs = \
|
||||
syscall/errno.lo \
|
||||
syscall/signame.lo \
|
||||
syscall/wait.lo \
|
||||
$(internal_x_net_lif_lo) \
|
||||
$(internal_x_net_route_lo) \
|
||||
$(golangorg_x_net_lif_lo) \
|
||||
$(golangorg_x_net_route_lo) \
|
||||
log/syslog/syslog_c.lo \
|
||||
$(os_lib_inotify_lo) \
|
||||
runtime/internal/atomic_c.lo \
|
||||
sync/atomic_c.lo \
|
||||
internal/cpu/cpu_gccgo.lo
|
||||
internal/cpu/cpu_gccgo.lo \
|
||||
golang.org/x/sys/cpu_gccgo.lo
|
||||
|
||||
libgo_ldflags = \
|
||||
-version-info $(libtool_VERSION) $(PTHREAD_CFLAGS) $(AM_LDFLAGS)
|
||||
@ -1020,6 +1022,11 @@ internal/cpu/cpu_gccgo.lo: go/internal/cpu/cpu_gccgo.c runtime.inc
|
||||
@$(MKDIR_P) internal/cpu
|
||||
$(LTCOMPILE) -c -o $@ $(srcdir)/go/internal/cpu/cpu_gccgo.c
|
||||
|
||||
# Similarly, golang.org/x/sys/cpu needs some C code.
|
||||
golang.org/x/sys/cpu_gccgo.lo: go/golang.org/x/sys/cpu/cpu_gccgo.c runtime.inc
|
||||
@$(MKDIR_P) golang.org/x/sys
|
||||
$(LTCOMPILE) -c -o $@ $(srcdir)/go/golang.org/x/sys/cpu/cpu_gccgo.c
|
||||
|
||||
# Solaris 11.4 changed the type of fields in struct stat.
|
||||
# Use a build tag, based on a configure check, to cope.
|
||||
if LIBGO_IS_SOLARIS
|
||||
@ -1038,10 +1045,10 @@ if LIBGO_IS_BSD
|
||||
|
||||
$(eval $(call PACKAGE_template,internal/x/net/route))
|
||||
|
||||
internal_x_net_route_lo = \
|
||||
internal/x/net/route.lo
|
||||
internal_x_net_route_check = \
|
||||
internal/x/net/route/check
|
||||
golangorg_x_net_route_lo = \
|
||||
golang.org/net/route.lo
|
||||
golangorg_x_net_route_check = \
|
||||
golang.org/x/net/route/check
|
||||
|
||||
endif
|
||||
|
||||
@ -1051,17 +1058,17 @@ if LIBGO_IS_SOLARIS
|
||||
|
||||
$(eval $(call PACKAGE_template,internal/x/net/lif))
|
||||
|
||||
internal_x_net_lif_lo = \
|
||||
internal/x/net/lif.lo
|
||||
internal_x_net_lif_check = \
|
||||
internal/x/net/lif/check
|
||||
golangorg_x_net_lif_lo = \
|
||||
golang.org/x/net/lif.lo
|
||||
golangorg_x_net_lif_check = \
|
||||
golang.org/x/net/lif/check
|
||||
|
||||
endif
|
||||
|
||||
TPACKAGES = $(shell cat $(srcdir)/check-packages.txt)
|
||||
TEST_PACKAGES = $(addsuffix /check,$(TPACKAGES)) \
|
||||
$(internal_x_net_lif_check) \
|
||||
$(internal_x_net_route_check)
|
||||
$(golangorg_x_net_lif_check) \
|
||||
$(golangorg_x_net_route_check)
|
||||
|
||||
check: check-tail
|
||||
check-recursive: check-head
|
||||
|
@ -218,10 +218,10 @@ LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
|
||||
am__DEPENDENCIES_2 = $(addsuffix .lo,$(PACKAGES)) \
|
||||
internal/bytealg/bytealg.lo reflect/makefunc_ffi_c.lo \
|
||||
$(am__DEPENDENCIES_1) syscall/errno.lo syscall/signame.lo \
|
||||
syscall/wait.lo $(internal_x_net_lif_lo) \
|
||||
$(internal_x_net_route_lo) log/syslog/syslog_c.lo \
|
||||
syscall/wait.lo $(golangorg_x_net_lif_lo) \
|
||||
$(golangorg_x_net_route_lo) log/syslog/syslog_c.lo \
|
||||
runtime/internal/atomic_c.lo sync/atomic_c.lo \
|
||||
internal/cpu/cpu_gccgo.lo
|
||||
internal/cpu/cpu_gccgo.lo golang.org/x/sys/cpu_gccgo.lo
|
||||
am__DEPENDENCIES_3 =
|
||||
am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \
|
||||
../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_3) \
|
||||
@ -670,6 +670,7 @@ toolexeclibgocrypto_DATA = \
|
||||
crypto/des.gox \
|
||||
crypto/dsa.gox \
|
||||
crypto/ecdsa.gox \
|
||||
crypto/ed25519.gox \
|
||||
crypto/elliptic.gox \
|
||||
crypto/hmac.gox \
|
||||
crypto/md5.gox \
|
||||
@ -854,8 +855,7 @@ toolexeclibgounicode_DATA = \
|
||||
# Some packages are only needed for tests, so unlike the other
|
||||
# internal packages nothing will explicitly depend on them.
|
||||
# Force them to be built.
|
||||
noinst_DATA = internal/x/net/internal/nettest.gox \
|
||||
internal/x/net/nettest.gox internal/testenv.gox \
|
||||
noinst_DATA = golang.org/x/net/nettest.gox internal/testenv.gox \
|
||||
internal/trace.gox net/internal/socktest.gox \
|
||||
os/signal/internal/pty.gox runtime/pprof/internal/profile.gox \
|
||||
zdefaultcc.go
|
||||
@ -915,13 +915,14 @@ libgo_go_objs = \
|
||||
syscall/errno.lo \
|
||||
syscall/signame.lo \
|
||||
syscall/wait.lo \
|
||||
$(internal_x_net_lif_lo) \
|
||||
$(internal_x_net_route_lo) \
|
||||
$(golangorg_x_net_lif_lo) \
|
||||
$(golangorg_x_net_route_lo) \
|
||||
log/syslog/syslog_c.lo \
|
||||
$(os_lib_inotify_lo) \
|
||||
runtime/internal/atomic_c.lo \
|
||||
sync/atomic_c.lo \
|
||||
internal/cpu/cpu_gccgo.lo
|
||||
internal/cpu/cpu_gccgo.lo \
|
||||
golang.org/x/sys/cpu_gccgo.lo
|
||||
|
||||
libgo_ldflags = \
|
||||
-version-info $(libtool_VERSION) $(PTHREAD_CFLAGS) $(AM_LDFLAGS)
|
||||
@ -1114,22 +1115,22 @@ extra_check_libs_cmd_vet_internal_cfg = $(abs_builddir)/libgotool.a
|
||||
# Use a build tag, based on a configure check, to cope.
|
||||
@HAVE_STAT_TIMESPEC_TRUE@@LIBGO_IS_SOLARIS_TRUE@matchargs_os = --tag=solaristag
|
||||
@LIBGO_IS_SOLARIS_FALSE@matchargs_os =
|
||||
@LIBGO_IS_BSD_TRUE@internal_x_net_route_lo = \
|
||||
@LIBGO_IS_BSD_TRUE@ internal/x/net/route.lo
|
||||
@LIBGO_IS_BSD_TRUE@golangorg_x_net_route_lo = \
|
||||
@LIBGO_IS_BSD_TRUE@ golang.org/net/route.lo
|
||||
|
||||
@LIBGO_IS_BSD_TRUE@internal_x_net_route_check = \
|
||||
@LIBGO_IS_BSD_TRUE@ internal/x/net/route/check
|
||||
@LIBGO_IS_BSD_TRUE@golangorg_x_net_route_check = \
|
||||
@LIBGO_IS_BSD_TRUE@ golang.org/x/net/route/check
|
||||
|
||||
@LIBGO_IS_SOLARIS_TRUE@internal_x_net_lif_lo = \
|
||||
@LIBGO_IS_SOLARIS_TRUE@ internal/x/net/lif.lo
|
||||
@LIBGO_IS_SOLARIS_TRUE@golangorg_x_net_lif_lo = \
|
||||
@LIBGO_IS_SOLARIS_TRUE@ golang.org/x/net/lif.lo
|
||||
|
||||
@LIBGO_IS_SOLARIS_TRUE@internal_x_net_lif_check = \
|
||||
@LIBGO_IS_SOLARIS_TRUE@ internal/x/net/lif/check
|
||||
@LIBGO_IS_SOLARIS_TRUE@golangorg_x_net_lif_check = \
|
||||
@LIBGO_IS_SOLARIS_TRUE@ golang.org/x/net/lif/check
|
||||
|
||||
TPACKAGES = $(shell cat $(srcdir)/check-packages.txt)
|
||||
TEST_PACKAGES = $(addsuffix /check,$(TPACKAGES)) \
|
||||
$(internal_x_net_lif_check) \
|
||||
$(internal_x_net_route_check)
|
||||
$(golangorg_x_net_lif_check) \
|
||||
$(golangorg_x_net_route_check)
|
||||
|
||||
MOSTLYCLEANFILES = \
|
||||
s-runtime_sysinfo s-sigtab s-runtime-inc s-zstdpkglist \
|
||||
@ -2597,7 +2598,6 @@ s-version: Makefile
|
||||
echo " BigEndian = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) bigendian`" >> version.go.tmp
|
||||
echo " CacheLineSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) cachelinesize`" >> version.go.tmp
|
||||
echo " DefaultPhysPageSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) defaultphyspagesize`" >> version.go.tmp
|
||||
echo " HugePageSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) hugepagesize`" >> version.go.tmp
|
||||
echo " Int64Align = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) int64align`" >> version.go.tmp
|
||||
echo " MinFrameSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) minframesize`" >> version.go.tmp
|
||||
echo " PCQuantum = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) pcquantum`" >> version.go.tmp
|
||||
@ -2631,14 +2631,16 @@ s-objabi: Makefile
|
||||
rm -f objabi.go.tmp
|
||||
echo "package objabi" > objabi.go.tmp
|
||||
echo "import \"runtime\"" >> objabi.go.tmp
|
||||
echo 'func init() { defaultGOROOT = `$(prefix)` }' >> objabi.go.tmp
|
||||
echo 'func defaultGOROOTValue() string { return `$(prefix)` }' >> objabi.go.tmp
|
||||
echo 'const defaultGO386 = `sse2`' >> objabi.go.tmp
|
||||
echo 'const defaultGOARM = `5`' >> objabi.go.tmp
|
||||
echo 'const defaultGOMIPS = `hardfloat`' >> objabi.go.tmp
|
||||
echo 'const defaultGOMIPS64 = `hardfloat`' >> objabi.go.tmp
|
||||
echo 'const defaultGOPPC64 = `power8`' >> objabi.go.tmp
|
||||
echo 'const defaultGOOS = runtime.GOOS' >> objabi.go.tmp
|
||||
echo 'const defaultGOARCH = runtime.GOARCH' >> objabi.go.tmp
|
||||
echo 'const defaultGO_EXTLINK_ENABLED = ``' >> objabi.go.tmp
|
||||
echo 'const defaultGO_LDSO = ``' >> objabi.go.tmp
|
||||
echo 'const version = `'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'`' >> objabi.go.tmp
|
||||
echo 'const stackGuardMultiplierDefault = 1' >> objabi.go.tmp
|
||||
echo 'const goexperiment = ``' >> objabi.go.tmp
|
||||
@ -2700,7 +2702,7 @@ s-zstdpkglist: Makefile
|
||||
echo 'package goroot' > zstdpkglist.go.tmp
|
||||
echo "" >> zstdpkglist.go.tmp
|
||||
echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp
|
||||
echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_/]*_c\.lo||g' | sed 's|\([a-z0-9_/]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
|
||||
echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_./]*_c\.lo||g' | sed 's|\([a-z0-9_./]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp
|
||||
echo '}' >> zstdpkglist.go.tmp
|
||||
$(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go
|
||||
$(STAMP) $@
|
||||
@ -2876,6 +2878,11 @@ internal/cpu/cpu_gccgo.lo: go/internal/cpu/cpu_gccgo.c runtime.inc
|
||||
@$(MKDIR_P) internal/cpu
|
||||
$(LTCOMPILE) -c -o $@ $(srcdir)/go/internal/cpu/cpu_gccgo.c
|
||||
|
||||
# Similarly, golang.org/x/sys/cpu needs some C code.
|
||||
golang.org/x/sys/cpu_gccgo.lo: go/golang.org/x/sys/cpu/cpu_gccgo.c runtime.inc
|
||||
@$(MKDIR_P) golang.org/x/sys
|
||||
$(LTCOMPILE) -c -o $@ $(srcdir)/go/golang.org/x/sys/cpu/cpu_gccgo.c
|
||||
|
||||
# Build internal/x/net/route only on BSD systems.
|
||||
|
||||
@LIBGO_IS_BSD_TRUE@$(eval $(call PACKAGE_template,internal/x/net/route))
|
||||
|
@ -1 +1 @@
|
||||
go1.12.2
|
||||
go1.13beta1
|
||||
|
@ -21,7 +21,6 @@ cmd/go/internal/par
|
||||
cmd/go/internal/search
|
||||
cmd/go/internal/semver
|
||||
cmd/go/internal/txtar
|
||||
cmd/go/internal/web2
|
||||
cmd/go/internal/work
|
||||
cmd/internal/buildid
|
||||
cmd/internal/edit
|
||||
@ -42,6 +41,7 @@ crypto/cipher
|
||||
crypto/des
|
||||
crypto/dsa
|
||||
crypto/ecdsa
|
||||
crypto/ed25519
|
||||
crypto/elliptic
|
||||
crypto/hmac
|
||||
crypto/internal/subtle
|
||||
@ -106,20 +106,11 @@ image/png
|
||||
index/suffixarray
|
||||
internal/cpu
|
||||
internal/fmtsort
|
||||
internal/oserror
|
||||
internal/poll
|
||||
internal/reflectlite
|
||||
internal/singleflight
|
||||
internal/trace
|
||||
internal/x/crypto/chacha20poly1305
|
||||
internal/x/crypto/cryptobyte
|
||||
internal/x/crypto/curve25519
|
||||
internal/x/crypto/hkdf
|
||||
internal/x/crypto/internal/chacha20
|
||||
internal/x/crypto/poly1305
|
||||
internal/x/net/dns/dnsmessage
|
||||
internal/x/net/http/httpguts
|
||||
internal/x/net/http/httpproxy
|
||||
internal/x/net/http2/hpack
|
||||
internal/x/net/idna
|
||||
internal/xcoff
|
||||
io
|
||||
io/ioutil
|
||||
|
4
libgo/configure
vendored
4
libgo/configure
vendored
@ -2542,7 +2542,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
ac_config_headers="$ac_config_headers config.h"
|
||||
|
||||
|
||||
libtool_VERSION=14:0:0
|
||||
libtool_VERSION=15:0:0
|
||||
|
||||
|
||||
# Default to --enable-multilib
|
||||
@ -13887,7 +13887,7 @@ go_include="-include"
|
||||
# All known GOOS values. This is the union of all operating systems
|
||||
# supported by the gofrontend and all operating systems supported by
|
||||
# the gc toolchain.
|
||||
ALLGOOS="aix android darwin dragonfly freebsd hurd irix js linux netbsd openbsd plan9 rtems solaris windows"
|
||||
ALLGOOS="aix android darwin dragonfly freebsd hurd illumos irix js linux netbsd openbsd plan9 rtems solaris windows"
|
||||
|
||||
is_darwin=no
|
||||
is_freebsd=no
|
||||
|
@ -10,7 +10,7 @@ AC_INIT(package-unused, version-unused,, libgo)
|
||||
AC_CONFIG_SRCDIR(Makefile.am)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
libtool_VERSION=14:0:0
|
||||
libtool_VERSION=15:0:0
|
||||
AC_SUBST(libtool_VERSION)
|
||||
|
||||
AM_ENABLE_MULTILIB(, ..)
|
||||
@ -154,7 +154,7 @@ AC_SUBST(go_include)
|
||||
# All known GOOS values. This is the union of all operating systems
|
||||
# supported by the gofrontend and all operating systems supported by
|
||||
# the gc toolchain.
|
||||
ALLGOOS="aix android darwin dragonfly freebsd hurd irix js linux netbsd openbsd plan9 rtems solaris windows"
|
||||
ALLGOOS="aix android darwin dragonfly freebsd hurd illumos irix js linux netbsd openbsd plan9 rtems solaris windows"
|
||||
|
||||
is_darwin=no
|
||||
is_freebsd=no
|
||||
|
@ -244,7 +244,7 @@ func formatPAXTime(ts time.Time) (s string) {
|
||||
if secs < 0 {
|
||||
sign = "-" // Remember sign
|
||||
secs = -(secs + 1) // Add a second to secs
|
||||
nsecs = -(nsecs - 1E9) // Take that second away from nsecs
|
||||
nsecs = -(nsecs - 1e9) // Take that second away from nsecs
|
||||
}
|
||||
return strings.TrimRight(fmt.Sprintf("%s%d.%09d", sign, secs, nsecs), "0")
|
||||
}
|
||||
|
@ -303,27 +303,27 @@ func TestFormatPAXTime(t *testing.T) {
|
||||
{1350244992, 300000000, "1350244992.3"},
|
||||
{1350244992, 23960100, "1350244992.0239601"},
|
||||
{1350244992, 23960108, "1350244992.023960108"},
|
||||
{+1, +1E9 - 1E0, "1.999999999"},
|
||||
{+1, +1E9 - 1E3, "1.999999"},
|
||||
{+1, +1E9 - 1E6, "1.999"},
|
||||
{+1, +0E0 - 0E0, "1"},
|
||||
{+1, +1E6 - 0E0, "1.001"},
|
||||
{+1, +1E3 - 0E0, "1.000001"},
|
||||
{+1, +1E0 - 0E0, "1.000000001"},
|
||||
{0, 1E9 - 1E0, "0.999999999"},
|
||||
{0, 1E9 - 1E3, "0.999999"},
|
||||
{0, 1E9 - 1E6, "0.999"},
|
||||
{0, 0E0, "0"},
|
||||
{0, 1E6 + 0E0, "0.001"},
|
||||
{0, 1E3 + 0E0, "0.000001"},
|
||||
{0, 1E0 + 0E0, "0.000000001"},
|
||||
{-1, -1E9 + 1E0, "-1.999999999"},
|
||||
{-1, -1E9 + 1E3, "-1.999999"},
|
||||
{-1, -1E9 + 1E6, "-1.999"},
|
||||
{-1, -0E0 + 0E0, "-1"},
|
||||
{-1, -1E6 + 0E0, "-1.001"},
|
||||
{-1, -1E3 + 0E0, "-1.000001"},
|
||||
{-1, -1E0 + 0E0, "-1.000000001"},
|
||||
{+1, +1e9 - 1e0, "1.999999999"},
|
||||
{+1, +1e9 - 1e3, "1.999999"},
|
||||
{+1, +1e9 - 1e6, "1.999"},
|
||||
{+1, +0e0 - 0e0, "1"},
|
||||
{+1, +1e6 - 0e0, "1.001"},
|
||||
{+1, +1e3 - 0e0, "1.000001"},
|
||||
{+1, +1e0 - 0e0, "1.000000001"},
|
||||
{0, 1e9 - 1e0, "0.999999999"},
|
||||
{0, 1e9 - 1e3, "0.999999"},
|
||||
{0, 1e9 - 1e6, "0.999"},
|
||||
{0, 0e0, "0"},
|
||||
{0, 1e6 + 0e0, "0.001"},
|
||||
{0, 1e3 + 0e0, "0.000001"},
|
||||
{0, 1e0 + 0e0, "0.000000001"},
|
||||
{-1, -1e9 + 1e0, "-1.999999999"},
|
||||
{-1, -1e9 + 1e3, "-1.999999"},
|
||||
{-1, -1e9 + 1e6, "-1.999"},
|
||||
{-1, -0e0 + 0e0, "-1"},
|
||||
{-1, -1e6 + 0e0, "-1.001"},
|
||||
{-1, -1e3 + 0e0, "-1.000001"},
|
||||
{-1, -1e0 + 0e0, "-1.000000001"},
|
||||
{-1350244992, 0, "-1350244992"},
|
||||
{-1350244992, -300000000, "-1350244992.3"},
|
||||
{-1350244992, -23960100, "-1350244992.0239601"},
|
||||
|
@ -154,10 +154,15 @@ func (fi headerFileInfo) Size() int64 {
|
||||
}
|
||||
return int64(fi.fh.UncompressedSize)
|
||||
}
|
||||
func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() }
|
||||
func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
|
||||
func (fi headerFileInfo) Mode() os.FileMode { return fi.fh.Mode() }
|
||||
func (fi headerFileInfo) Sys() interface{} { return fi.fh }
|
||||
func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() }
|
||||
func (fi headerFileInfo) ModTime() time.Time {
|
||||
if fi.fh.Modified.IsZero() {
|
||||
return fi.fh.ModTime()
|
||||
}
|
||||
return fi.fh.Modified.UTC()
|
||||
}
|
||||
func (fi headerFileInfo) Mode() os.FileMode { return fi.fh.Mode() }
|
||||
func (fi headerFileInfo) Sys() interface{} { return fi.fh }
|
||||
|
||||
// FileInfoHeader creates a partially-populated FileHeader from an
|
||||
// os.FileInfo.
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"internal/race"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -114,6 +113,47 @@ func TestFileHeaderRoundTrip64(t *testing.T) {
|
||||
testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t)
|
||||
}
|
||||
|
||||
func TestFileHeaderRoundTripModified(t *testing.T) {
|
||||
fh := &FileHeader{
|
||||
Name: "foo.txt",
|
||||
UncompressedSize: 987654321,
|
||||
Modified: time.Now().Local(),
|
||||
ModifiedTime: 1234,
|
||||
ModifiedDate: 5678,
|
||||
}
|
||||
fi := fh.FileInfo()
|
||||
fh2, err := FileInfoHeader(fi)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := fh2.Modified, fh.Modified.UTC(); got != want {
|
||||
t.Errorf("Modified: got %s, want %s\n", got, want)
|
||||
}
|
||||
if got, want := fi.ModTime(), fh.Modified.UTC(); got != want {
|
||||
t.Errorf("Modified: got %s, want %s\n", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileHeaderRoundTripWithoutModified(t *testing.T) {
|
||||
fh := &FileHeader{
|
||||
Name: "foo.txt",
|
||||
UncompressedSize: 987654321,
|
||||
ModifiedTime: 1234,
|
||||
ModifiedDate: 5678,
|
||||
}
|
||||
fi := fh.FileInfo()
|
||||
fh2, err := FileInfoHeader(fi)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := fh2.ModTime(), fh.ModTime(); got != want {
|
||||
t.Errorf("Modified: got %s, want %s\n", got, want)
|
||||
}
|
||||
if got, want := fi.ModTime(), fh.ModTime(); got != want {
|
||||
t.Errorf("Modified: got %s, want %s\n", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type repeatedByte struct {
|
||||
off int64
|
||||
b byte
|
||||
@ -268,7 +308,7 @@ func TestZip64EdgeCase(t *testing.T) {
|
||||
// Tests that we generate a zip64 file if the directory at offset
|
||||
// 0xFFFFFFFF, but not before.
|
||||
func TestZip64DirectoryOffset(t *testing.T) {
|
||||
if testing.Short() && race.Enabled {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping in short mode")
|
||||
}
|
||||
t.Parallel()
|
||||
@ -313,7 +353,7 @@ func TestZip64DirectoryOffset(t *testing.T) {
|
||||
|
||||
// At 16k records, we need to generate a zip64 file.
|
||||
func TestZip64ManyRecords(t *testing.T) {
|
||||
if testing.Short() && race.Enabled {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping in short mode")
|
||||
}
|
||||
t.Parallel()
|
||||
|
@ -197,6 +197,9 @@ func (b *Reader) Discard(n int) (discarded int, err error) {
|
||||
func (b *Reader) Read(p []byte) (n int, err error) {
|
||||
n = len(p)
|
||||
if n == 0 {
|
||||
if b.Buffered() > 0 {
|
||||
return 0, nil
|
||||
}
|
||||
return 0, b.readErr()
|
||||
}
|
||||
if b.r == b.w {
|
||||
|
@ -1481,6 +1481,60 @@ func newScriptedReader(steps ...func(p []byte) (n int, err error)) io.Reader {
|
||||
return &sr
|
||||
}
|
||||
|
||||
// eofReader returns the number of bytes read and io.EOF for the read that consumes the last of the content.
|
||||
type eofReader struct {
|
||||
buf []byte
|
||||
}
|
||||
|
||||
func (r *eofReader) Read(p []byte) (int, error) {
|
||||
read := copy(p, r.buf)
|
||||
r.buf = r.buf[read:]
|
||||
|
||||
switch read {
|
||||
case 0, len(r.buf):
|
||||
// As allowed in the documentation, this will return io.EOF
|
||||
// in the same call that consumes the last of the data.
|
||||
// https://godoc.org/io#Reader
|
||||
return read, io.EOF
|
||||
}
|
||||
|
||||
return read, nil
|
||||
}
|
||||
|
||||
func TestPartialReadEOF(t *testing.T) {
|
||||
src := make([]byte, 10)
|
||||
eofR := &eofReader{buf: src}
|
||||
r := NewReader(eofR)
|
||||
|
||||
// Start by reading 5 of the 10 available bytes.
|
||||
dest := make([]byte, 5)
|
||||
read, err := r.Read(dest)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if n := len(dest); read != n {
|
||||
t.Fatalf("read %d bytes; wanted %d bytes", read, n)
|
||||
}
|
||||
|
||||
// The Reader should have buffered all the content from the io.Reader.
|
||||
if n := len(eofR.buf); n != 0 {
|
||||
t.Fatalf("got %d bytes left in bufio.Reader source; want 0 bytes", n)
|
||||
}
|
||||
// To prove the point, check that there are still 5 bytes available to read.
|
||||
if n := r.Buffered(); n != 5 {
|
||||
t.Fatalf("got %d bytes buffered in bufio.Reader; want 5 bytes", n)
|
||||
}
|
||||
|
||||
// This is the second read of 0 bytes.
|
||||
read, err = r.Read([]byte{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if read != 0 {
|
||||
t.Fatalf("read %d bytes; want 0 bytes", read)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReaderCopyOptimal(b *testing.B) {
|
||||
// Optimal case is where the underlying reader implements io.WriterTo
|
||||
srcBuf := bytes.NewBuffer(make([]byte, 8192))
|
||||
|
@ -31,6 +31,19 @@ func ExampleScanner_lines() {
|
||||
}
|
||||
}
|
||||
|
||||
// Return the most recent call to Scan as a []byte.
|
||||
func ExampleScanner_Bytes() {
|
||||
scanner := bufio.NewScanner(strings.NewReader("gopher"))
|
||||
for scanner.Scan() {
|
||||
fmt.Println(len(scanner.Bytes()) == 6)
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "shouldn't see an error scanning a string")
|
||||
}
|
||||
// Output:
|
||||
// true
|
||||
}
|
||||
|
||||
// Use a Scanner to implement a simple word-count utility by scanning the
|
||||
// input as a sequence of space-delimited tokens.
|
||||
func ExampleScanner_words() {
|
||||
@ -94,6 +107,9 @@ func ExampleScanner_emptyFinalToken() {
|
||||
return i + 1, data[:i], nil
|
||||
}
|
||||
}
|
||||
if !atEOF {
|
||||
return 0, nil, nil
|
||||
}
|
||||
// There is one final token to be delivered, which may be the empty string.
|
||||
// Returning bufio.ErrFinalToken here tells Scan there are no more tokens after this
|
||||
// but does not trigger an error to be returned from Scan itself.
|
||||
|
@ -73,7 +73,7 @@ var (
|
||||
|
||||
const (
|
||||
// MaxScanTokenSize is the maximum size used to buffer a token
|
||||
// unless the user provides an explicit buffer with Scan.Buffer.
|
||||
// unless the user provides an explicit buffer with Scanner.Buffer.
|
||||
// The actual maximum token size may be smaller as the buffer
|
||||
// may need to include, for instance, a newline.
|
||||
MaxScanTokenSize = 64 * 1024
|
||||
|
@ -151,7 +151,7 @@ func delete(m map[Type]Type1, key Type)
|
||||
// Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
|
||||
// String: the number of bytes in v.
|
||||
// Channel: the number of elements queued (unread) in the channel buffer;
|
||||
// if v is nil, len(v) is zero.
|
||||
// if v is nil, len(v) is zero.
|
||||
// For some arguments, such as a string literal or a simple array expression, the
|
||||
// result can be a constant. See the Go language specification's "Length and
|
||||
// capacity" section for details.
|
||||
@ -226,10 +226,9 @@ func close(c chan<- Type)
|
||||
// invocation of F then behaves like a call to panic, terminating G's
|
||||
// execution and running any deferred functions. This continues until all
|
||||
// functions in the executing goroutine have stopped, in reverse order. At
|
||||
// that point, the program is terminated and the error condition is reported,
|
||||
// including the value of the argument to panic. This termination sequence
|
||||
// is called panicking and can be controlled by the built-in function
|
||||
// recover.
|
||||
// that point, the program is terminated with a non-zero exit code. This
|
||||
// termination sequence is called panicking and can be controlled by the
|
||||
// built-in function recover.
|
||||
func panic(v interface{})
|
||||
|
||||
// The recover built-in function allows a program to manage behavior of a
|
||||
|
@ -21,9 +21,6 @@ type Buffer struct {
|
||||
buf []byte // contents are the bytes buf[off : len(buf)]
|
||||
off int // read at &buf[off], write at &buf[len(buf)]
|
||||
lastRead readOp // last read operation, so that Unread* can work correctly.
|
||||
|
||||
// FIXME: it would be advisable to align Buffer to cachelines to avoid false
|
||||
// sharing.
|
||||
}
|
||||
|
||||
// The readOp constants describe the last action performed on
|
||||
@ -385,13 +382,15 @@ func (b *Buffer) UnreadRune() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var errUnreadByte = errors.New("bytes.Buffer: UnreadByte: previous operation was not a successful read")
|
||||
|
||||
// UnreadByte unreads the last byte returned by the most recent successful
|
||||
// read operation that read at least one byte. If a write has happened since
|
||||
// the last read, if the last read returned an error, or if the read read zero
|
||||
// bytes, UnreadByte returns an error.
|
||||
func (b *Buffer) UnreadByte() error {
|
||||
if b.lastRead == opInvalid {
|
||||
return errors.New("bytes.Buffer: UnreadByte: previous operation was not a successful read")
|
||||
return errUnreadByte
|
||||
}
|
||||
b.lastRead = opInvalid
|
||||
if b.off > 0 {
|
||||
|
@ -131,11 +131,8 @@ func TestBasicOperations(t *testing.T) {
|
||||
check(t, "TestBasicOperations (3)", &buf, "")
|
||||
|
||||
n, err := buf.Write(testBytes[0:1])
|
||||
if n != 1 {
|
||||
t.Errorf("wrote 1 byte, but n == %d", n)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("err should always be nil, but err == %s", err)
|
||||
if want := 1; err != nil || n != want {
|
||||
t.Errorf("Write: got (%d, %v), want (%d, %v)", n, err, want, nil)
|
||||
}
|
||||
check(t, "TestBasicOperations (4)", &buf, "a")
|
||||
|
||||
@ -143,8 +140,8 @@ func TestBasicOperations(t *testing.T) {
|
||||
check(t, "TestBasicOperations (5)", &buf, "ab")
|
||||
|
||||
n, err = buf.Write(testBytes[2:26])
|
||||
if n != 24 {
|
||||
t.Errorf("wrote 24 bytes, but n == %d", n)
|
||||
if want := 24; err != nil || n != want {
|
||||
t.Errorf("Write: got (%d, %v), want (%d, %v)", n, err, want, nil)
|
||||
}
|
||||
check(t, "TestBasicOperations (6)", &buf, testString[0:26])
|
||||
|
||||
@ -159,15 +156,12 @@ func TestBasicOperations(t *testing.T) {
|
||||
|
||||
buf.WriteByte(testString[1])
|
||||
c, err := buf.ReadByte()
|
||||
if err != nil {
|
||||
t.Error("ReadByte unexpected eof")
|
||||
}
|
||||
if c != testString[1] {
|
||||
t.Errorf("ReadByte wrong value c=%v", c)
|
||||
if want := testString[1]; err != nil || c != want {
|
||||
t.Errorf("ReadByte: got (%q, %v), want (%q, %v)", c, err, want, nil)
|
||||
}
|
||||
c, err = buf.ReadByte()
|
||||
if err == nil {
|
||||
t.Error("ReadByte unexpected not eof")
|
||||
if err != io.EOF {
|
||||
t.Errorf("ReadByte: got (%q, %v), want (%q, %v)", c, err, byte(0), io.EOF)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,23 +12,12 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Equal returns a boolean reporting whether a and b
|
||||
// Equal reports whether a and b
|
||||
// are the same length and contain the same bytes.
|
||||
// A nil argument is equivalent to an empty slice.
|
||||
func Equal(a, b []byte) bool {
|
||||
return bytealg.Equal(a, b)
|
||||
}
|
||||
|
||||
func equalPortable(a, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, c := range a {
|
||||
if c != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
// Neither cmd/compile nor gccgo allocates for these string conversions.
|
||||
return string(a) == string(b)
|
||||
}
|
||||
|
||||
// Compare returns an integer comparing two byte slices lexicographically.
|
||||
@ -114,12 +103,34 @@ func indexBytePortable(s []byte, c byte) int {
|
||||
// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
|
||||
func LastIndex(s, sep []byte) int {
|
||||
n := len(sep)
|
||||
if n == 0 {
|
||||
switch {
|
||||
case n == 0:
|
||||
return len(s)
|
||||
case n == 1:
|
||||
return LastIndexByte(s, sep[0])
|
||||
case n == len(s):
|
||||
if Equal(s, sep) {
|
||||
return 0
|
||||
}
|
||||
return -1
|
||||
case n > len(s):
|
||||
return -1
|
||||
}
|
||||
c := sep[0]
|
||||
for i := len(s) - n; i >= 0; i-- {
|
||||
if s[i] == c && (n == 1 || Equal(s[i:i+n], sep)) {
|
||||
// Rabin-Karp search from the end of the string
|
||||
hashss, pow := hashStrRev(sep)
|
||||
last := len(s) - n
|
||||
var h uint32
|
||||
for i := len(s) - 1; i >= last; i-- {
|
||||
h = h*primeRK + uint32(s[i])
|
||||
}
|
||||
if h == hashss && Equal(s[last:], sep) {
|
||||
return last
|
||||
}
|
||||
for i := last - 1; i >= 0; i-- {
|
||||
h *= primeRK
|
||||
h += uint32(s[i])
|
||||
h -= pow * uint32(s[i+n])
|
||||
if h == hashss && Equal(s[i:i+n], sep) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
@ -477,13 +488,16 @@ func Map(mapping func(r rune) rune, s []byte) []byte {
|
||||
// It panics if count is negative or if
|
||||
// the result of (len(b) * count) overflows.
|
||||
func Repeat(b []byte, count int) []byte {
|
||||
if count == 0 {
|
||||
return []byte{}
|
||||
}
|
||||
// Since we cannot return an error on overflow,
|
||||
// we should panic if the repeat will generate
|
||||
// an overflow.
|
||||
// See Issue golang.org/issue/16237.
|
||||
if count < 0 {
|
||||
panic("bytes: negative Repeat count")
|
||||
} else if count > 0 && len(b)*count/count != len(b) {
|
||||
} else if len(b)*count/count != len(b) {
|
||||
panic("bytes: Repeat count causes overflow")
|
||||
}
|
||||
|
||||
@ -496,11 +510,66 @@ func Repeat(b []byte, count int) []byte {
|
||||
return nb
|
||||
}
|
||||
|
||||
// ToUpper treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters within it mapped to their upper case.
|
||||
func ToUpper(s []byte) []byte { return Map(unicode.ToUpper, s) }
|
||||
// ToUpper returns a copy of the byte slice s with all Unicode letters mapped to
|
||||
// their upper case.
|
||||
func ToUpper(s []byte) []byte {
|
||||
isASCII, hasLower := true, false
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if c >= utf8.RuneSelf {
|
||||
isASCII = false
|
||||
break
|
||||
}
|
||||
hasLower = hasLower || ('a' <= c && c <= 'z')
|
||||
}
|
||||
|
||||
// ToLower treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their lower case.
|
||||
func ToLower(s []byte) []byte { return Map(unicode.ToLower, s) }
|
||||
if isASCII { // optimize for ASCII-only byte slices.
|
||||
if !hasLower {
|
||||
// Just return a copy.
|
||||
return append([]byte(""), s...)
|
||||
}
|
||||
b := make([]byte, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if 'a' <= c && c <= 'z' {
|
||||
c -= 'a' - 'A'
|
||||
}
|
||||
b[i] = c
|
||||
}
|
||||
return b
|
||||
}
|
||||
return Map(unicode.ToUpper, s)
|
||||
}
|
||||
|
||||
// ToLower returns a copy of the byte slice s with all Unicode letters mapped to
|
||||
// their lower case.
|
||||
func ToLower(s []byte) []byte {
|
||||
isASCII, hasUpper := true, false
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if c >= utf8.RuneSelf {
|
||||
isASCII = false
|
||||
break
|
||||
}
|
||||
hasUpper = hasUpper || ('A' <= c && c <= 'Z')
|
||||
}
|
||||
|
||||
if isASCII { // optimize for ASCII-only byte slices.
|
||||
if !hasUpper {
|
||||
return append([]byte(""), s...)
|
||||
}
|
||||
b := make([]byte, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if 'A' <= c && c <= 'Z' {
|
||||
c += 'a' - 'A'
|
||||
}
|
||||
b[i] = c
|
||||
}
|
||||
return b
|
||||
}
|
||||
return Map(unicode.ToLower, s)
|
||||
}
|
||||
|
||||
// ToTitle treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their title case.
|
||||
func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
|
||||
@ -523,6 +592,35 @@ func ToTitleSpecial(c unicode.SpecialCase, s []byte) []byte {
|
||||
return Map(c.ToTitle, s)
|
||||
}
|
||||
|
||||
// ToValidUTF8 treats s as UTF-8-encoded bytes and returns a copy with each run of bytes
|
||||
// representing invalid UTF-8 replaced with the bytes in replacement, which may be empty.
|
||||
func ToValidUTF8(s, replacement []byte) []byte {
|
||||
b := make([]byte, 0, len(s)+len(replacement))
|
||||
invalid := false // previous byte was from an invalid UTF-8 sequence
|
||||
for i := 0; i < len(s); {
|
||||
c := s[i]
|
||||
if c < utf8.RuneSelf {
|
||||
i++
|
||||
invalid = false
|
||||
b = append(b, byte(c))
|
||||
continue
|
||||
}
|
||||
_, wid := utf8.DecodeRune(s[i:])
|
||||
if wid == 1 {
|
||||
i++
|
||||
if !invalid {
|
||||
invalid = true
|
||||
b = append(b, replacement...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
invalid = false
|
||||
b = append(b, s[i:i+wid]...)
|
||||
i += wid
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// isSeparator reports whether the rune could mark a word boundary.
|
||||
// TODO: update when package unicode captures more of the properties.
|
||||
func isSeparator(r rune) bool {
|
||||
@ -734,7 +832,41 @@ func TrimRight(s []byte, cutset string) []byte {
|
||||
// TrimSpace returns a subslice of s by slicing off all leading and
|
||||
// trailing white space, as defined by Unicode.
|
||||
func TrimSpace(s []byte) []byte {
|
||||
return TrimFunc(s, unicode.IsSpace)
|
||||
// Fast path for ASCII: look for the first ASCII non-space byte
|
||||
start := 0
|
||||
for ; start < len(s); start++ {
|
||||
c := s[start]
|
||||
if c >= utf8.RuneSelf {
|
||||
// If we run into a non-ASCII byte, fall back to the
|
||||
// slower unicode-aware method on the remaining bytes
|
||||
return TrimFunc(s[start:], unicode.IsSpace)
|
||||
}
|
||||
if asciiSpace[c] == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Now look for the first ASCII non-space byte from the end
|
||||
stop := len(s)
|
||||
for ; stop > start; stop-- {
|
||||
c := s[stop-1]
|
||||
if c >= utf8.RuneSelf {
|
||||
return TrimFunc(s[start:stop], unicode.IsSpace)
|
||||
}
|
||||
if asciiSpace[c] == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// At this point s[start:stop] starts and ends with an ASCII
|
||||
// non-space bytes, so we're done. Non-ASCII cases have already
|
||||
// been handled above.
|
||||
if start == stop {
|
||||
// Special case to preserve previous TrimLeftFunc behavior,
|
||||
// returning nil instead of empty slice if all spaces.
|
||||
return nil
|
||||
}
|
||||
return s[start:stop]
|
||||
}
|
||||
|
||||
// Runes interprets s as a sequence of UTF-8-encoded code points.
|
||||
@ -987,3 +1119,20 @@ func hashStr(sep []byte) (uint32, uint32) {
|
||||
}
|
||||
return hash, pow
|
||||
}
|
||||
|
||||
// hashStrRev returns the hash of the reverse of sep and the
|
||||
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
|
||||
func hashStrRev(sep []byte) (uint32, uint32) {
|
||||
hash := uint32(0)
|
||||
for i := len(sep) - 1; i >= 0; i-- {
|
||||
hash = hash*primeRK + uint32(sep[i])
|
||||
}
|
||||
var pow, sq uint32 = 1, primeRK
|
||||
for i := len(sep); i > 0; i >>= 1 {
|
||||
if i&1 != 0 {
|
||||
pow *= sq
|
||||
}
|
||||
sq *= sq
|
||||
}
|
||||
return hash, pow
|
||||
}
|
||||
|
@ -52,15 +52,17 @@ type BinOpTest struct {
|
||||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
for _, tt := range compareTests {
|
||||
eql := Equal(tt.a, tt.b)
|
||||
if eql != (tt.i == 0) {
|
||||
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
|
||||
}
|
||||
eql = EqualPortable(tt.a, tt.b)
|
||||
if eql != (tt.i == 0) {
|
||||
t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql)
|
||||
// Run the tests and check for allocation at the same time.
|
||||
allocs := testing.AllocsPerRun(10, func() {
|
||||
for _, tt := range compareTests {
|
||||
eql := Equal(tt.a, tt.b)
|
||||
if eql != (tt.i == 0) {
|
||||
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
|
||||
}
|
||||
}
|
||||
})
|
||||
if allocs > 0 {
|
||||
t.Errorf("Equal allocated %v times", allocs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,11 +579,6 @@ func BenchmarkEqual(b *testing.B) {
|
||||
benchBytes(b, sizes, bmEqual(Equal))
|
||||
}
|
||||
|
||||
func BenchmarkEqualPort(b *testing.B) {
|
||||
sizes := []int{1, 6, 32, 4 << 10, 4 << 20, 64 << 20}
|
||||
benchBytes(b, sizes, bmEqual(EqualPortable))
|
||||
}
|
||||
|
||||
func bmEqual(equal func([]byte, []byte) bool) func(b *testing.B, n int) {
|
||||
return func(b *testing.B, n int) {
|
||||
if len(bmbuf) < 2*n {
|
||||
@ -682,34 +679,6 @@ func BenchmarkCountSingle(b *testing.B) {
|
||||
})
|
||||
}
|
||||
|
||||
type ExplodeTest struct {
|
||||
s string
|
||||
n int
|
||||
a []string
|
||||
}
|
||||
|
||||
var explodetests = []ExplodeTest{
|
||||
{"", -1, []string{}},
|
||||
{abcd, -1, []string{"a", "b", "c", "d"}},
|
||||
{faces, -1, []string{"☺", "☻", "☹"}},
|
||||
{abcd, 2, []string{"a", "bcd"}},
|
||||
}
|
||||
|
||||
func TestExplode(t *testing.T) {
|
||||
for _, tt := range explodetests {
|
||||
a := SplitN([]byte(tt.s), nil, tt.n)
|
||||
result := sliceOfString(a)
|
||||
if !eq(result, tt.a) {
|
||||
t.Errorf(`Explode("%s", %d) = %v; want %v`, tt.s, tt.n, result, tt.a)
|
||||
continue
|
||||
}
|
||||
s := Join(a, []byte{})
|
||||
if string(s) != tt.s {
|
||||
t.Errorf(`Join(Explode("%s", %d), "") = "%s"`, tt.s, tt.n, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type SplitTest struct {
|
||||
s string
|
||||
sep string
|
||||
@ -718,7 +687,9 @@ type SplitTest struct {
|
||||
}
|
||||
|
||||
var splittests = []SplitTest{
|
||||
{"", "", -1, []string{}},
|
||||
{abcd, "a", 0, nil},
|
||||
{abcd, "", 2, []string{"a", "bcd"}},
|
||||
{abcd, "a", -1, []string{"", "bcd"}},
|
||||
{abcd, "z", -1, []string{"abcd"}},
|
||||
{abcd, "", -1, []string{"a", "b", "c", "d"}},
|
||||
@ -748,7 +719,7 @@ func TestSplit(t *testing.T) {
|
||||
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
|
||||
continue
|
||||
}
|
||||
if tt.n == 0 {
|
||||
if tt.n == 0 || len(a) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -914,54 +885,72 @@ func TestFieldsFunc(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test case for any function which accepts and returns a byte slice.
|
||||
// For ease of creation, we write the byte slices as strings.
|
||||
// For ease of creation, we write the input byte slice as a string.
|
||||
type StringTest struct {
|
||||
in, out string
|
||||
in string
|
||||
out []byte
|
||||
}
|
||||
|
||||
var upperTests = []StringTest{
|
||||
{"", ""},
|
||||
{"abc", "ABC"},
|
||||
{"AbC123", "ABC123"},
|
||||
{"azAZ09_", "AZAZ09_"},
|
||||
{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
|
||||
{"", []byte("")},
|
||||
{"ONLYUPPER", []byte("ONLYUPPER")},
|
||||
{"abc", []byte("ABC")},
|
||||
{"AbC123", []byte("ABC123")},
|
||||
{"azAZ09_", []byte("AZAZ09_")},
|
||||
{"longStrinGwitHmixofsmaLLandcAps", []byte("LONGSTRINGWITHMIXOFSMALLANDCAPS")},
|
||||
{"long\u0250string\u0250with\u0250nonascii\u2C6Fchars", []byte("LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS")},
|
||||
{"\u0250\u0250\u0250\u0250\u0250", []byte("\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F")}, // grows one byte per char
|
||||
{"a\u0080\U0010FFFF", []byte("A\u0080\U0010FFFF")}, // test utf8.RuneSelf and utf8.MaxRune
|
||||
}
|
||||
|
||||
var lowerTests = []StringTest{
|
||||
{"", ""},
|
||||
{"abc", "abc"},
|
||||
{"AbC123", "abc123"},
|
||||
{"azAZ09_", "azaz09_"},
|
||||
{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
|
||||
{"", []byte("")},
|
||||
{"abc", []byte("abc")},
|
||||
{"AbC123", []byte("abc123")},
|
||||
{"azAZ09_", []byte("azaz09_")},
|
||||
{"longStrinGwitHmixofsmaLLandcAps", []byte("longstringwithmixofsmallandcaps")},
|
||||
{"LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS", []byte("long\u0250string\u0250with\u0250nonascii\u0250chars")},
|
||||
{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", []byte("\u0251\u0251\u0251\u0251\u0251")}, // shrinks one byte per char
|
||||
{"A\u0080\U0010FFFF", []byte("a\u0080\U0010FFFF")}, // test utf8.RuneSelf and utf8.MaxRune
|
||||
}
|
||||
|
||||
const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
|
||||
|
||||
var trimSpaceTests = []StringTest{
|
||||
{"", ""},
|
||||
{"abc", "abc"},
|
||||
{space + "abc" + space, "abc"},
|
||||
{" ", ""},
|
||||
{" \t\r\n \t\t\r\r\n\n ", ""},
|
||||
{" \t\r\n x\t\t\r\r\n\n ", "x"},
|
||||
{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
|
||||
{"1 \t\r\n2", "1 \t\r\n2"},
|
||||
{" x\x80", "x\x80"},
|
||||
{" x\xc0", "x\xc0"},
|
||||
{"x \xc0\xc0 ", "x \xc0\xc0"},
|
||||
{"x \xc0", "x \xc0"},
|
||||
{"x \xc0 ", "x \xc0"},
|
||||
{"x \xc0\xc0 ", "x \xc0\xc0"},
|
||||
{"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"},
|
||||
{"x ☺ ", "x ☺"},
|
||||
{"", nil},
|
||||
{" a", []byte("a")},
|
||||
{"b ", []byte("b")},
|
||||
{"abc", []byte("abc")},
|
||||
{space + "abc" + space, []byte("abc")},
|
||||
{" ", nil},
|
||||
{"\u3000 ", nil},
|
||||
{" \u3000", nil},
|
||||
{" \t\r\n \t\t\r\r\n\n ", nil},
|
||||
{" \t\r\n x\t\t\r\r\n\n ", []byte("x")},
|
||||
{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", []byte("x\t\t\r\r\ny")},
|
||||
{"1 \t\r\n2", []byte("1 \t\r\n2")},
|
||||
{" x\x80", []byte("x\x80")},
|
||||
{" x\xc0", []byte("x\xc0")},
|
||||
{"x \xc0\xc0 ", []byte("x \xc0\xc0")},
|
||||
{"x \xc0", []byte("x \xc0")},
|
||||
{"x \xc0 ", []byte("x \xc0")},
|
||||
{"x \xc0\xc0 ", []byte("x \xc0\xc0")},
|
||||
{"x ☺\xc0\xc0 ", []byte("x ☺\xc0\xc0")},
|
||||
{"x ☺ ", []byte("x ☺")},
|
||||
}
|
||||
|
||||
// Execute f on each test case. funcName should be the name of f; it's used
|
||||
// in failure reports.
|
||||
func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCases []StringTest) {
|
||||
for _, tc := range testCases {
|
||||
actual := string(f([]byte(tc.in)))
|
||||
if actual != tc.out {
|
||||
actual := f([]byte(tc.in))
|
||||
if actual == nil && tc.out != nil {
|
||||
t.Errorf("%s(%q) = nil; want %q", funcName, tc.in, tc.out)
|
||||
}
|
||||
if actual != nil && tc.out == nil {
|
||||
t.Errorf("%s(%q) = %q; want nil", funcName, tc.in, actual)
|
||||
}
|
||||
if !Equal(actual, tc.out) {
|
||||
t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
|
||||
}
|
||||
}
|
||||
@ -1049,6 +1038,64 @@ func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTest
|
||||
|
||||
func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
|
||||
|
||||
func BenchmarkToUpper(b *testing.B) {
|
||||
for _, tc := range upperTests {
|
||||
tin := []byte(tc.in)
|
||||
b.Run(tc.in, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
actual := ToUpper(tin)
|
||||
if !Equal(actual, tc.out) {
|
||||
b.Errorf("ToUpper(%q) = %q; want %q", tc.in, actual, tc.out)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkToLower(b *testing.B) {
|
||||
for _, tc := range lowerTests {
|
||||
tin := []byte(tc.in)
|
||||
b.Run(tc.in, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
actual := ToLower(tin)
|
||||
if !Equal(actual, tc.out) {
|
||||
b.Errorf("ToLower(%q) = %q; want %q", tc.in, actual, tc.out)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var toValidUTF8Tests = []struct {
|
||||
in string
|
||||
repl string
|
||||
out string
|
||||
}{
|
||||
{"", "\uFFFD", ""},
|
||||
{"abc", "\uFFFD", "abc"},
|
||||
{"\uFDDD", "\uFFFD", "\uFDDD"},
|
||||
{"a\xffb", "\uFFFD", "a\uFFFDb"},
|
||||
{"a\xffb\uFFFD", "X", "aXb\uFFFD"},
|
||||
{"a☺\xffb☺\xC0\xAFc☺\xff", "", "a☺b☺c☺"},
|
||||
{"a☺\xffb☺\xC0\xAFc☺\xff", "日本語", "a☺日本語b☺日本語c☺日本語"},
|
||||
{"\xC0\xAF", "\uFFFD", "\uFFFD"},
|
||||
{"\xE0\x80\xAF", "\uFFFD", "\uFFFD"},
|
||||
{"\xed\xa0\x80", "abc", "abc"},
|
||||
{"\xed\xbf\xbf", "\uFFFD", "\uFFFD"},
|
||||
{"\xF0\x80\x80\xaf", "☺", "☺"},
|
||||
{"\xF8\x80\x80\x80\xAF", "\uFFFD", "\uFFFD"},
|
||||
{"\xFC\x80\x80\x80\x80\xAF", "\uFFFD", "\uFFFD"},
|
||||
}
|
||||
|
||||
func TestToValidUTF8(t *testing.T) {
|
||||
for _, tc := range toValidUTF8Tests {
|
||||
got := ToValidUTF8([]byte(tc.in), []byte(tc.repl))
|
||||
if !Equal(got, []byte(tc.out)) {
|
||||
t.Errorf("ToValidUTF8(%q, %q) = %q; want %q", tc.in, tc.repl, got, tc.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
|
||||
|
||||
type RepeatTest struct {
|
||||
@ -1255,8 +1302,11 @@ var isValidRune = predicate{
|
||||
}
|
||||
|
||||
type TrimFuncTest struct {
|
||||
f predicate
|
||||
in, out string
|
||||
f predicate
|
||||
in string
|
||||
trimOut []byte
|
||||
leftOut []byte
|
||||
rightOut []byte
|
||||
}
|
||||
|
||||
func not(p predicate) predicate {
|
||||
@ -1269,20 +1319,68 @@ func not(p predicate) predicate {
|
||||
}
|
||||
|
||||
var trimFuncTests = []TrimFuncTest{
|
||||
{isSpace, space + " hello " + space, "hello"},
|
||||
{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
|
||||
{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
|
||||
{not(isSpace), "hello" + space + "hello", space},
|
||||
{not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"},
|
||||
{isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"},
|
||||
{not(isValidRune), "\xc0a\xc0", "a"},
|
||||
{isSpace, space + " hello " + space,
|
||||
[]byte("hello"),
|
||||
[]byte("hello " + space),
|
||||
[]byte(space + " hello")},
|
||||
{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51",
|
||||
[]byte("hello"),
|
||||
[]byte("hello34\u0e50\u0e51"),
|
||||
[]byte("\u0e50\u0e5212hello")},
|
||||
{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F",
|
||||
[]byte("hello"),
|
||||
[]byte("helloEF\u2C6F\u2C6FGH\u2C6F\u2C6F"),
|
||||
[]byte("\u2C6F\u2C6F\u2C6F\u2C6FABCDhello")},
|
||||
{not(isSpace), "hello" + space + "hello",
|
||||
[]byte(space),
|
||||
[]byte(space + "hello"),
|
||||
[]byte("hello" + space)},
|
||||
{not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo",
|
||||
[]byte("\u0e50\u0e521234\u0e50\u0e51"),
|
||||
[]byte("\u0e50\u0e521234\u0e50\u0e51helo"),
|
||||
[]byte("hello\u0e50\u0e521234\u0e50\u0e51")},
|
||||
{isValidRune, "ab\xc0a\xc0cd",
|
||||
[]byte("\xc0a\xc0"),
|
||||
[]byte("\xc0a\xc0cd"),
|
||||
[]byte("ab\xc0a\xc0")},
|
||||
{not(isValidRune), "\xc0a\xc0",
|
||||
[]byte("a"),
|
||||
[]byte("a\xc0"),
|
||||
[]byte("\xc0a")},
|
||||
// The nils returned by TrimLeftFunc are odd behavior, but we need
|
||||
// to preserve backwards compatibility.
|
||||
{isSpace, "",
|
||||
nil,
|
||||
nil,
|
||||
[]byte("")},
|
||||
{isSpace, " ",
|
||||
nil,
|
||||
nil,
|
||||
[]byte("")},
|
||||
}
|
||||
|
||||
func TestTrimFunc(t *testing.T) {
|
||||
for _, tc := range trimFuncTests {
|
||||
actual := string(TrimFunc([]byte(tc.in), tc.f.f))
|
||||
if actual != tc.out {
|
||||
t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out)
|
||||
trimmers := []struct {
|
||||
name string
|
||||
trim func(s []byte, f func(r rune) bool) []byte
|
||||
out []byte
|
||||
}{
|
||||
{"TrimFunc", TrimFunc, tc.trimOut},
|
||||
{"TrimLeftFunc", TrimLeftFunc, tc.leftOut},
|
||||
{"TrimRightFunc", TrimRightFunc, tc.rightOut},
|
||||
}
|
||||
for _, trimmer := range trimmers {
|
||||
actual := trimmer.trim([]byte(tc.in), tc.f.f)
|
||||
if actual == nil && trimmer.out != nil {
|
||||
t.Errorf("%s(%q, %q) = nil; want %q", trimmer.name, tc.in, tc.f.name, trimmer.out)
|
||||
}
|
||||
if actual != nil && trimmer.out == nil {
|
||||
t.Errorf("%s(%q, %q) = %q; want nil", trimmer.name, tc.in, tc.f.name, actual)
|
||||
}
|
||||
if !Equal(actual, trimmer.out) {
|
||||
t.Errorf("%s(%q, %q) = %q; want %q", trimmer.name, tc.in, tc.f.name, actual, trimmer.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1622,9 +1720,41 @@ func BenchmarkFieldsFunc(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkTrimSpace(b *testing.B) {
|
||||
s := []byte(" Some text. \n")
|
||||
for i := 0; i < b.N; i++ {
|
||||
TrimSpace(s)
|
||||
tests := []struct {
|
||||
name string
|
||||
input []byte
|
||||
}{
|
||||
{"NoTrim", []byte("typical")},
|
||||
{"ASCII", []byte(" foo bar ")},
|
||||
{"SomeNonASCII", []byte(" \u2000\t\r\n x\t\t\r\r\ny\n \u3000 ")},
|
||||
{"JustNonASCII", []byte("\u2000\u2000\u2000☺☺☺☺\u3000\u3000\u3000")},
|
||||
}
|
||||
for _, test := range tests {
|
||||
b.Run(test.name, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
TrimSpace(test.input)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkToValidUTF8(b *testing.B) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []byte
|
||||
}{
|
||||
{"Valid", []byte("typical")},
|
||||
{"InvalidASCII", []byte("foo\xffbar")},
|
||||
{"InvalidNonASCII", []byte("日本語\xff日本語")},
|
||||
}
|
||||
replacement := []byte("\uFFFD")
|
||||
b.ResetTimer()
|
||||
for _, test := range tests {
|
||||
b.Run(test.name, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ToValidUTF8(test.input, replacement)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1647,6 +1777,39 @@ func makeBenchInputHard() []byte {
|
||||
|
||||
var benchInputHard = makeBenchInputHard()
|
||||
|
||||
func benchmarkIndexHard(b *testing.B, sep []byte) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Index(benchInputHard, sep)
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkLastIndexHard(b *testing.B, sep []byte) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
LastIndex(benchInputHard, sep)
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkCountHard(b *testing.B, sep []byte) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Count(benchInputHard, sep)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexHard1(b *testing.B) { benchmarkIndexHard(b, []byte("<>")) }
|
||||
func BenchmarkIndexHard2(b *testing.B) { benchmarkIndexHard(b, []byte("</pre>")) }
|
||||
func BenchmarkIndexHard3(b *testing.B) { benchmarkIndexHard(b, []byte("<b>hello world</b>")) }
|
||||
func BenchmarkIndexHard4(b *testing.B) {
|
||||
benchmarkIndexHard(b, []byte("<pre><b>hello</b><strong>world</strong></pre>"))
|
||||
}
|
||||
|
||||
func BenchmarkLastIndexHard1(b *testing.B) { benchmarkLastIndexHard(b, []byte("<>")) }
|
||||
func BenchmarkLastIndexHard2(b *testing.B) { benchmarkLastIndexHard(b, []byte("</pre>")) }
|
||||
func BenchmarkLastIndexHard3(b *testing.B) { benchmarkLastIndexHard(b, []byte("<b>hello world</b>")) }
|
||||
|
||||
func BenchmarkCountHard1(b *testing.B) { benchmarkCountHard(b, []byte("<>")) }
|
||||
func BenchmarkCountHard2(b *testing.B) { benchmarkCountHard(b, []byte("</pre>")) }
|
||||
func BenchmarkCountHard3(b *testing.B) { benchmarkCountHard(b, []byte("<b>hello world</b>")) }
|
||||
|
||||
func BenchmarkSplitEmptySeparator(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Split(benchInputHard, nil)
|
||||
|
@ -365,6 +365,16 @@ func ExampleToTitle() {
|
||||
// ХЛЕБ
|
||||
}
|
||||
|
||||
func ExampleToTitleSpecial() {
|
||||
str := []byte("ahoj vývojári golang")
|
||||
totitle := bytes.ToTitleSpecial(unicode.AzeriCase, str)
|
||||
fmt.Println("Original : " + string(str))
|
||||
fmt.Println("ToTitle : " + string(totitle))
|
||||
// Output:
|
||||
// Original : ahoj vývojári golang
|
||||
// ToTitle : AHOJ VÝVOJÁRİ GOLANG
|
||||
}
|
||||
|
||||
func ExampleTrim() {
|
||||
fmt.Printf("[%q]", bytes.Trim([]byte(" !!! Achtung! Achtung! !!! "), "! "))
|
||||
// Output: ["Achtung! Achtung"]
|
||||
@ -438,11 +448,31 @@ func ExampleToUpper() {
|
||||
// Output: GOPHER
|
||||
}
|
||||
|
||||
func ExampleToUpperSpecial() {
|
||||
str := []byte("ahoj vývojári golang")
|
||||
totitle := bytes.ToUpperSpecial(unicode.AzeriCase, str)
|
||||
fmt.Println("Original : " + string(str))
|
||||
fmt.Println("ToUpper : " + string(totitle))
|
||||
// Output:
|
||||
// Original : ahoj vývojári golang
|
||||
// ToUpper : AHOJ VÝVOJÁRİ GOLANG
|
||||
}
|
||||
|
||||
func ExampleToLower() {
|
||||
fmt.Printf("%s", bytes.ToLower([]byte("Gopher")))
|
||||
// Output: gopher
|
||||
}
|
||||
|
||||
func ExampleToLowerSpecial() {
|
||||
str := []byte("AHOJ VÝVOJÁRİ GOLANG")
|
||||
totitle := bytes.ToLowerSpecial(unicode.AzeriCase, str)
|
||||
fmt.Println("Original : " + string(str))
|
||||
fmt.Println("ToLower : " + string(totitle))
|
||||
// Output:
|
||||
// Original : AHOJ VÝVOJÁRİ GOLANG
|
||||
// ToLower : ahoj vývojári golang
|
||||
}
|
||||
|
||||
func ExampleReader_Len() {
|
||||
fmt.Println(bytes.NewReader([]byte("Hi!")).Len())
|
||||
fmt.Println(bytes.NewReader([]byte("こんにちは!")).Len())
|
||||
|
@ -6,4 +6,3 @@ package bytes
|
||||
|
||||
// Export func for testing
|
||||
var IndexBytePortable = indexBytePortable
|
||||
var EqualPortable = equalPortable
|
||||
|
@ -296,7 +296,7 @@ Go functions can be exported for use by C code in the following way:
|
||||
|
||||
They will be available in the C code as:
|
||||
|
||||
extern int64 MyFunction(int arg1, int arg2, GoString arg3);
|
||||
extern GoInt64 MyFunction(int arg1, int arg2, GoString arg3);
|
||||
extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
|
||||
|
||||
found in the _cgo_export.h generated header, after any preambles
|
||||
@ -710,7 +710,7 @@ _cgo_main.c:
|
||||
|
||||
int main() { return 0; }
|
||||
void crosscall2(void(*fn)(void*, int, uintptr_t), void *a, int c, uintptr_t ctxt) { }
|
||||
uintptr_t _cgo_wait_runtime_init_done() { return 0; }
|
||||
uintptr_t _cgo_wait_runtime_init_done(void) { return 0; }
|
||||
void _cgo_release_context(uintptr_t ctxt) { }
|
||||
char* _cgo_topofstack(void) { return (char*)0; }
|
||||
void _cgo_allocate(void *a, int c) { }
|
||||
|
@ -1274,6 +1274,8 @@ func (p *Package) isVariable(x ast.Expr) bool {
|
||||
return true
|
||||
case *ast.SelectorExpr:
|
||||
return p.isVariable(x.X)
|
||||
case *ast.IndexExpr:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -1609,6 +1611,7 @@ func (p *Package) gccCmd() []string {
|
||||
c = append(c, p.gccMachine()...)
|
||||
if goos == "aix" {
|
||||
c = append(c, "-maix64")
|
||||
c = append(c, "-mcmodel=large")
|
||||
}
|
||||
c = append(c, "-") //read input from standard input
|
||||
return c
|
||||
|
@ -136,21 +136,31 @@ func gofmt(n interface{}) string {
|
||||
// (due to the printer possibly inserting newlines because of position
|
||||
// information) operators.
|
||||
var gofmtLineReplacer = strings.NewReplacer(
|
||||
"{\n", "{",
|
||||
",\n", ",",
|
||||
// Want to replace \n without ; after everything from
|
||||
// https://golang.org/ref/spec#Operators_and_punctuation
|
||||
// EXCEPT ++ -- ) ] }
|
||||
"++\n", "++;",
|
||||
"--\n", "--;",
|
||||
"+\n", "+",
|
||||
"-\n", "-",
|
||||
"*\n", "*",
|
||||
"/\n", "/",
|
||||
"%\n", "%",
|
||||
"&\n", "&",
|
||||
"|\n", "|",
|
||||
"^\n", "^",
|
||||
"<\n", "<",
|
||||
">\n", ">",
|
||||
"=\n", "=",
|
||||
|
||||
"+\n", "+ ",
|
||||
"-\n", "- ",
|
||||
"*\n", "* ",
|
||||
"/\n", "/ ",
|
||||
"%\n", "% ",
|
||||
"&\n", "& ",
|
||||
"|\n", "| ",
|
||||
"^\n", "^ ",
|
||||
"<\n", "< ",
|
||||
">\n", "> ",
|
||||
"=\n", "= ",
|
||||
"!\n", "! ", // not possible in gofmt today
|
||||
"(\n", "(",
|
||||
"[\n", "[", // not possible in gofmt today
|
||||
"{\n", "{",
|
||||
",\n", ",",
|
||||
".\n", ". ",
|
||||
":\n", ": ", // not possible in gofmt today
|
||||
|
||||
"\n", ";",
|
||||
)
|
||||
|
||||
|
@ -64,14 +64,14 @@ func (p *Package) writeDefs() {
|
||||
fmt.Fprintf(fm, "int main() { return 0; }\n")
|
||||
if *importRuntimeCgo {
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { }\n")
|
||||
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done() { return 0; }\n")
|
||||
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void) { return 0; }\n")
|
||||
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt) { }\n")
|
||||
fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
|
||||
} else {
|
||||
// If we're not importing runtime/cgo, we *are* runtime/cgo,
|
||||
// which provides these functions. We just need a prototype.
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt);\n")
|
||||
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done();\n")
|
||||
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
|
||||
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\n")
|
||||
}
|
||||
fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n")
|
||||
@ -341,6 +341,12 @@ func dynimport(obj string) {
|
||||
fatalf("cannot load imported symbols from XCOFF file %s: %v", obj, err)
|
||||
}
|
||||
for _, s := range sym {
|
||||
if s.Name == "runtime_rt0_go" || s.Name == "_rt0_ppc64_aix_lib" {
|
||||
// These symbols are imported by runtime/cgo but
|
||||
// must not be added to _cgo_import.go as there are
|
||||
// Go symbols.
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, s.Name, s.Library)
|
||||
}
|
||||
lib, err := f.ImportedLibraries()
|
||||
@ -782,14 +788,14 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
||||
fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n")
|
||||
|
||||
// We use packed structs, but they are always aligned.
|
||||
// The pragmas and address-of-packed-member are not recognized as warning groups in clang 3.4.1, so ignore unknown pragmas first.
|
||||
// remove as part of #27619 (all: drop support for FreeBSD 10).
|
||||
// The pragmas and address-of-packed-member are only recognized as
|
||||
// warning groups in clang 4.0+, so ignore unknown pragmas first.
|
||||
fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Wunknown-pragmas\"\n")
|
||||
fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Wpragmas\"\n")
|
||||
fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Waddress-of-packed-member\"\n")
|
||||
|
||||
fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__);\n")
|
||||
fmt.Fprintf(fgcc, "extern __SIZE_TYPE__ _cgo_wait_runtime_init_done();\n")
|
||||
fmt.Fprintf(fgcc, "extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
|
||||
fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n")
|
||||
fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);")
|
||||
fmt.Fprintf(fgcc, "%s\n", tsanProlog)
|
||||
@ -1485,10 +1491,11 @@ __cgo_size_assert(double, 8)
|
||||
|
||||
extern char* _cgo_topofstack(void);
|
||||
|
||||
/* We use packed structs, but they are always aligned. */
|
||||
/* The pragmas and address-of-packed-member are not recognized as warning groups in clang 3.4.1, so ignore unknown pragmas first. */
|
||||
/* remove as part of #27619 (all: drop support for FreeBSD 10). */
|
||||
|
||||
/*
|
||||
We use packed structs, but they are always aligned.
|
||||
The pragmas and address-of-packed-member are only recognized as warning
|
||||
groups in clang 4.0+, so ignore unknown pragmas first.
|
||||
*/
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
|
||||
@ -1929,5 +1936,5 @@ static void GoInit(void) {
|
||||
runtime_iscgo = 1;
|
||||
}
|
||||
|
||||
extern __SIZE_TYPE__ _cgo_wait_runtime_init_done() __attribute__ ((weak));
|
||||
extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(void) __attribute__ ((weak));
|
||||
`
|
||||
|
@ -21,7 +21,7 @@
|
||||
// fix update packages to use new APIs
|
||||
// fmt gofmt (reformat) package sources
|
||||
// generate generate Go files by processing source
|
||||
// get download and install packages and dependencies
|
||||
// get add dependencies to current module and install them
|
||||
// install compile and install packages and dependencies
|
||||
// list list packages or modules
|
||||
// mod module maintenance
|
||||
@ -47,6 +47,8 @@
|
||||
// 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
|
||||
@ -73,8 +75,8 @@
|
||||
// Build compiles the packages named by the import paths,
|
||||
// along with their dependencies, but it does not install the results.
|
||||
//
|
||||
// If the arguments to build are a list of .go files, build treats
|
||||
// them as a list of source files specifying a single package.
|
||||
// If the arguments to build are a list of .go files from a single directory,
|
||||
// build treats them as a list of source files specifying a single package.
|
||||
//
|
||||
// When compiling a single main package, build writes
|
||||
// the resulting executable to an output file named after
|
||||
@ -88,10 +90,10 @@
|
||||
//
|
||||
// When compiling packages, build ignores files that end in '_test.go'.
|
||||
//
|
||||
// The -o flag, only allowed when compiling a single package,
|
||||
// forces build to write the resulting executable or object
|
||||
// to the named output file, instead of the default behavior described
|
||||
// in the last two paragraphs.
|
||||
// The -o flag forces build to write the resulting executable or object
|
||||
// to the named output file or directory, instead of the default behavior described
|
||||
// in the last two paragraphs. If the named output is a directory that exists,
|
||||
// then any resulting executables will be written to that directory.
|
||||
//
|
||||
// The -i flag installs the packages that are dependencies of the target.
|
||||
//
|
||||
@ -150,10 +152,18 @@
|
||||
// install and load all packages from dir instead of the usual locations.
|
||||
// For example, when building with a non-standard configuration,
|
||||
// use -pkgdir to keep generated packages in a separate location.
|
||||
// -tags 'tag list'
|
||||
// a space-separated list of build tags to consider satisfied during the
|
||||
// -tags tag,list
|
||||
// a comma-separated list of build tags to consider satisfied during the
|
||||
// build. For more information about build tags, see the description of
|
||||
// build constraints in the documentation for the go/build package.
|
||||
// (Earlier versions of Go used a space-separated list, and that form
|
||||
// is deprecated but still recognized.)
|
||||
// -trimpath
|
||||
// remove all file system paths from the resulting executable.
|
||||
// Instead of absolute file system paths, the recorded file names
|
||||
// will begin with either "go" (for the standard library),
|
||||
// or a module path@version (when using modules),
|
||||
// or a plain import path (when using GOPATH).
|
||||
// -toolexec 'cmd args'
|
||||
// a program to use to invoke toolchain programs like vet and asm.
|
||||
// For example, instead of running asm, the go command will run
|
||||
@ -201,7 +211,8 @@
|
||||
// so go clean is mainly concerned with object files left by other
|
||||
// tools or by manual invocations of go build.
|
||||
//
|
||||
// Specifically, clean removes the following files from each of the
|
||||
// If a package argument is given or the -i or -r flag is set,
|
||||
// clean removes the following files from each of the
|
||||
// source directories corresponding to the import paths:
|
||||
//
|
||||
// _obj/ old object directory, left from Makefiles
|
||||
@ -366,7 +377,7 @@
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// go env [-json] [var ...]
|
||||
// go env [-json] [-u] [-w] [var ...]
|
||||
//
|
||||
// Env prints Go environment information.
|
||||
//
|
||||
@ -378,6 +389,14 @@
|
||||
// The -json flag prints the environment in JSON format
|
||||
// instead of as a shell script.
|
||||
//
|
||||
// The -u flag requires one or more arguments and unsets
|
||||
// the default setting for the named environment variables,
|
||||
// if one has been set with 'go env -w'.
|
||||
//
|
||||
// The -w flag requires one or more arguments of the
|
||||
// form NAME=VALUE and changes the default settings
|
||||
// of the named environment variables to the given values.
|
||||
//
|
||||
// For more about environment variables, see 'go help environment'.
|
||||
//
|
||||
//
|
||||
@ -503,11 +522,13 @@
|
||||
// "go tool foo".
|
||||
//
|
||||
// Generate processes packages in the order given on the command line,
|
||||
// one at a time. If the command line lists .go files, they are treated
|
||||
// as a single package. Within a package, generate processes the
|
||||
// one at a time. If the command line lists .go files from a single directory,
|
||||
// they are treated as a single package. Within a package, generate processes the
|
||||
// source files in a package in file name order, one at a time. Within
|
||||
// a source file, generate runs generators in the order they appear
|
||||
// in the file, one at a time.
|
||||
// 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.
|
||||
//
|
||||
// If any generator returns an error exit status, "go generate" skips
|
||||
// all further processing for that package.
|
||||
@ -533,67 +554,116 @@
|
||||
// For more about specifying packages, see 'go help packages'.
|
||||
//
|
||||
//
|
||||
// Download and install packages and dependencies
|
||||
// Add dependencies to current module and install them
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]
|
||||
// go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]
|
||||
//
|
||||
// Get downloads the packages named by the import paths, along with their
|
||||
// dependencies. It then installs the named packages, like 'go install'.
|
||||
// Get resolves and adds dependencies to the current development module
|
||||
// and then builds and installs them.
|
||||
//
|
||||
// The -d flag instructs get to stop after downloading the packages; that is,
|
||||
// it instructs get not to install the packages.
|
||||
// The first step is to resolve which dependencies to add.
|
||||
//
|
||||
// The -f flag, valid only when -u is set, forces get -u not to verify that
|
||||
// each package has been checked out from the source control repository
|
||||
// implied by its import path. This can be useful if the source is a local fork
|
||||
// of the original.
|
||||
// For each named package or package pattern, get must decide which version of
|
||||
// the corresponding module to use. By default, get chooses the latest tagged
|
||||
// release version, such as v0.4.5 or v1.2.3. If there are no tagged release
|
||||
// versions, get chooses the latest tagged pre-release version, such as
|
||||
// v0.0.1-pre1. If there are no tagged versions at all, get chooses the latest
|
||||
// known commit.
|
||||
//
|
||||
// The -fix flag instructs get to run the fix tool on the downloaded packages
|
||||
// before resolving dependencies or building the code.
|
||||
// This default version selection can be overridden by adding an @version
|
||||
// suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
|
||||
// For modules stored in source control repositories, the version suffix can
|
||||
// also be a commit hash, branch identifier, or other syntax known to the
|
||||
// source control system, as in 'go get golang.org/x/text@master'.
|
||||
//
|
||||
// If a module under consideration is already a dependency of the current
|
||||
// development module, then get will update the required version.
|
||||
// Specifying a version earlier than the current required version is valid and
|
||||
// downgrades the dependency. The version suffix @none indicates that the
|
||||
// dependency should be removed entirely, downgrading or removing modules
|
||||
// depending on it as needed.
|
||||
//
|
||||
// The version suffix @latest explicitly requests the latest minor release of the
|
||||
// given path. The suffix @patch requests the latest patch release: if the path
|
||||
// is already in the build list, the selected version will have the same minor
|
||||
// version. If the path is not already in the build list, @patch is equivalent
|
||||
// to @latest. Neither @latest nor @patch will cause 'go get' to downgrade a module
|
||||
// in the build list if it is required at a newer pre-release version that is
|
||||
// newer than the latest released version.
|
||||
//
|
||||
// Although get defaults to using the latest version of the module containing
|
||||
// a named package, it does not use the latest version of that module's
|
||||
// dependencies. Instead it prefers to use the specific dependency versions
|
||||
// requested by that module. For example, if the latest A requires module
|
||||
// B v1.2.3, while B v1.2.4 and v1.3.1 are also available, then 'go get A'
|
||||
// will use the latest A but then use B v1.2.3, as requested by A. (If there
|
||||
// are competing requirements for a particular module, then 'go get' resolves
|
||||
// those requirements by taking the maximum requested version.)
|
||||
//
|
||||
// The -t flag instructs get to consider modules needed to build tests of
|
||||
// packages specified on the command line.
|
||||
//
|
||||
// The -u flag instructs get to update modules providing dependencies
|
||||
// of packages named on the command line to use newer minor or patch
|
||||
// releases when available. Continuing the previous example, 'go get -u A'
|
||||
// will use the latest A with B v1.3.1 (not B v1.2.3). If B requires module C,
|
||||
// but C does not provide any packages needed to build packages in A
|
||||
// (not including tests), then C will not be updated.
|
||||
//
|
||||
// The -u=patch flag (not -u patch) also instructs get to update dependencies,
|
||||
// but changes the default to select patch releases.
|
||||
// Continuing the previous example,
|
||||
// 'go get -u=patch A@latest' will use the latest A with B v1.2.4 (not B v1.2.3),
|
||||
// while 'go get -u=patch A' will use a patch release of A instead.
|
||||
//
|
||||
// When the -t and -u flags are used together, get will update
|
||||
// test dependencies as well.
|
||||
//
|
||||
// In general, adding a new dependency may require upgrading
|
||||
// existing dependencies to keep a working build, and 'go get' does
|
||||
// this automatically. Similarly, downgrading one dependency may
|
||||
// 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.
|
||||
//
|
||||
// The -t flag instructs get to also download the packages required to build
|
||||
// the tests for the specified packages.
|
||||
// The second step is to download (if needed), build, and install
|
||||
// the named packages.
|
||||
//
|
||||
// The -u flag instructs get to use the network to update the named packages
|
||||
// and their dependencies. By default, get uses the network to check out
|
||||
// missing packages but does not use it to look for updates to existing packages.
|
||||
// If an argument names a module but not a package (because there is no
|
||||
// Go source code in the module's root directory), then the install step
|
||||
// is skipped for that argument, instead of causing a build failure.
|
||||
// For example 'go get golang.org/x/perf' succeeds even though there
|
||||
// is no code corresponding to that import path.
|
||||
//
|
||||
// The -v flag enables verbose progress and debug output.
|
||||
// Note that package patterns are allowed and are expanded after resolving
|
||||
// the module versions. For example, 'go get golang.org/x/perf/cmd/...'
|
||||
// adds the latest golang.org/x/perf and then installs the commands in that
|
||||
// latest version.
|
||||
//
|
||||
// Get also accepts build flags to control the installation. See 'go help build'.
|
||||
// The -d flag instructs get to download the source code needed to build
|
||||
// the named packages, including downloading necessary dependencies,
|
||||
// but not to build and install them.
|
||||
//
|
||||
// When checking out a new package, get creates the target directory
|
||||
// GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
|
||||
// get uses the first one. For more details see: 'go help gopath'.
|
||||
// With no package arguments, 'go get' applies to Go package in the
|
||||
// current directory, if any. In particular, 'go get -u' and
|
||||
// 'go get -u=patch' update all the dependencies of that package.
|
||||
// With no package arguments and also without -u, 'go get' is not much more
|
||||
// than 'go install', and 'go get -d' not much more than 'go list'.
|
||||
//
|
||||
// When checking out or updating a package, get looks for a branch or tag
|
||||
// that matches the locally installed version of Go. The most important
|
||||
// rule is that if the local installation is running version "go1", get
|
||||
// searches for a branch or tag named "go1". If no such version exists
|
||||
// it retrieves the default branch of the package.
|
||||
//
|
||||
// When go get checks out or updates a Git repository,
|
||||
// it also updates any git submodules referenced by the repository.
|
||||
//
|
||||
// Get never checks out or updates code stored in vendor directories.
|
||||
// For more about modules, see 'go help modules'.
|
||||
//
|
||||
// For more about specifying packages, see 'go help packages'.
|
||||
//
|
||||
// For more about how 'go get' finds source code to
|
||||
// download, see 'go help importpath'.
|
||||
// This text describes the behavior of get using modules to manage source
|
||||
// code and dependencies. If instead the go command is running in GOPATH
|
||||
// mode, the details of get's flags and effects change, as does 'go help get'.
|
||||
// See 'go help modules' and 'go help gopath-get'.
|
||||
//
|
||||
// This text describes the behavior of get when using GOPATH
|
||||
// to manage source code and dependencies.
|
||||
// If instead the go command is running in module-aware mode,
|
||||
// the details of get's flags and effects change, as does 'go help get'.
|
||||
// See 'go help modules' and 'go help module-get'.
|
||||
//
|
||||
// See also: go build, go install, go clean.
|
||||
// See also: go build, go install, go clean, go mod.
|
||||
//
|
||||
//
|
||||
// Compile and install packages and dependencies
|
||||
@ -604,6 +674,15 @@
|
||||
//
|
||||
// Install compiles and installs the packages named by the import paths.
|
||||
//
|
||||
// Executables are installed in the directory named by the GOBIN environment
|
||||
// variable, which defaults to $GOPATH/bin or $HOME/go/bin if the GOPATH
|
||||
// environment variable is not set. Executables in $GOROOT
|
||||
// are installed in $GOROOT/bin or $GOTOOLDIR instead of $GOBIN.
|
||||
//
|
||||
// When module-aware mode is disabled, other packages are installed in the
|
||||
// directory $GOPATH/pkg/$GOOS_$GOARCH. When module-aware mode is enabled,
|
||||
// other packages are built and cached but not installed.
|
||||
//
|
||||
// The -i flag installs the dependencies of the named packages as well.
|
||||
//
|
||||
// For more about the build flags, see 'go help build'.
|
||||
@ -648,7 +727,7 @@
|
||||
// StaleReason string // explanation for Stale==true
|
||||
// Root string // Go root or Go path dir containing this package
|
||||
// ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
// BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
// BinaryOnly bool // binary-only package (no longer supported)
|
||||
// ForTest string // package is only for use in named test
|
||||
// Export string // file containing export data (when using -export)
|
||||
// Module *Module // info about package's containing module, if any (can be nil)
|
||||
@ -790,17 +869,18 @@
|
||||
// applied to a Go struct, but now a Module struct:
|
||||
//
|
||||
// type Module struct {
|
||||
// Path string // module path
|
||||
// Version string // module version
|
||||
// Versions []string // available module versions (with -versions)
|
||||
// Replace *Module // replaced by this module
|
||||
// Time *time.Time // time version was created
|
||||
// Update *Module // available update, if any (with -u)
|
||||
// Main bool // is this the main module?
|
||||
// Indirect bool // is this module only an indirect dependency of main module?
|
||||
// Dir string // directory holding files for this module, if any
|
||||
// GoMod string // path to go.mod file for this module, if any
|
||||
// Error *ModuleError // error loading module
|
||||
// Path string // module path
|
||||
// Version string // module version
|
||||
// Versions []string // available module versions (with -versions)
|
||||
// Replace *Module // replaced by this module
|
||||
// Time *time.Time // time version was created
|
||||
// Update *Module // available update, if any (with -u)
|
||||
// Main bool // is this the main module?
|
||||
// Indirect bool // is this module only an indirect dependency of main module?
|
||||
// Dir string // directory holding files for this module, if any
|
||||
// GoMod string // path to go.mod file for this module, if any
|
||||
// GoVersion string // go version used in module
|
||||
// Error *ModuleError // error loading module
|
||||
// }
|
||||
//
|
||||
// type ModuleError struct {
|
||||
@ -1129,7 +1209,7 @@
|
||||
// go run [build flags] [-exec xprog] package [arguments...]
|
||||
//
|
||||
// Run compiles and runs the named main Go package.
|
||||
// Typically the package is specified as a list of .go source files,
|
||||
// Typically the package is specified as a list of .go source files from a single directory,
|
||||
// but it may also be an import path, file system path, or pattern
|
||||
// matching a single known package, as in 'go run .' or 'go run my/cmd'.
|
||||
//
|
||||
@ -1213,7 +1293,10 @@
|
||||
// line. If a package test fails, go test prints the full test output.
|
||||
// If invoked with the -bench or -v flag, go test prints the full
|
||||
// output even for passing package tests, in order to display the
|
||||
// requested benchmark results or verbose logging.
|
||||
// requested benchmark results or verbose logging. After the package
|
||||
// tests for all of the listed packages finish, and their output is
|
||||
// printed, go test prints a final 'FAIL' status if any package test
|
||||
// has failed.
|
||||
//
|
||||
// In package list mode only, go test caches successful package test
|
||||
// results to avoid unnecessary repeated running of tests. When the
|
||||
@ -1293,9 +1376,27 @@
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// go version
|
||||
// go version [-m] [-v] [file ...]
|
||||
//
|
||||
// Version prints the Go version, as reported by runtime.Version.
|
||||
// Version prints the build information for Go executables.
|
||||
//
|
||||
// Go version reports the Go version used to build each of the named
|
||||
// executable files.
|
||||
//
|
||||
// If no files are named on the command line, go version prints its own
|
||||
// version information.
|
||||
//
|
||||
// If a directory is named, go version walks that directory, recursively,
|
||||
// looking for recognized Go binaries and reporting their versions.
|
||||
// By default, go version does not report unrecognized files found
|
||||
// during a directory scan. The -v flag causes it to report unrecognized files.
|
||||
//
|
||||
// The -m flag causes go version to print each executable's embedded
|
||||
// module version information, when available. In the output, the module
|
||||
// information consists of multiple lines following the version line, each
|
||||
// indented by a leading tab character.
|
||||
//
|
||||
// See also: go doc runtime/debug.BuildInfo.
|
||||
//
|
||||
//
|
||||
// Report likely mistakes in packages
|
||||
@ -1373,6 +1474,9 @@
|
||||
// Build the listed main packages, plus all packages that they
|
||||
// import, into a Go plugin. Packages not named main are ignored.
|
||||
//
|
||||
// On AIX, when linking a C program that uses a Go archive built with
|
||||
// -buildmode=c-archive, you must pass -Wl,-bnoobjreorder to the C compiler.
|
||||
//
|
||||
//
|
||||
// Calling between Go and C
|
||||
//
|
||||
@ -1434,10 +1538,17 @@
|
||||
//
|
||||
// Environment variables
|
||||
//
|
||||
// The go command, and the tools it invokes, examine a few different
|
||||
// environment variables. For many of these, you can see the default
|
||||
// value of on your system by running 'go env NAME', where NAME is the
|
||||
// name of the variable.
|
||||
// The go command and the tools it invokes consult environment variables
|
||||
// for configuration. If an environment variable is unset, the go command
|
||||
// uses a sensible default setting. To see the effective setting of the
|
||||
// variable <NAME>, run 'go env <NAME>'. To change the default setting,
|
||||
// run 'go env -w <NAME>=<VALUE>'. Defaults changed using 'go env -w'
|
||||
// are recorded in a Go environment configuration file stored in the
|
||||
// per-user configuration directory, as reported by os.UserConfigDir.
|
||||
// The location of the configuration file can be changed by setting
|
||||
// the environment variable GOENV, and 'go env GOENV' prints the
|
||||
// effective location, but 'go env -w' cannot change the default location.
|
||||
// See 'go help env' for details.
|
||||
//
|
||||
// General-purpose environment variables:
|
||||
//
|
||||
@ -1451,10 +1562,15 @@
|
||||
// GOCACHE
|
||||
// The directory where the go command will store cached
|
||||
// information for reuse in future builds.
|
||||
// GOENV
|
||||
// The location of the Go environment configuration file.
|
||||
// Cannot be set using 'go env -w'.
|
||||
// GOFLAGS
|
||||
// A space-separated list of -flag=value settings to apply
|
||||
// to go commands by default, when the given flag is known by
|
||||
// the current command. Flags listed on the command-line
|
||||
// the current command. Each entry must be a standalone flag.
|
||||
// Because the entries are space-separated, flag values must
|
||||
// not contain spaces. Flags listed on the command line
|
||||
// are applied after this list and therefore override it.
|
||||
// GOOS
|
||||
// The operating system for which to compile code.
|
||||
@ -1462,22 +1578,27 @@
|
||||
// GOPATH
|
||||
// For more details see: 'go help gopath'.
|
||||
// GOPROXY
|
||||
// URL of Go module proxy. See 'go help goproxy'.
|
||||
// GORACE
|
||||
// Options for the race detector.
|
||||
// See https://golang.org/doc/articles/race_detector.html.
|
||||
// URL of Go module proxy. See 'go help modules'.
|
||||
// GOPRIVATE, GONOPROXY, GONOSUMDB
|
||||
// Comma-separated list of glob patterns (in the syntax of Go's path.Match)
|
||||
// of module path prefixes that should always be fetched directly
|
||||
// or that should not be compared against the checksum database.
|
||||
// See 'go help module-private'.
|
||||
// GOROOT
|
||||
// The root of the go tree.
|
||||
// GOSUMDB
|
||||
// The name of checksum database to use and optionally its public key and
|
||||
// URL. See 'go help module-auth'.
|
||||
// GOTMPDIR
|
||||
// The directory where the go command will write
|
||||
// temporary source files, packages, and binaries.
|
||||
//
|
||||
// Each entry in the GOFLAGS list must be a standalone flag.
|
||||
// Because the entries are space-separated, flag values must
|
||||
// not contain spaces.
|
||||
//
|
||||
// Environment variables for use with cgo:
|
||||
//
|
||||
// AR
|
||||
// The command to use to manipulate library archives when
|
||||
// building with the gccgo compiler.
|
||||
// The default is 'ar'.
|
||||
// CC
|
||||
// The command to use to compile C code.
|
||||
// CGO_ENABLED
|
||||
@ -1507,12 +1628,10 @@
|
||||
// but for the linker.
|
||||
// CXX
|
||||
// The command to use to compile C++ code.
|
||||
// FC
|
||||
// The command to use to compile Fortran code.
|
||||
// PKG_CONFIG
|
||||
// Path to pkg-config tool.
|
||||
// AR
|
||||
// The command to use to manipulate library archives when
|
||||
// building with the gccgo compiler.
|
||||
// The default is 'ar'.
|
||||
//
|
||||
// Architecture-specific environment variables:
|
||||
//
|
||||
@ -1528,6 +1647,9 @@
|
||||
// GOMIPS64
|
||||
// For GOARCH=mips64{,le}, whether to use floating point instructions.
|
||||
// Valid values are hardfloat (default), softfloat.
|
||||
// GOWASM
|
||||
// For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
|
||||
// Valid values are satconv, signext.
|
||||
//
|
||||
// Special-purpose environment variables:
|
||||
//
|
||||
@ -1544,14 +1666,18 @@
|
||||
// when using -linkmode=auto with code that uses cgo.
|
||||
// Set to 0 to disable external linking mode, 1 to enable it.
|
||||
// GIT_ALLOW_PROTOCOL
|
||||
// Defined by Git. A colon-separated list of schemes that are allowed to be used
|
||||
// with git fetch/clone. If set, any scheme not explicitly mentioned will be
|
||||
// considered insecure by 'go get'.
|
||||
// Defined by Git. A colon-separated list of schemes that are allowed
|
||||
// to be used with git fetch/clone. If set, any scheme not explicitly
|
||||
// mentioned will be considered insecure by 'go get'.
|
||||
// Because the variable is defined by Git, the default value cannot
|
||||
// be set using 'go env -w'.
|
||||
//
|
||||
// Additional information available from 'go env' but not read from the environment:
|
||||
//
|
||||
// GOEXE
|
||||
// The executable file name suffix (".exe" on Windows, "" on other systems).
|
||||
// GOGCCFLAGS
|
||||
// A space-separated list of arguments supplied to the CC command.
|
||||
// GOHOSTARCH
|
||||
// The architecture (GOARCH) of the Go toolchain binaries.
|
||||
// GOHOSTOS
|
||||
@ -1598,15 +1724,6 @@
|
||||
// line comment. See the go/build package documentation for
|
||||
// more details.
|
||||
//
|
||||
// Through the Go 1.12 release, non-test Go source files can also include
|
||||
// a //go:binary-only-package comment, indicating that the package
|
||||
// sources are included for documentation only and must not be used to
|
||||
// build the package binary. This enables distribution of Go packages in
|
||||
// their compiled form alone. Even binary-only packages require accurate
|
||||
// import blocks listing required dependencies, so that those
|
||||
// dependencies can be supplied when linking the resulting command.
|
||||
// Note that this feature is scheduled to be removed after the Go 1.12 release.
|
||||
//
|
||||
//
|
||||
// The go.mod file
|
||||
//
|
||||
@ -1689,6 +1806,13 @@
|
||||
// including go build, go get, go install, go list, go test, go mod graph,
|
||||
// go mod tidy, and go mod why.
|
||||
//
|
||||
// The expected language version, set by the go directive, determines
|
||||
// which language features are available when compiling the module.
|
||||
// Language features available in that version will be available for use.
|
||||
// Language features removed in earlier versions, or added in later versions,
|
||||
// will not be available. Note that the language version does not affect
|
||||
// build tags, which are determined by the Go release being used.
|
||||
//
|
||||
//
|
||||
// GOPATH environment variable
|
||||
//
|
||||
@ -1845,17 +1969,73 @@
|
||||
// See https://golang.org/s/go15vendor for details.
|
||||
//
|
||||
//
|
||||
// Module proxy protocol
|
||||
// Legacy GOPATH go get
|
||||
//
|
||||
// The go command by default downloads modules from version control systems
|
||||
// directly, just as 'go get' always has. The GOPROXY environment variable allows
|
||||
// further control over the download source. If GOPROXY is unset, is the empty string,
|
||||
// or is the string "direct", downloads use the default direct connection to version
|
||||
// control systems. Setting GOPROXY to "off" disallows downloading modules from
|
||||
// any source. Otherwise, GOPROXY is expected to be the URL of a module proxy,
|
||||
// in which case the go command will fetch all modules from that proxy.
|
||||
// No matter the source of the modules, downloaded modules must match existing
|
||||
// entries in go.sum (see 'go help modules' for discussion of verification).
|
||||
// The 'go get' command changes behavior depending on whether the
|
||||
// go command is running in module-aware mode or legacy GOPATH mode.
|
||||
// This help text, accessible as 'go help gopath-get' even in module-aware mode,
|
||||
// describes 'go get' as it operates in legacy GOPATH mode.
|
||||
//
|
||||
// Usage: go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]
|
||||
//
|
||||
// Get downloads the packages named by the import paths, along with their
|
||||
// dependencies. It then installs the named packages, like 'go install'.
|
||||
//
|
||||
// The -d flag instructs get to stop after downloading the packages; that is,
|
||||
// it instructs get not to install the packages.
|
||||
//
|
||||
// The -f flag, valid only when -u is set, forces get -u not to verify that
|
||||
// each package has been checked out from the source control repository
|
||||
// implied by its import path. This can be useful if the source is a local fork
|
||||
// of the original.
|
||||
//
|
||||
// The -fix flag instructs get to run the fix tool on the downloaded packages
|
||||
// before resolving dependencies or building the code.
|
||||
//
|
||||
// The -insecure flag permits fetching from repositories and resolving
|
||||
// custom domains using insecure schemes such as HTTP. Use with caution.
|
||||
//
|
||||
// The -t flag instructs get to also download the packages required to build
|
||||
// the tests for the specified packages.
|
||||
//
|
||||
// The -u flag instructs get to use the network to update the named packages
|
||||
// and their dependencies. By default, get uses the network to check out
|
||||
// missing packages but does not use it to look for updates to existing packages.
|
||||
//
|
||||
// The -v flag enables verbose progress and debug output.
|
||||
//
|
||||
// Get also accepts build flags to control the installation. See 'go help build'.
|
||||
//
|
||||
// When checking out a new package, get creates the target directory
|
||||
// GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
|
||||
// get uses the first one. For more details see: 'go help gopath'.
|
||||
//
|
||||
// When checking out or updating a package, get looks for a branch or tag
|
||||
// that matches the locally installed version of Go. The most important
|
||||
// rule is that if the local installation is running version "go1", get
|
||||
// searches for a branch or tag named "go1". If no such version exists
|
||||
// it retrieves the default branch of the package.
|
||||
//
|
||||
// When go get checks out or updates a Git repository,
|
||||
// it also updates any git submodules referenced by the repository.
|
||||
//
|
||||
// Get never checks out or updates code stored in vendor directories.
|
||||
//
|
||||
// For more about specifying packages, see 'go help packages'.
|
||||
//
|
||||
// For more about how 'go get' finds source code to
|
||||
// download, see 'go help importpath'.
|
||||
//
|
||||
// This text describes the behavior of get when using GOPATH
|
||||
// to manage source code and dependencies.
|
||||
// If instead the go command is running in module-aware mode,
|
||||
// the details of get's flags and effects change, as does 'go help get'.
|
||||
// See 'go help modules' and 'go help module-get'.
|
||||
//
|
||||
// See also: go build, go install, go clean.
|
||||
//
|
||||
//
|
||||
// Module proxy protocol
|
||||
//
|
||||
// A Go module proxy is any web server that can respond to GET requests for
|
||||
// URLs of a specified form. The requests have no query parameters, so even
|
||||
@ -2104,34 +2284,28 @@
|
||||
// Modules replace the old GOPATH-based approach to specifying
|
||||
// which source files are used in a given build.
|
||||
//
|
||||
// Preliminary module support
|
||||
// Module support
|
||||
//
|
||||
// Go 1.11 includes preliminary support for Go modules,
|
||||
// including a new module-aware 'go get' command.
|
||||
// We intend to keep revising this support, while preserving compatibility,
|
||||
// until it can be declared official (no longer preliminary),
|
||||
// and then at a later point we may remove support for work
|
||||
// in GOPATH and the old 'go get' command.
|
||||
// Go 1.13 includes support for Go modules. Module-aware mode is active by default
|
||||
// whenever a go.mod file is found in, or in a parent of, the current directory.
|
||||
//
|
||||
// The quickest way to take advantage of the new Go 1.11 module support
|
||||
// is to check out your repository into a directory outside GOPATH/src,
|
||||
// create a go.mod file (described in the next section) there, and run
|
||||
// The quickest way to take advantage of module support is to check out your
|
||||
// repository, create a go.mod file (described in the next section) there, and run
|
||||
// go commands from within that file tree.
|
||||
//
|
||||
// For more fine-grained control, the module support in Go 1.11 respects
|
||||
// For more fine-grained control, Go 1.13 continues to respect
|
||||
// a temporary environment variable, GO111MODULE, which can be set to one
|
||||
// of three string values: off, on, or auto (the default).
|
||||
// If GO111MODULE=off, then the go command never uses the
|
||||
// new module support. Instead it looks in vendor directories and GOPATH
|
||||
// to find dependencies; we now refer to this as "GOPATH mode."
|
||||
// If GO111MODULE=on, then the go command requires the use of modules,
|
||||
// never consulting GOPATH. We refer to this as the command being
|
||||
// module-aware or running in "module-aware mode".
|
||||
// If GO111MODULE=auto or is unset, then the go command enables or
|
||||
// disables module support based on the current directory.
|
||||
// Module support is enabled only when the current directory is outside
|
||||
// GOPATH/src and itself contains a go.mod file or is below a directory
|
||||
// containing a go.mod file.
|
||||
// never consulting GOPATH. We refer to this as the command
|
||||
// being module-aware or running in "module-aware mode".
|
||||
// If GO111MODULE=off, then the go command never uses
|
||||
// module support. Instead it looks in vendor directories and GOPATH
|
||||
// to find dependencies; we now refer to this as "GOPATH mode."
|
||||
// If GO111MODULE=auto or is unset, then the go command enables or disables
|
||||
// module support based on the current directory.
|
||||
// Module support is enabled only when the current directory contains a
|
||||
// go.mod file or is below a directory containing a go.mod file.
|
||||
//
|
||||
// In module-aware mode, GOPATH no longer defines the meaning of imports
|
||||
// during a build, but it still stores downloaded dependencies (in GOPATH/pkg/mod)
|
||||
@ -2422,26 +2596,35 @@
|
||||
//
|
||||
// Module downloading and verification
|
||||
//
|
||||
// The go command maintains, in the main module's root directory alongside
|
||||
// go.mod, a file named go.sum containing the expected cryptographic checksums
|
||||
// of the content of specific module versions. Each time a dependency is
|
||||
// used, its checksum is added to go.sum if missing or else required to match
|
||||
// the existing entry in go.sum.
|
||||
// The go command can fetch modules from a proxy or connect to source control
|
||||
// servers directly, according to the setting of the GOPROXY environment
|
||||
// variable (see 'go help env'). The default setting for GOPROXY is
|
||||
// "https://proxy.golang.org,direct", which means to try the
|
||||
// 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.
|
||||
//
|
||||
// The go command maintains a cache of downloaded packages and computes
|
||||
// and records the cryptographic checksum of each package at download time.
|
||||
// In normal operation, the go command checks these pre-computed checksums
|
||||
// against the main module's go.sum file, instead of recomputing them on
|
||||
// each command invocation. The 'go mod verify' command checks that
|
||||
// the cached copies of module downloads still match both their recorded
|
||||
// checksums and the entries in go.sum.
|
||||
// The GOPRIVATE and GONOPROXY environment variables allow bypassing
|
||||
// the proxy for selected modules. See 'go help module-private' for details.
|
||||
//
|
||||
// The go command can fetch modules from a proxy instead of connecting
|
||||
// to source control systems directly, according to the setting of the GOPROXY
|
||||
// environment variable.
|
||||
// No matter the source of the modules, the go command checks downloads against
|
||||
// known checksums, to detect unexpected changes in the content of any specific
|
||||
// module version from one day to the next. This check first consults the current
|
||||
// module's go.sum file but falls back to the Go checksum database, controlled by
|
||||
// the GOSUMDB and GONOSUMDB environment variables. See 'go help module-auth'
|
||||
// for details.
|
||||
//
|
||||
// See 'go help goproxy' for details about the proxy and also the format of
|
||||
// the cached downloaded packages.
|
||||
// See 'go help goproxy' for details about the proxy protocol and also
|
||||
// the format of the cached downloaded packages.
|
||||
//
|
||||
// Modules and vendoring
|
||||
//
|
||||
@ -2463,108 +2646,135 @@
|
||||
// are still ignored.
|
||||
//
|
||||
//
|
||||
// Module-aware go get
|
||||
// Module authentication using go.sum
|
||||
//
|
||||
// The 'go get' command changes behavior depending on whether the
|
||||
// go command is running in module-aware mode or legacy GOPATH mode.
|
||||
// This help text, accessible as 'go help module-get' even in legacy GOPATH mode,
|
||||
// describes 'go get' as it operates in module-aware mode.
|
||||
// The go command tries to authenticate every downloaded module,
|
||||
// checking that the bits downloaded for a specific module version today
|
||||
// match bits downloaded yesterday. This ensures repeatable builds
|
||||
// and detects introduction of unexpected changes, malicious or not.
|
||||
//
|
||||
// Usage: go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]
|
||||
// In each module's root, alongside go.mod, the go command maintains
|
||||
// a file named go.sum containing the cryptographic checksums of the
|
||||
// module's dependencies.
|
||||
//
|
||||
// Get resolves and adds dependencies to the current development module
|
||||
// and then builds and installs them.
|
||||
// The form of each line in go.sum is three fields:
|
||||
//
|
||||
// The first step is to resolve which dependencies to add.
|
||||
// <module> <version>[/go.mod] <hash>
|
||||
//
|
||||
// For each named package or package pattern, get must decide which version of
|
||||
// the corresponding module to use. By default, get chooses the latest tagged
|
||||
// release version, such as v0.4.5 or v1.2.3. If there are no tagged release
|
||||
// versions, get chooses the latest tagged prerelease version, such as
|
||||
// v0.0.1-pre1. If there are no tagged versions at all, get chooses the latest
|
||||
// known commit.
|
||||
// Each known module version results in two lines in the go.sum file.
|
||||
// The first line gives the hash of the module version's file tree.
|
||||
// The second line appends "/go.mod" to the version and gives the hash
|
||||
// of only the module version's (possibly synthesized) go.mod file.
|
||||
// The go.mod-only hash allows downloading and authenticating a
|
||||
// module version's go.mod file, which is needed to compute the
|
||||
// dependency graph, without also downloading all the module's source code.
|
||||
//
|
||||
// This default version selection can be overridden by adding an @version
|
||||
// suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'.
|
||||
// For modules stored in source control repositories, the version suffix can
|
||||
// also be a commit hash, branch identifier, or other syntax known to the
|
||||
// source control system, as in 'go get golang.org/x/text@master'.
|
||||
// The version suffix @latest explicitly requests the default behavior
|
||||
// described above.
|
||||
// The hash begins with an algorithm prefix of the form "h<N>:".
|
||||
// The only defined algorithm prefix is "h1:", which uses SHA-256.
|
||||
//
|
||||
// If a module under consideration is already a dependency of the current
|
||||
// development module, then get will update the required version.
|
||||
// Specifying a version earlier than the current required version is valid and
|
||||
// downgrades the dependency. The version suffix @none indicates that the
|
||||
// dependency should be removed entirely, downgrading or removing modules
|
||||
// depending on it as needed.
|
||||
// Module authentication failures
|
||||
//
|
||||
// Although get defaults to using the latest version of the module containing
|
||||
// a named package, it does not use the latest version of that module's
|
||||
// dependencies. Instead it prefers to use the specific dependency versions
|
||||
// requested by that module. For example, if the latest A requires module
|
||||
// B v1.2.3, while B v1.2.4 and v1.3.1 are also available, then 'go get A'
|
||||
// will use the latest A but then use B v1.2.3, as requested by A. (If there
|
||||
// are competing requirements for a particular module, then 'go get' resolves
|
||||
// those requirements by taking the maximum requested version.)
|
||||
// The go command maintains a cache of downloaded packages and computes
|
||||
// and records the cryptographic checksum of each package at download time.
|
||||
// In normal operation, the go command checks the main module's go.sum file
|
||||
// against these precomputed checksums instead of recomputing them on
|
||||
// each command invocation. The 'go mod verify' command checks that
|
||||
// the cached copies of module downloads still match both their recorded
|
||||
// checksums and the entries in go.sum.
|
||||
//
|
||||
// The -u flag instructs get to update dependencies to use newer minor or
|
||||
// patch releases when available. Continuing the previous example,
|
||||
// 'go get -u A' will use the latest A with B v1.3.1 (not B v1.2.3).
|
||||
// In day-to-day development, the checksum of a given module version
|
||||
// should never change. Each time a dependency is used by a given main
|
||||
// module, the go command checks its local cached copy, freshly
|
||||
// downloaded or not, against the main module's go.sum. If the checksums
|
||||
// don't match, the go command reports the mismatch as a security error
|
||||
// and refuses to run the build. When this happens, proceed with caution:
|
||||
// code changing unexpectedly means today's build will not match
|
||||
// yesterday's, and the unexpected change may not be beneficial.
|
||||
//
|
||||
// The -u=patch flag (not -u patch) instructs get to update dependencies
|
||||
// to use newer patch releases when available. Continuing the previous example,
|
||||
// 'go get -u=patch A' will use the latest A with B v1.2.4 (not B v1.2.3).
|
||||
// If the go command reports a mismatch in go.sum, the downloaded code
|
||||
// for the reported module version does not match the one used in a
|
||||
// previous build of the main module. It is important at that point
|
||||
// to find out what the right checksum should be, to decide whether
|
||||
// go.sum is wrong or the downloaded code is wrong. Usually go.sum is right:
|
||||
// you want to use the same code you used yesterday.
|
||||
//
|
||||
// In general, adding a new dependency may require upgrading
|
||||
// existing dependencies to keep a working build, and 'go get' does
|
||||
// this automatically. Similarly, downgrading one dependency may
|
||||
// require downgrading other dependencies, and 'go get' does
|
||||
// this automatically as well.
|
||||
// If a downloaded module is not yet included in go.sum and it is a publicly
|
||||
// available module, the go command consults the Go checksum database to fetch
|
||||
// the expected go.sum lines. If the downloaded code does not match those
|
||||
// lines, the go command reports the mismatch and exits. Note that the
|
||||
// database is not consulted for module versions already listed in go.sum.
|
||||
//
|
||||
// The -m flag instructs get to stop here, after resolving, upgrading,
|
||||
// and downgrading modules and updating go.mod. When using -m,
|
||||
// each specified package path must be a module path as well,
|
||||
// not the import path of a package below the module root.
|
||||
// If a go.sum mismatch is reported, it is always worth investigating why
|
||||
// the code downloaded today differs from what was downloaded yesterday.
|
||||
//
|
||||
// The -insecure flag permits fetching from repositories and resolving
|
||||
// custom domains using insecure schemes such as HTTP. Use with caution.
|
||||
// The GOSUMDB environment variable identifies the name of checksum database
|
||||
// to use and optionally its public key and URL, as in:
|
||||
//
|
||||
// The second step is to download (if needed), build, and install
|
||||
// the named packages.
|
||||
// GOSUMDB="sum.golang.org"
|
||||
// GOSUMDB="sum.golang.org+<publickey>"
|
||||
// GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"
|
||||
//
|
||||
// If an argument names a module but not a package (because there is no
|
||||
// Go source code in the module's root directory), then the install step
|
||||
// is skipped for that argument, instead of causing a build failure.
|
||||
// For example 'go get golang.org/x/perf' succeeds even though there
|
||||
// is no code corresponding to that import path.
|
||||
// The go command knows the public key of sum.golang.org; use of any other
|
||||
// database requires giving the public key explicitly. The URL defaults to
|
||||
// "https://" followed by the database name.
|
||||
//
|
||||
// Note that package patterns are allowed and are expanded after resolving
|
||||
// the module versions. For example, 'go get golang.org/x/perf/cmd/...'
|
||||
// adds the latest golang.org/x/perf and then installs the commands in that
|
||||
// latest version.
|
||||
// GOSUMDB defaults to "sum.golang.org", the Go checksum database run by Google.
|
||||
// See https://sum.golang.org/privacy for the service's privacy policy.
|
||||
//
|
||||
// The -d flag instructs get to download the source code needed to build
|
||||
// the named packages, including downloading necessary dependencies,
|
||||
// but not to build and install them.
|
||||
// If GOSUMDB is set to "off", or if "go get" is invoked with the -insecure flag,
|
||||
// the checksum database is not consulted, and all unrecognized modules are
|
||||
// accepted, at the cost of giving up the security guarantee of verified repeatable
|
||||
// downloads for all modules. A better way to bypass the checksum database
|
||||
// for specific modules is to use the GOPRIVATE or GONOSUMDB environment
|
||||
// variables. See 'go help module-private' for details.
|
||||
//
|
||||
// With no package arguments, 'go get' applies to the main module,
|
||||
// and to the Go package in the current directory, if any. In particular,
|
||||
// 'go get -u' and 'go get -u=patch' update all the dependencies of the
|
||||
// main module. With no package arguments and also without -u,
|
||||
// 'go get' is not much more than 'go install', and 'go get -d' not much
|
||||
// more than 'go list'.
|
||||
// The 'go env -w' command (see 'go help env') can be used to set these variables
|
||||
// for future go command invocations.
|
||||
//
|
||||
// For more about modules, see 'go help modules'.
|
||||
//
|
||||
// For more about specifying packages, see 'go help packages'.
|
||||
// Module configuration for non-public modules
|
||||
//
|
||||
// This text describes the behavior of get using modules to manage source
|
||||
// code and dependencies. If instead the go command is running in GOPATH
|
||||
// mode, the details of get's flags and effects change, as does 'go help get'.
|
||||
// See 'go help modules' and 'go help gopath-get'.
|
||||
// The go command defaults to downloading modules from the public Go module
|
||||
// mirror at proxy.golang.org. It also defaults to validating downloaded modules,
|
||||
// regardless of source, against the public Go checksum database at sum.golang.org.
|
||||
// These defaults work well for publicly available source code.
|
||||
//
|
||||
// See also: go build, go install, go clean, go mod.
|
||||
// The GOPRIVATE environment variable controls which modules the go command
|
||||
// considers to be private (not available publicly) and should therefore not use the
|
||||
// proxy or checksum database. The variable is a comma-separated list of
|
||||
// glob patterns (in the syntax of Go's path.Match) of module path prefixes.
|
||||
// For example,
|
||||
//
|
||||
// GOPRIVATE=*.corp.example.com,rsc.io/private
|
||||
//
|
||||
// causes the go command to treat as private any module with a path prefix
|
||||
// matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private,
|
||||
// and rsc.io/private/quux.
|
||||
//
|
||||
// The GOPRIVATE environment variable may be used by other tools as well to
|
||||
// identify non-public modules. For example, an editor could use GOPRIVATE
|
||||
// to decide whether to hyperlink a package import to a godoc.org page.
|
||||
//
|
||||
// For fine-grained control over module download and validation, the GONOPROXY
|
||||
// and GONOSUMDB environment variables accept the same kind of glob list
|
||||
// and override GOPRIVATE for the specific decision of whether to use the proxy
|
||||
// and checksum database, respectively.
|
||||
//
|
||||
// For example, if a company ran a module proxy serving private modules,
|
||||
// users would configure go using:
|
||||
//
|
||||
// GOPRIVATE=*.corp.example.com
|
||||
// GOPROXY=proxy.example.com
|
||||
// GONOPROXY=none
|
||||
//
|
||||
// This would tell the go command and other tools that modules beginning with
|
||||
// a corp.example.com subdomain are private but that the company proxy should
|
||||
// be used for downloading both public and private modules, because
|
||||
// GONOPROXY has been set to a pattern that won't match any modules,
|
||||
// overriding GOPRIVATE.
|
||||
//
|
||||
// The 'go env -w' command (see 'go help env') can be used to set these variables
|
||||
// for future go command invocations.
|
||||
//
|
||||
//
|
||||
// Package lists and patterns
|
||||
|
@ -6,7 +6,6 @@ package main_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cmd/internal/sys"
|
||||
"context"
|
||||
"debug/elf"
|
||||
"debug/macho"
|
||||
@ -27,6 +26,11 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cmd/go/internal/cache"
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/robustio"
|
||||
"cmd/internal/sys"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -118,6 +122,8 @@ 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) {
|
||||
// $GO_GCFLAGS a compiler debug flag known to cmd/dist, make.bash, etc.
|
||||
// It is not a standard go command flag; use os.Getenv, not cfg.Getenv.
|
||||
if os.Getenv("GO_GCFLAGS") != "" {
|
||||
fmt.Fprintf(os.Stderr, "testing: warning: no tests to run\n") // magic string for cmd/go
|
||||
fmt.Printf("cmd/go test is not compatible with $GO_GCFLAGS being set\n")
|
||||
@ -166,6 +172,7 @@ func TestMain(m *testing.M) {
|
||||
defer removeAll(testTmpDir)
|
||||
}
|
||||
|
||||
testGOCACHE = cache.DefaultDir()
|
||||
if canRun {
|
||||
testBin = filepath.Join(testTmpDir, "testbin")
|
||||
if err := os.Mkdir(testBin, 0777); err != nil {
|
||||
@ -212,7 +219,9 @@ func TestMain(m *testing.M) {
|
||||
return
|
||||
}
|
||||
|
||||
out, err := exec.Command(gotool, args...).CombinedOutput()
|
||||
buildCmd := exec.Command(gotool, args...)
|
||||
buildCmd.Env = append(os.Environ(), "GOFLAGS=-mod=vendor")
|
||||
out, err := buildCmd.CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out)
|
||||
os.Exit(2)
|
||||
@ -252,6 +261,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
}
|
||||
// Don't let these environment variables confuse the test.
|
||||
os.Setenv("GOENV", "off")
|
||||
os.Unsetenv("GOBIN")
|
||||
os.Unsetenv("GOPATH")
|
||||
os.Unsetenv("GIT_ALLOW_PROTOCOL")
|
||||
@ -260,7 +270,7 @@ func TestMain(m *testing.M) {
|
||||
// Setting HOME to a non-existent directory will break
|
||||
// those systems. Disable ccache and use real compiler. Issue 17668.
|
||||
os.Setenv("CCACHE_DISABLE", "1")
|
||||
if os.Getenv("GOCACHE") == "" {
|
||||
if cfg.Getenv("GOCACHE") == "" {
|
||||
os.Setenv("GOCACHE", testGOCACHE) // because $HOME is gone
|
||||
}
|
||||
|
||||
@ -422,6 +432,7 @@ func (tg *testgoData) setenv(name, val string) {
|
||||
func (tg *testgoData) unsetenv(name string) {
|
||||
if tg.env == nil {
|
||||
tg.env = append([]string(nil), os.Environ()...)
|
||||
tg.env = append(tg.env, "GO111MODULE=off")
|
||||
}
|
||||
for i, v := range tg.env {
|
||||
if strings.HasPrefix(v, name+"=") {
|
||||
@ -675,7 +686,7 @@ func (tg *testgoData) creatingTemp(path string) {
|
||||
if tg.wd != "" && !filepath.IsAbs(path) {
|
||||
path = filepath.Join(tg.pwd(), path)
|
||||
}
|
||||
tg.must(os.RemoveAll(path))
|
||||
tg.must(robustio.RemoveAll(path))
|
||||
tg.temps = append(tg.temps, path)
|
||||
}
|
||||
|
||||
@ -877,7 +888,7 @@ func removeAll(dir string) error {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return os.RemoveAll(dir)
|
||||
return robustio.RemoveAll(dir)
|
||||
}
|
||||
|
||||
// failSSH puts an ssh executable in the PATH that always fails.
|
||||
@ -1171,7 +1182,7 @@ func testMove(t *testing.T, vcs, url, base, config string) {
|
||||
case "svn":
|
||||
// SVN doesn't believe in text files so we can't just edit the config.
|
||||
// Check out a different repo into the wrong place.
|
||||
tg.must(os.RemoveAll(tg.path("src/code.google.com/p/rsc-svn")))
|
||||
tg.must(robustio.RemoveAll(tg.path("src/code.google.com/p/rsc-svn")))
|
||||
tg.run("get", "-d", "-u", "code.google.com/p/rsc-svn2/trunk")
|
||||
tg.must(os.Rename(tg.path("src/code.google.com/p/rsc-svn2"), tg.path("src/code.google.com/p/rsc-svn")))
|
||||
default:
|
||||
@ -1212,10 +1223,12 @@ func TestInternalCache(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMoveGit(t *testing.T) {
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
testMove(t, "git", "rsc.io/pdf", "pdf", "rsc.io/pdf/.git/config")
|
||||
}
|
||||
|
||||
func TestMoveHG(t *testing.T) {
|
||||
testenv.MustHaveExecPath(t, "hg")
|
||||
testMove(t, "hg", "vcs-test.golang.org/go/custom-hg-hello", "custom-hg-hello", "vcs-test.golang.org/go/custom-hg-hello/.hg/hgrc")
|
||||
}
|
||||
|
||||
@ -1277,9 +1290,7 @@ func TestImportCycle(t *testing.T) {
|
||||
// cmd/go: custom import path checking should not apply to Go packages without import comment.
|
||||
func TestIssue10952(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -1295,9 +1306,7 @@ func TestIssue10952(t *testing.T) {
|
||||
|
||||
func TestIssue16471(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -1313,9 +1322,7 @@ func TestIssue16471(t *testing.T) {
|
||||
// Test git clone URL that uses SCP-like syntax and custom import path checking.
|
||||
func TestIssue11457(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -1340,9 +1347,7 @@ func TestIssue11457(t *testing.T) {
|
||||
|
||||
func TestGetGitDefaultBranch(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -1368,9 +1373,7 @@ func TestGetGitDefaultBranch(t *testing.T) {
|
||||
// Security issue. Don't disable. See golang.org/issue/22125.
|
||||
func TestAccidentalGitCheckout(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -1644,6 +1647,7 @@ func TestInstallToGOBINCommandLinePackage(t *testing.T) {
|
||||
|
||||
func TestGoGetNonPkg(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -1660,6 +1664,7 @@ func TestGoGetNonPkg(t *testing.T) {
|
||||
|
||||
func TestGoGetTestOnlyPkg(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -1690,7 +1695,7 @@ func TestInstalls(t *testing.T) {
|
||||
goarch := strings.TrimSpace(tg.getStdout())
|
||||
tg.setenv("GOARCH", goarch)
|
||||
fixbin := filepath.Join(goroot, "pkg", "tool", goos+"_"+goarch, "fix") + exeSuffix
|
||||
tg.must(os.RemoveAll(fixbin))
|
||||
tg.must(robustio.RemoveAll(fixbin))
|
||||
tg.run("install", "cmd/fix")
|
||||
tg.wantExecutable(fixbin, "did not install cmd/fix to $GOROOT/pkg/tool")
|
||||
tg.must(os.Remove(fixbin))
|
||||
@ -1884,11 +1889,12 @@ func TestGoListTest(t *testing.T) {
|
||||
tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo")
|
||||
|
||||
tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort")
|
||||
tg.grepStdout(`^reflect$`, "missing reflect")
|
||||
tg.grepStdout(`^internal/reflectlite$`, "missing internal/reflectlite")
|
||||
tg.grepStdoutNot(`^sort`, "unexpected sort")
|
||||
}
|
||||
|
||||
func TestGoListCompiledCgo(t *testing.T) {
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
@ -2048,6 +2054,7 @@ func TestDefaultGOPATH(t *testing.T) {
|
||||
|
||||
func TestDefaultGOPATHGet(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -2060,13 +2067,13 @@ func TestDefaultGOPATHGet(t *testing.T) {
|
||||
tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH")
|
||||
|
||||
// no warning if directory already exists
|
||||
tg.must(os.RemoveAll(tg.path("home/go")))
|
||||
tg.must(robustio.RemoveAll(tg.path("home/go")))
|
||||
tg.tempDir("home/go")
|
||||
tg.run("get", "github.com/golang/example/hello")
|
||||
tg.grepStderrNot(".", "expected no output on standard error")
|
||||
|
||||
// error if $HOME/go is a file
|
||||
tg.must(os.RemoveAll(tg.path("home/go")))
|
||||
tg.must(robustio.RemoveAll(tg.path("home/go")))
|
||||
tg.tempFile("home/go", "")
|
||||
tg.runFail("get", "github.com/golang/example/hello")
|
||||
tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file")
|
||||
@ -2429,6 +2436,7 @@ func TestSymlinkWarning(t *testing.T) {
|
||||
// Issue 8181.
|
||||
func TestGoGetDashTIssue8181(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -2443,6 +2451,7 @@ func TestGoGetDashTIssue8181(t *testing.T) {
|
||||
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()
|
||||
@ -2528,6 +2537,7 @@ func TestCoverageRuns(t *testing.T) {
|
||||
|
||||
func TestCoverageDotImport(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo has no cover tool")
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
@ -2610,6 +2620,14 @@ func TestCoverageDepLoop(t *testing.T) {
|
||||
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 TestCoverageImportMainLoop(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo has no cover tool")
|
||||
tg := testgo(t)
|
||||
@ -2699,6 +2717,7 @@ func TestCoverageFunc(t *testing.T) {
|
||||
// Issue 24588.
|
||||
func TestCoverageDashC(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo has no cover tool")
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
@ -2855,7 +2874,7 @@ func TestCgoDependsOnSyscall(t *testing.T) {
|
||||
files, err := filepath.Glob(filepath.Join(runtime.GOROOT(), "pkg", "*_race"))
|
||||
tg.must(err)
|
||||
for _, file := range files {
|
||||
tg.check(os.RemoveAll(file))
|
||||
tg.check(robustio.RemoveAll(file))
|
||||
}
|
||||
tg.tempFile("src/foo/foo.go", `
|
||||
package foo
|
||||
@ -2911,6 +2930,7 @@ func TestCgoPkgConfig(t *testing.T) {
|
||||
|
||||
tg.run("env", "PKG_CONFIG")
|
||||
pkgConfig := strings.TrimSpace(tg.getStdout())
|
||||
testenv.MustHaveExecPath(t, pkgConfig)
|
||||
if out, err := exec.Command(pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
|
||||
t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
|
||||
}
|
||||
@ -3013,9 +3033,7 @@ func TestIssue7573(t *testing.T) {
|
||||
if !canCgo {
|
||||
t.Skip("skipping because cgo not enabled")
|
||||
}
|
||||
if _, err := exec.LookPath("gccgo"); err != nil {
|
||||
t.Skip("skipping because no gccgo compiler found")
|
||||
}
|
||||
testenv.MustHaveExecPath(t, "gccgo")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3304,6 +3322,7 @@ func TestGoGenerateBadImports(t *testing.T) {
|
||||
|
||||
func TestGoGetCustomDomainWildcard(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3315,6 +3334,7 @@ func TestGoGetCustomDomainWildcard(t *testing.T) {
|
||||
|
||||
func TestGoGetInternalWildcard(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3374,6 +3394,7 @@ func TestVetWithOnlyCgoFiles(t *testing.T) {
|
||||
if !canCgo {
|
||||
t.Skip("skipping because cgo not enabled")
|
||||
}
|
||||
tooSlow(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3386,6 +3407,7 @@ func TestVetWithOnlyCgoFiles(t *testing.T) {
|
||||
// Issue 9767, 19769.
|
||||
func TestGoGetDotSlashDownload(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3395,22 +3417,6 @@ func TestGoGetDotSlashDownload(t *testing.T) {
|
||||
tg.run("get", "./pprof_mac_fix")
|
||||
}
|
||||
|
||||
// Issue 13037: Was not parsing <meta> tags in 404 served over HTTPS
|
||||
func TestGoGetHTTPS404(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "linux", "freebsd":
|
||||
default:
|
||||
t.Skipf("test case does not work on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.tempDir("src")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.run("get", "bazil.org/fuse/fs/fstestutil")
|
||||
}
|
||||
|
||||
// Test that you cannot import a main package.
|
||||
// See golang.org/issue/4210 and golang.org/issue/17475.
|
||||
func TestImportMain(t *testing.T) {
|
||||
@ -3625,7 +3631,7 @@ func TestImportLocal(t *testing.T) {
|
||||
var _ = x.X
|
||||
`)
|
||||
tg.runFail("build", "dir/x")
|
||||
tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
|
||||
tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
|
||||
|
||||
// ... even in a test.
|
||||
tg.tempFile("src/dir/x/xx.go", `package x
|
||||
@ -3638,7 +3644,7 @@ func TestImportLocal(t *testing.T) {
|
||||
`)
|
||||
tg.run("build", "dir/x")
|
||||
tg.runFail("test", "dir/x")
|
||||
tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
|
||||
tg.grepStderr("cannot import current directory", "did not diagnose import current directory")
|
||||
|
||||
// ... even in an xtest.
|
||||
tg.tempFile("src/dir/x/xx.go", `package x
|
||||
@ -3651,12 +3657,13 @@ func TestImportLocal(t *testing.T) {
|
||||
`)
|
||||
tg.run("build", "dir/x")
|
||||
tg.runFail("test", "dir/x")
|
||||
tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
|
||||
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()
|
||||
@ -3668,6 +3675,7 @@ func TestGoGetInsecure(t *testing.T) {
|
||||
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")
|
||||
@ -3696,6 +3704,7 @@ func TestGoGetInsecure(t *testing.T) {
|
||||
|
||||
func TestGoGetUpdateInsecure(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3720,6 +3729,7 @@ func TestGoGetUpdateInsecure(t *testing.T) {
|
||||
|
||||
func TestGoGetUpdateUnknownProtocol(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3754,6 +3764,7 @@ func TestGoGetUpdateUnknownProtocol(t *testing.T) {
|
||||
|
||||
func TestGoGetInsecureCustomDomain(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3856,6 +3867,7 @@ func TestGoGetUpdate(t *testing.T) {
|
||||
// former dependencies, not current ones.
|
||||
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -3883,6 +3895,7 @@ func TestGoGetUpdate(t *testing.T) {
|
||||
// Issue #20512.
|
||||
func TestGoGetRace(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
if !canRace {
|
||||
t.Skip("skipping because race detector not supported")
|
||||
}
|
||||
@ -3899,6 +3912,7 @@ func TestGoGetDomainRoot(t *testing.T) {
|
||||
// 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()
|
||||
@ -3913,10 +3927,10 @@ func TestGoGetDomainRoot(t *testing.T) {
|
||||
tg.run("get", "go-get-issue-9357.appspot.com")
|
||||
tg.run("get", "-u", "go-get-issue-9357.appspot.com")
|
||||
|
||||
tg.must(os.RemoveAll(tg.path("src/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(os.RemoveAll(tg.path("src/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")
|
||||
}
|
||||
|
||||
@ -4131,7 +4145,7 @@ func TestCgoConsistentResults(t *testing.T) {
|
||||
t.Skip("skipping because cgo not enabled")
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "solaris":
|
||||
case "solaris", "illumos":
|
||||
testenv.SkipFlaky(t, 13247)
|
||||
}
|
||||
|
||||
@ -4203,9 +4217,9 @@ func TestBinaryOnlyPackages(t *testing.T) {
|
||||
|
||||
package p1
|
||||
`)
|
||||
tg.wantStale("p1", "missing or invalid binary-only package", "p1 is binary-only but has no binary, should be stale")
|
||||
tg.wantStale("p1", "binary-only packages are no longer supported", "p1 is binary-only, and this message should always be printed")
|
||||
tg.runFail("install", "p1")
|
||||
tg.grepStderr("missing or invalid binary-only package", "did not report attempt to compile binary-only package")
|
||||
tg.grepStderr("binary-only packages are no longer supported", "did not report attempt to compile binary-only package")
|
||||
|
||||
tg.tempFile("src/p1/p1.go", `
|
||||
package p1
|
||||
@ -4231,48 +4245,13 @@ func TestBinaryOnlyPackages(t *testing.T) {
|
||||
import _ "fmt"
|
||||
func G()
|
||||
`)
|
||||
tg.wantNotStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
|
||||
tg.run("install", "-x", "p1") // no-op, up to date
|
||||
tg.grepBothNot(`[\\/]compile`, "should not have run compiler")
|
||||
tg.run("install", "p2") // does not rebuild p1 (or else p2 will fail)
|
||||
tg.wantNotStale("p2", "", "should NOT want to rebuild p2")
|
||||
tg.wantStale("p1", "binary-only package", "should NOT want to rebuild p1 (first)")
|
||||
tg.runFail("install", "p2")
|
||||
tg.grepStderr("p1: binary-only packages are no longer supported", "did not report error for binary-only p1")
|
||||
|
||||
// changes to the non-source-code do not matter,
|
||||
// and only one file needs the special comment.
|
||||
tg.tempFile("src/p1/missing2.go", `
|
||||
package p1
|
||||
func H()
|
||||
`)
|
||||
tg.wantNotStale("p1", "binary-only package", "should NOT want to rebuild p1 (second)")
|
||||
tg.wantNotStale("p2", "", "should NOT want to rebuild p2")
|
||||
|
||||
tg.tempFile("src/p3/p3.go", `
|
||||
package main
|
||||
import (
|
||||
"p1"
|
||||
"p2"
|
||||
)
|
||||
func main() {
|
||||
p1.F(false)
|
||||
p2.F()
|
||||
}
|
||||
`)
|
||||
tg.run("install", "p3")
|
||||
|
||||
tg.run("run", tg.path("src/p3/p3.go"))
|
||||
tg.grepStdout("hello from p1", "did not see message from p1")
|
||||
|
||||
tg.tempFile("src/p4/p4.go", `package main`)
|
||||
// The odd string split below avoids vet complaining about
|
||||
// a // +build line appearing too late in this source file.
|
||||
tg.tempFile("src/p4/p4not.go", `//go:binary-only-package
|
||||
|
||||
/`+`/ +build asdf
|
||||
|
||||
package main
|
||||
`)
|
||||
tg.run("list", "-f", "{{.BinaryOnly}}", "p4")
|
||||
tg.grepStdout("false", "did not see BinaryOnly=false for p4")
|
||||
tg.run("list", "-deps", "-f", "{{.ImportPath}}: {{.BinaryOnly}}", "p2")
|
||||
tg.grepStdout("p1: true", "p1 not listed as BinaryOnly")
|
||||
tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
|
||||
}
|
||||
|
||||
// Issue 16050.
|
||||
@ -4324,6 +4303,7 @@ func TestGenerateUsesBuildContext(t *testing.T) {
|
||||
// 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()
|
||||
@ -4535,8 +4515,9 @@ func TestLinkXImportPathEscape(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
exe := "./linkx" + exeSuffix
|
||||
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()
|
||||
@ -4677,7 +4658,7 @@ func TestBuildTagsNoComma(t *testing.T) {
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("go"))
|
||||
tg.run("build", "-tags", "tag1 tag2", "math")
|
||||
tg.runFail("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")
|
||||
}
|
||||
|
||||
@ -4772,7 +4753,7 @@ func TestExecutableGOROOT(t *testing.T) {
|
||||
check(t, symGoTool, newRoot)
|
||||
})
|
||||
|
||||
tg.must(os.RemoveAll(tg.path("new/pkg")))
|
||||
tg.must(robustio.RemoveAll(tg.path("new/pkg")))
|
||||
|
||||
// Binaries built in the new tree should report the
|
||||
// new tree when they call runtime.GOROOT.
|
||||
@ -4969,14 +4950,14 @@ func TestTestRegexps(t *testing.T) {
|
||||
x_test.go:15: LOG: Y running N=10000
|
||||
x_test.go:15: LOG: Y running N=1000000
|
||||
x_test.go:15: LOG: Y running N=100000000
|
||||
x_test.go:15: LOG: Y running N=2000000000
|
||||
x_test.go:15: LOG: Y running N=1000000000
|
||||
--- BENCH: BenchmarkX/Y
|
||||
x_test.go:15: LOG: Y running N=1
|
||||
x_test.go:15: LOG: Y running N=100
|
||||
x_test.go:15: LOG: Y running N=10000
|
||||
x_test.go:15: LOG: Y running N=1000000
|
||||
x_test.go:15: LOG: Y running N=100000000
|
||||
x_test.go:15: LOG: Y running N=2000000000
|
||||
x_test.go:15: LOG: Y running N=1000000000
|
||||
--- BENCH: BenchmarkX
|
||||
x_test.go:13: LOG: X running N=1
|
||||
--- BENCH: BenchmarkXX
|
||||
@ -5072,9 +5053,8 @@ func TestExecBuildX(t *testing.T) {
|
||||
t.Skip("skipping because cgo not enabled")
|
||||
}
|
||||
|
||||
if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
|
||||
t.Skipf("skipping because unix shell is not supported on %s", runtime.GOOS)
|
||||
}
|
||||
testenv.MustHaveExecPath(t, "/usr/bin/env")
|
||||
testenv.MustHaveExecPath(t, "bash")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -5082,6 +5062,11 @@ func TestExecBuildX(t *testing.T) {
|
||||
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")
|
||||
@ -5124,7 +5109,7 @@ func TestExecBuildX(t *testing.T) {
|
||||
if len(matches) == 0 {
|
||||
t.Fatal("no WORK directory")
|
||||
}
|
||||
tg.must(os.RemoveAll(matches[1]))
|
||||
tg.must(robustio.RemoveAll(matches[1]))
|
||||
}
|
||||
|
||||
func TestParallelNumber(t *testing.T) {
|
||||
@ -5155,9 +5140,10 @@ func TestUpxCompression(t *testing.T) {
|
||||
t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
|
||||
testenv.MustHaveExecPath(t, "upx")
|
||||
out, err := exec.Command("upx", "--version").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Skip("skipping because upx is not available")
|
||||
t.Fatalf("upx --version failed: %v", err)
|
||||
}
|
||||
|
||||
// upx --version prints `upx <version>` in the first line of output:
|
||||
@ -5166,13 +5152,13 @@ func TestUpxCompression(t *testing.T) {
|
||||
re := regexp.MustCompile(`([[:digit:]]+)\.([[:digit:]]+)`)
|
||||
upxVersion := re.FindStringSubmatch(string(out))
|
||||
if len(upxVersion) != 3 {
|
||||
t.Errorf("bad upx version string: %s", upxVersion)
|
||||
t.Fatalf("bad upx version string: %s", upxVersion)
|
||||
}
|
||||
|
||||
major, err1 := strconv.Atoi(upxVersion[1])
|
||||
minor, err2 := strconv.Atoi(upxVersion[2])
|
||||
if err1 != nil || err2 != nil {
|
||||
t.Errorf("bad upx version string: %s", upxVersion[0])
|
||||
t.Fatalf("bad upx version string: %s", upxVersion[0])
|
||||
}
|
||||
|
||||
// Anything below 3.94 is known not to work with go binaries
|
||||
@ -5225,26 +5211,29 @@ func TestQEMUUserMode(t *testing.T) {
|
||||
src, obj := tg.path("main.go"), tg.path("main")
|
||||
|
||||
for _, arch := range testArchs {
|
||||
out, err := exec.Command("qemu-"+arch.qemu, "--version").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Logf("Skipping %s test (qemu-%s not available)", arch.g, arch.qemu)
|
||||
continue
|
||||
}
|
||||
arch := arch
|
||||
t.Run(arch.g, func(t *testing.T) {
|
||||
qemu := "qemu-" + arch.qemu
|
||||
testenv.MustHaveExecPath(t, qemu)
|
||||
|
||||
tg.setenv("GOARCH", arch.g)
|
||||
tg.run("build", "-o", obj, src)
|
||||
out, err := exec.Command(qemu, "--version").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("%s --version failed: %v", qemu, err)
|
||||
}
|
||||
|
||||
out, err = exec.Command("qemu-"+arch.qemu, obj).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Logf("qemu-%s output:\n%s\n", arch.qemu, out)
|
||||
t.Errorf("qemu-%s failed with %v", arch.qemu, err)
|
||||
continue
|
||||
}
|
||||
if want := "hello qemu-user"; string(out) != want {
|
||||
t.Errorf("bad output from qemu-%s:\ngot %s; want %s", arch.qemu, out, want)
|
||||
}
|
||||
tg.setenv("GOARCH", arch.g)
|
||||
tg.run("build", "-o", obj, src)
|
||||
|
||||
out, err = exec.Command(qemu, obj).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Logf("%s output:\n%s\n", qemu, out)
|
||||
t.Fatalf("%s failed with %v", qemu, err)
|
||||
}
|
||||
if want := "hello qemu-user"; string(out) != want {
|
||||
t.Errorf("bad output from %s:\ngot %s; want %s", qemu, out, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCacheListStale(t *testing.T) {
|
||||
@ -5296,8 +5285,14 @@ func TestCacheVet(t *testing.T) {
|
||||
if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
|
||||
t.Skip("GODEBUG gocacheverify")
|
||||
}
|
||||
if os.Getenv("GOCACHE") == "off" {
|
||||
tooSlow(t)
|
||||
if testing.Short() {
|
||||
// In short mode, reuse cache.
|
||||
// Test failures may be masked if the cache has just the right entries already
|
||||
// (not a concern during all.bash, which runs in a clean cache).
|
||||
if cfg.Getenv("GOCACHE") == "off" {
|
||||
tooSlow(t)
|
||||
}
|
||||
} else {
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOCACHE", tg.path("cache"))
|
||||
}
|
||||
@ -5681,6 +5676,7 @@ func TestTestSkipVetAfterFailedBuild(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTestVetRebuild(t *testing.T) {
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
@ -5960,6 +5956,7 @@ func TestBadCgoDirectives(t *testing.T) {
|
||||
if !canCgo {
|
||||
t.Skip("no cgo")
|
||||
}
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
@ -5992,7 +5989,7 @@ func TestBadCgoDirectives(t *testing.T) {
|
||||
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,
|
||||
// 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")
|
||||
}
|
||||
@ -6074,6 +6071,7 @@ func TestTwoPkgConfigs(t *testing.T) {
|
||||
if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
|
||||
t.Skipf("no shell scripts on %s", runtime.GOOS)
|
||||
}
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
@ -6104,6 +6102,8 @@ func TestCgoCache(t *testing.T) {
|
||||
if !canCgo {
|
||||
t.Skip("no cgo")
|
||||
}
|
||||
tooSlow(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
@ -6154,6 +6154,7 @@ func TestLinkerTmpDirIsDeleted(t *testing.T) {
|
||||
if !canCgo {
|
||||
t.Skip("skipping because cgo not enabled")
|
||||
}
|
||||
tooSlow(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@ -6243,6 +6244,7 @@ func TestGoTestWithoutTests(t *testing.T) {
|
||||
|
||||
// Issue 25579.
|
||||
func TestGoBuildDashODevNull(t *testing.T) {
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
@ -6255,6 +6257,7 @@ func TestGoBuildDashODevNull(t *testing.T) {
|
||||
// Issue 25093.
|
||||
func TestCoverpkgTestOnly(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo has no cover tool")
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
|
@ -5,7 +5,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -13,14 +12,18 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"cmd/go/internal/robustio"
|
||||
)
|
||||
|
||||
func TestAbsolutePath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmp, err := ioutil.TempDir("", "TestAbsolutePath")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
defer robustio.RemoveAll(tmp)
|
||||
|
||||
file := filepath.Join(tmp, "a.go")
|
||||
err = ioutil.WriteFile(file, []byte{}, 0644)
|
||||
@ -33,21 +36,11 @@ func TestAbsolutePath(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Chdir(wd)
|
||||
|
||||
// Chdir so current directory and a.go reside on the same drive.
|
||||
err = os.Chdir(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
noVolume := file[len(filepath.VolumeName(file)):]
|
||||
wrongPath := filepath.Join(dir, noVolume)
|
||||
output, err := exec.Command(testenv.GoToolPath(t), "build", noVolume).CombinedOutput()
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "build", noVolume)
|
||||
cmd.Dir = dir
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err == nil {
|
||||
t.Fatal("build should fail")
|
||||
}
|
||||
@ -55,69 +48,3 @@ func TestAbsolutePath(t *testing.T) {
|
||||
t.Fatalf("wrong output found: %v %v", err, string(output))
|
||||
}
|
||||
}
|
||||
|
||||
func runIcacls(t *testing.T, args ...string) string {
|
||||
t.Helper()
|
||||
out, err := exec.Command("icacls", args...).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("icacls failed: %v\n%v", err, string(out))
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
|
||||
func runGetACL(t *testing.T, path string) string {
|
||||
t.Helper()
|
||||
cmd := fmt.Sprintf(`Get-Acl "%s" | Select -expand AccessToString`, path)
|
||||
out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("Get-Acl failed: %v\n%v", err, string(out))
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// For issue 22343: verify that executable file created by "go build" command
|
||||
// has discretionary access control list (DACL) set as if the file
|
||||
// was created in the destination directory.
|
||||
func TestACL(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "TestACL")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
newtmpdir := filepath.Join(tmpdir, "tmp")
|
||||
err = os.Mkdir(newtmpdir, 0777)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// When TestACL/tmp directory is created, it will have
|
||||
// the same security attributes as TestACL.
|
||||
// Add Guest account full access to TestACL/tmp - this
|
||||
// will make all files created in TestACL/tmp have different
|
||||
// security attributes to the files created in TestACL.
|
||||
runIcacls(t, newtmpdir,
|
||||
"/grant", "*S-1-5-32-546:(oi)(ci)f", // add Guests group to have full access
|
||||
)
|
||||
|
||||
src := filepath.Join(tmpdir, "main.go")
|
||||
err = ioutil.WriteFile(src, []byte("package main; func main() { }\n"), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
exe := filepath.Join(tmpdir, "main.exe")
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src)
|
||||
cmd.Env = append(os.Environ(),
|
||||
"TMP="+newtmpdir,
|
||||
"TEMP="+newtmpdir,
|
||||
)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("go command failed: %v\n%v", err, string(out))
|
||||
}
|
||||
|
||||
// exe file is expected to have the same security attributes as the src.
|
||||
if got, expected := runGetACL(t, exe), runGetACL(t, src); got != expected {
|
||||
t.Fatalf("expected Get-Acl output of \n%v\n, got \n%v\n", expected, got)
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,14 @@ import (
|
||||
"testing"
|
||||
|
||||
"cmd/go/internal/help"
|
||||
"cmd/go/internal/modload"
|
||||
)
|
||||
|
||||
func TestDocsUpToDate(t *testing.T) {
|
||||
if !modload.Enabled() {
|
||||
t.Skipf("help.Help in GOPATH mode is configured by main.main")
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
// Match the command in mkalldocs.sh that generates alldocs.go.
|
||||
help.Help(buf, []string{"documentation"})
|
||||
|
34
libgo/go/cmd/go/init_test.go
Normal file
34
libgo/go/cmd/go/init_test.go
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2018 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_test
|
||||
|
||||
import (
|
||||
"internal/testenv"
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// BenchmarkExecGoEnv measures how long it takes for 'go env GOARCH' to run.
|
||||
// Since 'go' is executed, remember to run 'go install cmd/go' before running
|
||||
// the benchmark if any changes were done.
|
||||
func BenchmarkExecGoEnv(b *testing.B) {
|
||||
testenv.MustHaveExec(b)
|
||||
b.StopTimer()
|
||||
gotool, err := testenv.GoTool()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
cmd := exec.Command(gotool, "env", "GOARCH")
|
||||
|
||||
b.StartTimer()
|
||||
err := cmd.Run()
|
||||
b.StopTimer()
|
||||
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
23
libgo/go/cmd/go/internal/auth/auth.go
Normal file
23
libgo/go/cmd/go/internal/auth/auth.go
Normal file
@ -0,0 +1,23 @@
|
||||
// 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 auth provides access to user-provided authentication credentials.
|
||||
package auth
|
||||
|
||||
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) {
|
||||
// TODO(golang.org/issue/26232): Support arbitrary user-provided credentials.
|
||||
netrcOnce.Do(readNetrc)
|
||||
for _, l := range netrc {
|
||||
if l.machine == req.URL.Host {
|
||||
req.SetBasicAuth(l.login, l.password)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
111
libgo/go/cmd/go/internal/auth/netrc.go
Normal file
111
libgo/go/cmd/go/internal/auth/netrc.go
Normal file
@ -0,0 +1,111 @@
|
||||
// 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 auth
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type netrcLine struct {
|
||||
machine string
|
||||
login string
|
||||
password string
|
||||
}
|
||||
|
||||
var (
|
||||
netrcOnce sync.Once
|
||||
netrc []netrcLine
|
||||
netrcErr error
|
||||
)
|
||||
|
||||
func parseNetrc(data string) []netrcLine {
|
||||
// See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html
|
||||
// for documentation on the .netrc format.
|
||||
var nrc []netrcLine
|
||||
var l netrcLine
|
||||
inMacro := false
|
||||
for _, line := range strings.Split(data, "\n") {
|
||||
if inMacro {
|
||||
if line == "" {
|
||||
inMacro = false
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
f := strings.Fields(line)
|
||||
i := 0
|
||||
for ; i < len(f)-1; i += 2 {
|
||||
// Reset at each "machine" token.
|
||||
// “The auto-login process searches the .netrc file for a machine token
|
||||
// that matches […]. Once a match is made, the subsequent .netrc tokens
|
||||
// are processed, stopping when the end of file is reached or another
|
||||
// machine or a default token is encountered.”
|
||||
switch f[i] {
|
||||
case "machine":
|
||||
l = netrcLine{machine: f[i+1]}
|
||||
case "default":
|
||||
break
|
||||
case "login":
|
||||
l.login = f[i+1]
|
||||
case "password":
|
||||
l.password = f[i+1]
|
||||
case "macdef":
|
||||
// “A macro is defined with the specified name; its contents begin with
|
||||
// the next .netrc line and continue until a null line (consecutive
|
||||
// new-line characters) is encountered.”
|
||||
inMacro = true
|
||||
}
|
||||
if l.machine != "" && l.login != "" && l.password != "" {
|
||||
nrc = append(nrc, l)
|
||||
l = netrcLine{}
|
||||
}
|
||||
}
|
||||
|
||||
if i < len(f) && f[i] == "default" {
|
||||
// “There can be only one default token, and it must be after all machine tokens.”
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nrc
|
||||
}
|
||||
|
||||
func netrcPath() (string, error) {
|
||||
if env := os.Getenv("NETRC"); env != "" {
|
||||
return env, nil
|
||||
}
|
||||
dir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
base := ".netrc"
|
||||
if runtime.GOOS == "windows" {
|
||||
base = "_netrc"
|
||||
}
|
||||
return filepath.Join(dir, base), nil
|
||||
}
|
||||
|
||||
func readNetrc() {
|
||||
path, err := netrcPath()
|
||||
if err != nil {
|
||||
netrcErr = err
|
||||
return
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
netrcErr = err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
netrc = parseNetrc(string(data))
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package web2
|
||||
package auth
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
@ -10,23 +10,46 @@ import (
|
||||
)
|
||||
|
||||
var testNetrc = `
|
||||
machine incomplete
|
||||
password none
|
||||
|
||||
machine api.github.com
|
||||
login user
|
||||
password pwd
|
||||
|
||||
machine incomlete.host
|
||||
login justlogin
|
||||
|
||||
|
||||
machine test.host
|
||||
login user2
|
||||
password pwd2
|
||||
|
||||
machine oneline login user3 password pwd3
|
||||
|
||||
machine ignore.host macdef ignore
|
||||
login nobody
|
||||
password nothing
|
||||
|
||||
machine hasmacro.too macdef ignore-next-lines login user4 password pwd4
|
||||
login nobody
|
||||
password nothing
|
||||
|
||||
default
|
||||
login anonymous
|
||||
password gopher@golang.org
|
||||
|
||||
machine after.default
|
||||
login oops
|
||||
password too-late-in-file
|
||||
`
|
||||
|
||||
func TestReadNetrc(t *testing.T) {
|
||||
func TestParseNetrc(t *testing.T) {
|
||||
lines := parseNetrc(testNetrc)
|
||||
want := []netrcLine{
|
||||
{"api.github.com", "user", "pwd"},
|
||||
{"test.host", "user2", "pwd2"},
|
||||
{"oneline", "user3", "pwd3"},
|
||||
{"hasmacro.too", "user4", "pwd4"},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(lines, want) {
|
@ -30,7 +30,7 @@ type Command struct {
|
||||
Run func(cmd *Command, args []string)
|
||||
|
||||
// UsageLine is the one-line usage message.
|
||||
// The first word in the line is taken to be the command name.
|
||||
// The words between "go" and the first flag or argument in the line are taken to be the command name.
|
||||
UsageLine string
|
||||
|
||||
// Short is the short description shown in the 'go help' output.
|
||||
@ -132,6 +132,10 @@ func SetExitStatus(n int) {
|
||||
exitMu.Unlock()
|
||||
}
|
||||
|
||||
func GetExitStatus() int {
|
||||
return exitStatus
|
||||
}
|
||||
|
||||
// Run runs the command, with stdout and stderr
|
||||
// connected to the go command's own stdout and stderr.
|
||||
// If the command fails, Run reports the error using Errorf.
|
||||
|
@ -4,34 +4,12 @@
|
||||
|
||||
package base
|
||||
|
||||
import "strings"
|
||||
|
||||
// EnvForDir returns a copy of the environment
|
||||
// suitable for running in the given directory.
|
||||
// The environment is the current process's environment
|
||||
// but with an updated $PWD, so that an os.Getwd in the
|
||||
// child will be faster.
|
||||
// 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.
|
||||
return MergeEnvLists([]string{"PWD=" + dir}, base)
|
||||
}
|
||||
|
||||
// MergeEnvLists merges the two environment lists such that
|
||||
// variables with the same name in "in" replace those in "out".
|
||||
// This always returns a newly allocated slice.
|
||||
func MergeEnvLists(in, out []string) []string {
|
||||
out = append([]string(nil), out...)
|
||||
NextVar:
|
||||
for _, inkv := range in {
|
||||
k := strings.SplitAfterN(inkv, "=", 2)[0]
|
||||
for i, outkv := range out {
|
||||
if strings.HasPrefix(outkv, k) {
|
||||
out[i] = inkv
|
||||
continue NextVar
|
||||
}
|
||||
}
|
||||
out = append(out, inkv)
|
||||
}
|
||||
return out
|
||||
return append(base, "PWD="+dir)
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ package base
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@ -62,7 +61,7 @@ func InitGOFLAGS() {
|
||||
// (Both will show the GOFLAGS setting if let succeed.)
|
||||
hideErrors := cfg.CmdName == "env" || cfg.CmdName == "bug"
|
||||
|
||||
goflags = strings.Fields(os.Getenv("GOFLAGS"))
|
||||
goflags = strings.Fields(cfg.Getenv("GOFLAGS"))
|
||||
if goflags == nil {
|
||||
goflags = []string{} // avoid work on later InitGOFLAGS call
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
urlpkg "net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -19,7 +20,6 @@ import (
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/envcmd"
|
||||
"cmd/go/internal/web"
|
||||
)
|
||||
|
||||
@ -43,48 +43,60 @@ func runBug(cmd *base.Command, args []string) {
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(bugHeader)
|
||||
inspectGoVersion(&buf)
|
||||
fmt.Fprint(&buf, "#### System details\n\n")
|
||||
fmt.Fprintln(&buf, "```")
|
||||
fmt.Fprintf(&buf, "go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
||||
env := cfg.CmdEnv
|
||||
env = append(env, envcmd.ExtraEnvVars()...)
|
||||
for _, e := range env {
|
||||
// Hide the TERM environment variable from "go bug".
|
||||
// See issue #18128
|
||||
if e.Name != "TERM" {
|
||||
fmt.Fprintf(&buf, "%s=\"%s\"\n", e.Name, e.Value)
|
||||
}
|
||||
}
|
||||
printGoDetails(&buf)
|
||||
printOSDetails(&buf)
|
||||
printCDetails(&buf)
|
||||
fmt.Fprintln(&buf, "```")
|
||||
printGoVersion(&buf)
|
||||
buf.WriteString("### Does this issue reproduce with the latest release?\n\n\n")
|
||||
printEnvDetails(&buf)
|
||||
buf.WriteString(bugFooter)
|
||||
|
||||
body := buf.String()
|
||||
url := "https://github.com/golang/go/issues/new?body=" + web.QueryEscape(body)
|
||||
url := "https://github.com/golang/go/issues/new?body=" + urlpkg.QueryEscape(body)
|
||||
if !web.OpenBrowser(url) {
|
||||
fmt.Print("Please file a new issue at golang.org/issue/new using this template:\n\n")
|
||||
fmt.Print(body)
|
||||
}
|
||||
}
|
||||
|
||||
const bugHeader = `Please answer these questions before submitting your issue. Thanks!
|
||||
const bugHeader = `<!-- Please answer these questions before submitting your issue. Thanks! -->
|
||||
|
||||
#### What did you do?
|
||||
`
|
||||
const bugFooter = `### What did you do?
|
||||
|
||||
<!--
|
||||
If possible, provide a recipe for reproducing the error.
|
||||
A complete runnable program is good.
|
||||
A link on play.golang.org is best.
|
||||
-->
|
||||
|
||||
|
||||
#### What did you expect to see?
|
||||
|
||||
### What did you expect to see?
|
||||
|
||||
|
||||
#### What did you see instead?
|
||||
|
||||
### What did you see instead?
|
||||
|
||||
`
|
||||
|
||||
func printGoVersion(w io.Writer) {
|
||||
fmt.Fprintf(w, "### What version of Go are you using (`go version`)?\n\n")
|
||||
fmt.Fprintf(w, "<pre>\n")
|
||||
fmt.Fprintf(w, "$ go version\n")
|
||||
printCmdOut(w, "", "go", "version")
|
||||
fmt.Fprintf(w, "</pre>\n")
|
||||
fmt.Fprintf(w, "\n")
|
||||
}
|
||||
|
||||
func printEnvDetails(w io.Writer) {
|
||||
fmt.Fprintf(w, "### What operating system and processor architecture are you using (`go env`)?\n\n")
|
||||
fmt.Fprintf(w, "<details><summary><code>go env</code> Output</summary><br><pre>\n")
|
||||
fmt.Fprintf(w, "$ go env\n")
|
||||
printCmdOut(w, "", "go", "env")
|
||||
printGoDetails(w)
|
||||
printOSDetails(w)
|
||||
printCDetails(w)
|
||||
fmt.Fprintf(w, "</pre></details>\n\n")
|
||||
}
|
||||
|
||||
func printGoDetails(w io.Writer) {
|
||||
printCmdOut(w, "GOROOT/bin/go version: ", filepath.Join(runtime.GOROOT(), "bin/go"), "version")
|
||||
printCmdOut(w, "GOROOT/bin/go tool compile -V: ", filepath.Join(runtime.GOROOT(), "bin/go"), "tool", "compile", "-V")
|
||||
@ -101,7 +113,9 @@ func printOSDetails(w io.Writer) {
|
||||
printGlibcVersion(w)
|
||||
case "openbsd", "netbsd", "freebsd", "dragonfly":
|
||||
printCmdOut(w, "uname -v: ", "uname", "-v")
|
||||
case "solaris":
|
||||
case "illumos", "solaris":
|
||||
// Be sure to use the OS-supplied uname, in "/usr/bin":
|
||||
printCmdOut(w, "uname -srv: ", "/usr/bin/uname", "-srv")
|
||||
out, err := ioutil.ReadFile("/etc/release")
|
||||
if err == nil {
|
||||
fmt.Fprintf(w, "/etc/release: %s\n", out)
|
||||
@ -129,30 +143,6 @@ func printCDetails(w io.Writer) {
|
||||
}
|
||||
}
|
||||
|
||||
func inspectGoVersion(w io.Writer) {
|
||||
data, err := web.Get("https://golang.org/VERSION?m=text")
|
||||
if err != nil {
|
||||
if cfg.BuildV {
|
||||
fmt.Printf("failed to read from golang.org/VERSION: %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// golang.org/VERSION currently returns a whitespace-free string,
|
||||
// but just in case, protect against that changing.
|
||||
// Similarly so for runtime.Version.
|
||||
release := string(bytes.TrimSpace(data))
|
||||
vers := strings.TrimSpace(runtime.Version())
|
||||
|
||||
if vers == release {
|
||||
// Up to date
|
||||
return
|
||||
}
|
||||
|
||||
// Devel version or outdated release. Either way, this request is apropos.
|
||||
fmt.Fprintf(w, "#### Does this issue reproduce with the latest release (%s)?\n\n\n", release)
|
||||
}
|
||||
|
||||
// printCmdOut prints the output of running the given command.
|
||||
// It ignores failures; 'go bug' is best effort.
|
||||
func printCmdOut(w io.Writer, prefix, path string, args ...string) {
|
||||
|
14
libgo/go/cmd/go/internal/cache/cache.go
vendored
14
libgo/go/cmd/go/internal/cache/cache.go
vendored
@ -33,7 +33,6 @@ type OutputID [HashSize]byte
|
||||
// A Cache is a package cache, backed by a file system directory tree.
|
||||
type Cache struct {
|
||||
dir string
|
||||
log *os.File
|
||||
now func() time.Time
|
||||
}
|
||||
|
||||
@ -63,13 +62,8 @@ func Open(dir string) (*Cache, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
f, err := os.OpenFile(filepath.Join(dir, "log.txt"), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c := &Cache{
|
||||
dir: dir,
|
||||
log: f,
|
||||
now: time.Now,
|
||||
}
|
||||
return c, nil
|
||||
@ -141,7 +135,6 @@ type Entry struct {
|
||||
// get is Get but does not respect verify mode, so that Put can use it.
|
||||
func (c *Cache) get(id ActionID) (Entry, error) {
|
||||
missing := func() (Entry, error) {
|
||||
fmt.Fprintf(c.log, "%d miss %x\n", c.now().Unix(), id)
|
||||
return Entry{}, errMissing
|
||||
}
|
||||
f, err := os.Open(c.fileName(id, "a"))
|
||||
@ -184,8 +177,6 @@ func (c *Cache) get(id ActionID) (Entry, error) {
|
||||
return missing()
|
||||
}
|
||||
|
||||
fmt.Fprintf(c.log, "%d get %x\n", c.now().Unix(), id)
|
||||
|
||||
c.used(c.fileName(id, "a"))
|
||||
|
||||
return Entry{buf, size, time.Unix(0, tm)}, nil
|
||||
@ -270,7 +261,7 @@ func (c *Cache) Trim() {
|
||||
// We maintain in dir/trim.txt the time of the last completed cache trim.
|
||||
// If the cache has been trimmed recently enough, do nothing.
|
||||
// This is the common case.
|
||||
data, _ := ioutil.ReadFile(filepath.Join(c.dir, "trim.txt"))
|
||||
data, _ := renameio.ReadFile(filepath.Join(c.dir, "trim.txt"))
|
||||
t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64)
|
||||
if err == nil && now.Sub(time.Unix(t, 0)) < trimInterval {
|
||||
return
|
||||
@ -287,7 +278,7 @@ func (c *Cache) Trim() {
|
||||
|
||||
// Ignore errors from here: if we don't write the complete timestamp, the
|
||||
// cache will appear older than it is, and we'll trim it again next time.
|
||||
renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())))
|
||||
renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())), 0666)
|
||||
}
|
||||
|
||||
// trimSubdir trims a single cache subdirectory.
|
||||
@ -349,7 +340,6 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify
|
||||
}
|
||||
os.Chtimes(file, c.now(), c.now()) // mainly for tests
|
||||
|
||||
fmt.Fprintf(c.log, "%d put %x %x %d\n", c.now().Unix(), id, out, size)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
51
libgo/go/cmd/go/internal/cache/cache_test.go
vendored
51
libgo/go/cmd/go/internal/cache/cache_test.go
vendored
@ -78,7 +78,7 @@ func TestGrowth(t *testing.T) {
|
||||
|
||||
n := 10000
|
||||
if testing.Short() {
|
||||
n = 1000
|
||||
n = 10
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
@ -144,55 +144,6 @@ func TestVerifyPanic(t *testing.T) {
|
||||
t.Fatal("mismatched Put did not panic in verify mode")
|
||||
}
|
||||
|
||||
func TestCacheLog(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "cachetest-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
c, err := Open(dir)
|
||||
if err != nil {
|
||||
t.Fatalf("Open: %v", err)
|
||||
}
|
||||
c.now = func() time.Time { return time.Unix(1e9, 0) }
|
||||
|
||||
id := ActionID(dummyID(1))
|
||||
c.Get(id)
|
||||
c.PutBytes(id, []byte("abc"))
|
||||
c.Get(id)
|
||||
|
||||
c, err = Open(dir)
|
||||
if err != nil {
|
||||
t.Fatalf("Open #2: %v", err)
|
||||
}
|
||||
c.now = func() time.Time { return time.Unix(1e9+1, 0) }
|
||||
c.Get(id)
|
||||
|
||||
id2 := ActionID(dummyID(2))
|
||||
c.Get(id2)
|
||||
c.PutBytes(id2, []byte("abc"))
|
||||
c.Get(id2)
|
||||
c.Get(id)
|
||||
|
||||
data, err := ioutil.ReadFile(filepath.Join(dir, "log.txt"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := `1000000000 miss 0100000000000000000000000000000000000000000000000000000000000000
|
||||
1000000000 put 0100000000000000000000000000000000000000000000000000000000000000 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 3
|
||||
1000000000 get 0100000000000000000000000000000000000000000000000000000000000000
|
||||
1000000001 get 0100000000000000000000000000000000000000000000000000000000000000
|
||||
1000000001 miss 0200000000000000000000000000000000000000000000000000000000000000
|
||||
1000000001 put 0200000000000000000000000000000000000000000000000000000000000000 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 3
|
||||
1000000001 get 0200000000000000000000000000000000000000000000000000000000000000
|
||||
1000000001 get 0100000000000000000000000000000000000000000000000000000000000000
|
||||
`
|
||||
if string(data) != want {
|
||||
t.Fatalf("log:\n%s\nwant:\n%s", string(data), want)
|
||||
}
|
||||
}
|
||||
|
||||
func dummyID(x int) [HashSize]byte {
|
||||
var out [HashSize]byte
|
||||
binary.LittleEndian.PutUint64(out[:], uint64(x))
|
||||
|
3
libgo/go/cmd/go/internal/cache/default.go
vendored
3
libgo/go/cmd/go/internal/cache/default.go
vendored
@ -12,6 +12,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cfg"
|
||||
)
|
||||
|
||||
// Default returns the default cache to use, or nil if no cache should be used.
|
||||
@ -73,7 +74,7 @@ func DefaultDir() string {
|
||||
// otherwise distinguish between an explicit "off" and a UserCacheDir error.
|
||||
|
||||
defaultDirOnce.Do(func() {
|
||||
defaultDir = os.Getenv("GOCACHE")
|
||||
defaultDir = cfg.Getenv("GOCACHE")
|
||||
if filepath.IsAbs(defaultDir) || defaultDir == "off" {
|
||||
return
|
||||
}
|
||||
|
@ -7,11 +7,15 @@
|
||||
package cfg
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"cmd/internal/objabi"
|
||||
)
|
||||
@ -34,11 +38,12 @@ var (
|
||||
BuildToolchainName string
|
||||
BuildToolchainCompiler func() string
|
||||
BuildToolchainLinker func() string
|
||||
BuildTrimpath bool // -trimpath flag
|
||||
BuildV bool // -v flag
|
||||
BuildWork bool // -work flag
|
||||
BuildX bool // -x flag
|
||||
|
||||
CmdName string // "build", "install", "list", etc.
|
||||
CmdName string // "build", "install", "list", "mod tidy", etc.
|
||||
|
||||
DebugActiongraph string // -debug-actiongraph flag (undocumented, unstable)
|
||||
)
|
||||
@ -46,6 +51,50 @@ var (
|
||||
func defaultContext() build.Context {
|
||||
ctxt := build.Default
|
||||
ctxt.JoinPath = filepath.Join // back door to say "do not use go command"
|
||||
|
||||
ctxt.GOROOT = findGOROOT()
|
||||
if runtime.Compiler != "gccgo" {
|
||||
// Note that we must use runtime.GOOS and runtime.GOARCH here,
|
||||
// as the tool directory does not move based on environment
|
||||
// variables. This matches the initialization of ToolDir in
|
||||
// go/build, except for using ctxt.GOROOT rather than
|
||||
// runtime.GOROOT.
|
||||
build.ToolDir = filepath.Join(ctxt.GOROOT, "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
|
||||
}
|
||||
|
||||
ctxt.GOPATH = envOr("GOPATH", ctxt.GOPATH)
|
||||
|
||||
// Override defaults computed in go/build with defaults
|
||||
// from go environment configuration file, if known.
|
||||
ctxt.GOOS = envOr("GOOS", ctxt.GOOS)
|
||||
ctxt.GOARCH = envOr("GOARCH", ctxt.GOARCH)
|
||||
|
||||
// The go/build rule for whether cgo is enabled is:
|
||||
// 1. If $CGO_ENABLED is set, respect it.
|
||||
// 2. Otherwise, if this is a cross-compile, disable cgo.
|
||||
// 3. Otherwise, use built-in default for GOOS/GOARCH.
|
||||
// Recreate that logic here with the new GOOS/GOARCH setting.
|
||||
if v := Getenv("CGO_ENABLED"); v == "0" || v == "1" {
|
||||
ctxt.CgoEnabled = v[0] == '1'
|
||||
} else if ctxt.GOOS != runtime.GOOS || ctxt.GOARCH != runtime.GOARCH {
|
||||
ctxt.CgoEnabled = false
|
||||
} else {
|
||||
// Use built-in default cgo setting for GOOS/GOARCH.
|
||||
// Note that ctxt.GOOS/GOARCH are derived from the preference list
|
||||
// (1) environment, (2) go/env file, (3) runtime constants,
|
||||
// while go/build.Default.GOOS/GOARCH are derived from the preference list
|
||||
// (1) environment, (2) runtime constants.
|
||||
// We know ctxt.GOOS/GOARCH == runtime.GOOS/GOARCH;
|
||||
// no matter how that happened, go/build.Default will make the
|
||||
// same decision (either the environment variables are set explicitly
|
||||
// to match the runtime constants, or else they are unset, in which
|
||||
// case go/build falls back to the runtime constants), so
|
||||
// go/build.Default.GOOS/GOARCH == runtime.GOOS/GOARCH.
|
||||
// So ctxt.CgoEnabled (== go/build.Default.CgoEnabled) is correct
|
||||
// as is and can be left unmodified.
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
return ctxt
|
||||
}
|
||||
|
||||
@ -70,54 +119,215 @@ var CmdEnv []EnvVar
|
||||
|
||||
// Global build parameters (used during package load)
|
||||
var (
|
||||
Goarch = BuildContext.GOARCH
|
||||
Goos = BuildContext.GOOS
|
||||
ExeSuffix string
|
||||
Gopath = filepath.SplitList(BuildContext.GOPATH)
|
||||
Goarch = BuildContext.GOARCH
|
||||
Goos = BuildContext.GOOS
|
||||
|
||||
ExeSuffix = exeSuffix()
|
||||
|
||||
// ModulesEnabled specifies whether the go command is running
|
||||
// in module-aware mode (as opposed to GOPATH mode).
|
||||
// It is equal to modload.Enabled, but not all packages can import modload.
|
||||
ModulesEnabled bool
|
||||
|
||||
// GoModInGOPATH records whether we've found a go.mod in GOPATH/src
|
||||
// in GO111MODULE=auto mode. In that case, we don't use modules
|
||||
// but people might expect us to, so 'go get' warns.
|
||||
GoModInGOPATH string
|
||||
)
|
||||
|
||||
func init() {
|
||||
func exeSuffix() string {
|
||||
if Goos == "windows" {
|
||||
ExeSuffix = ".exe"
|
||||
return ".exe"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var envCache struct {
|
||||
once sync.Once
|
||||
m map[string]string
|
||||
}
|
||||
|
||||
// EnvFile returns the name of the Go environment configuration file.
|
||||
func EnvFile() (string, error) {
|
||||
if file := os.Getenv("GOENV"); file != "" {
|
||||
if file == "off" {
|
||||
return "", fmt.Errorf("GOENV=off")
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
dir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if dir == "" {
|
||||
return "", fmt.Errorf("missing user-config dir")
|
||||
}
|
||||
return filepath.Join(dir, "go/env"), nil
|
||||
}
|
||||
|
||||
func initEnvCache() {
|
||||
envCache.m = make(map[string]string)
|
||||
file, _ := EnvFile()
|
||||
if file == "" {
|
||||
return
|
||||
}
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for len(data) > 0 {
|
||||
// Get next line.
|
||||
line := data
|
||||
i := bytes.IndexByte(data, '\n')
|
||||
if i >= 0 {
|
||||
line, data = line[:i], data[i+1:]
|
||||
} else {
|
||||
data = nil
|
||||
}
|
||||
|
||||
i = bytes.IndexByte(line, '=')
|
||||
if i < 0 || line[0] < 'A' || 'Z' < line[0] {
|
||||
// Line is missing = (or empty) or a comment or not a valid env name. Ignore.
|
||||
// (This should not happen, since the file should be maintained almost
|
||||
// exclusively by "go env -w", but better to silently ignore than to make
|
||||
// the go command unusable just because somehow the env file has
|
||||
// gotten corrupted.)
|
||||
continue
|
||||
}
|
||||
key, val := line[:i], line[i+1:]
|
||||
envCache.m[string(key)] = string(val)
|
||||
}
|
||||
}
|
||||
|
||||
// Getenv gets the value for the configuration key.
|
||||
// It consults the operating system environment
|
||||
// and then the go/env file.
|
||||
// If Getenv is called for a key that cannot be set
|
||||
// in the go/env file (for example GODEBUG), it panics.
|
||||
// This ensures that CanGetenv is accurate, so that
|
||||
// 'go env -w' stays in sync with what Getenv can retrieve.
|
||||
func Getenv(key string) string {
|
||||
if !CanGetenv(key) {
|
||||
switch key {
|
||||
case "CGO_TEST_ALLOW", "CGO_TEST_DISALLOW", "CGO_test_ALLOW", "CGO_test_DISALLOW":
|
||||
// used by internal/work/security_test.go; allow
|
||||
default:
|
||||
panic("internal error: invalid Getenv " + key)
|
||||
}
|
||||
}
|
||||
val := os.Getenv(key)
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
envCache.once.Do(initEnvCache)
|
||||
return envCache.m[key]
|
||||
}
|
||||
|
||||
// CanGetenv reports whether key is a valid go/env configuration key.
|
||||
func CanGetenv(key string) bool {
|
||||
return strings.Contains(knownEnv, "\t"+key+"\n")
|
||||
}
|
||||
|
||||
var knownEnv = `
|
||||
AR
|
||||
CC
|
||||
CGO_CFLAGS
|
||||
CGO_CFLAGS_ALLOW
|
||||
CGO_CFLAGS_DISALLOW
|
||||
CGO_CPPFLAGS
|
||||
CGO_CPPFLAGS_ALLOW
|
||||
CGO_CPPFLAGS_DISALLOW
|
||||
CGO_CXXFLAGS
|
||||
CGO_CXXFLAGS_ALLOW
|
||||
CGO_CXXFLAGS_DISALLOW
|
||||
CGO_ENABLED
|
||||
CGO_FFLAGS
|
||||
CGO_FFLAGS_ALLOW
|
||||
CGO_FFLAGS_DISALLOW
|
||||
CGO_LDFLAGS
|
||||
CGO_LDFLAGS_ALLOW
|
||||
CGO_LDFLAGS_DISALLOW
|
||||
CXX
|
||||
FC
|
||||
GCCGO
|
||||
GO111MODULE
|
||||
GO386
|
||||
GOARCH
|
||||
GOARM
|
||||
GOBIN
|
||||
GOCACHE
|
||||
GOENV
|
||||
GOEXE
|
||||
GOFLAGS
|
||||
GOGCCFLAGS
|
||||
GOHOSTARCH
|
||||
GOHOSTOS
|
||||
GOMIPS
|
||||
GOMIPS64
|
||||
GONOPROXY
|
||||
GONOSUMDB
|
||||
GOOS
|
||||
GOPATH
|
||||
GOPPC64
|
||||
GOPRIVATE
|
||||
GOPROXY
|
||||
GOROOT
|
||||
GOSUMDB
|
||||
GOTMPDIR
|
||||
GOTOOLDIR
|
||||
GOWASM
|
||||
GO_EXTLINK_ENABLED
|
||||
PKG_CONFIG
|
||||
`
|
||||
|
||||
var (
|
||||
GOROOT = findGOROOT()
|
||||
GOBIN = os.Getenv("GOBIN")
|
||||
GOROOT = BuildContext.GOROOT
|
||||
GOBIN = Getenv("GOBIN")
|
||||
GOROOTbin = filepath.Join(GOROOT, "bin")
|
||||
GOROOTpkg = filepath.Join(GOROOT, "pkg")
|
||||
GOROOTsrc = filepath.Join(GOROOT, "src")
|
||||
GOROOT_FINAL = findGOROOT_FINAL()
|
||||
|
||||
// Used in envcmd.MkEnv and build ID computations.
|
||||
GOARM = fmt.Sprint(objabi.GOARM)
|
||||
GO386 = objabi.GO386
|
||||
GOMIPS = objabi.GOMIPS
|
||||
GOMIPS64 = objabi.GOMIPS64
|
||||
GOARM = envOr("GOARM", fmt.Sprint(objabi.GOARM))
|
||||
GO386 = envOr("GO386", objabi.GO386)
|
||||
GOMIPS = envOr("GOMIPS", objabi.GOMIPS)
|
||||
GOMIPS64 = envOr("GOMIPS64", objabi.GOMIPS64)
|
||||
GOPPC64 = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", objabi.GOPPC64))
|
||||
GOWASM = envOr("GOWASM", fmt.Sprint(objabi.GOWASM))
|
||||
|
||||
GOPROXY = envOr("GOPROXY", "https://proxy.golang.org,direct")
|
||||
GOSUMDB = envOr("GOSUMDB", "sum.golang.org")
|
||||
GOPRIVATE = Getenv("GOPRIVATE")
|
||||
GONOPROXY = envOr("GONOPROXY", GOPRIVATE)
|
||||
GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE)
|
||||
)
|
||||
|
||||
// Update build context to use our computed GOROOT.
|
||||
func init() {
|
||||
BuildContext.GOROOT = GOROOT
|
||||
if runtime.Compiler != "gccgo" {
|
||||
// Note that we must use runtime.GOOS and runtime.GOARCH here,
|
||||
// as the tool directory does not move based on environment
|
||||
// variables. This matches the initialization of ToolDir in
|
||||
// go/build, except for using GOROOT rather than
|
||||
// runtime.GOROOT.
|
||||
build.ToolDir = filepath.Join(GOROOT, "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
|
||||
// GetArchEnv returns the name and setting of the
|
||||
// GOARCH-specific architecture environment variable.
|
||||
// If the current architecture has no GOARCH-specific variable,
|
||||
// GetArchEnv returns empty key and value.
|
||||
func GetArchEnv() (key, val string) {
|
||||
switch Goarch {
|
||||
case "arm":
|
||||
return "GOARM", GOARM
|
||||
case "386":
|
||||
return "GO386", GO386
|
||||
case "mips", "mipsle":
|
||||
return "GOMIPS", GOMIPS
|
||||
case "mips64", "mips64le":
|
||||
return "GOMIPS64", GOMIPS64
|
||||
case "ppc64", "ppc64le":
|
||||
return "GOPPC64", GOPPC64
|
||||
case "wasm":
|
||||
return "GOWASM", GOWASM
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
|
||||
// envOr returns Getenv(key) if set, or else def.
|
||||
func envOr(key, def string) string {
|
||||
val := Getenv(key)
|
||||
if val == "" {
|
||||
val = def
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// There is a copy of findGOROOT, isSameDir, and isGOROOT in
|
||||
@ -131,7 +341,7 @@ func init() {
|
||||
//
|
||||
// There is a copy of this code in x/tools/cmd/godoc/goroot.go.
|
||||
func findGOROOT() string {
|
||||
if env := os.Getenv("GOROOT"); env != "" {
|
||||
if env := Getenv("GOROOT"); env != "" {
|
||||
return filepath.Clean(env)
|
||||
}
|
||||
def := filepath.Clean(runtime.GOROOT())
|
||||
@ -167,6 +377,8 @@ func findGOROOT() string {
|
||||
}
|
||||
|
||||
func findGOROOT_FINAL() string {
|
||||
// $GOROOT_FINAL is only for use during make.bash
|
||||
// so it is not settable using go/env, so we use os.Getenv here.
|
||||
def := GOROOT
|
||||
if env := os.Getenv("GOROOT_FINAL"); env != "" {
|
||||
def = filepath.Clean(env)
|
||||
|
@ -33,7 +33,8 @@ The go command builds most objects in a temporary directory,
|
||||
so go clean is mainly concerned with object files left by other
|
||||
tools or by manual invocations of go build.
|
||||
|
||||
Specifically, clean removes the following files from each of the
|
||||
If a package argument is given or the -i or -r flag is set,
|
||||
clean removes the following files from each of the
|
||||
source directories corresponding to the import paths:
|
||||
|
||||
_obj/ old object directory, left from Makefiles
|
||||
@ -105,7 +106,16 @@ func init() {
|
||||
}
|
||||
|
||||
func runClean(cmd *base.Command, args []string) {
|
||||
if len(args) > 0 || !modload.Enabled() || modload.HasModRoot() {
|
||||
// golang.org/issue/29925: only load packages before cleaning if
|
||||
// either the flags and arguments explicitly imply a package,
|
||||
// or no other target (such as a cache) was requested to be cleaned.
|
||||
cleanPkg := len(args) > 0 || cleanI || cleanR
|
||||
if (!modload.Enabled() || modload.HasModRoot()) &&
|
||||
!cleanCache && !cleanModcache && !cleanTestcache {
|
||||
cleanPkg = true
|
||||
}
|
||||
|
||||
if cleanPkg {
|
||||
for _, pkg := range load.PackagesAndErrors(args) {
|
||||
clean(pkg)
|
||||
}
|
||||
@ -122,11 +132,11 @@ func runClean(cmd *base.Command, args []string) {
|
||||
// and not something that we want to remove. Also, we'd like to preserve
|
||||
// the access log for future analysis, even if the cache is cleared.
|
||||
subdirs, _ := filepath.Glob(filepath.Join(dir, "[0-9a-f][0-9a-f]"))
|
||||
printedErrors := false
|
||||
if len(subdirs) > 0 {
|
||||
if cfg.BuildN || cfg.BuildX {
|
||||
b.Showcmd("", "rm -r %s", strings.Join(subdirs, " "))
|
||||
}
|
||||
printedErrors := false
|
||||
for _, d := range subdirs {
|
||||
// Only print the first error - there may be many.
|
||||
// This also mimics what os.RemoveAll(dir) would do.
|
||||
@ -136,6 +146,12 @@ func runClean(cmd *base.Command, args []string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logFile := filepath.Join(dir, "log.txt")
|
||||
if err := os.RemoveAll(logFile); err != nil && !printedErrors {
|
||||
printedErrors = true
|
||||
base.Errorf("go clean -cache: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,13 @@ package envcmd
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cache"
|
||||
@ -22,7 +25,7 @@ import (
|
||||
)
|
||||
|
||||
var CmdEnv = &base.Command{
|
||||
UsageLine: "go env [-json] [var ...]",
|
||||
UsageLine: "go env [-json] [-u] [-w] [var ...]",
|
||||
Short: "print Go environment information",
|
||||
Long: `
|
||||
Env prints Go environment information.
|
||||
@ -35,6 +38,14 @@ each named variable on its own line.
|
||||
The -json flag prints the environment in JSON format
|
||||
instead of as a shell script.
|
||||
|
||||
The -u flag requires one or more arguments and unsets
|
||||
the default setting for the named environment variables,
|
||||
if one has been set with 'go env -w'.
|
||||
|
||||
The -w flag requires one or more arguments of the
|
||||
form NAME=VALUE and changes the default settings
|
||||
of the named environment variables to the given values.
|
||||
|
||||
For more about environment variables, see 'go help environment'.
|
||||
`,
|
||||
}
|
||||
@ -43,26 +54,36 @@ func init() {
|
||||
CmdEnv.Run = runEnv // break init cycle
|
||||
}
|
||||
|
||||
var envJson = CmdEnv.Flag.Bool("json", false, "")
|
||||
var (
|
||||
envJson = CmdEnv.Flag.Bool("json", false, "")
|
||||
envU = CmdEnv.Flag.Bool("u", false, "")
|
||||
envW = CmdEnv.Flag.Bool("w", false, "")
|
||||
)
|
||||
|
||||
func MkEnv() []cfg.EnvVar {
|
||||
var b work.Builder
|
||||
b.Init()
|
||||
|
||||
envFile, _ := cfg.EnvFile()
|
||||
env := []cfg.EnvVar{
|
||||
{Name: "GO111MODULE", Value: cfg.Getenv("GO111MODULE")},
|
||||
{Name: "GOARCH", Value: cfg.Goarch},
|
||||
{Name: "GOBIN", Value: cfg.GOBIN},
|
||||
{Name: "GOCACHE", Value: cache.DefaultDir()},
|
||||
{Name: "GOENV", Value: envFile},
|
||||
{Name: "GOEXE", Value: cfg.ExeSuffix},
|
||||
{Name: "GOFLAGS", Value: os.Getenv("GOFLAGS")},
|
||||
{Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")},
|
||||
{Name: "GOHOSTARCH", Value: runtime.GOARCH},
|
||||
{Name: "GOHOSTOS", Value: runtime.GOOS},
|
||||
{Name: "GONOPROXY", Value: cfg.GONOPROXY},
|
||||
{Name: "GONOSUMDB", Value: cfg.GONOSUMDB},
|
||||
{Name: "GOOS", Value: cfg.Goos},
|
||||
{Name: "GOPATH", Value: cfg.BuildContext.GOPATH},
|
||||
{Name: "GOPROXY", Value: os.Getenv("GOPROXY")},
|
||||
{Name: "GORACE", Value: os.Getenv("GORACE")},
|
||||
{Name: "GOPRIVATE", Value: cfg.GOPRIVATE},
|
||||
{Name: "GOPROXY", Value: cfg.GOPROXY},
|
||||
{Name: "GOROOT", Value: cfg.GOROOT},
|
||||
{Name: "GOTMPDIR", Value: os.Getenv("GOTMPDIR")},
|
||||
{Name: "GOSUMDB", Value: cfg.GOSUMDB},
|
||||
{Name: "GOTMPDIR", Value: cfg.Getenv("GOTMPDIR")},
|
||||
{Name: "GOTOOLDIR", Value: base.ToolDir},
|
||||
}
|
||||
|
||||
@ -72,25 +93,20 @@ func MkEnv() []cfg.EnvVar {
|
||||
env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoName})
|
||||
}
|
||||
|
||||
switch cfg.Goarch {
|
||||
case "arm":
|
||||
env = append(env, cfg.EnvVar{Name: "GOARM", Value: cfg.GOARM})
|
||||
case "386":
|
||||
env = append(env, cfg.EnvVar{Name: "GO386", Value: cfg.GO386})
|
||||
case "mips", "mipsle":
|
||||
env = append(env, cfg.EnvVar{Name: "GOMIPS", Value: cfg.GOMIPS})
|
||||
case "mips64", "mips64le":
|
||||
env = append(env, cfg.EnvVar{Name: "GOMIPS64", Value: cfg.GOMIPS64})
|
||||
key, val := cfg.GetArchEnv()
|
||||
if key != "" {
|
||||
env = append(env, cfg.EnvVar{Name: key, Value: val})
|
||||
}
|
||||
|
||||
cc := cfg.DefaultCC(cfg.Goos, cfg.Goarch)
|
||||
if env := strings.Fields(os.Getenv("CC")); len(env) > 0 {
|
||||
if env := strings.Fields(cfg.Getenv("CC")); len(env) > 0 {
|
||||
cc = env[0]
|
||||
}
|
||||
cxx := cfg.DefaultCXX(cfg.Goos, cfg.Goarch)
|
||||
if env := strings.Fields(os.Getenv("CXX")); len(env) > 0 {
|
||||
if env := strings.Fields(cfg.Getenv("CXX")); len(env) > 0 {
|
||||
cxx = env[0]
|
||||
}
|
||||
env = append(env, cfg.EnvVar{Name: "AR", Value: envOr("AR", "ar")})
|
||||
env = append(env, cfg.EnvVar{Name: "CC", Value: cc})
|
||||
env = append(env, cfg.EnvVar{Name: "CXX", Value: cxx})
|
||||
|
||||
@ -103,6 +119,14 @@ func MkEnv() []cfg.EnvVar {
|
||||
return env
|
||||
}
|
||||
|
||||
func envOr(name, def string) string {
|
||||
val := cfg.Getenv(name)
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func findEnv(env []cfg.EnvVar, name string) string {
|
||||
for _, e := range env {
|
||||
if e.Name == name {
|
||||
@ -150,7 +174,25 @@ func ExtraEnvVarsCostly() []cfg.EnvVar {
|
||||
}
|
||||
}
|
||||
|
||||
// argKey returns the KEY part of the arg KEY=VAL, or else arg itself.
|
||||
func argKey(arg string) string {
|
||||
i := strings.Index(arg, "=")
|
||||
if i < 0 {
|
||||
return arg
|
||||
}
|
||||
return arg[:i]
|
||||
}
|
||||
|
||||
func runEnv(cmd *base.Command, args []string) {
|
||||
if *envJson && *envU {
|
||||
base.Fatalf("go env: cannot use -json with -u")
|
||||
}
|
||||
if *envJson && *envW {
|
||||
base.Fatalf("go env: cannot use -json with -w")
|
||||
}
|
||||
if *envU && *envW {
|
||||
base.Fatalf("go env: cannot use -u with -w")
|
||||
}
|
||||
env := cfg.CmdEnv
|
||||
env = append(env, ExtraEnvVars()...)
|
||||
|
||||
@ -161,7 +203,7 @@ func runEnv(cmd *base.Command, args []string) {
|
||||
if len(args) > 0 {
|
||||
needCostly = false
|
||||
for _, arg := range args {
|
||||
switch arg {
|
||||
switch argKey(arg) {
|
||||
case "CGO_CFLAGS",
|
||||
"CGO_CPPFLAGS",
|
||||
"CGO_CXXFLAGS",
|
||||
@ -177,6 +219,55 @@ func runEnv(cmd *base.Command, args []string) {
|
||||
env = append(env, ExtraEnvVarsCostly()...)
|
||||
}
|
||||
|
||||
if *envW {
|
||||
// Process and sanity-check command line.
|
||||
if len(args) == 0 {
|
||||
base.Fatalf("go env -w: no KEY=VALUE arguments given")
|
||||
}
|
||||
osEnv := make(map[string]string)
|
||||
for _, e := range cfg.OrigEnv {
|
||||
if i := strings.Index(e, "="); i >= 0 {
|
||||
osEnv[e[:i]] = e[i+1:]
|
||||
}
|
||||
}
|
||||
add := make(map[string]string)
|
||||
for _, arg := range args {
|
||||
i := strings.Index(arg, "=")
|
||||
if i < 0 {
|
||||
base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
|
||||
}
|
||||
key, val := arg[:i], arg[i+1:]
|
||||
if err := checkEnvWrite(key, val, env); err != nil {
|
||||
base.Fatalf("go env -w: %v", err)
|
||||
}
|
||||
if _, ok := add[key]; ok {
|
||||
base.Fatalf("go env -w: multiple values for key: %s", key)
|
||||
}
|
||||
add[key] = val
|
||||
if osVal := osEnv[key]; osVal != "" && osVal != val {
|
||||
fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
|
||||
}
|
||||
}
|
||||
updateEnvFile(add, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if *envU {
|
||||
// Process and sanity-check command line.
|
||||
if len(args) == 0 {
|
||||
base.Fatalf("go env -u: no arguments given")
|
||||
}
|
||||
del := make(map[string]bool)
|
||||
for _, arg := range args {
|
||||
if err := checkEnvWrite(arg, "", env); err != nil {
|
||||
base.Fatalf("go env -u: %v", err)
|
||||
}
|
||||
del[arg] = true
|
||||
}
|
||||
updateEnvFile(nil, del)
|
||||
return
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
if *envJson {
|
||||
var es []cfg.EnvVar
|
||||
@ -235,6 +326,118 @@ func printEnvAsJSON(env []cfg.EnvVar) {
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", "\t")
|
||||
if err := enc.Encode(m); err != nil {
|
||||
base.Fatalf("%s", err)
|
||||
base.Fatalf("go env -json: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func checkEnvWrite(key, val string, env []cfg.EnvVar) error {
|
||||
switch key {
|
||||
case "GOEXE", "GOGCCFLAGS", "GOHOSTARCH", "GOHOSTOS", "GOMOD", "GOTOOLDIR":
|
||||
return fmt.Errorf("%s cannot be modified", key)
|
||||
case "GOENV":
|
||||
return fmt.Errorf("%s can only be set using the OS environment", key)
|
||||
}
|
||||
|
||||
// To catch typos and the like, check that we know the variable.
|
||||
if !cfg.CanGetenv(key) {
|
||||
return fmt.Errorf("unknown go command variable %s", key)
|
||||
}
|
||||
|
||||
if !utf8.ValidString(val) {
|
||||
return fmt.Errorf("invalid UTF-8 in %s=... value", key)
|
||||
}
|
||||
if strings.Contains(val, "\x00") {
|
||||
return fmt.Errorf("invalid NUL in %s=... value", key)
|
||||
}
|
||||
if strings.ContainsAny(val, "\v\r\n") {
|
||||
return fmt.Errorf("invalid newline in %s=... value", key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateEnvFile(add map[string]string, del map[string]bool) {
|
||||
file, err := cfg.EnvFile()
|
||||
if file == "" {
|
||||
base.Fatalf("go env: cannot find go env config: %v", err)
|
||||
}
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil && (!os.IsNotExist(err) || len(add) == 0) {
|
||||
base.Fatalf("go env: reading go env config: %v", err)
|
||||
}
|
||||
|
||||
lines := strings.SplitAfter(string(data), "\n")
|
||||
if lines[len(lines)-1] == "" {
|
||||
lines = lines[:len(lines)-1]
|
||||
} else {
|
||||
lines[len(lines)-1] += "\n"
|
||||
}
|
||||
|
||||
// Delete all but last copy of any duplicated variables,
|
||||
// since the last copy is the one that takes effect.
|
||||
prev := make(map[string]int)
|
||||
for l, line := range lines {
|
||||
if key := lineToKey(line); key != "" {
|
||||
if p, ok := prev[key]; ok {
|
||||
lines[p] = ""
|
||||
}
|
||||
prev[key] = l
|
||||
}
|
||||
}
|
||||
|
||||
// Add variables (go env -w). Update existing lines in file if present, add to end otherwise.
|
||||
for key, val := range add {
|
||||
if p, ok := prev[key]; ok {
|
||||
lines[p] = key + "=" + val + "\n"
|
||||
delete(add, key)
|
||||
}
|
||||
}
|
||||
for key, val := range add {
|
||||
lines = append(lines, key+"="+val+"\n")
|
||||
}
|
||||
|
||||
// Delete requested variables (go env -u).
|
||||
for key := range del {
|
||||
if p, ok := prev[key]; ok {
|
||||
lines[p] = ""
|
||||
}
|
||||
}
|
||||
|
||||
// Sort runs of KEY=VALUE lines
|
||||
// (that is, blocks of lines where blocks are separated
|
||||
// by comments, blank lines, or invalid lines).
|
||||
start := 0
|
||||
for i := 0; i <= len(lines); i++ {
|
||||
if i == len(lines) || lineToKey(lines[i]) == "" {
|
||||
sortKeyValues(lines[start:i])
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
data = []byte(strings.Join(lines, ""))
|
||||
err = ioutil.WriteFile(file, data, 0666)
|
||||
if err != nil {
|
||||
// Try creating directory.
|
||||
os.MkdirAll(filepath.Dir(file), 0777)
|
||||
err = ioutil.WriteFile(file, data, 0666)
|
||||
if err != nil {
|
||||
base.Fatalf("go env: writing go env config: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// lineToKey returns the KEY part of the line KEY=VALUE or else an empty string.
|
||||
func lineToKey(line string) string {
|
||||
i := strings.Index(line, "=")
|
||||
if i < 0 || strings.Contains(line[:i], "#") {
|
||||
return ""
|
||||
}
|
||||
return line[:i]
|
||||
}
|
||||
|
||||
// sortKeyValues sorts a sequence of lines by key.
|
||||
// It differs from sort.Strings in that GO386= sorts after GO=.
|
||||
func sortKeyValues(lines []string) {
|
||||
sort.Slice(lines, func(i, j int) bool {
|
||||
return lineToKey(lines[i]) < lineToKey(lines[j])
|
||||
})
|
||||
}
|
||||
|
@ -110,11 +110,13 @@ specifies that the command "foo" represents the generator
|
||||
"go tool foo".
|
||||
|
||||
Generate processes packages in the order given on the command line,
|
||||
one at a time. If the command line lists .go files, they are treated
|
||||
as a single package. Within a package, generate processes the
|
||||
one at a time. If the command line lists .go files from a single directory,
|
||||
they are treated as a single package. Within a package, generate processes the
|
||||
source files in a package in file name order, one at a time. Within
|
||||
a source file, generate runs generators in the order they appear
|
||||
in the file, one at a time.
|
||||
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.
|
||||
|
||||
If any generator returns an error exit status, "go generate" skips
|
||||
all further processing for that package.
|
||||
@ -161,6 +163,9 @@ func runGenerate(cmd *base.Command, args []string) {
|
||||
log.Fatalf("generate: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "generate")
|
||||
|
||||
// Even if the arguments are .go files, this loop suffices.
|
||||
printed := false
|
||||
for _, pkg := range load.Packages(args) {
|
||||
@ -374,7 +379,12 @@ Words:
|
||||
// Substitute command if required.
|
||||
if len(words) > 0 && g.commands[words[0]] != nil {
|
||||
// Replace 0th word by command substitution.
|
||||
words = append(g.commands[words[0]], words[1:]...)
|
||||
//
|
||||
// Force a copy of the command definition to
|
||||
// ensure words doesn't end up as a reference
|
||||
// to the g.commands content.
|
||||
tmpCmdWords := append([]string(nil), (g.commands[words[0]])...)
|
||||
words = append(tmpCmdWords, words[1:]...)
|
||||
}
|
||||
// Substitute environment variables.
|
||||
for i, word := range words {
|
||||
@ -428,7 +438,7 @@ func (g *Generator) exec(words []string) {
|
||||
cmd.Stderr = os.Stderr
|
||||
// Run the command in the package directory.
|
||||
cmd.Dir = g.dir
|
||||
cmd.Env = base.MergeEnvLists(g.env, cfg.OrigEnv)
|
||||
cmd.Env = append(cfg.OrigEnv, g.env...)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
g.errorf("running %q: %s", words[0], err)
|
||||
|
@ -5,6 +5,7 @@
|
||||
package generate
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
@ -15,6 +16,15 @@ type splitTest struct {
|
||||
out []string
|
||||
}
|
||||
|
||||
// Same as above, except including source line number to set
|
||||
type splitTestWithLine struct {
|
||||
in string
|
||||
out []string
|
||||
lineNumber int
|
||||
}
|
||||
|
||||
const anyLineNo = 0
|
||||
|
||||
var splitTests = []splitTest{
|
||||
{"", nil},
|
||||
{"x", []string{"x"}},
|
||||
@ -54,3 +64,191 @@ func TestGenerateCommandParse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These environment variables will be undefined before the splitTestWithLine tests
|
||||
var undefEnvList = []string{
|
||||
"_XYZZY_",
|
||||
}
|
||||
|
||||
// These environment variables will be defined before the splitTestWithLine tests
|
||||
var defEnvMap = map[string]string{
|
||||
"_PLUGH_": "SomeVal",
|
||||
"_X": "Y",
|
||||
}
|
||||
|
||||
// TestGenerateCommandShortHand - similar to TestGenerateCommandParse,
|
||||
// except:
|
||||
// 1. if the result starts with -command, record that shorthand
|
||||
// before moving on to the next test.
|
||||
// 2. If a source line number is specified, set that in the parser
|
||||
// before executing the test. i.e., execute the split as if it
|
||||
// processing that source line.
|
||||
func TestGenerateCommandShorthand(t *testing.T) {
|
||||
g := &Generator{
|
||||
r: nil, // Unused here.
|
||||
path: "/usr/ken/sys/proc.go",
|
||||
dir: "/usr/ken/sys",
|
||||
file: "proc.go",
|
||||
pkg: "sys",
|
||||
commands: make(map[string][]string),
|
||||
}
|
||||
|
||||
var inLine string
|
||||
var expected, got []string
|
||||
|
||||
g.setEnv()
|
||||
|
||||
// Set up the system environment variables
|
||||
for i := range undefEnvList {
|
||||
os.Unsetenv(undefEnvList[i])
|
||||
}
|
||||
for k := range defEnvMap {
|
||||
os.Setenv(k, defEnvMap[k])
|
||||
}
|
||||
|
||||
// simple command from environment variable
|
||||
inLine = "//go:generate -command CMD0 \"ab${_X}cd\""
|
||||
expected = []string{"-command", "CMD0", "abYcd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
|
||||
// try again, with an extra level of indirection (should leave variable in command)
|
||||
inLine = "//go:generate -command CMD0 \"ab${DOLLAR}{_X}cd\""
|
||||
expected = []string{"-command", "CMD0", "ab${_X}cd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
|
||||
// Now the interesting part, record that output as a command
|
||||
g.setShorthand(got)
|
||||
|
||||
// see that the command still substitutes correctly from env. variable
|
||||
inLine = "//go:generate CMD0"
|
||||
expected = []string{"abYcd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
|
||||
// Now change the value of $X and see if the recorded definition is
|
||||
// still intact (vs. having the $_X already substituted out)
|
||||
|
||||
os.Setenv("_X", "Z")
|
||||
inLine = "//go:generate CMD0"
|
||||
expected = []string{"abZcd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
|
||||
// What if the variable is now undefined? Should be empty substitution.
|
||||
|
||||
os.Unsetenv("_X")
|
||||
inLine = "//go:generate CMD0"
|
||||
expected = []string{"abcd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
|
||||
// Try another undefined variable as an extra check
|
||||
os.Unsetenv("_Z")
|
||||
inLine = "//go:generate -command CMD1 \"ab${_Z}cd\""
|
||||
expected = []string{"-command", "CMD1", "abcd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
|
||||
g.setShorthand(got)
|
||||
|
||||
inLine = "//go:generate CMD1"
|
||||
expected = []string{"abcd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
|
||||
const val = "someNewValue"
|
||||
os.Setenv("_Z", val)
|
||||
|
||||
// try again with the properly-escaped variable.
|
||||
|
||||
inLine = "//go:generate -command CMD2 \"ab${DOLLAR}{_Z}cd\""
|
||||
expected = []string{"-command", "CMD2", "ab${_Z}cd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
|
||||
g.setShorthand(got)
|
||||
|
||||
inLine = "//go:generate CMD2"
|
||||
expected = []string{"ab" + val + "cd"}
|
||||
got = g.split(inLine + "\n")
|
||||
|
||||
if !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("split(%q): got %q expected %q", inLine, got, expected)
|
||||
}
|
||||
}
|
||||
|
||||
// Command-related tests for TestGenerateCommandShortHand2
|
||||
// -- Note line numbers included to check substitutions from "build-in" variable - $GOLINE
|
||||
var splitTestsLines = []splitTestWithLine{
|
||||
{"-command TEST1 $GOLINE", []string{"-command", "TEST1", "22"}, 22},
|
||||
{"-command TEST2 ${DOLLAR}GOLINE", []string{"-command", "TEST2", "$GOLINE"}, 26},
|
||||
{"TEST1", []string{"22"}, 33},
|
||||
{"TEST2", []string{"66"}, 66},
|
||||
{"TEST1 ''", []string{"22", "''"}, 99},
|
||||
{"TEST2 ''", []string{"44", "''"}, 44},
|
||||
}
|
||||
|
||||
// TestGenerateCommandShortHand - similar to TestGenerateCommandParse,
|
||||
// except:
|
||||
// 1. if the result starts with -command, record that shorthand
|
||||
// before moving on to the next test.
|
||||
// 2. If a source line number is specified, set that in the parser
|
||||
// before executing the test. i.e., execute the split as if it
|
||||
// processing that source line.
|
||||
func TestGenerateCommandShortHand2(t *testing.T) {
|
||||
g := &Generator{
|
||||
r: nil, // Unused here.
|
||||
path: "/usr/ken/sys/proc.go",
|
||||
dir: "/usr/ken/sys",
|
||||
file: "proc.go",
|
||||
pkg: "sys",
|
||||
commands: make(map[string][]string),
|
||||
}
|
||||
g.setEnv()
|
||||
for _, test := range splitTestsLines {
|
||||
// if the test specified a line number, reflect that
|
||||
if test.lineNumber != anyLineNo {
|
||||
g.lineNum = test.lineNumber
|
||||
g.setEnv()
|
||||
}
|
||||
// First with newlines.
|
||||
got := g.split("//go:generate " + test.in + "\n")
|
||||
if !reflect.DeepEqual(got, test.out) {
|
||||
t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
|
||||
}
|
||||
// Then with CRLFs, thank you Windows.
|
||||
got = g.split("//go:generate " + test.in + "\r\n")
|
||||
if !reflect.DeepEqual(got, test.out) {
|
||||
t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
|
||||
}
|
||||
if got[0] == "-command" { // record commands
|
||||
g.setShorthand(got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,11 +118,6 @@ func runGet(cmd *base.Command, args []string) {
|
||||
// Should not happen: main.go should install the separate module-enabled get code.
|
||||
base.Fatalf("go get: modules not implemented")
|
||||
}
|
||||
if cfg.GoModInGOPATH != "" {
|
||||
// Warn about not using modules with GO111MODULE=auto when go.mod exists.
|
||||
// To silence the warning, users can set GO111MODULE=off.
|
||||
fmt.Fprintf(os.Stderr, "go get: warning: modules disabled by GO111MODULE=auto in GOPATH/src;\n\tignoring %s;\n\tsee 'go help modules'\n", base.ShortPath(cfg.GoModInGOPATH))
|
||||
}
|
||||
|
||||
work.BuildInit()
|
||||
|
||||
@ -177,12 +172,6 @@ func runGet(cmd *base.Command, args []string) {
|
||||
// everything.
|
||||
load.ClearPackageCache()
|
||||
|
||||
// In order to rebuild packages information completely,
|
||||
// we need to clear commands cache. Command packages are
|
||||
// referring to evicted packages from the package cache.
|
||||
// This leads to duplicated loads of the standard packages.
|
||||
load.ClearCmdCache()
|
||||
|
||||
pkgs := load.PackagesForBuild(args)
|
||||
|
||||
// Phase 3. Install.
|
||||
@ -240,7 +229,8 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
||||
}
|
||||
load1 := func(path string, mode int) *load.Package {
|
||||
if parent == nil {
|
||||
return load.LoadPackageNoFlags(path, stk)
|
||||
mode := 0 // don't do module or vendor resolution
|
||||
return load.LoadImport(path, base.Cwd, nil, stk, nil, mode)
|
||||
}
|
||||
return load.LoadImport(path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
|
||||
}
|
||||
@ -397,7 +387,7 @@ func downloadPackage(p *load.Package) error {
|
||||
blindRepo bool // set if the repo has unusual configuration
|
||||
)
|
||||
|
||||
security := web.Secure
|
||||
security := web.SecureOnly
|
||||
if Insecure {
|
||||
security = web.Insecure
|
||||
}
|
||||
|
@ -41,6 +41,9 @@ func checkPath(path string, fileName bool) error {
|
||||
if path == "" {
|
||||
return fmt.Errorf("empty string")
|
||||
}
|
||||
if path[0] == '-' {
|
||||
return fmt.Errorf("leading dash")
|
||||
}
|
||||
if strings.Contains(path, "..") {
|
||||
return fmt.Errorf("double dot")
|
||||
}
|
||||
|
@ -8,9 +8,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"internal/lazyregexp"
|
||||
"internal/singleflight"
|
||||
"log"
|
||||
"net/url"
|
||||
urlpkg "net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -53,7 +54,7 @@ var defaultSecureScheme = map[string]bool{
|
||||
}
|
||||
|
||||
func (v *vcsCmd) isSecure(repo string) bool {
|
||||
u, err := url.Parse(repo)
|
||||
u, err := urlpkg.Parse(repo)
|
||||
if err != nil {
|
||||
// If repo is not a URL, it's not secure.
|
||||
return false
|
||||
@ -111,7 +112,7 @@ var vcsHg = &vcsCmd{
|
||||
name: "Mercurial",
|
||||
cmd: "hg",
|
||||
|
||||
createCmd: []string{"clone -U {repo} {dir}"},
|
||||
createCmd: []string{"clone -U -- {repo} {dir}"},
|
||||
downloadCmd: []string{"pull"},
|
||||
|
||||
// We allow both tag and branch names as 'tags'
|
||||
@ -127,7 +128,7 @@ var vcsHg = &vcsCmd{
|
||||
tagSyncDefault: []string{"update default"},
|
||||
|
||||
scheme: []string{"https", "http", "ssh"},
|
||||
pingCmd: "identify {scheme}://{repo}",
|
||||
pingCmd: "identify -- {scheme}://{repo}",
|
||||
remoteRepo: hgRemoteRepo,
|
||||
}
|
||||
|
||||
@ -144,7 +145,7 @@ var vcsGit = &vcsCmd{
|
||||
name: "Git",
|
||||
cmd: "git",
|
||||
|
||||
createCmd: []string{"clone {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"},
|
||||
createCmd: []string{"clone -- {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"},
|
||||
downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},
|
||||
|
||||
tagCmd: []tagCmd{
|
||||
@ -164,13 +165,13 @@ var vcsGit = &vcsCmd{
|
||||
tagSyncDefault: []string{"submodule update --init --recursive"},
|
||||
|
||||
scheme: []string{"git", "https", "http", "git+ssh", "ssh"},
|
||||
pingCmd: "ls-remote {scheme}://{repo}",
|
||||
pingCmd: "ls-remote -- {scheme}://{repo}",
|
||||
remoteRepo: gitRemoteRepo,
|
||||
}
|
||||
|
||||
// scpSyntaxRe matches the SCP-like addresses used by Git to access
|
||||
// repositories by SSH.
|
||||
var scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
|
||||
var scpSyntaxRe = lazyregexp.New(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
|
||||
|
||||
func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) {
|
||||
cmd := "config remote.origin.url"
|
||||
@ -187,19 +188,19 @@ func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error
|
||||
}
|
||||
out := strings.TrimSpace(string(outb))
|
||||
|
||||
var repoURL *url.URL
|
||||
var repoURL *urlpkg.URL
|
||||
if m := scpSyntaxRe.FindStringSubmatch(out); m != nil {
|
||||
// Match SCP-like syntax and convert it to a URL.
|
||||
// Eg, "git@github.com:user/repo" becomes
|
||||
// "ssh://git@github.com/user/repo".
|
||||
repoURL = &url.URL{
|
||||
repoURL = &urlpkg.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User(m[1]),
|
||||
User: urlpkg.User(m[1]),
|
||||
Host: m[2],
|
||||
Path: m[3],
|
||||
}
|
||||
} else {
|
||||
repoURL, err = url.Parse(out)
|
||||
repoURL, err = urlpkg.Parse(out)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -221,7 +222,7 @@ var vcsBzr = &vcsCmd{
|
||||
name: "Bazaar",
|
||||
cmd: "bzr",
|
||||
|
||||
createCmd: []string{"branch {repo} {dir}"},
|
||||
createCmd: []string{"branch -- {repo} {dir}"},
|
||||
|
||||
// Without --overwrite bzr will not pull tags that changed.
|
||||
// Replace by --overwrite-tags after http://pad.lv/681792 goes in.
|
||||
@ -232,7 +233,7 @@ var vcsBzr = &vcsCmd{
|
||||
tagSyncDefault: []string{"update -r revno:-1"},
|
||||
|
||||
scheme: []string{"https", "http", "bzr", "bzr+ssh"},
|
||||
pingCmd: "info {scheme}://{repo}",
|
||||
pingCmd: "info -- {scheme}://{repo}",
|
||||
remoteRepo: bzrRemoteRepo,
|
||||
resolveRepo: bzrResolveRepo,
|
||||
}
|
||||
@ -283,14 +284,14 @@ var vcsSvn = &vcsCmd{
|
||||
name: "Subversion",
|
||||
cmd: "svn",
|
||||
|
||||
createCmd: []string{"checkout {repo} {dir}"},
|
||||
createCmd: []string{"checkout -- {repo} {dir}"},
|
||||
downloadCmd: []string{"update"},
|
||||
|
||||
// There is no tag command in subversion.
|
||||
// The branch information is all in the path names.
|
||||
|
||||
scheme: []string{"https", "http", "svn", "svn+ssh"},
|
||||
pingCmd: "info {scheme}://{repo}",
|
||||
pingCmd: "info -- {scheme}://{repo}",
|
||||
remoteRepo: svnRemoteRepo,
|
||||
}
|
||||
|
||||
@ -333,7 +334,7 @@ var vcsFossil = &vcsCmd{
|
||||
name: "Fossil",
|
||||
cmd: "fossil",
|
||||
|
||||
createCmd: []string{"-go-internal-mkdir {dir} clone {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"},
|
||||
createCmd: []string{"-go-internal-mkdir {dir} clone -- {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"},
|
||||
downloadCmd: []string{"up"},
|
||||
|
||||
tagCmd: []tagCmd{{"tag ls", `(.*)`}},
|
||||
@ -424,8 +425,8 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
|
||||
cmd.Dir = dir
|
||||
cmd.Env = base.EnvForDir(cmd.Dir, os.Environ())
|
||||
if cfg.BuildX {
|
||||
fmt.Printf("cd %s\n", dir)
|
||||
fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " "))
|
||||
fmt.Fprintf(os.Stderr, "cd %s\n", dir)
|
||||
fmt.Fprintf(os.Stderr, "%s %s\n", v.cmd, strings.Join(args, " "))
|
||||
}
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
@ -525,13 +526,11 @@ func (v *vcsCmd) tagSync(dir, tag string) error {
|
||||
// version control system and repository name.
|
||||
type vcsPath struct {
|
||||
prefix string // prefix this description applies to
|
||||
re string // pattern for import path
|
||||
regexp *lazyregexp.Regexp // compiled pattern for import path
|
||||
repo string // repository to use (expand with match of re)
|
||||
vcs string // version control system to use (expand with match of re)
|
||||
check func(match map[string]string) error // additional checks
|
||||
ping bool // ping for scheme to use to download repo
|
||||
|
||||
regexp *regexp.Regexp // cached compiled form of re
|
||||
}
|
||||
|
||||
// vcsFromDir inspects dir and its parents to determine the
|
||||
@ -632,7 +631,14 @@ type RepoRoot struct {
|
||||
vcs *vcsCmd // internal: vcs command access
|
||||
}
|
||||
|
||||
var httpPrefixRE = regexp.MustCompile(`^https?:`)
|
||||
func httpPrefix(s string) string {
|
||||
for _, prefix := range [...]string{"http:", "https:"} {
|
||||
if strings.HasPrefix(s, prefix) {
|
||||
return prefix
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ModuleMode specifies whether to prefer modules when looking up code sources.
|
||||
type ModuleMode int
|
||||
@ -677,10 +683,10 @@ var errUnknownSite = errors.New("dynamic lookup required to find mapping")
|
||||
func repoRootFromVCSPaths(importPath, scheme string, security web.SecurityMode, vcsPaths []*vcsPath) (*RepoRoot, error) {
|
||||
// A common error is to use https://packagepath because that's what
|
||||
// hg and git require. Diagnose this helpfully.
|
||||
if loc := httpPrefixRE.FindStringIndex(importPath); loc != nil {
|
||||
if prefix := httpPrefix(importPath); prefix != "" {
|
||||
// The importPath has been cleaned, so has only one slash. The pattern
|
||||
// ignores the slashes; the error message puts them back on the RHS at least.
|
||||
return nil, fmt.Errorf("%q not allowed in import path", importPath[loc[0]:loc[1]]+"//")
|
||||
return nil, fmt.Errorf("%q not allowed in import path", prefix+"//")
|
||||
}
|
||||
for _, srv := range vcsPaths {
|
||||
if !strings.HasPrefix(importPath, srv.prefix) {
|
||||
@ -724,7 +730,7 @@ func repoRootFromVCSPaths(importPath, scheme string, security web.SecurityMode,
|
||||
match["repo"] = scheme + "://" + match["repo"]
|
||||
} else {
|
||||
for _, scheme := range vcs.scheme {
|
||||
if security == web.Secure && !vcs.isSecureScheme(scheme) {
|
||||
if security == web.SecureOnly && !vcs.isSecureScheme(scheme) {
|
||||
continue
|
||||
}
|
||||
if vcs.pingCmd != "" && vcs.ping(scheme, match["repo"]) == nil {
|
||||
@ -748,20 +754,35 @@ func repoRootFromVCSPaths(importPath, scheme string, security web.SecurityMode,
|
||||
return nil, errUnknownSite
|
||||
}
|
||||
|
||||
// urlForImportPath returns a partially-populated URL for the given Go import path.
|
||||
//
|
||||
// The URL leaves the Scheme field blank so that web.Get will try any scheme
|
||||
// allowed by the selected security mode.
|
||||
func urlForImportPath(importPath string) (*urlpkg.URL, error) {
|
||||
slash := strings.Index(importPath, "/")
|
||||
if slash < 0 {
|
||||
slash = len(importPath)
|
||||
}
|
||||
host, path := importPath[:slash], importPath[slash:]
|
||||
if !strings.Contains(host, ".") {
|
||||
return nil, errors.New("import path does not begin with hostname")
|
||||
}
|
||||
if len(path) == 0 {
|
||||
path = "/"
|
||||
}
|
||||
return &urlpkg.URL{Host: host, Path: path, RawQuery: "go-get=1"}, nil
|
||||
}
|
||||
|
||||
// repoRootForImportDynamic finds a *RepoRoot for a custom domain that's not
|
||||
// statically known by repoRootForImportPathStatic.
|
||||
//
|
||||
// This handles custom import paths like "name.tld/pkg/foo" or just "name.tld".
|
||||
func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.SecurityMode) (*RepoRoot, error) {
|
||||
slash := strings.Index(importPath, "/")
|
||||
if slash < 0 {
|
||||
slash = len(importPath)
|
||||
url, err := urlForImportPath(importPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
host := importPath[:slash]
|
||||
if !strings.Contains(host, ".") {
|
||||
return nil, errors.New("import path does not begin with hostname")
|
||||
}
|
||||
urlStr, body, err := web.GetMaybeInsecure(importPath, security)
|
||||
resp, err := web.Get(security, url)
|
||||
if err != nil {
|
||||
msg := "https fetch: %v"
|
||||
if security == web.Insecure {
|
||||
@ -769,6 +790,7 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se
|
||||
}
|
||||
return nil, fmt.Errorf(msg, err)
|
||||
}
|
||||
body := resp.Body
|
||||
defer body.Close()
|
||||
imports, err := parseMetaGoImports(body, mod)
|
||||
if err != nil {
|
||||
@ -778,12 +800,12 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se
|
||||
mmi, err := matchGoImport(imports, importPath)
|
||||
if err != nil {
|
||||
if _, ok := err.(ImportMismatchError); !ok {
|
||||
return nil, fmt.Errorf("parse %s: %v", urlStr, err)
|
||||
return nil, fmt.Errorf("parse %s: %v", url, err)
|
||||
}
|
||||
return nil, fmt.Errorf("parse %s: no go-import meta tags (%s)", urlStr, err)
|
||||
return nil, fmt.Errorf("parse %s: no go-import meta tags (%s)", resp.URL, err)
|
||||
}
|
||||
if cfg.BuildV {
|
||||
log.Printf("get %q: found meta tag %#v at %s", importPath, mmi, urlStr)
|
||||
log.Printf("get %q: found meta tag %#v at %s", importPath, mmi, url)
|
||||
}
|
||||
// If the import was "uni.edu/bob/project", which said the
|
||||
// prefix was "uni.edu" and the RepoRoot was "evilroot.com",
|
||||
@ -795,24 +817,23 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se
|
||||
if cfg.BuildV {
|
||||
log.Printf("get %q: verifying non-authoritative meta tag", importPath)
|
||||
}
|
||||
urlStr0 := urlStr
|
||||
var imports []metaImport
|
||||
urlStr, imports, err = metaImportsForPrefix(mmi.Prefix, mod, security)
|
||||
url, imports, err = metaImportsForPrefix(mmi.Prefix, mod, security)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
metaImport2, err := matchGoImport(imports, importPath)
|
||||
if err != nil || mmi != metaImport2 {
|
||||
return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, mmi.Prefix)
|
||||
return nil, fmt.Errorf("%s and %s disagree about go-import for %s", resp.URL, url, mmi.Prefix)
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateRepoRoot(mmi.RepoRoot); err != nil {
|
||||
return nil, fmt.Errorf("%s: invalid repo root %q: %v", urlStr, mmi.RepoRoot, err)
|
||||
return nil, fmt.Errorf("%s: invalid repo root %q: %v", resp.URL, mmi.RepoRoot, err)
|
||||
}
|
||||
vcs := vcsByCmd(mmi.VCS)
|
||||
if vcs == nil && mmi.VCS != "mod" {
|
||||
return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, mmi.VCS)
|
||||
return nil, fmt.Errorf("%s: unknown vcs %q", resp.URL, mmi.VCS)
|
||||
}
|
||||
|
||||
rr := &RepoRoot{
|
||||
@ -828,13 +849,16 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se
|
||||
// validateRepoRoot returns an error if repoRoot does not seem to be
|
||||
// a valid URL with scheme.
|
||||
func validateRepoRoot(repoRoot string) error {
|
||||
url, err := url.Parse(repoRoot)
|
||||
url, err := urlpkg.Parse(repoRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if url.Scheme == "" {
|
||||
return errors.New("no scheme")
|
||||
}
|
||||
if url.Scheme == "file" {
|
||||
return errors.New("file scheme disallowed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -850,9 +874,9 @@ var (
|
||||
//
|
||||
// The importPath is of the form "golang.org/x/tools".
|
||||
// It is an error if no imports are found.
|
||||
// urlStr will still be valid if err != nil.
|
||||
// The returned urlStr will be of the form "https://golang.org/x/tools?go-get=1"
|
||||
func metaImportsForPrefix(importPrefix string, mod ModuleMode, security web.SecurityMode) (urlStr string, imports []metaImport, err error) {
|
||||
// url will still be valid if err != nil.
|
||||
// The returned url will be of the form "https://golang.org/x/tools?go-get=1"
|
||||
func metaImportsForPrefix(importPrefix string, mod ModuleMode, security web.SecurityMode) (*urlpkg.URL, []metaImport, error) {
|
||||
setCache := func(res fetchResult) (fetchResult, error) {
|
||||
fetchCacheMu.Lock()
|
||||
defer fetchCacheMu.Unlock()
|
||||
@ -868,25 +892,31 @@ func metaImportsForPrefix(importPrefix string, mod ModuleMode, security web.Secu
|
||||
}
|
||||
fetchCacheMu.Unlock()
|
||||
|
||||
urlStr, body, err := web.GetMaybeInsecure(importPrefix, security)
|
||||
url, err := urlForImportPath(importPrefix)
|
||||
if err != nil {
|
||||
return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("fetch %s: %v", urlStr, err)})
|
||||
return setCache(fetchResult{err: err})
|
||||
}
|
||||
resp, err := web.Get(security, url)
|
||||
if err != nil {
|
||||
return setCache(fetchResult{url: url, err: fmt.Errorf("fetch %s: %v", resp.URL, err)})
|
||||
}
|
||||
body := resp.Body
|
||||
defer body.Close()
|
||||
imports, err := parseMetaGoImports(body, mod)
|
||||
if err != nil {
|
||||
return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("parsing %s: %v", urlStr, err)})
|
||||
return setCache(fetchResult{url: url, err: fmt.Errorf("parsing %s: %v", resp.URL, err)})
|
||||
}
|
||||
if len(imports) == 0 {
|
||||
err = fmt.Errorf("fetch %s: no go-import meta tag", urlStr)
|
||||
err = fmt.Errorf("fetch %s: no go-import meta tag", url)
|
||||
}
|
||||
return setCache(fetchResult{urlStr: urlStr, imports: imports, err: err})
|
||||
return setCache(fetchResult{url: url, imports: imports, err: err})
|
||||
})
|
||||
res := resi.(fetchResult)
|
||||
return res.urlStr, res.imports, res.err
|
||||
return res.url, res.imports, res.err
|
||||
}
|
||||
|
||||
type fetchResult struct {
|
||||
urlStr string // e.g. "https://foo.com/x/bar?go-get=1"
|
||||
url *urlpkg.URL
|
||||
imports []metaImport
|
||||
err error
|
||||
}
|
||||
@ -975,7 +1005,7 @@ var vcsPaths = []*vcsPath{
|
||||
// Github
|
||||
{
|
||||
prefix: "github.com/",
|
||||
re: `^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[\p{L}0-9_.\-]+)*$`,
|
||||
regexp: lazyregexp.New(`^(?P<root>github\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[\p{L}0-9_.\-]+)*$`),
|
||||
vcs: "git",
|
||||
repo: "https://{root}",
|
||||
check: noVCSSuffix,
|
||||
@ -984,7 +1014,7 @@ var vcsPaths = []*vcsPath{
|
||||
// Bitbucket
|
||||
{
|
||||
prefix: "bitbucket.org/",
|
||||
re: `^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
|
||||
regexp: lazyregexp.New(`^(?P<root>bitbucket\.org/(?P<bitname>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),
|
||||
repo: "https://{root}",
|
||||
check: bitbucketVCS,
|
||||
},
|
||||
@ -992,7 +1022,7 @@ var vcsPaths = []*vcsPath{
|
||||
// IBM DevOps Services (JazzHub)
|
||||
{
|
||||
prefix: "hub.jazz.net/git/",
|
||||
re: `^(?P<root>hub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
|
||||
regexp: lazyregexp.New(`^(?P<root>hub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`),
|
||||
vcs: "git",
|
||||
repo: "https://{root}",
|
||||
check: noVCSSuffix,
|
||||
@ -1001,7 +1031,7 @@ var vcsPaths = []*vcsPath{
|
||||
// Git at Apache
|
||||
{
|
||||
prefix: "git.apache.org/",
|
||||
re: `^(?P<root>git\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`,
|
||||
regexp: lazyregexp.New(`^(?P<root>git\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`),
|
||||
vcs: "git",
|
||||
repo: "https://{root}",
|
||||
},
|
||||
@ -1009,7 +1039,7 @@ var vcsPaths = []*vcsPath{
|
||||
// Git at OpenStack
|
||||
{
|
||||
prefix: "git.openstack.org/",
|
||||
re: `^(?P<root>git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`,
|
||||
regexp: lazyregexp.New(`^(?P<root>git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`),
|
||||
vcs: "git",
|
||||
repo: "https://{root}",
|
||||
},
|
||||
@ -1017,7 +1047,7 @@ var vcsPaths = []*vcsPath{
|
||||
// chiselapp.com for fossil
|
||||
{
|
||||
prefix: "chiselapp.com/",
|
||||
re: `^(?P<root>chiselapp\.com/user/[A-Za-z0-9]+/repository/[A-Za-z0-9_.\-]+)$`,
|
||||
regexp: lazyregexp.New(`^(?P<root>chiselapp\.com/user/[A-Za-z0-9]+/repository/[A-Za-z0-9_.\-]+)$`),
|
||||
vcs: "fossil",
|
||||
repo: "https://{root}",
|
||||
},
|
||||
@ -1025,8 +1055,8 @@ var vcsPaths = []*vcsPath{
|
||||
// General syntax for any server.
|
||||
// Must be last.
|
||||
{
|
||||
re: `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P<vcs>bzr|fossil|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$`,
|
||||
ping: true,
|
||||
regexp: lazyregexp.New(`(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P<vcs>bzr|fossil|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$`),
|
||||
ping: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1038,25 +1068,13 @@ var vcsPathsAfterDynamic = []*vcsPath{
|
||||
// Launchpad. See golang.org/issue/11436.
|
||||
{
|
||||
prefix: "launchpad.net/",
|
||||
re: `^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
|
||||
regexp: lazyregexp.New(`^(?P<root>launchpad\.net/((?P<project>[A-Za-z0-9_.\-]+)(?P<series>/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`),
|
||||
vcs: "bzr",
|
||||
repo: "https://{root}",
|
||||
check: launchpadVCS,
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
// fill in cached regexps.
|
||||
// Doing this eagerly discovers invalid regexp syntax
|
||||
// without having to run a command that needs that regexp.
|
||||
for _, srv := range vcsPaths {
|
||||
srv.regexp = regexp.MustCompile(srv.re)
|
||||
}
|
||||
for _, srv := range vcsPathsAfterDynamic {
|
||||
srv.regexp = regexp.MustCompile(srv.re)
|
||||
}
|
||||
}
|
||||
|
||||
// noVCSSuffix checks that the repository name does not
|
||||
// end in .foo for any version control system foo.
|
||||
// The usual culprit is ".git".
|
||||
@ -1080,8 +1098,13 @@ func bitbucketVCS(match map[string]string) error {
|
||||
var resp struct {
|
||||
SCM string `json:"scm"`
|
||||
}
|
||||
url := expand(match, "https://api.bitbucket.org/2.0/repositories/{bitname}?fields=scm")
|
||||
data, err := web.Get(url)
|
||||
url := &urlpkg.URL{
|
||||
Scheme: "https",
|
||||
Host: "api.bitbucket.org",
|
||||
Path: expand(match, "/2.0/repositories/{bitname}"),
|
||||
RawQuery: "fields=scm",
|
||||
}
|
||||
data, err := web.GetBytes(url)
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*web.HTTPError); ok && httpErr.StatusCode == 403 {
|
||||
// this may be a private repository. If so, attempt to determine which
|
||||
@ -1123,7 +1146,12 @@ func launchpadVCS(match map[string]string) error {
|
||||
if match["project"] == "" || match["series"] == "" {
|
||||
return nil
|
||||
}
|
||||
_, err := web.Get(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format"))
|
||||
url := &urlpkg.URL{
|
||||
Scheme: "https",
|
||||
Host: "code.launchpad.net",
|
||||
Path: expand(match, "/{project}{series}/.bzr/branch-format"),
|
||||
}
|
||||
_, err := web.GetBytes(url)
|
||||
if err != nil {
|
||||
match["root"] = expand(match, "launchpad.net/{project}")
|
||||
match["repo"] = expand(match, "https://{root}")
|
||||
|
@ -181,7 +181,7 @@ func TestRepoRootForImportPath(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
got, err := RepoRootForImportPath(test.path, IgnoreMod, web.Secure)
|
||||
got, err := RepoRootForImportPath(test.path, IgnoreMod, web.SecureOnly)
|
||||
want := test.want
|
||||
|
||||
if want == nil {
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/modload"
|
||||
)
|
||||
|
||||
// Help implements the 'help' command.
|
||||
@ -35,8 +36,10 @@ func Help(w io.Writer, args []string) {
|
||||
usage := &base.Command{Long: buf.String()}
|
||||
cmds := []*base.Command{usage}
|
||||
for _, cmd := range base.Go.Commands {
|
||||
if cmd.UsageLine == "gopath-get" {
|
||||
// Avoid duplication of the "get" documentation.
|
||||
// Avoid duplication of the "get" documentation.
|
||||
if cmd.UsageLine == "module-get" && modload.Enabled() {
|
||||
continue
|
||||
} else if cmd.UsageLine == "gopath-get" && !modload.Enabled() {
|
||||
continue
|
||||
}
|
||||
cmds = append(cmds, cmd)
|
||||
|
@ -469,10 +469,17 @@ var HelpEnvironment = &base.Command{
|
||||
Short: "environment variables",
|
||||
Long: `
|
||||
|
||||
The go command, and the tools it invokes, examine a few different
|
||||
environment variables. For many of these, you can see the default
|
||||
value of on your system by running 'go env NAME', where NAME is the
|
||||
name of the variable.
|
||||
The go command and the tools it invokes consult environment variables
|
||||
for configuration. If an environment variable is unset, the go command
|
||||
uses a sensible default setting. To see the effective setting of the
|
||||
variable <NAME>, run 'go env <NAME>'. To change the default setting,
|
||||
run 'go env -w <NAME>=<VALUE>'. Defaults changed using 'go env -w'
|
||||
are recorded in a Go environment configuration file stored in the
|
||||
per-user configuration directory, as reported by os.UserConfigDir.
|
||||
The location of the configuration file can be changed by setting
|
||||
the environment variable GOENV, and 'go env GOENV' prints the
|
||||
effective location, but 'go env -w' cannot change the default location.
|
||||
See 'go help env' for details.
|
||||
|
||||
General-purpose environment variables:
|
||||
|
||||
@ -486,10 +493,15 @@ General-purpose environment variables:
|
||||
GOCACHE
|
||||
The directory where the go command will store cached
|
||||
information for reuse in future builds.
|
||||
GOENV
|
||||
The location of the Go environment configuration file.
|
||||
Cannot be set using 'go env -w'.
|
||||
GOFLAGS
|
||||
A space-separated list of -flag=value settings to apply
|
||||
to go commands by default, when the given flag is known by
|
||||
the current command. Flags listed on the command-line
|
||||
the current command. Each entry must be a standalone flag.
|
||||
Because the entries are space-separated, flag values must
|
||||
not contain spaces. Flags listed on the command line
|
||||
are applied after this list and therefore override it.
|
||||
GOOS
|
||||
The operating system for which to compile code.
|
||||
@ -497,22 +509,27 @@ General-purpose environment variables:
|
||||
GOPATH
|
||||
For more details see: 'go help gopath'.
|
||||
GOPROXY
|
||||
URL of Go module proxy. See 'go help goproxy'.
|
||||
GORACE
|
||||
Options for the race detector.
|
||||
See https://golang.org/doc/articles/race_detector.html.
|
||||
URL of Go module proxy. See 'go help modules'.
|
||||
GOPRIVATE, GONOPROXY, GONOSUMDB
|
||||
Comma-separated list of glob patterns (in the syntax of Go's path.Match)
|
||||
of module path prefixes that should always be fetched directly
|
||||
or that should not be compared against the checksum database.
|
||||
See 'go help module-private'.
|
||||
GOROOT
|
||||
The root of the go tree.
|
||||
GOSUMDB
|
||||
The name of checksum database to use and optionally its public key and
|
||||
URL. See 'go help module-auth'.
|
||||
GOTMPDIR
|
||||
The directory where the go command will write
|
||||
temporary source files, packages, and binaries.
|
||||
|
||||
Each entry in the GOFLAGS list must be a standalone flag.
|
||||
Because the entries are space-separated, flag values must
|
||||
not contain spaces.
|
||||
|
||||
Environment variables for use with cgo:
|
||||
|
||||
AR
|
||||
The command to use to manipulate library archives when
|
||||
building with the gccgo compiler.
|
||||
The default is 'ar'.
|
||||
CC
|
||||
The command to use to compile C code.
|
||||
CGO_ENABLED
|
||||
@ -542,12 +559,10 @@ Environment variables for use with cgo:
|
||||
but for the linker.
|
||||
CXX
|
||||
The command to use to compile C++ code.
|
||||
FC
|
||||
The command to use to compile Fortran code.
|
||||
PKG_CONFIG
|
||||
Path to pkg-config tool.
|
||||
AR
|
||||
The command to use to manipulate library archives when
|
||||
building with the gccgo compiler.
|
||||
The default is 'ar'.
|
||||
|
||||
Architecture-specific environment variables:
|
||||
|
||||
@ -563,6 +578,9 @@ Architecture-specific environment variables:
|
||||
GOMIPS64
|
||||
For GOARCH=mips64{,le}, whether to use floating point instructions.
|
||||
Valid values are hardfloat (default), softfloat.
|
||||
GOWASM
|
||||
For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
|
||||
Valid values are satconv, signext.
|
||||
|
||||
Special-purpose environment variables:
|
||||
|
||||
@ -579,14 +597,18 @@ Special-purpose environment variables:
|
||||
when using -linkmode=auto with code that uses cgo.
|
||||
Set to 0 to disable external linking mode, 1 to enable it.
|
||||
GIT_ALLOW_PROTOCOL
|
||||
Defined by Git. A colon-separated list of schemes that are allowed to be used
|
||||
with git fetch/clone. If set, any scheme not explicitly mentioned will be
|
||||
considered insecure by 'go get'.
|
||||
Defined by Git. A colon-separated list of schemes that are allowed
|
||||
to be used with git fetch/clone. If set, any scheme not explicitly
|
||||
mentioned will be considered insecure by 'go get'.
|
||||
Because the variable is defined by Git, the default value cannot
|
||||
be set using 'go env -w'.
|
||||
|
||||
Additional information available from 'go env' but not read from the environment:
|
||||
|
||||
GOEXE
|
||||
The executable file name suffix (".exe" on Windows, "" on other systems).
|
||||
GOGCCFLAGS
|
||||
A space-separated list of arguments supplied to the CC command.
|
||||
GOHOSTARCH
|
||||
The architecture (GOARCH) of the Go toolchain binaries.
|
||||
GOHOSTOS
|
||||
@ -635,15 +657,6 @@ constraints, but the go command stops scanning for build constraints
|
||||
at the first item in the file that is not a blank line or //-style
|
||||
line comment. See the go/build package documentation for
|
||||
more details.
|
||||
|
||||
Through the Go 1.12 release, non-test Go source files can also include
|
||||
a //go:binary-only-package comment, indicating that the package
|
||||
sources are included for documentation only and must not be used to
|
||||
build the package binary. This enables distribution of Go packages in
|
||||
their compiled form alone. Even binary-only packages require accurate
|
||||
import blocks listing required dependencies, so that those
|
||||
dependencies can be supplied when linking the resulting command.
|
||||
Note that this feature is scheduled to be removed after the Go 1.12 release.
|
||||
`,
|
||||
}
|
||||
|
||||
@ -693,6 +706,9 @@ are:
|
||||
-buildmode=plugin
|
||||
Build the listed main packages, plus all packages that they
|
||||
import, into a Go plugin. Packages not named main are ignored.
|
||||
|
||||
On AIX, when linking a C program that uses a Go archive built with
|
||||
-buildmode=c-archive, you must pass -Wl,-bnoobjreorder to the C compiler.
|
||||
`,
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,9 @@ func matchTag(name string, tags map[string]bool, want bool) bool {
|
||||
if name == "linux" {
|
||||
have = have || tags["android"]
|
||||
}
|
||||
if name == "solaris" {
|
||||
have = have || tags["illumos"]
|
||||
}
|
||||
return have == want
|
||||
}
|
||||
|
||||
@ -152,7 +155,9 @@ func matchTag(name string, tags map[string]bool, want bool) bool {
|
||||
// name_$(GOARCH)_test.*
|
||||
// name_$(GOOS)_$(GOARCH)_test.*
|
||||
//
|
||||
// An exception: if GOOS=android, then files with GOOS=linux are also matched.
|
||||
// Exceptions:
|
||||
// if GOOS=android, then files with GOOS=linux are also matched.
|
||||
// if GOOS=illumos, then files with GOOS=solaris are also matched.
|
||||
//
|
||||
// If tags["*"] is true, then MatchFile will consider all possible
|
||||
// GOOS and GOARCH to be available and will consequently
|
||||
@ -184,28 +189,58 @@ func MatchFile(name string, tags map[string]bool) bool {
|
||||
}
|
||||
n := len(l)
|
||||
if n >= 2 && KnownOS[l[n-2]] && KnownArch[l[n-1]] {
|
||||
return tags[l[n-2]] && tags[l[n-1]]
|
||||
return matchTag(l[n-2], tags, true) && matchTag(l[n-1], tags, true)
|
||||
}
|
||||
if n >= 1 && KnownOS[l[n-1]] {
|
||||
return tags[l[n-1]]
|
||||
return matchTag(l[n-1], tags, true)
|
||||
}
|
||||
if n >= 1 && KnownArch[l[n-1]] {
|
||||
return tags[l[n-1]]
|
||||
return matchTag(l[n-1], tags, true)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var KnownOS = make(map[string]bool)
|
||||
var KnownArch = make(map[string]bool)
|
||||
|
||||
func init() {
|
||||
for _, v := range strings.Fields(goosList) {
|
||||
KnownOS[v] = true
|
||||
}
|
||||
for _, v := range strings.Fields(goarchList) {
|
||||
KnownArch[v] = true
|
||||
}
|
||||
var KnownOS = map[string]bool{
|
||||
"aix": true,
|
||||
"android": true,
|
||||
"darwin": true,
|
||||
"dragonfly": true,
|
||||
"freebsd": true,
|
||||
"hurd": true,
|
||||
"illumos": true,
|
||||
"js": true,
|
||||
"linux": true,
|
||||
"nacl": true,
|
||||
"netbsd": true,
|
||||
"openbsd": true,
|
||||
"plan9": true,
|
||||
"solaris": true,
|
||||
"windows": true,
|
||||
"zos": true,
|
||||
}
|
||||
|
||||
const goosList = "aix android darwin dragonfly freebsd hurd js linux nacl netbsd openbsd plan9 solaris windows zos "
|
||||
const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm "
|
||||
var KnownArch = map[string]bool{
|
||||
"386": true,
|
||||
"amd64": true,
|
||||
"amd64p32": true,
|
||||
"arm": true,
|
||||
"armbe": true,
|
||||
"arm64": true,
|
||||
"arm64be": true,
|
||||
"ppc64": true,
|
||||
"ppc64le": true,
|
||||
"mips": true,
|
||||
"mipsle": true,
|
||||
"mips64": true,
|
||||
"mips64le": true,
|
||||
"mips64p32": true,
|
||||
"mips64p32le": true,
|
||||
"ppc": true,
|
||||
"riscv": true,
|
||||
"riscv64": true,
|
||||
"s390": true,
|
||||
"s390x": true,
|
||||
"sparc": true,
|
||||
"sparc64": true,
|
||||
"wasm": true,
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ func ScanDir(dir string, tags map[string]bool) ([]string, []string, error) {
|
||||
// If the directory entry is a symlink, stat it to obtain the info for the
|
||||
// link target instead of the link itself.
|
||||
if info.Mode()&os.ModeSymlink != 0 {
|
||||
info, err = os.Stat(name)
|
||||
info, err = os.Stat(filepath.Join(dir, name))
|
||||
if err != nil {
|
||||
continue // Ignore broken symlinks.
|
||||
}
|
||||
|
@ -5,10 +5,13 @@
|
||||
package imports
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -51,17 +54,41 @@ func TestScan(t *testing.T) {
|
||||
t.Errorf("json missing test import net/http (%q)", testImports)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanStar(t *testing.T) {
|
||||
func TestScanDir(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
imports, _, err := ScanDir("testdata/import1", map[string]bool{"*": true})
|
||||
dirs, err := ioutil.ReadDir("testdata")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, dir := range dirs {
|
||||
if !dir.IsDir() || strings.HasPrefix(dir.Name(), ".") {
|
||||
continue
|
||||
}
|
||||
t.Run(dir.Name(), func(t *testing.T) {
|
||||
tagsData, err := ioutil.ReadFile(filepath.Join("testdata", dir.Name(), "tags.txt"))
|
||||
if err != nil {
|
||||
t.Fatalf("error reading tags: %v", err)
|
||||
}
|
||||
tags := make(map[string]bool)
|
||||
for _, t := range strings.Fields(string(tagsData)) {
|
||||
tags[t] = true
|
||||
}
|
||||
|
||||
want := []string{"import1", "import2", "import3", "import4"}
|
||||
if !reflect.DeepEqual(imports, want) {
|
||||
t.Errorf("ScanDir testdata/import1:\nhave %v\nwant %v", imports, want)
|
||||
wantData, err := ioutil.ReadFile(filepath.Join("testdata", dir.Name(), "want.txt"))
|
||||
if err != nil {
|
||||
t.Fatalf("error reading want: %v", err)
|
||||
}
|
||||
want := string(bytes.TrimSpace(wantData))
|
||||
|
||||
imports, _, err := ScanDir(path.Join("testdata", dir.Name()), tags)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := strings.Join(imports, "\n")
|
||||
if got != want {
|
||||
t.Errorf("ScanDir: got imports:\n%s\n\nwant:\n%s", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import "cmd/go/internal/cfg"
|
||||
|
||||
var tags map[string]bool
|
||||
|
||||
// Tags returns a set of build tags that are true for the target platform.
|
||||
// It includes GOOS, GOARCH, the compiler, possibly "cgo",
|
||||
// release tags like "go1.13", and user-specified build tags.
|
||||
func Tags() map[string]bool {
|
||||
if tags == nil {
|
||||
tags = loadTags()
|
||||
@ -32,3 +35,15 @@ func loadTags() map[string]bool {
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
var anyTags map[string]bool
|
||||
|
||||
// AnyTags returns a special set of build tags that satisfy nearly all
|
||||
// build tag expressions. Only "ignore" and malformed build tag requirements
|
||||
// are considered false.
|
||||
func AnyTags() map[string]bool {
|
||||
if anyTags == nil {
|
||||
anyTags = map[string]bool{"*": true}
|
||||
}
|
||||
return anyTags
|
||||
}
|
||||
|
3
libgo/go/cmd/go/internal/imports/testdata/android/a_android.go
vendored
Normal file
3
libgo/go/cmd/go/internal/imports/testdata/android/a_android.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package android
|
||||
|
||||
import _ "a"
|
3
libgo/go/cmd/go/internal/imports/testdata/android/b_android_arm64.go
vendored
Normal file
3
libgo/go/cmd/go/internal/imports/testdata/android/b_android_arm64.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package android
|
||||
|
||||
import _ "b"
|
3
libgo/go/cmd/go/internal/imports/testdata/android/c_linux.go
vendored
Normal file
3
libgo/go/cmd/go/internal/imports/testdata/android/c_linux.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package android
|
||||
|
||||
import _ "c"
|
3
libgo/go/cmd/go/internal/imports/testdata/android/d_linux_arm64.go
vendored
Normal file
3
libgo/go/cmd/go/internal/imports/testdata/android/d_linux_arm64.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package android
|
||||
|
||||
import _ "d"
|
5
libgo/go/cmd/go/internal/imports/testdata/android/e.go
vendored
Normal file
5
libgo/go/cmd/go/internal/imports/testdata/android/e.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// +build android
|
||||
|
||||
package android
|
||||
|
||||
import _ "e"
|
5
libgo/go/cmd/go/internal/imports/testdata/android/f.go
vendored
Normal file
5
libgo/go/cmd/go/internal/imports/testdata/android/f.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// +build linux
|
||||
|
||||
package android
|
||||
|
||||
import _ "f"
|
5
libgo/go/cmd/go/internal/imports/testdata/android/g.go
vendored
Normal file
5
libgo/go/cmd/go/internal/imports/testdata/android/g.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// +build !android
|
||||
|
||||
package android
|
||||
|
||||
import _ "g"
|
3
libgo/go/cmd/go/internal/imports/testdata/illumos/a_illumos.go
vendored
Normal file
3
libgo/go/cmd/go/internal/imports/testdata/illumos/a_illumos.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package illumos
|
||||
|
||||
import _ "a"
|
3
libgo/go/cmd/go/internal/imports/testdata/illumos/b_illumos_amd64.go
vendored
Normal file
3
libgo/go/cmd/go/internal/imports/testdata/illumos/b_illumos_amd64.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package illumos
|
||||
|
||||
import _ "b"
|
3
libgo/go/cmd/go/internal/imports/testdata/illumos/c_solaris.go
vendored
Normal file
3
libgo/go/cmd/go/internal/imports/testdata/illumos/c_solaris.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package illumos
|
||||
|
||||
import _ "c"
|
3
libgo/go/cmd/go/internal/imports/testdata/illumos/d_solaris_amd64.go
vendored
Normal file
3
libgo/go/cmd/go/internal/imports/testdata/illumos/d_solaris_amd64.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package illumos
|
||||
|
||||
import _ "d"
|
5
libgo/go/cmd/go/internal/imports/testdata/illumos/e.go
vendored
Normal file
5
libgo/go/cmd/go/internal/imports/testdata/illumos/e.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// +build illumos
|
||||
|
||||
package illumos
|
||||
|
||||
import _ "e"
|
5
libgo/go/cmd/go/internal/imports/testdata/illumos/f.go
vendored
Normal file
5
libgo/go/cmd/go/internal/imports/testdata/illumos/f.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// +build solaris
|
||||
|
||||
package illumos
|
||||
|
||||
import _ "f"
|
5
libgo/go/cmd/go/internal/imports/testdata/illumos/g.go
vendored
Normal file
5
libgo/go/cmd/go/internal/imports/testdata/illumos/g.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// +build !illumos
|
||||
|
||||
package illumos
|
||||
|
||||
import _ "g"
|
@ -60,7 +60,7 @@ to -f '{{.ImportPath}}'. The struct being passed to the template is:
|
||||
StaleReason string // explanation for Stale==true
|
||||
Root string // Go root or Go path dir containing this package
|
||||
ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
BinaryOnly bool // binary-only package (no longer supported)
|
||||
ForTest string // package is only for use in named test
|
||||
Export string // file containing export data (when using -export)
|
||||
Module *Module // info about package's containing module, if any (can be nil)
|
||||
@ -202,17 +202,18 @@ When listing modules, the -f flag still specifies a format template
|
||||
applied to a Go struct, but now a Module struct:
|
||||
|
||||
type Module struct {
|
||||
Path string // module path
|
||||
Version string // module version
|
||||
Versions []string // available module versions (with -versions)
|
||||
Replace *Module // replaced by this module
|
||||
Time *time.Time // time version was created
|
||||
Update *Module // available update, if any (with -u)
|
||||
Main bool // is this the main module?
|
||||
Indirect bool // is this module only an indirect dependency of main module?
|
||||
Dir string // directory holding files for this module, if any
|
||||
GoMod string // path to go.mod file for this module, if any
|
||||
Error *ModuleError // error loading module
|
||||
Path string // module path
|
||||
Version string // module version
|
||||
Versions []string // available module versions (with -versions)
|
||||
Replace *Module // replaced by this module
|
||||
Time *time.Time // time version was created
|
||||
Update *Module // available update, if any (with -u)
|
||||
Main bool // is this the main module?
|
||||
Indirect bool // is this module only an indirect dependency of main module?
|
||||
Dir string // directory holding files for this module, if any
|
||||
GoMod string // path to go.mod file for this module, if any
|
||||
GoVersion string // go version used in module
|
||||
Error *ModuleError // error loading module
|
||||
}
|
||||
|
||||
type ModuleError struct {
|
||||
@ -446,37 +447,34 @@ func runList(cmd *base.Command, args []string) {
|
||||
continue
|
||||
}
|
||||
if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 {
|
||||
pmain, ptest, pxtest, err := load.GetTestPackagesFor(p, nil)
|
||||
if err != nil {
|
||||
if *listE {
|
||||
pkgs = append(pkgs, &load.Package{
|
||||
PackagePublic: load.PackagePublic{
|
||||
ImportPath: p.ImportPath + ".test",
|
||||
Error: &load.PackageError{Err: err.Error()},
|
||||
},
|
||||
})
|
||||
continue
|
||||
var pmain, ptest, pxtest *load.Package
|
||||
var err error
|
||||
if *listE {
|
||||
pmain, ptest, pxtest = load.TestPackagesAndErrors(p, nil)
|
||||
} else {
|
||||
pmain, ptest, pxtest, err = load.TestPackagesFor(p, nil)
|
||||
if err != nil {
|
||||
base.Errorf("can't load test package: %s", err)
|
||||
}
|
||||
base.Errorf("can't load test package: %s", err)
|
||||
continue
|
||||
}
|
||||
pkgs = append(pkgs, pmain)
|
||||
if ptest != nil {
|
||||
if pmain != nil {
|
||||
pkgs = append(pkgs, pmain)
|
||||
data := pmain.Internal.TestmainGo
|
||||
h := cache.NewHash("testmain")
|
||||
h.Write([]byte("testmain\n"))
|
||||
h.Write(data)
|
||||
out, _, err := c.Put(h.Sum(), bytes.NewReader(data))
|
||||
if err != nil {
|
||||
base.Fatalf("%s", err)
|
||||
}
|
||||
pmain.GoFiles[0] = c.OutputFile(out)
|
||||
}
|
||||
if ptest != nil && ptest != p {
|
||||
pkgs = append(pkgs, ptest)
|
||||
}
|
||||
if pxtest != nil {
|
||||
pkgs = append(pkgs, pxtest)
|
||||
}
|
||||
|
||||
data := *pmain.Internal.TestmainGo
|
||||
h := cache.NewHash("testmain")
|
||||
h.Write([]byte("testmain\n"))
|
||||
h.Write(data)
|
||||
out, _, err := c.Put(h.Sum(), bytes.NewReader(data))
|
||||
if err != nil {
|
||||
base.Fatalf("%s", err)
|
||||
}
|
||||
pmain.GoFiles[0] = c.OutputFile(out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,32 +6,8 @@ package load
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// hasSubdir reports whether dir is a subdirectory of
|
||||
// (possibly multiple levels below) root.
|
||||
// If so, it sets rel to the path fragment that must be
|
||||
// appended to root to reach dir.
|
||||
func hasSubdir(root, dir string) (rel string, ok bool) {
|
||||
if p, err := filepath.EvalSymlinks(root); err == nil {
|
||||
root = p
|
||||
}
|
||||
if p, err := filepath.EvalSymlinks(dir); err == nil {
|
||||
dir = p
|
||||
}
|
||||
const sep = string(filepath.Separator)
|
||||
root = filepath.Clean(root)
|
||||
if !strings.HasSuffix(root, sep) {
|
||||
root += sep
|
||||
}
|
||||
dir = filepath.Clean(dir)
|
||||
if !strings.HasPrefix(dir, root) {
|
||||
return "", false
|
||||
}
|
||||
return filepath.ToSlash(dir[len(root):]), true
|
||||
}
|
||||
|
||||
// expandPath returns the symlink-expanded form of path.
|
||||
func expandPath(p string) string {
|
||||
x, err := filepath.EvalSymlinks(p)
|
||||
|
File diff suppressed because it is too large
Load Diff
68
libgo/go/cmd/go/internal/load/pkg_test.go
Normal file
68
libgo/go/cmd/go/internal/load/pkg_test.go
Normal file
@ -0,0 +1,68 @@
|
||||
package load
|
||||
|
||||
import (
|
||||
"cmd/go/internal/cfg"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDefaultExecName(t *testing.T) {
|
||||
oldModulesEnabled := cfg.ModulesEnabled
|
||||
defer func() { cfg.ModulesEnabled = oldModulesEnabled }()
|
||||
for _, tt := range []struct {
|
||||
in string
|
||||
wantMod string
|
||||
wantGopath string
|
||||
}{
|
||||
{"example.com/mycmd", "mycmd", "mycmd"},
|
||||
{"example.com/mycmd/v0", "v0", "v0"},
|
||||
{"example.com/mycmd/v1", "v1", "v1"},
|
||||
{"example.com/mycmd/v2", "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
|
||||
{"example.com/mycmd/v3", "mycmd", "v3"}, // Semantic import versioning, use second last element in module mode.
|
||||
{"mycmd", "mycmd", "mycmd"},
|
||||
{"mycmd/v0", "v0", "v0"},
|
||||
{"mycmd/v1", "v1", "v1"},
|
||||
{"mycmd/v2", "mycmd", "v2"}, // Semantic import versioning, use second last element in module mode.
|
||||
{"v0", "v0", "v0"},
|
||||
{"v1", "v1", "v1"},
|
||||
{"v2", "v2", "v2"},
|
||||
} {
|
||||
{
|
||||
cfg.ModulesEnabled = true
|
||||
gotMod := DefaultExecName(tt.in)
|
||||
if gotMod != tt.wantMod {
|
||||
t.Errorf("DefaultExecName(%q) in module mode = %v; want %v", tt.in, gotMod, tt.wantMod)
|
||||
}
|
||||
}
|
||||
{
|
||||
cfg.ModulesEnabled = false
|
||||
gotGopath := DefaultExecName(tt.in)
|
||||
if gotGopath != tt.wantGopath {
|
||||
t.Errorf("DefaultExecName(%q) in gopath mode = %v; want %v", tt.in, gotGopath, tt.wantGopath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsVersionElement(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, tt := range []struct {
|
||||
in string
|
||||
want bool
|
||||
}{
|
||||
{"v0", false},
|
||||
{"v05", false},
|
||||
{"v1", false},
|
||||
{"v2", true},
|
||||
{"v3", true},
|
||||
{"v9", true},
|
||||
{"v10", true},
|
||||
{"v11", true},
|
||||
{"v", false},
|
||||
{"vx", false},
|
||||
} {
|
||||
got := isVersionElement(tt.in)
|
||||
if got != tt.want {
|
||||
t.Errorf("isVersionElement(%q) = %v; want %v", tt.in, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
@ -15,10 +15,10 @@ import (
|
||||
"go/doc"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"internal/lazytemplate"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
@ -39,10 +39,43 @@ type TestCover struct {
|
||||
DeclVars func(*Package, ...string) map[string]*CoverVar
|
||||
}
|
||||
|
||||
// TestPackagesFor returns three packages:
|
||||
// TestPackagesFor is like TestPackagesAndErrors but it returns
|
||||
// an error if the test packages or their dependencies have errors.
|
||||
// Only test packages without errors are returned.
|
||||
func TestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
|
||||
pmain, ptest, pxtest = TestPackagesAndErrors(p, cover)
|
||||
for _, p1 := range []*Package{ptest, pxtest, pmain} {
|
||||
if p1 == nil {
|
||||
// pxtest may be nil
|
||||
continue
|
||||
}
|
||||
if p1.Error != nil {
|
||||
err = p1.Error
|
||||
break
|
||||
}
|
||||
if len(p1.DepsErrors) > 0 {
|
||||
perr := p1.DepsErrors[0]
|
||||
perr.Pos = "" // show full import stack
|
||||
err = perr
|
||||
break
|
||||
}
|
||||
}
|
||||
if pmain.Error != nil || len(pmain.DepsErrors) > 0 {
|
||||
pmain = nil
|
||||
}
|
||||
if ptest.Error != nil || len(ptest.DepsErrors) > 0 {
|
||||
ptest = nil
|
||||
}
|
||||
if pxtest != nil && (pxtest.Error != nil || len(pxtest.DepsErrors) > 0) {
|
||||
pxtest = nil
|
||||
}
|
||||
return pmain, ptest, pxtest, err
|
||||
}
|
||||
|
||||
// TestPackagesAndErrors returns three packages:
|
||||
// - pmain, the package main corresponding to the test binary (running tests in ptest and pxtest).
|
||||
// - ptest, the package p compiled with added "package p" test files.
|
||||
// - pxtest, the result of compiling any "package p_test" (external) test files.
|
||||
// - pmain, the package main corresponding to the test binary (running tests in ptest and pxtest).
|
||||
//
|
||||
// If the package has no "package p_test" test files, pxtest will be nil.
|
||||
// If the non-test compilation of package p can be reused
|
||||
@ -50,57 +83,59 @@ type TestCover struct {
|
||||
// package p need not be instrumented for coverage or any other reason),
|
||||
// then the returned ptest == p.
|
||||
//
|
||||
// An error is returned if the testmain source cannot be completely generated
|
||||
// (for example, due to a syntax error in a test file). No error will be
|
||||
// returned for errors loading packages, but the Error or DepsError fields
|
||||
// of the returned packages may be set.
|
||||
//
|
||||
// The caller is expected to have checked that len(p.TestGoFiles)+len(p.XTestGoFiles) > 0,
|
||||
// or else there's no point in any of this.
|
||||
func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) {
|
||||
func TestPackagesAndErrors(p *Package, cover *TestCover) (pmain, ptest, pxtest *Package) {
|
||||
pre := newPreload()
|
||||
defer pre.flush()
|
||||
allImports := append([]string{}, p.TestImports...)
|
||||
allImports = append(allImports, p.XTestImports...)
|
||||
pre.preloadImports(allImports, p.Internal.Build)
|
||||
|
||||
var ptestErr, pxtestErr *PackageError
|
||||
var imports, ximports []*Package
|
||||
var stk ImportStack
|
||||
stk.Push(p.ImportPath + " (test)")
|
||||
rawTestImports := str.StringList(p.TestImports)
|
||||
var ptestImportsTesting, pxtestImportsTesting bool
|
||||
for i, path := range p.TestImports {
|
||||
p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
|
||||
if p1.Error != nil {
|
||||
return nil, nil, nil, p1.Error
|
||||
}
|
||||
if len(p1.DepsErrors) > 0 {
|
||||
err := p1.DepsErrors[0]
|
||||
err.Pos = "" // show full import stack
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
p1 := loadImport(pre, path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport)
|
||||
if str.Contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
|
||||
// Same error that loadPackage returns (via reusePackage) in pkg.go.
|
||||
// Can't change that code, because that code is only for loading the
|
||||
// non-test copy of a package.
|
||||
err := &PackageError{
|
||||
ptestErr = &PackageError{
|
||||
ImportStack: testImportStack(stk[0], p1, p.ImportPath),
|
||||
Err: "import cycle not allowed in test",
|
||||
IsImportCycle: true,
|
||||
}
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
p.TestImports[i] = p1.ImportPath
|
||||
imports = append(imports, p1)
|
||||
if path == "testing" {
|
||||
ptestImportsTesting = true
|
||||
}
|
||||
}
|
||||
stk.Pop()
|
||||
stk.Push(p.ImportPath + "_test")
|
||||
pxtestNeedsPtest := false
|
||||
rawXTestImports := str.StringList(p.XTestImports)
|
||||
for i, path := range p.XTestImports {
|
||||
p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
|
||||
if p1.Error != nil {
|
||||
return nil, nil, nil, p1.Error
|
||||
}
|
||||
if len(p1.DepsErrors) > 0 {
|
||||
err := p1.DepsErrors[0]
|
||||
err.Pos = "" // show full import stack
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
p1 := loadImport(pre, path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport)
|
||||
if p1.ImportPath == p.ImportPath {
|
||||
pxtestNeedsPtest = true
|
||||
} else {
|
||||
ximports = append(ximports, p1)
|
||||
}
|
||||
p.XTestImports[i] = p1.ImportPath
|
||||
if path == "testing" {
|
||||
pxtestImportsTesting = true
|
||||
}
|
||||
}
|
||||
stk.Pop()
|
||||
|
||||
@ -108,7 +143,11 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
|
||||
if len(p.TestGoFiles) > 0 || p.Name == "main" || cover != nil && cover.Local {
|
||||
ptest = new(Package)
|
||||
*ptest = *p
|
||||
ptest.Error = ptestErr
|
||||
ptest.ForTest = p.ImportPath
|
||||
if ptestImportsTesting {
|
||||
ptest.Internal.TestinginitGo = formatTestinginit(p)
|
||||
}
|
||||
ptest.GoFiles = nil
|
||||
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
|
||||
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
|
||||
@ -140,6 +179,7 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
|
||||
m[k] = append(m[k], v...)
|
||||
}
|
||||
ptest.Internal.Build.ImportPos = m
|
||||
ptest.collectDeps()
|
||||
} else {
|
||||
ptest = p
|
||||
}
|
||||
@ -152,9 +192,11 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
|
||||
ImportPath: p.ImportPath + "_test",
|
||||
Root: p.Root,
|
||||
Dir: p.Dir,
|
||||
Goroot: p.Goroot,
|
||||
GoFiles: p.XTestGoFiles,
|
||||
Imports: p.XTestImports,
|
||||
ForTest: p.ImportPath,
|
||||
Error: pxtestErr,
|
||||
},
|
||||
Internal: PackageInternal{
|
||||
LocalPrefix: p.Internal.LocalPrefix,
|
||||
@ -170,9 +212,13 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
|
||||
Gccgoflags: p.Internal.Gccgoflags,
|
||||
},
|
||||
}
|
||||
if pxtestImportsTesting {
|
||||
pxtest.Internal.TestinginitGo = formatTestinginit(pxtest)
|
||||
}
|
||||
if pxtestNeedsPtest {
|
||||
pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
|
||||
}
|
||||
pxtest.collectDeps()
|
||||
}
|
||||
|
||||
// Build main package.
|
||||
@ -206,10 +252,7 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
|
||||
if dep == ptest.ImportPath {
|
||||
pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
|
||||
} else {
|
||||
p1 := LoadImport(dep, "", nil, &stk, nil, 0)
|
||||
if p1.Error != nil {
|
||||
return nil, nil, nil, p1.Error
|
||||
}
|
||||
p1 := loadImport(pre, dep, "", nil, &stk, nil, 0)
|
||||
pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
|
||||
}
|
||||
}
|
||||
@ -240,8 +283,8 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
|
||||
// The list of imports is used by recompileForTest and by the loop
|
||||
// afterward that gathers t.Cover information.
|
||||
t, err := loadTestFuncs(ptest)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
if err != nil && pmain.Error == nil {
|
||||
pmain.Error = &PackageError{Err: err.Error()}
|
||||
}
|
||||
t.Cover = cover
|
||||
if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
|
||||
@ -254,6 +297,7 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
|
||||
pmain.Imports = append(pmain.Imports, pxtest.ImportPath)
|
||||
t.ImportXtest = true
|
||||
}
|
||||
pmain.collectDeps()
|
||||
|
||||
// Sort and dedup pmain.Imports.
|
||||
// Only matters for go list -test output.
|
||||
@ -290,12 +334,12 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
|
||||
}
|
||||
|
||||
data, err := formatTestmain(t)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
if err != nil && pmain.Error == nil {
|
||||
pmain.Error = &PackageError{Err: err.Error()}
|
||||
}
|
||||
pmain.Internal.TestmainGo = &data
|
||||
pmain.Internal.TestmainGo = data
|
||||
|
||||
return pmain, ptest, pxtest, nil
|
||||
return pmain, ptest, pxtest
|
||||
}
|
||||
|
||||
func testImportStack(top string, p *Package, target string) []string {
|
||||
@ -321,9 +365,10 @@ Search:
|
||||
// preal, packages that import the package under test should get ptest instead
|
||||
// of preal. This is particularly important if pxtest depends on functionality
|
||||
// exposed in test sources in ptest. Second, if there is a main package
|
||||
// (other than pmain) anywhere, we need to clear p.Internal.BuildInfo in
|
||||
// the test copy to prevent link conflicts. This may happen if both -coverpkg
|
||||
// and the command line patterns include multiple main packages.
|
||||
// (other than pmain) anywhere, we need to set p.Internal.ForceLibrary and
|
||||
// clear p.Internal.BuildInfo in the test copy to prevent link conflicts.
|
||||
// This may happen if both -coverpkg and the command line patterns include
|
||||
// multiple main packages.
|
||||
func recompileForTest(pmain, preal, ptest, pxtest *Package) {
|
||||
// The "test copy" of preal is ptest.
|
||||
// For each package that depends on preal, make a "test copy"
|
||||
@ -354,6 +399,7 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) {
|
||||
p = p1
|
||||
p.Target = ""
|
||||
p.Internal.BuildInfo = ""
|
||||
p.Internal.ForceLibrary = true
|
||||
}
|
||||
|
||||
// Update p.Internal.Imports to use test copies.
|
||||
@ -419,21 +465,33 @@ type coverInfo struct {
|
||||
}
|
||||
|
||||
// loadTestFuncs returns the testFuncs describing the tests that will be run.
|
||||
// The returned testFuncs is always non-nil, even if an error occurred while
|
||||
// processing test files.
|
||||
func loadTestFuncs(ptest *Package) (*testFuncs, error) {
|
||||
t := &testFuncs{
|
||||
Package: ptest,
|
||||
}
|
||||
var err error
|
||||
for _, file := range ptest.TestGoFiles {
|
||||
if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil {
|
||||
return nil, err
|
||||
if lerr := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); lerr != nil && err == nil {
|
||||
err = lerr
|
||||
}
|
||||
}
|
||||
for _, file := range ptest.XTestGoFiles {
|
||||
if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil {
|
||||
return nil, err
|
||||
if lerr := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); lerr != nil && err == nil {
|
||||
err = lerr
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
return t, err
|
||||
}
|
||||
|
||||
// formatTestinginit returns the content of the _testinginit.go file for p.
|
||||
func formatTestinginit(p *Package) []byte {
|
||||
var buf bytes.Buffer
|
||||
if err := testinginitTmpl.Execute(&buf, p); err != nil {
|
||||
panic("testinginit template execution failed") // shouldn't be possible
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// formatTestmain returns the content of the _testmain.go file for t.
|
||||
@ -565,7 +623,26 @@ func checkTestFunc(fn *ast.FuncDecl, arg string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var testmainTmpl = template.Must(template.New("main").Parse(`
|
||||
var testinginitTmpl = lazytemplate.New("init", `
|
||||
package {{.Name}}
|
||||
|
||||
import _go_testing "testing"
|
||||
|
||||
{{/*
|
||||
Call testing.Init before any other user initialization code runs.
|
||||
(This file is passed to the compiler first.)
|
||||
This provides the illusion of the old behavior where testing flags
|
||||
were registered as part of the testing package's initialization.
|
||||
*/}}
|
||||
var _ = func() bool {
|
||||
_go_testing.Init()
|
||||
return true
|
||||
}()
|
||||
`)
|
||||
|
||||
var testmainTmpl = lazytemplate.New("main", `
|
||||
// Code generated by 'go test'. DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -666,4 +743,4 @@ func main() {
|
||||
{{end}}
|
||||
}
|
||||
|
||||
`))
|
||||
`)
|
||||
|
@ -159,7 +159,9 @@ func TestRLockExcludesOnlyLock(t *testing.T) {
|
||||
f2 := mustOpen(t, f.Name())
|
||||
defer f2.Close()
|
||||
|
||||
if runtime.GOOS == "solaris" || runtime.GOOS == "aix" {
|
||||
doUnlockTF := false
|
||||
switch runtime.GOOS {
|
||||
case "aix", "illumos", "solaris":
|
||||
// When using POSIX locks (as on Solaris), we can't safely read-lock the
|
||||
// same inode through two different descriptors at the same time: when the
|
||||
// first descriptor is closed, the second descriptor would still be open but
|
||||
@ -167,8 +169,9 @@ func TestRLockExcludesOnlyLock(t *testing.T) {
|
||||
lockF2 := mustBlock(t, "RLock", f2)
|
||||
unlock(t, f)
|
||||
lockF2(t)
|
||||
} else {
|
||||
default:
|
||||
rLock(t, f2)
|
||||
doUnlockTF = true
|
||||
}
|
||||
|
||||
other := mustOpen(t, f.Name())
|
||||
@ -176,7 +179,7 @@ func TestRLockExcludesOnlyLock(t *testing.T) {
|
||||
lockOther := mustBlock(t, "Lock", other)
|
||||
|
||||
unlock(t, f2)
|
||||
if runtime.GOOS != "solaris" && runtime.GOOS != "aix" {
|
||||
if doUnlockTF {
|
||||
unlock(t, f)
|
||||
}
|
||||
lockOther(t)
|
||||
|
@ -7,6 +7,7 @@ package lockedfile
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A Mutex provides mutual exclusion within and across processes by locking a
|
||||
@ -21,7 +22,8 @@ import (
|
||||
// must not be copied after first use. The Path field must be set before first
|
||||
// use and must not be change thereafter.
|
||||
type Mutex struct {
|
||||
Path string // The path to the well-known lock file. Must be non-empty.
|
||||
Path string // The path to the well-known lock file. Must be non-empty.
|
||||
mu sync.Mutex // A redundant mutex. The race detector doesn't know about file locking, so in tests we may need to lock something that it understands.
|
||||
}
|
||||
|
||||
// MutexAt returns a new Mutex with Path set to the given non-empty path.
|
||||
@ -56,5 +58,10 @@ func (mu *Mutex) Lock() (unlock func(), err error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return func() { f.Close() }, nil
|
||||
mu.mu.Lock()
|
||||
|
||||
return func() {
|
||||
mu.mu.Unlock()
|
||||
f.Close()
|
||||
}, nil
|
||||
}
|
||||
|
@ -5,13 +5,15 @@
|
||||
package modcmd
|
||||
|
||||
import (
|
||||
"cmd/go/internal/cfg"
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/modfetch"
|
||||
"cmd/go/internal/modload"
|
||||
"cmd/go/internal/module"
|
||||
"cmd/go/internal/par"
|
||||
"encoding/json"
|
||||
"os"
|
||||
)
|
||||
|
||||
var cmdDownload = &base.Command{
|
||||
@ -66,6 +68,13 @@ type moduleJSON struct {
|
||||
}
|
||||
|
||||
func runDownload(cmd *base.Command, args []string) {
|
||||
// Check whether modules are enabled and whether we're in a module.
|
||||
if cfg.Getenv("GO111MODULE") == "off" {
|
||||
base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
|
||||
}
|
||||
if !modload.HasModRoot() && len(args) == 0 {
|
||||
base.Fatalf("go mod download: no modules specified (see 'go help mod download')")
|
||||
}
|
||||
if len(args) == 0 {
|
||||
args = []string{"all"}
|
||||
}
|
||||
|
@ -385,7 +385,9 @@ type replaceJSON struct {
|
||||
// editPrintJSON prints the -json output.
|
||||
func editPrintJSON(modFile *modfile.File) {
|
||||
var f fileJSON
|
||||
f.Module = modFile.Module.Mod
|
||||
if modFile.Module != nil {
|
||||
f.Module = modFile.Module.Mod
|
||||
}
|
||||
if modFile.Go != nil {
|
||||
f.Go = modFile.Go.Version
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ package modcmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"cmd/go/internal/cfg"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
@ -33,6 +34,14 @@ func runGraph(cmd *base.Command, args []string) {
|
||||
if len(args) > 0 {
|
||||
base.Fatalf("go mod graph: graph takes no arguments")
|
||||
}
|
||||
// Checks go mod expected behavior
|
||||
if !modload.Enabled() {
|
||||
if cfg.Getenv("GO111MODULE") == "off" {
|
||||
base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
|
||||
} else {
|
||||
base.Fatalf("go: cannot find main module; see 'go help modules'")
|
||||
}
|
||||
}
|
||||
modload.LoadBuildList()
|
||||
|
||||
reqs := modload.MinReqs()
|
||||
|
@ -35,6 +35,9 @@ func runInit(cmd *base.Command, args []string) {
|
||||
if len(args) == 1 {
|
||||
modload.CmdModModule = args[0]
|
||||
}
|
||||
if os.Getenv("GO111MODULE") == "off" {
|
||||
base.Fatalf("go mod init: modules disabled by GO111MODULE=off; see 'go help modules'")
|
||||
}
|
||||
if _, err := os.Stat("go.mod"); err == nil {
|
||||
base.Fatalf("go mod init: go.mod already exists")
|
||||
}
|
||||
|
@ -11,10 +11,12 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/imports"
|
||||
"cmd/go/internal/modload"
|
||||
"cmd/go/internal/module"
|
||||
)
|
||||
@ -71,6 +73,7 @@ func runVendor(cmd *base.Command, args []string) {
|
||||
if cfg.BuildV {
|
||||
fmt.Fprintf(os.Stderr, "# %s %s%s\n", m.Path, m.Version, repl)
|
||||
}
|
||||
sort.Strings(pkgs)
|
||||
for _, pkg := range pkgs {
|
||||
fmt.Fprintf(&buf, "%s\n", pkg)
|
||||
if cfg.BuildV {
|
||||
@ -100,7 +103,7 @@ func vendorPkg(vdir, pkg string) {
|
||||
if src == "" {
|
||||
fmt.Fprintf(os.Stderr, "internal error: no pkg for %s -> %s\n", pkg, realPath)
|
||||
}
|
||||
copyDir(dst, src, matchNonTest)
|
||||
copyDir(dst, src, matchPotentialSourceFile)
|
||||
if m := modload.PackageModule(realPath); m.Path != "" {
|
||||
copyMetadata(m.Path, realPath, dst, src)
|
||||
}
|
||||
@ -153,7 +156,7 @@ var metaPrefixes = []string{
|
||||
}
|
||||
|
||||
// matchMetadata reports whether info is a metadata file.
|
||||
func matchMetadata(info os.FileInfo) bool {
|
||||
func matchMetadata(dir string, info os.FileInfo) bool {
|
||||
name := info.Name()
|
||||
for _, p := range metaPrefixes {
|
||||
if strings.HasPrefix(name, p) {
|
||||
@ -163,13 +166,34 @@ func matchMetadata(info os.FileInfo) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// matchNonTest reports whether info is any non-test file (including non-Go files).
|
||||
func matchNonTest(info os.FileInfo) bool {
|
||||
return !strings.HasSuffix(info.Name(), "_test.go")
|
||||
// matchPotentialSourceFile reports whether info may be relevant to a build operation.
|
||||
func matchPotentialSourceFile(dir string, info os.FileInfo) bool {
|
||||
if strings.HasSuffix(info.Name(), "_test.go") {
|
||||
return false
|
||||
}
|
||||
if strings.HasSuffix(info.Name(), ".go") {
|
||||
f, err := os.Open(filepath.Join(dir, info.Name()))
|
||||
if err != nil {
|
||||
base.Fatalf("go mod vendor: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
content, err := imports.ReadImports(f, false, nil)
|
||||
if err == nil && !imports.ShouldBuild(content, imports.AnyTags()) {
|
||||
// The file is explicitly tagged "ignore", so it can't affect the build.
|
||||
// Leave it out.
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// We don't know anything about this file, so optimistically assume that it is
|
||||
// needed.
|
||||
return true
|
||||
}
|
||||
|
||||
// copyDir copies all regular files satisfying match(info) from src to dst.
|
||||
func copyDir(dst, src string, match func(os.FileInfo) bool) {
|
||||
func copyDir(dst, src string, match func(dir string, info os.FileInfo) bool) {
|
||||
files, err := ioutil.ReadDir(src)
|
||||
if err != nil {
|
||||
base.Fatalf("go mod vendor: %v", err)
|
||||
@ -178,7 +202,7 @@ func copyDir(dst, src string, match func(os.FileInfo) bool) {
|
||||
base.Fatalf("go mod vendor: %v", err)
|
||||
}
|
||||
for _, file := range files {
|
||||
if file.IsDir() || !file.Mode().IsRegular() || !match(file) {
|
||||
if file.IsDir() || !file.Mode().IsRegular() || !match(src, file) {
|
||||
continue
|
||||
}
|
||||
r, err := os.Open(filepath.Join(src, file.Name()))
|
||||
|
@ -6,6 +6,7 @@ package modcmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cmd/go/internal/cfg"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -36,6 +37,14 @@ func runVerify(cmd *base.Command, args []string) {
|
||||
// NOTE(rsc): Could take a module pattern.
|
||||
base.Fatalf("go mod verify: verify takes no arguments")
|
||||
}
|
||||
// Checks go mod expected behavior
|
||||
if !modload.Enabled() {
|
||||
if cfg.Getenv("GO111MODULE") == "off" {
|
||||
base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
|
||||
} else {
|
||||
base.Fatalf("go: cannot find main module; see 'go help modules'")
|
||||
}
|
||||
}
|
||||
ok := true
|
||||
for _, mod := range modload.LoadBuildList()[1:] {
|
||||
ok = verifyMod(mod) && ok
|
||||
|
@ -41,19 +41,29 @@ func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error {
|
||||
|
||||
// Convert requirements block, which may use raw SHA1 hashes as versions,
|
||||
// to valid semver requirement list, respecting major versions.
|
||||
var work par.Work
|
||||
var (
|
||||
work par.Work
|
||||
mu sync.Mutex
|
||||
need = make(map[string]string)
|
||||
replace = make(map[string]*modfile.Replace)
|
||||
)
|
||||
|
||||
for _, r := range mf.Replace {
|
||||
replace[r.New.Path] = r
|
||||
replace[r.Old.Path] = r
|
||||
}
|
||||
for _, r := range mf.Require {
|
||||
m := r.Mod
|
||||
if m.Path == "" {
|
||||
continue
|
||||
}
|
||||
if re, ok := replace[m.Path]; ok {
|
||||
work.Add(re.New)
|
||||
continue
|
||||
}
|
||||
work.Add(r.Mod)
|
||||
}
|
||||
|
||||
var (
|
||||
mu sync.Mutex
|
||||
need = make(map[string]string)
|
||||
)
|
||||
work.Do(10, func(item interface{}) {
|
||||
r := item.(module.Version)
|
||||
repo, info, err := modfetch.ImportRepoRev(r.Path, r.Version)
|
||||
@ -76,15 +86,15 @@ func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error {
|
||||
}
|
||||
sort.Strings(paths)
|
||||
for _, path := range paths {
|
||||
if re, ok := replace[path]; ok {
|
||||
err := f.AddReplace(re.Old.Path, re.Old.Version, path, need[path])
|
||||
if err != nil {
|
||||
return fmt.Errorf("add replace: %v", err)
|
||||
}
|
||||
}
|
||||
f.AddNewRequire(path, need[path], false)
|
||||
}
|
||||
|
||||
for _, r := range mf.Replace {
|
||||
err := f.AddReplace(r.Old.Path, r.Old.Version, r.New.Path, r.New.Version)
|
||||
if err != nil {
|
||||
return fmt.Errorf("add replace: %v", err)
|
||||
}
|
||||
}
|
||||
f.Cleanup()
|
||||
return nil
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func testMain(m *testing.M) int {
|
||||
cfg.GOPROXY = "direct"
|
||||
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "skipping because git binary not found")
|
||||
fmt.Println("PASS")
|
||||
@ -104,11 +106,11 @@ func TestConvertLegacyConfig(t *testing.T) {
|
||||
github.com/AdRoll/goamz v0.0.0-20150130162828-d3664b76d905
|
||||
github.com/MSOpenTech/azure-sdk-for-go v0.0.0-20150323223030-d90753bcad2e
|
||||
github.com/Sirupsen/logrus v0.7.3
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd
|
||||
github.com/bugsnag/bugsnag-go v1.0.3-0.20141110184014-b1d153021fcd
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b
|
||||
github.com/bugsnag/panicwrap v0.0.0-20141110184334-e5f9854865b9
|
||||
github.com/codegangsta/cli v0.0.0-20150131031259-6086d7927ec3
|
||||
github.com/docker/docker v0.0.0-20150204013315-165ea5c158cf
|
||||
github.com/codegangsta/cli v1.4.2-0.20150131031259-6086d7927ec3
|
||||
github.com/docker/docker v1.4.2-0.20150204013315-165ea5c158cf
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1
|
||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7
|
||||
github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5
|
||||
@ -116,7 +118,7 @@ func TestConvertLegacyConfig(t *testing.T) {
|
||||
github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e
|
||||
github.com/jlhawn/go-crypto v0.0.0-20150401213827-cd738dde20f0
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43
|
||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50
|
||||
github.com/yvasiyarov/gorelic v0.0.7-0.20141212073537-a9bba5b9ab50
|
||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f
|
||||
golang.org/x/net v0.0.0-20150202051010-1dfe7915deaf
|
||||
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789
|
||||
@ -126,7 +128,7 @@ func TestConvertLegacyConfig(t *testing.T) {
|
||||
|
||||
{
|
||||
// golang.org/issue/24585 - confusion about v2.0.0 tag in legacy non-v2 module
|
||||
"github.com/fishy/gcsbucket", "v0.0.0-20150410205453-618d60fe84e0",
|
||||
"github.com/fishy/gcsbucket", "v0.0.0-20180217031846-618d60fe84e0",
|
||||
`module github.com/fishy/gcsbucket
|
||||
|
||||
require (
|
||||
@ -136,7 +138,7 @@ func TestConvertLegacyConfig(t *testing.T) {
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible
|
||||
golang.org/x/net v0.0.0-20180216171745-136a25c244d3
|
||||
golang.org/x/oauth2 v0.0.0-20180207181906-543e37812f10
|
||||
golang.org/x/text v0.0.0-20180208041248-4e4a3210bb54
|
||||
golang.org/x/text v0.3.1-0.20180208041248-4e4a3210bb54
|
||||
google.golang.org/api v0.0.0-20180217000815-c7a403bb5fe1
|
||||
google.golang.org/appengine v1.0.0
|
||||
google.golang.org/genproto v0.0.0-20180206005123-2b5a72b8730b
|
||||
|
@ -6,6 +6,9 @@ package modconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/lazyregexp"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -15,9 +18,14 @@ import (
|
||||
)
|
||||
|
||||
func ParseGopkgLock(file string, data []byte) (*modfile.File, error) {
|
||||
type pkg struct {
|
||||
Path string
|
||||
Version string
|
||||
Source string
|
||||
}
|
||||
mf := new(modfile.File)
|
||||
var list []module.Version
|
||||
var r *module.Version
|
||||
var list []pkg
|
||||
var r *pkg
|
||||
for lineno, line := range strings.Split(string(data), "\n") {
|
||||
lineno++
|
||||
if i := strings.Index(line, "#"); i >= 0 {
|
||||
@ -25,7 +33,7 @@ func ParseGopkgLock(file string, data []byte) (*modfile.File, error) {
|
||||
}
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "[[projects]]" {
|
||||
list = append(list, module.Version{})
|
||||
list = append(list, pkg{})
|
||||
r = &list[len(list)-1]
|
||||
continue
|
||||
}
|
||||
@ -52,6 +60,8 @@ func ParseGopkgLock(file string, data []byte) (*modfile.File, error) {
|
||||
switch key {
|
||||
case "name":
|
||||
r.Path = val
|
||||
case "source":
|
||||
r.Source = val
|
||||
case "revision", "version":
|
||||
// Note: key "version" should take priority over "revision",
|
||||
// and it does, because dep writes toml keys in alphabetical order,
|
||||
@ -68,7 +78,55 @@ func ParseGopkgLock(file string, data []byte) (*modfile.File, error) {
|
||||
if r.Path == "" || r.Version == "" {
|
||||
return nil, fmt.Errorf("%s: empty [[projects]] stanza (%s)", file, r.Path)
|
||||
}
|
||||
mf.Require = append(mf.Require, &modfile.Require{Mod: r})
|
||||
mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: r.Path, Version: r.Version}})
|
||||
|
||||
if r.Source != "" {
|
||||
// Convert "source" to import path, such as
|
||||
// git@test.com:x/y.git and https://test.com/x/y.git.
|
||||
// We get "test.com/x/y" at last.
|
||||
source, err := decodeSource(r.Source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
old := module.Version{Path: r.Path, Version: r.Version}
|
||||
new := module.Version{Path: source, Version: r.Version}
|
||||
mf.Replace = append(mf.Replace, &modfile.Replace{Old: old, New: new})
|
||||
}
|
||||
}
|
||||
return mf, nil
|
||||
}
|
||||
|
||||
var scpSyntaxReg = lazyregexp.New(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
|
||||
|
||||
func decodeSource(source string) (string, error) {
|
||||
var u *url.URL
|
||||
var p string
|
||||
if m := scpSyntaxReg.FindStringSubmatch(source); m != nil {
|
||||
// Match SCP-like syntax and convert it to a URL.
|
||||
// Eg, "git@github.com:user/repo" becomes
|
||||
// "ssh://git@github.com/user/repo".
|
||||
u = &url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User(m[1]),
|
||||
Host: m[2],
|
||||
Path: "/" + m[3],
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
u, err = url.Parse(source)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%q is not a valid URI", source)
|
||||
}
|
||||
}
|
||||
|
||||
// If no scheme was passed, then the entire path will have been put into
|
||||
// u.Path. Either way, construct the normalized path correctly.
|
||||
if u.Host == "" {
|
||||
p = source
|
||||
} else {
|
||||
p = path.Join(u.Host, u.Path)
|
||||
}
|
||||
p = strings.TrimSuffix(p, ".git")
|
||||
p = strings.TrimSuffix(p, ".hg")
|
||||
return p, nil
|
||||
}
|
||||
|
@ -15,8 +15,7 @@ func ParseGlideLock(file string, data []byte) (*modfile.File, error) {
|
||||
mf := new(modfile.File)
|
||||
imports := false
|
||||
name := ""
|
||||
for lineno, line := range strings.Split(string(data), "\n") {
|
||||
lineno++
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
@ -13,8 +13,7 @@ import (
|
||||
|
||||
func ParseGLOCKFILE(file string, data []byte) (*modfile.File, error) {
|
||||
mf := new(modfile.File)
|
||||
for lineno, line := range strings.Split(string(data), "\n") {
|
||||
lineno++
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
f := strings.Fields(line)
|
||||
if len(f) >= 2 && f[0] != "cmd" {
|
||||
mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: f[0], Version: f[1]}})
|
||||
|
@ -58,6 +58,9 @@ func Test(t *testing.T) {
|
||||
for _, r := range out.Require {
|
||||
fmt.Fprintf(&buf, "%s %s\n", r.Mod.Path, r.Mod.Version)
|
||||
}
|
||||
for _, r := range out.Replace {
|
||||
fmt.Fprintf(&buf, "replace: %s %s %s %s\n", r.Old.Path, r.Old.Version, r.New.Path, r.New.Version)
|
||||
}
|
||||
if !bytes.Equal(buf.Bytes(), want) {
|
||||
t.Errorf("have:\n%s\nwant:\n%s", buf.Bytes(), want)
|
||||
}
|
||||
|
@ -13,8 +13,7 @@ import (
|
||||
|
||||
func ParseDependenciesTSV(file string, data []byte) (*modfile.File, error) {
|
||||
mf := new(modfile.File)
|
||||
for lineno, line := range strings.Split(string(data), "\n") {
|
||||
lineno++
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
f := strings.Split(line, "\t")
|
||||
if len(f) >= 3 {
|
||||
mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: f[0], Version: f[2]}})
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user