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:
Ian Lance Taylor 2019-09-06 18:12:46 +00:00 committed by Ian Lance Taylor
parent 920ea3b8ba
commit aa8901e9bb
1733 changed files with 94705 additions and 35756 deletions

View File

@ -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.

View File

@ -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.

View File

@ -38,6 +38,7 @@ func BenchmarkSlowNonASCII(b *testing.B) {
}
func main() {
testing.Init()
os.Args = []string{os.Args[0], "-test.benchtime=100ms"}
flag.Parse()

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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))

View File

@ -1 +1 @@
go1.12.2
go1.13beta1

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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")
}

View File

@ -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"},

View File

@ -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.

View File

@ -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()

View File

@ -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 {

View File

@ -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))

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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)
}
}
}

View File

@ -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
}

View File

@ -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)

View File

@ -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())

View File

@ -6,4 +6,3 @@ package bytes
// Export func for testing
var IndexBytePortable = indexBytePortable
var EqualPortable = equalPortable

View File

@ -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) { }

View File

@ -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

View File

@ -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", ";",
)

View File

@ -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));
`

View File

@ -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

View File

@ -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()

View File

@ -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)
}
}

View File

@ -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"})

View 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)
}
}
}

View 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
}

View 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))
}

View File

@ -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) {

View File

@ -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.

View File

@ -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)
}

View File

@ -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
}

View File

@ -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) {

View File

@ -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
}

View File

@ -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))

View File

@ -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
}

View File

@ -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)

View File

@ -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)
}
}
}

View File

@ -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])
})
}

View File

@ -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)

View File

@ -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)
}
}
}

View File

@ -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
}

View File

@ -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")
}

View File

@ -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}")

View File

@ -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 {

View File

@ -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)

View File

@ -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.
`,
}

View File

@ -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,
}

View File

@ -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.
}

View File

@ -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)
}
})
}
}

View File

@ -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
}

View File

@ -0,0 +1,3 @@
package android
import _ "a"

View File

@ -0,0 +1,3 @@
package android
import _ "b"

View File

@ -0,0 +1,3 @@
package android
import _ "c"

View File

@ -0,0 +1,3 @@
package android
import _ "d"

View File

@ -0,0 +1,5 @@
// +build android
package android
import _ "e"

View File

@ -0,0 +1,5 @@
// +build linux
package android
import _ "f"

View File

@ -0,0 +1,5 @@
// +build !android
package android
import _ "g"

View File

@ -0,0 +1,3 @@
package illumos
import _ "a"

View File

@ -0,0 +1,3 @@
package illumos
import _ "b"

View File

@ -0,0 +1,3 @@
package illumos
import _ "c"

View File

@ -0,0 +1,3 @@
package illumos
import _ "d"

View File

@ -0,0 +1,5 @@
// +build illumos
package illumos
import _ "e"

View File

@ -0,0 +1,5 @@
// +build solaris
package illumos
import _ "f"

View File

@ -0,0 +1,5 @@
// +build !illumos
package illumos
import _ "g"

View File

@ -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)
}
}
}

View File

@ -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

View 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)
}
}
}

View File

@ -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}}
}
`))
`)

View File

@ -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)

View File

@ -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
}

View File

@ -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"}
}

View File

@ -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
}

View File

@ -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()

View File

@ -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")
}

View File

@ -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()))

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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]}})

View File

@ -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)
}

View File

@ -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