From bc998d034f45d1828a8663b2eed928faf22a7d01 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor
Date: Thu, 14 Sep 2017 17:11:35 +0000
Subject: [PATCH] libgo: update to go1.9
Reviewed-on: https://go-review.googlesource.com/63753
From-SVN: r252767
---
gcc/go/gofrontend/MERGE | 2 +-
gcc/testsuite/go.test/test/fixedbugs/bug273.go | 15 +-
gotools/ChangeLog | 12 +
gotools/Makefile.am | 53 +-
gotools/Makefile.in | 54 +-
libgo/MERGE | 2 +-
libgo/Makefile.am | 94 +-
libgo/Makefile.in | 131 +-
libgo/VERSION | 2 +-
libgo/configure | 2 +-
libgo/configure.ac | 2 +-
libgo/go/archive/tar/common.go | 20 +-
libgo/go/archive/tar/tar_test.go | 80 +-
libgo/go/archive/tar/writer.go | 10 +-
libgo/go/archive/zip/register.go | 47 +-
libgo/go/archive/zip/struct.go | 2 +-
libgo/go/archive/zip/writer.go | 21 +-
libgo/go/archive/zip/writer_test.go | 90 +-
libgo/go/archive/zip/zip_test.go | 14 +-
libgo/go/bufio/bufio.go | 5 +-
libgo/go/bufio/scan_test.go | 1 -
libgo/go/builtin/builtin.go | 6 +-
libgo/go/bytes/buffer.go | 137 +-
libgo/go/bytes/buffer_test.go | 76 +-
libgo/go/bytes/bytes.go | 60 +-
libgo/go/bytes/bytes_amd64.go | 17 +-
libgo/go/bytes/bytes_generic.go | 6 +
libgo/go/bytes/bytes_s390x.go | 6 +
libgo/go/bytes/bytes_test.go | 146 +
libgo/go/bytes/example_test.go | 9 +
libgo/go/bytes/export_test.go | 1 +
libgo/go/cmd/cgo/ast.go | 14 +-
libgo/go/cmd/cgo/doc.go | 80 +-
libgo/go/cmd/cgo/gcc.go | 464 +-
libgo/go/cmd/cgo/main.go | 31 +-
libgo/go/cmd/cgo/out.go | 25 +-
libgo/go/cmd/go/alldocs.go | 178 +-
libgo/go/cmd/go/build_test.go | 44 -
libgo/go/cmd/go/env.go | 138 -
libgo/go/cmd/go/go_test.go | 731 +++-
libgo/go/cmd/go/go_unix_test.go | 10 +-
libgo/go/cmd/go/internal/base/base.go | 173 +
libgo/go/cmd/go/internal/base/env.go | 37 +
libgo/go/cmd/go/internal/base/flag.go | 35 +
libgo/go/cmd/go/internal/base/path.go | 74 +
libgo/go/cmd/go/{ => internal/base}/signal.go | 12 +-
.../cmd/go/{ => internal/base}/signal_notunix.go | 8 +-
libgo/go/cmd/go/{ => internal/base}/signal_unix.go | 6 +-
libgo/go/cmd/go/internal/base/tool.go | 53 +
libgo/go/cmd/go/{ => internal/bug}/bug.go | 36 +-
libgo/go/cmd/go/internal/buildid/buildid.go | 201 +
libgo/go/cmd/go/{ => internal/buildid}/note.go | 4 +-
libgo/go/cmd/go/internal/cfg/cfg.go | 134 +
libgo/go/cmd/go/{ => internal/clean}/clean.go | 64 +-
libgo/go/cmd/go/internal/cmdflag/flag.go | 123 +
libgo/go/cmd/go/{ => internal/doc}/doc.go | 39 +-
libgo/go/cmd/go/internal/envcmd/env.go | 178 +
libgo/go/cmd/go/{ => internal/fix}/fix.go | 19 +-
libgo/go/cmd/go/{ => internal/fmtcmd}/fmt.go | 29 +-
.../go/cmd/go/{ => internal/generate}/generate.go | 44 +-
.../go/{ => internal/generate}/generate_test.go | 2 +-
libgo/go/cmd/go/{ => internal/get}/discovery.go | 9 +-
libgo/go/cmd/go/{ => internal/get}/get.go | 250 +-
libgo/go/cmd/go/internal/get/pkg_test.go | 83 +
libgo/go/cmd/go/{ => internal/get}/tag_test.go | 2 +-
libgo/go/cmd/go/{ => internal/get}/vcs.go | 73 +-
libgo/go/cmd/go/{ => internal/get}/vcs_test.go | 20 +-
libgo/go/cmd/go/internal/help/help.go | 178 +
.../cmd/go/{help.go => internal/help/helpdoc.go} | 71 +-
libgo/go/cmd/go/{ => internal/list}/context.go | 2 +-
libgo/go/cmd/go/{ => internal/list}/list.go | 56 +-
libgo/go/cmd/go/internal/load/match_test.go | 165 +
libgo/go/cmd/go/internal/load/path.go | 80 +
libgo/go/cmd/go/{ => internal/load}/pkg.go | 885 ++--
libgo/go/cmd/go/internal/load/search.go | 338 ++
libgo/go/cmd/go/{ => internal/load}/testgo.go | 2 +-
libgo/go/cmd/go/{ => internal/run}/run.go | 109 +-
libgo/go/cmd/go/internal/str/str.go | 141 +
libgo/go/cmd/go/{ => internal/test}/test.go | 649 +--
libgo/go/cmd/go/internal/test/testflag.go | 211 +
libgo/go/cmd/go/{ => internal/tool}/tool.go | 98 +-
libgo/go/cmd/go/{ => internal/version}/version.go | 9 +-
libgo/go/cmd/go/internal/vet/vet.go | 56 +
libgo/go/cmd/go/internal/vet/vetflag.go | 99 +
libgo/go/cmd/go/{ => internal/web}/bootstrap.go | 20 +-
libgo/go/cmd/go/{ => internal/web}/http.go | 38 +-
libgo/go/cmd/go/internal/web/security.go | 16 +
libgo/go/cmd/go/{ => internal/work}/build.go | 1902 ++++-----
libgo/go/cmd/go/internal/work/build_test.go | 227 +
libgo/go/cmd/go/internal/work/testgo.go | 17 +
libgo/go/cmd/go/main.go | 789 +---
libgo/go/cmd/go/match_test.go | 88 -
libgo/go/cmd/go/note_test.go | 13 +-
libgo/go/cmd/go/pkg_test.go | 194 -
libgo/go/cmd/go/script | 23 -
libgo/go/cmd/go/script.txt | 352 --
libgo/go/cmd/go/test.bash | 820 ----
libgo/go/cmd/go/testdata/src/bench/x_test.go | 6 +
libgo/go/cmd/go/testdata/src/cgoasm/p.go | 8 +
libgo/go/cmd/go/testdata/src/cgoasm/p.s | 2 +
libgo/go/cmd/go/testdata/src/exclude/empty/x.txt | 0
libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go | 1 +
libgo/go/cmd/go/testdata/src/exclude/x.go | 3 +
libgo/go/cmd/go/testdata/src/exclude/x_linux.go | 3 +
.../go/cmd/go/testdata/src/testlist/bench_test.go | 14 +
.../cmd/go/testdata/src/testlist/example_test.go | 21 +
libgo/go/cmd/go/testdata/src/testlist/test_test.go | 10 +
libgo/go/cmd/go/testdata/src/testregexp/x_test.go | 17 +
libgo/go/cmd/go/testdata/src/testregexp/z_test.go | 19 +
libgo/go/cmd/go/testflag.go | 294 --
libgo/go/cmd/go/vendor_test.go | 6 +-
libgo/go/cmd/go/vet.go | 52 -
libgo/go/cmd/gofmt/doc.go | 5 +-
libgo/go/cmd/gofmt/gofmt.go | 70 +-
libgo/go/cmd/gofmt/gofmt_test.go | 70 +-
libgo/go/cmd/gofmt/rewrite.go | 2 +-
libgo/go/cmd/internal/browser/browser.go | 25 +-
libgo/go/cmd/internal/objabi/autotype.go | 37 +
libgo/go/cmd/internal/objabi/doc.go | 120 +
libgo/go/cmd/internal/objabi/flag.go | 115 +
libgo/go/cmd/internal/objabi/funcdata.go | 25 +
libgo/go/cmd/internal/objabi/head.go | 104 +
libgo/go/cmd/internal/objabi/line.go | 82 +
libgo/go/cmd/internal/objabi/path.go | 41 +
libgo/go/cmd/internal/objabi/path_test.go | 33 +
libgo/go/cmd/internal/objabi/reloctype.go | 200 +
libgo/go/cmd/internal/objabi/reloctype_string.go | 17 +
libgo/go/cmd/internal/objabi/stack.go | 20 +
libgo/go/cmd/internal/objabi/symkind.go | 60 +
libgo/go/cmd/internal/objabi/symkind_string.go | 16 +
libgo/go/cmd/internal/objabi/typekind.go | 41 +
libgo/go/cmd/internal/objabi/util.go | 119 +
libgo/go/cmd/internal/objabi/zbootstrap.go | 15 +
libgo/go/compress/bzip2/bzip2_test.go | 24 +-
libgo/go/compress/bzip2/huffman.go | 4 -
libgo/go/compress/flate/huffman_code.go | 5 +
libgo/go/compress/flate/inflate.go | 7 +-
libgo/go/compress/flate/reverse_bits.go | 48 -
libgo/go/compress/gzip/gzip.go | 5 +-
libgo/go/compress/lzw/reader.go | 14 +-
libgo/go/compress/lzw/reader_test.go | 97 +
libgo/go/container/heap/heap.go | 7 +-
libgo/go/context/context.go | 40 +-
libgo/go/context/context_test.go | 2 +-
libgo/go/crypto/aes/cipher_generic.go | 2 +-
libgo/go/crypto/aes/cipher_ppc64le.go | 82 +
libgo/go/crypto/crypto.go | 68 +-
libgo/go/crypto/des/block.go | 114 +-
libgo/go/crypto/des/cipher.go | 51 +-
libgo/go/crypto/des/const.go | 3 +
libgo/go/crypto/des/des_test.go | 39 +-
libgo/go/crypto/dsa/dsa_test.go | 17 +-
libgo/go/crypto/md5/md5.go | 3 +
libgo/go/crypto/rand/rand_linux.go | 28 +-
libgo/go/crypto/rand/util.go | 17 +-
libgo/go/crypto/rand/util_test.go | 53 +
libgo/go/crypto/rc4/rc4.go | 6 +-
libgo/go/crypto/sha1/sha1.go | 11 +-
libgo/go/crypto/sha1/sha1_test.go | 2 +-
libgo/go/crypto/sha1/sha1block.go | 2 +-
libgo/go/crypto/sha1/sha1block_amd64.go | 8 +-
libgo/go/crypto/sha1/sha1block_s390x.go | 2 +-
libgo/go/crypto/sha256/sha256block_amd64.go | 11 +
libgo/go/crypto/sha512/sha512block_amd64.go | 26 +
libgo/go/crypto/sha512/sha512block_decl.go | 2 +-
libgo/go/crypto/tls/common.go | 36 +-
libgo/go/crypto/tls/conn.go | 2 +-
libgo/go/crypto/tls/conn_test.go | 41 +-
libgo/go/crypto/tls/generate_cert.go | 2 +-
libgo/go/crypto/tls/handshake_client.go | 2 +-
libgo/go/crypto/tls/handshake_messages.go | 11 +-
libgo/go/crypto/tls/handshake_messages_test.go | 4 +
libgo/go/crypto/tls/handshake_server.go | 8 +-
libgo/go/crypto/tls/handshake_server_test.go | 4 +
libgo/go/crypto/x509/pkcs1.go | 12 +-
libgo/go/crypto/x509/root_bsd.go | 3 +-
libgo/go/crypto/x509/root_darwin.go | 22 +-
libgo/go/crypto/x509/root_unix.go | 34 +-
libgo/go/crypto/x509/root_unix_test.go | 127 +
libgo/go/crypto/x509/test-file.crt | 32 +
libgo/go/crypto/x509/testdata/test-dir.crt | 31 +
libgo/go/crypto/x509/verify.go | 12 +-
libgo/go/crypto/x509/verify_test.go | 219 +-
libgo/go/crypto/x509/x509.go | 142 +-
libgo/go/crypto/x509/x509_test.go | 5 +
libgo/go/database/sql/convert.go | 215 +-
libgo/go/database/sql/convert_test.go | 18 +-
libgo/go/database/sql/driver/driver.go | 30 +
libgo/go/database/sql/fakedb_test.go | 94 +-
libgo/go/database/sql/sql.go | 684 ++-
libgo/go/database/sql/sql_test.go | 650 ++-
libgo/go/debug/dwarf/export_test.go | 7 +
libgo/go/debug/dwarf/line.go | 74 +-
libgo/go/debug/dwarf/line_test.go | 85 +
libgo/go/debug/dwarf/testdata/line-gcc-win.bin | Bin 0 -> 133202 bytes
libgo/go/debug/dwarf/type_test.go | 14 +
libgo/go/debug/pe/file_cgo_test.go | 31 +
libgo/go/debug/pe/file_test.go | 141 +-
libgo/go/encoding/ascii85/ascii85_test.go | 37 +-
libgo/go/encoding/asn1/asn1.go | 35 +-
libgo/go/encoding/asn1/asn1_test.go | 29 +
libgo/go/encoding/asn1/common.go | 1 +
libgo/go/encoding/asn1/marshal.go | 10 +-
libgo/go/encoding/base32/base32.go | 162 +-
libgo/go/encoding/base32/base32_test.go | 284 +-
libgo/go/encoding/base64/base64.go | 62 +-
libgo/go/encoding/base64/base64_test.go | 40 +-
libgo/go/encoding/binary/binary.go | 3 +-
libgo/go/encoding/binary/binary_test.go | 24 +
libgo/go/encoding/binary/varint.go | 12 +-
libgo/go/encoding/csv/reader.go | 69 +-
libgo/go/encoding/csv/reader_test.go | 31 +
libgo/go/encoding/gob/codec_test.go | 74 +-
libgo/go/encoding/gob/decode.go | 49 +-
libgo/go/encoding/gob/decoder.go | 4 +
libgo/go/encoding/gob/doc.go | 90 +-
libgo/go/encoding/gob/encode.go | 30 +-
libgo/go/encoding/gob/encoder_test.go | 65 +
libgo/go/encoding/gob/error.go | 1 -
libgo/go/encoding/gob/gobencdec_test.go | 2 +-
libgo/go/encoding/gob/timing_test.go | 188 +-
libgo/go/encoding/gob/type.go | 56 +-
libgo/go/encoding/gob/type_test.go | 6 +-
libgo/go/encoding/hex/hex.go | 5 +-
libgo/go/encoding/json/bench_test.go | 137 +-
libgo/go/encoding/json/decode.go | 7 +-
libgo/go/encoding/json/encode.go | 57 +-
libgo/go/encoding/json/encode_test.go | 176 +-
libgo/go/encoding/json/scanner.go | 5 +
libgo/go/encoding/json/scanner_test.go | 20 +
libgo/go/encoding/json/stream_test.go | 10 +-
libgo/go/encoding/pem/pem.go | 10 +-
libgo/go/encoding/pem/pem_test.go | 34 +-
libgo/go/encoding/xml/marshal_test.go | 100 +-
libgo/go/encoding/xml/read.go | 28 +-
libgo/go/encoding/xml/read_test.go | 156 +
libgo/go/encoding/xml/typeinfo.go | 20 +-
libgo/go/encoding/xml/xml_test.go | 34 -
libgo/go/expvar/expvar.go | 142 +-
libgo/go/expvar/expvar_test.go | 168 +-
libgo/go/flag/flag.go | 4 +-
libgo/go/flag/flag_test.go | 17 +
libgo/go/fmt/doc.go | 10 +-
libgo/go/fmt/fmt_test.go | 42 +
libgo/go/fmt/format.go | 40 +
libgo/go/fmt/print.go | 2 -
libgo/go/go/ast/ast.go | 16 +-
libgo/go/go/build/build.go | 84 +-
libgo/go/go/build/build_test.go | 38 +-
libgo/go/go/build/deps_test.go | 132 +-
libgo/go/go/build/doc.go | 1 +
libgo/go/go/constant/value.go | 16 +-
libgo/go/go/constant/value_test.go | 3 +-
libgo/go/go/doc/comment.go | 19 +-
libgo/go/go/doc/comment_test.go | 6 +
libgo/go/go/doc/doc_test.go | 5 +-
libgo/go/go/doc/exports.go | 4 +-
libgo/go/go/format/internal.go | 8 +-
libgo/go/go/importer/importer.go | 32 +-
.../go/go/internal/gccgoimporter/importer_test.go | 1 +
libgo/go/go/internal/gccgoimporter/parser.go | 50 +-
libgo/go/go/internal/gcimporter/bimport.go | 208 +-
libgo/go/go/internal/gcimporter/gcimporter.go | 3 +-
libgo/go/go/internal/gcimporter/gcimporter_test.go | 70 +-
.../go/internal/gcimporter/testdata/issue20046.go | 9 +
libgo/go/go/internal/srcimporter/srcimporter.go | 211 +
.../go/go/internal/srcimporter/srcimporter_test.go | 150 +
libgo/go/go/parser/error_test.go | 4 +-
libgo/go/go/parser/parser.go | 11 +-
libgo/go/go/parser/parser_test.go | 15 +
libgo/go/go/parser/performance_test.go | 13 +-
libgo/go/go/parser/short_test.go | 2 +
libgo/go/go/printer/nodes.go | 21 +-
libgo/go/go/printer/printer.go | 61 +-
libgo/go/go/printer/printer_test.go | 102 +-
libgo/go/go/printer/testdata/declarations.golden | 21 +
libgo/go/go/printer/testdata/declarations.input | 20 +
libgo/go/go/token/position.go | 37 +-
libgo/go/go/token/serialize.go | 19 +-
libgo/go/go/types/api.go | 28 +-
libgo/go/go/types/api_test.go | 185 +-
libgo/go/go/types/assignments.go | 4 +-
libgo/go/go/types/call.go | 14 +-
libgo/go/go/types/check.go | 14 +-
libgo/go/go/types/check_test.go | 2 +-
libgo/go/go/types/decl.go | 194 +-
libgo/go/go/types/example_test.go | 4 +-
libgo/go/go/types/expr.go | 63 +-
libgo/go/go/types/gotype.go | 190 +-
libgo/go/go/types/hilbert_test.go | 3 +-
libgo/go/go/types/lookup.go | 83 +-
libgo/go/go/types/methodset.go | 52 +-
libgo/go/go/types/object.go | 109 +-
libgo/go/go/types/object_test.go | 44 +
libgo/go/go/types/operand.go | 14 +-
libgo/go/go/types/package.go | 8 +-
libgo/go/go/types/predicates.go | 2 +-
libgo/go/go/types/resolver.go | 133 +-
libgo/go/go/types/sizes.go | 37 +-
libgo/go/go/types/stdlib_test.go | 18 +-
libgo/go/go/types/testdata/builtins.src | 1 +
libgo/go/go/types/testdata/cycles.src | 11 +-
libgo/go/go/types/testdata/decls1.src | 2 +-
libgo/go/go/types/testdata/expr3.src | 2 +-
libgo/go/go/types/testdata/issues.src | 25 +-
libgo/go/go/types/testdata/shifts.src | 18 +-
libgo/go/go/types/testdata/stmt0.src | 20 +-
libgo/go/go/types/testdata/vardecl.src | 18 +-
libgo/go/go/types/type.go | 2 +-
libgo/go/go/types/typestring.go | 1 +
libgo/go/go/types/typestring_test.go | 5 +-
libgo/go/go/types/typexpr.go | 66 +-
.../x/crypto/chacha20poly1305/chacha20poly1305.go | 2 +-
.../chacha20poly1305/chacha20poly1305_amd64.go | 59 +-
...vectors.go => chacha20poly1305_vectors_test.go} | 0
.../internal/chacha20/chacha_test.go | 4 +
.../golang_org/x/crypto/curve25519/curve25519.go | 23 +-
.../x/crypto/curve25519/curve25519_test.go | 10 +
.../golang_org/x/crypto/poly1305/poly1305_test.go | 67 +
libgo/go/golang_org/x/crypto/poly1305/sum_ref.go | 1634 +------
libgo/go/golang_org/x/net/http2/hpack/encode.go | 29 +-
.../go/golang_org/x/net/http2/hpack/encode_test.go | 70 +-
libgo/go/golang_org/x/net/http2/hpack/hpack.go | 106 +-
.../go/golang_org/x/net/http2/hpack/hpack_test.go | 150 +-
libgo/go/golang_org/x/net/http2/hpack/tables.go | 255 +-
.../go/golang_org/x/net/http2/hpack/tables_test.go | 214 +
libgo/go/golang_org/x/net/idna/idna.go | 672 ++-
libgo/go/golang_org/x/net/idna/punycode.go | 23 +-
libgo/go/golang_org/x/net/idna/tables.go | 4479 ++++++++++++++++++++
libgo/go/golang_org/x/net/idna/trie.go | 72 +
libgo/go/golang_org/x/net/idna/trieval.go | 116 +
libgo/go/golang_org/x/net/lif/address.go | 4 +-
libgo/go/golang_org/x/net/lif/address_test.go | 6 +-
libgo/go/golang_org/x/net/lif/binary.go | 49 +-
libgo/go/golang_org/x/net/lif/defs_solaris.go | 2 +-
libgo/go/golang_org/x/net/lif/link.go | 8 +-
libgo/go/golang_org/x/net/lif/link_test.go | 6 +-
libgo/go/golang_org/x/net/lif/sys.go | 21 +
libgo/go/golang_org/x/net/nettest/conntest.go | 456 ++
libgo/go/golang_org/x/net/nettest/conntest_go16.go | 24 +
libgo/go/golang_org/x/net/nettest/conntest_go17.go | 24 +
libgo/go/golang_org/x/net/nettest/conntest_test.go | 126 +
libgo/go/golang_org/x/net/proxy/direct.go | 18 +
libgo/go/golang_org/x/net/proxy/per_host.go | 140 +
libgo/go/golang_org/x/net/proxy/per_host_test.go | 55 +
libgo/go/golang_org/x/net/proxy/proxy.go | 94 +
libgo/go/golang_org/x/net/proxy/proxy_test.go | 142 +
libgo/go/golang_org/x/net/proxy/socks5.go | 213 +
libgo/go/golang_org/x/net/route/address.go | 152 +-
libgo/go/golang_org/x/net/route/binary.go | 2 +-
libgo/go/golang_org/x/net/route/defs_darwin.go | 8 +
libgo/go/golang_org/x/net/route/defs_dragonfly.go | 8 +
libgo/go/golang_org/x/net/route/defs_freebsd.go | 8 +
libgo/go/golang_org/x/net/route/defs_netbsd.go | 8 +
libgo/go/golang_org/x/net/route/defs_openbsd.go | 12 +
libgo/go/golang_org/x/net/route/message.go | 8 +-
.../golang_org/x/net/route/message_darwin_test.go | 31 +-
.../golang_org/x/net/route/message_freebsd_test.go | 94 +-
libgo/go/golang_org/x/net/route/message_test.go | 159 +-
libgo/go/golang_org/x/net/route/route.go | 59 +-
libgo/go/golang_org/x/net/route/route_classic.go | 36 +
libgo/go/golang_org/x/net/route/route_openbsd.go | 35 +-
libgo/go/golang_org/x/net/route/sys.go | 7 +-
libgo/go/golang_org/x/net/route/sys_darwin.go | 45 +-
libgo/go/golang_org/x/net/route/sys_dragonfly.go | 39 +-
libgo/go/golang_org/x/net/route/sys_freebsd.go | 39 +-
libgo/go/golang_org/x/net/route/sys_netbsd.go | 34 +-
libgo/go/golang_org/x/net/route/sys_openbsd.go | 39 +-
libgo/go/golang_org/x/net/route/syscall.go | 5 -
libgo/go/golang_org/x/net/route/zsys_darwin.go | 6 +
libgo/go/golang_org/x/net/route/zsys_dragonfly.go | 6 +
.../go/golang_org/x/net/route/zsys_freebsd_386.go | 6 +
.../golang_org/x/net/route/zsys_freebsd_amd64.go | 6 +
.../go/golang_org/x/net/route/zsys_freebsd_arm.go | 6 +
libgo/go/golang_org/x/net/route/zsys_netbsd.go | 6 +
libgo/go/golang_org/x/net/route/zsys_openbsd.go | 10 +
.../golang_org/x/text/secure/bidirule/bidirule.go | 344 ++
libgo/go/golang_org/x/text/secure/doc.go | 8 +
.../golang_org/x/text/transform/examples_test.go | 39 +
libgo/go/golang_org/x/text/transform/transform.go | 4 +-
libgo/go/golang_org/x/text/unicode/bidi/bidi.go | 198 +
libgo/go/golang_org/x/text/unicode/bidi/bracket.go | 337 ++
libgo/go/golang_org/x/text/unicode/bidi/core.go | 1060 +++++
.../golang_org/x/text/unicode/bidi/example_test.go | 185 +
libgo/go/golang_org/x/text/unicode/bidi/prop.go | 208 +
libgo/go/golang_org/x/text/unicode/bidi/tables.go | 1781 ++++++++
libgo/go/golang_org/x/text/unicode/bidi/trieval.go | 62 +
libgo/go/golang_org/x/text/unicode/doc.go | 10 +
.../golang_org/x/text/unicode/norm/composition.go | 2 +
.../x/text/unicode/norm/example_iter_test.go | 84 +
.../golang_org/x/text/unicode/norm/example_test.go | 29 +
.../go/golang_org/x/text/unicode/norm/forminfo.go | 51 +-
libgo/go/golang_org/x/text/unicode/norm/input.go | 2 +
libgo/go/golang_org/x/text/unicode/norm/iter.go | 2 +
.../go/golang_org/x/text/unicode/norm/normalize.go | 7 +-
.../golang_org/x/text/unicode/norm/readwriter.go | 2 +
libgo/go/golang_org/x/text/unicode/norm/tables.go | 1022 ++---
.../go/golang_org/x/text/unicode/norm/transform.go | 2 +
libgo/go/golang_org/x/text/unicode/norm/trie.go | 2 +
libgo/go/hash/crc32/crc32_amd64.go | 30 +-
libgo/go/hash/crc32/crc32_amd64p32.go | 14 +-
libgo/go/hash/crc32/crc32_arm64.go | 53 +
libgo/go/hash/crc32/crc32_otherarch.go | 2 +-
libgo/go/hash/crc32/crc32_ppc64le.go | 89 +
libgo/go/hash/crc32/crc32_test.go | 86 +-
libgo/go/hash/crc32/gen_const_ppc64le.go | 150 +
libgo/go/hash/fnv/fnv.go | 122 +-
libgo/go/hash/fnv/fnv_test.go | 39 +
libgo/go/html/template/attr.go | 3 +-
libgo/go/html/template/doc.go | 4 +-
libgo/go/html/template/error.go | 28 +
libgo/go/html/template/escape.go | 240 +-
libgo/go/html/template/escape_test.go | 192 +-
libgo/go/html/template/js.go | 2 +-
libgo/go/html/template/template.go | 20 +-
libgo/go/html/template/transition.go | 4 +-
libgo/go/image/color/ycbcr.go | 58 +-
libgo/go/image/geom.go | 6 +-
libgo/go/image/geom_test.go | 7 +-
libgo/go/image/gif/reader.go | 45 +-
libgo/go/image/gif/reader_test.go | 63 +-
libgo/go/image/gif/writer.go | 39 +-
libgo/go/image/gif/writer_test.go | 61 +
libgo/go/image/image_test.go | 12 +-
libgo/go/image/internal/imageutil/gen.go | 2 +-
libgo/go/image/internal/imageutil/impl.go | 8 +-
libgo/go/image/jpeg/huffman.go | 3 +-
libgo/go/image/jpeg/reader.go | 17 +-
libgo/go/image/jpeg/scan.go | 10 +-
libgo/go/image/jpeg/writer.go | 29 +-
libgo/go/image/jpeg/writer_test.go | 58 +-
libgo/go/image/png/reader.go | 17 +-
libgo/go/image/png/reader_test.go | 71 +-
libgo/go/image/png/writer.go | 106 +-
libgo/go/image/png/writer_test.go | 25 +
libgo/go/internal/cpu/cpu.go | 32 +
libgo/go/internal/cpu/cpu_arm.go | 7 +
libgo/go/internal/cpu/cpu_arm64.go | 7 +
libgo/go/internal/cpu/cpu_mips.go | 7 +
libgo/go/internal/cpu/cpu_mips64.go | 7 +
libgo/go/internal/cpu/cpu_mips64le.go | 7 +
libgo/go/internal/cpu/cpu_mipsle.go | 7 +
libgo/go/internal/cpu/cpu_ppc64.go | 7 +
libgo/go/internal/cpu/cpu_ppc64le.go | 7 +
libgo/go/internal/cpu/cpu_s390x.go | 7 +
libgo/go/internal/cpu/cpu_test.go | 27 +
libgo/go/internal/cpu/cpu_x86.go | 59 +
libgo/go/internal/poll/export_posix_test.go | 15 +
libgo/go/internal/poll/export_test.go | 35 +
libgo/go/internal/poll/fd.go | 57 +
libgo/go/{net => internal/poll}/fd_io_plan9.go | 14 +-
libgo/go/{net => internal/poll}/fd_mutex.go | 39 +-
libgo/go/{net => internal/poll}/fd_mutex_test.go | 85 +-
libgo/go/internal/poll/fd_plan9.go | 216 +
libgo/go/internal/poll/fd_poll_nacl.go | 94 +
libgo/go/{net => internal/poll}/fd_poll_runtime.go | 83 +-
libgo/go/internal/poll/fd_posix.go | 57 +
libgo/go/internal/poll/fd_posix_test.go | 43 +
libgo/go/internal/poll/fd_unix.go | 452 ++
libgo/go/internal/poll/fd_windows.go | 873 ++++
libgo/go/{net => internal/poll}/hook_cloexec.go | 10 +-
libgo/go/internal/poll/hook_unix.go | 15 +
libgo/go/internal/poll/hook_windows.go | 16 +
libgo/go/internal/poll/sendfile_bsd.go | 53 +
libgo/go/internal/poll/sendfile_linux.go | 50 +
libgo/go/internal/poll/sendfile_solaris.go | 63 +
libgo/go/internal/poll/sendfile_windows.go | 23 +
libgo/go/internal/poll/sock_cloexec.go | 50 +
libgo/go/internal/poll/sockopt.go | 36 +
libgo/go/internal/poll/sockopt_linux.go | 16 +
libgo/go/internal/poll/sockopt_unix.go | 18 +
libgo/go/internal/poll/sockopt_windows.go | 25 +
libgo/go/internal/poll/sockoptip.go | 27 +
libgo/go/internal/poll/strconv.go | 41 +
libgo/go/internal/poll/sys_cloexec.go | 36 +
libgo/go/internal/poll/writev.go | 83 +
libgo/go/internal/poll/writev_test.go | 62 +
libgo/go/internal/testenv/testenv.go | 16 +
libgo/go/internal/testenv/testenv_windows.go | 1 -
libgo/go/internal/trace/parser.go | 221 +-
libgo/go/internal/trace/writer.go | 2 +-
libgo/go/io/example_test.go | 22 +
libgo/go/io/io.go | 4 +-
libgo/go/io/ioutil/example_test.go | 12 +
libgo/go/io/ioutil/tempfile_test.go | 13 +-
libgo/go/io/multi_test.go | 24 +-
libgo/go/log/log.go | 20 +-
libgo/go/log/log_test.go | 10 +
libgo/go/log/syslog/syslog.go | 15 +-
libgo/go/math/acosh.go | 7 +
libgo/go/math/all_test.go | 347 +-
libgo/go/math/arith_s390x.go | 48 +
libgo/go/math/arith_s390x_test.go | 298 ++
libgo/go/math/asinh.go | 7 +
libgo/go/math/atanh.go | 7 +
libgo/go/math/big/arith.go | 63 +-
libgo/go/math/big/arith_decl.go | 1 -
libgo/go/math/big/arith_decl_pure.go | 4 -
libgo/go/math/big/arith_s390x_test.go | 2 +-
libgo/go/math/big/arith_test.go | 29 -
libgo/go/math/big/float.go | 20 +-
libgo/go/math/big/float_test.go | 28 +
libgo/go/math/big/floatconv_test.go | 29 +-
libgo/go/math/big/int.go | 36 +-
libgo/go/math/big/int_test.go | 125 +-
libgo/go/math/big/nat.go | 63 +-
libgo/go/math/big/nat_test.go | 30 -
libgo/go/math/big/natconv.go | 3 +-
libgo/go/math/big/natconv_test.go | 8 +
libgo/go/math/big/prime_test.go | 2 +-
libgo/go/math/big/ratconv.go | 4 +-
libgo/go/math/bits/bits.go | 330 ++
libgo/go/math/bits/bits_tables.go | 83 +
libgo/go/math/bits/bits_test.go | 747 ++++
libgo/go/math/bits/example_test.go | 80 +
libgo/go/math/bits/make_tables.go | 92 +
libgo/go/math/cbrt.go | 7 +
libgo/go/math/const.go | 2 +
libgo/go/math/erf.go | 14 +
libgo/go/math/example_test.go | 20 +
libgo/go/math/export_s390x_test.go | 17 +
libgo/go/math/floor_asm.go | 5 +-
libgo/go/math/jn.go | 6 +-
libgo/go/math/pow.go | 7 +
libgo/go/math/pow10.go | 56 +-
libgo/go/math/rand/rand.go | 3 +-
libgo/go/math/sincos.go | 6 +-
libgo/go/math/sincos_386.go | 15 +
libgo/go/mime/encodedword.go | 20 +-
libgo/go/mime/encodedword_test.go | 3 +
libgo/go/mime/mediatype.go | 10 +-
libgo/go/mime/mediatype_test.go | 18 +-
libgo/go/mime/multipart/formdata.go | 26 +-
libgo/go/mime/multipart/formdata_test.go | 48 +-
libgo/go/mime/multipart/writer.go | 11 +-
libgo/go/mime/multipart/writer_test.go | 19 +-
libgo/go/mime/type.go | 108 +-
libgo/go/mime/type_test.go | 40 +
libgo/go/net/cgo_unix.go | 4 +-
libgo/go/net/dial.go | 168 +-
libgo/go/net/dial_test.go | 118 +-
libgo/go/net/dnsclient_unix.go | 118 +-
libgo/go/net/dnsclient_unix_test.go | 620 ++-
libgo/go/net/error_posix.go | 21 +
libgo/go/net/error_test.go | 42 +-
libgo/go/net/external_test.go | 4 +-
libgo/go/net/fd_plan9.go | 152 +-
libgo/go/net/fd_poll_nacl.go | 89 -
libgo/go/net/fd_posix.go | 21 -
libgo/go/net/fd_posix_test.go | 57 -
libgo/go/net/fd_unix.go | 351 +-
libgo/go/net/fd_windows.go | 568 +--
libgo/go/net/file_test.go | 4 +-
libgo/go/net/file_unix.go | 9 +-
libgo/go/net/hook_unix.go | 10 +-
libgo/go/net/hook_windows.go | 9 +-
libgo/go/net/http/cgi/host_test.go | 2 +-
libgo/go/net/http/cgi/posix_test.go | 3 +-
libgo/go/net/http/client.go | 47 +-
libgo/go/net/http/client_test.go | 185 +-
libgo/go/net/http/clientserver_test.go | 27 +
libgo/go/net/http/cookie.go | 2 +-
libgo/go/net/http/cookie_test.go | 9 +-
libgo/go/net/http/cookiejar/jar.go | 5 +-
libgo/go/net/http/cookiejar/jar_test.go | 57 +-
libgo/go/net/http/export_test.go | 33 +-
libgo/go/net/http/fcgi/child.go | 56 +
libgo/go/net/http/fcgi/fcgi.go | 2 +-
libgo/go/net/http/fcgi/fcgi_test.go | 66 +
libgo/go/net/http/filetransport_test.go | 1 +
libgo/go/net/http/fs.go | 50 +-
libgo/go/net/http/fs_test.go | 74 +-
libgo/go/net/http/h2_bundle.go | 2349 +++++++---
libgo/go/net/http/httptest/recorder.go | 3 +-
libgo/go/net/http/httptest/recorder_test.go | 13 +-
libgo/go/net/http/httptest/server.go | 47 +-
libgo/go/net/http/httptest/server_test.go | 118 +-
libgo/go/net/http/httputil/reverseproxy.go | 48 +-
libgo/go/net/http/httputil/reverseproxy_test.go | 133 +-
libgo/go/net/http/main_test.go | 23 +-
libgo/go/net/http/npn_test.go | 24 +-
libgo/go/net/http/pprof/pprof.go | 51 +-
libgo/go/net/http/proxy_test.go | 8 +-
libgo/go/net/http/request.go | 63 +-
libgo/go/net/http/request_test.go | 23 +
libgo/go/net/http/response.go | 35 +-
libgo/go/net/http/response_test.go | 51 +-
libgo/go/net/http/serve_test.go | 483 ++-
libgo/go/net/http/server.go | 302 +-
libgo/go/net/http/sniff.go | 4 +-
libgo/go/net/http/sniff_test.go | 4 +
libgo/go/net/http/transfer.go | 32 +-
libgo/go/net/http/transport.go | 255 +-
libgo/go/net/http/transport_internal_test.go | 31 +-
libgo/go/net/http/transport_test.go | 745 ++--
libgo/go/net/interface.go | 16 +-
libgo/go/net/interface_linux.go | 4 +-
libgo/go/net/interface_test.go | 6 +-
libgo/go/net/interface_windows.go | 5 +-
libgo/go/net/internal/socktest/sys_cloexec.go | 4 +-
libgo/go/net/internal/socktest/sys_unix.go | 12 +-
libgo/go/net/ip.go | 24 +-
libgo/go/net/ip_test.go | 182 +-
libgo/go/net/iprawsock.go | 103 +-
libgo/go/net/iprawsock_posix.go | 10 +-
libgo/go/net/iprawsock_test.go | 72 +
libgo/go/net/ipsock.go | 100 +-
libgo/go/net/ipsock_plan9.go | 37 +-
libgo/go/net/ipsock_posix.go | 129 +-
libgo/go/net/ipsock_test.go | 2 +-
libgo/go/net/listen_test.go | 16 +-
libgo/go/net/lookup.go | 44 +-
libgo/go/net/lookup_test.go | 22 +-
libgo/go/net/lookup_unix.go | 86 +-
libgo/go/net/lookup_windows.go | 2 +-
libgo/go/net/mail/message.go | 28 +-
libgo/go/net/mail/message_test.go | 11 +
libgo/go/net/main_cloexec_test.go | 10 +-
libgo/go/net/main_test.go | 16 +-
libgo/go/net/main_unix_test.go | 16 +-
libgo/go/net/main_windows_test.go | 22 +-
libgo/go/net/mockserver_test.go | 16 +-
libgo/go/net/net.go | 29 +-
libgo/go/net/net_test.go | 14 +-
libgo/go/net/platform_test.go | 14 +-
libgo/go/net/port_unix.go | 3 +-
libgo/go/net/rawconn.go | 62 +
libgo/go/net/rawconn_unix_test.go | 94 +
libgo/go/net/rawconn_windows_test.go | 36 +
libgo/go/net/rpc/debug.go | 23 +-
libgo/go/net/rpc/jsonrpc/all_test.go | 58 +
libgo/go/net/rpc/jsonrpc/client.go | 3 +-
libgo/go/net/rpc/server.go | 36 +-
libgo/go/net/rpc/server_test.go | 67 +-
libgo/go/net/sendfile_bsd.go | 67 +
libgo/go/net/sendfile_dragonfly.go | 106 -
libgo/go/net/sendfile_freebsd.go | 106 -
libgo/go/net/sendfile_linux.go | 46 +-
libgo/go/net/sendfile_solaris.go | 62 +-
libgo/go/net/sendfile_windows.go | 14 +-
libgo/go/net/smtp/smtp.go | 2 +-
libgo/go/net/smtp/smtp_test.go | 5 +
libgo/go/net/sock_cloexec.go | 43 +-
libgo/go/net/sock_posix.go | 38 +-
libgo/go/net/sockopt_bsd.go | 2 +-
libgo/go/net/sockopt_posix.go | 34 +-
libgo/go/net/sockoptip_bsd.go | 20 +-
libgo/go/net/sockoptip_linux.go | 18 +-
libgo/go/net/sockoptip_posix.go | 34 +-
libgo/go/net/sockoptip_windows.go | 17 +-
libgo/go/net/sys_cloexec.go | 27 +-
libgo/go/net/tcpsock.go | 90 +-
libgo/go/net/tcpsock_plan9.go | 3 +
libgo/go/net/tcpsock_posix.go | 2 +-
libgo/go/net/tcpsock_test.go | 12 +-
libgo/go/net/tcpsock_unix_test.go | 39 +-
libgo/go/net/tcpsockopt_darwin.go | 14 +-
libgo/go/net/tcpsockopt_dragonfly.go | 14 +-
libgo/go/net/tcpsockopt_posix.go | 10 +-
libgo/go/net/tcpsockopt_solaris.go | 14 +-
libgo/go/net/tcpsockopt_unix.go | 14 +-
libgo/go/net/tcpsockopt_windows.go | 8 +-
libgo/go/net/timeout_test.go | 21 +-
libgo/go/net/udpsock.go | 148 +-
libgo/go/net/udpsock_posix.go | 6 +-
libgo/go/net/udpsock_test.go | 4 +-
libgo/go/net/unixsock.go | 108 +-
libgo/go/net/url/url.go | 23 +-
libgo/go/net/writev_test.go | 7 +-
libgo/go/net/writev_unix.go | 74 +-
libgo/go/os/error_posix.go | 18 +
libgo/go/os/example_test.go | 16 +-
libgo/go/os/exec/env_test.go | 39 +
libgo/go/os/exec/exec.go | 67 +-
libgo/go/os/exec/exec_posix_test.go | 83 +
libgo/go/os/exec/exec_test.go | 156 +-
libgo/go/os/exec/{exec_posix.go => exec_unix.go} | 2 +-
libgo/go/os/exec/exec_windows.go | 23 +
libgo/go/os/exec_windows.go | 80 +-
libgo/go/os/executable.go | 3 +-
libgo/go/os/executable_path.go | 40 +-
libgo/go/os/executable_procfs.go | 4 +-
libgo/go/os/executable_test.go | 9 +-
libgo/go/os/export_windows_test.go | 6 +-
libgo/go/os/file.go | 99 +-
libgo/go/os/file_plan9.go | 54 +-
libgo/go/os/file_posix.go | 60 +-
libgo/go/os/file_unix.go | 155 +-
libgo/go/os/os_test.go | 379 +-
libgo/go/os/pipe_bsd.go | 4 +-
libgo/go/os/pipe_freebsd.go | 34 +
libgo/go/os/pipe_linux.go | 2 +-
libgo/go/os/pipe_test.go | 111 +-
libgo/go/os/proc.go | 11 +
libgo/go/os/signal/doc.go | 9 +-
libgo/go/os/signal/signal.go | 59 +-
libgo/go/os/signal/signal_test.go | 91 +
libgo/go/os/stat_unix.go | 2 +-
libgo/go/os/sys_darwin.go | 26 +-
libgo/go/os/types.go | 2 +-
libgo/go/os/types_unix.go | 2 -
libgo/go/os/types_windows.go | 36 +-
libgo/go/os/user/cgo_lookup_unix.go | 266 ++
libgo/go/os/user/lookup.go | 22 +-
libgo/go/os/user/lookup_android.go | 13 -
libgo/go/os/user/lookup_stubs.go | 38 +-
libgo/go/os/user/lookup_unix.go | 361 +-
libgo/go/os/user/lookup_unix_test.go | 276 ++
libgo/go/os/user/user_test.go | 12 +-
libgo/go/os/wait_unimp.go | 2 +-
libgo/go/os/wait_waitid.go | 5 +-
libgo/go/path/example_test.go | 40 +-
libgo/go/path/filepath/match_test.go | 4 +-
libgo/go/path/filepath/path.go | 9 +
libgo/go/path/filepath/path_test.go | 57 +-
libgo/go/path/path.go | 5 +-
libgo/go/plugin/plugin.go | 8 +-
libgo/go/plugin/plugin_dlopen.go | 52 +-
libgo/go/reflect/all_test.go | 292 +-
libgo/go/reflect/deepequal.go | 6 +
libgo/go/reflect/set_test.go | 18 +
libgo/go/reflect/type.go | 429 +-
libgo/go/reflect/value.go | 21 +-
libgo/go/regexp/all_test.go | 10 +-
libgo/go/regexp/exec.go | 6 +-
libgo/go/regexp/exec_test.go | 29 +
libgo/go/regexp/onepass.go | 42 +-
libgo/go/regexp/onepass_test.go | 22 +
libgo/go/regexp/regexp.go | 49 +-
libgo/go/regexp/syntax/parse.go | 4 +-
libgo/go/runtime/cgo_gccgo.go | 21 +-
libgo/go/runtime/cgocheck.go | 2 +-
libgo/go/runtime/chan.go | 12 +-
libgo/go/runtime/cpuprof.go | 501 +--
libgo/go/runtime/crash_cgo_test.go | 66 +-
libgo/go/runtime/crash_test.go | 138 +-
libgo/go/runtime/crash_unix_test.go | 30 +
libgo/go/runtime/debug/garbage.go | 4 +-
libgo/go/runtime/debug/garbage_test.go | 68 +-
libgo/go/runtime/env_posix.go | 2 +-
libgo/go/runtime/error.go | 37 +-
libgo/go/runtime/example_test.go | 54 +
libgo/go/runtime/export_test.go | 115 +-
libgo/go/runtime/export_unix_test.go | 19 +
libgo/go/runtime/extern.go | 21 +-
libgo/go/runtime/fastlog2.go | 6 -
libgo/go/runtime/float.go | 53 +
libgo/go/runtime/gc_test.go | 51 +
libgo/go/runtime/hashmap.go | 160 +-
libgo/go/runtime/hashmap_fast.go | 460 +-
libgo/go/runtime/heapdump.go | 4 +-
libgo/go/runtime/iface_test.go | 144 +
libgo/go/runtime/internal/sys/intrinsics.go | 8 +-
libgo/go/runtime/internal/sys/intrinsics_test.go | 12 +-
libgo/go/runtime/lfstack.go | 37 +-
libgo/go/runtime/lock_futex.go | 26 +-
libgo/go/runtime/lock_sema.go | 27 +-
libgo/go/runtime/malloc.go | 196 +-
libgo/go/runtime/malloc_test.go | 76 +-
libgo/go/runtime/map_test.go | 92 +
libgo/go/runtime/mapspeed_test.go | 15 +
libgo/go/runtime/mbarrier.go | 6 +
libgo/go/runtime/mbitmap.go | 80 +-
libgo/go/runtime/mcache.go | 15 +-
libgo/go/runtime/mcentral.go | 40 +-
libgo/go/runtime/mfinal.go | 18 +-
libgo/go/runtime/mfixalloc.go | 10 +-
libgo/go/runtime/mgc.go | 652 ++-
libgo/go/runtime/mgclarge.go | 326 ++
libgo/go/runtime/mgcmark.go | 133 +-
libgo/go/runtime/mgcsweep.go | 98 +-
libgo/go/runtime/mgcwork.go | 180 +-
libgo/go/runtime/mheap.go | 589 ++-
libgo/go/runtime/mksizeclasses.go | 2 +-
libgo/go/runtime/mprof.go | 221 +-
libgo/go/runtime/msize.go | 22 -
libgo/go/runtime/mstats.go | 113 +-
libgo/go/runtime/mstkbar.go | 395 --
libgo/go/runtime/net_plan9.go | 4 +-
libgo/go/runtime/netpoll.go | 91 +-
libgo/go/runtime/netpoll_epoll.go | 8 +-
libgo/go/runtime/netpoll_kqueue.go | 10 +-
libgo/go/runtime/netpoll_nacl.go | 4 +
libgo/go/runtime/netpoll_solaris.go | 18 +-
libgo/go/runtime/netpoll_stub.go | 2 +
libgo/go/runtime/netpoll_windows.go | 28 +-
libgo/go/runtime/numcpu_freebsd_test.go | 15 +
libgo/go/runtime/os_gccgo.go | 2 +-
libgo/go/runtime/panic.go | 23 +-
libgo/go/runtime/pprof/elf.go | 109 +
.../pprof/internal}/profile/encode.go | 0
.../pprof/internal}/profile/filter.go | 0
.../pprof/internal}/profile/legacy_profile.go | 0
.../pprof/internal}/profile/profile.go | 3 +
.../pprof/internal}/profile/profile_test.go | 0
.../pprof/internal}/profile/proto.go | 0
.../pprof/internal}/profile/proto_test.go | 0
.../pprof/internal}/profile/prune.go | 0
.../pprof/internal/protopprof/protomemprofile.go | 83 -
.../internal/protopprof/protomemprofile_test.go | 104 -
.../pprof/internal/protopprof/protopprof.go | 105 -
.../pprof/internal/protopprof/protopprof_test.go | 171 -
libgo/go/runtime/pprof/label.go | 85 +
libgo/go/runtime/pprof/label_test.go | 82 +
libgo/go/runtime/pprof/map.go | 89 +
libgo/go/runtime/pprof/mprof_test.go | 17 +-
libgo/go/runtime/pprof/pprof.go | 101 +-
libgo/go/runtime/pprof/pprof_test.go | 406 +-
libgo/go/runtime/pprof/proto.go | 515 +++
libgo/go/runtime/pprof/proto_test.go | 224 +
libgo/go/runtime/pprof/protobuf.go | 141 +
libgo/go/runtime/pprof/protomem.go | 93 +
libgo/go/runtime/pprof/protomem_test.go | 74 +
libgo/go/runtime/pprof/runtime.go | 36 +
libgo/go/runtime/pprof/runtime_test.go | 96 +
libgo/go/runtime/proc.go | 294 +-
libgo/go/runtime/proc_test.go | 17 +-
libgo/go/runtime/profbuf.go | 561 +++
libgo/go/runtime/profbuf_test.go | 182 +
libgo/go/runtime/proflabel.go | 40 +
libgo/go/runtime/rand_test.go | 45 +
libgo/go/runtime/relax_stub.go | 17 +
libgo/go/runtime/runtime1.go | 70 +-
libgo/go/runtime/runtime2.go | 67 +-
libgo/go/runtime/runtime_test.go | 18 +-
libgo/go/runtime/rwmutex.go | 125 +
libgo/go/runtime/rwmutex_test.go | 178 +
libgo/go/runtime/select.go | 11 +-
libgo/go/runtime/sema.go | 328 +-
libgo/go/runtime/signal_sighandler.go | 2 +-
libgo/go/runtime/signal_unix.go | 137 +-
libgo/go/runtime/sigqueue.go | 63 +-
libgo/go/runtime/sizeclasses.go | 2 +-
libgo/go/runtime/string.go | 20 +-
libgo/go/runtime/string_test.go | 15 +
libgo/go/runtime/stubs.go | 62 +-
libgo/go/runtime/stubs_linux.go | 9 +
libgo/go/runtime/stubs_nonlinux.go | 12 +
libgo/go/runtime/symtab.go | 38 +-
libgo/go/runtime/symtab_test.go | 17 +-
.../go/runtime/testdata/testprog/numcpu_freebsd.go | 126 +
libgo/go/runtime/testdata/testprog/panicrace.go | 27 +
libgo/go/runtime/testdata/testprogcgo/cgo.go | 8 +-
.../runtime/testdata/testprogcgo/numgoroutine.go | 99 +
.../go/runtime/testdata/testprognet/signalexec.go | 70 +
libgo/go/runtime/time.go | 15 +-
libgo/go/runtime/timeasm.go | 17 +
libgo/go/runtime/timestub.go | 21 +
libgo/go/runtime/trace.go | 158 +-
libgo/go/runtime/trace/trace_stack_test.go | 7 +-
libgo/go/runtime/traceback_gccgo.go | 11 +-
libgo/go/runtime/write_err_android.go | 2 +-
libgo/go/sort/example_test.go | 35 +
libgo/go/sort/genzfunc.go | 4 +
libgo/go/sort/search.go | 4 +-
libgo/go/sort/sort.go | 19 +-
libgo/go/sort/zfuncversion.go | 10 +-
libgo/go/strconv/atof_test.go | 10 +-
libgo/go/strconv/decimal.go | 4 +-
libgo/go/strconv/itoa.go | 111 +-
libgo/go/strconv/itoa_test.go | 78 +-
libgo/go/strconv/quote.go | 6 +-
libgo/go/strings/example_test.go | 47 +
libgo/go/strings/replace_test.go | 41 +
libgo/go/strings/strings.go | 274 +-
libgo/go/strings/strings_amd64.go | 43 +-
libgo/go/strings/strings_generic.go | 22 +-
libgo/go/strings/strings_s390x.go | 32 +-
libgo/go/strings/strings_test.go | 103 +-
libgo/go/sync/atomic/atomic_test.go | 24 +-
libgo/go/sync/atomic/doc.go | 4 +-
libgo/go/sync/atomic/value.go | 1 -
libgo/go/sync/cond.go | 1 -
libgo/go/sync/export_test.go | 2 +
libgo/go/sync/map.go | 375 ++
libgo/go/sync/map_bench_test.go | 215 +
libgo/go/sync/map_reference_test.go | 151 +
libgo/go/sync/map_test.go | 170 +
libgo/go/sync/mutex.go | 152 +-
libgo/go/sync/mutex_test.go | 35 +-
libgo/go/sync/pool.go | 14 +-
libgo/go/sync/pool_test.go | 11 +
libgo/go/sync/runtime.go | 8 +-
libgo/go/sync/runtime_sema_test.go | 6 +-
libgo/go/sync/rwmutex.go | 25 +-
libgo/go/sync/rwmutex_test.go | 3 +
libgo/go/sync/waitgroup.go | 4 +-
libgo/go/sync/waitgroup_test.go | 26 +-
libgo/go/syscall/errors_plan9.go | 1 +
libgo/go/syscall/exec_bsd.go | 42 +-
libgo/go/syscall/exec_freebsd.go | 25 +
libgo/go/syscall/exec_linux.go | 149 +-
libgo/go/syscall/exec_linux_test.go | 305 +-
libgo/go/syscall/exec_unix.go | 18 +-
libgo/go/syscall/forkpipe_bsd.go | 20 +
libgo/go/syscall/net.go | 34 +
libgo/go/syscall/syscall.go | 13 +-
libgo/go/syscall/syscall_dragonfly.go | 4 +-
libgo/go/syscall/syscall_linux_386.go | 4 +
libgo/go/syscall/syscall_linux_amd64.go | 2 +
libgo/go/syscall/syscall_linux_mipsx.go | 4 +
libgo/go/syscall/syscall_linux_s390x.go | 4 +
libgo/go/syscall/syscall_unix_test.go | 8 +-
libgo/go/testing/benchmark.go | 44 +-
libgo/go/testing/helper_test.go | 70 +
libgo/go/testing/helperfuncs_test.go | 67 +
libgo/go/testing/internal/testdeps/deps.go | 7 +
libgo/go/testing/match.go | 9 +-
libgo/go/testing/match_test.go | 67 +-
libgo/go/testing/quick/quick.go | 30 +-
libgo/go/testing/quick/quick_test.go | 18 +
libgo/go/testing/sub_test.go | 93 +-
libgo/go/testing/testing.go | 188 +-
libgo/go/text/scanner/example_test.go | 35 +-
libgo/go/text/scanner/scanner.go | 5 +-
libgo/go/text/template/doc.go | 18 +-
libgo/go/text/template/exec.go | 10 +-
libgo/go/text/template/exec_test.go | 3 +
libgo/go/text/template/funcs.go | 5 +-
libgo/go/text/template/parse/lex_test.go | 4 +-
libgo/go/text/template/parse/parse.go | 1 -
libgo/go/text/template/template.go | 1 +
libgo/go/time/example_test.go | 3 +
libgo/go/time/export_test.go | 13 +
libgo/go/time/format.go | 50 +-
libgo/go/time/format_test.go | 4 +-
libgo/go/time/genzabbrs.go | 4 +-
libgo/go/time/mono_test.go | 261 ++
libgo/go/time/sleep_test.go | 4 +-
libgo/go/time/sys_plan9.go | 4 +
libgo/go/time/sys_unix.go | 4 +
libgo/go/time/sys_windows.go | 4 +
libgo/go/time/time.go | 397 +-
libgo/go/time/time_test.go | 74 +
libgo/go/time/zoneinfo.go | 34 +-
libgo/go/time/zoneinfo_abbrs_windows.go | 176 +-
libgo/go/time/zoneinfo_plan9.go | 2 +-
libgo/go/time/zoneinfo_read.go | 13 +-
libgo/go/time/zoneinfo_test.go | 50 +-
libgo/go/time/zoneinfo_windows.go | 2 +-
libgo/go/unicode/letter.go | 4 +-
libgo/go/unicode/tables.go | 63 +-
libgo/godeps.sh | 3 +-
libgo/match.sh | 8 +-
libgo/merge.sh | 2 +-
libgo/misc/cgo/errors/issue18452.go | 18 +
libgo/misc/cgo/errors/issue18889.go | 7 +
libgo/misc/cgo/errors/ptr.go | 8 +
libgo/misc/cgo/errors/test.bash | 4 +-
libgo/misc/cgo/fortran/test.bash | 2 +-
libgo/misc/cgo/test/cgo_test.go | 4 +
libgo/misc/cgo/test/issue18720.go | 28 +
libgo/misc/cgo/test/issue20129.go | 33 +
libgo/misc/cgo/test/issue20266.go | 21 +
libgo/misc/cgo/test/issue20266/issue20266.h | 9 +
libgo/misc/cgo/test/issue20369.go | 20 +
libgo/misc/cgo/test/issue6612.go | 17 +-
libgo/misc/cgo/testcarchive/carchive_test.go | 170 +-
libgo/misc/cgo/testcarchive/main2.c | 35 +-
libgo/misc/cgo/testcarchive/main3.c | 34 +
libgo/misc/cgo/testcarchive/main5.c | 18 +
libgo/misc/cgo/testcarchive/main6.c | 34 +
libgo/misc/cgo/testcarchive/src/libgo2/libgo2.go | 30 +
libgo/misc/cgo/testcarchive/src/libgo3/libgo3.go | 12 +
libgo/misc/cgo/testcarchive/src/libgo6/sigprof.go | 25 +
libgo/misc/cgo/testcshared/main0.c | 6 +
libgo/misc/cgo/testcshared/src/p/p.go | 3 +
libgo/misc/cgo/testcshared/test.bash | 20 +-
libgo/misc/cgo/testplugin/src/issue19534/main.go | 23 +
libgo/misc/cgo/testplugin/src/issue19534/plugin.go | 9 +
libgo/misc/cgo/testplugin/test.bash | 8 +-
libgo/misc/cgo/testplugin/unnamed1.go | 11 +
libgo/misc/cgo/testplugin/unnamed2.go | 9 +
libgo/misc/cgo/testsanitizers/test.bash | 57 +-
libgo/misc/cgo/testsanitizers/tsan10.go | 31 +
libgo/misc/cgo/testsanitizers/tsan11.go | 55 +
libgo/misc/cgo/testsanitizers/tsan12.go | 35 +
libgo/misc/cgo/testsanitizers/tsan_shared.go | 63 +
libgo/misc/cgo/testshared/shared_test.go | 20 +-
libgo/misc/cgo/testshared/src/division/division.go | 17 +
libgo/runtime/go-now.c | 15 +-
libgo/runtime/proc.c | 6 +
libgo/runtime/runtime.h | 51 -
libgo/runtime/runtime_c.c | 26 +-
libgo/testsuite/gotest | 8 +-
985 files changed, 56840 insertions(+), 20397 deletions(-)
delete mode 100644 libgo/go/cmd/go/build_test.go
delete mode 100644 libgo/go/cmd/go/env.go
create mode 100644 libgo/go/cmd/go/internal/base/base.go
create mode 100644 libgo/go/cmd/go/internal/base/env.go
create mode 100644 libgo/go/cmd/go/internal/base/flag.go
create mode 100644 libgo/go/cmd/go/internal/base/path.go
rename libgo/go/cmd/go/{ => internal/base}/signal.go (66%)
rename libgo/go/cmd/go/{ => internal/base}/signal_notunix.go (60%)
rename libgo/go/cmd/go/{ => internal/base}/signal_unix.go (75%)
create mode 100644 libgo/go/cmd/go/internal/base/tool.go
rename libgo/go/cmd/go/{ => internal/bug}/bug.go (88%)
create mode 100644 libgo/go/cmd/go/internal/buildid/buildid.go
rename libgo/go/cmd/go/{ => internal/buildid}/note.go (98%)
create mode 100644 libgo/go/cmd/go/internal/cfg/cfg.go
rename libgo/go/cmd/go/{ => internal/clean}/clean.go (81%)
create mode 100644 libgo/go/cmd/go/internal/cmdflag/flag.go
rename libgo/go/cmd/go/{ => internal/doc}/doc.go (79%)
create mode 100644 libgo/go/cmd/go/internal/envcmd/env.go
rename libgo/go/cmd/go/{ => internal/fix}/fix.go (60%)
rename libgo/go/cmd/go/{ => internal/fmtcmd}/fmt.go (61%)
rename libgo/go/cmd/go/{ => internal/generate}/generate.go (91%)
rename libgo/go/cmd/go/{ => internal/generate}/generate_test.go (98%)
rename libgo/go/cmd/go/{ => internal/get}/discovery.go (89%)
rename libgo/go/cmd/go/{ => internal/get}/get.go (75%)
create mode 100644 libgo/go/cmd/go/internal/get/pkg_test.go
rename libgo/go/cmd/go/{ => internal/get}/tag_test.go (99%)
rename libgo/go/cmd/go/{ => internal/get}/vcs.go (94%)
rename libgo/go/cmd/go/{ => internal/get}/vcs_test.go (94%)
create mode 100644 libgo/go/cmd/go/internal/help/help.go
rename libgo/go/cmd/go/{help.go => internal/help/helpdoc.go} (90%)
rename libgo/go/cmd/go/{ => internal/list}/context.go (99%)
rename libgo/go/cmd/go/{ => internal/list}/list.go (85%)
create mode 100644 libgo/go/cmd/go/internal/load/match_test.go
create mode 100644 libgo/go/cmd/go/internal/load/path.go
rename libgo/go/cmd/go/{ => internal/load}/pkg.go (76%)
create mode 100644 libgo/go/cmd/go/internal/load/search.go
rename libgo/go/cmd/go/{ => internal/load}/testgo.go (97%)
rename libgo/go/cmd/go/{ => internal/run}/run.go (52%)
create mode 100644 libgo/go/cmd/go/internal/str/str.go
rename libgo/go/cmd/go/{ => internal/test}/test.go (71%)
create mode 100644 libgo/go/cmd/go/internal/test/testflag.go
rename libgo/go/cmd/go/{ => internal/tool}/tool.go (58%)
rename libgo/go/cmd/go/{ => internal/version}/version.go (72%)
create mode 100644 libgo/go/cmd/go/internal/vet/vet.go
create mode 100644 libgo/go/cmd/go/internal/vet/vetflag.go
rename libgo/go/cmd/go/{ => internal/web}/bootstrap.go (55%)
rename libgo/go/cmd/go/{ => internal/web}/http.go (74%)
create mode 100644 libgo/go/cmd/go/internal/web/security.go
rename libgo/go/cmd/go/{ => internal/work}/build.go (64%)
create mode 100644 libgo/go/cmd/go/internal/work/build_test.go
create mode 100644 libgo/go/cmd/go/internal/work/testgo.go
delete mode 100644 libgo/go/cmd/go/match_test.go
delete mode 100644 libgo/go/cmd/go/pkg_test.go
delete mode 100644 libgo/go/cmd/go/script
delete mode 100644 libgo/go/cmd/go/script.txt
delete mode 100644 libgo/go/cmd/go/test.bash
create mode 100644 libgo/go/cmd/go/testdata/src/bench/x_test.go
create mode 100644 libgo/go/cmd/go/testdata/src/cgoasm/p.go
create mode 100644 libgo/go/cmd/go/testdata/src/cgoasm/p.s
create mode 100644 libgo/go/cmd/go/testdata/src/exclude/empty/x.txt
create mode 100644 libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go
create mode 100644 libgo/go/cmd/go/testdata/src/exclude/x.go
create mode 100644 libgo/go/cmd/go/testdata/src/exclude/x_linux.go
create mode 100644 libgo/go/cmd/go/testdata/src/testlist/bench_test.go
create mode 100644 libgo/go/cmd/go/testdata/src/testlist/example_test.go
create mode 100644 libgo/go/cmd/go/testdata/src/testlist/test_test.go
create mode 100644 libgo/go/cmd/go/testdata/src/testregexp/x_test.go
create mode 100644 libgo/go/cmd/go/testdata/src/testregexp/z_test.go
delete mode 100644 libgo/go/cmd/go/testflag.go
delete mode 100644 libgo/go/cmd/go/vet.go
create mode 100644 libgo/go/cmd/internal/objabi/autotype.go
create mode 100644 libgo/go/cmd/internal/objabi/doc.go
create mode 100644 libgo/go/cmd/internal/objabi/flag.go
create mode 100644 libgo/go/cmd/internal/objabi/funcdata.go
create mode 100644 libgo/go/cmd/internal/objabi/head.go
create mode 100644 libgo/go/cmd/internal/objabi/line.go
create mode 100644 libgo/go/cmd/internal/objabi/path.go
create mode 100644 libgo/go/cmd/internal/objabi/path_test.go
create mode 100644 libgo/go/cmd/internal/objabi/reloctype.go
create mode 100644 libgo/go/cmd/internal/objabi/reloctype_string.go
create mode 100644 libgo/go/cmd/internal/objabi/stack.go
create mode 100644 libgo/go/cmd/internal/objabi/symkind.go
create mode 100644 libgo/go/cmd/internal/objabi/symkind_string.go
create mode 100644 libgo/go/cmd/internal/objabi/typekind.go
create mode 100644 libgo/go/cmd/internal/objabi/util.go
create mode 100644 libgo/go/cmd/internal/objabi/zbootstrap.go
delete mode 100644 libgo/go/compress/flate/reverse_bits.go
create mode 100644 libgo/go/crypto/aes/cipher_ppc64le.go
create mode 100644 libgo/go/crypto/sha256/sha256block_amd64.go
create mode 100644 libgo/go/crypto/sha512/sha512block_amd64.go
create mode 100644 libgo/go/crypto/x509/root_unix_test.go
create mode 100644 libgo/go/crypto/x509/test-file.crt
create mode 100644 libgo/go/crypto/x509/testdata/test-dir.crt
create mode 100644 libgo/go/debug/dwarf/export_test.go
create mode 100644 libgo/go/debug/dwarf/testdata/line-gcc-win.bin
create mode 100644 libgo/go/debug/pe/file_cgo_test.go
create mode 100644 libgo/go/go/internal/gcimporter/testdata/issue20046.go
create mode 100644 libgo/go/go/internal/srcimporter/srcimporter.go
create mode 100644 libgo/go/go/internal/srcimporter/srcimporter_test.go
create mode 100644 libgo/go/go/types/object_test.go
rename libgo/go/golang_org/x/crypto/chacha20poly1305/{chacha20poly1305_test_vectors.go => chacha20poly1305_vectors_test.go} (100%)
create mode 100644 libgo/go/golang_org/x/net/http2/hpack/tables_test.go
create mode 100644 libgo/go/golang_org/x/net/idna/tables.go
create mode 100644 libgo/go/golang_org/x/net/idna/trie.go
create mode 100644 libgo/go/golang_org/x/net/idna/trieval.go
create mode 100644 libgo/go/golang_org/x/net/lif/sys.go
create mode 100644 libgo/go/golang_org/x/net/nettest/conntest.go
create mode 100644 libgo/go/golang_org/x/net/nettest/conntest_go16.go
create mode 100644 libgo/go/golang_org/x/net/nettest/conntest_go17.go
create mode 100644 libgo/go/golang_org/x/net/nettest/conntest_test.go
create mode 100644 libgo/go/golang_org/x/net/proxy/direct.go
create mode 100644 libgo/go/golang_org/x/net/proxy/per_host.go
create mode 100644 libgo/go/golang_org/x/net/proxy/per_host_test.go
create mode 100644 libgo/go/golang_org/x/net/proxy/proxy.go
create mode 100644 libgo/go/golang_org/x/net/proxy/proxy_test.go
create mode 100644 libgo/go/golang_org/x/net/proxy/socks5.go
create mode 100644 libgo/go/golang_org/x/text/secure/bidirule/bidirule.go
create mode 100644 libgo/go/golang_org/x/text/secure/doc.go
create mode 100644 libgo/go/golang_org/x/text/transform/examples_test.go
create mode 100644 libgo/go/golang_org/x/text/unicode/bidi/bidi.go
create mode 100644 libgo/go/golang_org/x/text/unicode/bidi/bracket.go
create mode 100644 libgo/go/golang_org/x/text/unicode/bidi/core.go
create mode 100644 libgo/go/golang_org/x/text/unicode/bidi/example_test.go
create mode 100644 libgo/go/golang_org/x/text/unicode/bidi/prop.go
create mode 100644 libgo/go/golang_org/x/text/unicode/bidi/tables.go
create mode 100644 libgo/go/golang_org/x/text/unicode/bidi/trieval.go
create mode 100644 libgo/go/golang_org/x/text/unicode/doc.go
create mode 100644 libgo/go/golang_org/x/text/unicode/norm/example_iter_test.go
create mode 100644 libgo/go/golang_org/x/text/unicode/norm/example_test.go
create mode 100644 libgo/go/hash/crc32/crc32_arm64.go
create mode 100644 libgo/go/hash/crc32/crc32_ppc64le.go
create mode 100644 libgo/go/hash/crc32/gen_const_ppc64le.go
create mode 100644 libgo/go/internal/cpu/cpu.go
create mode 100644 libgo/go/internal/cpu/cpu_arm.go
create mode 100644 libgo/go/internal/cpu/cpu_arm64.go
create mode 100644 libgo/go/internal/cpu/cpu_mips.go
create mode 100644 libgo/go/internal/cpu/cpu_mips64.go
create mode 100644 libgo/go/internal/cpu/cpu_mips64le.go
create mode 100644 libgo/go/internal/cpu/cpu_mipsle.go
create mode 100644 libgo/go/internal/cpu/cpu_ppc64.go
create mode 100644 libgo/go/internal/cpu/cpu_ppc64le.go
create mode 100644 libgo/go/internal/cpu/cpu_s390x.go
create mode 100644 libgo/go/internal/cpu/cpu_test.go
create mode 100644 libgo/go/internal/cpu/cpu_x86.go
create mode 100644 libgo/go/internal/poll/export_posix_test.go
create mode 100644 libgo/go/internal/poll/export_test.go
create mode 100644 libgo/go/internal/poll/fd.go
rename libgo/go/{net => internal/poll}/fd_io_plan9.go (91%)
rename libgo/go/{net => internal/poll}/fd_mutex.go (89%)
rename libgo/go/{net => internal/poll}/fd_mutex_test.go (67%)
create mode 100644 libgo/go/internal/poll/fd_plan9.go
create mode 100644 libgo/go/internal/poll/fd_poll_nacl.go
rename libgo/go/{net => internal/poll}/fd_poll_runtime.go (52%)
create mode 100644 libgo/go/internal/poll/fd_posix.go
create mode 100644 libgo/go/internal/poll/fd_posix_test.go
create mode 100644 libgo/go/internal/poll/fd_unix.go
create mode 100644 libgo/go/internal/poll/fd_windows.go
rename libgo/go/{net => internal/poll}/hook_cloexec.go (50%)
create mode 100644 libgo/go/internal/poll/hook_unix.go
create mode 100644 libgo/go/internal/poll/hook_windows.go
create mode 100644 libgo/go/internal/poll/sendfile_bsd.go
create mode 100644 libgo/go/internal/poll/sendfile_linux.go
create mode 100644 libgo/go/internal/poll/sendfile_solaris.go
create mode 100644 libgo/go/internal/poll/sendfile_windows.go
create mode 100644 libgo/go/internal/poll/sock_cloexec.go
create mode 100644 libgo/go/internal/poll/sockopt.go
create mode 100644 libgo/go/internal/poll/sockopt_linux.go
create mode 100644 libgo/go/internal/poll/sockopt_unix.go
create mode 100644 libgo/go/internal/poll/sockopt_windows.go
create mode 100644 libgo/go/internal/poll/sockoptip.go
create mode 100644 libgo/go/internal/poll/strconv.go
create mode 100644 libgo/go/internal/poll/sys_cloexec.go
create mode 100644 libgo/go/internal/poll/writev.go
create mode 100644 libgo/go/internal/poll/writev_test.go
create mode 100644 libgo/go/math/bits/bits.go
create mode 100644 libgo/go/math/bits/bits_tables.go
create mode 100644 libgo/go/math/bits/bits_test.go
create mode 100644 libgo/go/math/bits/example_test.go
create mode 100644 libgo/go/math/bits/make_tables.go
create mode 100644 libgo/go/math/example_test.go
create mode 100644 libgo/go/math/sincos_386.go
create mode 100644 libgo/go/net/error_posix.go
delete mode 100644 libgo/go/net/fd_poll_nacl.go
delete mode 100644 libgo/go/net/fd_posix.go
delete mode 100644 libgo/go/net/fd_posix_test.go
create mode 100644 libgo/go/net/rawconn.go
create mode 100644 libgo/go/net/rawconn_unix_test.go
create mode 100644 libgo/go/net/rawconn_windows_test.go
create mode 100644 libgo/go/net/sendfile_bsd.go
delete mode 100644 libgo/go/net/sendfile_dragonfly.go
delete mode 100644 libgo/go/net/sendfile_freebsd.go
create mode 100644 libgo/go/os/error_posix.go
create mode 100644 libgo/go/os/exec/env_test.go
create mode 100644 libgo/go/os/exec/exec_posix_test.go
rename libgo/go/os/exec/{exec_posix.go => exec_unix.go} (95%)
create mode 100644 libgo/go/os/exec/exec_windows.go
create mode 100644 libgo/go/os/pipe_freebsd.go
create mode 100644 libgo/go/os/user/cgo_lookup_unix.go
create mode 100644 libgo/go/os/user/lookup_unix_test.go
create mode 100644 libgo/go/runtime/example_test.go
create mode 100644 libgo/go/runtime/export_unix_test.go
create mode 100644 libgo/go/runtime/float.go
create mode 100644 libgo/go/runtime/mgclarge.go
delete mode 100644 libgo/go/runtime/mstkbar.go
create mode 100644 libgo/go/runtime/numcpu_freebsd_test.go
create mode 100644 libgo/go/runtime/pprof/elf.go
rename libgo/go/{internal/pprof => runtime/pprof/internal}/profile/encode.go (100%)
rename libgo/go/{internal/pprof => runtime/pprof/internal}/profile/filter.go (100%)
rename libgo/go/{internal/pprof => runtime/pprof/internal}/profile/legacy_profile.go (100%)
rename libgo/go/{internal/pprof => runtime/pprof/internal}/profile/profile.go (99%)
rename libgo/go/{internal/pprof => runtime/pprof/internal}/profile/profile_test.go (100%)
rename libgo/go/{internal/pprof => runtime/pprof/internal}/profile/proto.go (100%)
rename libgo/go/{internal/pprof => runtime/pprof/internal}/profile/proto_test.go (100%)
rename libgo/go/{internal/pprof => runtime/pprof/internal}/profile/prune.go (100%)
delete mode 100644 libgo/go/runtime/pprof/internal/protopprof/protomemprofile.go
delete mode 100644 libgo/go/runtime/pprof/internal/protopprof/protomemprofile_test.go
delete mode 100644 libgo/go/runtime/pprof/internal/protopprof/protopprof.go
delete mode 100644 libgo/go/runtime/pprof/internal/protopprof/protopprof_test.go
create mode 100644 libgo/go/runtime/pprof/label.go
create mode 100644 libgo/go/runtime/pprof/label_test.go
create mode 100644 libgo/go/runtime/pprof/map.go
create mode 100644 libgo/go/runtime/pprof/proto.go
create mode 100644 libgo/go/runtime/pprof/proto_test.go
create mode 100644 libgo/go/runtime/pprof/protobuf.go
create mode 100644 libgo/go/runtime/pprof/protomem.go
create mode 100644 libgo/go/runtime/pprof/protomem_test.go
create mode 100644 libgo/go/runtime/pprof/runtime.go
create mode 100644 libgo/go/runtime/pprof/runtime_test.go
create mode 100644 libgo/go/runtime/profbuf.go
create mode 100644 libgo/go/runtime/profbuf_test.go
create mode 100644 libgo/go/runtime/proflabel.go
create mode 100644 libgo/go/runtime/rand_test.go
create mode 100644 libgo/go/runtime/relax_stub.go
create mode 100644 libgo/go/runtime/rwmutex.go
create mode 100644 libgo/go/runtime/rwmutex_test.go
create mode 100644 libgo/go/runtime/stubs_linux.go
create mode 100644 libgo/go/runtime/stubs_nonlinux.go
create mode 100644 libgo/go/runtime/testdata/testprog/numcpu_freebsd.go
create mode 100644 libgo/go/runtime/testdata/testprog/panicrace.go
create mode 100644 libgo/go/runtime/testdata/testprogcgo/numgoroutine.go
create mode 100644 libgo/go/runtime/testdata/testprognet/signalexec.go
create mode 100644 libgo/go/runtime/timeasm.go
create mode 100644 libgo/go/runtime/timestub.go
create mode 100644 libgo/go/sync/map.go
create mode 100644 libgo/go/sync/map_bench_test.go
create mode 100644 libgo/go/sync/map_reference_test.go
create mode 100644 libgo/go/sync/map_test.go
create mode 100644 libgo/go/syscall/exec_freebsd.go
create mode 100644 libgo/go/syscall/forkpipe_bsd.go
create mode 100644 libgo/go/syscall/net.go
create mode 100644 libgo/go/testing/helper_test.go
create mode 100644 libgo/go/testing/helperfuncs_test.go
create mode 100644 libgo/go/time/mono_test.go
create mode 100644 libgo/misc/cgo/errors/issue18452.go
create mode 100644 libgo/misc/cgo/errors/issue18889.go
create mode 100644 libgo/misc/cgo/test/issue18720.go
create mode 100644 libgo/misc/cgo/test/issue20129.go
create mode 100644 libgo/misc/cgo/test/issue20266.go
create mode 100644 libgo/misc/cgo/test/issue20266/issue20266.h
create mode 100644 libgo/misc/cgo/test/issue20369.go
create mode 100644 libgo/misc/cgo/testcarchive/main6.c
create mode 100644 libgo/misc/cgo/testcarchive/src/libgo6/sigprof.go
create mode 100644 libgo/misc/cgo/testplugin/src/issue19534/main.go
create mode 100644 libgo/misc/cgo/testplugin/src/issue19534/plugin.go
create mode 100644 libgo/misc/cgo/testsanitizers/tsan10.go
create mode 100644 libgo/misc/cgo/testsanitizers/tsan11.go
create mode 100644 libgo/misc/cgo/testsanitizers/tsan12.go
create mode 100644 libgo/misc/cgo/testsanitizers/tsan_shared.go
create mode 100644 libgo/misc/cgo/testshared/src/division/division.go
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index b07bce8..a1ccb2b 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-199f175f4239d1ca6d7e80d08639955d41c3b09f
+4e063a8eee636cce17aea48c7183e78431174de3
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug273.go b/gcc/testsuite/go.test/test/fixedbugs/bug273.go
index aabb912..c04f211 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug273.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug273.go
@@ -1,10 +1,10 @@
// run
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 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.
-// http://code.google.com/p/go/issues/detail?id=589
+// https://golang.org/issue/589
package main
@@ -48,15 +48,6 @@ func bigcap() {
g1 = make([]block, 10, big)
}
-var g3 map[block]block
-func badmapcap() {
- g3 = make(map[block]block, minus1)
-}
-
-func bigmapcap() {
- g3 = make(map[block]block, big)
-}
-
type cblock [1<<16-1]byte
var g4 chan cblock
@@ -78,8 +69,6 @@ func main() {
shouldfail(badcap, "badcap")
shouldfail(badcap1, "badcap1")
shouldfail(bigcap, "bigcap")
- shouldfail(badmapcap, "badmapcap")
- shouldfail(bigmapcap, "bigmapcap")
shouldfail(badchancap, "badchancap")
shouldfail(bigchancap, "bigchancap")
shouldfail(overflowchan, "overflowchan")
diff --git a/gotools/ChangeLog b/gotools/ChangeLog
index 0a84eef..8fac16e 100644
--- a/gotools/ChangeLog
+++ b/gotools/ChangeLog
@@ -1,3 +1,15 @@
+2017-09-14 Ian Lance Taylor
+
+ * Makefile.am (LIBGOTOOL): Define.
+ (go_cmd_go_files): Update for Go 1.9 release.
+ (go$(EXEEXT)): Depend on and link against $(LIBGOTOOL).
+ (CHECK_ENV): Add definition of shell variable fl.
+ (check-go-tool): Update for rearrangement of cmd/go sources in Go
+ 1.9 release. Echo failure message if test fails.
+ (check-runtime): Echo failure message if test fails.
+ (check-cgo-test, check-carchive-test): Likewise.
+ * Makefile.in: Rebuild.
+
2017-08-30 Ian Lance Taylor
* configure.ac: Substitute GOC_FOR_TARGET and GCC_FOR_TARGET.
diff --git a/gotools/Makefile.am b/gotools/Makefile.am
index 41a2c72..4f13ffe 100644
--- a/gotools/Makefile.am
+++ b/gotools/Makefile.am
@@ -28,6 +28,8 @@ STAMP = echo timestamp >
libgodir = ../$(target_noncanonical)/libgo
LIBGODEP = $(libgodir)/libgo.la
+LIBGOTOOL = $(libgodir)/libgotool.a
+
if NATIVE
# Use the compiler we just built.
GOCOMPILER = $(GOC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET)
@@ -48,34 +50,8 @@ libgomiscdir = $(srcdir)/../libgo/misc
go_cmd_go_files = \
$(cmdsrcdir)/go/alldocs.go \
- $(cmdsrcdir)/go/bug.go \
- $(cmdsrcdir)/go/build.go \
- $(cmdsrcdir)/go/clean.go \
- $(cmdsrcdir)/go/context.go \
- $(cmdsrcdir)/go/discovery.go \
- $(cmdsrcdir)/go/doc.go \
- $(cmdsrcdir)/go/env.go \
- $(cmdsrcdir)/go/fix.go \
- $(cmdsrcdir)/go/fmt.go \
- $(cmdsrcdir)/go/generate.go \
- $(cmdsrcdir)/go/get.go \
$(cmdsrcdir)/go/go11.go \
- $(cmdsrcdir)/go/help.go \
- $(cmdsrcdir)/go/http.go \
- $(cmdsrcdir)/go/list.go \
- $(cmdsrcdir)/go/main.go \
- $(cmdsrcdir)/go/note.go \
- $(cmdsrcdir)/go/pkg.go \
- $(cmdsrcdir)/go/run.go \
- $(cmdsrcdir)/go/signal.go \
- $(cmdsrcdir)/go/signal_unix.go \
- $(cmdsrcdir)/go/test.go \
- $(cmdsrcdir)/go/testflag.go \
- $(cmdsrcdir)/go/tool.go \
- $(cmdsrcdir)/go/vcs.go \
- $(cmdsrcdir)/go/version.go \
- $(cmdsrcdir)/go/vet.go \
- $(libgodir)/zstdpkglist.go
+ $(cmdsrcdir)/go/main.go
go_cmd_gofmt_files = \
$(cmdsrcdir)/gofmt/doc.go \
@@ -124,8 +100,8 @@ bin_PROGRAMS = go$(EXEEXT) gofmt$(EXEEXT)
noinst_PROGRAMS = cgo$(EXEEXT)
man_MANS = go.1 gofmt.1
-go$(EXEEXT): $(go_cmd_go_files) zdefaultcc.go $(LIBGODEP)
- $(GOLINK) $(go_cmd_go_files) zdefaultcc.go $(LIBS) $(NET_LIBS)
+go$(EXEEXT): $(go_cmd_go_files) $(LIBGOTOOL) $(LIBGODEP)
+ $(GOLINK) $(go_cmd_go_files) $(LIBGOTOOL) $(LIBS) $(NET_LIBS)
gofmt$(EXEEXT): $(go_cmd_gofmt_files) $(LIBGODEP)
$(GOLINK) $(go_cmd_gofmt_files) $(LIBS) $(NET_LIBS)
cgo$(EXEEXT): $(go_cmd_cgo_files) zdefaultcc.go $(LIBGODEP)
@@ -175,6 +151,8 @@ check-gcc: Makefile
# CHECK_ENV sets up the environment to run the newly built go tool.
# If you change this, change ECHO_ENV, below.
+# The fl shell variable is used to avoid having FAIL appear
+# in the log unnecessarily.
CHECK_ENV = \
PATH=`echo $(abs_builddir):$${PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
export PATH; \
@@ -190,7 +168,8 @@ CHECK_ENV = \
LD_LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
export LD_LIBRARY_PATH; \
GOROOT=$${abs_libgodir}; \
- export GOROOT;
+ export GOROOT; \
+ fl1="FA"; fl2="IL"; fl="$${fl1}$${fl2}";
# ECHO_ENV is a variant of CHECK_ENV to put into a testlog file.
# It assumes that abs_libgodir is set.
@@ -201,16 +180,18 @@ check-go-tool: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo check-gcc
rm -rf check-go-dir cmd_go-testlog
$(MKDIR_P) check-go-dir/src/cmd/go
cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/
- cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/
- cp zdefaultcc.go check-go-dir/src/cmd/go/
+ cp -r $(cmdsrcdir)/go/internal check-go-dir/src/cmd/go/
+ cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/internal/load/
+ cp $(libgodir)/zdefaultcc.go check-go-dir/src/cmd/go/internal/cfg/
cp -r $(cmdsrcdir)/go/testdata check-go-dir/src/cmd/go/
+ cp -r $(cmdsrcdir)/internal check-go-dir/src/cmd/
@abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
abs_checkdir=`cd check-go-dir && $(PWD_COMMAND)`; \
echo "cd check-go-dir/src/cmd/go && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cmd_go-testlog
$(CHECK_ENV) \
GOPATH=`cd check-go-dir && $(PWD_COMMAND)`; \
export GOPATH; \
- (cd check-go-dir/src/cmd/go && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) > cmd_go-testlog 2>&1 || true
+ (cd check-go-dir/src/cmd/go && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cmd_go-testlog 2>&1 || echo "--- $${fl} go test cmd/go (0.00s)" >> cmd_go-testlog
grep '^--- ' cmd_go-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
# check-runtime runs `go test runtime` in our environment.
@@ -232,7 +213,7 @@ check-runtime: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo check-gcc
GOARCH=`$(abs_builddir)/go$(EXEEXT) env GOARCH`; \
GOOS=`$(abs_builddir)/go$(EXEEXT) env GOOS`; \
files=`$(SHELL) $(libgosrcdir)/../match.sh --goarch=$${GOARCH} --goos=$${GOOS} --srcdir=$(libgosrcdir)/runtime --extrafiles="$(libgodir)/runtime_sysinfo.go $(libgodir)/sigtab.go" --tag=libffi`; \
- $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles="$${files}" -test.v >> runtime-testlog 2>&1 || true
+ $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles="$${files}" -test.v >> runtime-testlog 2>&1 || echo "--- $${fl} go test runtime (0.00s)" >> runtime-testlog
grep '^--- ' runtime-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
# check-cgo-test runs `go test misc/cgo/test` in our environment.
@@ -245,7 +226,7 @@ check-cgo-test: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo check-gcc
$(CHECK_ENV) \
GOTRACEBACK=2; \
export GOTRACEBACK; \
- (cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cgo-testlog 2>&1 || true
+ (cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cgo-testlog 2>&1 || echo "--- $${fl} go test misc/cgo/test (0.00s)" >> cgo-testlog
grep '^--- ' cgo-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
# check-carchive-test runs `go test misc/cgo/testcarchive/carchive_test.go`
@@ -259,7 +240,7 @@ check-carchive-test: go$(EXEEXT) cgo$(EXEEXT) check-head check-gccgo check-gcc
$(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.v carchive_test.go) >> carchive-testlog 2>&1 || true
+ (cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.v carchive_test.go) >> carchive-testlog 2>&1 || echo "--- $${fl} go test misc/cgo/testcarchive (0.00s)" >> carchive-testlog
grep '^--- ' carchive-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
# The check targets runs the tests and assembles the output files.
diff --git a/gotools/Makefile.in b/gotools/Makefile.in
index 148665a..b9734f1 100644
--- a/gotools/Makefile.in
+++ b/gotools/Makefile.in
@@ -255,6 +255,7 @@ PWD_COMMAND = $${PWDCMD-pwd}
STAMP = echo timestamp >
libgodir = ../$(target_noncanonical)/libgo
LIBGODEP = $(libgodir)/libgo.la
+LIBGOTOOL = $(libgodir)/libgotool.a
@NATIVE_FALSE@GOCOMPILER = $(GOC)
# Use the compiler we just built.
@@ -268,34 +269,8 @@ cmdsrcdir = $(libgosrcdir)/cmd
libgomiscdir = $(srcdir)/../libgo/misc
go_cmd_go_files = \
$(cmdsrcdir)/go/alldocs.go \
- $(cmdsrcdir)/go/bug.go \
- $(cmdsrcdir)/go/build.go \
- $(cmdsrcdir)/go/clean.go \
- $(cmdsrcdir)/go/context.go \
- $(cmdsrcdir)/go/discovery.go \
- $(cmdsrcdir)/go/doc.go \
- $(cmdsrcdir)/go/env.go \
- $(cmdsrcdir)/go/fix.go \
- $(cmdsrcdir)/go/fmt.go \
- $(cmdsrcdir)/go/generate.go \
- $(cmdsrcdir)/go/get.go \
$(cmdsrcdir)/go/go11.go \
- $(cmdsrcdir)/go/help.go \
- $(cmdsrcdir)/go/http.go \
- $(cmdsrcdir)/go/list.go \
- $(cmdsrcdir)/go/main.go \
- $(cmdsrcdir)/go/note.go \
- $(cmdsrcdir)/go/pkg.go \
- $(cmdsrcdir)/go/run.go \
- $(cmdsrcdir)/go/signal.go \
- $(cmdsrcdir)/go/signal_unix.go \
- $(cmdsrcdir)/go/test.go \
- $(cmdsrcdir)/go/testflag.go \
- $(cmdsrcdir)/go/tool.go \
- $(cmdsrcdir)/go/vcs.go \
- $(cmdsrcdir)/go/version.go \
- $(cmdsrcdir)/go/vet.go \
- $(libgodir)/zstdpkglist.go
+ $(cmdsrcdir)/go/main.go
go_cmd_gofmt_files = \
$(cmdsrcdir)/gofmt/doc.go \
@@ -330,6 +305,8 @@ MOSTLYCLEANFILES = \
# CHECK_ENV sets up the environment to run the newly built go tool.
# If you change this, change ECHO_ENV, below.
+# The fl shell variable is used to avoid having FAIL appear
+# in the log unnecessarily.
@NATIVE_TRUE@CHECK_ENV = \
@NATIVE_TRUE@ PATH=`echo $(abs_builddir):$${PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
@NATIVE_TRUE@ export PATH; \
@@ -345,7 +322,8 @@ MOSTLYCLEANFILES = \
@NATIVE_TRUE@ LD_LIBRARY_PATH=`echo $${abs_libgodir}/.libs:$${LD_LIBRARY_PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,,'`; \
@NATIVE_TRUE@ export LD_LIBRARY_PATH; \
@NATIVE_TRUE@ GOROOT=$${abs_libgodir}; \
-@NATIVE_TRUE@ export GOROOT;
+@NATIVE_TRUE@ export GOROOT; \
+@NATIVE_TRUE@ fl1="FA"; fl2="IL"; fl="$${fl1}$${fl2}";
# ECHO_ENV is a variant of CHECK_ENV to put into a testlog file.
@@ -598,8 +576,8 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-@NATIVE_FALSE@uninstall-local:
@NATIVE_FALSE@install-exec-local:
+@NATIVE_FALSE@uninstall-local:
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
@@ -707,8 +685,8 @@ s-zdefaultcc: Makefile
mostlyclean-local:
rm -rf check-go-dir check-runtime-dir cgo-test-dir carchive-test-dir
-@NATIVE_TRUE@go$(EXEEXT): $(go_cmd_go_files) zdefaultcc.go $(LIBGODEP)
-@NATIVE_TRUE@ $(GOLINK) $(go_cmd_go_files) zdefaultcc.go $(LIBS) $(NET_LIBS)
+@NATIVE_TRUE@go$(EXEEXT): $(go_cmd_go_files) $(LIBGOTOOL) $(LIBGODEP)
+@NATIVE_TRUE@ $(GOLINK) $(go_cmd_go_files) $(LIBGOTOOL) $(LIBS) $(NET_LIBS)
@NATIVE_TRUE@gofmt$(EXEEXT): $(go_cmd_gofmt_files) $(LIBGODEP)
@NATIVE_TRUE@ $(GOLINK) $(go_cmd_gofmt_files) $(LIBS) $(NET_LIBS)
@NATIVE_TRUE@cgo$(EXEEXT): $(go_cmd_cgo_files) zdefaultcc.go $(LIBGODEP)
@@ -761,16 +739,18 @@ mostlyclean-local:
@NATIVE_TRUE@ rm -rf check-go-dir cmd_go-testlog
@NATIVE_TRUE@ $(MKDIR_P) check-go-dir/src/cmd/go
@NATIVE_TRUE@ cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/
-@NATIVE_TRUE@ cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/
-@NATIVE_TRUE@ cp zdefaultcc.go check-go-dir/src/cmd/go/
+@NATIVE_TRUE@ cp -r $(cmdsrcdir)/go/internal check-go-dir/src/cmd/go/
+@NATIVE_TRUE@ cp $(libgodir)/zstdpkglist.go check-go-dir/src/cmd/go/internal/load/
+@NATIVE_TRUE@ cp $(libgodir)/zdefaultcc.go check-go-dir/src/cmd/go/internal/cfg/
@NATIVE_TRUE@ cp -r $(cmdsrcdir)/go/testdata check-go-dir/src/cmd/go/
+@NATIVE_TRUE@ cp -r $(cmdsrcdir)/internal check-go-dir/src/cmd/
@NATIVE_TRUE@ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \
@NATIVE_TRUE@ abs_checkdir=`cd check-go-dir && $(PWD_COMMAND)`; \
@NATIVE_TRUE@ echo "cd check-go-dir/src/cmd/go && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.v" > cmd_go-testlog
@NATIVE_TRUE@ $(CHECK_ENV) \
@NATIVE_TRUE@ GOPATH=`cd check-go-dir && $(PWD_COMMAND)`; \
@NATIVE_TRUE@ export GOPATH; \
-@NATIVE_TRUE@ (cd check-go-dir/src/cmd/go && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) > cmd_go-testlog 2>&1 || true
+@NATIVE_TRUE@ (cd check-go-dir/src/cmd/go && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cmd_go-testlog 2>&1 || echo "--- $${fl} go test cmd/go (0.00s)" >> cmd_go-testlog
@NATIVE_TRUE@ grep '^--- ' cmd_go-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
# check-runtime runs `go test runtime` in our environment.
@@ -792,7 +772,7 @@ mostlyclean-local:
@NATIVE_TRUE@ GOARCH=`$(abs_builddir)/go$(EXEEXT) env GOARCH`; \
@NATIVE_TRUE@ GOOS=`$(abs_builddir)/go$(EXEEXT) env GOOS`; \
@NATIVE_TRUE@ files=`$(SHELL) $(libgosrcdir)/../match.sh --goarch=$${GOARCH} --goos=$${GOOS} --srcdir=$(libgosrcdir)/runtime --extrafiles="$(libgodir)/runtime_sysinfo.go $(libgodir)/sigtab.go" --tag=libffi`; \
-@NATIVE_TRUE@ $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles="$${files}" -test.v >> runtime-testlog 2>&1 || true
+@NATIVE_TRUE@ $(SHELL) $(libgosrcdir)/../testsuite/gotest --goarch=$${GOARCH} --goos=$${GOOS} --basedir=$(libgosrcdir)/.. --srcdir=$(libgosrcdir)/runtime --pkgpath=runtime --pkgfiles="$${files}" -test.v >> runtime-testlog 2>&1 || echo "--- $${fl} go test runtime (0.00s)" >> runtime-testlog
@NATIVE_TRUE@ grep '^--- ' runtime-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
# check-cgo-test runs `go test misc/cgo/test` in our environment.
@@ -805,7 +785,7 @@ mostlyclean-local:
@NATIVE_TRUE@ $(CHECK_ENV) \
@NATIVE_TRUE@ GOTRACEBACK=2; \
@NATIVE_TRUE@ export GOTRACEBACK; \
-@NATIVE_TRUE@ (cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -test.v) >> cgo-testlog 2>&1 || true
+@NATIVE_TRUE@ (cd cgo-test-dir/misc/cgo/test && $(abs_builddir)/go$(EXEEXT) test -test.short -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/'
# check-carchive-test runs `go test misc/cgo/testcarchive/carchive_test.go`
@@ -819,7 +799,7 @@ mostlyclean-local:
@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.v carchive_test.go) >> carchive-testlog 2>&1 || true
+@NATIVE_TRUE@ (cd carchive-test-dir/misc/cgo/testcarchive && $(abs_builddir)/go$(EXEEXT) test -test.v carchive_test.go) >> carchive-testlog 2>&1 || echo "--- $${fl} go test misc/cgo/testcarchive (0.00s)" >> carchive-testlog
@NATIVE_TRUE@ grep '^--- ' carchive-testlog | sed -e 's/^--- \(.*\) ([^)]*)$$/\1/'
# The check targets runs the tests and assembles the output files.
diff --git a/libgo/MERGE b/libgo/MERGE
index ddfb006..85703d6 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-352996a381701cfa0c16e8de29cbde8f3922182f
+c8aec4095e089ff6ac50d18e97c3f46561f14f48
The first line of this file holds the git revision number of the
last merge done from the master library sources.
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index 9800d20..2376130 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -117,6 +117,8 @@ toolexeclib_LTLIBRARIES = libgo.la
toolexeclib_LIBRARIES = libgobegin.a libgolibbegin.a
endif
+noinst_LIBRARIES = libgotool.a
+
toolexeclibgo_DATA = \
bufio.gox \
bytes.gox \
@@ -299,6 +301,7 @@ toolexeclibgomathdir = $(toolexeclibgodir)/math
toolexeclibgomath_DATA = \
math/big.gox \
+ math/bits.gox \
math/cmplx.gox \
math/rand.gox
@@ -534,6 +537,21 @@ s-sigtab: $(srcdir)/mksigtab.sh gen-sysinfo.go
$(SHELL) $(srcdir)/mvifdiff.sh tmp-sigtab.go sigtab.go
$(STAMP) $@
+GCCGO_INSTALL_NAME := $(shell echo gccgo|sed '$(program_transform_name)')
+GCC_INSTALL_NAME := $(shell echo gcc|sed '$(program_transform_name)')
+GXX_INSTALL_NAME := $(shell echo g++|sed '$(program_transform_name)')
+
+zdefaultcc.go: s-zdefaultcc; @true
+s-zdefaultcc: Makefile
+ echo 'package cfg' > zdefaultcc.go.tmp
+ echo >> zdefaultcc.go.tmp
+ echo 'const DefaultGCCGO = "$(bindir)/$(GCCGO_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const DefaultCC = "$(GCC_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const DefaultCXX = "$(GXX_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const DefaultPkgConfig = "pkg-config"' >> zdefaultcc.go.tmp
+ $(SHELL) $(srcdir)/../move-if-change zdefaultcc.go.tmp zdefaultcc.go
+ $(STAMP) $@
+
# _Complex_lock and _Reader_lock are Go translations of some AIX system
# types and should not be exported back to C
# semt is a Go translation of the C type sem_t; it fails to convert on
@@ -555,13 +573,13 @@ s-runtime-inc: runtime.lo Makefile
rm -f runtime.inc.tmp2 runtime.inc.tmp3
$(STAMP) $@
-noinst_DATA = zstdpkglist.go
+noinst_DATA = zstdpkglist.go zdefaultcc.go
# Generate the list of go std packages that were included in libgo
zstdpkglist.go: s-zstdpkglist; @true
s-zstdpkglist: Makefile
rm -f zstdpkglist.go.tmp
- echo 'package main' > zstdpkglist.go.tmp
+ echo 'package load' > 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
@@ -660,7 +678,6 @@ PACKAGES = \
archive/zip \
bufio \
bytes \
- cmd/internal/browser \
compress/bzip2 \
compress/flate \
compress/gzip \
@@ -724,6 +741,7 @@ PACKAGES = \
go/importer \
go/internal/gccgoimporter \
go/internal/gcimporter \
+ go/internal/srcimporter \
go/parser \
go/printer \
go/scanner \
@@ -736,7 +754,10 @@ PACKAGES = \
golang_org/x/net/http2/hpack \
golang_org/x/net/idna \
golang_org/x/net/lex/httplex \
+ golang_org/x/net/proxy \
+ golang_org/x/text/secure/bidirule \
golang_org/x/text/transform \
+ golang_org/x/text/unicode/bidi \
golang_org/x/text/unicode/norm \
golang_org/x/text/width \
hash \
@@ -756,7 +777,7 @@ PACKAGES = \
image/png \
index/suffixarray \
internal/nettrace \
- internal/pprof/profile \
+ internal/poll \
internal/race \
internal/singleflight \
internal/syscall/unix \
@@ -768,6 +789,7 @@ PACKAGES = \
log/syslog \
math \
math/big \
+ math/bits \
math/cmplx \
math/rand \
mime \
@@ -804,7 +826,7 @@ PACKAGES = \
runtime/internal/atomic \
runtime/internal/sys \
runtime/pprof \
- runtime/pprof/internal/protopprof \
+ runtime/pprof/internal/profile \
runtime/trace \
sort \
strconv \
@@ -871,6 +893,37 @@ libgolibbegin_a_SOURCES = \
libgolibbegin_a_CFLAGS = $(AM_CFLAGS) -fPIC
+GOTOOL_PACKAGES = \
+ cmd/go/internal/base \
+ cmd/go/internal/bug \
+ cmd/go/internal/buildid \
+ cmd/go/internal/cfg \
+ cmd/go/internal/clean \
+ cmd/go/internal/cmdflag \
+ cmd/go/internal/doc \
+ cmd/go/internal/envcmd \
+ cmd/go/internal/fix \
+ cmd/go/internal/fmtcmd \
+ cmd/go/internal/generate \
+ cmd/go/internal/get \
+ cmd/go/internal/help \
+ cmd/go/internal/list \
+ cmd/go/internal/load \
+ cmd/go/internal/run \
+ cmd/go/internal/str \
+ cmd/go/internal/test \
+ cmd/go/internal/tool \
+ cmd/go/internal/version \
+ cmd/go/internal/vet \
+ cmd/go/internal/web \
+ cmd/go/internal/work \
+ cmd/internal/browser \
+ cmd/internal/objabi
+
+libgotool_a_SOURCES =
+libgotool_a_DEPENDENCIES = $(addsuffix .lo,$(GOTOOL_PACKAGES))
+libgotool_a_LIBADD = $(addsuffix .o,$(GOTOOL_PACKAGES))
+
# Make sure runtime.inc is built before compiling any .c file.
$(libgo_la_OBJECTS): runtime.inc
$(libgo_llgo_la_OBJECTS): runtime.inc
@@ -925,7 +978,7 @@ GOBENCH =
CHECK = \
GC="$(GOC) $(GOCFLAGS) $($(subst /,_,$@)_GOCFLAGS) -L `${PWD_COMMAND}` -L `${PWD_COMMAND}`/.libs"; \
export GC; \
- GOLIBS="$(MATH_LIBS) $(NET_LIBS) $(LIBS)"; \
+ GOLIBS="$(extra_check_libs_$(subst /,_,$(@D))) $(MATH_LIBS) $(NET_LIBS) $(LIBS)"; \
export GOLIBS; \
RUNTESTFLAGS="$(RUNTESTFLAGS)"; \
export RUNTESTFLAGS; \
@@ -985,7 +1038,8 @@ CHECK_DEPS = \
$(toolexeclibgotesting_DATA) \
$(toolexeclibgotext_DATA) \
$(toolexeclibgotexttemplate_DATA) \
- $(toolexeclibgounicode_DATA)
+ $(toolexeclibgounicode_DATA) \
+ $(noinst_LIBRARIES)
if GOC_IS_LLGO
CHECK_DEPS += libgo-llgo.la libgobegin-llgo.a
@@ -1025,6 +1079,7 @@ endef
# This line expands PACKAGE_template once for each package name listed
# in $(PACKAGES).
$(foreach package,$(PACKAGES),$(eval $(call PACKAGE_template,$(package))))
+$(foreach package,$(GOTOOL_PACKAGES),$(eval $(call PACKAGE_template,$(package))))
# Pass -ffp-contract=off, or 386-specific options, when building the
# math package. MATH_FLAG is defined in configure.ac.
@@ -1066,6 +1121,17 @@ runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline
extra_go_files_runtime_internal_sys = version.go
runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys)
+extra_go_files_cmd_go_internal_cfg = zdefaultcc.go
+cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg)
+
+extra_go_files_cmd_go_internal_load = zstdpkglist.go
+cmd/go/internal/load.lo.dep: $(extra_go_files_cmd_go_internal_load)
+
+extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a
+extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a
+extra_check_libs_cmd_go_internal_load = $(abs_builddir)/libgotool.a
+extra_check_libs_cmd_go_internal_work = $(abs_builddir)/libgotool.a
+
# FIXME: The following C files may as well move to the runtime
# directory and be treated like other C files.
@@ -1177,6 +1243,11 @@ TEST_PACKAGES = \
unicode/check \
archive/tar/check \
archive/zip/check \
+ cmd/go/internal/generate/check \
+ cmd/go/internal/get/check \
+ cmd/go/internal/load/check \
+ cmd/go/internal/work/check \
+ cmd/internal/objabi/check \
compress/bzip2/check \
compress/flate/check \
compress/gzip/check \
@@ -1230,6 +1301,7 @@ TEST_PACKAGES = \
go/format/check \
go/internal/gcimporter/check \
go/internal/gccgoimporter/check \
+ go/internal/srcimporter/check \
go/parser/check \
go/printer/check \
go/scanner/check \
@@ -1243,6 +1315,7 @@ TEST_PACKAGES = \
golang_org/x/net/idna/check \
golang_org/x/net/lex/httplex/check \
$(golang_org_x_net_lif_check) \
+ golang_org/x/net/proxy/check \
$(golang_org_x_net_route_check) \
hash/adler32/check \
hash/crc32/check \
@@ -1253,12 +1326,13 @@ TEST_PACKAGES = \
image/jpeg/check \
image/png/check \
index/suffixarray/check \
- internal/pprof/profile/check \
+ internal/poll/check \
internal/singleflight/check \
internal/trace/check \
io/ioutil/check \
log/syslog/check \
math/big/check \
+ math/bits/check \
math/cmplx/check \
math/rand/check \
mime/multipart/check \
@@ -1287,7 +1361,7 @@ TEST_PACKAGES = \
runtime/internal/atomic/check \
runtime/internal/sys/check \
runtime/pprof/check \
- runtime/pprof/internal/protopprof/check \
+ runtime/pprof/internal/profile/check \
runtime/trace/check \
sync/atomic/check \
text/scanner/check \
@@ -1413,7 +1487,7 @@ mostlyclean-local:
find . -name '*-testsum' -print | xargs rm -f
find . -name '*-testlog' -print | xargs rm -f
-CLEANFILES = *.go *.c s-version libgo.sum libgo.log runtime.inc
+CLEANFILES = *.go *.c s-* libgo.sum libgo.log runtime.inc
clean-local:
find . -name '*.la' -print | xargs $(LIBTOOL) --mode=clean rm -f
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 9a2bd47..5f7adb2 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -155,7 +155,7 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgotextdir)" \
"$(DESTDIR)$(toolexeclibgotexttemplatedir)" \
"$(DESTDIR)$(toolexeclibgounicodedir)"
-LIBRARIES = $(toolexeclib_LIBRARIES)
+LIBRARIES = $(noinst_LIBRARIES) $(toolexeclib_LIBRARIES)
ARFLAGS = cru
libgobegin_llgo_a_AR = $(AR) $(ARFLAGS)
libgobegin_llgo_a_LIBADD =
@@ -169,6 +169,9 @@ libgolibbegin_a_AR = $(AR) $(ARFLAGS)
libgolibbegin_a_LIBADD =
am_libgolibbegin_a_OBJECTS = libgolibbegin_a-go-libmain.$(OBJEXT)
libgolibbegin_a_OBJECTS = $(am_libgolibbegin_a_OBJECTS)
+libgotool_a_AR = $(AR) $(ARFLAGS)
+am_libgotool_a_OBJECTS =
+libgotool_a_OBJECTS = $(am_libgotool_a_OBJECTS)
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
@LIBGO_IS_LINUX_TRUE@am__DEPENDENCIES_1 = syscall/clone_linux.lo
am__DEPENDENCIES_2 = $(addsuffix .lo,$(PACKAGES)) bytes/index.lo \
@@ -229,8 +232,8 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libgobegin_llgo_a_SOURCES) $(libgobegin_a_SOURCES) \
- $(libgolibbegin_a_SOURCES) $(libgo_llgo_la_SOURCES) \
- $(libgo_la_SOURCES)
+ $(libgolibbegin_a_SOURCES) $(libgotool_a_SOURCES) \
+ $(libgo_llgo_la_SOURCES) $(libgo_la_SOURCES)
MULTISRCTOP =
MULTIBUILDTOP =
MULTIDIRS =
@@ -518,6 +521,7 @@ FLAGS_TO_PASS = $(AM_MAKEFLAGS)
@GOC_IS_LLGO_TRUE@toolexeclib_LTLIBRARIES = libgo-llgo.la
@GOC_IS_LLGO_FALSE@toolexeclib_LIBRARIES = libgobegin.a libgolibbegin.a
@GOC_IS_LLGO_TRUE@toolexeclib_LIBRARIES = libgobegin-llgo.a
+noinst_LIBRARIES = libgotool.a
toolexeclibgo_DATA = \
bufio.gox \
bytes.gox \
@@ -681,6 +685,7 @@ toolexeclibgolog_DATA = \
toolexeclibgomathdir = $(toolexeclibgodir)/math
toolexeclibgomath_DATA = \
math/big.gox \
+ math/bits.gox \
math/cmplx.gox \
math/rand.gox
@@ -809,7 +814,10 @@ runtime_files = \
$(rtems_task_variable_add_file) \
$(runtime_getncpu_file)
-noinst_DATA = zstdpkglist.go
+GCCGO_INSTALL_NAME := $(shell echo gccgo|sed '$(program_transform_name)')
+GCC_INSTALL_NAME := $(shell echo gcc|sed '$(program_transform_name)')
+GXX_INSTALL_NAME := $(shell echo g++|sed '$(program_transform_name)')
+noinst_DATA = zstdpkglist.go zdefaultcc.go
@LIBGO_IS_LINUX_FALSE@syscall_epoll_file =
@LIBGO_IS_LINUX_TRUE@syscall_epoll_file = epoll.go
SYSINFO_FLAGS = \
@@ -823,7 +831,6 @@ PACKAGES = \
archive/zip \
bufio \
bytes \
- cmd/internal/browser \
compress/bzip2 \
compress/flate \
compress/gzip \
@@ -887,6 +894,7 @@ PACKAGES = \
go/importer \
go/internal/gccgoimporter \
go/internal/gcimporter \
+ go/internal/srcimporter \
go/parser \
go/printer \
go/scanner \
@@ -899,7 +907,10 @@ PACKAGES = \
golang_org/x/net/http2/hpack \
golang_org/x/net/idna \
golang_org/x/net/lex/httplex \
+ golang_org/x/net/proxy \
+ golang_org/x/text/secure/bidirule \
golang_org/x/text/transform \
+ golang_org/x/text/unicode/bidi \
golang_org/x/text/unicode/norm \
golang_org/x/text/width \
hash \
@@ -919,7 +930,7 @@ PACKAGES = \
image/png \
index/suffixarray \
internal/nettrace \
- internal/pprof/profile \
+ internal/poll \
internal/race \
internal/singleflight \
internal/syscall/unix \
@@ -931,6 +942,7 @@ PACKAGES = \
log/syslog \
math \
math/big \
+ math/bits \
math/cmplx \
math/rand \
mime \
@@ -967,7 +979,7 @@ PACKAGES = \
runtime/internal/atomic \
runtime/internal/sys \
runtime/pprof \
- runtime/pprof/internal/protopprof \
+ runtime/pprof/internal/profile \
runtime/trace \
sort \
strconv \
@@ -1031,6 +1043,36 @@ libgolibbegin_a_SOURCES = \
runtime/go-libmain.c
libgolibbegin_a_CFLAGS = $(AM_CFLAGS) -fPIC
+GOTOOL_PACKAGES = \
+ cmd/go/internal/base \
+ cmd/go/internal/bug \
+ cmd/go/internal/buildid \
+ cmd/go/internal/cfg \
+ cmd/go/internal/clean \
+ cmd/go/internal/cmdflag \
+ cmd/go/internal/doc \
+ cmd/go/internal/envcmd \
+ cmd/go/internal/fix \
+ cmd/go/internal/fmtcmd \
+ cmd/go/internal/generate \
+ cmd/go/internal/get \
+ cmd/go/internal/help \
+ cmd/go/internal/list \
+ cmd/go/internal/load \
+ cmd/go/internal/run \
+ cmd/go/internal/str \
+ cmd/go/internal/test \
+ cmd/go/internal/tool \
+ cmd/go/internal/version \
+ cmd/go/internal/vet \
+ cmd/go/internal/web \
+ cmd/go/internal/work \
+ cmd/internal/browser \
+ cmd/internal/objabi
+
+libgotool_a_SOURCES =
+libgotool_a_DEPENDENCIES = $(addsuffix .lo,$(GOTOOL_PACKAGES))
+libgotool_a_LIBADD = $(addsuffix .o,$(GOTOOL_PACKAGES))
LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
AM_GOCFLAGS = $(STRINGOPS_FLAG) $(GO_SPLIT_STACK)
GOCOMPILE = $(GOC) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_GOCFLAGS) $(GOCFLAGS)
@@ -1078,7 +1120,7 @@ GOBENCH =
CHECK = \
GC="$(GOC) $(GOCFLAGS) $($(subst /,_,$@)_GOCFLAGS) -L `${PWD_COMMAND}` -L `${PWD_COMMAND}`/.libs"; \
export GC; \
- GOLIBS="$(MATH_LIBS) $(NET_LIBS) $(LIBS)"; \
+ GOLIBS="$(extra_check_libs_$(subst /,_,$(@D))) $(MATH_LIBS) $(NET_LIBS) $(LIBS)"; \
export GOLIBS; \
RUNTESTFLAGS="$(RUNTESTFLAGS)"; \
export RUNTESTFLAGS; \
@@ -1125,7 +1167,8 @@ CHECK_DEPS = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \
$(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA) \
$(toolexeclibgotext_DATA) $(toolexeclibgotexttemplate_DATA) \
- $(toolexeclibgounicode_DATA) $(am__append_3) $(am__append_4)
+ $(toolexeclibgounicode_DATA) $(noinst_LIBRARIES) \
+ $(am__append_3) $(am__append_4)
# Pass -ffp-contract=off, or 386-specific options, when building the
# math package. MATH_FLAG is defined in configure.ac.
@@ -1160,6 +1203,12 @@ runtime_internal_sys_lo_check_GOCFLAGS = -fgo-compiling-runtime
# Also use -fno-inline to get better results from the memory profiler.
runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline
extra_go_files_runtime_internal_sys = version.go
+extra_go_files_cmd_go_internal_cfg = zdefaultcc.go
+extra_go_files_cmd_go_internal_load = zstdpkglist.go
+extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a
+extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a
+extra_check_libs_cmd_go_internal_load = $(abs_builddir)/libgotool.a
+extra_check_libs_cmd_go_internal_work = $(abs_builddir)/libgotool.a
@HAVE_STAT_TIMESPEC_FALSE@@LIBGO_IS_SOLARIS_TRUE@matchargs_os =
# Solaris 12 changed the type of fields in struct stat.
@@ -1207,6 +1256,11 @@ TEST_PACKAGES = \
unicode/check \
archive/tar/check \
archive/zip/check \
+ cmd/go/internal/generate/check \
+ cmd/go/internal/get/check \
+ cmd/go/internal/load/check \
+ cmd/go/internal/work/check \
+ cmd/internal/objabi/check \
compress/bzip2/check \
compress/flate/check \
compress/gzip/check \
@@ -1260,6 +1314,7 @@ TEST_PACKAGES = \
go/format/check \
go/internal/gcimporter/check \
go/internal/gccgoimporter/check \
+ go/internal/srcimporter/check \
go/parser/check \
go/printer/check \
go/scanner/check \
@@ -1273,6 +1328,7 @@ TEST_PACKAGES = \
golang_org/x/net/idna/check \
golang_org/x/net/lex/httplex/check \
$(golang_org_x_net_lif_check) \
+ golang_org/x/net/proxy/check \
$(golang_org_x_net_route_check) \
hash/adler32/check \
hash/crc32/check \
@@ -1283,12 +1339,13 @@ TEST_PACKAGES = \
image/jpeg/check \
image/png/check \
index/suffixarray/check \
- internal/pprof/profile/check \
+ internal/poll/check \
internal/singleflight/check \
internal/trace/check \
io/ioutil/check \
log/syslog/check \
math/big/check \
+ math/bits/check \
math/cmplx/check \
math/rand/check \
mime/multipart/check \
@@ -1317,7 +1374,7 @@ TEST_PACKAGES = \
runtime/internal/atomic/check \
runtime/internal/sys/check \
runtime/pprof/check \
- runtime/pprof/internal/protopprof/check \
+ runtime/pprof/internal/profile/check \
runtime/trace/check \
sync/atomic/check \
text/scanner/check \
@@ -1335,7 +1392,7 @@ MOSTLYCLEANFILES = \
libgo.head libgo.sum.sep libgo.log.sep libgo.var \
libcalls-list runtime.inc runtime.inc.tmp2 runtime.inc.tmp3
-CLEANFILES = *.go *.c s-version libgo.sum libgo.log runtime.inc
+CLEANFILES = *.go *.c s-* libgo.sum libgo.log runtime.inc
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
@@ -1390,6 +1447,9 @@ $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
distclean-hdr:
-rm -f config.h stamp-h1
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
install-toolexeclibLIBRARIES: $(toolexeclib_LIBRARIES)
@$(NORMAL_INSTALL)
@list='$(toolexeclib_LIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
@@ -1433,6 +1493,10 @@ libgolibbegin.a: $(libgolibbegin_a_OBJECTS) $(libgolibbegin_a_DEPENDENCIES) $(EX
-rm -f libgolibbegin.a
$(libgolibbegin_a_AR) libgolibbegin.a $(libgolibbegin_a_OBJECTS) $(libgolibbegin_a_LIBADD)
$(RANLIB) libgolibbegin.a
+libgotool.a: $(libgotool_a_OBJECTS) $(libgotool_a_DEPENDENCIES) $(EXTRA_libgotool_a_DEPENDENCIES)
+ -rm -f libgotool.a
+ $(libgotool_a_AR) libgotool.a $(libgotool_a_OBJECTS) $(libgotool_a_LIBADD)
+ $(RANLIB) libgotool.a
install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES)
@$(NORMAL_INSTALL)
@list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \
@@ -2797,8 +2861,8 @@ maintainer-clean-generic:
clean: clean-multi clean-recursive
clean-am: clean-generic clean-libtool clean-local \
- clean-toolexeclibLIBRARIES clean-toolexeclibLTLIBRARIES \
- mostlyclean-am
+ clean-noinstLIBRARIES clean-toolexeclibLIBRARIES \
+ clean-toolexeclibLTLIBRARIES mostlyclean-am
distclean: distclean-multi distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
@@ -2931,17 +2995,18 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am all-multi am--refresh check check-am clean \
clean-generic clean-libtool clean-local clean-multi \
- clean-toolexeclibLIBRARIES clean-toolexeclibLTLIBRARIES ctags \
- ctags-recursive distclean distclean-compile distclean-generic \
- distclean-hdr distclean-libtool distclean-local \
- distclean-multi distclean-tags dvi dvi-am html html-am info \
- info-am install install-am install-data install-data-am \
- install-dvi install-dvi-am install-exec install-exec-am \
- install-html install-html-am install-info install-info-am \
- install-man install-multi install-pdf install-pdf-am \
- install-ps install-ps-am install-strip \
- install-toolexeclibLIBRARIES install-toolexeclibLTLIBRARIES \
- install-toolexeclibgoDATA install-toolexeclibgoarchiveDATA \
+ clean-noinstLIBRARIES clean-toolexeclibLIBRARIES \
+ clean-toolexeclibLTLIBRARIES ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-hdr \
+ distclean-libtool distclean-local distclean-multi \
+ distclean-tags dvi dvi-am html html-am info info-am install \
+ install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-multi install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip install-toolexeclibLIBRARIES \
+ install-toolexeclibLTLIBRARIES install-toolexeclibgoDATA \
+ install-toolexeclibgoarchiveDATA \
install-toolexeclibgocompressDATA \
install-toolexeclibgocontainerDATA \
install-toolexeclibgocryptoDATA \
@@ -3069,6 +3134,17 @@ s-sigtab: $(srcdir)/mksigtab.sh gen-sysinfo.go
$(SHELL) $(srcdir)/mvifdiff.sh tmp-sigtab.go sigtab.go
$(STAMP) $@
+zdefaultcc.go: s-zdefaultcc; @true
+s-zdefaultcc: Makefile
+ echo 'package cfg' > zdefaultcc.go.tmp
+ echo >> zdefaultcc.go.tmp
+ echo 'const DefaultGCCGO = "$(bindir)/$(GCCGO_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const DefaultCC = "$(GCC_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const DefaultCXX = "$(GXX_INSTALL_NAME)"' >> zdefaultcc.go.tmp
+ echo 'const DefaultPkgConfig = "pkg-config"' >> zdefaultcc.go.tmp
+ $(SHELL) $(srcdir)/../move-if-change zdefaultcc.go.tmp zdefaultcc.go
+ $(STAMP) $@
+
# _Complex_lock and _Reader_lock are Go translations of some AIX system
# types and should not be exported back to C
# semt is a Go translation of the C type sem_t; it fails to convert on
@@ -3094,7 +3170,7 @@ s-runtime-inc: runtime.lo Makefile
zstdpkglist.go: s-zstdpkglist; @true
s-zstdpkglist: Makefile
rm -f zstdpkglist.go.tmp
- echo 'package main' > zstdpkglist.go.tmp
+ echo 'package load' > 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
@@ -3211,9 +3287,12 @@ endef
# This line expands PACKAGE_template once for each package name listed
# in $(PACKAGES).
$(foreach package,$(PACKAGES),$(eval $(call PACKAGE_template,$(package))))
+$(foreach package,$(GOTOOL_PACKAGES),$(eval $(call PACKAGE_template,$(package))))
runtime.lo.dep: $(extra_go_files_runtime)
syscall.lo.dep: $(extra_go_files_syscall)
runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys)
+cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg)
+cmd/go/internal/load.lo.dep: $(extra_go_files_cmd_go_internal_load)
# FIXME: The following C files may as well move to the runtime
# directory and be treated like other C files.
diff --git a/libgo/VERSION b/libgo/VERSION
index b38ce77..6d1d72f 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.8.3
+go1.9
diff --git a/libgo/configure b/libgo/configure
index 3b0d0d2..1e5e41b 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -2494,7 +2494,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers config.h"
-libtool_VERSION=11:0:0
+libtool_VERSION=12:0:0
# Default to --enable-multilib
diff --git a/libgo/configure.ac b/libgo/configure.ac
index 80ad3df..4bfe169 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -11,7 +11,7 @@ AC_INIT(package-unused, version-unused,, libgo)
AC_CONFIG_SRCDIR(Makefile.am)
AC_CONFIG_HEADER(config.h)
-libtool_VERSION=11:0:0
+libtool_VERSION=12:0:0
AC_SUBST(libtool_VERSION)
AM_ENABLE_MULTILIB(, ..)
diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go
index d2ae66d..d49c5c3 100644
--- a/libgo/go/archive/tar/common.go
+++ b/libgo/go/archive/tar/common.go
@@ -158,11 +158,15 @@ func (fi headerFileInfo) Mode() (mode os.FileMode) {
// sysStat, if non-nil, populates h from system-dependent fields of fi.
var sysStat func(fi os.FileInfo, h *Header) error
-// Mode constants from the tar spec.
const (
- c_ISUID = 04000 // Set uid
- c_ISGID = 02000 // Set gid
- c_ISVTX = 01000 // Save text (sticky bit)
+ // Mode constants from the USTAR spec:
+ // See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_06
+ c_ISUID = 04000 // Set uid
+ c_ISGID = 02000 // Set gid
+ c_ISVTX = 01000 // Save text (sticky bit)
+
+ // Common Unix mode constants; these are not defined in any common tar standard.
+ // Header.FileInfo understands these, but FileInfoHeader will never produce these.
c_ISDIR = 040000 // Directory
c_ISFIFO = 010000 // FIFO
c_ISREG = 0100000 // Regular file
@@ -208,30 +212,24 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
}
switch {
case fm.IsRegular():
- h.Mode |= c_ISREG
h.Typeflag = TypeReg
h.Size = fi.Size()
case fi.IsDir():
h.Typeflag = TypeDir
- h.Mode |= c_ISDIR
h.Name += "/"
case fm&os.ModeSymlink != 0:
h.Typeflag = TypeSymlink
- h.Mode |= c_ISLNK
h.Linkname = link
case fm&os.ModeDevice != 0:
if fm&os.ModeCharDevice != 0 {
- h.Mode |= c_ISCHR
h.Typeflag = TypeChar
} else {
- h.Mode |= c_ISBLK
h.Typeflag = TypeBlock
}
case fm&os.ModeNamedPipe != 0:
h.Typeflag = TypeFifo
- h.Mode |= c_ISFIFO
case fm&os.ModeSocket != 0:
- h.Mode |= c_ISSOCK
+ return nil, fmt.Errorf("archive/tar: sockets not supported")
default:
return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
}
diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go
index cf8337c..fb7a9dc 100644
--- a/libgo/go/archive/tar/tar_test.go
+++ b/libgo/go/archive/tar/tar_test.go
@@ -6,9 +6,11 @@ package tar
import (
"bytes"
+ "internal/testenv"
"io/ioutil"
"os"
"path"
+ "path/filepath"
"reflect"
"strings"
"testing"
@@ -27,7 +29,7 @@ func TestFileInfoHeader(t *testing.T) {
if g, e := h.Name, "small.txt"; g != e {
t.Errorf("Name = %q; want %q", g, e)
}
- if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e {
+ if g, e := h.Mode, int64(fi.Mode().Perm()); g != e {
t.Errorf("Mode = %#o; want %#o", g, e)
}
if g, e := h.Size, int64(5); g != e {
@@ -55,7 +57,7 @@ func TestFileInfoHeaderDir(t *testing.T) {
t.Errorf("Name = %q; want %q", g, e)
}
// Ignoring c_ISGID for golang.org/issue/4867
- if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm())|c_ISDIR; g != e {
+ if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm()); g != e {
t.Errorf("Mode = %#o; want %#o", g, e)
}
if g, e := h.Size, int64(0); g != e {
@@ -67,40 +69,56 @@ func TestFileInfoHeaderDir(t *testing.T) {
}
func TestFileInfoHeaderSymlink(t *testing.T) {
- h, err := FileInfoHeader(symlink{}, "some-target")
+ testenv.MustHaveSymlink(t)
+
+ tmpdir, err := ioutil.TempDir("", "TestFileInfoHeaderSymlink")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ link := filepath.Join(tmpdir, "link")
+ target := tmpdir
+ err = os.Symlink(target, link)
+ if err != nil {
+ t.Fatal(err)
+ }
+ fi, err := os.Lstat(link)
if err != nil {
t.Fatal(err)
}
- if g, e := h.Name, "some-symlink"; g != e {
+
+ h, err := FileInfoHeader(fi, target)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if g, e := h.Name, fi.Name(); g != e {
t.Errorf("Name = %q; want %q", g, e)
}
- if g, e := h.Linkname, "some-target"; g != e {
+ if g, e := h.Linkname, target; g != e {
t.Errorf("Linkname = %q; want %q", g, e)
}
+ if g, e := h.Typeflag, byte(TypeSymlink); g != e {
+ t.Errorf("Typeflag = %v; want %v", g, e)
+ }
}
-type symlink struct{}
-
-func (symlink) Name() string { return "some-symlink" }
-func (symlink) Size() int64 { return 0 }
-func (symlink) Mode() os.FileMode { return os.ModeSymlink }
-func (symlink) ModTime() time.Time { return time.Time{} }
-func (symlink) IsDir() bool { return false }
-func (symlink) Sys() interface{} { return nil }
-
func TestRoundTrip(t *testing.T) {
data := []byte("some file contents")
var b bytes.Buffer
tw := NewWriter(&b)
hdr := &Header{
- Name: "file.txt",
- Uid: 1 << 21, // too big for 8 octal digits
- Size: int64(len(data)),
- ModTime: time.Now(),
+ Name: "file.txt",
+ Uid: 1 << 21, // too big for 8 octal digits
+ Size: int64(len(data)),
+ // AddDate to strip monotonic clock reading,
+ // and Round to discard sub-second precision,
+ // both of which are not included in the tar header
+ // and would otherwise break the round-trip check
+ // below.
+ ModTime: time.Now().AddDate(0, 0, 0).Round(1 * time.Second),
}
- // tar only supports second precision.
- hdr.ModTime = hdr.ModTime.Add(-time.Duration(hdr.ModTime.Nanosecond()) * time.Nanosecond)
if err := tw.WriteHeader(hdr); err != nil {
t.Fatalf("tw.WriteHeader: %v", err)
}
@@ -139,7 +157,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// regular file.
h: &Header{
Name: "test.txt",
- Mode: 0644 | c_ISREG,
+ Mode: 0644,
Size: 12,
ModTime: time.Unix(1360600916, 0),
Typeflag: TypeReg,
@@ -149,7 +167,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// symbolic link.
h: &Header{
Name: "link.txt",
- Mode: 0777 | c_ISLNK,
+ Mode: 0777,
Size: 0,
ModTime: time.Unix(1360600852, 0),
Typeflag: TypeSymlink,
@@ -159,7 +177,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// character device node.
h: &Header{
Name: "dev/null",
- Mode: 0666 | c_ISCHR,
+ Mode: 0666,
Size: 0,
ModTime: time.Unix(1360578951, 0),
Typeflag: TypeChar,
@@ -169,7 +187,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// block device node.
h: &Header{
Name: "dev/sda",
- Mode: 0660 | c_ISBLK,
+ Mode: 0660,
Size: 0,
ModTime: time.Unix(1360578954, 0),
Typeflag: TypeBlock,
@@ -179,7 +197,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// directory.
h: &Header{
Name: "dir/",
- Mode: 0755 | c_ISDIR,
+ Mode: 0755,
Size: 0,
ModTime: time.Unix(1360601116, 0),
Typeflag: TypeDir,
@@ -189,7 +207,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// fifo node.
h: &Header{
Name: "dev/initctl",
- Mode: 0600 | c_ISFIFO,
+ Mode: 0600,
Size: 0,
ModTime: time.Unix(1360578949, 0),
Typeflag: TypeFifo,
@@ -199,7 +217,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// setuid.
h: &Header{
Name: "bin/su",
- Mode: 0755 | c_ISREG | c_ISUID,
+ Mode: 0755 | c_ISUID,
Size: 23232,
ModTime: time.Unix(1355405093, 0),
Typeflag: TypeReg,
@@ -209,7 +227,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// setguid.
h: &Header{
Name: "group.txt",
- Mode: 0750 | c_ISREG | c_ISGID,
+ Mode: 0750 | c_ISGID,
Size: 0,
ModTime: time.Unix(1360602346, 0),
Typeflag: TypeReg,
@@ -219,7 +237,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// sticky.
h: &Header{
Name: "sticky.txt",
- Mode: 0600 | c_ISREG | c_ISVTX,
+ Mode: 0600 | c_ISVTX,
Size: 7,
ModTime: time.Unix(1360602540, 0),
Typeflag: TypeReg,
@@ -229,7 +247,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// hard link.
h: &Header{
Name: "hard.txt",
- Mode: 0644 | c_ISREG,
+ Mode: 0644,
Size: 0,
Linkname: "file.txt",
ModTime: time.Unix(1360600916, 0),
@@ -240,7 +258,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// More information.
h: &Header{
Name: "info.txt",
- Mode: 0600 | c_ISREG,
+ Mode: 0600,
Size: 0,
Uid: 1000,
Gid: 1000,
diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go
index 596fb8b..c51c243 100644
--- a/libgo/go/archive/tar/writer.go
+++ b/libgo/go/archive/tar/writer.go
@@ -121,9 +121,15 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s)
if needsPaxHeader {
paxHeaders[paxKeyword] = s
- return
}
- f.formatString(b, s)
+
+ // Write string in a best-effort manner to satisfy readers that expect
+ // the field to be non-empty.
+ s = toASCII(s)
+ if len(s) > len(b) {
+ s = s[:len(b)]
+ }
+ f.formatString(b, s) // Should never error
}
var formatNumeric = func(b []byte, x int64, paxKeyword string) {
// Try octal first.
diff --git a/libgo/go/archive/zip/register.go b/libgo/go/archive/zip/register.go
index 2e76386..51e9c3e 100644
--- a/libgo/go/archive/zip/register.go
+++ b/libgo/go/archive/zip/register.go
@@ -103,51 +103,46 @@ func (r *pooledFlateReader) Close() error {
}
var (
- mu sync.RWMutex // guards compressor and decompressor maps
+ compressors sync.Map // map[uint16]Compressor
+ decompressors sync.Map // map[uint16]Decompressor
+)
- compressors = map[uint16]Compressor{
- Store: func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil },
- Deflate: func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil },
- }
+func init() {
+ compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
+ compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
- decompressors = map[uint16]Decompressor{
- Store: ioutil.NopCloser,
- Deflate: newFlateReader,
- }
-)
+ decompressors.Store(Store, Decompressor(ioutil.NopCloser))
+ decompressors.Store(Deflate, Decompressor(newFlateReader))
+}
// RegisterDecompressor allows custom decompressors for a specified method ID.
// The common methods Store and Deflate are built in.
func RegisterDecompressor(method uint16, dcomp Decompressor) {
- mu.Lock()
- defer mu.Unlock()
-
- if _, ok := decompressors[method]; ok {
+ if _, dup := decompressors.LoadOrStore(method, dcomp); dup {
panic("decompressor already registered")
}
- decompressors[method] = dcomp
}
// RegisterCompressor registers custom compressors for a specified method ID.
// The common methods Store and Deflate are built in.
func RegisterCompressor(method uint16, comp Compressor) {
- mu.Lock()
- defer mu.Unlock()
-
- if _, ok := compressors[method]; ok {
+ if _, dup := compressors.LoadOrStore(method, comp); dup {
panic("compressor already registered")
}
- compressors[method] = comp
}
func compressor(method uint16) Compressor {
- mu.RLock()
- defer mu.RUnlock()
- return compressors[method]
+ ci, ok := compressors.Load(method)
+ if !ok {
+ return nil
+ }
+ return ci.(Compressor)
}
func decompressor(method uint16) Decompressor {
- mu.RLock()
- defer mu.RUnlock()
- return decompressors[method]
+ di, ok := decompressors.Load(method)
+ if !ok {
+ return nil
+ }
+ return di.(Decompressor)
}
diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go
index e92d02f..0be210e 100644
--- a/libgo/go/archive/zip/struct.go
+++ b/libgo/go/archive/zip/struct.go
@@ -5,7 +5,7 @@
/*
Package zip provides support for reading and writing ZIP archives.
-See: https://www.pkware.com/documents/casestudies/APPNOTE.TXT
+See: https://www.pkware.com/appnote
This package does not support disk spanning.
diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go
index 8940e25..9f4fcee 100644
--- a/libgo/go/archive/zip/writer.go
+++ b/libgo/go/archive/zip/writer.go
@@ -11,10 +11,9 @@ import (
"hash"
"hash/crc32"
"io"
+ "unicode/utf8"
)
-// TODO(adg): support zip file comments
-
// Writer implements a zip file writer.
type Writer struct {
cw *countWriter
@@ -201,6 +200,20 @@ func (w *Writer) Create(name string) (io.Writer, error) {
return w.CreateHeader(header)
}
+func hasValidUTF8(s string) bool {
+ n := 0
+ for _, r := range s {
+ // By default, ZIP uses CP437, which is only identical to ASCII for the printable characters.
+ if r < 0x20 || r >= 0x7f {
+ if !utf8.ValidRune(r) {
+ return false
+ }
+ n++
+ }
+ }
+ return n > 0
+}
+
// CreateHeader adds a file to the zip file using the provided FileHeader
// for the file metadata.
// It returns a Writer to which the file contents should be written.
@@ -221,6 +234,10 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
fh.Flags |= 0x8 // we will write a data descriptor
+ if hasValidUTF8(fh.Name) || hasValidUTF8(fh.Comment) {
+ fh.Flags |= 0x800 // filename or comment have valid utf-8 string
+ }
+
fh.CreatorVersion = fh.CreatorVersion&0xff00 | zipVersion20 // preserve compatibility byte
fh.ReaderVersion = zipVersion20
diff --git a/libgo/go/archive/zip/writer_test.go b/libgo/go/archive/zip/writer_test.go
index 86841c7..92fb6ec 100644
--- a/libgo/go/archive/zip/writer_test.go
+++ b/libgo/go/archive/zip/writer_test.go
@@ -87,6 +87,69 @@ func TestWriter(t *testing.T) {
}
}
+func TestWriterUTF8(t *testing.T) {
+ var utf8Tests = []struct {
+ name string
+ comment string
+ expect uint16
+ }{
+ {
+ name: "hi, hello",
+ comment: "in the world",
+ expect: 0x8,
+ },
+ {
+ name: "hi, ããã«ã¡ã",
+ comment: "in the world",
+ expect: 0x808,
+ },
+ {
+ name: "hi, hello",
+ comment: "in the ä¸ç",
+ expect: 0x808,
+ },
+ {
+ name: "hi, ããã«ã¡ã",
+ comment: "in the ä¸ç",
+ expect: 0x808,
+ },
+ }
+
+ // write a zip file
+ buf := new(bytes.Buffer)
+ w := NewWriter(buf)
+
+ for _, test := range utf8Tests {
+ h := &FileHeader{
+ Name: test.name,
+ Comment: test.comment,
+ Method: Deflate,
+ }
+ w, err := w.CreateHeader(h)
+ if err != nil {
+ t.Fatal(err)
+ }
+ w.Write([]byte{})
+ }
+
+ if err := w.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ // read it back
+ r, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, test := range utf8Tests {
+ got := r.File[i].Flags
+ t.Logf("name %v, comment %v", test.name, test.comment)
+ if got != test.expect {
+ t.Fatalf("Flags: got %v, want %v", got, test.expect)
+ }
+ }
+}
+
func TestWriterOffset(t *testing.T) {
largeData := make([]byte, 1<<17)
for i := range largeData {
@@ -181,12 +244,11 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
}
func BenchmarkCompressedZipGarbage(b *testing.B) {
- b.ReportAllocs()
- var buf bytes.Buffer
bigBuf := bytes.Repeat([]byte("a"), 1<<20)
- for i := 0; i <= b.N; i++ {
+
+ runOnce := func(buf *bytes.Buffer) {
buf.Reset()
- zw := NewWriter(&buf)
+ zw := NewWriter(buf)
for j := 0; j < 3; j++ {
w, _ := zw.CreateHeader(&FileHeader{
Name: "foo",
@@ -195,11 +257,19 @@ func BenchmarkCompressedZipGarbage(b *testing.B) {
w.Write(bigBuf)
}
zw.Close()
- if i == 0 {
- // Reset the timer after the first time through.
- // This effectively discards the very large initial flate setup cost,
- // as well as the initialization of bigBuf.
- b.ResetTimer()
- }
}
+
+ b.ReportAllocs()
+ // Run once and then reset the timer.
+ // This effectively discards the very large initial flate setup cost,
+ // as well as the initialization of bigBuf.
+ runOnce(&bytes.Buffer{})
+ b.ResetTimer()
+
+ b.RunParallel(func(pb *testing.PB) {
+ var buf bytes.Buffer
+ for pb.Next() {
+ runOnce(&buf)
+ }
+ })
}
diff --git a/libgo/go/archive/zip/zip_test.go b/libgo/go/archive/zip/zip_test.go
index 57edb2c..18c2171 100644
--- a/libgo/go/archive/zip/zip_test.go
+++ b/libgo/go/archive/zip/zip_test.go
@@ -255,7 +255,7 @@ func TestZip64EdgeCase(t *testing.T) {
testZip64DirectoryRecordLength(buf, t)
}
-// Tests that we generate a zip64 file if the the directory at offset
+// 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 {
@@ -681,6 +681,18 @@ func BenchmarkZip64Test(b *testing.B) {
}
}
+func BenchmarkZip64TestSizes(b *testing.B) {
+ for _, size := range []int64{1 << 12, 1 << 20, 1 << 26} {
+ b.Run(fmt.Sprint(size), func(b *testing.B) {
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ testZip64(b, size)
+ }
+ })
+ })
+ }
+}
+
func TestSuffixSaver(t *testing.T) {
const keep = 10
ss := &suffixSaver{keep: keep}
diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go
index e1e8fb2..da94a25 100644
--- a/libgo/go/bufio/bufio.go
+++ b/libgo/go/bufio/bufio.go
@@ -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 bufio implements buffered I/O. It wraps an io.Reader or io.Writer
+// Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer
// object, creating another object (Reader or Writer) that also implements
// the interface but provides buffering and some help for textual I/O.
package bufio
@@ -458,6 +458,7 @@ func (b *Reader) ReadString(delim byte) (string, error) {
}
// WriteTo implements io.WriterTo.
+// This may make multiple calls to the Read method of the underlying Reader.
func (b *Reader) WriteTo(w io.Writer) (n int64, err error) {
n, err = b.writeBuf(w)
if err != nil {
@@ -513,7 +514,7 @@ func (b *Reader) writeBuf(w io.Writer) (int64, error) {
// Writer implements buffering for an io.Writer object.
// If an error occurs writing to a Writer, no more data will be
-// accepted and all subsequent writes will return the error.
+// accepted and all subsequent writes, and Flush, will return the error.
// After all data has been written, the client should call the
// Flush method to guarantee all data has been forwarded to
// the underlying io.Writer.
diff --git a/libgo/go/bufio/scan_test.go b/libgo/go/bufio/scan_test.go
index 1bb1e88..2568225 100644
--- a/libgo/go/bufio/scan_test.go
+++ b/libgo/go/bufio/scan_test.go
@@ -169,7 +169,6 @@ func genLine(buf *bytes.Buffer, lineNum, n int, addNewline bool) {
}
buf.WriteByte('\n')
}
- return
}
// Test the line splitter, including some carriage returns but no long lines.
diff --git a/libgo/go/builtin/builtin.go b/libgo/go/builtin/builtin.go
index 281de0b..1c7c041 100644
--- a/libgo/go/builtin/builtin.go
+++ b/libgo/go/builtin/builtin.go
@@ -85,11 +85,11 @@ type uintptr uintptr
// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
-type byte byte
+type byte = uint8
// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
-type rune rune
+type rune = int32
// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
@@ -179,7 +179,7 @@ func cap(v Type) int
// Channel: The channel's buffer is initialized with the specified
// buffer capacity. If zero, or the size is omitted, the channel is
// unbuffered.
-func make(Type, size IntegerType) Type
+func make(t Type, size ...IntegerType) Type
// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go
index 196419d..20e42bb 100644
--- a/libgo/go/bytes/buffer.go
+++ b/libgo/go/bytes/buffer.go
@@ -15,10 +15,15 @@ import (
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
- buf []byte // contents are the bytes buf[off : len(buf)]
- off int // read at &buf[off], write at &buf[len(buf)]
- bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
- lastRead readOp // last read operation, so that Unread* can work correctly.
+ 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: lastRead can fit in a single byte
+
+ // memory to hold first slice; helps small buffers avoid allocation.
+ // FIXME: it would be advisable to align Buffer to cachelines to avoid false
+ // sharing.
+ bootstrap [64]byte
}
// The readOp constants describe the last action performed on
@@ -68,13 +73,13 @@ func (b *Buffer) Cap() int { return cap(b.buf) }
// but continues to use the same allocated storage.
// It panics if n is negative or greater than the length of the buffer.
func (b *Buffer) Truncate(n int) {
+ if n == 0 {
+ b.Reset()
+ return
+ }
b.lastRead = opInvalid
- switch {
- case n < 0 || n > b.Len():
+ if n < 0 || n > b.Len() {
panic("bytes.Buffer: truncation out of range")
- case n == 0:
- // Reuse buffer space.
- b.off = 0
}
b.buf = b.buf[0 : b.off+n]
}
@@ -82,7 +87,22 @@ func (b *Buffer) Truncate(n int) {
// Reset resets the buffer to be empty,
// but it retains the underlying storage for use by future writes.
// Reset is the same as Truncate(0).
-func (b *Buffer) Reset() { b.Truncate(0) }
+func (b *Buffer) Reset() {
+ b.buf = b.buf[:0]
+ b.off = 0
+ b.lastRead = opInvalid
+}
+
+// tryGrowByReslice is a inlineable version of grow for the fast-case where the
+// internal buffer only needs to be resliced.
+// It returns the index where bytes should be written and whether it succeeded.
+func (b *Buffer) tryGrowByReslice(n int) (int, bool) {
+ if l := len(b.buf); l+n <= cap(b.buf) {
+ b.buf = b.buf[:l+n]
+ return l, true
+ }
+ return 0, false
+}
// grow grows the buffer to guarantee space for n more bytes.
// It returns the index where bytes should be written.
@@ -91,29 +111,33 @@ func (b *Buffer) grow(n int) int {
m := b.Len()
// If buffer is empty, reset to recover space.
if m == 0 && b.off != 0 {
- b.Truncate(0)
+ b.Reset()
}
- if len(b.buf)+n > cap(b.buf) {
- var buf []byte
- if b.buf == nil && n <= len(b.bootstrap) {
- buf = b.bootstrap[0:]
- } else if m+n <= cap(b.buf)/2 {
- // We can slide things down instead of allocating a new
- // slice. We only need m+n <= cap(b.buf) to slide, but
- // we instead let capacity get twice as large so we
- // don't spend all our time copying.
- copy(b.buf[:], b.buf[b.off:])
- buf = b.buf[:m]
- } else {
- // not enough space anywhere
- buf = makeSlice(2*cap(b.buf) + n)
- copy(buf, b.buf[b.off:])
- }
+ // Try to grow by means of a reslice.
+ if i, ok := b.tryGrowByReslice(n); ok {
+ return i
+ }
+ // Check if we can make use of bootstrap array.
+ if b.buf == nil && n <= len(b.bootstrap) {
+ b.buf = b.bootstrap[:n]
+ return 0
+ }
+ if m+n <= cap(b.buf)/2 {
+ // We can slide things down instead of allocating a new
+ // slice. We only need m+n <= cap(b.buf) to slide, but
+ // we instead let capacity get twice as large so we
+ // don't spend all our time copying.
+ copy(b.buf[:], b.buf[b.off:])
+ } else {
+ // Not enough space anywhere, we need to allocate.
+ buf := makeSlice(2*cap(b.buf) + n)
+ copy(buf, b.buf[b.off:])
b.buf = buf
- b.off = 0
}
- b.buf = b.buf[0 : b.off+m+n]
- return b.off + m
+ // Restore b.off and len(b.buf).
+ b.off = 0
+ b.buf = b.buf[:m+n]
+ return m
}
// Grow grows the buffer's capacity, if necessary, to guarantee space for
@@ -134,7 +158,10 @@ func (b *Buffer) Grow(n int) {
// buffer becomes too large, Write will panic with ErrTooLarge.
func (b *Buffer) Write(p []byte) (n int, err error) {
b.lastRead = opInvalid
- m := b.grow(len(p))
+ m, ok := b.tryGrowByReslice(len(p))
+ if !ok {
+ m = b.grow(len(p))
+ }
return copy(b.buf[m:], p), nil
}
@@ -143,7 +170,10 @@ func (b *Buffer) Write(p []byte) (n int, err error) {
// buffer becomes too large, WriteString will panic with ErrTooLarge.
func (b *Buffer) WriteString(s string) (n int, err error) {
b.lastRead = opInvalid
- m := b.grow(len(s))
+ m, ok := b.tryGrowByReslice(len(s))
+ if !ok {
+ m = b.grow(len(s))
+ }
return copy(b.buf[m:], s), nil
}
@@ -161,7 +191,7 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
b.lastRead = opInvalid
// If buffer is empty, reset to recover space.
if b.off >= len(b.buf) {
- b.Truncate(0)
+ b.Reset()
}
for {
if free := cap(b.buf) - len(b.buf); free < MinRead {
@@ -225,7 +255,7 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
}
}
// Buffer is now empty; reset.
- b.Truncate(0)
+ b.Reset()
return
}
@@ -235,7 +265,10 @@ func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
// ErrTooLarge.
func (b *Buffer) WriteByte(c byte) error {
b.lastRead = opInvalid
- m := b.grow(1)
+ m, ok := b.tryGrowByReslice(1)
+ if !ok {
+ m = b.grow(1)
+ }
b.buf[m] = c
return nil
}
@@ -250,7 +283,10 @@ func (b *Buffer) WriteRune(r rune) (n int, err error) {
return 1, nil
}
b.lastRead = opInvalid
- m := b.grow(utf8.UTFMax)
+ m, ok := b.tryGrowByReslice(utf8.UTFMax)
+ if !ok {
+ m = b.grow(utf8.UTFMax)
+ }
n = utf8.EncodeRune(b.buf[m:m+utf8.UTFMax], r)
b.buf = b.buf[:m+n]
return n, nil
@@ -264,7 +300,7 @@ func (b *Buffer) Read(p []byte) (n int, err error) {
b.lastRead = opInvalid
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
- b.Truncate(0)
+ b.Reset()
if len(p) == 0 {
return
}
@@ -302,7 +338,7 @@ func (b *Buffer) ReadByte() (byte, error) {
b.lastRead = opInvalid
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
- b.Truncate(0)
+ b.Reset()
return 0, io.EOF
}
c := b.buf[b.off]
@@ -320,7 +356,7 @@ func (b *Buffer) ReadRune() (r rune, size int, err error) {
b.lastRead = opInvalid
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
- b.Truncate(0)
+ b.Reset()
return 0, 0, io.EOF
}
c := b.buf[b.off]
@@ -337,12 +373,12 @@ func (b *Buffer) ReadRune() (r rune, size int, err error) {
// UnreadRune unreads the last rune returned by ReadRune.
// If the most recent read or write operation on the buffer was
-// not a ReadRune, UnreadRune returns an error. (In this regard
+// not a successful ReadRune, UnreadRune returns an error. (In this regard
// it is stricter than UnreadByte, which will unread the last byte
// from any read operation.)
func (b *Buffer) UnreadRune() error {
if b.lastRead <= opInvalid {
- return errors.New("bytes.Buffer: UnreadRune: previous operation was not ReadRune")
+ return errors.New("bytes.Buffer: UnreadRune: previous operation was not a successful ReadRune")
}
if b.off >= int(b.lastRead) {
b.off -= int(b.lastRead)
@@ -351,12 +387,13 @@ func (b *Buffer) UnreadRune() error {
return nil
}
-// UnreadByte unreads the last byte returned by the most recent
-// read operation. If write has happened since the last read, UnreadByte
-// returns an error.
+// 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 read")
+ return errors.New("bytes.Buffer: UnreadByte: previous operation was not a successful read")
}
b.lastRead = opInvalid
if b.off > 0 {
@@ -404,10 +441,12 @@ func (b *Buffer) ReadString(delim byte) (line string, err error) {
return string(slice), err
}
-// NewBuffer creates and initializes a new Buffer using buf as its initial
-// contents. It is intended to prepare a Buffer to read existing data. It
-// can also be used to size the internal buffer for writing. To do that,
-// buf should have the desired capacity but a length of zero.
+// NewBuffer creates and initializes a new Buffer using buf as its
+// initial contents. The new Buffer takes ownership of buf, and the
+// caller should not use buf after this call. NewBuffer is intended to
+// prepare a Buffer to read existing data. It can also be used to size
+// the internal buffer for writing. To do that, buf should have the
+// desired capacity but a length of zero.
//
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
// sufficient to initialize a Buffer.
diff --git a/libgo/go/bytes/buffer_test.go b/libgo/go/bytes/buffer_test.go
index b1b85f9..ce2f01a 100644
--- a/libgo/go/bytes/buffer_test.go
+++ b/libgo/go/bytes/buffer_test.go
@@ -6,8 +6,10 @@ package bytes_test
import (
. "bytes"
+ "internal/testenv"
"io"
"math/rand"
+ "os/exec"
"runtime"
"testing"
"unicode/utf8"
@@ -311,6 +313,19 @@ func TestRuneIO(t *testing.T) {
// Check that UnreadRune works
buf.Reset()
+
+ // check at EOF
+ if err := buf.UnreadRune(); err == nil {
+ t.Fatal("UnreadRune at EOF: got no error")
+ }
+ if _, _, err := buf.ReadRune(); err == nil {
+ t.Fatal("ReadRune at EOF: got no error")
+ }
+ if err := buf.UnreadRune(); err == nil {
+ t.Fatal("UnreadRune after ReadRune at EOF: got no error")
+ }
+
+ // check not at EOF
buf.Write(b)
for r := rune(0); r < NRune; r++ {
r1, size, _ := buf.ReadRune()
@@ -473,15 +488,34 @@ func TestReadEmptyAtEOF(t *testing.T) {
func TestUnreadByte(t *testing.T) {
b := new(Buffer)
+
+ // check at EOF
+ if err := b.UnreadByte(); err == nil {
+ t.Fatal("UnreadByte at EOF: got no error")
+ }
+ if _, err := b.ReadByte(); err == nil {
+ t.Fatal("ReadByte at EOF: got no error")
+ }
+ if err := b.UnreadByte(); err == nil {
+ t.Fatal("UnreadByte after ReadByte at EOF: got no error")
+ }
+
+ // check not at EOF
b.WriteString("abcdefghijklmnopqrstuvwxyz")
- _, err := b.ReadBytes('m')
- if err != nil {
- t.Fatalf("ReadBytes: %v", err)
+ // after unsuccessful read
+ if n, err := b.Read(nil); n != 0 || err != nil {
+ t.Fatalf("Read(nil) = %d,%v; want 0,nil", n, err)
+ }
+ if err := b.UnreadByte(); err == nil {
+ t.Fatal("UnreadByte after Read(nil): got no error")
}
- err = b.UnreadByte()
- if err != nil {
+ // after successful read
+ if _, err := b.ReadBytes('m'); err != nil {
+ t.Fatalf("ReadBytes: %v", err)
+ }
+ if err := b.UnreadByte(); err != nil {
t.Fatalf("UnreadByte: %v", err)
}
c, err := b.ReadByte()
@@ -514,6 +548,38 @@ func TestBufferGrowth(t *testing.T) {
}
}
+// Test that tryGrowByReslice is inlined.
+// Only execute on "linux-amd64" builder in order to avoid breakage.
+func TestTryGrowByResliceInlined(t *testing.T) {
+ targetBuilder := "linux-amd64"
+ if testenv.Builder() != targetBuilder {
+ t.Skipf("%q gets executed on %q builder only", t.Name(), targetBuilder)
+ }
+ t.Parallel()
+ goBin := testenv.GoToolPath(t)
+ out, err := exec.Command(goBin, "tool", "nm", goBin).CombinedOutput()
+ if err != nil {
+ t.Fatalf("go tool nm: %v: %s", err, out)
+ }
+ // Verify this doesn't exist:
+ sym := "bytes.(*Buffer).tryGrowByReslice"
+ if Contains(out, []byte(sym)) {
+ t.Errorf("found symbol %q in cmd/go, but should be inlined", sym)
+ }
+}
+
+func BenchmarkWriteByte(b *testing.B) {
+ const n = 4 << 10
+ b.SetBytes(n)
+ buf := NewBuffer(make([]byte, n))
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ for i := 0; i < n; i++ {
+ buf.WriteByte('x')
+ }
+ }
+}
+
func BenchmarkWriteRune(b *testing.B) {
const n = 4 << 10
const r = 'âº'
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index 406a3825..7c878af 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -46,36 +46,21 @@ func explode(s []byte, n int) [][]byte {
return a[0:na]
}
-// Count counts the number of non-overlapping instances of sep in s.
-// If sep is an empty slice, Count returns 1 + the number of Unicode code points in s.
-func Count(s, sep []byte) int {
- n := len(sep)
- if n == 0 {
+// countGeneric actually implements Count
+func countGeneric(s, sep []byte) int {
+ // special case
+ if len(sep) == 0 {
return utf8.RuneCount(s) + 1
}
- if n > len(s) {
- return 0
- }
- count := 0
- c := sep[0]
- i := 0
- t := s[:len(s)-n+1]
- for i < len(t) {
- if t[i] != c {
- o := IndexByte(t[i:], c)
- if o < 0 {
- break
- }
- i += o
- }
- if n == 1 || Equal(s[i:i+n], sep) {
- count++
- i += n
- continue
+ n := 0
+ for {
+ i := Index(s, sep)
+ if i == -1 {
+ return n
}
- i++
+ n++
+ s = s[i+len(sep):]
}
- return count
}
// Contains reports whether subslice is within b.
@@ -229,20 +214,21 @@ func genSplit(s, sep []byte, sepSave, n int) [][]byte {
if n < 0 {
n = Count(s, sep) + 1
}
- c := sep[0]
- start := 0
+
a := make([][]byte, n)
- na := 0
- for i := 0; i+len(sep) <= len(s) && na+1 < n; i++ {
- if s[i] == c && (len(sep) == 1 || Equal(s[i:i+len(sep)], sep)) {
- a[na] = s[start : i+sepSave]
- na++
- start = i + len(sep)
- i += len(sep) - 1
+ n--
+ i := 0
+ for i < n {
+ m := Index(s, sep)
+ if m < 0 {
+ break
}
+ a[i] = s[:m+sepSave]
+ s = s[m+len(sep):]
+ i++
}
- a[na] = s[start:]
- return a[0 : na+1]
+ a[i] = s
+ return a[:i+1]
}
// SplitN slices s into subslices separated by sep and returns a slice of
diff --git a/libgo/go/bytes/bytes_amd64.go b/libgo/go/bytes/bytes_amd64.go
index 58a07ef..d40c744 100644
--- a/libgo/go/bytes/bytes_amd64.go
+++ b/libgo/go/bytes/bytes_amd64.go
@@ -6,17 +6,19 @@
package bytes
+import "internal/cpu"
+
//go:noescape
// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s.
// indexShortStr requires 2 <= len(c) <= shortStringLen
-func indexShortStr(s, c []byte) int // ../runtime/asm_$GOARCH.s
-func supportAVX2() bool // ../runtime/asm_$GOARCH.s
+func indexShortStr(s, c []byte) int // ../runtime/asm_amd64.s
+func countByte(s []byte, c byte) int // ../runtime/asm_amd64.s
var shortStringLen int
func init() {
- if supportAVX2() {
+ if cpu.X86.HasAVX2 {
shortStringLen = 63
} else {
shortStringLen = 31
@@ -96,6 +98,15 @@ func Index(s, sep []byte) int {
return -1
}
+// Count counts the number of non-overlapping instances of sep in s.
+// If sep is an empty slice, Count returns 1 + the number of Unicode code points in s.
+func Count(s, sep []byte) int {
+ if len(sep) == 1 && cpu.X86.HasPOPCNT {
+ return countByte(s, sep[0])
+ }
+ return countGeneric(s, sep)
+}
+
// primeRK is the prime base used in Rabin-Karp algorithm.
const primeRK = 16777619
diff --git a/libgo/go/bytes/bytes_generic.go b/libgo/go/bytes/bytes_generic.go
index 91baa22..75a9c36 100644
--- a/libgo/go/bytes/bytes_generic.go
+++ b/libgo/go/bytes/bytes_generic.go
@@ -39,3 +39,9 @@ func Index(s, sep []byte) int {
}
return -1
}
+
+// Count counts the number of non-overlapping instances of sep in s.
+// If sep is an empty slice, Count returns 1 + the number of Unicode code points in s.
+func Count(s, sep []byte) int {
+ return countGeneric(s, sep)
+}
diff --git a/libgo/go/bytes/bytes_s390x.go b/libgo/go/bytes/bytes_s390x.go
index a05ca47..54e013e 100644
--- a/libgo/go/bytes/bytes_s390x.go
+++ b/libgo/go/bytes/bytes_s390x.go
@@ -99,6 +99,12 @@ func Index(s, sep []byte) int {
return -1
}
+// Count counts the number of non-overlapping instances of sep in s.
+// If sep is an empty slice, Count returns 1 + the number of Unicode code points in s.
+func Count(s, sep []byte) int {
+ return countGeneric(s, sep)
+}
+
// primeRK is the prime base used in Rabin-Karp algorithm.
const primeRK = 16777619
diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go
index ad01952..d571eb3 100644
--- a/libgo/go/bytes/bytes_test.go
+++ b/libgo/go/bytes/bytes_test.go
@@ -401,6 +401,79 @@ func TestIndexRune(t *testing.T) {
}
}
+// test count of a single byte across page offsets
+func TestCountByte(t *testing.T) {
+ b := make([]byte, 5015) // bigger than a page
+ windows := []int{1, 2, 3, 4, 15, 16, 17, 31, 32, 33, 63, 64, 65, 128}
+ testCountWindow := func(i, window int) {
+ for j := 0; j < window; j++ {
+ b[i+j] = byte(100)
+ p := Count(b[i:i+window], []byte{100})
+ if p != j+1 {
+ t.Errorf("TestCountByte.Count(%q, 100) = %d", b[i:i+window], p)
+ }
+ pGeneric := CountGeneric(b[i:i+window], []byte{100})
+ if pGeneric != j+1 {
+ t.Errorf("TestCountByte.CountGeneric(%q, 100) = %d", b[i:i+window], p)
+ }
+ }
+ }
+
+ maxWnd := windows[len(windows)-1]
+
+ for i := 0; i <= 2*maxWnd; i++ {
+ for _, window := range windows {
+ if window > len(b[i:]) {
+ window = len(b[i:])
+ }
+ testCountWindow(i, window)
+ for j := 0; j < window; j++ {
+ b[i+j] = byte(0)
+ }
+ }
+ }
+ for i := 4096 - (maxWnd + 1); i < len(b); i++ {
+ for _, window := range windows {
+ if window > len(b[i:]) {
+ window = len(b[i:])
+ }
+ testCountWindow(i, window)
+ for j := 0; j < window; j++ {
+ b[i+j] = byte(0)
+ }
+ }
+ }
+}
+
+// Make sure we don't count bytes outside our window
+func TestCountByteNoMatch(t *testing.T) {
+ b := make([]byte, 5015)
+ windows := []int{1, 2, 3, 4, 15, 16, 17, 31, 32, 33, 63, 64, 65, 128}
+ for i := 0; i <= len(b); i++ {
+ for _, window := range windows {
+ if window > len(b[i:]) {
+ window = len(b[i:])
+ }
+ // Fill the window with non-match
+ for j := 0; j < window; j++ {
+ b[i+j] = byte(100)
+ }
+ // Try to find something that doesn't exist
+ p := Count(b[i:i+window], []byte{0})
+ if p != 0 {
+ t.Errorf("TestCountByteNoMatch(%q, 0) = %d", b[i:i+window], p)
+ }
+ pGeneric := CountGeneric(b[i:i+window], []byte{0})
+ if pGeneric != 0 {
+ t.Errorf("TestCountByteNoMatch.CountGeneric(%q, 100) = %d", b[i:i+window], p)
+ }
+ for j := 0; j < window; j++ {
+ b[i+j] = byte(0)
+ }
+ }
+ }
+}
+
var bmbuf []byte
func valName(x int) string {
@@ -594,6 +667,26 @@ func BenchmarkCountEasy(b *testing.B) {
})
}
+func BenchmarkCountSingle(b *testing.B) {
+ benchBytes(b, indexSizes, func(b *testing.B, n int) {
+ buf := bmbuf[0:n]
+ step := 8
+ for i := 0; i < len(buf); i += step {
+ buf[i] = 1
+ }
+ expect := (len(buf) + (step - 1)) / step
+ for i := 0; i < b.N; i++ {
+ j := Count(buf, []byte{1})
+ if j != expect {
+ b.Fatal("bad count", j, expect)
+ }
+ }
+ for i := 0; i < len(buf); i++ {
+ buf[i] = 0
+ }
+ })
+}
+
type ExplodeTest struct {
s string
n int
@@ -1437,6 +1530,59 @@ func BenchmarkTrimSpace(b *testing.B) {
}
}
+func makeBenchInputHard() []byte {
+ tokens := [...]string{
+ "", "", "", "",
+ "
", "
", "", "",
+ "hello", "world",
+ }
+ x := make([]byte, 0, 1<<20)
+ for {
+ i := rand.Intn(len(tokens))
+ if len(x)+len(tokens[i]) >= 1<<20 {
+ break
+ }
+ x = append(x, tokens[i]...)
+ }
+ return x
+}
+
+var benchInputHard = makeBenchInputHard()
+
+func BenchmarkSplitEmptySeparator(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Split(benchInputHard, nil)
+ }
+}
+
+func BenchmarkSplitSingleByteSeparator(b *testing.B) {
+ sep := []byte("/")
+ for i := 0; i < b.N; i++ {
+ Split(benchInputHard, sep)
+ }
+}
+
+func BenchmarkSplitMultiByteSeparator(b *testing.B) {
+ sep := []byte("hello")
+ for i := 0; i < b.N; i++ {
+ Split(benchInputHard, sep)
+ }
+}
+
+func BenchmarkSplitNSingleByteSeparator(b *testing.B) {
+ sep := []byte("/")
+ for i := 0; i < b.N; i++ {
+ SplitN(benchInputHard, sep, 10)
+ }
+}
+
+func BenchmarkSplitNMultiByteSeparator(b *testing.B) {
+ sep := []byte("hello")
+ for i := 0; i < b.N; i++ {
+ SplitN(benchInputHard, sep, 10)
+ }
+}
+
func BenchmarkRepeat(b *testing.B) {
for i := 0; i < b.N; i++ {
Repeat([]byte("-"), 80)
diff --git a/libgo/go/bytes/example_test.go b/libgo/go/bytes/example_test.go
index 0d35a0d..9397277 100644
--- a/libgo/go/bytes/example_test.go
+++ b/libgo/go/bytes/example_test.go
@@ -30,6 +30,15 @@ func ExampleBuffer_reader() {
// Output: Gophers rule!
}
+func ExampleBuffer_Grow() {
+ var b bytes.Buffer
+ b.Grow(64)
+ bb := b.Bytes()
+ b.Write([]byte("64 bytes or fewer"))
+ fmt.Printf("%q", bb[:b.Len()])
+ // Output: "64 bytes or fewer"
+}
+
func ExampleCompare() {
// Interpret Compare's result by comparing it to zero.
var a, b []byte
diff --git a/libgo/go/bytes/export_test.go b/libgo/go/bytes/export_test.go
index f61523e..823c8b0 100644
--- a/libgo/go/bytes/export_test.go
+++ b/libgo/go/bytes/export_test.go
@@ -7,3 +7,4 @@ package bytes
// Export func for testing
var IndexBytePortable = indexBytePortable
var EqualPortable = equalPortable
+var CountGeneric = countGeneric
diff --git a/libgo/go/cmd/cgo/ast.go b/libgo/go/cmd/cgo/ast.go
index 8ce8241..7122a9d 100644
--- a/libgo/go/cmd/cgo/ast.go
+++ b/libgo/go/cmd/cgo/ast.go
@@ -17,8 +17,8 @@ import (
"strings"
)
-func parse(name string, flags parser.Mode) *ast.File {
- ast1, err := parser.ParseFile(fset, name, nil, flags)
+func parse(name string, src []byte, flags parser.Mode) *ast.File {
+ ast1, err := parser.ParseFile(fset, name, src, flags)
if err != nil {
if list, ok := err.(scanner.ErrorList); ok {
// If err is a scanner.ErrorList, its String will print just
@@ -39,12 +39,12 @@ func sourceLine(n ast.Node) int {
return fset.Position(n.Pos()).Line
}
-// ReadGo populates f with information learned from reading the
-// Go source file with the given file name. It gathers the C preamble
+// ParseGo populates f with information learned from the Go source code
+// which was read from the named file. It gathers the C preamble
// attached to the import "C" comment, a list of references to C.xxx,
// a list of exported functions, and the actual AST, to be rewritten and
// printed.
-func (f *File) ReadGo(name string) {
+func (f *File) ParseGo(name string, src []byte) {
// Create absolute path for file, so that it will be used in error
// messages and recorded in debug line number information.
// This matches the rest of the toolchain. See golang.org/issue/5122.
@@ -58,8 +58,8 @@ func (f *File) ReadGo(name string) {
// so we use ast1 to look for the doc comments on import "C"
// and on exported functions, and we use ast2 for translating
// and reprinting.
- ast1 := parse(name, parser.ParseComments)
- ast2 := parse(name, 0)
+ ast1 := parse(name, src, parser.ParseComments)
+ ast2 := parse(name, src, 0)
f.Package = ast1.Name.Name
f.Name = make(map[string]*Name)
diff --git a/libgo/go/cmd/cgo/doc.go b/libgo/go/cmd/cgo/doc.go
index 85441e6..b238882 100644
--- a/libgo/go/cmd/cgo/doc.go
+++ b/libgo/go/cmd/cgo/doc.go
@@ -14,27 +14,27 @@ as C.stdout, or functions such as C.putchar.
If the import of "C" is immediately preceded by a comment, that
comment, called the preamble, is used as a header when compiling
-the C parts of the package. For example:
+the C parts of the package. For example:
// #include
// #include
import "C"
The preamble may contain any C code, including function and variable
-declarations and definitions. These may then be referred to from Go
-code as though they were defined in the package "C". All names
+declarations and definitions. These may then be referred to from Go
+code as though they were defined in the package "C". All names
declared in the preamble may be used, even if they start with a
-lower-case letter. Exception: static variables in the preamble may
+lower-case letter. Exception: static variables in the preamble may
not be referenced from Go code; static functions are permitted.
-See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See
+See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See
"C? Go? Cgo!" for an introduction to using cgo:
https://golang.org/doc/articles/c_go_cgo.html.
CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS and LDFLAGS may be defined with pseudo
#cgo directives within these comments to tweak the behavior of the C, C++
-or Fortran compiler. Values defined in multiple directives are concatenated
-together. The directive can include a list of build constraints limiting its
+or Fortran compiler. Values defined in multiple directives are concatenated
+together. The directive can include a list of build constraints limiting its
effect to systems satisfying one of the constraints
(see https://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax).
For example:
@@ -57,16 +57,16 @@ The default pkg-config tool may be changed by setting the PKG_CONFIG environment
When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and
CGO_LDFLAGS environment variables are added to the flags derived from
-these directives. Package-specific flags should be set using the
+these directives. Package-specific flags should be set using the
directives, not the environment variables, so that builds work in
unmodified environments.
All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and
-used to compile C files in that package. All the CPPFLAGS and CXXFLAGS
+used to compile C files in that package. All the CPPFLAGS and CXXFLAGS
directives in a package are concatenated and used to compile C++ files in that
-package. All the CPPFLAGS and FFLAGS directives in a package are concatenated
-and used to compile Fortran files in that package. All the LDFLAGS directives
-in any package in the program are concatenated and used at link time. All the
+package. All the CPPFLAGS and FFLAGS directives in a package are concatenated
+and used to compile Fortran files in that package. All the LDFLAGS directives
+in any package in the program are concatenated and used at link time. All the
pkg-config directives are concatenated and sent to pkg-config simultaneously
to add to each appropriate set of command-line flags.
@@ -84,27 +84,27 @@ Will be expanded to:
When the Go tool sees that one or more Go files use the special import
"C", it will look for other non-Go files in the directory and compile
-them as part of the Go package. Any .c, .s, or .S files will be
-compiled with the C compiler. Any .cc, .cpp, or .cxx files will be
-compiled with the C++ compiler. Any .f, .F, .for or .f90 files will be
+them as part of the Go package. Any .c, .s, or .S files will be
+compiled with the C compiler. Any .cc, .cpp, or .cxx files will be
+compiled with the C++ compiler. Any .f, .F, .for or .f90 files will be
compiled with the fortran compiler. Any .h, .hh, .hpp, or .hxx files will
not be compiled separately, but, if these header files are changed,
-the C and C++ files will be recompiled. The default C and C++
+the C and C++ files will be recompiled. The default C and C++
compilers may be changed by the CC and CXX environment variables,
respectively; those environment variables may include command line
options.
The cgo tool is enabled by default for native builds on systems where
-it is expected to work. It is disabled by default when
-cross-compiling. You can control this by setting the CGO_ENABLED
+it is expected to work. It is disabled by default when
+cross-compiling. You can control this by setting the CGO_ENABLED
environment variable when running the go tool: set it to 1 to enable
-the use of cgo, and to 0 to disable it. The go tool will set the
+the use of cgo, and to 0 to disable it. The go tool will set the
build constraint "cgo" if cgo is enabled.
When cross-compiling, you must specify a C cross-compiler for cgo to
-use. You can do this by setting the CC_FOR_TARGET environment
+use. You can do this by setting the CC_FOR_TARGET environment
variable when building the toolchain using make.bash, or by setting
-the CC environment variable any time you run the go tool. The
+the CC environment variable any time you run the go tool. The
CXX_FOR_TARGET and CXX environment variables work in a similar way for
C++ code.
@@ -138,7 +138,7 @@ C's union types are represented as a Go byte array with the same length.
Go structs cannot embed fields with C types.
Go code cannot refer to zero-sized fields that occur at the end of
-non-empty C structs. To get the address of such a field (which is the
+non-empty C structs. To get the address of such a field (which is the
only operation you can do with a zero-sized field) you must take the
address of the struct and add the size of the struct.
@@ -150,7 +150,7 @@ is different from the same C type used in another.
Any C function (even void functions) may be called in a multiple
assignment context to retrieve both the return value (if any) and the
C errno variable as an error (use _ to skip the result value if the
-function returns void). For example:
+function returns void). For example:
n, err = C.sqrt(-1)
_, err := C.voidFunc()
@@ -187,11 +187,11 @@ received from Go. For example:
In C, a function argument written as a fixed size array
actually requires a pointer to the first element of the array.
C compilers are aware of this calling convention and adjust
-the call accordingly, but Go cannot. In Go, you must pass
+the call accordingly, but Go cannot. In Go, you must pass
the pointer to the first element explicitly: C.f(&C.x[0]).
A few special functions convert between Go and C types
-by making copies of the data. In pseudo-Go definitions:
+by making copies of the data. In pseudo-Go definitions:
// Go string to C string
// The C string is allocated in the C heap using malloc.
@@ -253,50 +253,50 @@ must be placed in preambles in other files, or in C source files.
Passing pointers
Go is a garbage collected language, and the garbage collector needs to
-know the location of every pointer to Go memory. Because of this,
+know the location of every pointer to Go memory. Because of this,
there are restrictions on passing pointers between Go and C.
In this section the term Go pointer means a pointer to memory
allocated by Go (such as by using the & operator or calling the
predefined new function) and the term C pointer means a pointer to
-memory allocated by C (such as by a call to C.malloc). Whether a
+memory allocated by C (such as by a call to C.malloc). Whether a
pointer is a Go pointer or a C pointer is a dynamic property
determined by how the memory was allocated; it has nothing to do with
the type of the pointer.
Go code may pass a Go pointer to C provided the Go memory to which it
-points does not contain any Go pointers. The C code must preserve
+points does not contain any Go pointers. The C code must preserve
this property: it must not store any Go pointers in Go memory, even
-temporarily. When passing a pointer to a field in a struct, the Go
+temporarily. When passing a pointer to a field in a struct, the Go
memory in question is the memory occupied by the field, not the entire
-struct. When passing a pointer to an element in an array or slice,
+struct. When passing a pointer to an element in an array or slice,
the Go memory in question is the entire array or the entire backing
array of the slice.
C code may not keep a copy of a Go pointer after the call returns.
-A Go function called by C code may not return a Go pointer. A Go
+A Go function called by C code may not return a Go pointer. A Go
function called by C code may take C pointers as arguments, and it may
store non-pointer or C pointer data through those pointers, but it may
-not store a Go pointer in memory pointed to by a C pointer. A Go
+not store a Go pointer in memory pointed to by a C pointer. A Go
function called by C code may take a Go pointer as an argument, but it
must preserve the property that the Go memory to which it points does
not contain any Go pointers.
-Go code may not store a Go pointer in C memory. C code may store Go
+Go code may not store a Go pointer in C memory. C code may store Go
pointers in C memory, subject to the rule above: it must stop storing
the Go pointer when the C function returns.
-These rules are checked dynamically at runtime. The checking is
+These rules are checked dynamically at runtime. The checking is
controlled by the cgocheck setting of the GODEBUG environment
-variable. The default setting is GODEBUG=cgocheck=1, which implements
-reasonably cheap dynamic checks. These checks may be disabled
-entirely using GODEBUG=cgocheck=0. Complete checking of pointer
+variable. The default setting is GODEBUG=cgocheck=1, which implements
+reasonably cheap dynamic checks. These checks may be disabled
+entirely using GODEBUG=cgocheck=0. Complete checking of pointer
handling, at some cost in run time, is available via GODEBUG=cgocheck=2.
It is possible to defeat this enforcement by using the unsafe package,
and of course there is nothing stopping the C code from doing anything
-it likes. However, programs that break these rules are likely to fail
+it likes. However, programs that break these rules are likely to fail
in unexpected and unpredictable ways.
Using cgo directly
@@ -499,7 +499,7 @@ Here is a _cgo_gotypes.go containing definitions for needed C types:
type _Ctype_void [0]byte
The _cgo_gotypes.go file also contains the definitions of the
-functions. They all have similar bodies that invoke runtime·cgocall
+functions. They all have similar bodies that invoke runtime·cgocall
to make a switch from the Go runtime world to the system C (GCC-based)
world.
@@ -835,7 +835,7 @@ to avoid conflicts), write the go.o file to that directory, and invoke
the host linker. The default value for the host linker is $CC, split
into fields, or else "gcc". The specific host linker command line can
be overridden using command line flags: cmd/link -extld=clang
--extldflags='-ggdb -O3'. If any package in a build includes a .cc or
+-extldflags='-ggdb -O3'. If any package in a build includes a .cc or
other file compiled by the C++ compiler, the go tool will use the
-extld option to set the host linker to the C++ compiler.
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go
index 028804e..03239a0 100644
--- a/libgo/go/cmd/cgo/gcc.go
+++ b/libgo/go/cmd/cgo/gcc.go
@@ -20,6 +20,7 @@ import (
"go/ast"
"go/parser"
"go/token"
+ "math"
"os"
"strconv"
"strings"
@@ -259,26 +260,26 @@ func (p *Package) guessKinds(f *File) []*Name {
// If we've already found this name as a #define
// and we can translate it as a constant value, do so.
if n.Define != "" {
- isConst := false
- if _, err := strconv.Atoi(n.Define); err == nil {
- isConst = true
- } else if n.Define[0] == '"' || n.Define[0] == '\'' {
- if _, err := parser.ParseExpr(n.Define); err == nil {
- isConst = true
- }
- }
- if isConst {
- n.Kind = "const"
+ if i, err := strconv.ParseInt(n.Define, 0, 64); err == nil {
+ n.Kind = "iconst"
// Turn decimal into hex, just for consistency
// with enum-derived constants. Otherwise
// in the cgo -godefs output half the constants
// are in hex and half are in whatever the #define used.
- i, err := strconv.ParseInt(n.Define, 0, 64)
- if err == nil {
- n.Const = fmt.Sprintf("%#x", i)
- } else {
+ n.Const = fmt.Sprintf("%#x", i)
+ } else if n.Define[0] == '\'' {
+ if _, err := parser.ParseExpr(n.Define); err == nil {
+ n.Kind = "iconst"
n.Const = n.Define
}
+ } else if n.Define[0] == '"' {
+ if _, err := parser.ParseExpr(n.Define); err == nil {
+ n.Kind = "sconst"
+ n.Const = n.Define
+ }
+ }
+
+ if n.IsConst() {
continue
}
@@ -287,11 +288,10 @@ func (p *Package) guessKinds(f *File) []*Name {
}
}
- needType = append(needType, n)
-
// If this is a struct, union, or enum type name, no need to guess the kind.
if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
n.Kind = "type"
+ needType = append(needType, n)
continue
}
@@ -317,14 +317,24 @@ func (p *Package) guessKinds(f *File) []*Name {
// void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; }
// #line xxx "not-type"
// void __cgo_f_xxx_2(void) { name *__cgo_undefined__; }
- // #line xxx "not-const"
+ // #line xxx "not-int-const"
// void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; }
+ // #line xxx "not-num-const"
+ // void __cgo_f_xxx_4(void) { static const double x = (name); }
+ // #line xxx "not-str-lit"
+ // void __cgo_f_xxx_5(void) { static const char x[] = (name); }
+ // #line xxx "not-signed-int-const"
+ // #if 0 < -(name)
+ // #line xxx "not-signed-int-const"
+ // #error found unsigned int
+ // #endif
//
// If we see an error at not-declared:xxx, the corresponding name is not declared.
// If we see an error at not-type:xxx, the corresponding name is a type.
- // If we see an error at not-const:xxx, the corresponding name is not an integer constant.
- // If we see no errors, we assume the name is an expression but not a constant
- // (so a variable or a function).
+ // If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
+ // If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
+ // If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
+ // If we see an error at not-signed-int-const:xxx, the corresponding name is not a signed integer literal.
//
// The specific input forms are chosen so that they are valid C syntax regardless of
// whether name denotes a type or an expression.
@@ -338,11 +348,24 @@ func (p *Package) guessKinds(f *File) []*Name {
"void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+
"#line %d \"not-type\"\n"+
"void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+
- "#line %d \"not-const\"\n"+
- "void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n",
+ "#line %d \"not-int-const\"\n"+
+ "void __cgo_f_%d_3(void) { enum { __cgo_undefined__ = (%s)*1 }; }\n"+
+ "#line %d \"not-num-const\"\n"+
+ "void __cgo_f_%d_4(void) { static const double x = (%s); }\n"+
+ "#line %d \"not-str-lit\"\n"+
+ "void __cgo_f_%d_5(void) { static const char s[] = (%s); }\n"+
+ "#line %d \"not-signed-int-const\"\n"+
+ "#if 0 < (%s)\n"+
+ "#line %d \"not-signed-int-const\"\n"+
+ "#error found unsigned int\n"+
+ "#endif\n",
+ i+1, i+1, n.C,
+ i+1, i+1, n.C,
i+1, i+1, n.C,
i+1, i+1, n.C,
- i+1, i+1, n.C)
+ i+1, i+1, n.C,
+ i+1, n.C, i+1,
+ )
}
fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
"int __cgo__1 = __cgo__2;\n")
@@ -356,13 +379,23 @@ func (p *Package) guessKinds(f *File) []*Name {
sniff := make([]int, len(names))
const (
notType = 1 << iota
- notConst
+ notIntConst
+ notNumConst
+ notStrLiteral
notDeclared
+ notSignedIntConst
)
+ sawUnmatchedErrors := false
for _, line := range strings.Split(stderr, "\n") {
- if !strings.Contains(line, ": error:") {
- // we only care about errors.
- // we tried to turn off warnings on the command line, but one never knows.
+ // Ignore warnings and random comments, with one
+ // exception: newer GCC versions will sometimes emit
+ // an error on a macro #define with a note referring
+ // to where the expansion occurs. We care about where
+ // the expansion occurs, so in that case treat the note
+ // as an error.
+ isError := strings.Contains(line, ": error:")
+ isErrorNote := strings.Contains(line, ": note:") && sawUnmatchedErrors
+ if !isError && !isErrorNote {
continue
}
@@ -380,6 +413,9 @@ func (p *Package) guessKinds(f *File) []*Name {
i, _ := strconv.Atoi(line[c1+1 : c2])
i--
if i < 0 || i >= len(names) {
+ if isError {
+ sawUnmatchedErrors = true
+ }
continue
}
@@ -395,9 +431,22 @@ func (p *Package) guessKinds(f *File) []*Name {
sniff[i] |= notDeclared
case "not-type":
sniff[i] |= notType
- case "not-const":
- sniff[i] |= notConst
+ case "not-int-const":
+ sniff[i] |= notIntConst
+ case "not-num-const":
+ sniff[i] |= notNumConst
+ case "not-str-lit":
+ sniff[i] |= notStrLiteral
+ case "not-signed-int-const":
+ sniff[i] |= notSignedIntConst
+ default:
+ if isError {
+ sawUnmatchedErrors = true
+ }
+ continue
}
+
+ sawUnmatchedErrors = false
}
if !completed {
@@ -405,14 +454,29 @@ func (p *Package) guessKinds(f *File) []*Name {
}
for i, n := range names {
- switch sniff[i] {
+ switch sniff[i] &^ notSignedIntConst {
default:
- error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go))
- case notType:
- n.Kind = "const"
- case notConst:
+ var tpos token.Pos
+ for _, ref := range f.Ref {
+ if ref.Name == n {
+ tpos = ref.Pos()
+ break
+ }
+ }
+ error_(tpos, "could not determine kind of name for C.%s", fixGo(n.Go))
+ case notStrLiteral | notType:
+ if sniff[i]¬SignedIntConst != 0 {
+ n.Kind = "uconst"
+ } else {
+ n.Kind = "iconst"
+ }
+ case notIntConst | notStrLiteral | notType:
+ n.Kind = "fconst"
+ case notIntConst | notNumConst | notType:
+ n.Kind = "sconst"
+ case notIntConst | notNumConst | notStrLiteral:
n.Kind = "type"
- case notConst | notType:
+ case notIntConst | notNumConst | notStrLiteral | notType:
n.Kind = "not-type"
}
}
@@ -450,18 +514,16 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
for i, n := range names {
fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
- if n.Kind == "const" {
+ if n.Kind == "iconst" || n.Kind == "uconst" {
fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
}
}
- // Apple's LLVM-based gcc does not include the enumeration
- // names and values in its DWARF debug output. In case we're
- // using such a gcc, create a data block initialized with the values.
- // We can read them out of the object file.
- fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n")
+ // We create a data block initialized with the values,
+ // so we can read them out of the object file.
+ fmt.Fprintf(&b, "long long __cgodebug_ints[] = {\n")
for _, n := range names {
- if n.Kind == "const" {
+ if n.Kind == "iconst" || n.Kind == "uconst" {
fmt.Fprintf(&b, "\t%s,\n", n.C)
} else {
fmt.Fprintf(&b, "\t0,\n")
@@ -475,15 +537,30 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
fmt.Fprintf(&b, "\t1\n")
fmt.Fprintf(&b, "};\n")
- d, bo, debugData := p.gccDebug(b.Bytes())
- enumVal := make([]int64, len(debugData)/8)
- for i := range enumVal {
- enumVal[i] = int64(bo.Uint64(debugData[i*8:]))
+ // do the same work for floats.
+ fmt.Fprintf(&b, "double __cgodebug_floats[] = {\n")
+ for _, n := range names {
+ if n.Kind == "fconst" {
+ fmt.Fprintf(&b, "\t%s,\n", n.C)
+ } else {
+ fmt.Fprintf(&b, "\t0,\n")
+ }
+ }
+ fmt.Fprintf(&b, "\t1\n")
+ fmt.Fprintf(&b, "};\n")
+
+ // do the same work for strings.
+ for i, n := range names {
+ if n.Kind == "sconst" {
+ fmt.Fprintf(&b, "const char __cgodebug_str__%d[] = %s;\n", i, n.C)
+ fmt.Fprintf(&b, "const unsigned long long __cgodebug_strlen__%d = sizeof(%s)-1;\n", i, n.C)
+ }
}
+ d, ints, floats, strs := p.gccDebug(b.Bytes(), len(names))
+
// Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
types := make([]dwarf.Type, len(names))
- enums := make([]dwarf.Offset, len(names))
nameToIndex := make(map[*Name]int)
for i, n := range names {
nameToIndex[n] = i
@@ -502,26 +579,6 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
break
}
switch e.Tag {
- case dwarf.TagEnumerationType:
- offset := e.Offset
- for {
- e, err := r.Next()
- if err != nil {
- fatalf("reading DWARF entry: %s", err)
- }
- if e.Tag == 0 {
- break
- }
- if e.Tag == dwarf.TagEnumerator {
- entryName := e.Val(dwarf.AttrName).(string)
- if strings.HasPrefix(entryName, "__cgo_enum__") {
- n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):])
- if 0 <= n && n < len(names) {
- enums[n] = offset
- }
- }
- }
- }
case dwarf.TagVariable:
name, _ := e.Val(dwarf.AttrName).(string)
typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
@@ -548,15 +605,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
if err != nil {
fatalf("malformed __cgo__ name: %s", name)
}
- if enums[i] != 0 {
- t, err := d.Type(enums[i])
- if err != nil {
- fatalf("loading DWARF type: %s", err)
- }
- types[i] = t
- } else {
- types[i] = t.Type
- }
+ types[i] = t.Type
}
if e.Tag != dwarf.TagCompileUnit {
r.SkipChildren()
@@ -580,17 +629,23 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
n.FuncType = conv.FuncType(f, pos)
} else {
n.Type = conv.Type(types[i], pos)
- if enums[i] != 0 && n.Type.EnumValues != nil {
- k := fmt.Sprintf("__cgo_enum__%d", i)
- n.Kind = "const"
- n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k])
- // Remove injected enum to ensure the value will deep-compare
- // equally in future loads of the same constant.
- delete(n.Type.EnumValues, k)
- }
- // Prefer debug data over DWARF debug output, if we have it.
- if n.Kind == "const" && i < len(enumVal) {
- n.Const = fmt.Sprintf("%#x", enumVal[i])
+ switch n.Kind {
+ case "iconst":
+ if i < len(ints) {
+ n.Const = fmt.Sprintf("%#x", ints[i])
+ }
+ case "uconst":
+ if i < len(ints) {
+ n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
+ }
+ case "fconst":
+ if i < len(floats) {
+ n.Const = fmt.Sprintf("%f", floats[i])
+ }
+ case "sconst":
+ if i < len(strs) {
+ n.Const = fmt.Sprintf("%q", strs[i])
+ }
}
}
conv.FinishType(pos)
@@ -1069,7 +1124,7 @@ func (p *Package) rewriteRef(f *File) {
// are trying to do a ,err call. Also check that
// functions are only used in calls.
for _, r := range f.Ref {
- if r.Name.Kind == "const" && r.Name.Const == "" {
+ if r.Name.IsConst() && r.Name.Const == "" {
error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
}
var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default
@@ -1109,6 +1164,10 @@ func (p *Package) rewriteRef(f *File) {
}
case "expr":
if r.Name.Kind == "func" {
+ if builtinDefs[r.Name.C] != "" {
+ error_(r.Pos(), "use of builtin '%s' not in function call", fixGo(r.Name.C))
+ }
+
// Function is being used in an expression, to e.g. pass around a C function pointer.
// Create a new Name for this Ref which causes the variable to be declared in Go land.
fpName := "fp_" + r.Name.Go
@@ -1277,12 +1336,55 @@ func (p *Package) gccCmd() []string {
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
// returns the corresponding DWARF data and, if present, debug data block.
-func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) {
+func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int64, floats []float64, strs []string) {
runGcc(stdin, p.gccCmd())
- isDebugData := func(s string) bool {
+ isDebugInts := func(s string) bool {
+ // Some systems use leading _ to denote non-assembly symbols.
+ return s == "__cgodebug_ints" || s == "___cgodebug_ints"
+ }
+ isDebugFloats := func(s string) bool {
+ // Some systems use leading _ to denote non-assembly symbols.
+ return s == "__cgodebug_floats" || s == "___cgodebug_floats"
+ }
+ indexOfDebugStr := func(s string) int {
+ // Some systems use leading _ to denote non-assembly symbols.
+ if strings.HasPrefix(s, "___") {
+ s = s[1:]
+ }
+ if strings.HasPrefix(s, "__cgodebug_str__") {
+ if n, err := strconv.Atoi(s[len("__cgodebug_str__"):]); err == nil {
+ return n
+ }
+ }
+ return -1
+ }
+ indexOfDebugStrlen := func(s string) int {
// Some systems use leading _ to denote non-assembly symbols.
- return s == "__cgodebug_data" || s == "___cgodebug_data"
+ if strings.HasPrefix(s, "___") {
+ s = s[1:]
+ }
+ if strings.HasPrefix(s, "__cgodebug_strlen__") {
+ if n, err := strconv.Atoi(s[len("__cgodebug_strlen__"):]); err == nil {
+ return n
+ }
+ }
+ return -1
+ }
+
+ strs = make([]string, nnames)
+
+ strdata := make(map[int]string, nnames)
+ strlens := make(map[int]int, nnames)
+
+ buildStrings := func() {
+ for n, strlen := range strlens {
+ data := strdata[n]
+ if len(data) <= strlen {
+ fatalf("invalid string literal")
+ }
+ strs[n] = string(data[:strlen])
+ }
}
if f, err := macho.Open(gccTmp()); err == nil {
@@ -1291,24 +1393,76 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
if err != nil {
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
}
- var data []byte
+ bo := f.ByteOrder
if f.Symtab != nil {
for i := range f.Symtab.Syms {
s := &f.Symtab.Syms[i]
- if isDebugData(s.Name) {
+ switch {
+ case isDebugInts(s.Name):
// Found it. Now find data section.
if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
if sdat, err := sect.Data(); err == nil {
- data = sdat[s.Value-sect.Addr:]
+ data := sdat[s.Value-sect.Addr:]
+ ints = make([]int64, len(data)/8)
+ for i := range ints {
+ ints[i] = int64(bo.Uint64(data[i*8:]))
+ }
}
}
}
+ case isDebugFloats(s.Name):
+ // Found it. Now find data section.
+ if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value-sect.Addr:]
+ floats = make([]float64, len(data)/8)
+ for i := range floats {
+ floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
+ }
+ }
+ }
+ }
+ default:
+ if n := indexOfDebugStr(s.Name); n != -1 {
+ // Found it. Now find data section.
+ if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value-sect.Addr:]
+ strdata[n] = string(data)
+ }
+ }
+ }
+ break
+ }
+ if n := indexOfDebugStrlen(s.Name); n != -1 {
+ // Found it. Now find data section.
+ if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value-sect.Addr:]
+ strlen := bo.Uint64(data[:8])
+ if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
+ fatalf("string literal too big")
+ }
+ strlens[n] = int(strlen)
+ }
+ }
+ }
+ break
+ }
}
}
+
+ buildStrings()
}
- return d, f.ByteOrder, data
+ return d, ints, floats, strs
}
if f, err := elf.Open(gccTmp()); err == nil {
@@ -1317,25 +1471,77 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
if err != nil {
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
}
- var data []byte
+ bo := f.ByteOrder
symtab, err := f.Symbols()
if err == nil {
for i := range symtab {
s := &symtab[i]
- if isDebugData(s.Name) {
+ switch {
+ case isDebugInts(s.Name):
+ // Found it. Now find data section.
+ if i := int(s.Section); 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value-sect.Addr:]
+ ints = make([]int64, len(data)/8)
+ for i := range ints {
+ ints[i] = int64(bo.Uint64(data[i*8:]))
+ }
+ }
+ }
+ }
+ case isDebugFloats(s.Name):
// Found it. Now find data section.
if i := int(s.Section); 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
if sdat, err := sect.Data(); err == nil {
- data = sdat[s.Value-sect.Addr:]
+ data := sdat[s.Value-sect.Addr:]
+ floats = make([]float64, len(data)/8)
+ for i := range floats {
+ floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
+ }
+ }
+ }
+ }
+ default:
+ if n := indexOfDebugStr(s.Name); n != -1 {
+ // Found it. Now find data section.
+ if i := int(s.Section); 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value-sect.Addr:]
+ strdata[n] = string(data)
+ }
}
}
+ break
+ }
+ if n := indexOfDebugStrlen(s.Name); n != -1 {
+ // Found it. Now find data section.
+ if i := int(s.Section); 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value-sect.Addr:]
+ strlen := bo.Uint64(data[:8])
+ if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
+ fatalf("string literal too big")
+ }
+ strlens[n] = int(strlen)
+ }
+ }
+ }
+ break
}
}
}
+
+ buildStrings()
}
- return d, f.ByteOrder, data
+ return d, ints, floats, strs
}
if f, err := pe.Open(gccTmp()); err == nil {
@@ -1344,20 +1550,70 @@ func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte)
if err != nil {
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
}
- var data []byte
+ bo := binary.LittleEndian
for _, s := range f.Symbols {
- if isDebugData(s.Name) {
+ switch {
+ case isDebugInts(s.Name):
if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
sect := f.Sections[i]
if s.Value < sect.Size {
if sdat, err := sect.Data(); err == nil {
- data = sdat[s.Value:]
+ data := sdat[s.Value:]
+ ints = make([]int64, len(data)/8)
+ for i := range ints {
+ ints[i] = int64(bo.Uint64(data[i*8:]))
+ }
+ }
+ }
+ }
+ case isDebugFloats(s.Name):
+ if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if s.Value < sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value:]
+ floats = make([]float64, len(data)/8)
+ for i := range floats {
+ floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
+ }
}
}
}
+ default:
+ if n := indexOfDebugStr(s.Name); n != -1 {
+ if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if s.Value < sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value:]
+ strdata[n] = string(data)
+ }
+ }
+ }
+ break
+ }
+ if n := indexOfDebugStrlen(s.Name); n != -1 {
+ if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
+ sect := f.Sections[i]
+ if s.Value < sect.Size {
+ if sdat, err := sect.Data(); err == nil {
+ data := sdat[s.Value:]
+ strlen := bo.Uint64(data[:8])
+ if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
+ fatalf("string literal too big")
+ }
+ strlens[n] = int(strlen)
+ }
+ }
+ }
+ break
+ }
}
}
- return d, binary.LittleEndian, data
+
+ buildStrings()
+
+ return d, ints, floats, strs
}
fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp())
@@ -2048,7 +2304,7 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
}
var r *Type
var gr []*ast.Field
- if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok {
+ if _, ok := base(dtype.ReturnType).(*dwarf.VoidType); ok {
gr = []*ast.Field{{Type: c.goVoid}}
} else if dtype.ReturnType != nil {
r = c.Type(unqual(dtype.ReturnType), pos)
diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go
index ac10205..c9a44fd 100644
--- a/libgo/go/cmd/cgo/main.go
+++ b/libgo/go/cmd/cgo/main.go
@@ -17,7 +17,7 @@ import (
"go/ast"
"go/printer"
"go/token"
- "io"
+ "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -88,7 +88,7 @@ type Name struct {
Mangle string // name used in generated Go
C string // name used in C
Define string // #define expansion
- Kind string // "const", "type", "var", "fpvar", "func", "not-type"
+ Kind string // "iconst", "uconst", "fconst", "sconst", "type", "var", "fpvar", "func", "not-type"
Type *Type // the type of xxx
FuncType *FuncType
AddError bool
@@ -100,6 +100,11 @@ func (n *Name) IsVar() bool {
return n.Kind == "var" || n.Kind == "fpvar"
}
+// IsConst reports whether Kind is either "iconst", "uconst", "fconst" or "sconst"
+func (n *Name) IsConst() bool {
+ return strings.HasSuffix(n.Kind, "const")
+}
+
// A ExpFunc is an exported function, callable from C.
// Such functions are identified in the Go input file
// by doc comments containing the line //export ExpName
@@ -274,30 +279,28 @@ func main() {
// concern is other cgo wrappers for the same functions.
// Use the beginning of the md5 of the input to disambiguate.
h := md5.New()
- for _, input := range goFiles {
+ fs := make([]*File, len(goFiles))
+ for i, input := range goFiles {
if *srcDir != "" {
input = filepath.Join(*srcDir, input)
}
- f, err := os.Open(input)
+
+ b, err := ioutil.ReadFile(input)
if err != nil {
fatalf("%s", err)
}
- io.Copy(h, f)
- f.Close()
- }
- cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6])
-
- fs := make([]*File, len(goFiles))
- for i, input := range goFiles {
- if *srcDir != "" {
- input = filepath.Join(*srcDir, input)
+ if _, err = h.Write(b); err != nil {
+ fatalf("%s", err)
}
+
f := new(File)
- f.ReadGo(input)
+ f.ParseGo(input, b)
f.DiscardCgoDirectives()
fs[i] = f
}
+ cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6])
+
if *objDir == "" {
// make sure that _obj directory exists, so that we can write
// all the output files there.
diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go
index a8292f2..c4ff07d 100644
--- a/libgo/go/cmd/cgo/out.go
+++ b/libgo/go/cmd/cgo/out.go
@@ -190,7 +190,7 @@ func (p *Package) writeDefs() {
for _, key := range nameKeys(p.Name) {
n := p.Name[key]
if n.Const != "" {
- fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const)
+ fmt.Fprintf(fgo2, "const %s = %s\n", n.Mangle, n.Const)
}
}
fmt.Fprintf(fgo2, "\n")
@@ -1303,7 +1303,7 @@ const gccProlog = `
*/
#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
-// Check at compile time that the sizes we use match our expectations.
+/* Check at compile time that the sizes we use match our expectations. */
#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n)
__cgo_size_assert(char, 1)
@@ -1328,6 +1328,27 @@ const noTsanProlog = `
`
// This must match the TSAN code in runtime/cgo/libcgo.h.
+// This is used when the code is built with the C/C++ Thread SANitizer,
+// which is not the same as the Go race detector.
+// __tsan_acquire tells TSAN that we are acquiring a lock on a variable,
+// in this case _cgo_sync. __tsan_release releases the lock.
+// (There is no actual lock, we are just telling TSAN that there is.)
+//
+// When we call from Go to C we call _cgo_tsan_acquire.
+// When the C function returns we call _cgo_tsan_release.
+// Similarly, when C calls back into Go we call _cgo_tsan_release
+// and then call _cgo_tsan_acquire when we return to C.
+// These calls tell TSAN that there is a serialization point at the C call.
+//
+// This is necessary because TSAN, which is a C/C++ tool, can not see
+// the synchronization in the Go code. Without these calls, when
+// multiple goroutines call into C code, TSAN does not understand
+// that the calls are properly synchronized on the Go side.
+//
+// To be clear, if the calls are not properly synchronized on the Go side,
+// we will be hiding races. But when using TSAN on mixed Go C/C++ code
+// it is more important to avoid false positives, which reduce confidence
+// in the tool, than to avoid false negatives.
const yesTsanProlog = `
#line 1 "cgo-tsan-prolog"
#define CGO_NO_SANITIZE_THREAD __attribute__ ((no_sanitize_thread))
diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go
index f946bf6..6f9dc32 100644
--- a/libgo/go/cmd/go/alldocs.go
+++ b/libgo/go/cmd/go/alldocs.go
@@ -118,8 +118,8 @@
// a suffix to use in the name of the package installation directory,
// in order to keep output separate from default builds.
// If using the -race flag, the install suffix is automatically set to race
-// or, if set explicitly, has _race appended to it. Likewise for the -msan
-// flag. Using a -buildmode option that requires non-default compile flags
+// or, if set explicitly, has _race appended to it. Likewise for the -msan
+// flag. Using a -buildmode option that requires non-default compile flags
// has a similar effect.
// -ldflags 'flag list'
// arguments to pass on each go tool link invocation.
@@ -131,16 +131,17 @@
// For example, when building with a non-standard configuration,
// use -pkgdir to keep generated packages in a separate location.
// -tags 'tag list'
-// a list of build tags to consider satisfied during the build.
-// For more information about build tags, see the description of
+// a space-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.
// -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
// 'cmd args /path/to/asm '.
//
-// The list flags accept a space-separated list of strings. To embed spaces
-// in an element in the list, surround it with either single or double quotes.
+// All the flags that take a list of arguments accept a space-separated
+// list of strings. To embed spaces in an element in the list, surround
+// it with either single or double quotes.
//
// For more about specifying packages, see 'go help packages'.
// For more about where packages and binaries are installed,
@@ -208,12 +209,13 @@
//
// Usage:
//
-// go doc [-u] [-c] [package|[package.]symbol[.method]]
+// go doc [-u] [-c] [package|[package.]symbol[.methodOrField]]
//
// Doc prints the documentation comments associated with the item identified by its
-// arguments (a package, const, func, type, var, or method) followed by a one-line
-// summary of each of the first-level items "under" that item (package-level
-// declarations for a package, methods for a type, etc.).
+// arguments (a package, const, func, type, var, method, or struct field)
+// followed by a one-line summary of each of the first-level items "under"
+// that item (package-level declarations for a package, methods for a type,
+// etc.).
//
// Doc accepts zero, one, or two arguments.
//
@@ -231,9 +233,9 @@
// which is schematically one of these:
//
// go doc
-// go doc [.]
-// go doc [.][.]
-// go doc [.][.]
+// go doc [.]
+// go doc [.][.]
+// go doc [.][.]
//
// The first item in this list matched by the argument is the one whose documentation
// is printed. (See the examples below.) However, if the argument starts with a capital
@@ -241,7 +243,7 @@
//
// For packages, the order of scanning is determined lexically in breadth-first order.
// That is, the package presented is the one that matches the search and is nearest
-// the root and lexically first at its level of the hierarchy. The GOROOT tree is
+// the root and lexically first at its level of the hierarchy. The GOROOT tree is
// always scanned in its entirety before GOPATH.
//
// If there is no package specified or matched, the package in the current
@@ -253,10 +255,10 @@
// elements like . and ... are not implemented by go doc.
//
// When run with two arguments, the first must be a full package path (not just a
-// suffix), and the second is a symbol or symbol and method; this is similar to the
-// syntax accepted by godoc:
+// suffix), and the second is a symbol, or symbol with method or struct field.
+// This is similar to the syntax accepted by godoc:
//
-// go doc [.]
+// go doc [.]
//
// In all forms, when matching symbols, lower-case letters in the argument match
// either case but upper-case letters match exactly. This means that there may be
@@ -307,22 +309,25 @@
// when showing the package's top-level documentation.
// -u
// Show documentation for unexported as well as exported
-// symbols and methods.
+// symbols, methods, and fields.
//
//
// Print Go environment information
//
// Usage:
//
-// go env [var ...]
+// go env [-json] [var ...]
//
// Env prints Go environment information.
//
// By default env prints information as a shell script
-// (on Windows, a batch file). If one or more variable
-// names is given as arguments, env prints the value of
+// (on Windows, a batch file). If one or more variable
+// names is given as arguments, env prints the value of
// each named variable on its own line.
//
+// The -json flag prints the environment in JSON format
+// instead of as a shell script.
+//
//
// Start a bug report
//
@@ -357,7 +362,7 @@
// go fmt [-n] [-x] [packages]
//
// Fmt runs the command 'gofmt -l -w' on the packages named
-// by the import paths. It prints the names of the files that are modified.
+// by the import paths. It prints the names of the files that are modified.
//
// For more about gofmt, see 'go doc cmd/gofmt'.
// For more about specifying packages, see 'go help packages'.
@@ -427,7 +432,7 @@
// As a last step before running the command, any invocations of any
// environment variables with alphanumeric names, such as $GOFILE or
// $HOME, are expanded throughout the command line. The syntax for
-// variable expansion is $NAME on all operating systems. Due to the
+// variable expansion is $NAME on all operating systems. Due to the
// order of evaluation, variables are expanded even inside quoted
// strings. If the variable NAME is not set, $NAME expands to the
// empty string.
@@ -504,7 +509,7 @@
// 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
+// 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.
@@ -518,8 +523,8 @@
// 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 most recent version of the package.
+// 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.
@@ -565,7 +570,7 @@
// golang.org/x/net/html
//
// The -f flag specifies an alternate format for the list, using the
-// syntax of package template. The default output is equivalent to -f
+// syntax of package template. The default output is equivalent to -f
// '{{.ImportPath}}'. The struct being passed to the template is:
//
// type Package struct {
@@ -658,12 +663,12 @@
// instead of using the template format.
//
// The -e flag changes the handling of erroneous packages, those that
-// cannot be found or are malformed. By default, the list command
+// cannot be found or are malformed. By default, the list command
// prints an error to standard error for each erroneous package and
// omits the packages from consideration during the usual printing.
// With the -e flag, the list command never prints errors to standard
// error and instead processes the erroneous packages with the usual
-// printing. Erroneous packages will have a non-empty ImportPath and
+// printing. Erroneous packages will have a non-empty ImportPath and
// a non-nil Error field; other information may or may not be missing
// (zeroed).
//
@@ -716,7 +721,7 @@
// the file pattern "*_test.go".
// Files whose names begin with "_" (including "_test.go") or "." are ignored.
// These additional files can contain test functions, benchmark functions, and
-// example functions. See 'go help testfunc' for more.
+// example functions. See 'go help testfunc' for more.
// Each listed package causes the execution of a separate test binary.
//
// Test files that declare a package with the suffix "_test" will be compiled as a
@@ -725,7 +730,7 @@
// The go tool will ignore a directory named "testdata", making it available
// to hold ancillary data needed by the tests.
//
-// By default, go test needs no arguments. It compiles and tests the package
+// By default, go test needs no arguments. It compiles and tests the package
// with source in the current directory, including tests, and runs the tests.
//
// The package is built in a temporary directory so it does not interfere with the
@@ -793,15 +798,13 @@
//
// Usage:
//
-// go vet [-n] [-x] [build flags] [packages]
+// go vet [-n] [-x] [build flags] [vet flags] [packages]
//
// Vet runs the Go vet command on the packages named by the import paths.
//
-// For more about vet, see 'go doc cmd/vet'.
+// For more about vet and its flags, see 'go doc cmd/vet'.
// For more about specifying packages, see 'go help packages'.
//
-// To run the vet tool with specific options, run 'go tool vet'.
-//
// The -n flag prints commands that would be executed.
// The -x flag prints commands as they are executed.
//
@@ -814,18 +817,18 @@
//
// There are two different ways to call between Go and C/C++ code.
//
-// The first is the cgo tool, which is part of the Go distribution. For
+// The first is the cgo tool, which is part of the Go distribution. For
// information on how to use it see the cgo documentation (go doc cmd/cgo).
//
// The second is the SWIG program, which is a general tool for
-// interfacing between languages. For information on SWIG see
-// http://swig.org/. When running go build, any file with a .swig
-// extension will be passed to SWIG. Any file with a .swigcxx extension
+// interfacing between languages. For information on SWIG see
+// http://swig.org/. When running go build, any file with a .swig
+// extension will be passed to SWIG. Any file with a .swigcxx extension
// will be passed to SWIG with the -c++ option.
//
// When either cgo or SWIG is used, go build will pass any .c, .m, .s,
// or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++
-// compiler. The CC or CXX environment variables may be set to determine
+// compiler. The CC or CXX environment variables may be set to determine
// the C or C++ compiler, respectively, to use.
//
//
@@ -846,10 +849,10 @@
// exactly one main package to be listed.
//
// -buildmode=c-shared
-// Build the listed main packages, plus all packages that they
-// import, into C shared libraries. The only callable symbols will
+// Build the listed main package, plus all packages it imports,
+// into a C shared library. The only callable symbols will
// be those functions exported using a cgo //export comment.
-// Non-main packages are ignored.
+// Requires exactly one main package to be listed.
//
// -buildmode=default
// Listed main packages are built into executables and listed
@@ -938,7 +941,7 @@
//
// Each directory listed in GOPATH must have a prescribed structure:
//
-// The src directory holds source code. The path below src
+// The src directory holds source code. The path below src
// determines the import path or executable name.
//
// The pkg directory holds installed package objects.
@@ -952,11 +955,11 @@
//
// The bin directory holds compiled commands.
// Each command is named for its source directory, but only
-// the final element, not the entire path. That is, the
+// the final element, not the entire path. That is, the
// command with source in DIR/src/foo/quux is installed into
-// DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped
+// DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped
// so that you can add DIR/bin to your PATH to get at the
-// installed commands. If the GOBIN environment variable is
+// installed commands. If the GOBIN environment variable is
// set, commands are installed to the directory it names instead
// of DIR/bin. GOBIN must be an absolute path.
//
@@ -1099,7 +1102,7 @@
// CC
// The command to use to compile C code.
// CGO_ENABLED
-// Whether the cgo command is supported. Either 0 or 1.
+// Whether the cgo command is supported. Either 0 or 1.
// CGO_CFLAGS
// Flags that cgo will pass to the compiler when compiling
// C code.
@@ -1151,7 +1154,7 @@
// Import path syntax
//
// An import path (see 'go help packages') denotes a package stored in the local
-// file system. In general, an import path denotes either a standard package (such
+// file system. In general, an import path denotes either a standard package (such
// as "unicode/utf8") or a package found in one of the work spaces (For more
// details see: 'go help gopath').
//
@@ -1222,7 +1225,7 @@
//
// specifies the given repository, with or without the .vcs suffix,
// using the named version control system, and then the path inside
-// that repository. The supported version control systems are:
+// that repository. The supported version control systems are:
//
// Bazaar .bzr
// Git .git
@@ -1242,7 +1245,7 @@
// example.org/repo or repo.git.
//
// When a version control system supports multiple protocols,
-// each is tried in turn when downloading. For example, a Git
+// each is tried in turn when downloading. For example, a Git
// download tries https://, then git+ssh://.
//
// By default, downloads are restricted to known secure protocols
@@ -1360,17 +1363,28 @@
//
// An import path is a pattern if it includes one or more "..." wildcards,
// each of which can match any string, including the empty string and
-// strings containing slashes. Such a pattern expands to all package
+// strings containing slashes. Such a pattern expands to all package
// directories found in the GOPATH trees with names matching the
-// patterns. As a special case, x/... matches x as well as x's subdirectories.
-// For example, net/... expands to net and packages in its subdirectories.
+// patterns.
+//
+// To make common patterns more convenient, there are two special cases.
+// First, /... at the end of the pattern can match an empty string,
+// so that net/... matches both net and packages in its subdirectories, like net/http.
+// Second, any slash-separated pattern element containing a wildcard never
+// participates in a match of the "vendor" element in the path of a vendored
+// package, so that ./... does not match packages in subdirectories of
+// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
+// Note, however, that a directory named vendor that itself contains code
+// is not a vendored package: cmd/vendor would be a command named vendor,
+// and the pattern cmd/... matches it.
+// See golang.org/s/go15vendor for more about vendoring.
//
// An import path can also name a package to be downloaded from
-// a remote repository. Run 'go help importpath' for details.
+// a remote repository. Run 'go help importpath' for details.
//
// Every package in a program must have a unique import path.
// By convention, this is arranged by starting each path with a
-// unique prefix that belongs to you. For example, paths used
+// unique prefix that belongs to you. For example, paths used
// internally at Google all begin with 'google', and paths
// denoting remote repositories begin with the path to the code,
// such as 'github.com/user/repo'.
@@ -1399,19 +1413,24 @@
//
// Several of the flags control profiling and write an execution profile
// suitable for "go tool pprof"; run "go tool pprof -h" for more
-// information. The --alloc_space, --alloc_objects, and --show_bytes
+// information. The --alloc_space, --alloc_objects, and --show_bytes
// options of pprof control how the information is presented.
//
// The following flags are recognized by the 'go test' command and
// control the execution of any test:
//
// -bench regexp
-// Run (sub)benchmarks matching a regular expression.
-// The given regular expression is split into smaller ones by
-// top-level '/', where each must match the corresponding part of a
-// benchmark's identifier.
-// By default, no benchmarks run. To run all benchmarks,
-// use '-bench .' or '-bench=.'.
+// Run only those benchmarks matching a regular expression.
+// By default, no benchmarks are run.
+// To run all benchmarks, use '-bench .' or '-bench=.'.
+// The regular expression is split by unbracketed slash (/)
+// characters into a sequence of regular expressions, and each
+// part of a benchmark's identifier must match the corresponding
+// element in the sequence, if any. Possible parents of matches
+// are run with b.N=1 to identify sub-benchmarks. For example,
+// given -bench=X/Y, top-level benchmarks matching X are run
+// with b.N=1 to find any sub-benchmarks matching Y, which are
+// then run in full.
//
// -benchtime t
// Run enough iterations of each benchmark to take t, specified
@@ -1425,6 +1444,10 @@
//
// -cover
// Enable coverage analysis.
+// Note that because coverage works by annotating the source
+// code before compilation, compilation and test failures with
+// coverage enabled may report line numbers that don't correspond
+// to the original sources.
//
// -covermode set,count,atomic
// Set the mode for coverage analysis for the package[s]
@@ -1445,9 +1468,14 @@
//
// -cpu 1,2,4
// Specify a list of GOMAXPROCS values for which the tests or
-// benchmarks should be executed. The default is the current value
+// benchmarks should be executed. The default is the current value
// of GOMAXPROCS.
//
+// -list regexp
+// List tests, benchmarks, or examples matching the regular expression.
+// No tests, benchmarks or examples will be run. This will only
+// list top-level tests. No subtest or subbenchmarks will be shown.
+//
// -parallel n
// Allow parallel execution of test functions that call t.Parallel.
// The value of this flag is the maximum number of tests to run
@@ -1459,9 +1487,13 @@
//
// -run regexp
// Run only those tests and examples matching the regular expression.
-// For tests the regular expression is split into smaller ones by
-// top-level '/', where each must match the corresponding part of a
-// test's identifier.
+// For tests, the regular expression is split by unbracketed slash (/)
+// characters into a sequence of regular expressions, and each part
+// of a test's identifier must match the corresponding element in
+// the sequence, if any. Note that possible parents of matches are
+// run too, so that -run=X/Y matches and runs and reports the result
+// of all tests matching X, even those without sub-tests matching Y,
+// because it must run them to look for those sub-tests.
//
// -short
// Tell long-running tests to shorten their run time.
@@ -1469,8 +1501,8 @@
// the Go tree can run a sanity check but not spend time running
// exhaustive tests.
//
-// -timeout t
-// If a test runs longer than t, panic.
+// -timeout d
+// If a test binary runs longer than duration d, panic.
// The default is 10 minutes (10m).
//
// -v
@@ -1493,7 +1525,7 @@
// calling runtime.SetBlockProfileRate with n.
// See 'go doc runtime.SetBlockProfileRate'.
// The profiler aims to sample, on average, one blocking event every
-// n nanoseconds the program spends blocked. By default,
+// n nanoseconds the program spends blocked. By default,
// if -test.blockprofile is set without this flag, all blocking events
// are recorded, equivalent to -test.blockprofilerate=1.
//
@@ -1511,7 +1543,7 @@
//
// -memprofilerate n
// Enable more precise (and expensive) memory profiles by setting
-// runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
+// runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
// To profile all memory allocations, use -test.memprofilerate=1
// and pass --alloc_space flag to the pprof tool.
//
@@ -1614,8 +1646,8 @@
// "Output:" is compiled, executed, and expected to produce no output.
//
// Godoc displays the body of ExampleXXX to demonstrate the use
-// of the function, constant, or variable XXX. An example of a method M with
-// receiver type T or *T is named ExampleT_M. There may be multiple examples
+// of the function, constant, or variable XXX. An example of a method M with
+// receiver type T or *T is named ExampleT_M. There may be multiple examples
// for a given function, constant, or variable, distinguished by a trailing _xxx,
// where xxx is a suffix not beginning with an upper case letter.
//
diff --git a/libgo/go/cmd/go/build_test.go b/libgo/go/cmd/go/build_test.go
deleted file mode 100644
index 79bbd54..0000000
--- a/libgo/go/cmd/go/build_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
- "os"
- "reflect"
- "testing"
-)
-
-func TestRemoveDevNull(t *testing.T) {
- fi, err := os.Lstat(os.DevNull)
- if err != nil {
- t.Skip(err)
- }
- if fi.Mode().IsRegular() {
- t.Errorf("Lstat(%s).Mode().IsRegular() = true; expected false", os.DevNull)
- }
- mayberemovefile(os.DevNull)
- _, err = os.Lstat(os.DevNull)
- if err != nil {
- t.Errorf("mayberemovefile(%s) did remove it; oops", os.DevNull)
- }
-}
-
-func TestSplitPkgConfigOutput(t *testing.T) {
- for _, test := range []struct {
- in []byte
- want []string
- }{
- {[]byte(`-r:foo -L/usr/white\ space/lib -lfoo\ bar -lbar\ baz`), []string{"-r:foo", "-L/usr/white space/lib", "-lfoo bar", "-lbar baz"}},
- {[]byte(`-lextra\ fun\ arg\\`), []string{`-lextra fun arg\`}},
- {[]byte(`broken flag\`), []string{"broken", "flag"}},
- {[]byte("\textra whitespace\r\n"), []string{"extra", "whitespace"}},
- {[]byte(" \r\n "), nil},
- } {
- got := splitPkgConfigOutput(test.in)
- if !reflect.DeepEqual(got, test.want) {
- t.Errorf("splitPkgConfigOutput(%v) = %v; want %v", test.in, got, test.want)
- }
- }
-}
diff --git a/libgo/go/cmd/go/env.go b/libgo/go/cmd/go/env.go
deleted file mode 100644
index 31710b7..0000000
--- a/libgo/go/cmd/go/env.go
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
- "fmt"
- "os"
- "runtime"
- "strings"
-)
-
-var cmdEnv = &Command{
- Run: runEnv,
- UsageLine: "env [var ...]",
- Short: "print Go environment information",
- Long: `
-Env prints Go environment information.
-
-By default env prints information as a shell script
-(on Windows, a batch file). If one or more variable
-names is given as arguments, env prints the value of
-each named variable on its own line.
- `,
-}
-
-type envVar struct {
- name, value string
-}
-
-func mkEnv() []envVar {
- var b builder
- b.init()
-
- env := []envVar{
- {"GOARCH", goarch},
- {"GOBIN", gobin},
- {"GOEXE", exeSuffix},
- {"GOHOSTARCH", runtime.GOARCH},
- {"GOHOSTOS", runtime.GOOS},
- {"GOOS", goos},
- {"GOPATH", buildContext.GOPATH},
- {"GORACE", os.Getenv("GORACE")},
- {"GOROOT", goroot},
- {"GOTOOLDIR", toolDir},
-
- // disable escape codes in clang errors
- {"TERM", "dumb"},
- }
-
- if gccgoBin != "" {
- env = append(env, envVar{"GCCGO", gccgoBin})
- } else {
- env = append(env, envVar{"GCCGO", gccgoName})
- }
-
- switch goarch {
- case "arm":
- env = append(env, envVar{"GOARM", os.Getenv("GOARM")})
- case "386":
- env = append(env, envVar{"GO386", os.Getenv("GO386")})
- }
-
- cmd := b.gccCmd(".")
- env = append(env, envVar{"CC", cmd[0]})
- env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")})
- cmd = b.gxxCmd(".")
- env = append(env, envVar{"CXX", cmd[0]})
-
- if buildContext.CgoEnabled {
- env = append(env, envVar{"CGO_ENABLED", "1"})
- } else {
- env = append(env, envVar{"CGO_ENABLED", "0"})
- }
-
- return env
-}
-
-func findEnv(env []envVar, name string) string {
- for _, e := range env {
- if e.name == name {
- return e.value
- }
- }
- return ""
-}
-
-// extraEnvVars returns environment variables that should not leak into child processes.
-func extraEnvVars() []envVar {
- var b builder
- b.init()
- cppflags, cflags, cxxflags, fflags, ldflags := b.cflags(&Package{})
- return []envVar{
- {"PKG_CONFIG", b.pkgconfigCmd()},
- {"CGO_CFLAGS", strings.Join(cflags, " ")},
- {"CGO_CPPFLAGS", strings.Join(cppflags, " ")},
- {"CGO_CXXFLAGS", strings.Join(cxxflags, " ")},
- {"CGO_FFLAGS", strings.Join(fflags, " ")},
- {"CGO_LDFLAGS", strings.Join(ldflags, " ")},
- }
-}
-
-func runEnv(cmd *Command, args []string) {
- env := newEnv
- env = append(env, extraEnvVars()...)
- if len(args) > 0 {
- for _, name := range args {
- fmt.Printf("%s\n", findEnv(env, name))
- }
- return
- }
-
- for _, e := range env {
- if e.name != "TERM" {
- switch runtime.GOOS {
- default:
- fmt.Printf("%s=\"%s\"\n", e.name, e.value)
- case "plan9":
- if strings.IndexByte(e.value, '\x00') < 0 {
- fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1))
- } else {
- v := strings.Split(e.value, "\x00")
- fmt.Printf("%s=(", e.name)
- for x, s := range v {
- if x > 0 {
- fmt.Printf(" ")
- }
- fmt.Printf("%s", s)
- }
- fmt.Printf(")\n")
- }
- case "windows":
- fmt.Printf("set %s=%s\n", e.name, e.value)
- }
- }
- }
-}
diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go
index eaa8685..28fb5ef 100644
--- a/libgo/go/cmd/go/go_test.go
+++ b/libgo/go/cmd/go/go_test.go
@@ -7,7 +7,6 @@ package main_test
import (
"bytes"
"fmt"
- "go/build"
"go/format"
"internal/race"
"internal/testenv"
@@ -74,6 +73,13 @@ func init() {
}
}
+// testGOROOT is the GOROOT to use when running testgo, a cmd/go binary
+// build from this process's current GOROOT, but run from a different
+// (temp) directory.
+var testGOROOT string
+
+var testCC string
+
// The TestMain function creates a go command for testing purposes and
// deletes it after the tests have been run.
func TestMain(m *testing.M) {
@@ -88,6 +94,20 @@ func TestMain(m *testing.M) {
os.Exit(2)
}
+ out, err = exec.Command("go", "env", "GOROOT").CombinedOutput()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not find testing GOROOT: %v\n%s", err, out)
+ os.Exit(2)
+ }
+ testGOROOT = strings.TrimSpace(string(out))
+
+ out, err = exec.Command("go", "env", "CC").CombinedOutput()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "could not find testing CC: %v\n%s", err, out)
+ os.Exit(2)
+ }
+ testCC = strings.TrimSpace(string(out))
+
if out, err := exec.Command("./testgo"+exeSuffix, "env", "CGO_ENABLED").Output(); err != nil {
fmt.Fprintf(os.Stderr, "running testgo failed: %v\n", err)
canRun = false
@@ -100,7 +120,9 @@ func TestMain(m *testing.M) {
switch runtime.GOOS {
case "linux", "darwin", "freebsd", "windows":
- canRace = canCgo && runtime.GOARCH == "amd64" && runtime.Compiler != "gccgo"
+ // The race detector doesn't work on Alpine Linux:
+ // golang.org/issue/14481
+ canRace = canCgo && runtime.GOARCH == "amd64" && !isAlpineLinux() && runtime.Compiler != "gccgo"
}
}
@@ -111,7 +133,7 @@ func TestMain(m *testing.M) {
if home, ccacheDir := os.Getenv("HOME"), os.Getenv("CCACHE_DIR"); home != "" && ccacheDir == "" {
// On some systems the default C compiler is ccache.
// Setting HOME to a non-existent directory will break
- // those systems. Set CCACHE_DIR to cope. Issue 17668.
+ // those systems. Set CCACHE_DIR to cope. Issue 17668.
os.Setenv("CCACHE_DIR", filepath.Join(home, ".ccache"))
}
os.Setenv("HOME", "/test-go-home-does-not-exist")
@@ -125,6 +147,14 @@ func TestMain(m *testing.M) {
os.Exit(r)
}
+func isAlpineLinux() bool {
+ if runtime.GOOS != "linux" {
+ return false
+ }
+ fi, err := os.Lstat("/etc/alpine-release")
+ return err == nil && fi.Mode().IsRegular()
+}
+
// The length of an mtime tick on this system. This is an estimate of
// how long we need to sleep to ensure that the mtime of two files is
// different.
@@ -251,6 +281,13 @@ func (tg *testgoData) unsetenv(name string) {
}
}
+func (tg *testgoData) goTool() string {
+ if tg.wd == "" {
+ return "./testgo" + exeSuffix
+ }
+ return filepath.Join(tg.wd, "testgo"+exeSuffix)
+}
+
// doRun runs the test go command, recording stdout and stderr and
// returning exit status.
func (tg *testgoData) doRun(args []string) error {
@@ -264,13 +301,20 @@ func (tg *testgoData) doRun(args []string) error {
}
}
}
- tg.t.Logf("running testgo %v", args)
- var prog string
- if tg.wd == "" {
- prog = "./testgo" + exeSuffix
- } else {
- prog = filepath.Join(tg.wd, "testgo"+exeSuffix)
+
+ hasGoroot := false
+ for _, v := range tg.env {
+ if strings.HasPrefix(v, "GOROOT=") {
+ hasGoroot = true
+ break
+ }
+ }
+ prog := tg.goTool()
+ if !hasGoroot {
+ tg.setenv("GOROOT", testGOROOT)
}
+
+ tg.t.Logf("running testgo %v", args)
cmd := exec.Command(prog, args...)
tg.stdout.Reset()
tg.stderr.Reset()
@@ -365,7 +409,7 @@ func (tg *testgoData) doGrepMatch(match string, b *bytes.Buffer) bool {
// doGrep looks for a regular expression in a buffer and fails if it
// is not found. The name argument is the name of the output we are
-// searching, "output" or "error". The msg argument is logged on
+// searching, "output" or "error". The msg argument is logged on
// failure.
func (tg *testgoData) doGrep(match string, b *bytes.Buffer, name, msg string) {
if !tg.doGrepMatch(match, b) {
@@ -1354,7 +1398,7 @@ func TestInstallFailsWithNoBuildableFiles(t *testing.T) {
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.setenv("CGO_ENABLED", "0")
tg.runFail("install", "cgotest")
- tg.grepStderr("no buildable Go source files", "go install cgotest did not report 'no buildable Go Source files'")
+ tg.grepStderr("build constraints exclude all Go files", "go install cgotest did not report 'build constraints exclude all Go files'")
}
func TestRelativeGOBINFail(t *testing.T) {
@@ -1483,11 +1527,11 @@ func TestGoGetNonPkg(t *testing.T) {
tg.setenv("GOPATH", tg.path("."))
tg.setenv("GOBIN", tg.path("gobin"))
tg.runFail("get", "-d", "golang.org/x/tools")
- tg.grepStderr("golang.org/x/tools: no buildable Go source files", "missing error")
+ tg.grepStderr("golang.org/x/tools: no Go files", "missing error")
tg.runFail("get", "-d", "-u", "golang.org/x/tools")
- tg.grepStderr("golang.org/x/tools: no buildable Go source files", "missing error")
+ tg.grepStderr("golang.org/x/tools: no Go files", "missing error")
tg.runFail("get", "-d", "golang.org/x/tools")
- tg.grepStderr("golang.org/x/tools: no buildable Go source files", "missing error")
+ tg.grepStderr("golang.org/x/tools: no Go files", "missing error")
}
func TestGoGetTestOnlyPkg(t *testing.T) {
@@ -1753,7 +1797,7 @@ func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
}
-// Issue 4186. go get cannot be used to download packages to $GOROOT.
+// Issue 4186. go get cannot be used to download packages to $GOROOT.
// Test that without GOPATH set, go get should fail.
func TestGoGetIntoGOROOT(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
@@ -1895,10 +1939,7 @@ func TestGoTestDashIDashOWritesBinary(t *testing.T) {
// Issue 4568.
func TestSymlinksList(t *testing.T) {
- switch runtime.GOOS {
- case "plan9", "windows":
- t.Skipf("skipping symlink test on %s", runtime.GOOS)
- }
+ testenv.MustHaveSymlink(t)
tg := testgo(t)
defer tg.cleanup()
@@ -1916,10 +1957,7 @@ func TestSymlinksList(t *testing.T) {
// Issue 14054.
func TestSymlinksVendor(t *testing.T) {
- switch runtime.GOOS {
- case "plan9", "windows":
- t.Skipf("skipping symlink test on %s", runtime.GOOS)
- }
+ testenv.MustHaveSymlink(t)
tg := testgo(t)
defer tg.cleanup()
@@ -1943,10 +1981,7 @@ func TestSymlinksVendor(t *testing.T) {
// Issue 15201.
func TestSymlinksVendor15201(t *testing.T) {
- switch runtime.GOOS {
- case "plan9", "windows":
- t.Skipf("skipping symlink test on %s", runtime.GOOS)
- }
+ testenv.MustHaveSymlink(t)
tg := testgo(t)
defer tg.cleanup()
@@ -1963,10 +1998,7 @@ func TestSymlinksVendor15201(t *testing.T) {
}
func TestSymlinksInternal(t *testing.T) {
- switch runtime.GOOS {
- case "plan9", "windows":
- t.Skipf("skipping symlink test on %s", runtime.GOOS)
- }
+ testenv.MustHaveSymlink(t)
tg := testgo(t)
defer tg.cleanup()
@@ -2030,8 +2062,10 @@ func TestCaseCollisions(t *testing.T) {
)`)
tg.tempFile("src/example/a/pkg/pkg.go", `package pkg`)
tg.tempFile("src/example/a/Pkg/pkg.go", `package pkg`)
- tg.runFail("list", "example/a")
- tg.grepStderr("case-insensitive import collision", "go list example/a did not report import collision")
+ tg.run("list", "-json", "example/a")
+ tg.grepStdout("case-insensitive import collision", "go list -json example/a did not report import collision")
+ tg.runFail("build", "example/a")
+ tg.grepStderr("case-insensitive import collision", "go build example/a did not report import collision")
tg.tempFile("src/example/b/file.go", `package b`)
tg.tempFile("src/example/b/FILE.go", `package b`)
f, err := os.Open(tg.path("src/example/b"))
@@ -2049,6 +2083,38 @@ func TestCaseCollisions(t *testing.T) {
}
tg.runFail(args...)
tg.grepStderr("case-insensitive file name collision", "go list example/b did not report file name collision")
+
+ tg.runFail("list", "example/a/pkg", "example/a/Pkg")
+ tg.grepStderr("case-insensitive import collision", "go list example/a/pkg example/a/Pkg did not report import collision")
+ tg.run("list", "-json", "-e", "example/a/pkg", "example/a/Pkg")
+ tg.grepStdout("case-insensitive import collision", "go list -json -e example/a/pkg example/a/Pkg did not report import collision")
+ tg.runFail("build", "example/a/pkg", "example/a/Pkg")
+ tg.grepStderr("case-insensitive import collision", "go build example/a/pkg example/a/Pkg did not report import collision")
+}
+
+// Issue 17451, 17662.
+func TestSymlinkWarning(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+
+ tg.tempDir("src/example/xx")
+ tg.tempDir("yy/zz")
+ tg.tempFile("yy/zz/zz.go", "package zz\n")
+ if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
+ t.Skip("symlink failed: %v", err)
+ }
+ tg.run("list", "example/xx/z...")
+ tg.grepStdoutNot(".", "list should not have matched anything")
+ tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
+ tg.grepStderrNot("symlink", "list should not have reported symlink")
+
+ tg.run("list", "example/xx/...")
+ tg.grepStdoutNot(".", "list should not have matched anything")
+ tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
+ tg.grepStderr("ignoring symlink", "list should have reported symlink")
}
// Issue 8181.
@@ -2195,29 +2261,6 @@ func TestCoverageUsesAtomicModeForRace(t *testing.T) {
checkCoverage(tg, data)
}
-func TestCoverageUsesActualSettingToOverrideEvenForRace(t *testing.T) {
- if testing.Short() {
- t.Skip("don't build libraries for coverage in short mode")
- }
- if !canRace {
- t.Skip("skipping because race detector not supported")
- }
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.creatingTemp("testdata/cover.out")
- tg.run("test", "-short", "-race", "-cover", "encoding/binary", "-covermode=count", "-coverprofile=testdata/cover.out")
- data := tg.getStdout() + tg.getStderr()
- if out, err := ioutil.ReadFile("testdata/cover.out"); err != nil {
- t.Error(err)
- } else {
- if !bytes.Contains(out, []byte("mode: count")) {
- t.Error("missing mode: count")
- }
- }
- checkCoverage(tg, data)
-}
-
func TestCoverageImportMainLoop(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -2228,6 +2271,20 @@ func TestCoverageImportMainLoop(t *testing.T) {
tg.grepStderr("not an importable package", "did not detect import main")
}
+func TestPluginNonMain(t *testing.T) {
+ wd, err := os.Getwd()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ pkg := filepath.Join(wd, "testdata", "testdep", "p2")
+
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ tg.runFail("build", "-buildmode=plugin", pkg)
+}
+
func TestTestEmpty(t *testing.T) {
if !canRace {
t.Skip("no race detector")
@@ -2235,7 +2292,6 @@ func TestTestEmpty(t *testing.T) {
wd, _ := os.Getwd()
testdata := filepath.Join(wd, "testdata")
-
for _, dir := range []string{"pkg", "test", "xtest", "pkgtest", "pkgxtest", "pkgtestxtest", "testxtest"} {
t.Run(dir, func(t *testing.T) {
tg := testgo(t)
@@ -2250,10 +2306,36 @@ func TestTestEmpty(t *testing.T) {
}
}
+func TestNoGoError(t *testing.T) {
+ wd, _ := os.Getwd()
+ testdata := filepath.Join(wd, "testdata")
+ for _, dir := range []string{"empty/test", "empty/xtest", "empty/testxtest", "exclude", "exclude/ignore", "exclude/empty"} {
+ t.Run(dir, func(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", testdata)
+ tg.cd(filepath.Join(testdata, "src"))
+ tg.runFail("build", "./"+dir)
+ var want string
+ if strings.Contains(dir, "test") {
+ want = "no non-test Go files in "
+ } else if dir == "exclude" {
+ want = "build constraints exclude all Go files in "
+ } else {
+ want = "no Go files in "
+ }
+ tg.grepStderr(want, "wrong reason for failure")
+ })
+ }
+}
+
func TestTestRaceInstall(t *testing.T) {
if !canRace {
t.Skip("no race detector")
}
+ if testing.Short() && testenv.Builder() == "" {
+ t.Skip("don't rebuild the standard library in short mode")
+ }
tg := testgo(t)
defer tg.cleanup()
@@ -2308,6 +2390,19 @@ func TestCoverageWithCgo(t *testing.T) {
}
}
+func TestCgoAsmError(t *testing.T) {
+ if !canCgo {
+ t.Skip("skipping because cgo not enabled")
+ }
+
+ tg := testgo(t)
+ tg.parallel()
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.runFail("build", "cgoasm")
+ tg.grepBoth("package using cgo has Go assembly file", "did not detect Go assembly file")
+}
+
func TestCgoDependsOnSyscall(t *testing.T) {
if testing.Short() {
t.Skip("skipping test that removes $GOROOT/pkg/*_race in short mode")
@@ -2445,7 +2540,7 @@ import "C"
func main() { C.f() }`)
tg.setenv("GOPATH", tg.path("."))
tg.run("build", "-n", "-compiler", "gccgo", "cgoref")
- tg.grepStderr(`gccgo.*\-L alibpath \-lalib`, `no Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage`)
+ tg.grepStderr(`gccgo.*\-L [^ ]*alibpath \-lalib`, `no Go-inline "#cgo LDFLAGS:" ("-L alibpath -lalib") passed to gccgo linking stage`)
}
func TestListTemplateContextFunction(t *testing.T) {
@@ -2535,7 +2630,7 @@ func TestGoBuildInTestOnlyDirectoryFailsWithAGoodError(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.runFail("build", "./testdata/testonly")
- tg.grepStderr("no buildable Go", "go build ./testdata/testonly produced unexpected error")
+ tg.grepStderr("no non-test Go files in", "go build ./testdata/testonly produced unexpected error")
}
func TestGoTestDetectsTestOnlyImportCycles(t *testing.T) {
@@ -2674,8 +2769,7 @@ func TestGoGetInternalWildcard(t *testing.T) {
}
func TestGoVetWithExternalTests(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
-
+ skipIfGccgo(t, "gccgo does not have vet")
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
@@ -2686,19 +2780,39 @@ func TestGoVetWithExternalTests(t *testing.T) {
}
func TestGoVetWithTags(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
-
+ skipIfGccgo(t, "gccgo does not have vet")
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
tg.run("install", "cmd/vet")
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.runFail("vet", "-tags", "tagtest", "vetpkg")
- tg.grepBoth(`c\.go.*wrong number of args for format`, "go get vetpkg did not run scan tagged file")
+ tg.grepBoth(`c\.go.*wrong number of args for format`, "go vet vetpkg did not run scan tagged file")
+}
+
+func TestGoVetWithFlagsOn(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not have vet")
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.run("install", "cmd/vet")
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.runFail("vet", "-printf", "vetpkg")
+ tg.grepBoth("missing argument for Printf", "go vet -printf vetpkg did not find missing argument for Printf")
+}
+
+func TestGoVetWithFlagsOff(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not have vet")
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.run("install", "cmd/vet")
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.run("vet", "-printf=false", "vetpkg")
}
-// Issue 9767.
-func TestGoGetRscIoToolstash(t *testing.T) {
+// Issue 9767, 19769.
+func TestGoGetDotSlashDownload(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
tg := testgo(t)
@@ -2706,7 +2820,7 @@ func TestGoGetRscIoToolstash(t *testing.T) {
tg.tempDir("src/rsc.io")
tg.setenv("GOPATH", tg.path("."))
tg.cd(tg.path("src/rsc.io"))
- tg.run("get", "./toolstash")
+ tg.run("get", "./pprof_mac_fix")
}
// Issue 13037: Was not parsing tags in 404 served over HTTPS
@@ -3047,17 +3161,8 @@ func TestGoInstallPkgdir(t *testing.T) {
}
func TestGoTestRaceInstallCgo(t *testing.T) {
- skipIfGccgo(t, "gccgo has no race detector")
-
- switch sys := runtime.GOOS + "/" + runtime.GOARCH; sys {
- case "darwin/amd64", "freebsd/amd64", "linux/amd64", "windows/amd64":
- // ok
- default:
- t.Skip("no race detector on %s", sys)
- }
-
- if !build.Default.CgoEnabled {
- t.Skip("no race detector without cgo")
+ if !canRace {
+ t.Skip("skipping because race detector not supported")
}
// golang.org/issue/10500.
@@ -3071,7 +3176,7 @@ func TestGoTestRaceInstallCgo(t *testing.T) {
tg.run("test", "-race", "-i", "runtime/race")
new, err := os.Stat(cgo)
tg.must(err)
- if new.ModTime() != old.ModTime() {
+ if !new.ModTime().Equal(old.ModTime()) {
t.Fatalf("go test -i runtime/race reinstalled cmd/cgo")
}
}
@@ -3100,7 +3205,7 @@ func TestGoTestRaceFailures(t *testing.T) {
func TestGoTestImportErrorStack(t *testing.T) {
const out = `package testdep/p1 (test)
imports testdep/p2
- imports testdep/p3: no buildable Go source files`
+ imports testdep/p3: build constraints exclude all Go files `
tg := testgo(t)
defer tg.cleanup()
@@ -3141,6 +3246,20 @@ func TestGoGetUpdate(t *testing.T) {
tg.run("get", "-d", "-u", "github.com/rsc/go-get-issue-9224-cmd")
}
+// Issue #20512.
+func TestGoGetRace(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+ if !canRace {
+ t.Skip("skipping because race detector not supported")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+ tg.run("get", "-race", "github.com/rsc/go-get-issue-9224-cmd")
+}
+
func TestGoGetDomainRoot(t *testing.T) {
// golang.org/issue/9357.
// go get foo.io (not foo.io/subdir) was not working consistently.
@@ -3477,7 +3596,7 @@ func TestBinaryOnlyPackages(t *testing.T) {
func F() { p1.F(true) }
`)
tg.runFail("install", "p2")
- tg.grepStderr("no buildable Go source files", "did not complain about missing sources")
+ tg.grepStderr("no Go files", "did not complain about missing sources")
tg.tempFile("src/p1/missing.go", `//go:binary-only-package
@@ -3675,6 +3794,28 @@ func TestMatchesOnlyBenchmarkIsOK(t *testing.T) {
tg.grepBoth(okPattern, "go test did not say ok")
}
+func TestBenchmarkLabels(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.run("test", "-run", "^$", "-bench", ".", "bench")
+ tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos")
+ tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch")
+ tg.grepStdout(`(?m)^pkg: bench`, "go test did not say pkg: bench")
+ tg.grepBothNot(`(?s)pkg:.*pkg:`, "go test said pkg multiple times")
+}
+
+func TestBenchmarkLabelsOutsideGOPATH(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.run("test", "-run", "^$", "-bench", ".", "testdata/standalone_benchmark_test.go")
+ tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos")
+ tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch")
+ tg.grepBothNot(`(?m)^pkg:`, "go test did say pkg:")
+}
+
func TestMatchesOnlyTestIsOK(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -3804,3 +3945,431 @@ func TestA(t *testing.T) {}`)
tg.grepStdout("pkgs$", "expected package not listed")
tg.grepStdout("pkgs/a", "expected package not listed")
}
+
+// Issue 18975.
+func TestFFLAGS(t *testing.T) {
+ if !canCgo {
+ t.Skip("skipping because cgo not enabled")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+
+ tg.tempFile("p/src/p/main.go", `package main
+ // #cgo FFLAGS: -no-such-fortran-flag
+ import "C"
+ func main() {}
+ `)
+ tg.tempFile("p/src/p/a.f", `! comment`)
+ tg.setenv("GOPATH", tg.path("p"))
+
+ // This should normally fail because we are passing an unknown flag,
+ // but issue #19080 points to Fortran compilers that succeed anyhow.
+ // To work either way we call doRun directly rather than run or runFail.
+ tg.doRun([]string{"build", "-x", "p"})
+
+ tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`)
+}
+
+// Issue 19198.
+// This is really a cmd/link issue but this is a convenient place to test it.
+func TestDuplicateGlobalAsmSymbols(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not use cmd/asm")
+ if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" {
+ t.Skipf("skipping test on %s", runtime.GOARCH)
+ }
+ if !canCgo {
+ t.Skip("skipping because cgo not enabled")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+
+ asm := `
+#include "textflag.h"
+
+DATA sym<>+0x0(SB)/8,$0
+GLOBL sym<>(SB),(NOPTR+RODATA),$8
+
+TEXT ·Data(SB),NOSPLIT,$0
+ MOVB sym<>(SB), AX
+ MOVB AX, ret+0(FP)
+ RET
+`
+ tg.tempFile("go/src/a/a.s", asm)
+ tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`)
+ tg.tempFile("go/src/b/b.s", asm)
+ tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`)
+ tg.tempFile("go/src/p/p.go", `
+package main
+import "a"
+import "b"
+import "C"
+func main() {
+ _ = a.Data() + b.Data()
+}
+`)
+ tg.setenv("GOPATH", tg.path("go"))
+ exe := filepath.Join(tg.tempdir, "p.exe")
+ tg.creatingTemp(exe)
+ tg.run("build", "-o", exe, "p")
+}
+
+func TestBuildTagsNoComma(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no standard packages")
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("go"))
+ tg.run("install", "-tags", "tag1 tag2", "math")
+ tg.runFail("install", "-tags", "tag1,tag2", "math")
+ tg.grepBoth("space-separated list contains comma", "-tags with a comma-separated list didn't error")
+ tg.runFail("build", "-tags", "tag1,tag2", "math")
+ tg.grepBoth("space-separated list contains comma", "-tags with a comma-separated list didn't error")
+}
+
+func copyFile(src, dst string, perm os.FileMode) error {
+ sf, err := os.Open(src)
+ if err != nil {
+ return err
+ }
+ defer sf.Close()
+
+ df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.Copy(df, sf)
+ err2 := df.Close()
+ if err != nil {
+ return err
+ }
+ return err2
+}
+
+func TestExecutableGOROOT(t *testing.T) {
+ skipIfGccgo(t, "gccgo has no GOROOT")
+ if runtime.GOOS == "openbsd" {
+ t.Skipf("test case does not work on %s, missing os.Executable", runtime.GOOS)
+ }
+
+ // Env with no GOROOT.
+ var env []string
+ for _, e := range os.Environ() {
+ if !strings.HasPrefix(e, "GOROOT=") {
+ env = append(env, e)
+ }
+ }
+
+ check := func(t *testing.T, exe, want string) {
+ cmd := exec.Command(exe, "env", "GOROOT")
+ cmd.Env = env
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("%s env GOROOT: %v, %s", exe, err, out)
+ }
+ goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out)))
+ if err != nil {
+ t.Fatal(err)
+ }
+ want, err = filepath.EvalSymlinks(want)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !strings.EqualFold(goroot, want) {
+ t.Errorf("go env GOROOT:\nhave %s\nwant %s", goroot, want)
+ } else {
+ t.Logf("go env GOROOT: %s", goroot)
+ }
+ }
+
+ // Note: Must not call tg methods inside subtests: tg is attached to outer t.
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ tg.makeTempdir()
+ tg.tempDir("new/bin")
+ newGoTool := tg.path("new/bin/go" + exeSuffix)
+ tg.must(copyFile(tg.goTool(), newGoTool, 0775))
+ newRoot := tg.path("new")
+
+ t.Run("RelocatedExe", func(t *testing.T) {
+ t.Skip("TODO: skipping known broken test; see golang.org/issue/20284")
+
+ // Should fall back to default location in binary.
+ // No way to dig out other than look at source code.
+ data, err := ioutil.ReadFile("../../runtime/internal/sys/zversion.go")
+ if err != nil {
+ t.Fatal(err)
+ }
+ m := regexp.MustCompile("const DefaultGoroot = `([^`]+)`").FindStringSubmatch(string(data))
+ if m == nil {
+ t.Fatal("cannot find DefaultGoroot in ../../runtime/internal/sys/zversion.go")
+ }
+ check(t, newGoTool, m[1])
+ })
+
+ // If the binary is sitting in a bin dir next to ../pkg/tool, that counts as a GOROOT,
+ // so it should find the new tree.
+ tg.tempDir("new/pkg/tool")
+ t.Run("RelocatedTree", func(t *testing.T) {
+ check(t, newGoTool, newRoot)
+ })
+
+ tg.tempDir("other/bin")
+ symGoTool := tg.path("other/bin/go" + exeSuffix)
+
+ // Symlink into go tree should still find go tree.
+ t.Run("SymlinkedExe", func(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+ if err := os.Symlink(newGoTool, symGoTool); err != nil {
+ t.Fatal(err)
+ }
+ check(t, symGoTool, newRoot)
+ })
+}
+
+func TestNeedVersion(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not use cmd/compile")
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.tempFile("goversion.go", `package main; func main() {}`)
+ path := tg.path("goversion.go")
+ tg.setenv("TESTGO_VERSION", "go1.testgo")
+ tg.runFail("run", path)
+ tg.grepStderr("compile", "does not match go tool version")
+}
+
+// Test that user can override default code generation flags.
+func TestUserOverrideFlags(t *testing.T) {
+ skipIfGccgo(t, "gccgo does not use -gcflags")
+ if !canCgo {
+ t.Skip("skipping because cgo not enabled")
+ }
+ if runtime.GOOS != "linux" {
+ // We are testing platform-independent code, so it's
+ // OK to skip cases that work differently.
+ t.Skipf("skipping on %s because test only works if c-archive implies -shared", runtime.GOOS)
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.tempFile("override.go", `package main
+
+import "C"
+
+//export GoFunc
+func GoFunc() {}
+
+func main() {}`)
+ tg.creatingTemp("override.a")
+ tg.creatingTemp("override.h")
+ tg.run("build", "-x", "-buildmode=c-archive", "-gcflags=-shared=false", tg.path("override.go"))
+ tg.grepStderr("compile .*-shared .*-shared=false", "user can not override code generation flag")
+}
+
+func TestCgoFlagContainsSpace(t *testing.T) {
+ if !canCgo {
+ t.Skip("skipping because cgo not enabled")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ ccName := filepath.Base(testCC)
+
+ tg.tempFile(fmt.Sprintf("src/%s/main.go", ccName), fmt.Sprintf(`package main
+ import (
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ )
+
+ func main() {
+ cmd := exec.Command(%q, os.Args[1:]...)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ err := cmd.Run()
+ if err != nil {
+ panic(err)
+ }
+
+ if os.Args[len(os.Args)-1] == "trivial.c" {
+ return
+ }
+ if filepath.Base(os.Args[len(os.Args)-1]) == "_cgo_defun.c" {
+ return
+ }
+
+ var success bool
+ for _, arg := range os.Args {
+ switch {
+ case strings.Contains(arg, "c flags"):
+ if success {
+ panic("duplicate CFLAGS")
+ }
+ success = true
+ case strings.Contains(arg, "ld flags"):
+ if success {
+ panic("duplicate LDFLAGS")
+ }
+ success = true
+ }
+ }
+ if !success {
+ panic("args should contains '-Ic flags' or '-Lld flags'")
+ }
+ }
+ `, testCC))
+ tg.cd(tg.path(fmt.Sprintf("src/%s", ccName)))
+ tg.run("build")
+ tg.setenv("CC", tg.path(fmt.Sprintf("src/%s/%s", ccName, ccName)))
+
+ tg.tempFile("src/cgo/main.go", `package main
+ // #cgo CFLAGS: -I"c flags"
+ // #cgo LDFLAGS: -L"ld flags"
+ import "C"
+ func main() {}
+ `)
+ tg.cd(tg.path("src/cgo"))
+ tg.run("run", "main.go")
+}
+
+// Issue #20435.
+func TestGoTestRaceCoverModeFailures(t *testing.T) {
+ if !canRace {
+ t.Skip("skipping because race detector not supported")
+ }
+
+ tg := testgo(t)
+ tg.parallel()
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+
+ tg.run("test", "testrace")
+
+ tg.runFail("test", "-race", "-covermode=set", "testrace")
+ tg.grepStderr(`-covermode must be "atomic", not "set", when -race is enabled`, "-race -covermode=set was allowed")
+ tg.grepBothNot("PASS", "something passed")
+}
+
+// Issue 9737: verify that GOARM and GO386 affect the computed build ID.
+func TestBuildIDContainsArchModeEnv(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+
+ var tg *testgoData
+ testWith := func(before, after func()) func(*testing.T) {
+ return func(t *testing.T) {
+ tg = testgo(t)
+ defer tg.cleanup()
+ tg.tempFile("src/mycmd/x.go", `package main
+func main() {}`)
+ tg.setenv("GOPATH", tg.path("."))
+
+ tg.cd(tg.path("src/mycmd"))
+ tg.setenv("GOOS", "linux")
+ before()
+ tg.run("install", "mycmd")
+ after()
+ tg.wantStale("mycmd", "build ID mismatch", "should be stale after environment variable change")
+ }
+ }
+
+ t.Run("386", testWith(func() {
+ tg.setenv("GOARCH", "386")
+ tg.setenv("GO386", "387")
+ }, func() {
+ tg.setenv("GO386", "sse2")
+ }))
+
+ t.Run("arm", testWith(func() {
+ tg.setenv("GOARCH", "arm")
+ tg.setenv("GOARM", "5")
+ }, func() {
+ tg.setenv("GOARM", "7")
+ }))
+}
+
+func TestTestRegexps(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.run("test", "-cpu=1", "-run=X/Y", "-bench=X/Y", "-count=2", "-v", "testregexp")
+ var lines []string
+ for _, line := range strings.SplitAfter(tg.getStdout(), "\n") {
+ if strings.Contains(line, "=== RUN") || strings.Contains(line, "--- BENCH") || strings.Contains(line, "LOG") {
+ lines = append(lines, line)
+ }
+ }
+
+ // Important parts:
+ // TestX is run, twice
+ // TestX/Y is run, twice
+ // TestXX is run, twice
+ // TestZ is not run
+ // BenchmarkX is run but only with N=1, once
+ // BenchmarkXX is run but only with N=1, once
+ // BenchmarkX/Y is run in full, twice
+ want := `=== RUN TestX
+=== RUN TestX/Y
+ x_test.go:6: LOG: X running
+ x_test.go:8: LOG: Y running
+=== RUN TestXX
+ z_test.go:10: LOG: XX running
+=== RUN TestX
+=== RUN TestX/Y
+ x_test.go:6: LOG: X running
+ x_test.go:8: LOG: Y running
+=== RUN TestXX
+ z_test.go:10: LOG: XX running
+--- 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
+--- 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
+--- BENCH: BenchmarkX
+ x_test.go:13: LOG: X running N=1
+--- BENCH: BenchmarkXX
+ z_test.go:18: LOG: XX running N=1
+`
+
+ have := strings.Join(lines, "")
+ if have != want {
+ t.Errorf("reduced output:<<<\n%s>>> want:<<<\n%s>>>", have, want)
+ }
+}
+
+func TestListTests(t *testing.T) {
+ var tg *testgoData
+ testWith := func(listName, expected string) func(*testing.T) {
+ return func(t *testing.T) {
+ tg = testgo(t)
+ defer tg.cleanup()
+ tg.run("test", "./testdata/src/testlist/...", fmt.Sprintf("-list=%s", listName))
+ tg.grepStdout(expected, fmt.Sprintf("-test.list=%s returned %q, expected %s", listName, tg.getStdout(), expected))
+ }
+ }
+
+ t.Run("Test", testWith("Test", "TestSimple"))
+ t.Run("Bench", testWith("Benchmark", "BenchmarkSimple"))
+ t.Run("Example1", testWith("Example", "ExampleSimple"))
+ t.Run("Example2", testWith("Example", "ExampleWithEmptyOutput"))
+}
diff --git a/libgo/go/cmd/go/go_unix_test.go b/libgo/go/cmd/go/go_unix_test.go
index c445a2e..f6e10ca 100644
--- a/libgo/go/cmd/go/go_unix_test.go
+++ b/libgo/go/cmd/go/go_unix_test.go
@@ -19,9 +19,13 @@ func TestGoBuildUmask(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.tempFile("x.go", `package main; func main() {}`)
- tg.creatingTemp("x")
- tg.run("build", tg.path("x.go"))
- fi, err := os.Stat("x")
+ // Make sure artifact will be output to /tmp/... in case the user
+ // has POSIX acl's on their go source tree.
+ // See issue 17909.
+ exe := tg.path("x")
+ tg.creatingTemp(exe)
+ tg.run("build", "-o", exe, tg.path("x.go"))
+ fi, err := os.Stat(exe)
if err != nil {
t.Fatal(err)
}
diff --git a/libgo/go/cmd/go/internal/base/base.go b/libgo/go/cmd/go/internal/base/base.go
new file mode 100644
index 0000000..aff33f7
--- /dev/null
+++ b/libgo/go/cmd/go/internal/base/base.go
@@ -0,0 +1,173 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package base defines shared basic pieces of the go command,
+// in particular logging and the Command structure.
+package base
+
+import (
+ "bytes"
+ "errors"
+ "flag"
+ "fmt"
+ "go/scanner"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+ "sync"
+
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/str"
+)
+
+// A Command is an implementation of a go command
+// like go build or go fix.
+type Command struct {
+ // Run runs the command.
+ // The args are the arguments after the command name.
+ 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.
+ UsageLine string
+
+ // Short is the short description shown in the 'go help' output.
+ Short string
+
+ // Long is the long message shown in the 'go help ' output.
+ Long string
+
+ // Flag is a set of flags specific to this command.
+ Flag flag.FlagSet
+
+ // CustomFlags indicates that the command will do its own
+ // flag parsing.
+ CustomFlags bool
+}
+
+// Commands lists the available commands and help topics.
+// The order here is the order in which they are printed by 'go help'.
+var Commands []*Command
+
+// Name returns the command's name: the first word in the usage line.
+func (c *Command) Name() string {
+ name := c.UsageLine
+ i := strings.Index(name, " ")
+ if i >= 0 {
+ name = name[:i]
+ }
+ return name
+}
+
+func (c *Command) Usage() {
+ fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
+ fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
+ os.Exit(2)
+}
+
+// Runnable reports whether the command can be run; otherwise
+// it is a documentation pseudo-command such as importpath.
+func (c *Command) Runnable() bool {
+ return c.Run != nil
+}
+
+var atExitFuncs []func()
+
+func AtExit(f func()) {
+ atExitFuncs = append(atExitFuncs, f)
+}
+
+func Exit() {
+ for _, f := range atExitFuncs {
+ f()
+ }
+ os.Exit(exitStatus)
+}
+
+func Fatalf(format string, args ...interface{}) {
+ Errorf(format, args...)
+ Exit()
+}
+
+func Errorf(format string, args ...interface{}) {
+ log.Printf(format, args...)
+ SetExitStatus(1)
+}
+
+func ExitIfErrors() {
+ if exitStatus != 0 {
+ Exit()
+ }
+}
+
+var exitStatus = 0
+var exitMu sync.Mutex
+
+func SetExitStatus(n int) {
+ exitMu.Lock()
+ if exitStatus < n {
+ exitStatus = n
+ }
+ exitMu.Unlock()
+}
+
+// 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.
+func Run(cmdargs ...interface{}) {
+ cmdline := str.StringList(cmdargs...)
+ if cfg.BuildN || cfg.BuildX {
+ fmt.Printf("%s\n", strings.Join(cmdline, " "))
+ if cfg.BuildN {
+ return
+ }
+ }
+
+ cmd := exec.Command(cmdline[0], cmdline[1:]...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ Errorf("%v", err)
+ }
+}
+
+// RunStdin is like run but connects Stdin.
+func RunStdin(cmdline []string) {
+ cmd := exec.Command(cmdline[0], cmdline[1:]...)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ cmd.Env = cfg.OrigEnv
+ StartSigHandlers()
+ if err := cmd.Run(); err != nil {
+ Errorf("%v", err)
+ }
+}
+
+// Usage is the usage-reporting function, filled in by package main
+// but here for reference by other packages.
+var Usage func()
+
+// ExpandScanner expands a scanner.List error into all the errors in the list.
+// The default Error method only shows the first error
+// and does not shorten paths.
+func ExpandScanner(err error) error {
+ // Look for parser errors.
+ if err, ok := err.(scanner.ErrorList); ok {
+ // Prepare error with \n before each message.
+ // When printed in something like context: %v
+ // this will put the leading file positions each on
+ // its own line. It will also show all the errors
+ // instead of just the first, as err.Error does.
+ var buf bytes.Buffer
+ for _, e := range err {
+ e.Pos.Filename = ShortPath(e.Pos.Filename)
+ buf.WriteString("\n")
+ buf.WriteString(e.Error())
+ }
+ return errors.New(buf.String())
+ }
+ return err
+}
diff --git a/libgo/go/cmd/go/internal/base/env.go b/libgo/go/cmd/go/internal/base/env.go
new file mode 100644
index 0000000..fcade9d
--- /dev/null
+++ b/libgo/go/cmd/go/internal/base/env.go
@@ -0,0 +1,37 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package 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.
+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
+}
diff --git a/libgo/go/cmd/go/internal/base/flag.go b/libgo/go/cmd/go/internal/base/flag.go
new file mode 100644
index 0000000..5e03e64
--- /dev/null
+++ b/libgo/go/cmd/go/internal/base/flag.go
@@ -0,0 +1,35 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package base
+
+import (
+ "flag"
+
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/str"
+)
+
+// A StringsFlag is a command-line flag that interprets its argument
+// as a space-separated list of possibly-quoted strings.
+type StringsFlag []string
+
+func (v *StringsFlag) Set(s string) error {
+ var err error
+ *v, err = str.SplitQuotedFields(s)
+ if *v == nil {
+ *v = []string{}
+ }
+ return err
+}
+
+func (v *StringsFlag) String() string {
+ return ""
+}
+
+// AddBuildFlagsNX adds the -n and -x build flags to the flag set.
+func AddBuildFlagsNX(flags *flag.FlagSet) {
+ flags.BoolVar(&cfg.BuildN, "n", false, "")
+ flags.BoolVar(&cfg.BuildX, "x", false, "")
+}
diff --git a/libgo/go/cmd/go/internal/base/path.go b/libgo/go/cmd/go/internal/base/path.go
new file mode 100644
index 0000000..4f12fa8
--- /dev/null
+++ b/libgo/go/cmd/go/internal/base/path.go
@@ -0,0 +1,74 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package base
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func getwd() string {
+ wd, err := os.Getwd()
+ if err != nil {
+ Fatalf("cannot determine current directory: %v", err)
+ }
+ return wd
+}
+
+var Cwd = getwd()
+
+// ShortPath returns an absolute or relative name for path, whatever is shorter.
+func ShortPath(path string) string {
+ if rel, err := filepath.Rel(Cwd, path); err == nil && len(rel) < len(path) {
+ return rel
+ }
+ return path
+}
+
+// RelPaths returns a copy of paths with absolute paths
+// made relative to the current directory if they would be shorter.
+func RelPaths(paths []string) []string {
+ var out []string
+ // TODO(rsc): Can this use Cwd from above?
+ pwd, _ := os.Getwd()
+ for _, p := range paths {
+ rel, err := filepath.Rel(pwd, p)
+ if err == nil && len(rel) < len(p) {
+ p = rel
+ }
+ out = append(out, p)
+ }
+ return out
+}
+
+// FilterDotUnderscoreFiles returns a slice containing all elements
+// of path whose base name doesn't begin with "." or "_".
+func FilterDotUnderscoreFiles(path []string) []string {
+ var out []string // lazily initialized
+ for i, p := range path {
+ base := filepath.Base(p)
+ if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "_") {
+ if out == nil {
+ out = append(make([]string, 0, len(path)), path[:i]...)
+ }
+ continue
+ }
+ if out != nil {
+ out = append(out, p)
+ }
+ }
+ if out == nil {
+ return path
+ }
+ return out
+}
+
+// IsTestFile reports whether the source file is a set of tests and should therefore
+// be excluded from coverage analysis.
+func IsTestFile(file string) bool {
+ // We don't cover tests, only the code they test.
+ return strings.HasSuffix(file, "_test.go")
+}
diff --git a/libgo/go/cmd/go/signal.go b/libgo/go/cmd/go/internal/base/signal.go
similarity index 66%
rename from libgo/go/cmd/go/signal.go
rename to libgo/go/cmd/go/internal/base/signal.go
index e8ba0d3..54d1187 100644
--- a/libgo/go/cmd/go/signal.go
+++ b/libgo/go/cmd/go/internal/base/signal.go
@@ -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 main
+package base
import (
"os"
@@ -10,8 +10,8 @@ import (
"sync"
)
-// interrupted is closed, if go process is interrupted.
-var interrupted = make(chan struct{})
+// Interrupted is closed when the go command receives an interrupt signal.
+var Interrupted = make(chan struct{})
// processSignals setups signal handler.
func processSignals() {
@@ -19,13 +19,13 @@ func processSignals() {
signal.Notify(sig, signalsToIgnore...)
go func() {
<-sig
- close(interrupted)
+ close(Interrupted)
}()
}
var onceProcessSignals sync.Once
-// startSigHandlers start signal handlers.
-func startSigHandlers() {
+// StartSigHandlers starts the signal handlers.
+func StartSigHandlers() {
onceProcessSignals.Do(processSignals)
}
diff --git a/libgo/go/cmd/go/signal_notunix.go b/libgo/go/cmd/go/internal/base/signal_notunix.go
similarity index 60%
rename from libgo/go/cmd/go/signal_notunix.go
rename to libgo/go/cmd/go/internal/base/signal_notunix.go
index 29aa9d8..9e869b0 100644
--- a/libgo/go/cmd/go/signal_notunix.go
+++ b/libgo/go/cmd/go/internal/base/signal_notunix.go
@@ -4,7 +4,7 @@
// +build plan9 windows
-package main
+package base
import (
"os"
@@ -12,6 +12,6 @@ import (
var signalsToIgnore = []os.Signal{os.Interrupt}
-// signalTrace is the signal to send to make a Go program
-// crash with a stack trace.
-var signalTrace os.Signal = nil
+// SignalTrace is the signal to send to make a Go program
+// crash with a stack trace (no such signal in this case).
+var SignalTrace os.Signal = nil
diff --git a/libgo/go/cmd/go/signal_unix.go b/libgo/go/cmd/go/internal/base/signal_unix.go
similarity index 75%
rename from libgo/go/cmd/go/signal_unix.go
rename to libgo/go/cmd/go/internal/base/signal_unix.go
index e86cd46..4ca3da9 100644
--- a/libgo/go/cmd/go/signal_unix.go
+++ b/libgo/go/cmd/go/internal/base/signal_unix.go
@@ -4,7 +4,7 @@
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
-package main
+package base
import (
"os"
@@ -13,6 +13,6 @@ import (
var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT}
-// signalTrace is the signal to send to make a Go program
+// SignalTrace is the signal to send to make a Go program
// crash with a stack trace.
-var signalTrace os.Signal = syscall.SIGQUIT
+var SignalTrace os.Signal = syscall.SIGQUIT
diff --git a/libgo/go/cmd/go/internal/base/tool.go b/libgo/go/cmd/go/internal/base/tool.go
new file mode 100644
index 0000000..c907772
--- /dev/null
+++ b/libgo/go/cmd/go/internal/base/tool.go
@@ -0,0 +1,53 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package base
+
+import (
+ "fmt"
+ "go/build"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "cmd/go/internal/cfg"
+)
+
+// Configuration for finding tool binaries.
+var (
+ ToolGOOS = runtime.GOOS
+ ToolGOARCH = runtime.GOARCH
+ ToolIsWindows = ToolGOOS == "windows"
+ ToolDir = build.ToolDir
+)
+
+const ToolWindowsExtension = ".exe"
+
+// Tool returns the path to the named tool (for example, "vet").
+// If the tool cannot be found, Tool exits the process.
+func Tool(toolName string) string {
+ toolPath := filepath.Join(ToolDir, toolName)
+ if ToolIsWindows {
+ toolPath += ToolWindowsExtension
+ }
+ if len(cfg.BuildToolexec) > 0 {
+ return toolPath
+ }
+ // Give a nice message if there is no tool with that name.
+ if _, err := os.Stat(toolPath); err != nil {
+ if isInGoToolsRepo(toolName) {
+ fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName)
+ } else {
+ fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
+ }
+ SetExitStatus(2)
+ Exit()
+ }
+ return toolPath
+}
+
+// TODO: Delete.
+func isInGoToolsRepo(toolName string) bool {
+ return false
+}
diff --git a/libgo/go/cmd/go/bug.go b/libgo/go/cmd/go/internal/bug/bug.go
similarity index 88%
rename from libgo/go/cmd/go/bug.go
rename to libgo/go/cmd/go/internal/bug/bug.go
index 658f6da..963da94 100644
--- a/libgo/go/cmd/go/bug.go
+++ b/libgo/go/cmd/go/internal/bug/bug.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package bug implements the ``go bug'' command.
+package bug
import (
"bytes"
@@ -15,9 +16,14 @@ import (
"regexp"
"runtime"
"strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/envcmd"
+ "cmd/go/internal/web"
)
-var cmdBug = &Command{
+var CmdBug = &base.Command{
Run: runBug,
UsageLine: "bug",
Short: "start a bug report",
@@ -28,23 +34,23 @@ The report includes useful system information.
}
func init() {
- cmdBug.Flag.BoolVar(&buildV, "v", false, "")
+ CmdBug.Flag.BoolVar(&cfg.BuildV, "v", false, "")
}
-func runBug(cmd *Command, args []string) {
+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 := newEnv
- env = append(env, extraEnvVars()...)
+ 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)
+ if e.Name != "TERM" {
+ fmt.Fprintf(&buf, "%s=\"%s\"\n", e.Name, e.Value)
}
}
printGoDetails(&buf)
@@ -53,8 +59,8 @@ func runBug(cmd *Command, args []string) {
fmt.Fprintln(&buf, "```")
body := buf.String()
- url := "https://github.com/golang/go/issues/new?body=" + queryEscape(body)
- if !openBrowser(url) {
+ url := "https://github.com/golang/go/issues/new?body=" + web.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)
}
@@ -97,7 +103,7 @@ func printOSDetails(w io.Writer) {
if err == nil {
fmt.Fprintf(w, "/etc/release: %s\n", out)
} else {
- if buildV {
+ if cfg.BuildV {
fmt.Printf("failed to read /etc/release: %v\n", err)
}
}
@@ -114,16 +120,16 @@ func printCDetails(w io.Writer) {
// Print up to the first newline.
fmt.Fprintf(w, "gdb --version: %s\n", firstLine(out))
} else {
- if buildV {
+ if cfg.BuildV {
fmt.Printf("failed to run gdb --version: %v\n", err)
}
}
}
func inspectGoVersion(w io.Writer) {
- data, err := httpGET("https://golang.org/VERSION?m=text")
+ data, err := web.Get("https://golang.org/VERSION?m=text")
if err != nil {
- if buildV {
+ if cfg.BuildV {
fmt.Printf("failed to read from golang.org/VERSION: %v\n", err)
}
return
@@ -150,7 +156,7 @@ func printCmdOut(w io.Writer, prefix, path string, args ...string) {
cmd := exec.Command(path, args...)
out, err := cmd.Output()
if err != nil {
- if buildV {
+ if cfg.BuildV {
fmt.Printf("%s %s: %v\n", path, strings.Join(args, " "), err)
}
return
diff --git a/libgo/go/cmd/go/internal/buildid/buildid.go b/libgo/go/cmd/go/internal/buildid/buildid.go
new file mode 100644
index 0000000..091c909
--- /dev/null
+++ b/libgo/go/cmd/go/internal/buildid/buildid.go
@@ -0,0 +1,201 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package buildid
+
+import (
+ "bytes"
+ "cmd/go/internal/cfg"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+)
+
+var (
+ errBuildIDToolchain = fmt.Errorf("build ID only supported in gc toolchain")
+ errBuildIDMalformed = fmt.Errorf("malformed object file")
+ errBuildIDUnknown = fmt.Errorf("lost build ID")
+)
+
+var (
+ bangArch = []byte("!")
+ pkgdef = []byte("__.PKGDEF")
+ goobject = []byte("go object ")
+ buildid = []byte("build id ")
+)
+
+// ReadBuildID reads the build ID from an archive or binary.
+// It only supports the gc toolchain.
+// Other toolchain maintainers should adjust this function.
+func ReadBuildID(name, target string) (id string, err error) {
+ if cfg.BuildToolchainName != "gc" {
+ return "", errBuildIDToolchain
+ }
+
+ // For commands, read build ID directly from binary.
+ if name == "main" {
+ return ReadBuildIDFromBinary(target)
+ }
+
+ // Otherwise, we expect to have an archive (.a) file,
+ // and we can read the build ID from the Go export data.
+ if !strings.HasSuffix(target, ".a") {
+ return "", &os.PathError{Op: "parse", Path: target, Err: errBuildIDUnknown}
+ }
+
+ // Read just enough of the target to fetch the build ID.
+ // The archive is expected to look like:
+ //
+ // !
+ // __.PKGDEF 0 0 0 644 7955 `
+ // go object darwin amd64 devel X:none
+ // build id "b41e5c45250e25c9fd5e9f9a1de7857ea0d41224"
+ //
+ // The variable-sized strings are GOOS, GOARCH, and the experiment list (X:none).
+ // Reading the first 1024 bytes should be plenty.
+ f, err := os.Open(target)
+ if err != nil {
+ return "", err
+ }
+ data := make([]byte, 1024)
+ n, err := io.ReadFull(f, data)
+ f.Close()
+
+ if err != nil && n == 0 {
+ return "", err
+ }
+
+ bad := func() (string, error) {
+ return "", &os.PathError{Op: "parse", Path: target, Err: errBuildIDMalformed}
+ }
+
+ // Archive header.
+ for i := 0; ; i++ { // returns during i==3
+ j := bytes.IndexByte(data, '\n')
+ if j < 0 {
+ return bad()
+ }
+ line := data[:j]
+ data = data[j+1:]
+ switch i {
+ case 0:
+ if !bytes.Equal(line, bangArch) {
+ return bad()
+ }
+ case 1:
+ if !bytes.HasPrefix(line, pkgdef) {
+ return bad()
+ }
+ case 2:
+ if !bytes.HasPrefix(line, goobject) {
+ return bad()
+ }
+ case 3:
+ if !bytes.HasPrefix(line, buildid) {
+ // Found the object header, just doesn't have a build id line.
+ // Treat as successful, with empty build id.
+ return "", nil
+ }
+ id, err := strconv.Unquote(string(line[len(buildid):]))
+ if err != nil {
+ return bad()
+ }
+ return id, nil
+ }
+ }
+}
+
+var (
+ goBuildPrefix = []byte("\xff Go build ID: \"")
+ goBuildEnd = []byte("\"\n \xff")
+
+ elfPrefix = []byte("\x7fELF")
+
+ machoPrefixes = [][]byte{
+ {0xfe, 0xed, 0xfa, 0xce},
+ {0xfe, 0xed, 0xfa, 0xcf},
+ {0xce, 0xfa, 0xed, 0xfe},
+ {0xcf, 0xfa, 0xed, 0xfe},
+ }
+)
+
+var BuildIDReadSize = 32 * 1024 // changed for testing
+
+// ReadBuildIDFromBinary reads the build ID from a binary.
+//
+// ELF binaries store the build ID in a proper PT_NOTE section.
+//
+// Other binary formats are not so flexible. For those, the linker
+// stores the build ID as non-instruction bytes at the very beginning
+// of the text segment, which should appear near the beginning
+// of the file. This is clumsy but fairly portable. Custom locations
+// can be added for other binary types as needed, like we did for ELF.
+func ReadBuildIDFromBinary(filename string) (id string, err error) {
+ if filename == "" {
+ return "", &os.PathError{Op: "parse", Path: filename, Err: errBuildIDUnknown}
+ }
+
+ // Read the first 32 kB of the binary file.
+ // That should be enough to find the build ID.
+ // In ELF files, the build ID is in the leading headers,
+ // which are typically less than 4 kB, not to mention 32 kB.
+ // In Mach-O files, there's no limit, so we have to parse the file.
+ // On other systems, we're trying to read enough that
+ // we get the beginning of the text segment in the read.
+ // The offset where the text segment begins in a hello
+ // world compiled for each different object format today:
+ //
+ // Plan 9: 0x20
+ // Windows: 0x600
+ //
+ f, err := os.Open(filename)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ data := make([]byte, BuildIDReadSize)
+ _, err = io.ReadFull(f, data)
+ if err == io.ErrUnexpectedEOF {
+ err = nil
+ }
+ if err != nil {
+ return "", err
+ }
+
+ if bytes.HasPrefix(data, elfPrefix) {
+ return readELFGoBuildID(filename, f, data)
+ }
+ for _, m := range machoPrefixes {
+ if bytes.HasPrefix(data, m) {
+ return readMachoGoBuildID(filename, f, data)
+ }
+ }
+
+ return readRawGoBuildID(filename, data)
+}
+
+// readRawGoBuildID finds the raw build ID stored in text segment data.
+func readRawGoBuildID(filename string, data []byte) (id string, err error) {
+ i := bytes.Index(data, goBuildPrefix)
+ if i < 0 {
+ // Missing. Treat as successful but build ID empty.
+ return "", nil
+ }
+
+ j := bytes.Index(data[i+len(goBuildPrefix):], goBuildEnd)
+ if j < 0 {
+ return "", &os.PathError{Op: "parse", Path: filename, Err: errBuildIDMalformed}
+ }
+
+ quoted := data[i+len(goBuildPrefix)-1 : i+len(goBuildPrefix)+j+1]
+ id, err = strconv.Unquote(string(quoted))
+ if err != nil {
+ return "", &os.PathError{Op: "parse", Path: filename, Err: errBuildIDMalformed}
+ }
+
+ return id, nil
+}
diff --git a/libgo/go/cmd/go/note.go b/libgo/go/cmd/go/internal/buildid/note.go
similarity index 98%
rename from libgo/go/cmd/go/note.go
rename to libgo/go/cmd/go/internal/buildid/note.go
index fae9536..68c91e2 100644
--- a/libgo/go/cmd/go/note.go
+++ b/libgo/go/cmd/go/internal/buildid/note.go
@@ -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 main
+package buildid
import (
"bytes"
@@ -25,7 +25,7 @@ func readAligned4(r io.Reader, sz int32) ([]byte, error) {
return data, nil
}
-func readELFNote(filename, name string, typ int32) ([]byte, error) {
+func ReadELFNote(filename, name string, typ int32) ([]byte, error) {
f, err := elf.Open(filename)
if err != nil {
return nil, err
diff --git a/libgo/go/cmd/go/internal/cfg/cfg.go b/libgo/go/cmd/go/internal/cfg/cfg.go
new file mode 100644
index 0000000..8257a0e
--- /dev/null
+++ b/libgo/go/cmd/go/internal/cfg/cfg.go
@@ -0,0 +1,134 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cfg holds configuration shared by multiple parts
+// of the go command.
+package cfg
+
+import (
+ "fmt"
+ "go/build"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "cmd/internal/objabi"
+)
+
+// These are general "build flags" used by build and other commands.
+var (
+ BuildA bool // -a flag
+ BuildBuildmode string // -buildmode flag
+ BuildContext = build.Default
+ BuildI bool // -i flag
+ BuildLdflags []string // -ldflags flag
+ BuildLinkshared bool // -linkshared flag
+ BuildMSan bool // -msan flag
+ BuildN bool // -n flag
+ BuildO string // -o flag
+ BuildP = runtime.NumCPU() // -p flag
+ BuildPkgdir string // -pkgdir flag
+ BuildRace bool // -race flag
+ BuildToolexec []string // -toolexec flag
+ BuildToolchainName string
+ BuildToolchainCompiler func() string
+ BuildToolchainLinker func() string
+ BuildV bool // -v flag
+ BuildWork bool // -work flag
+ BuildX bool // -x flag
+)
+
+func init() {
+ BuildToolchainCompiler = func() string { return "missing-compiler" }
+ BuildToolchainLinker = func() string { return "missing-linker" }
+}
+
+// An EnvVar is an environment variable Name=Value.
+type EnvVar struct {
+ Name string
+ Value string
+}
+
+// OrigEnv is the original environment of the program at startup.
+var OrigEnv []string
+
+// CmdEnv is the new environment for running go tool commands.
+// User binaries (during go test or go run) are run with OrigEnv,
+// not CmdEnv.
+var CmdEnv []EnvVar
+
+// Global build parameters (used during package load)
+var (
+ Goarch = BuildContext.GOARCH
+ Goos = BuildContext.GOOS
+ ExeSuffix string
+ Gopath = filepath.SplitList(BuildContext.GOPATH)
+)
+
+func init() {
+ if Goos == "windows" {
+ ExeSuffix = ".exe"
+ }
+}
+
+var (
+ GOROOT = findGOROOT()
+ GOBIN = os.Getenv("GOBIN")
+ GOROOTbin = filepath.Join(GOROOT, "bin")
+ GOROOTpkg = filepath.Join(GOROOT, "pkg")
+ GOROOTsrc = filepath.Join(GOROOT, "src")
+
+ // Used in envcmd.MkEnv and build ID computations.
+ GOARM = fmt.Sprint(objabi.GOARM)
+ GO386 = objabi.GO386
+)
+
+// Update build context to use our computed GOROOT.
+func init() {
+ BuildContext.GOROOT = GOROOT
+ // 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().
+ if runtime.Compiler != "gccgo" {
+ build.ToolDir = filepath.Join(GOROOT, "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
+ }
+}
+
+func findGOROOT() string {
+ if env := os.Getenv("GOROOT"); env != "" {
+ return filepath.Clean(env)
+ }
+ if runtime.Compiler != "gccgo" {
+ exe, err := os.Executable()
+ if err == nil {
+ exe, err = filepath.Abs(exe)
+ if err == nil {
+ if dir := filepath.Join(exe, "../.."); isGOROOT(dir) {
+ return dir
+ }
+ exe, err = filepath.EvalSymlinks(exe)
+ if err == nil {
+ if dir := filepath.Join(exe, "../.."); isGOROOT(dir) {
+ return dir
+ }
+ }
+ }
+ }
+ }
+ return filepath.Clean(runtime.GOROOT())
+}
+
+// isGOROOT reports whether path looks like a GOROOT.
+//
+// It does this by looking for the path/pkg/tool directory,
+// which is necessary for useful operation of the cmd/go tool,
+// and is not typically present in a GOPATH.
+func isGOROOT(path string) bool {
+ stat, err := os.Stat(filepath.Join(path, "pkg", "tool"))
+ if err != nil {
+ return false
+ }
+ return stat.IsDir()
+}
diff --git a/libgo/go/cmd/go/clean.go b/libgo/go/cmd/go/internal/clean/clean.go
similarity index 81%
rename from libgo/go/cmd/go/clean.go
rename to libgo/go/cmd/go/internal/clean/clean.go
index 7b07150..454cac1 100644
--- a/libgo/go/cmd/go/clean.go
+++ b/libgo/go/cmd/go/internal/clean/clean.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package clean implements the ``go clean'' command.
+package clean
import (
"fmt"
@@ -10,9 +11,14 @@ import (
"os"
"path/filepath"
"strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/work"
)
-var cmdClean = &Command{
+var CmdClean = &base.Command{
UsageLine: "clean [-i] [-r] [-n] [-x] [build flags] [packages]",
Short: "remove object files",
Long: `
@@ -63,24 +69,24 @@ var cleanR bool // clean -r flag
func init() {
// break init cycle
- cmdClean.Run = runClean
+ CmdClean.Run = runClean
- cmdClean.Flag.BoolVar(&cleanI, "i", false, "")
- cmdClean.Flag.BoolVar(&cleanR, "r", false, "")
+ CmdClean.Flag.BoolVar(&cleanI, "i", false, "")
+ CmdClean.Flag.BoolVar(&cleanR, "r", false, "")
// -n and -x are important enough to be
// mentioned explicitly in the docs but they
// are part of the build flags.
- addBuildFlags(cmdClean)
+ work.AddBuildFlags(CmdClean)
}
-func runClean(cmd *Command, args []string) {
- for _, pkg := range packagesAndErrors(args) {
+func runClean(cmd *base.Command, args []string) {
+ for _, pkg := range load.PackagesAndErrors(args) {
clean(pkg)
}
}
-var cleaned = map[*Package]bool{}
+var cleaned = map[*load.Package]bool{}
// TODO: These are dregs left by Makefile-based builds.
// Eventually, can stop deleting these.
@@ -105,24 +111,24 @@ var cleanExt = map[string]bool{
".so": true,
}
-func clean(p *Package) {
+func clean(p *load.Package) {
if cleaned[p] {
return
}
cleaned[p] = true
if p.Dir == "" {
- errorf("can't load package: %v", p.Error)
+ base.Errorf("can't load package: %v", p.Error)
return
}
dirs, err := ioutil.ReadDir(p.Dir)
if err != nil {
- errorf("go clean %s: %v", p.Dir, err)
+ base.Errorf("go clean %s: %v", p.Dir, err)
return
}
- var b builder
- b.print = fmt.Print
+ var b work.Builder
+ b.Print = fmt.Print
packageFile := map[string]bool{}
if p.Name != "main" {
@@ -172,8 +178,8 @@ func clean(p *Package) {
}
}
- if buildN || buildX {
- b.showcmd(p.Dir, "rm -f %s", strings.Join(allRemove, " "))
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd(p.Dir, "rm -f %s", strings.Join(allRemove, " "))
}
toRemove := map[string]bool{}
@@ -185,20 +191,20 @@ func clean(p *Package) {
if dir.IsDir() {
// TODO: Remove once Makefiles are forgotten.
if cleanDir[name] {
- if buildN || buildX {
- b.showcmd(p.Dir, "rm -r %s", name)
- if buildN {
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd(p.Dir, "rm -r %s", name)
+ if cfg.BuildN {
continue
}
}
if err := os.RemoveAll(filepath.Join(p.Dir, name)); err != nil {
- errorf("go clean: %v", err)
+ base.Errorf("go clean: %v", err)
}
}
continue
}
- if buildN {
+ if cfg.BuildN {
continue
}
@@ -207,17 +213,17 @@ func clean(p *Package) {
}
}
- if cleanI && p.target != "" {
- if buildN || buildX {
- b.showcmd("", "rm -f %s", p.target)
+ if cleanI && p.Internal.Target != "" {
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd("", "rm -f %s", p.Internal.Target)
}
- if !buildN {
- removeFile(p.target)
+ if !cfg.BuildN {
+ removeFile(p.Internal.Target)
}
}
if cleanR {
- for _, p1 := range p.imports {
+ for _, p1 := range p.Internal.Imports {
clean(p1)
}
}
@@ -231,7 +237,7 @@ func removeFile(f string) {
return
}
// Windows does not allow deletion of a binary file while it is executing.
- if toolIsWindows {
+ if base.ToolIsWindows {
// Remove lingering ~ file from last attempt.
if _, err2 := os.Stat(f + "~"); err2 == nil {
os.Remove(f + "~")
@@ -244,5 +250,5 @@ func removeFile(f string) {
return
}
}
- errorf("go clean: %v", err)
+ base.Errorf("go clean: %v", err)
}
diff --git a/libgo/go/cmd/go/internal/cmdflag/flag.go b/libgo/go/cmd/go/internal/cmdflag/flag.go
new file mode 100644
index 0000000..7ab3022
--- /dev/null
+++ b/libgo/go/cmd/go/internal/cmdflag/flag.go
@@ -0,0 +1,123 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cmdflag handles flag processing common to several go tools.
+package cmdflag
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strconv"
+ "strings"
+
+ "cmd/go/internal/base"
+)
+
+// The flag handling part of go commands such as test is large and distracting.
+// We can't use the standard flag package because some of the flags from
+// our command line are for us, and some are for the binary we're running,
+// and some are for both.
+
+// Defn defines a flag we know about.
+type Defn struct {
+ Name string // Name on command line.
+ BoolVar *bool // If it's a boolean flag, this points to it.
+ Value flag.Value // The flag.Value represented.
+ PassToTest bool // Pass to the test binary? Used only by go test.
+ Present bool // Flag has been seen.
+}
+
+// IsBool reports whether v is a bool flag.
+func IsBool(v flag.Value) bool {
+ vv, ok := v.(interface {
+ IsBoolFlag() bool
+ })
+ if ok {
+ return vv.IsBoolFlag()
+ }
+ return false
+}
+
+// SetBool sets the addressed boolean to the value.
+func SetBool(cmd string, flag *bool, value string) {
+ x, err := strconv.ParseBool(value)
+ if err != nil {
+ SyntaxError(cmd, "illegal bool flag value "+value)
+ }
+ *flag = x
+}
+
+// SetInt sets the addressed integer to the value.
+func SetInt(cmd string, flag *int, value string) {
+ x, err := strconv.Atoi(value)
+ if err != nil {
+ SyntaxError(cmd, "illegal int flag value "+value)
+ }
+ *flag = x
+}
+
+// SyntaxError reports an argument syntax error and exits the program.
+func SyntaxError(cmd, msg string) {
+ fmt.Fprintf(os.Stderr, "go %s: %s\n", cmd, msg)
+ if cmd == "test" {
+ fmt.Fprintf(os.Stderr, `run "go help %s" or "go help testflag" for more information`+"\n", cmd)
+ } else {
+ fmt.Fprintf(os.Stderr, `run "go help %s" for more information`+"\n", cmd)
+ }
+ os.Exit(2)
+}
+
+// Parse sees if argument i is present in the definitions and if so,
+// returns its definition, value, and whether it consumed an extra word.
+// If the flag begins (cmd+".") it is ignored for the purpose of this function.
+func Parse(cmd string, defns []*Defn, args []string, i int) (f *Defn, value string, extra bool) {
+ arg := args[i]
+ if strings.HasPrefix(arg, "--") { // reduce two minuses to one
+ arg = arg[1:]
+ }
+ switch arg {
+ case "-?", "-h", "-help":
+ base.Usage()
+ }
+ if arg == "" || arg[0] != '-' {
+ return
+ }
+ name := arg[1:]
+ // If there's already a prefix such as "test.", drop it for now.
+ name = strings.TrimPrefix(name, cmd+".")
+ equals := strings.Index(name, "=")
+ if equals >= 0 {
+ value = name[equals+1:]
+ name = name[:equals]
+ }
+ for _, f = range defns {
+ if name == f.Name {
+ // Booleans are special because they have modes -x, -x=true, -x=false.
+ if f.BoolVar != nil || IsBool(f.Value) {
+ if equals < 0 { // Otherwise, it's been set and will be verified in SetBool.
+ value = "true"
+ } else {
+ // verify it parses
+ SetBool(cmd, new(bool), value)
+ }
+ } else { // Non-booleans must have a value.
+ extra = equals < 0
+ if extra {
+ if i+1 >= len(args) {
+ SyntaxError(cmd, "missing argument for flag "+f.Name)
+ }
+ value = args[i+1]
+ }
+ }
+ if f.Present {
+ SyntaxError(cmd, f.Name+" flag may be set only once")
+ }
+ f.Present = true
+ return
+ }
+ }
+ f = nil
+ return
+}
diff --git a/libgo/go/cmd/go/doc.go b/libgo/go/cmd/go/internal/doc/doc.go
similarity index 79%
rename from libgo/go/cmd/go/doc.go
rename to libgo/go/cmd/go/internal/doc/doc.go
index 8299839..d73dd9a 100644
--- a/libgo/go/cmd/go/doc.go
+++ b/libgo/go/cmd/go/internal/doc/doc.go
@@ -2,20 +2,25 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:generate ./mkalldocs.sh
+// Package doc implements the ``go doc'' command.
+package doc
-package main
+import (
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+)
-var cmdDoc = &Command{
+var CmdDoc = &base.Command{
Run: runDoc,
- UsageLine: "doc [-u] [-c] [package|[package.]symbol[.method]]",
+ UsageLine: "doc [-u] [-c] [package|[package.]symbol[.methodOrField]]",
CustomFlags: true,
Short: "show documentation for package or symbol",
Long: `
Doc prints the documentation comments associated with the item identified by its
-arguments (a package, const, func, type, var, or method) followed by a one-line
-summary of each of the first-level items "under" that item (package-level
-declarations for a package, methods for a type, etc.).
+arguments (a package, const, func, type, var, method, or struct field)
+followed by a one-line summary of each of the first-level items "under"
+that item (package-level declarations for a package, methods for a type,
+etc.).
Doc accepts zero, one, or two arguments.
@@ -33,9 +38,9 @@ on what is installed in GOROOT and GOPATH, as well as the form of the argument,
which is schematically one of these:
go doc
- go doc [.]
- go doc [.][.]
- go doc [.][.]
+ go doc [.]
+ go doc [.][.]
+ go doc [.][.]
The first item in this list matched by the argument is the one whose documentation
is printed. (See the examples below.) However, if the argument starts with a capital
@@ -43,7 +48,7 @@ letter it is assumed to identify a symbol or method in the current directory.
For packages, the order of scanning is determined lexically in breadth-first order.
That is, the package presented is the one that matches the search and is nearest
-the root and lexically first at its level of the hierarchy. The GOROOT tree is
+the root and lexically first at its level of the hierarchy. The GOROOT tree is
always scanned in its entirety before GOPATH.
If there is no package specified or matched, the package in the current
@@ -55,10 +60,10 @@ path. The go tool's usual package mechanism does not apply: package path
elements like . and ... are not implemented by go doc.
When run with two arguments, the first must be a full package path (not just a
-suffix), and the second is a symbol or symbol and method; this is similar to the
-syntax accepted by godoc:
+suffix), and the second is a symbol, or symbol with method or struct field.
+This is similar to the syntax accepted by godoc:
- go doc [.]
+ go doc [.]
In all forms, when matching symbols, lower-case letters in the argument match
either case but upper-case letters match exactly. This means that there may be
@@ -109,10 +114,10 @@ Flags:
when showing the package's top-level documentation.
-u
Show documentation for unexported as well as exported
- symbols and methods.
+ symbols, methods, and fields.
`,
}
-func runDoc(cmd *Command, args []string) {
- run(buildToolExec, tool("doc"), args)
+func runDoc(cmd *base.Command, args []string) {
+ base.Run(cfg.BuildToolexec, base.Tool("doc"), args)
}
diff --git a/libgo/go/cmd/go/internal/envcmd/env.go b/libgo/go/cmd/go/internal/envcmd/env.go
new file mode 100644
index 0000000..43d4334
--- /dev/null
+++ b/libgo/go/cmd/go/internal/envcmd/env.go
@@ -0,0 +1,178 @@
+// Copyright 2012 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 envcmd implements the ``go env'' command.
+package envcmd
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "runtime"
+ "strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/work"
+)
+
+var CmdEnv = &base.Command{
+ UsageLine: "env [-json] [var ...]",
+ Short: "print Go environment information",
+ Long: `
+Env prints Go environment information.
+
+By default env prints information as a shell script
+(on Windows, a batch file). If one or more variable
+names is given as arguments, env prints the value of
+each named variable on its own line.
+
+The -json flag prints the environment in JSON format
+instead of as a shell script.
+ `,
+}
+
+func init() {
+ CmdEnv.Run = runEnv // break init cycle
+}
+
+var envJson = CmdEnv.Flag.Bool("json", false, "")
+
+func MkEnv() []cfg.EnvVar {
+ var b work.Builder
+ b.Init()
+
+ env := []cfg.EnvVar{
+ {Name: "GOARCH", Value: cfg.Goarch},
+ {Name: "GOBIN", Value: cfg.GOBIN},
+ {Name: "GOEXE", Value: cfg.ExeSuffix},
+ {Name: "GOHOSTARCH", Value: runtime.GOARCH},
+ {Name: "GOHOSTOS", Value: runtime.GOOS},
+ {Name: "GOOS", Value: cfg.Goos},
+ {Name: "GOPATH", Value: cfg.BuildContext.GOPATH},
+ {Name: "GORACE", Value: os.Getenv("GORACE")},
+ {Name: "GOROOT", Value: cfg.GOROOT},
+ {Name: "GOTOOLDIR", Value: base.ToolDir},
+
+ // disable escape codes in clang errors
+ {Name: "TERM", Value: "dumb"},
+ }
+
+ if work.GccgoBin != "" {
+ env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin})
+ } else {
+ 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})
+ }
+
+ cmd := b.GccCmd(".")
+ env = append(env, cfg.EnvVar{Name: "CC", Value: cmd[0]})
+ env = append(env, cfg.EnvVar{Name: "GOGCCFLAGS", Value: strings.Join(cmd[3:], " ")})
+ cmd = b.GxxCmd(".")
+ env = append(env, cfg.EnvVar{Name: "CXX", Value: cmd[0]})
+
+ if cfg.BuildContext.CgoEnabled {
+ env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1"})
+ } else {
+ env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0"})
+ }
+
+ return env
+}
+
+func findEnv(env []cfg.EnvVar, name string) string {
+ for _, e := range env {
+ if e.Name == name {
+ return e.Value
+ }
+ }
+ return ""
+}
+
+// ExtraEnvVars returns environment variables that should not leak into child processes.
+func ExtraEnvVars() []cfg.EnvVar {
+ var b work.Builder
+ b.Init()
+ cppflags, cflags, cxxflags, fflags, ldflags := b.CFlags(&load.Package{})
+ return []cfg.EnvVar{
+ {Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")},
+ {Name: "CGO_CPPFLAGS", Value: strings.Join(cppflags, " ")},
+ {Name: "CGO_CXXFLAGS", Value: strings.Join(cxxflags, " ")},
+ {Name: "CGO_FFLAGS", Value: strings.Join(fflags, " ")},
+ {Name: "CGO_LDFLAGS", Value: strings.Join(ldflags, " ")},
+ {Name: "PKG_CONFIG", Value: b.PkgconfigCmd()},
+ }
+}
+
+func runEnv(cmd *base.Command, args []string) {
+ env := cfg.CmdEnv
+ env = append(env, ExtraEnvVars()...)
+ if len(args) > 0 {
+ if *envJson {
+ var es []cfg.EnvVar
+ for _, name := range args {
+ e := cfg.EnvVar{Name: name, Value: findEnv(env, name)}
+ es = append(es, e)
+ }
+ printEnvAsJSON(es)
+ } else {
+ for _, name := range args {
+ fmt.Printf("%s\n", findEnv(env, name))
+ }
+ }
+ return
+ }
+
+ if *envJson {
+ printEnvAsJSON(env)
+ return
+ }
+
+ for _, e := range env {
+ if e.Name != "TERM" {
+ switch runtime.GOOS {
+ default:
+ fmt.Printf("%s=\"%s\"\n", e.Name, e.Value)
+ case "plan9":
+ if strings.IndexByte(e.Value, '\x00') < 0 {
+ fmt.Printf("%s='%s'\n", e.Name, strings.Replace(e.Value, "'", "''", -1))
+ } else {
+ v := strings.Split(e.Value, "\x00")
+ fmt.Printf("%s=(", e.Name)
+ for x, s := range v {
+ if x > 0 {
+ fmt.Printf(" ")
+ }
+ fmt.Printf("%s", s)
+ }
+ fmt.Printf(")\n")
+ }
+ case "windows":
+ fmt.Printf("set %s=%s\n", e.Name, e.Value)
+ }
+ }
+ }
+}
+
+func printEnvAsJSON(env []cfg.EnvVar) {
+ m := make(map[string]string)
+ for _, e := range env {
+ if e.Name == "TERM" {
+ continue
+ }
+ m[e.Name] = e.Value
+ }
+ enc := json.NewEncoder(os.Stdout)
+ enc.SetIndent("", "\t")
+ if err := enc.Encode(m); err != nil {
+ base.Fatalf("%s", err)
+ }
+}
diff --git a/libgo/go/cmd/go/fix.go b/libgo/go/cmd/go/internal/fix/fix.go
similarity index 60%
rename from libgo/go/cmd/go/fix.go
rename to libgo/go/cmd/go/internal/fix/fix.go
index 3af7adb..788d49b 100644
--- a/libgo/go/cmd/go/fix.go
+++ b/libgo/go/cmd/go/internal/fix/fix.go
@@ -2,9 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package fix implements the ``go fix'' command.
+package fix
-var cmdFix = &Command{
+import (
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
+)
+
+var CmdFix = &base.Command{
Run: runFix,
UsageLine: "fix [packages]",
Short: "run go tool fix on packages",
@@ -20,11 +28,12 @@ See also: go fmt, go vet.
`,
}
-func runFix(cmd *Command, args []string) {
- for _, pkg := range packages(args) {
+func runFix(cmd *base.Command, args []string) {
+ for _, pkg := range load.Packages(args) {
// Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package,
// not to packages in subdirectories.
- run(stringList(buildToolExec, tool("fix"), relPaths(pkg.allgofiles)))
+ files := base.FilterDotUnderscoreFiles(base.RelPaths(pkg.Internal.AllGoFiles))
+ base.Run(str.StringList(cfg.BuildToolexec, base.Tool("fix"), files))
}
}
diff --git a/libgo/go/cmd/go/fmt.go b/libgo/go/cmd/go/internal/fmtcmd/fmt.go
similarity index 61%
rename from libgo/go/cmd/go/fmt.go
rename to libgo/go/cmd/go/internal/fmtcmd/fmt.go
index 4ed7722..0563a04 100644
--- a/libgo/go/cmd/go/fmt.go
+++ b/libgo/go/cmd/go/internal/fmtcmd/fmt.go
@@ -2,24 +2,30 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package fmtcmd implements the ``go fmt'' command.
+package fmtcmd
import (
"os"
"path/filepath"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
)
func init() {
- addBuildFlagsNX(cmdFmt)
+ base.AddBuildFlagsNX(&CmdFmt.Flag)
}
-var cmdFmt = &Command{
+var CmdFmt = &base.Command{
Run: runFmt,
UsageLine: "fmt [-n] [-x] [packages]",
Short: "run gofmt on package sources",
Long: `
Fmt runs the command 'gofmt -l -w' on the packages named
-by the import paths. It prints the names of the files that are modified.
+by the import paths. It prints the names of the files that are modified.
For more about gofmt, see 'go doc cmd/gofmt'.
For more about specifying packages, see 'go help packages'.
@@ -33,28 +39,29 @@ See also: go fix, go vet.
`,
}
-func runFmt(cmd *Command, args []string) {
+func runFmt(cmd *base.Command, args []string) {
gofmt := gofmtPath()
- for _, pkg := range packages(args) {
+ for _, pkg := range load.Packages(args) {
// Use pkg.gofiles instead of pkg.Dir so that
// the command only applies to this package,
// not to packages in subdirectories.
- run(stringList(gofmt, "-l", "-w", relPaths(pkg.allgofiles)))
+ files := base.FilterDotUnderscoreFiles(base.RelPaths(pkg.Internal.AllGoFiles))
+ base.Run(str.StringList(gofmt, "-l", "-w", files))
}
}
func gofmtPath() string {
gofmt := "gofmt"
- if toolIsWindows {
- gofmt += toolWindowsExtension
+ if base.ToolIsWindows {
+ gofmt += base.ToolWindowsExtension
}
- gofmtPath := filepath.Join(gobin, gofmt)
+ gofmtPath := filepath.Join(cfg.GOBIN, gofmt)
if _, err := os.Stat(gofmtPath); err == nil {
return gofmtPath
}
- gofmtPath = filepath.Join(goroot, "bin", gofmt)
+ gofmtPath = filepath.Join(cfg.GOROOT, "bin", gofmt)
if _, err := os.Stat(gofmtPath); err == nil {
return gofmtPath
}
diff --git a/libgo/go/cmd/go/generate.go b/libgo/go/cmd/go/internal/generate/generate.go
similarity index 91%
rename from libgo/go/cmd/go/generate.go
rename to libgo/go/cmd/go/internal/generate/generate.go
index 2d92a0c..d47c9b7 100644
--- a/libgo/go/cmd/go/generate.go
+++ b/libgo/go/cmd/go/internal/generate/generate.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package generate implements the ``go generate'' command.
+package generate
import (
"bufio"
@@ -16,9 +17,14 @@ import (
"regexp"
"strconv"
"strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/work"
)
-var cmdGenerate = &Command{
+var CmdGenerate = &base.Command{
Run: runGenerate,
UsageLine: "generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]",
Short: "generate Go files by processing source",
@@ -74,7 +80,7 @@ line.
As a last step before running the command, any invocations of any
environment variables with alphanumeric names, such as $GOFILE or
$HOME, are expanded throughout the command line. The syntax for
-variable expansion is $NAME on all operating systems. Due to the
+variable expansion is $NAME on all operating systems. Due to the
order of evaluation, variables are expanded even inside quoted
strings. If the variable NAME is not set, $NAME expands to the
empty string.
@@ -131,12 +137,12 @@ var (
)
func init() {
- addBuildFlags(cmdGenerate)
- cmdGenerate.Flag.StringVar(&generateRunFlag, "run", "", "")
+ work.AddBuildFlags(CmdGenerate)
+ CmdGenerate.Flag.StringVar(&generateRunFlag, "run", "", "")
}
-func runGenerate(cmd *Command, args []string) {
- ignoreImports = true
+func runGenerate(cmd *base.Command, args []string) {
+ load.IgnoreImports = true
if generateRunFlag != "" {
var err error
@@ -146,8 +152,8 @@ func runGenerate(cmd *Command, args []string) {
}
}
// Even if the arguments are .go files, this loop suffices.
- for _, pkg := range packages(args) {
- for _, file := range pkg.gofiles {
+ for _, pkg := range load.Packages(args) {
+ for _, file := range pkg.Internal.GoFiles {
if !generate(pkg.Name, file) {
break
}
@@ -195,13 +201,13 @@ func (g *Generator) run() (ok bool) {
if e != stop {
panic(e)
}
- setExitStatus(1)
+ base.SetExitStatus(1)
}
}()
g.dir, g.file = filepath.Split(g.path)
g.dir = filepath.Clean(g.dir) // No final separator please.
- if buildV {
- fmt.Fprintf(os.Stderr, "%s\n", shortPath(g.path))
+ if cfg.BuildV {
+ fmt.Fprintf(os.Stderr, "%s\n", base.ShortPath(g.path))
}
// Scan for lines that start "//go:generate".
@@ -255,16 +261,16 @@ func (g *Generator) run() (ok bool) {
continue
}
// Run the command line.
- if buildN || buildX {
+ if cfg.BuildN || cfg.BuildX {
fmt.Fprintf(os.Stderr, "%s\n", strings.Join(words, " "))
}
- if buildN {
+ if cfg.BuildN {
continue
}
g.exec(words)
}
if err != nil && err != io.EOF {
- g.errorf("error reading %s: %s", shortPath(g.path), err)
+ g.errorf("error reading %s: %s", base.ShortPath(g.path), err)
}
return true
}
@@ -277,8 +283,8 @@ func isGoGenerate(buf []byte) bool {
// single go:generate command.
func (g *Generator) setEnv() {
g.env = []string{
- "GOARCH=" + buildContext.GOARCH,
- "GOOS=" + buildContext.GOOS,
+ "GOARCH=" + cfg.BuildContext.GOARCH,
+ "GOOS=" + cfg.BuildContext.GOOS,
"GOFILE=" + g.file,
"GOLINE=" + strconv.Itoa(g.lineNum),
"GOPACKAGE=" + g.pkg,
@@ -354,7 +360,7 @@ var stop = fmt.Errorf("error in generation")
// It then exits the program (with exit status 1) because generation stops
// at the first error.
func (g *Generator) errorf(format string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, "%s:%d: %s\n", shortPath(g.path), g.lineNum,
+ fmt.Fprintf(os.Stderr, "%s:%d: %s\n", base.ShortPath(g.path), g.lineNum,
fmt.Sprintf(format, args...))
panic(stop)
}
@@ -393,7 +399,7 @@ func (g *Generator) exec(words []string) {
cmd.Stderr = os.Stderr
// Run the command in the package directory.
cmd.Dir = g.dir
- cmd.Env = mergeEnvLists(g.env, origEnv)
+ cmd.Env = base.MergeEnvLists(g.env, cfg.OrigEnv)
err := cmd.Run()
if err != nil {
g.errorf("running %q: %s", words[0], err)
diff --git a/libgo/go/cmd/go/generate_test.go b/libgo/go/cmd/go/internal/generate/generate_test.go
similarity index 98%
rename from libgo/go/cmd/go/generate_test.go
rename to libgo/go/cmd/go/internal/generate/generate_test.go
index dd116e6..defc153 100644
--- a/libgo/go/cmd/go/generate_test.go
+++ b/libgo/go/cmd/go/internal/generate/generate_test.go
@@ -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 main
+package generate
import (
"reflect"
diff --git a/libgo/go/cmd/go/discovery.go b/libgo/go/cmd/go/internal/get/discovery.go
similarity index 89%
rename from libgo/go/cmd/go/discovery.go
rename to libgo/go/cmd/go/internal/get/discovery.go
index b60eaef..b2918db 100644
--- a/libgo/go/cmd/go/discovery.go
+++ b/libgo/go/cmd/go/internal/get/discovery.go
@@ -2,14 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !cmd_go_bootstrap
-
-// This code is compiled into the real 'go' binary, but it is not
-// compiled into the binary that is built during all.bash, so as
-// to avoid needing to build net (and thus use cgo) during the
-// bootstrap process.
-
-package main
+package get
import (
"encoding/xml"
diff --git a/libgo/go/cmd/go/get.go b/libgo/go/cmd/go/internal/get/get.go
similarity index 75%
rename from libgo/go/cmd/go/get.go
rename to libgo/go/cmd/go/internal/get/get.go
index 6fb4235..5503211 100644
--- a/libgo/go/cmd/go/get.go
+++ b/libgo/go/cmd/go/internal/get/get.go
@@ -2,20 +2,26 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package get implements the ``go get'' command.
+package get
import (
"fmt"
"go/build"
"os"
"path/filepath"
- "regexp"
"runtime"
- "strconv"
"strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
+ "cmd/go/internal/web"
+ "cmd/go/internal/work"
)
-var cmdGet = &Command{
+var CmdGet = &base.Command{
UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [build flags] [packages]",
Short: "download and install packages and dependencies",
Long: `
@@ -40,7 +46,7 @@ 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
+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.
@@ -54,8 +60,8 @@ 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 most recent version of the package.
+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.
@@ -71,21 +77,24 @@ See also: go build, go install, go clean.
`,
}
-var getD = cmdGet.Flag.Bool("d", false, "")
-var getF = cmdGet.Flag.Bool("f", false, "")
-var getT = cmdGet.Flag.Bool("t", false, "")
-var getU = cmdGet.Flag.Bool("u", false, "")
-var getFix = cmdGet.Flag.Bool("fix", false, "")
-var getInsecure = cmdGet.Flag.Bool("insecure", false, "")
+var getD = CmdGet.Flag.Bool("d", false, "")
+var getF = CmdGet.Flag.Bool("f", false, "")
+var getT = CmdGet.Flag.Bool("t", false, "")
+var getU = CmdGet.Flag.Bool("u", false, "")
+var getFix = CmdGet.Flag.Bool("fix", false, "")
+var getInsecure = CmdGet.Flag.Bool("insecure", false, "")
func init() {
- addBuildFlags(cmdGet)
- cmdGet.Run = runGet // break init loop
+ work.AddBuildFlags(CmdGet)
+ CmdGet.Run = runGet // break init loop
}
-func runGet(cmd *Command, args []string) {
+func runGet(cmd *base.Command, args []string) {
+ work.InstrumentInit()
+ work.BuildModeInit()
+
if *getF && !*getU {
- fatalf("go get: cannot use -f flag without -u")
+ base.Fatalf("go get: cannot use -f flag without -u")
}
// Disable any prompting for passwords by Git.
@@ -115,17 +124,17 @@ func runGet(cmd *Command, args []string) {
os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
}
- // Phase 1. Download/update.
- var stk importStack
+ // Phase 1. Download/update.
+ var stk load.ImportStack
mode := 0
if *getT {
- mode |= getTestDeps
+ mode |= load.GetTestDeps
}
args = downloadPaths(args)
for _, arg := range args {
download(arg, nil, &stk, mode)
}
- exitIfErrors()
+ base.ExitIfErrors()
// Phase 2. Rescan packages and re-evaluate args list.
@@ -134,22 +143,18 @@ func runGet(cmd *Command, args []string) {
// the information will be recomputed. Instead of keeping
// track of the reverse dependency information, evict
// everything.
- for name := range packageCache {
- delete(packageCache, name)
- }
+ 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.
- for name := range cmdCache {
- delete(cmdCache, name)
- }
+ load.ClearCmdCache()
- args = importPaths(args)
- packagesForBuild(args)
+ args = load.ImportPaths(args)
+ load.PackagesForBuild(args)
- // Phase 3. Install.
+ // Phase 3. Install.
if *getD {
// Download only.
// Check delayed until now so that importPaths
@@ -157,7 +162,7 @@ func runGet(cmd *Command, args []string) {
return
}
- installPackages(args, true)
+ work.InstallPackages(args, true)
}
// downloadPaths prepares the list of paths to pass to download.
@@ -166,7 +171,7 @@ func runGet(cmd *Command, args []string) {
// in the hope that we can figure out the repository from the
// initial ...-free prefix.
func downloadPaths(args []string) []string {
- args = importPathsNoDotExpansion(args)
+ args = load.ImportPathsNoDotExpansion(args)
var out []string
for _, a := range args {
if strings.Contains(a, "...") {
@@ -175,9 +180,9 @@ func downloadPaths(args []string) []string {
// warnings. They will be printed by the
// eventual call to importPaths instead.
if build.IsLocalImport(a) {
- expand = matchPackagesInFS(a)
+ expand = load.MatchPackagesInFS(a)
} else {
- expand = matchPackages(a)
+ expand = load.MatchPackages(a)
}
if len(expand) > 0 {
out = append(out, expand...)
@@ -204,21 +209,21 @@ var downloadRootCache = map[string]bool{}
// download runs the download half of the get command
// for the package named by the argument.
-func download(arg string, parent *Package, stk *importStack, mode int) {
- if mode&useVendor != 0 {
+func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) {
+ if mode&load.UseVendor != 0 {
// Caller is responsible for expanding vendor paths.
panic("internal error: download mode has useVendor set")
}
- load := func(path string, mode int) *Package {
+ load1 := func(path string, mode int) *load.Package {
if parent == nil {
- return loadPackage(path, stk)
+ return load.LoadPackage(path, stk)
}
- return loadImport(path, parent.Dir, parent, stk, nil, mode)
+ return load.LoadImport(path, parent.Dir, parent, stk, nil, mode)
}
- p := load(arg, mode)
- if p.Error != nil && p.Error.hard {
- errorf("%s", p.Error)
+ p := load1(arg, mode)
+ if p.Error != nil && p.Error.Hard {
+ base.Errorf("%s", p.Error)
return
}
@@ -240,26 +245,26 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
// Only process each package once.
// (Unless we're fetching test dependencies for this package,
// in which case we want to process it again.)
- if downloadCache[arg] && mode&getTestDeps == 0 {
+ if downloadCache[arg] && mode&load.GetTestDeps == 0 {
return
}
downloadCache[arg] = true
- pkgs := []*Package{p}
+ pkgs := []*load.Package{p}
wildcardOkay := len(*stk) == 0
isWildcard := false
// Download if the package is missing, or update if we're using -u.
if p.Dir == "" || *getU {
// The actual download.
- stk.push(arg)
+ stk.Push(arg)
err := downloadPackage(p)
if err != nil {
- errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()})
- stk.pop()
+ base.Errorf("%s", &load.PackageError{ImportStack: stk.Copy(), Err: err.Error()})
+ stk.Pop()
return
}
- stk.pop()
+ stk.Pop()
args := []string{arg}
// If the argument has a wildcard in it, re-evaluate the wildcard.
@@ -267,31 +272,25 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
// for p has been replaced in the package cache.
if wildcardOkay && strings.Contains(arg, "...") {
if build.IsLocalImport(arg) {
- args = matchPackagesInFS(arg)
+ args = load.MatchPackagesInFS(arg)
} else {
- args = matchPackages(arg)
+ args = load.MatchPackages(arg)
}
isWildcard = true
}
// Clear all relevant package cache entries before
// doing any new loads.
- for _, arg := range args {
- p := packageCache[arg]
- if p != nil {
- delete(packageCache, p.Dir)
- delete(packageCache, p.ImportPath)
- }
- }
+ load.ClearPackageCachePartial(args)
pkgs = pkgs[:0]
for _, arg := range args {
// Note: load calls loadPackage or loadImport,
// which push arg onto stk already.
// Do not push here too, or else stk will say arg imports arg.
- p := load(arg, mode)
+ p := load1(arg, mode)
if p.Error != nil {
- errorf("%s", p.Error)
+ base.Errorf("%s", p.Error)
continue
}
pkgs = append(pkgs, p)
@@ -302,12 +301,13 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
// due to wildcard expansion.
for _, p := range pkgs {
if *getFix {
- run(buildToolExec, stringList(tool("fix"), relPaths(p.allgofiles)))
+ files := base.FilterDotUnderscoreFiles(base.RelPaths(p.Internal.AllGoFiles))
+ base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), files))
// The imports might have changed, so reload again.
- p = reloadPackage(arg, stk)
+ p = load.ReloadPackage(arg, stk)
if p.Error != nil {
- errorf("%s", p.Error)
+ base.Errorf("%s", p.Error)
return
}
}
@@ -315,16 +315,16 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
if isWildcard {
// Report both the real package and the
// wildcard in any error message.
- stk.push(p.ImportPath)
+ stk.Push(p.ImportPath)
}
// Process dependencies, now that we know what they are.
imports := p.Imports
- if mode&getTestDeps != 0 {
+ if mode&load.GetTestDeps != 0 {
// Process test dependencies when -t is specified.
// (But don't get test dependencies for test dependencies:
// we always pass mode 0 to the recursive calls below.)
- imports = stringList(imports, p.TestImports, p.XTestImports)
+ imports = str.StringList(imports, p.TestImports, p.XTestImports)
}
for i, path := range imports {
if path == "C" {
@@ -332,19 +332,19 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
}
// Fail fast on import naming full vendor path.
// Otherwise expand path as needed for test imports.
- // Note that p.Imports can have additional entries beyond p.build.Imports.
+ // Note that p.Imports can have additional entries beyond p.Internal.Build.Imports.
orig := path
- if i < len(p.build.Imports) {
- orig = p.build.Imports[i]
+ if i < len(p.Internal.Build.Imports) {
+ orig = p.Internal.Build.Imports[i]
}
- if j, ok := findVendor(orig); ok {
- stk.push(path)
- err := &PackageError{
- ImportStack: stk.copy(),
+ if j, ok := load.FindVendor(orig); ok {
+ stk.Push(path)
+ err := &load.PackageError{
+ ImportStack: stk.Copy(),
Err: "must be imported as " + path[j+len("vendor/"):],
}
- stk.pop()
- errorf("%s", err)
+ stk.Pop()
+ base.Errorf("%s", err)
continue
}
// If this is a test import, apply vendor lookup now.
@@ -352,34 +352,34 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
// download does caching based on the value of path,
// so it must be the fully qualified path already.
if i >= len(p.Imports) {
- path = vendoredImportPath(p, path)
+ path = load.VendoredImportPath(p, path)
}
download(path, p, stk, 0)
}
if isWildcard {
- stk.pop()
+ stk.Pop()
}
}
}
// downloadPackage runs the create or download command
// to make the first copy of or update a copy of the given package.
-func downloadPackage(p *Package) error {
+func downloadPackage(p *load.Package) error {
var (
vcs *vcsCmd
repo, rootPath string
err error
)
- security := secure
+ security := web.Secure
if *getInsecure {
- security = insecure
+ security = web.Insecure
}
- if p.build.SrcRoot != "" {
+ if p.Internal.Build.SrcRoot != "" {
// Directory exists. Look for checkout along path to src.
- vcs, rootPath, err = vcsFromDir(p.Dir, p.build.SrcRoot)
+ vcs, rootPath, err = vcsFromDir(p.Dir, p.Internal.Build.SrcRoot)
if err != nil {
return err
}
@@ -387,7 +387,7 @@ func downloadPackage(p *Package) error {
// Double-check where it came from.
if *getU && vcs.remoteRepo != nil {
- dir := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
+ dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
remote, err := vcs.remoteRepo(vcs, dir)
if err != nil {
return err
@@ -421,31 +421,31 @@ func downloadPackage(p *Package) error {
return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
}
- if p.build.SrcRoot == "" {
+ if p.Internal.Build.SrcRoot == "" {
// Package not found. Put in first directory of $GOPATH.
- list := filepath.SplitList(buildContext.GOPATH)
+ list := filepath.SplitList(cfg.BuildContext.GOPATH)
if len(list) == 0 {
return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'")
}
// Guard against people setting GOPATH=$GOROOT.
- if filepath.Clean(list[0]) == filepath.Clean(goroot) {
+ if filepath.Clean(list[0]) == filepath.Clean(cfg.GOROOT) {
return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
}
if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
return fmt.Errorf("cannot download, %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
}
- p.build.Root = list[0]
- p.build.SrcRoot = filepath.Join(list[0], "src")
- p.build.PkgRoot = filepath.Join(list[0], "pkg")
+ p.Internal.Build.Root = list[0]
+ p.Internal.Build.SrcRoot = filepath.Join(list[0], "src")
+ p.Internal.Build.PkgRoot = filepath.Join(list[0], "pkg")
}
- root := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
+ root := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath))
// If we've considered this repository already, don't do it again.
if downloadRootCache[root] {
return nil
}
downloadRootCache[root] = true
- if buildV {
+ if cfg.BuildV {
fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath)
}
@@ -464,7 +464,7 @@ func downloadPackage(p *Package) error {
return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
}
- _, err := os.Stat(p.build.Root)
+ _, err := os.Stat(p.Internal.Build.Root)
gopathExisted := err == nil
// Some version control tools require the parent of the target to exist.
@@ -472,8 +472,8 @@ func downloadPackage(p *Package) error {
if err = os.MkdirAll(parent, 0777); err != nil {
return err
}
- if buildV && !gopathExisted && p.build.Root == buildContext.GOPATH {
- fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.build.Root)
+ if cfg.BuildV && !gopathExisted && p.Internal.Build.Root == cfg.BuildContext.GOPATH {
+ fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.Internal.Build.Root)
}
if err = vcs.create(root, repo); err != nil {
@@ -486,7 +486,7 @@ func downloadPackage(p *Package) error {
}
}
- if buildN {
+ if cfg.BuildN {
// Do not show tag sync in -n; it's noise more than anything,
// and since we're not running commands, no tag will be found.
// But avoid printing nothing.
@@ -510,14 +510,6 @@ func downloadPackage(p *Package) error {
return nil
}
-// goTag matches go release tags such as go1 and go1.2.3.
-// The numbers involved must be small (at most 4 digits),
-// have no unnecessary leading zeros, and the version cannot
-// end in .0 - it is go1, not go1.0 or go1.0.0.
-var goTag = regexp.MustCompile(
- `^go((0|[1-9][0-9]{0,3})\.)*([1-9][0-9]{0,3})$`,
-)
-
// selectTag returns the closest matching tag for a given version.
// Closest means the latest one that is not after the current release.
// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.
@@ -525,7 +517,7 @@ var goTag = regexp.MustCompile(
// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".
//
// NOTE(rsc): Eventually we will need to decide on some logic here.
-// For now, there is only "go1". This matches the docs in go help get.
+// For now, there is only "go1". This matches the docs in go help get.
func selectTag(goVersion string, tags []string) (match string) {
for _, t := range tags {
if t == "go1" {
@@ -533,56 +525,4 @@ func selectTag(goVersion string, tags []string) (match string) {
}
}
return ""
-
- /*
- if goTag.MatchString(goVersion) {
- v := goVersion
- for _, t := range tags {
- if !goTag.MatchString(t) {
- continue
- }
- if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 {
- match = t
- }
- }
- }
-
- return match
- */
-}
-
-// cmpGoVersion returns -1, 0, +1 reporting whether
-// x < y, x == y, or x > y.
-func cmpGoVersion(x, y string) int {
- // Malformed strings compare less than well-formed strings.
- if !goTag.MatchString(x) {
- return -1
- }
- if !goTag.MatchString(y) {
- return +1
- }
-
- // Compare numbers in sequence.
- xx := strings.Split(x[len("go"):], ".")
- yy := strings.Split(y[len("go"):], ".")
-
- for i := 0; i < len(xx) && i < len(yy); i++ {
- // The Atoi are guaranteed to succeed
- // because the versions match goTag.
- xi, _ := strconv.Atoi(xx[i])
- yi, _ := strconv.Atoi(yy[i])
- if xi < yi {
- return -1
- } else if xi > yi {
- return +1
- }
- }
-
- if len(xx) < len(yy) {
- return -1
- }
- if len(xx) > len(yy) {
- return +1
- }
- return 0
}
diff --git a/libgo/go/cmd/go/internal/get/pkg_test.go b/libgo/go/cmd/go/internal/get/pkg_test.go
new file mode 100644
index 0000000..b8937a5
--- /dev/null
+++ b/libgo/go/cmd/go/internal/get/pkg_test.go
@@ -0,0 +1,83 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package get
+
+import (
+ "cmd/go/internal/str"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+var foldDupTests = []struct {
+ list []string
+ f1, f2 string
+}{
+ {str.StringList("math/rand", "math/big"), "", ""},
+ {str.StringList("math", "strings"), "", ""},
+ {str.StringList("strings"), "", ""},
+ {str.StringList("strings", "strings"), "strings", "strings"},
+ {str.StringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"},
+}
+
+func TestFoldDup(t *testing.T) {
+ for _, tt := range foldDupTests {
+ f1, f2 := str.FoldDup(tt.list)
+ if f1 != tt.f1 || f2 != tt.f2 {
+ t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2)
+ }
+ }
+}
+
+var parseMetaGoImportsTests = []struct {
+ in string
+ out []metaImport
+}{
+ {
+ ``,
+ []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+ },
+ {
+ `
+ `,
+ []metaImport{
+ {"foo/bar", "git", "https://github.com/rsc/foo/bar"},
+ {"baz/quux", "git", "http://github.com/rsc/baz/quux"},
+ },
+ },
+ {
+ `
+
+ `,
+ []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+ },
+ {
+ `
+ `,
+ []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+ },
+ {
+ ``,
+ []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+ },
+ {
+ // XML doesn't like .
+ `
Page Not FoundDRAFT
`,
+ []metaImport{{"chitin.io/chitin", "git", "https://github.com/chitin-io/chitin"}},
+ },
+}
+
+func TestParseMetaGoImports(t *testing.T) {
+ for i, tt := range parseMetaGoImportsTests {
+ out, err := parseMetaGoImports(strings.NewReader(tt.in))
+ if err != nil {
+ t.Errorf("test#%d: %v", i, err)
+ continue
+ }
+ if !reflect.DeepEqual(out, tt.out) {
+ t.Errorf("test#%d:\n\thave %q\n\twant %q", i, out, tt.out)
+ }
+ }
+}
diff --git a/libgo/go/cmd/go/tag_test.go b/libgo/go/cmd/go/internal/get/tag_test.go
similarity index 99%
rename from libgo/go/cmd/go/tag_test.go
rename to libgo/go/cmd/go/internal/get/tag_test.go
index 6649bd6..9a25dfa 100644
--- a/libgo/go/cmd/go/tag_test.go
+++ b/libgo/go/cmd/go/internal/get/tag_test.go
@@ -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 main
+package get
import "testing"
diff --git a/libgo/go/cmd/go/vcs.go b/libgo/go/cmd/go/internal/get/vcs.go
similarity index 94%
rename from libgo/go/cmd/go/vcs.go
rename to libgo/go/cmd/go/internal/get/vcs.go
index fcdce22..71d0b51 100644
--- a/libgo/go/cmd/go/vcs.go
+++ b/libgo/go/cmd/go/internal/get/vcs.go
@@ -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 main
+package get
import (
"bytes"
@@ -18,6 +18,10 @@ import (
"regexp"
"strings"
"sync"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/web"
)
// A vcsCmd describes how to use a version control system
@@ -298,15 +302,20 @@ func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error
out := string(outb)
// Expect:
- // ...
- // Repository Root:
- // ...
-
- i := strings.Index(out, "\nRepository Root: ")
+ //
+ // ...
+ // URL:
+ // ...
+ //
+ // Note that we're not using the Repository Root line,
+ // because svn allows checking out subtrees.
+ // The URL will be the URL of the subtree (what we used with 'svn co')
+ // while the Repository Root may be a much higher parent.
+ i := strings.Index(out, "\nURL: ")
if i < 0 {
return "", fmt.Errorf("unable to parse output of svn info")
}
- out = out[i+len("\nRepository Root: "):]
+ out = out[i+len("\nURL: "):]
i = strings.Index(out, "\n")
if i < 0 {
return "", fmt.Errorf("unable to parse output of svn info")
@@ -320,7 +329,7 @@ func (v *vcsCmd) String() string {
}
// run runs the command line cmd in the given directory.
-// keyval is a list of key, value pairs. run expands
+// keyval is a list of key, value pairs. run expands
// instances of {key} in cmd into value, but only after
// splitting cmd into individual arguments.
// If an error occurs, run prints the command line and the
@@ -372,8 +381,8 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
cmd := exec.Command(v.cmd, args...)
cmd.Dir = dir
- cmd.Env = envForDir(cmd.Dir, os.Environ())
- if buildX {
+ 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, " "))
}
@@ -383,7 +392,7 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
err = cmd.Run()
out := buf.Bytes()
if err != nil {
- if verbose || buildV {
+ if verbose || cfg.BuildV {
fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " "))
os.Stderr.Write(out)
}
@@ -535,19 +544,9 @@ type repoRoot struct {
var httpPrefixRE = regexp.MustCompile(`^https?:`)
-// securityMode specifies whether a function should make network
-// calls using insecure transports (eg, plain text HTTP).
-// The zero value is "secure".
-type securityMode int
-
-const (
- secure securityMode = iota
- insecure
-)
-
// repoRootForImportPath analyzes importPath to determine the
// version control system, and code repository to use.
-func repoRootForImportPath(importPath string, security securityMode) (*repoRoot, error) {
+func repoRootForImportPath(importPath string, security web.SecurityMode) (*repoRoot, error) {
rr, err := repoRootFromVCSPaths(importPath, "", security, vcsPaths)
if err == errUnknownSite {
// If there are wildcards, look up the thing before the wildcard,
@@ -583,7 +582,7 @@ var errUnknownSite = errors.New("dynamic lookup required to find mapping")
// repoRootFromVCSPaths attempts to map importPath to a repoRoot
// using the mappings defined in vcsPaths.
// If scheme is non-empty, that scheme is forced.
-func repoRootFromVCSPaths(importPath, scheme string, security securityMode, vcsPaths []*vcsPath) (*repoRoot, error) {
+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 {
@@ -633,7 +632,7 @@ func repoRootFromVCSPaths(importPath, scheme string, security securityMode, vcsP
match["repo"] = scheme + "://" + match["repo"]
} else {
for _, scheme := range vcs.scheme {
- if security == secure && !vcs.isSecureScheme(scheme) {
+ if security == web.Secure && !vcs.isSecureScheme(scheme) {
continue
}
if vcs.ping(scheme, match["repo"]) == nil {
@@ -657,7 +656,7 @@ func repoRootFromVCSPaths(importPath, scheme string, security securityMode, vcsP
// statically known by repoRootForImportPathStatic.
//
// This handles custom import paths like "name.tld/pkg/foo" or just "name.tld".
-func repoRootForImportDynamic(importPath string, security securityMode) (*repoRoot, error) {
+func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*repoRoot, error) {
slash := strings.Index(importPath, "/")
if slash < 0 {
slash = len(importPath)
@@ -666,10 +665,10 @@ func repoRootForImportDynamic(importPath string, security securityMode) (*repoRo
if !strings.Contains(host, ".") {
return nil, errors.New("import path does not begin with hostname")
}
- urlStr, body, err := httpsOrHTTP(importPath, security)
+ urlStr, body, err := web.GetMaybeInsecure(importPath, security)
if err != nil {
msg := "https fetch: %v"
- if security == insecure {
+ if security == web.Insecure {
msg = "http/" + msg
}
return nil, fmt.Errorf(msg, err)
@@ -687,17 +686,17 @@ func repoRootForImportDynamic(importPath string, security securityMode) (*repoRo
}
return nil, fmt.Errorf("parse %s: no go-import meta tags (%s)", urlStr, err)
}
- if buildV {
+ if cfg.BuildV {
log.Printf("get %q: found meta tag %#v at %s", importPath, mmi, urlStr)
}
// If the import was "uni.edu/bob/project", which said the
// prefix was "uni.edu" and the RepoRoot was "evilroot.com",
// make sure we don't trust Bob and check out evilroot.com to
// "uni.edu" yet (possibly overwriting/preempting another
- // non-evil student). Instead, first verify the root and see
+ // non-evil student). Instead, first verify the root and see
// if it matches Bob's claim.
if mmi.Prefix != importPath {
- if buildV {
+ if cfg.BuildV {
log.Printf("get %q: verifying non-authoritative meta tag", importPath)
}
urlStr0 := urlStr
@@ -741,7 +740,7 @@ var (
// 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, security securityMode) (urlStr string, imports []metaImport, err error) {
+func metaImportsForPrefix(importPrefix string, security web.SecurityMode) (urlStr string, imports []metaImport, err error) {
setCache := func(res fetchResult) (fetchResult, error) {
fetchCacheMu.Lock()
defer fetchCacheMu.Unlock()
@@ -757,7 +756,7 @@ func metaImportsForPrefix(importPrefix string, security securityMode) (urlStr st
}
fetchCacheMu.Unlock()
- urlStr, body, err := httpsOrHTTP(importPrefix, security)
+ urlStr, body, err := web.GetMaybeInsecure(importPrefix, security)
if err != nil {
return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("fetch %s: %v", urlStr, err)})
}
@@ -857,7 +856,7 @@ var vcsPaths = []*vcsPath{
// Github
{
prefix: "github.com/",
- re: `^(?Pgithub\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
+ re: `^(?Pgithub\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[\p{L}0-9_.\-]+)*$`,
vcs: "git",
repo: "https://{root}",
check: noVCSSuffix,
@@ -954,10 +953,10 @@ func bitbucketVCS(match map[string]string) error {
var resp struct {
SCM string `json:"scm"`
}
- url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}")
- data, err := httpGET(url)
+ url := expand(match, "https://api.bitbucket.org/2.0/repositories/{bitname}?fields=scm")
+ data, err := web.Get(url)
if err != nil {
- if httpErr, ok := err.(*httpError); ok && httpErr.statusCode == 403 {
+ if httpErr, ok := err.(*web.HTTPError); ok && httpErr.StatusCode == 403 {
// this may be a private repository. If so, attempt to determine which
// VCS it uses. See issue 5375.
root := match["root"]
@@ -997,7 +996,7 @@ func launchpadVCS(match map[string]string) error {
if match["project"] == "" || match["series"] == "" {
return nil
}
- _, err := httpGET(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format"))
+ _, err := web.Get(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format"))
if err != nil {
match["root"] = expand(match, "launchpad.net/{project}")
match["repo"] = expand(match, "https://{root}")
diff --git a/libgo/go/cmd/go/vcs_test.go b/libgo/go/cmd/go/internal/get/vcs_test.go
similarity index 94%
rename from libgo/go/cmd/go/vcs_test.go
rename to libgo/go/cmd/go/internal/get/vcs_test.go
index c73f5d0..62d352a 100644
--- a/libgo/go/cmd/go/vcs_test.go
+++ b/libgo/go/cmd/go/internal/get/vcs_test.go
@@ -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 main
+package get
import (
"errors"
@@ -12,6 +12,8 @@ import (
"path"
"path/filepath"
"testing"
+
+ "cmd/go/internal/web"
)
// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath.
@@ -30,6 +32,14 @@ func TestRepoRootForImportPath(t *testing.T) {
repo: "https://github.com/golang/groupcache",
},
},
+ // Unicode letters in directories (issue 18660).
+ {
+ "github.com/user/unicode/иÑпÑÑание",
+ &repoRoot{
+ vcs: vcsGit,
+ repo: "https://github.com/user/unicode",
+ },
+ },
// IBM DevOps Services tests
{
"hub.jazz.net/git/user1/pkgname",
@@ -147,21 +157,21 @@ func TestRepoRootForImportPath(t *testing.T) {
}
for _, test := range tests {
- got, err := repoRootForImportPath(test.path, secure)
+ got, err := repoRootForImportPath(test.path, web.Secure)
want := test.want
if want == nil {
if err == nil {
- t.Errorf("RepoRootForImport(%q): Error expected but not received", test.path)
+ t.Errorf("repoRootForImportPath(%q): Error expected but not received", test.path)
}
continue
}
if err != nil {
- t.Errorf("RepoRootForImport(%q): %v", test.path, err)
+ t.Errorf("repoRootForImportPath(%q): %v", test.path, err)
continue
}
if got.vcs.name != want.vcs.name || got.repo != want.repo {
- t.Errorf("RepoRootForImport(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.repo, want.vcs, want.repo)
+ t.Errorf("repoRootForImportPath(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.repo, want.vcs, want.repo)
}
}
}
diff --git a/libgo/go/cmd/go/internal/help/help.go b/libgo/go/cmd/go/internal/help/help.go
new file mode 100644
index 0000000..b4c5217
--- /dev/null
+++ b/libgo/go/cmd/go/internal/help/help.go
@@ -0,0 +1,178 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package help implements the ``go help'' command.
+package help
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+ "text/template"
+ "unicode"
+ "unicode/utf8"
+
+ "cmd/go/internal/base"
+)
+
+// Help implements the 'help' command.
+func Help(args []string) {
+ if len(args) == 0 {
+ PrintUsage(os.Stdout)
+ // not exit 2: succeeded at 'go help'.
+ return
+ }
+ if len(args) != 1 {
+ fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
+ os.Exit(2) // failed at 'go help'
+ }
+
+ arg := args[0]
+
+ // 'go help documentation' generates doc.go.
+ if arg == "documentation" {
+ fmt.Println("// Copyright 2011 The Go Authors. All rights reserved.")
+ fmt.Println("// Use of this source code is governed by a BSD-style")
+ fmt.Println("// license that can be found in the LICENSE file.")
+ fmt.Println()
+ fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.")
+ fmt.Println("// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.")
+ fmt.Println()
+ buf := new(bytes.Buffer)
+ PrintUsage(buf)
+ usage := &base.Command{Long: buf.String()}
+ tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, append([]*base.Command{usage}, base.Commands...))
+ fmt.Println("package main")
+ return
+ }
+
+ for _, cmd := range base.Commands {
+ if cmd.Name() == arg {
+ tmpl(os.Stdout, helpTemplate, cmd)
+ // not exit 2: succeeded at 'go help cmd'.
+ return
+ }
+ }
+
+ fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'go help'.\n", arg)
+ os.Exit(2) // failed at 'go help cmd'
+}
+
+var usageTemplate = `Go is a tool for managing Go source code.
+
+Usage:
+
+ go command [arguments]
+
+The commands are:
+{{range .}}{{if .Runnable}}
+ {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "go help [command]" for more information about a command.
+
+Additional help topics:
+{{range .}}{{if not .Runnable}}
+ {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
+
+Use "go help [topic]" for more information about that topic.
+
+`
+
+var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+`
+
+var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
+
+{{end}}{{if .Runnable}}Usage:
+
+ go {{.UsageLine}}
+
+{{end}}{{.Long | trim}}
+
+
+{{end}}`
+
+// commentWriter writes a Go comment to the underlying io.Writer,
+// using line comment form (//).
+type commentWriter struct {
+ W io.Writer
+ wroteSlashes bool // Wrote "//" at the beginning of the current line.
+}
+
+func (c *commentWriter) Write(p []byte) (int, error) {
+ var n int
+ for i, b := range p {
+ if !c.wroteSlashes {
+ s := "//"
+ if b != '\n' {
+ s = "// "
+ }
+ if _, err := io.WriteString(c.W, s); err != nil {
+ return n, err
+ }
+ c.wroteSlashes = true
+ }
+ n0, err := c.W.Write(p[i : i+1])
+ n += n0
+ if err != nil {
+ return n, err
+ }
+ if b == '\n' {
+ c.wroteSlashes = false
+ }
+ }
+ return len(p), nil
+}
+
+// An errWriter wraps a writer, recording whether a write error occurred.
+type errWriter struct {
+ w io.Writer
+ err error
+}
+
+func (w *errWriter) Write(b []byte) (int, error) {
+ n, err := w.w.Write(b)
+ if err != nil {
+ w.err = err
+ }
+ return n, err
+}
+
+// tmpl executes the given template text on data, writing the result to w.
+func tmpl(w io.Writer, text string, data interface{}) {
+ t := template.New("top")
+ t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
+ template.Must(t.Parse(text))
+ ew := &errWriter{w: w}
+ err := t.Execute(ew, data)
+ if ew.err != nil {
+ // I/O error writing. Ignore write on closed pipe.
+ if strings.Contains(ew.err.Error(), "pipe") {
+ os.Exit(1)
+ }
+ base.Fatalf("writing output: %v", ew.err)
+ }
+ if err != nil {
+ panic(err)
+ }
+}
+
+func capitalize(s string) string {
+ if s == "" {
+ return s
+ }
+ r, n := utf8.DecodeRuneInString(s)
+ return string(unicode.ToTitle(r)) + s[n:]
+}
+
+func PrintUsage(w io.Writer) {
+ bw := bufio.NewWriter(w)
+ tmpl(bw, usageTemplate, base.Commands)
+ bw.Flush()
+}
diff --git a/libgo/go/cmd/go/help.go b/libgo/go/cmd/go/internal/help/helpdoc.go
similarity index 90%
rename from libgo/go/cmd/go/help.go
rename to libgo/go/cmd/go/internal/help/helpdoc.go
index 6b7422c..516fff3 100644
--- a/libgo/go/cmd/go/help.go
+++ b/libgo/go/cmd/go/internal/help/helpdoc.go
@@ -2,31 +2,33 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+package help
-var helpC = &Command{
+import "cmd/go/internal/base"
+
+var HelpC = &base.Command{
UsageLine: "c",
Short: "calling between Go and C",
Long: `
There are two different ways to call between Go and C/C++ code.
-The first is the cgo tool, which is part of the Go distribution. For
+The first is the cgo tool, which is part of the Go distribution. For
information on how to use it see the cgo documentation (go doc cmd/cgo).
The second is the SWIG program, which is a general tool for
-interfacing between languages. For information on SWIG see
-http://swig.org/. When running go build, any file with a .swig
-extension will be passed to SWIG. Any file with a .swigcxx extension
+interfacing between languages. For information on SWIG see
+http://swig.org/. When running go build, any file with a .swig
+extension will be passed to SWIG. Any file with a .swigcxx extension
will be passed to SWIG with the -c++ option.
When either cgo or SWIG is used, go build will pass any .c, .m, .s,
or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++
-compiler. The CC or CXX environment variables may be set to determine
+compiler. The CC or CXX environment variables may be set to determine
the C or C++ compiler, respectively, to use.
`,
}
-var helpPackages = &Command{
+var HelpPackages = &base.Command{
UsageLine: "packages",
Short: "description of package lists",
Long: `
@@ -67,17 +69,28 @@ the Go repository.
An import path is a pattern if it includes one or more "..." wildcards,
each of which can match any string, including the empty string and
-strings containing slashes. Such a pattern expands to all package
+strings containing slashes. Such a pattern expands to all package
directories found in the GOPATH trees with names matching the
-patterns. As a special case, x/... matches x as well as x's subdirectories.
-For example, net/... expands to net and packages in its subdirectories.
+patterns.
+
+To make common patterns more convenient, there are two special cases.
+First, /... at the end of the pattern can match an empty string,
+so that net/... matches both net and packages in its subdirectories, like net/http.
+Second, any slash-separated pattern element containing a wildcard never
+participates in a match of the "vendor" element in the path of a vendored
+package, so that ./... does not match packages in subdirectories of
+./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
+Note, however, that a directory named vendor that itself contains code
+is not a vendored package: cmd/vendor would be a command named vendor,
+and the pattern cmd/... matches it.
+See golang.org/s/go15vendor for more about vendoring.
An import path can also name a package to be downloaded from
-a remote repository. Run 'go help importpath' for details.
+a remote repository. Run 'go help importpath' for details.
Every package in a program must have a unique import path.
By convention, this is arranged by starting each path with a
-unique prefix that belongs to you. For example, paths used
+unique prefix that belongs to you. For example, paths used
internally at Google all begin with 'google', and paths
denoting remote repositories begin with the path to the code,
such as 'github.com/user/repo'.
@@ -100,13 +113,13 @@ by the go tool, as are directories named "testdata".
`,
}
-var helpImportPath = &Command{
+var HelpImportPath = &base.Command{
UsageLine: "importpath",
Short: "import path syntax",
Long: `
An import path (see 'go help packages') denotes a package stored in the local
-file system. In general, an import path denotes either a standard package (such
+file system. In general, an import path denotes either a standard package (such
as "unicode/utf8") or a package found in one of the work spaces (For more
details see: 'go help gopath').
@@ -177,7 +190,7 @@ To declare the code location, an import path of the form
specifies the given repository, with or without the .vcs suffix,
using the named version control system, and then the path inside
-that repository. The supported version control systems are:
+that repository. The supported version control systems are:
Bazaar .bzr
Git .git
@@ -197,7 +210,7 @@ denotes the foo/bar directory of the Git repository at
example.org/repo or repo.git.
When a version control system supports multiple protocols,
-each is tried in turn when downloading. For example, a Git
+each is tried in turn when downloading. For example, a Git
download tries https://, then git+ssh://.
By default, downloads are restricted to known secure protocols
@@ -277,7 +290,7 @@ See https://golang.org/s/go14customimport for details.
`,
}
-var helpGopath = &Command{
+var HelpGopath = &base.Command{
UsageLine: "gopath",
Short: "GOPATH environment variable",
Long: `
@@ -299,7 +312,7 @@ See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH.
Each directory listed in GOPATH must have a prescribed structure:
-The src directory holds source code. The path below src
+The src directory holds source code. The path below src
determines the import path or executable name.
The pkg directory holds installed package objects.
@@ -313,11 +326,11 @@ has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
The bin directory holds compiled commands.
Each command is named for its source directory, but only
-the final element, not the entire path. That is, the
+the final element, not the entire path. That is, the
command with source in DIR/src/foo/quux is installed into
-DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped
+DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped
so that you can add DIR/bin to your PATH to get at the
-installed commands. If the GOBIN environment variable is
+installed commands. If the GOBIN environment variable is
set, commands are installed to the directory it names instead
of DIR/bin. GOBIN must be an absolute path.
@@ -429,7 +442,7 @@ See https://golang.org/s/go15vendor for details.
`,
}
-var helpEnvironment = &Command{
+var HelpEnvironment = &base.Command{
UsageLine: "environment",
Short: "environment variables",
Long: `
@@ -464,7 +477,7 @@ Environment variables for use with cgo:
CC
The command to use to compile C code.
CGO_ENABLED
- Whether the cgo command is supported. Either 0 or 1.
+ Whether the cgo command is supported. Either 0 or 1.
CGO_CFLAGS
Flags that cgo will pass to the compiler when compiling
C code.
@@ -514,7 +527,7 @@ Special-purpose environment variables:
`,
}
-var helpFileType = &Command{
+var HelpFileType = &base.Command{
UsageLine: "filetype",
Short: "file types",
Long: `
@@ -560,7 +573,7 @@ for more details.
`,
}
-var helpBuildmode = &Command{
+var HelpBuildmode = &base.Command{
UsageLine: "buildmode",
Short: "description of build modes",
Long: `
@@ -579,10 +592,10 @@ are:
exactly one main package to be listed.
-buildmode=c-shared
- Build the listed main packages, plus all packages that they
- import, into C shared libraries. The only callable symbols will
+ Build the listed main package, plus all packages it imports,
+ into a C shared library. The only callable symbols will
be those functions exported using a cgo //export comment.
- Non-main packages are ignored.
+ Requires exactly one main package to be listed.
-buildmode=default
Listed main packages are built into executables and listed
diff --git a/libgo/go/cmd/go/context.go b/libgo/go/cmd/go/internal/list/context.go
similarity index 99%
rename from libgo/go/cmd/go/context.go
rename to libgo/go/cmd/go/internal/list/context.go
index 94cd54d..68d691e 100644
--- a/libgo/go/cmd/go/context.go
+++ b/libgo/go/cmd/go/internal/list/context.go
@@ -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 main
+package list
import (
"go/build"
diff --git a/libgo/go/cmd/go/list.go b/libgo/go/cmd/go/internal/list/list.go
similarity index 85%
rename from libgo/go/cmd/go/list.go
rename to libgo/go/cmd/go/internal/list/list.go
index 2f24083..241d089 100644
--- a/libgo/go/cmd/go/list.go
+++ b/libgo/go/cmd/go/internal/list/list.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package list implements the ``go list'' command.
+package list
import (
"bufio"
@@ -11,9 +12,14 @@ import (
"os"
"strings"
"text/template"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/work"
)
-var cmdList = &Command{
+var CmdList = &base.Command{
UsageLine: "list [-e] [-f format] [-json] [build flags] [packages]",
Short: "list packages",
Long: `
@@ -27,7 +33,7 @@ The default output shows the package import path:
golang.org/x/net/html
The -f flag specifies an alternate format for the list, using the
-syntax of package template. The default output is equivalent to -f
+syntax of package template. The default output is equivalent to -f
'{{.ImportPath}}'. The struct being passed to the template is:
type Package struct {
@@ -120,12 +126,12 @@ The -json flag causes the package data to be printed in JSON format
instead of using the template format.
The -e flag changes the handling of erroneous packages, those that
-cannot be found or are malformed. By default, the list command
+cannot be found or are malformed. By default, the list command
prints an error to standard error for each erroneous package and
omits the packages from consideration during the usual printing.
With the -e flag, the list command never prints errors to standard
error and instead processes the erroneous packages with the usual
-printing. Erroneous packages will have a non-empty ImportPath and
+printing. Erroneous packages will have a non-empty ImportPath and
a non-nil Error field; other information may or may not be missing
(zeroed).
@@ -136,27 +142,27 @@ For more about specifying packages, see 'go help packages'.
}
func init() {
- cmdList.Run = runList // break init cycle
- addBuildFlags(cmdList)
+ CmdList.Run = runList // break init cycle
+ work.AddBuildFlags(CmdList)
}
-var listE = cmdList.Flag.Bool("e", false, "")
-var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
-var listJson = cmdList.Flag.Bool("json", false, "")
+var listE = CmdList.Flag.Bool("e", false, "")
+var listFmt = CmdList.Flag.String("f", "{{.ImportPath}}", "")
+var listJson = CmdList.Flag.Bool("json", false, "")
var nl = []byte{'\n'}
-func runList(cmd *Command, args []string) {
- buildModeInit()
+func runList(cmd *base.Command, args []string) {
+ work.BuildModeInit()
out := newTrackingWriter(os.Stdout)
defer out.w.Flush()
- var do func(*Package)
+ var do func(*load.PackagePublic)
if *listJson {
- do = func(p *Package) {
+ do = func(p *load.PackagePublic) {
b, err := json.MarshalIndent(p, "", "\t")
if err != nil {
out.Flush()
- fatalf("%s", err)
+ base.Fatalf("%s", err)
}
out.Write(b)
out.Write(nl)
@@ -165,7 +171,7 @@ func runList(cmd *Command, args []string) {
var cachedCtxt *Context
context := func() *Context {
if cachedCtxt == nil {
- cachedCtxt = newContext(&buildContext)
+ cachedCtxt = newContext(&cfg.BuildContext)
}
return cachedCtxt
}
@@ -175,12 +181,12 @@ func runList(cmd *Command, args []string) {
}
tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt)
if err != nil {
- fatalf("%s", err)
+ base.Fatalf("%s", err)
}
- do = func(p *Package) {
+ do = func(p *load.PackagePublic) {
if err := tmpl.Execute(out, p); err != nil {
out.Flush()
- fatalf("%s", err)
+ base.Fatalf("%s", err)
}
if out.NeedNL() {
out.Write(nl)
@@ -188,17 +194,17 @@ func runList(cmd *Command, args []string) {
}
}
- load := packages
+ loadpkgs := load.Packages
if *listE {
- load = packagesAndErrors
+ loadpkgs = load.PackagesAndErrors
}
- for _, pkg := range load(args) {
+ for _, pkg := range loadpkgs(args) {
// Show vendor-expanded paths in listing
- pkg.TestImports = pkg.vendored(pkg.TestImports)
- pkg.XTestImports = pkg.vendored(pkg.XTestImports)
+ pkg.TestImports = pkg.Vendored(pkg.TestImports)
+ pkg.XTestImports = pkg.Vendored(pkg.XTestImports)
- do(pkg)
+ do(&pkg.PackagePublic)
}
}
diff --git a/libgo/go/cmd/go/internal/load/match_test.go b/libgo/go/cmd/go/internal/load/match_test.go
new file mode 100644
index 0000000..b8d67da
--- /dev/null
+++ b/libgo/go/cmd/go/internal/load/match_test.go
@@ -0,0 +1,165 @@
+// Copyright 2012 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 load
+
+import (
+ "strings"
+ "testing"
+)
+
+var matchPatternTests = `
+ pattern ...
+ match foo
+
+ pattern net
+ match net
+ not net/http
+
+ pattern net/http
+ match net/http
+ not net
+
+ pattern net...
+ match net net/http netchan
+ not not/http not/net/http
+
+ # Special cases. Quoting docs:
+
+ # First, /... at the end of the pattern can match an empty string,
+ # so that net/... matches both net and packages in its subdirectories, like net/http.
+ pattern net/...
+ match net net/http
+ not not/http not/net/http netchan
+
+ # Second, any slash-separted pattern element containing a wildcard never
+ # participates in a match of the "vendor" element in the path of a vendored
+ # package, so that ./... does not match packages in subdirectories of
+ # ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
+ # Note, however, that a directory named vendor that itself contains code
+ # is not a vendored package: cmd/vendor would be a command named vendor,
+ # and the pattern cmd/... matches it.
+ pattern ./...
+ match ./vendor ./mycode/vendor
+ not ./vendor/foo ./mycode/vendor/foo
+
+ pattern ./vendor/...
+ match ./vendor/foo ./vendor/foo/vendor
+ not ./vendor/foo/vendor/bar
+
+ pattern mycode/vendor/...
+ match mycode/vendor mycode/vendor/foo mycode/vendor/foo/vendor
+ not mycode/vendor/foo/vendor/bar
+
+ pattern x/vendor/y
+ match x/vendor/y
+ not x/vendor
+
+ pattern x/vendor/y/...
+ match x/vendor/y x/vendor/y/z x/vendor/y/vendor x/vendor/y/z/vendor
+ not x/vendor/y/vendor/z
+
+ pattern .../vendor/...
+ match x/vendor/y x/vendor/y/z x/vendor/y/vendor x/vendor/y/z/vendor
+`
+
+func TestMatchPattern(t *testing.T) {
+ testPatterns(t, "matchPattern", matchPatternTests, func(pattern, name string) bool {
+ return matchPattern(pattern)(name)
+ })
+}
+
+var treeCanMatchPatternTests = `
+ pattern ...
+ match foo
+
+ pattern net
+ match net
+ not net/http
+
+ pattern net/http
+ match net net/http
+
+ pattern net...
+ match net netchan net/http
+ not not/http not/net/http
+
+ pattern net/...
+ match net net/http
+ not not/http netchan
+
+ pattern abc.../def
+ match abcxyz
+ not xyzabc
+
+ pattern x/y/z/...
+ match x x/y x/y/z x/y/z/w
+
+ pattern x/y/z
+ match x x/y x/y/z
+ not x/y/z/w
+
+ pattern x/.../y/z
+ match x/a/b/c
+ not y/x/a/b/c
+`
+
+func TestTreeCanMatchPattern(t *testing.T) {
+ testPatterns(t, "treeCanMatchPattern", treeCanMatchPatternTests, func(pattern, name string) bool {
+ return treeCanMatchPattern(pattern)(name)
+ })
+}
+
+var hasPathPrefixTests = []stringPairTest{
+ {"abc", "a", false},
+ {"a/bc", "a", true},
+ {"a", "a", true},
+ {"a/bc", "a/", true},
+}
+
+func TestHasPathPrefix(t *testing.T) {
+ testStringPairs(t, "hasPathPrefix", hasPathPrefixTests, hasPathPrefix)
+}
+
+type stringPairTest struct {
+ in1 string
+ in2 string
+ out bool
+}
+
+func testStringPairs(t *testing.T, name string, tests []stringPairTest, f func(string, string) bool) {
+ for _, tt := range tests {
+ if out := f(tt.in1, tt.in2); out != tt.out {
+ t.Errorf("%s(%q, %q) = %v, want %v", name, tt.in1, tt.in2, out, tt.out)
+ }
+ }
+}
+
+func testPatterns(t *testing.T, name, tests string, fn func(string, string) bool) {
+ var patterns []string
+ for _, line := range strings.Split(tests, "\n") {
+ if i := strings.Index(line, "#"); i >= 0 {
+ line = line[:i]
+ }
+ f := strings.Fields(line)
+ if len(f) == 0 {
+ continue
+ }
+ switch f[0] {
+ default:
+ t.Fatalf("unknown directive %q", f[0])
+ case "pattern":
+ patterns = f[1:]
+ case "match", "not":
+ want := f[0] == "match"
+ for _, pattern := range patterns {
+ for _, in := range f[1:] {
+ if fn(pattern, in) != want {
+ t.Errorf("%s(%q, %q) = %v, want %v", name, pattern, in, !want, want)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/libgo/go/cmd/go/internal/load/path.go b/libgo/go/cmd/go/internal/load/path.go
new file mode 100644
index 0000000..9cc85dd
--- /dev/null
+++ b/libgo/go/cmd/go/internal/load/path.go
@@ -0,0 +1,80 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package 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
+}
+
+// hasPathPrefix reports whether the path s begins with the
+// elements in prefix.
+func hasPathPrefix(s, prefix string) bool {
+ switch {
+ default:
+ return false
+ case len(s) == len(prefix):
+ return s == prefix
+ case len(s) > len(prefix):
+ if prefix != "" && prefix[len(prefix)-1] == '/' {
+ return strings.HasPrefix(s, prefix)
+ }
+ return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
+ }
+}
+
+// expandPath returns the symlink-expanded form of path.
+func expandPath(p string) string {
+ x, err := filepath.EvalSymlinks(p)
+ if err == nil {
+ return x
+ }
+ return p
+}
+
+// hasFilePathPrefix reports whether the filesystem path s begins with the
+// elements in prefix.
+func hasFilePathPrefix(s, prefix string) bool {
+ sv := strings.ToUpper(filepath.VolumeName(s))
+ pv := strings.ToUpper(filepath.VolumeName(prefix))
+ s = s[len(sv):]
+ prefix = prefix[len(pv):]
+ switch {
+ default:
+ return false
+ case sv != pv:
+ return false
+ case len(s) == len(prefix):
+ return s == prefix
+ case len(s) > len(prefix):
+ if prefix != "" && prefix[len(prefix)-1] == filepath.Separator {
+ return strings.HasPrefix(s, prefix)
+ }
+ return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix
+ }
+}
diff --git a/libgo/go/cmd/go/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go
similarity index 76%
rename from libgo/go/cmd/go/pkg.go
rename to libgo/go/cmd/go/internal/load/pkg.go
index f0dc956..acb20fe 100644
--- a/libgo/go/cmd/go/pkg.go
+++ b/libgo/go/cmd/go/internal/load/pkg.go
@@ -2,32 +2,38 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package load loads packages.
+package load
import (
- "bytes"
"crypto/sha1"
- "errors"
"fmt"
"go/build"
- "go/scanner"
"go/token"
- "io"
"io/ioutil"
"os"
pathpkg "path"
"path/filepath"
"runtime"
"sort"
- "strconv"
"strings"
"unicode"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/buildid"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/str"
)
-var ignoreImports bool // control whether we ignore imports in packages
+var IgnoreImports bool // control whether we ignore imports in packages
// A Package describes a single package found in a directory.
type Package struct {
+ PackagePublic // visible in 'go list'
+ Internal PackageInternal // for use inside go command only
+}
+
+type PackagePublic struct {
// Note: These fields are part of the go command's public API.
// See list.go. It is okay to add fields, but not to change or
// remove existing ones. Keep in sync with list.go
@@ -82,31 +88,59 @@ type Package struct {
TestImports []string `json:",omitempty"` // imports from TestGoFiles
XTestGoFiles []string `json:",omitempty"` // _test.go files outside package
XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
+}
+type PackageInternal struct {
// Unexported fields are not part of the public API.
- build *build.Package
- pkgdir string // overrides build.PkgDir
- imports []*Package
- deps []*Package
- gofiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
- sfiles []string
- allgofiles []string // gofiles + IgnoredGoFiles, absolute paths
- target string // installed file for this package (may be executable)
- fake bool // synthesized package
- external bool // synthesized external test package
- forceLibrary bool // this package is a library (even if named "main")
- cmdline bool // defined by files listed on command line
- local bool // imported via local path (./ or ../)
- localPrefix string // interpret ./ and ../ imports relative to this prefix
- exeName string // desired name for temporary executable
- coverMode string // preprocess Go source files with the coverage tool in this mode
- coverVars map[string]*CoverVar // variables created by coverage analysis
- omitDWARF bool // tell linker not to write DWARF information
- buildID string // expected build ID for generated package
- gobinSubdir bool // install target would be subdir of GOBIN
+ Build *build.Package
+ Pkgdir string // overrides build.PkgDir
+ Imports []*Package
+ Deps []*Package
+ GoFiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths
+ SFiles []string
+ AllGoFiles []string // gofiles + IgnoredGoFiles, absolute paths
+ Target string // installed file for this package (may be executable)
+ Fake bool // synthesized package
+ External bool // synthesized external test package
+ ForceLibrary bool // this package is a library (even if named "main")
+ Cmdline bool // defined by files listed on command line
+ Local bool // imported via local path (./ or ../)
+ LocalPrefix string // interpret ./ and ../ imports relative to this prefix
+ ExeName string // desired name for temporary executable
+ CoverMode string // preprocess Go source files with the coverage tool in this mode
+ CoverVars map[string]*CoverVar // variables created by coverage analysis
+ OmitDebug bool // tell linker not to write debug information
+ BuildID string // expected build ID for generated package
+ GobinSubdir bool // install target would be subdir of GOBIN
+}
+
+type NoGoError struct {
+ Package *Package
+}
+
+func (e *NoGoError) Error() string {
+ // Count files beginning with _ and ., which we will pretend don't exist at all.
+ dummy := 0
+ for _, name := range e.Package.IgnoredGoFiles {
+ if strings.HasPrefix(name, "_") || strings.HasPrefix(name, ".") {
+ dummy++
+ }
+ }
+
+ if len(e.Package.IgnoredGoFiles) > dummy {
+ // Go files exist, but they were ignored due to build constraints.
+ return "build constraints exclude all Go files in " + e.Package.Dir
+ }
+ if len(e.Package.TestGoFiles)+len(e.Package.XTestGoFiles) > 0 {
+ // Test Go files exist, but we're not interested in them.
+ // The double-negative is unfortunate but we want e.Package.Dir
+ // to appear at the end of error message.
+ return "no non-test Go files in " + e.Package.Dir
+ }
+ return "no Go files in " + e.Package.Dir
}
-// vendored returns the vendor-resolved version of imports,
+// Vendored returns the vendor-resolved version of imports,
// which should be p.TestImports or p.XTestImports, NOT p.Imports.
// The imports in p.TestImports and p.XTestImports are not recursively
// loaded during the initial load of p, so they list the imports found in
@@ -116,14 +150,14 @@ type Package struct {
// can produce better error messages if it starts with the original paths.
// The initial load of p loads all the non-test imports and rewrites
// the vendored paths, so nothing should ever call p.vendored(p.Imports).
-func (p *Package) vendored(imports []string) []string {
+func (p *Package) Vendored(imports []string) []string {
if len(imports) > 0 && len(p.Imports) > 0 && &imports[0] == &p.Imports[0] {
panic("internal error: p.vendored(p.Imports) called")
}
seen := make(map[string]bool)
var all []string
for _, path := range imports {
- path = vendoredImportPath(p, path)
+ path = VendoredImportPath(p, path)
if !seen[path] {
seen[path] = true
all = append(all, path)
@@ -140,13 +174,13 @@ type CoverVar struct {
}
func (p *Package) copyBuild(pp *build.Package) {
- p.build = pp
+ p.Internal.Build = pp
- if pp.PkgTargetRoot != "" && buildPkgdir != "" {
+ if pp.PkgTargetRoot != "" && cfg.BuildPkgdir != "" {
old := pp.PkgTargetRoot
- pp.PkgRoot = buildPkgdir
- pp.PkgTargetRoot = buildPkgdir
- pp.PkgObj = filepath.Join(buildPkgdir, strings.TrimPrefix(pp.PkgObj, old))
+ pp.PkgRoot = cfg.BuildPkgdir
+ pp.PkgTargetRoot = cfg.BuildPkgdir
+ pp.PkgObj = filepath.Join(cfg.BuildPkgdir, strings.TrimPrefix(pp.PkgObj, old))
}
p.Dir = pp.Dir
@@ -160,10 +194,9 @@ func (p *Package) copyBuild(pp *build.Package) {
// TODO? Target
p.Goroot = pp.Goroot
- if buildContext.Compiler == "gccgo" {
+ p.Standard = p.Goroot && p.ImportPath != "" && isStandardImportPath(p.ImportPath)
+ if cfg.BuildToolchainName == "gccgo" {
p.Standard = stdpkg[p.ImportPath]
- } else {
- p.Standard = p.Goroot && p.ImportPath != "" && isStandardImportPath(p.ImportPath)
}
p.GoFiles = pp.GoFiles
p.CgoFiles = pp.CgoFiles
@@ -180,6 +213,7 @@ func (p *Package) copyBuild(pp *build.Package) {
p.CgoCFLAGS = pp.CgoCFLAGS
p.CgoCPPFLAGS = pp.CgoCPPFLAGS
p.CgoCXXFLAGS = pp.CgoCXXFLAGS
+ p.CgoFFLAGS = pp.CgoFFLAGS
p.CgoLDFLAGS = pp.CgoLDFLAGS
p.CgoPkgConfig = pp.CgoPkgConfig
// We modify p.Imports in place, so make copy now.
@@ -189,7 +223,7 @@ func (p *Package) copyBuild(pp *build.Package) {
p.TestImports = pp.TestImports
p.XTestGoFiles = pp.XTestGoFiles
p.XTestImports = pp.XTestImports
- if ignoreImports {
+ if IgnoreImports {
p.Imports = nil
p.TestImports = nil
p.XTestImports = nil
@@ -214,13 +248,13 @@ type PackageError struct {
ImportStack []string // shortest path from package named on command line to this one
Pos string // position of error
Err string // the error itself
- isImportCycle bool // the error is an import cycle
- hard bool // whether the error is soft or hard; soft errors are ignored in some places
+ IsImportCycle bool `json:"-"` // the error is an import cycle
+ Hard bool `json:"-"` // whether the error is soft or hard; soft errors are ignored in some places
}
func (p *PackageError) Error() string {
// Import cycles deserve special treatment.
- if p.isImportCycle {
+ if p.IsImportCycle {
return fmt.Sprintf("%s\npackage %s\n", p.Err, strings.Join(p.ImportStack, "\n\timports "))
}
if p.Pos != "" {
@@ -234,25 +268,25 @@ func (p *PackageError) Error() string {
return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err
}
-// An importStack is a stack of import paths.
-type importStack []string
+// An ImportStack is a stack of import paths.
+type ImportStack []string
-func (s *importStack) push(p string) {
+func (s *ImportStack) Push(p string) {
*s = append(*s, p)
}
-func (s *importStack) pop() {
+func (s *ImportStack) Pop() {
*s = (*s)[0 : len(*s)-1]
}
-func (s *importStack) copy() []string {
+func (s *ImportStack) Copy() []string {
return append([]string{}, *s...)
}
// shorterThan reports whether sp is shorter than t.
// We use this to record the shortest import sequence
// that leads to a particular package.
-func (sp *importStack) shorterThan(t []string) bool {
+func (sp *ImportStack) shorterThan(t []string) bool {
s := *sp
if len(s) != len(t) {
return len(s) < len(t)
@@ -271,15 +305,31 @@ func (sp *importStack) shorterThan(t []string) bool {
// we return the same pointer each time.
var packageCache = map[string]*Package{}
+func ClearPackageCache() {
+ for name := range packageCache {
+ delete(packageCache, name)
+ }
+}
+
+func ClearPackageCachePartial(args []string) {
+ for _, arg := range args {
+ p := packageCache[arg]
+ if p != nil {
+ delete(packageCache, p.Dir)
+ delete(packageCache, p.ImportPath)
+ }
+ }
+}
+
// reloadPackage is like loadPackage but makes sure
// not to use the package cache.
-func reloadPackage(arg string, stk *importStack) *Package {
+func ReloadPackage(arg string, stk *ImportStack) *Package {
p := packageCache[arg]
if p != nil {
delete(packageCache, p.Dir)
delete(packageCache, p.ImportPath)
}
- return loadPackage(arg, stk)
+ return LoadPackage(arg, stk)
}
// dirToImportPath returns the pseudo-import path we use for a package
@@ -313,20 +363,20 @@ const (
// recorded as the canonical import path. At that point, future loads
// of that package must not pass useVendor, because
// disallowVendor will reject direct use of paths containing /vendor/.
- useVendor = 1 << iota
+ UseVendor = 1 << iota
// getTestDeps is for download (part of "go get") and indicates
// that test dependencies should be fetched too.
- getTestDeps
+ GetTestDeps
)
// loadImport scans the directory named by path, which must be an import path,
// but possibly a local import path (an absolute file system path or one beginning
-// with ./ or ../). A local relative path is interpreted relative to srcDir.
+// with ./ or ../). A local relative path is interpreted relative to srcDir.
// It returns a *Package describing the package found in that directory.
-func loadImport(path, srcDir string, parent *Package, stk *importStack, importPos []token.Position, mode int) *Package {
- stk.push(path)
- defer stk.pop()
+func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
+ stk.Push(path)
+ defer stk.Pop()
// Determine canonical identifier for this package.
// For a local import the identifier is the pseudo-import path
@@ -338,12 +388,12 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
isLocal := build.IsLocalImport(path)
if isLocal {
importPath = dirToImportPath(filepath.Join(srcDir, path))
- } else if mode&useVendor != 0 {
+ } else if mode&UseVendor != 0 {
// We do our own vendor resolution, because we want to
// find out the key to use in packageCache without the
// overhead of repeated calls to buildContext.Import.
// The code is also needed in a few other places anyway.
- path = vendoredImportPath(parent, path)
+ path = VendoredImportPath(parent, path)
importPath = path
}
@@ -352,7 +402,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
p = reusePackage(p, stk)
} else {
p = new(Package)
- p.local = isLocal
+ p.Internal.Local = isLocal
p.ImportPath = importPath
packageCache[importPath] = p
@@ -363,14 +413,14 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
// TODO: After Go 1, decide when to pass build.AllowBinary here.
// See issue 3268 for mistakes to avoid.
buildMode := build.ImportComment
- if mode&useVendor == 0 || path != origPath {
+ if mode&UseVendor == 0 || path != origPath {
// Not vendoring, or we already found the vendored path.
buildMode |= build.IgnoreVendor
}
- bp, err := buildContext.Import(path, srcDir, buildMode)
+ bp, err := cfg.BuildContext.Import(path, srcDir, buildMode)
bp.ImportPath = importPath
- if gobin != "" {
- bp.BinDir = gobin
+ if cfg.GOBIN != "" {
+ bp.BinDir = cfg.GOBIN
}
if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path &&
!strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") {
@@ -383,7 +433,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
if origPath != cleanImport(origPath) {
p.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: fmt.Sprintf("non-canonical import path: %q should be %q", origPath, pathpkg.Clean(origPath)),
}
p.Incomplete = true
@@ -394,7 +444,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
if perr := disallowInternal(srcDir, p, stk); perr != p {
return setErrorPos(perr, importPos)
}
- if mode&useVendor != 0 {
+ if mode&UseVendor != 0 {
if perr := disallowVendor(srcDir, origPath, p, stk); perr != p {
return setErrorPos(perr, importPos)
}
@@ -403,16 +453,16 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
if p.Name == "main" && parent != nil && parent.Dir != p.Dir {
perr := *p
perr.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: fmt.Sprintf("import %q is a program, not an importable package", path),
}
return setErrorPos(&perr, importPos)
}
- if p.local && parent != nil && !parent.local {
+ if p.Internal.Local && parent != nil && !parent.Internal.Local {
perr := *p
perr.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: fmt.Sprintf("local import %q in non-local package", path),
}
return setErrorPos(&perr, importPos)
@@ -424,7 +474,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
func setErrorPos(p *Package, importPos []token.Position) *Package {
if len(importPos) > 0 {
pos := importPos[0]
- pos.Filename = shortPath(pos.Filename)
+ pos.Filename = base.ShortPath(pos.Filename)
p.Error.Pos = pos.String()
}
return p
@@ -453,11 +503,11 @@ func isDir(path string) bool {
return result
}
-// vendoredImportPath returns the expansion of path when it appears in parent.
+// VendoredImportPath returns the expansion of path when it appears in parent.
// If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path,
// x/vendor/path, vendor/path, or else stay path if none of those exist.
-// vendoredImportPath returns the expanded path or, if no expansion is found, the original.
-func vendoredImportPath(parent *Package, path string) (found string) {
+// VendoredImportPath returns the expanded path or, if no expansion is found, the original.
+func VendoredImportPath(parent *Package, path string) (found string) {
if parent == nil || parent.Root == "" {
return path
}
@@ -470,8 +520,8 @@ func vendoredImportPath(parent *Package, path string) (found string) {
root = expandPath(root)
}
- if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.local && filepath.Join(root, parent.ImportPath) != dir {
- fatalf("unexpected directory layout:\n"+
+ if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.Internal.Local && filepath.Join(root, parent.ImportPath) != dir {
+ base.Fatalf("unexpected directory layout:\n"+
" import path: %s\n"+
" root: %s\n"+
" dir: %s\n"+
@@ -545,24 +595,24 @@ func hasGoFiles(dir string) bool {
// reusePackage reuses package p to satisfy the import at the top
// of the import stack stk. If this use causes an import loop,
// reusePackage updates p's error information to record the loop.
-func reusePackage(p *Package, stk *importStack) *Package {
- // We use p.imports==nil to detect a package that
+func reusePackage(p *Package, stk *ImportStack) *Package {
+ // We use p.Internal.Imports==nil to detect a package that
// is in the midst of its own loadPackage call
- // (all the recursion below happens before p.imports gets set).
- if p.imports == nil {
+ // (all the recursion below happens before p.Internal.Imports gets set).
+ if p.Internal.Imports == nil {
if p.Error == nil {
p.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: "import cycle not allowed",
- isImportCycle: true,
+ IsImportCycle: true,
}
}
p.Incomplete = true
}
// Don't rewrite the import stack in the error if we have an import cycle.
// If we do, we'll lose the path that describes the cycle.
- if p.Error != nil && !p.Error.isImportCycle && stk.shorterThan(p.Error.ImportStack) {
- p.Error.ImportStack = stk.copy()
+ if p.Error != nil && !p.Error.IsImportCycle && stk.shorterThan(p.Error.ImportStack) {
+ p.Error.ImportStack = stk.Copy()
}
return p
}
@@ -570,7 +620,7 @@ func reusePackage(p *Package, stk *importStack) *Package {
// disallowInternal checks that srcDir is allowed to import p.
// If the import is allowed, disallowInternal returns the original package p.
// If not, it returns a new package containing just an appropriate error.
-func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
+func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package {
// golang.org/s/go14internal:
// An import of a path containing the element âinternalâ
// is disallowed if the importing code is outside the tree
@@ -590,7 +640,7 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
}
// We can't check standard packages with gccgo.
- if buildContext.Compiler == "gccgo" && p.Standard {
+ if cfg.BuildContext.Compiler == "gccgo" && p.Standard {
return p
}
@@ -628,7 +678,7 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
// Internal is present, and srcDir is outside parent's tree. Not allowed.
perr := *p
perr.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: "use of internal package not allowed",
}
perr.Incomplete = true
@@ -657,7 +707,7 @@ func findInternal(path string) (index int, ok bool) {
// disallowVendor checks that srcDir is allowed to import p as path.
// If the import is allowed, disallowVendor returns the original package p.
// If not, it returns a new package containing just an appropriate error.
-func disallowVendor(srcDir, path string, p *Package, stk *importStack) *Package {
+func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package {
// The stack includes p.ImportPath.
// If that's the only thing on the stack, we started
// with a name given on the command line, not an
@@ -671,10 +721,10 @@ func disallowVendor(srcDir, path string, p *Package, stk *importStack) *Package
}
// Paths like x/vendor/y must be imported as y, never as x/vendor/y.
- if i, ok := findVendor(path); ok {
+ if i, ok := FindVendor(path); ok {
perr := *p
perr.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: "must be imported as " + path[i+len("vendor/"):],
}
perr.Incomplete = true
@@ -689,7 +739,7 @@ func disallowVendor(srcDir, path string, p *Package, stk *importStack) *Package
// is not subject to the rules, only subdirectories of vendor.
// This allows people to have packages and commands named vendor,
// for maximal compatibility with existing source trees.
-func disallowVendorVisibility(srcDir string, p *Package, stk *importStack) *Package {
+func disallowVendorVisibility(srcDir string, p *Package, stk *ImportStack) *Package {
// The stack includes p.ImportPath.
// If that's the only thing on the stack, we started
// with a name given on the command line, not an
@@ -699,7 +749,7 @@ func disallowVendorVisibility(srcDir string, p *Package, stk *importStack) *Pack
}
// Check for "vendor" element.
- i, ok := findVendor(p.ImportPath)
+ i, ok := FindVendor(p.ImportPath)
if !ok {
return p
}
@@ -728,22 +778,22 @@ func disallowVendorVisibility(srcDir string, p *Package, stk *importStack) *Pack
// Vendor is present, and srcDir is outside parent's tree. Not allowed.
perr := *p
perr.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: "use of vendored package not allowed",
}
perr.Incomplete = true
return &perr
}
-// findVendor looks for the last non-terminating "vendor" path element in the given import path.
-// If there isn't one, findVendor returns ok=false.
-// Otherwise, findVendor returns ok=true and the index of the "vendor".
+// FindVendor looks for the last non-terminating "vendor" path element in the given import path.
+// If there isn't one, FindVendor returns ok=false.
+// Otherwise, FindVendor returns ok=true and the index of the "vendor".
//
// Note that terminating "vendor" elements don't count: "x/vendor" is its own package,
// not the vendored copy of an import "" (the empty import path).
// This will allow people to have packages or commands named vendor.
// This may help reduce breakage, or it may just be confusing. We'll see.
-func findVendor(path string) (index int, ok bool) {
+func FindVendor(path string) (index int, ok bool) {
// Two cases, depending on internal at start of string or not.
// The order matters: we must return the index of the final element,
// because the final one is where the effective import path starts.
@@ -759,54 +809,33 @@ func findVendor(path string) (index int, ok bool) {
type targetDir int
const (
- toRoot targetDir = iota // to bin dir inside package root (default)
- toTool // GOROOT/pkg/tool
- stalePath // the old import path; fail to build
+ ToRoot targetDir = iota // to bin dir inside package root (default)
+ ToTool // GOROOT/pkg/tool
+ StalePath // the old import path; fail to build
)
// goTools is a map of Go program import path to install target directory.
-var goTools = map[string]targetDir{
- "cmd/addr2line": toTool,
- "cmd/api": toTool,
- "cmd/asm": toTool,
- "cmd/compile": toTool,
- "cmd/cgo": toTool,
- "cmd/cover": toTool,
- "cmd/dist": toTool,
- "cmd/doc": toTool,
- "cmd/fix": toTool,
- "cmd/link": toTool,
- "cmd/newlink": toTool,
- "cmd/nm": toTool,
- "cmd/objdump": toTool,
- "cmd/pack": toTool,
- "cmd/pprof": toTool,
- "cmd/trace": toTool,
- "cmd/vet": toTool,
- "code.google.com/p/go.tools/cmd/cover": stalePath,
- "code.google.com/p/go.tools/cmd/godoc": stalePath,
- "code.google.com/p/go.tools/cmd/vet": stalePath,
-}
-
-// expandScanner expands a scanner.List error into all the errors in the list.
-// The default Error method only shows the first error.
-func expandScanner(err error) error {
- // Look for parser errors.
- if err, ok := err.(scanner.ErrorList); ok {
- // Prepare error with \n before each message.
- // When printed in something like context: %v
- // this will put the leading file positions each on
- // its own line. It will also show all the errors
- // instead of just the first, as err.Error does.
- var buf bytes.Buffer
- for _, e := range err {
- e.Pos.Filename = shortPath(e.Pos.Filename)
- buf.WriteString("\n")
- buf.WriteString(e.Error())
- }
- return errors.New(buf.String())
- }
- return err
+var GoTools = map[string]targetDir{
+ "cmd/addr2line": ToTool,
+ "cmd/api": ToTool,
+ "cmd/asm": ToTool,
+ "cmd/compile": ToTool,
+ "cmd/cgo": ToTool,
+ "cmd/cover": ToTool,
+ "cmd/dist": ToTool,
+ "cmd/doc": ToTool,
+ "cmd/fix": ToTool,
+ "cmd/link": ToTool,
+ "cmd/newlink": ToTool,
+ "cmd/nm": ToTool,
+ "cmd/objdump": ToTool,
+ "cmd/pack": ToTool,
+ "cmd/pprof": ToTool,
+ "cmd/trace": ToTool,
+ "cmd/vet": ToTool,
+ "code.google.com/p/go.tools/cmd/cover": StalePath,
+ "code.google.com/p/go.tools/cmd/godoc": StalePath,
+ "code.google.com/p/go.tools/cmd/vet": StalePath,
}
var raceExclude = map[string]bool{
@@ -828,27 +857,32 @@ var cgoSyscallExclude = map[string]bool{
"runtime/msan": true,
}
+var foldPath = make(map[string]string)
+
// load populates p using information from bp, err, which should
// be the result of calling build.Context.Import.
-func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package {
+func (p *Package) load(stk *ImportStack, bp *build.Package, err error) *Package {
p.copyBuild(bp)
// When using gccgo the go/build package will not be able to
- // find a standard package. It would be nicer to not get that
+ // find a standard package. It would be nicer to not get that
// error, but go/build doesn't know stdpkg.
- if runtime.Compiler == "gccgo" && err != nil && p.Standard {
+ if cfg.BuildToolchainName == "gccgo" && err != nil && p.Standard {
err = nil
}
// The localPrefix is the path we interpret ./ imports relative to.
// Synthesized main packages sometimes override this.
- p.localPrefix = dirToImportPath(p.Dir)
+ p.Internal.LocalPrefix = dirToImportPath(p.Dir)
if err != nil {
+ if _, ok := err.(*build.NoGoError); ok {
+ err = &NoGoError{Package: p}
+ }
p.Incomplete = true
- err = expandScanner(err)
+ err = base.ExpandScanner(err)
p.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: err.Error(),
}
return p
@@ -856,7 +890,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
useBindir := p.Name == "main"
if !p.Standard {
- switch buildBuildmode {
+ switch cfg.BuildBuildmode {
case "c-archive", "c-shared", "plugin":
useBindir = false
}
@@ -864,111 +898,111 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
if useBindir {
// Report an error when the old code.google.com/p/go.tools paths are used.
- if goTools[p.ImportPath] == stalePath {
+ if GoTools[p.ImportPath] == StalePath {
newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
e := fmt.Sprintf("the %v command has moved; use %v instead.", p.ImportPath, newPath)
p.Error = &PackageError{Err: e}
return p
}
_, elem := filepath.Split(p.Dir)
- full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem
- if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH {
+ full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
+ if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
// Install cross-compiled binaries to subdirectories of bin.
elem = full
}
- if p.build.BinDir != "" {
+ if p.Internal.Build.BinDir != "" {
// Install to GOBIN or bin of GOPATH entry.
- p.target = filepath.Join(p.build.BinDir, elem)
- if !p.Goroot && strings.Contains(elem, "/") && gobin != "" {
+ p.Internal.Target = filepath.Join(p.Internal.Build.BinDir, elem)
+ if !p.Goroot && strings.Contains(elem, "/") && cfg.GOBIN != "" {
// Do not create $GOBIN/goos_goarch/elem.
- p.target = ""
- p.gobinSubdir = true
+ p.Internal.Target = ""
+ p.Internal.GobinSubdir = true
}
}
- if goTools[p.ImportPath] == toTool {
+ if GoTools[p.ImportPath] == ToTool {
// This is for 'go tool'.
// Override all the usual logic and force it into the tool directory.
- if buildContext.Compiler == "gccgo" {
- p.target = filepath.Join(runtime.GCCGOTOOLDIR, elem)
+ if cfg.BuildToolchainName == "gccgo" {
+ p.Internal.Target = filepath.Join(runtime.GCCGOTOOLDIR, elem)
} else {
- p.target = filepath.Join(gorootPkg, "tool", full)
+ p.Internal.Target = filepath.Join(cfg.GOROOTpkg, "tool", full)
}
}
- if p.target != "" && buildContext.GOOS == "windows" {
- p.target += ".exe"
+ if p.Internal.Target != "" && cfg.BuildContext.GOOS == "windows" {
+ p.Internal.Target += ".exe"
}
- } else if p.local {
+ } else if p.Internal.Local {
// Local import turned into absolute path.
// No permanent install target.
- p.target = ""
+ p.Internal.Target = ""
} else {
- p.target = p.build.PkgObj
- if buildLinkshared {
- shlibnamefile := p.target[:len(p.target)-2] + ".shlibname"
+ p.Internal.Target = p.Internal.Build.PkgObj
+ if cfg.BuildLinkshared {
+ shlibnamefile := p.Internal.Target[:len(p.Internal.Target)-2] + ".shlibname"
shlib, err := ioutil.ReadFile(shlibnamefile)
if err == nil {
libname := strings.TrimSpace(string(shlib))
- if buildContext.Compiler == "gccgo" {
- p.Shlib = filepath.Join(p.build.PkgTargetRoot, "shlibs", libname)
+ if cfg.BuildContext.Compiler == "gccgo" {
+ p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, "shlibs", libname)
} else {
- p.Shlib = filepath.Join(p.build.PkgTargetRoot, libname)
+ p.Shlib = filepath.Join(p.Internal.Build.PkgTargetRoot, libname)
}
} else if !os.IsNotExist(err) {
- fatalf("unexpected error reading %s: %v", shlibnamefile, err)
+ base.Fatalf("unexpected error reading %s: %v", shlibnamefile, err)
}
}
}
- importPaths := p.Imports
+ ImportPaths := p.Imports
// Packages that use cgo import runtime/cgo implicitly.
// Packages that use cgo also import syscall implicitly,
// to wrap errno.
// Exclude certain packages to avoid circular dependencies.
if len(p.CgoFiles) > 0 && (!p.Standard || !cgoExclude[p.ImportPath]) {
- importPaths = append(importPaths, "runtime/cgo")
+ ImportPaths = append(ImportPaths, "runtime/cgo")
}
if len(p.CgoFiles) > 0 && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) {
- importPaths = append(importPaths, "syscall")
+ ImportPaths = append(ImportPaths, "syscall")
}
- if buildContext.CgoEnabled && p.Name == "main" && !p.Goroot {
+ if cfg.BuildContext.CgoEnabled && p.Name == "main" && !p.Goroot {
// Currently build modes c-shared, pie (on systems that do not
// support PIE with internal linking mode), plugin, and
// -linkshared force external linking mode, as of course does
// -ldflags=-linkmode=external. External linking mode forces
// an import of runtime/cgo.
- pieCgo := buildBuildmode == "pie" && (buildContext.GOOS != "linux" || buildContext.GOARCH != "amd64")
+ pieCgo := cfg.BuildBuildmode == "pie" && (cfg.BuildContext.GOOS != "linux" || cfg.BuildContext.GOARCH != "amd64")
linkmodeExternal := false
- for i, a := range buildLdflags {
+ for i, a := range cfg.BuildLdflags {
if a == "-linkmode=external" {
linkmodeExternal = true
}
- if a == "-linkmode" && i+1 < len(buildLdflags) && buildLdflags[i+1] == "external" {
+ if a == "-linkmode" && i+1 < len(cfg.BuildLdflags) && cfg.BuildLdflags[i+1] == "external" {
linkmodeExternal = true
}
}
- if buildBuildmode == "c-shared" || buildBuildmode == "plugin" || pieCgo || buildLinkshared || linkmodeExternal {
- importPaths = append(importPaths, "runtime/cgo")
+ if cfg.BuildBuildmode == "c-shared" || cfg.BuildBuildmode == "plugin" || pieCgo || cfg.BuildLinkshared || linkmodeExternal {
+ ImportPaths = append(ImportPaths, "runtime/cgo")
}
}
// Everything depends on runtime, except runtime, its internal
// subpackages, and unsafe.
if !p.Standard || (p.ImportPath != "runtime" && !strings.HasPrefix(p.ImportPath, "runtime/internal/") && p.ImportPath != "unsafe") {
- importPaths = append(importPaths, "runtime")
+ ImportPaths = append(ImportPaths, "runtime")
// When race detection enabled everything depends on runtime/race.
// Exclude certain packages to avoid circular dependencies.
- if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
- importPaths = append(importPaths, "runtime/race")
+ if cfg.BuildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
+ ImportPaths = append(ImportPaths, "runtime/race")
}
// MSan uses runtime/msan.
- if buildMSan && (!p.Standard || !raceExclude[p.ImportPath]) {
- importPaths = append(importPaths, "runtime/msan")
+ if cfg.BuildMSan && (!p.Standard || !raceExclude[p.ImportPath]) {
+ ImportPaths = append(ImportPaths, "runtime/msan")
}
// On ARM with GOARM=5, everything depends on math for the link.
- if p.Name == "main" && goarch == "arm" {
- importPaths = append(importPaths, "math")
+ if p.Name == "main" && cfg.Goarch == "arm" {
+ ImportPaths = append(ImportPaths, "math")
}
}
@@ -977,35 +1011,35 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
// This can be an issue particularly for runtime/internal/atomic;
// see issue 13655.
if p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal/")) && p.ImportPath != "runtime/internal/sys" {
- importPaths = append(importPaths, "runtime/internal/sys")
+ ImportPaths = append(ImportPaths, "runtime/internal/sys")
}
// Build list of full paths to all Go files in the package,
// for use by commands like go fmt.
- p.gofiles = stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)
- for i := range p.gofiles {
- p.gofiles[i] = filepath.Join(p.Dir, p.gofiles[i])
+ p.Internal.GoFiles = str.StringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)
+ for i := range p.Internal.GoFiles {
+ p.Internal.GoFiles[i] = filepath.Join(p.Dir, p.Internal.GoFiles[i])
}
- sort.Strings(p.gofiles)
+ sort.Strings(p.Internal.GoFiles)
- p.sfiles = stringList(p.SFiles)
- for i := range p.sfiles {
- p.sfiles[i] = filepath.Join(p.Dir, p.sfiles[i])
+ p.Internal.SFiles = str.StringList(p.SFiles)
+ for i := range p.Internal.SFiles {
+ p.Internal.SFiles[i] = filepath.Join(p.Dir, p.Internal.SFiles[i])
}
- sort.Strings(p.sfiles)
+ sort.Strings(p.Internal.SFiles)
- p.allgofiles = stringList(p.IgnoredGoFiles)
- for i := range p.allgofiles {
- p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i])
+ p.Internal.AllGoFiles = str.StringList(p.IgnoredGoFiles)
+ for i := range p.Internal.AllGoFiles {
+ p.Internal.AllGoFiles[i] = filepath.Join(p.Dir, p.Internal.AllGoFiles[i])
}
- p.allgofiles = append(p.allgofiles, p.gofiles...)
- sort.Strings(p.allgofiles)
+ p.Internal.AllGoFiles = append(p.Internal.AllGoFiles, p.Internal.GoFiles...)
+ sort.Strings(p.Internal.AllGoFiles)
// Check for case-insensitive collision of input files.
// To avoid problems on case-insensitive files, we reject any package
// where two different input files have equal names under a case-insensitive
// comparison.
- f1, f2 := foldDup(stringList(
+ f1, f2 := str.FoldDup(str.StringList(
p.GoFiles,
p.CgoFiles,
p.IgnoredGoFiles,
@@ -1023,7 +1057,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
))
if f1 != "" {
p.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: fmt.Sprintf("case-insensitive file name collision: %q and %q", f1, f2),
}
return p
@@ -1042,41 +1076,41 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
}
- for i, path := range importPaths {
+ for i, path := range ImportPaths {
if path == "C" {
continue
}
- p1 := loadImport(path, p.Dir, p, stk, p.build.ImportPos[path], useVendor)
- if !reqStdPkgSrc && p1.Standard {
+ p1 := LoadImport(path, p.Dir, p, stk, p.Internal.Build.ImportPos[path], UseVendor)
+ if cfg.BuildToolchainName == "gccgo" && p1.Standard {
continue
}
if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil {
p.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath),
}
- pos := p.build.ImportPos[path]
+ pos := p.Internal.Build.ImportPos[path]
if len(pos) > 0 {
p.Error.Pos = pos[0].String()
}
}
path = p1.ImportPath
- importPaths[i] = path
+ ImportPaths[i] = path
if i < len(p.Imports) {
p.Imports[i] = path
}
save(path, p1)
imports = append(imports, p1)
- for _, dep := range p1.deps {
+ for _, dep := range p1.Internal.Deps {
save(dep.ImportPath, dep)
}
if p1.Incomplete {
p.Incomplete = true
}
}
- p.imports = imports
+ p.Internal.Imports = imports
p.Deps = make([]string, 0, len(deps))
for dep := range deps {
@@ -1088,21 +1122,21 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
if p1 == nil {
panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath)
}
- p.deps = append(p.deps, p1)
+ p.Internal.Deps = append(p.Internal.Deps, p1)
if p1.Error != nil {
p.DepsErrors = append(p.DepsErrors, p1.Error)
}
}
// unsafe is a fake package.
- if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
- p.target = ""
+ if p.Standard && (p.ImportPath == "unsafe" || cfg.BuildContext.Compiler == "gccgo") {
+ p.Internal.Target = ""
}
- p.Target = p.target
+ p.Target = p.Internal.Target
// If cgo is not enabled, ignore cgo supporting sources
// just as we ignore go files containing import "C".
- if !buildContext.CgoEnabled {
+ if !cfg.BuildContext.CgoEnabled {
p.CFiles = nil
p.CXXFiles = nil
p.MFiles = nil
@@ -1115,32 +1149,31 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
// The gc toolchain only permits C source files with cgo.
- if len(p.CFiles) > 0 && !p.usesCgo() && !p.usesSwig() && buildContext.Compiler == "gc" {
+ if len(p.CFiles) > 0 && !p.UsesCgo() && !p.UsesSwig() && cfg.BuildContext.Compiler == "gc" {
p.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: fmt.Sprintf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " ")),
}
return p
}
- // In the absence of errors lower in the dependency tree,
- // check for case-insensitive collisions of import paths.
- if len(p.DepsErrors) == 0 {
- dep1, dep2 := foldDup(p.Deps)
- if dep1 != "" {
- p.Error = &PackageError{
- ImportStack: stk.copy(),
- Err: fmt.Sprintf("case-insensitive import collision: %q and %q", dep1, dep2),
- }
- return p
+ // Check for case-insensitive collisions of import paths.
+ fold := str.ToFold(p.ImportPath)
+ if other := foldPath[fold]; other == "" {
+ foldPath[fold] = p.ImportPath
+ } else if other != p.ImportPath {
+ p.Error = &PackageError{
+ ImportStack: stk.Copy(),
+ Err: fmt.Sprintf("case-insensitive import collision: %q and %q", p.ImportPath, other),
}
+ return p
}
if p.BinaryOnly {
// For binary-only package, use build ID from supplied package binary.
- buildID, err := readBuildID(p)
+ buildID, err := buildid.ReadBuildID(p.Name, p.Target)
if err == nil {
- p.buildID = buildID
+ p.Internal.BuildID = buildID
}
} else {
computeBuildID(p)
@@ -1149,18 +1182,18 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
// usesSwig reports whether the package needs to run SWIG.
-func (p *Package) usesSwig() bool {
+func (p *Package) UsesSwig() bool {
return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
}
// usesCgo reports whether the package needs to run cgo
-func (p *Package) usesCgo() bool {
+func (p *Package) UsesCgo() bool {
return len(p.CgoFiles) > 0
}
// packageList returns the list of packages in the dag rooted at roots
// as visited in a depth-first post-order traversal.
-func packageList(roots []*Package) []*Package {
+func PackageList(roots []*Package) []*Package {
seen := map[*Package]bool{}
all := []*Package{}
var walk func(*Package)
@@ -1169,7 +1202,7 @@ func packageList(roots []*Package) []*Package {
return
}
seen[p] = true
- for _, p1 := range p.imports {
+ for _, p1 := range p.Internal.Imports {
walk(p1)
}
all = append(all, p)
@@ -1182,8 +1215,8 @@ func packageList(roots []*Package) []*Package {
// computeStale computes the Stale flag in the package dag that starts
// at the named pkgs (command-line arguments).
-func computeStale(pkgs ...*Package) {
- for _, p := range packageList(pkgs) {
+func ComputeStale(pkgs ...*Package) {
+ for _, p := range PackageList(pkgs) {
p.Stale, p.StaleReason = isStale(p)
}
}
@@ -1458,7 +1491,7 @@ var isGoRelease = strings.HasPrefix(runtime.Version(), "go1")
// isStale reports whether package p needs to be rebuilt,
// along with the reason why.
func isStale(p *Package) (bool, string) {
- if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
+ if p.Standard && (p.ImportPath == "unsafe" || cfg.BuildContext.Compiler == "gccgo") {
// fake, builtin package
return false, "builtin package"
}
@@ -1474,11 +1507,11 @@ func isStale(p *Package) (bool, string) {
// if a rebuild is needed, that rebuild attempt will produce a useful error.
// (Some commands, such as 'go list', do not attempt to rebuild.)
if p.BinaryOnly {
- if p.target == "" {
+ if p.Internal.Target == "" {
// Fail if a build is attempted.
return true, "no source code for package, but no install target"
}
- if _, err := os.Stat(p.target); err != nil {
+ if _, err := os.Stat(p.Internal.Target); err != nil {
// Fail if a build is attempted.
return true, "no source code for package, but cannot access install target: " + err.Error()
}
@@ -1486,17 +1519,17 @@ func isStale(p *Package) (bool, string) {
}
// If the -a flag is given, rebuild everything.
- if buildA {
+ if cfg.BuildA {
return true, "build -a flag in use"
}
// If there's no install target, we have to rebuild.
- if p.target == "" {
+ if p.Internal.Target == "" {
return true, "no install target"
}
// Package is stale if completely unbuilt.
- fi, err := os.Stat(p.target)
+ fi, err := os.Stat(p.Internal.Target)
if err != nil {
return true, "cannot stat install target"
}
@@ -1509,13 +1542,13 @@ func isStale(p *Package) (bool, string) {
// It also catches changes in toolchain, like when flipping between
// two versions of Go compiling a single GOPATH.
// See issue 8290 and issue 10702.
- targetBuildID, err := readBuildID(p)
- if err == nil && targetBuildID != p.buildID {
+ targetBuildID, err := buildid.ReadBuildID(p.Name, p.Target)
+ if err == nil && targetBuildID != p.Internal.BuildID {
return true, "build ID mismatch"
}
// Package is stale if a dependency is.
- for _, p1 := range p.deps {
+ for _, p1 := range p.Internal.Deps {
if p1.Stale {
return true, "stale dependency"
}
@@ -1553,8 +1586,8 @@ func isStale(p *Package) (bool, string) {
}
// Package is stale if a dependency is, or if a dependency is newer.
- for _, p1 := range p.deps {
- if p1.target != "" && olderThan(p1.target) {
+ for _, p1 := range p.Internal.Deps {
+ if p1.Internal.Target != "" && olderThan(p1.Internal.Target) {
return true, "newer dependency"
}
}
@@ -1572,11 +1605,11 @@ func isStale(p *Package) (bool, string) {
// and get a full rebuild anyway.
// Excluding $GOROOT used to also fix issue 4106, but that's now
// taken care of above (at least when the installed Go is a released version).
- if p.Root != goroot {
- if olderThan(buildToolchain.compiler()) {
+ if p.Root != cfg.GOROOT {
+ if olderThan(cfg.BuildToolchainCompiler()) {
return true, "newer compiler"
}
- if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
+ if p.Internal.Build.IsCommand() && olderThan(cfg.BuildToolchainLinker()) {
return true, "newer linker"
}
}
@@ -1619,7 +1652,7 @@ func isStale(p *Package) (bool, string) {
// to test for write access, and then skip GOPATH roots we don't have write
// access to. But hopefully we can just use the mtimes always.
- srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
+ srcs := str.StringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles)
for _, src := range srcs {
if olderThan(filepath.Join(p.Dir, src)) {
return true, "newer source file"
@@ -1629,7 +1662,7 @@ func isStale(p *Package) (bool, string) {
return false, ""
}
-// computeBuildID computes the build ID for p, leaving it in p.buildID.
+// computeBuildID computes the build ID for p, leaving it in p.Internal.BuildID.
// Build ID is a hash of the information we want to detect changes in.
// See the long comment in isStale for details.
func computeBuildID(p *Package) {
@@ -1637,11 +1670,12 @@ func computeBuildID(p *Package) {
// Include the list of files compiled as part of the package.
// This lets us detect removed files. See issue 3895.
- inputFiles := stringList(
+ inputFiles := str.StringList(
p.GoFiles,
p.CgoFiles,
p.CFiles,
p.CXXFiles,
+ p.FFiles,
p.MFiles,
p.HFiles,
p.SFiles,
@@ -1656,12 +1690,23 @@ func computeBuildID(p *Package) {
// Include the content of runtime/internal/sys/zversion.go in the hash
// for package runtime. This will give package runtime a
// different build ID in each Go release.
- if p.Standard && p.ImportPath == "runtime/internal/sys" && buildContext.Compiler != "gccgo" {
+ if p.Standard && p.ImportPath == "runtime/internal/sys" && cfg.BuildContext.Compiler != "gccgo" {
data, err := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go"))
- if err != nil {
- fatalf("go: %s", err)
+ if os.IsNotExist(err) {
+ p.Stale = true
+ p.StaleReason = fmt.Sprintf("missing zversion.go")
+ } else if err != nil {
+ base.Fatalf("go: %s", err)
}
fmt.Fprintf(h, "zversion %q\n", string(data))
+
+ // Add environment variables that affect code generation.
+ switch cfg.BuildContext.GOARCH {
+ case "arm":
+ fmt.Fprintf(h, "GOARM=%s\n", cfg.GOARM)
+ case "386":
+ fmt.Fprintf(h, "GO386=%s\n", cfg.GO386)
+ }
}
// Include the build IDs of any dependencies in the hash.
@@ -1672,22 +1717,26 @@ func computeBuildID(p *Package) {
// people use the same GOPATH but switch between
// different Go releases. See issue 10702.
// This is also a better fix for issue 8290.
- for _, p1 := range p.deps {
- fmt.Fprintf(h, "dep %s %s\n", p1.ImportPath, p1.buildID)
+ for _, p1 := range p.Internal.Deps {
+ fmt.Fprintf(h, "dep %s %s\n", p1.ImportPath, p1.Internal.BuildID)
}
- p.buildID = fmt.Sprintf("%x", h.Sum(nil))
+ p.Internal.BuildID = fmt.Sprintf("%x", h.Sum(nil))
}
-var cwd, _ = os.Getwd()
-
var cmdCache = map[string]*Package{}
+func ClearCmdCache() {
+ for name := range cmdCache {
+ delete(cmdCache, name)
+ }
+}
+
// loadPackage is like loadImport but is used for command-line arguments,
// not for paths found in import statements. In addition to ordinary import paths,
// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands
// in the Go command directory, as well as paths to those directories.
-func loadPackage(arg string, stk *importStack) *Package {
+func LoadPackage(arg string, stk *ImportStack) *Package {
if build.IsLocalImport(arg) {
dir := arg
if !filepath.IsAbs(dir) {
@@ -1696,7 +1745,7 @@ func loadPackage(arg string, stk *importStack) *Package {
dir = abs
}
}
- if sub, ok := hasSubdir(gorootSrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") {
+ if sub, ok := hasSubdir(cfg.GOROOTsrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") {
arg = sub
}
}
@@ -1704,24 +1753,24 @@ func loadPackage(arg string, stk *importStack) *Package {
if p := cmdCache[arg]; p != nil {
return p
}
- stk.push(arg)
- defer stk.pop()
+ stk.Push(arg)
+ defer stk.Pop()
- bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
+ bp, err := cfg.BuildContext.ImportDir(filepath.Join(cfg.GOROOTsrc, arg), 0)
bp.ImportPath = arg
bp.Goroot = true
- bp.BinDir = gorootBin
- if gobin != "" {
- bp.BinDir = gobin
+ bp.BinDir = cfg.GOROOTbin
+ if cfg.GOROOTbin != "" {
+ bp.BinDir = cfg.GOROOTbin
}
- bp.Root = goroot
- bp.SrcRoot = gorootSrc
+ bp.Root = cfg.GOROOT
+ bp.SrcRoot = cfg.GOROOTsrc
p := new(Package)
cmdCache[arg] = p
p.load(stk, bp, err)
if p.Error == nil && p.Name != "main" {
p.Error = &PackageError{
- ImportStack: stk.copy(),
+ ImportStack: stk.Copy(),
Err: fmt.Sprintf("expected package main but found package %s in %s", p.Name, p.Dir),
}
}
@@ -1735,28 +1784,28 @@ func loadPackage(arg string, stk *importStack) *Package {
// referring to io/ioutil rather than a hypothetical import of
// "./ioutil".
if build.IsLocalImport(arg) {
- bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
+ bp, _ := cfg.BuildContext.ImportDir(filepath.Join(base.Cwd, arg), build.FindOnly)
if bp.ImportPath != "" && bp.ImportPath != "." {
arg = bp.ImportPath
}
}
- return loadImport(arg, cwd, nil, stk, nil, 0)
+ return LoadImport(arg, base.Cwd, nil, stk, nil, 0)
}
// packages returns the packages named by the
-// command line arguments 'args'. If a named package
+// command line arguments 'args'. If a named package
// cannot be loaded at all (for example, if the directory does not exist),
// then packages prints an error and does not include that
// package in the results. However, if errors occur trying
// to load dependencies of a named package, the named
// package is still returned, with p.Incomplete = true
// and details in p.DepsErrors.
-func packages(args []string) []*Package {
+func Packages(args []string) []*Package {
var pkgs []*Package
- for _, pkg := range packagesAndErrors(args) {
+ for _, pkg := range PackagesAndErrors(args) {
if pkg.Error != nil {
- errorf("can't load package: %s", pkg.Error)
+ base.Errorf("can't load package: %s", pkg.Error)
continue
}
pkgs = append(pkgs, pkg)
@@ -1768,15 +1817,15 @@ func packages(args []string) []*Package {
// *Package for every argument, even the ones that
// cannot be loaded at all.
// The packages that fail to load will have p.Error != nil.
-func packagesAndErrors(args []string) []*Package {
+func PackagesAndErrors(args []string) []*Package {
if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
- return []*Package{goFilesPackage(args)}
+ return []*Package{GoFilesPackage(args)}
}
- args = importPaths(args)
+ args = ImportPaths(args)
var (
pkgs []*Package
- stk importStack
+ stk ImportStack
seenArg = make(map[string]bool)
seenPkg = make(map[*Package]bool)
)
@@ -1786,14 +1835,14 @@ func packagesAndErrors(args []string) []*Package {
continue
}
seenArg[arg] = true
- pkg := loadPackage(arg, &stk)
+ pkg := LoadPackage(arg, &stk)
if seenPkg[pkg] {
continue
}
seenPkg[pkg] = true
pkgs = append(pkgs, pkg)
}
- computeStale(pkgs...)
+ ComputeStale(pkgs...)
return pkgs
}
@@ -1801,12 +1850,12 @@ func packagesAndErrors(args []string) []*Package {
// packagesForBuild is like 'packages' but fails if any of
// the packages or their dependencies have errors
// (cannot be built).
-func packagesForBuild(args []string) []*Package {
- pkgs := packagesAndErrors(args)
+func PackagesForBuild(args []string) []*Package {
+ pkgs := PackagesAndErrors(args)
printed := map[*PackageError]bool{}
for _, pkg := range pkgs {
if pkg.Error != nil {
- errorf("can't load package: %s", pkg.Error)
+ base.Errorf("can't load package: %s", pkg.Error)
}
for _, err := range pkg.DepsErrors {
// Since these are errors in dependencies,
@@ -1815,11 +1864,11 @@ func packagesForBuild(args []string) []*Package {
// Only print each once.
if !printed[err] {
printed[err] = true
- errorf("%s", err)
+ base.Errorf("%s", err)
}
}
}
- exitIfErrors()
+ base.ExitIfErrors()
// Check for duplicate loads of the same package.
// That should be impossible, but if it does happen then
@@ -1828,223 +1877,95 @@ func packagesForBuild(args []string) []*Package {
// which doesn't work very well.
seen := map[string]bool{}
reported := map[string]bool{}
- for _, pkg := range packageList(pkgs) {
+ for _, pkg := range PackageList(pkgs) {
if seen[pkg.ImportPath] && !reported[pkg.ImportPath] {
reported[pkg.ImportPath] = true
- errorf("internal error: duplicate loads of %s", pkg.ImportPath)
+ base.Errorf("internal error: duplicate loads of %s", pkg.ImportPath)
}
seen[pkg.ImportPath] = true
}
- exitIfErrors()
+ base.ExitIfErrors()
return pkgs
}
-// 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
-}
-
-var (
- errBuildIDToolchain = fmt.Errorf("build ID only supported in gc toolchain")
- errBuildIDMalformed = fmt.Errorf("malformed object file")
- errBuildIDUnknown = fmt.Errorf("lost build ID")
-)
-
-var (
- bangArch = []byte("!")
- pkgdef = []byte("__.PKGDEF")
- goobject = []byte("go object ")
- buildid = []byte("build id ")
-)
-
-// readBuildID reads the build ID from an archive or binary.
-// It only supports the gc toolchain.
-// Other toolchain maintainers should adjust this function.
-func readBuildID(p *Package) (id string, err error) {
- if buildToolchain != (gcToolchain{}) {
- return "", errBuildIDToolchain
- }
-
- // For commands, read build ID directly from binary.
- if p.Name == "main" {
- return ReadBuildIDFromBinary(p.Target)
- }
-
- // Otherwise, we expect to have an archive (.a) file,
- // and we can read the build ID from the Go export data.
- if !strings.HasSuffix(p.Target, ".a") {
- return "", &os.PathError{Op: "parse", Path: p.Target, Err: errBuildIDUnknown}
- }
-
- // Read just enough of the target to fetch the build ID.
- // The archive is expected to look like:
- //
- // !
- // __.PKGDEF 0 0 0 644 7955 `
- // go object darwin amd64 devel X:none
- // build id "b41e5c45250e25c9fd5e9f9a1de7857ea0d41224"
- //
- // The variable-sized strings are GOOS, GOARCH, and the experiment list (X:none).
- // Reading the first 1024 bytes should be plenty.
- f, err := os.Open(p.Target)
- if err != nil {
- return "", err
- }
- data := make([]byte, 1024)
- n, err := io.ReadFull(f, data)
- f.Close()
-
- if err != nil && n == 0 {
- return "", err
+// GoFilesPackage creates a package for building a collection of Go files
+// (typically named on the command line). The target is named p.a for
+// package p or named after the first Go file for package main.
+func GoFilesPackage(gofiles []string) *Package {
+ // TODO: Remove this restriction.
+ for _, f := range gofiles {
+ if !strings.HasSuffix(f, ".go") {
+ base.Fatalf("named files must be .go files")
+ }
}
- bad := func() (string, error) {
- return "", &os.PathError{Op: "parse", Path: p.Target, Err: errBuildIDMalformed}
- }
+ var stk ImportStack
+ ctxt := cfg.BuildContext
+ ctxt.UseAllFiles = true
- // Archive header.
- for i := 0; ; i++ { // returns during i==3
- j := bytes.IndexByte(data, '\n')
- if j < 0 {
- return bad()
+ // Synthesize fake "directory" that only shows the named files,
+ // to make it look like this is a standard package or
+ // command directory. So that local imports resolve
+ // consistently, the files must all be in the same directory.
+ var dirent []os.FileInfo
+ var dir string
+ for _, file := range gofiles {
+ fi, err := os.Stat(file)
+ if err != nil {
+ base.Fatalf("%s", err)
}
- line := data[:j]
- data = data[j+1:]
- switch i {
- case 0:
- if !bytes.Equal(line, bangArch) {
- return bad()
- }
- case 1:
- if !bytes.HasPrefix(line, pkgdef) {
- return bad()
- }
- case 2:
- if !bytes.HasPrefix(line, goobject) {
- return bad()
- }
- case 3:
- if !bytes.HasPrefix(line, buildid) {
- // Found the object header, just doesn't have a build id line.
- // Treat as successful, with empty build id.
- return "", nil
- }
- id, err := strconv.Unquote(string(line[len(buildid):]))
- if err != nil {
- return bad()
- }
- return id, nil
+ if fi.IsDir() {
+ base.Fatalf("%s is a directory, should be a Go file", file)
}
+ dir1, _ := filepath.Split(file)
+ if dir1 == "" {
+ dir1 = "./"
+ }
+ if dir == "" {
+ dir = dir1
+ } else if dir != dir1 {
+ base.Fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
+ }
+ dirent = append(dirent, fi)
}
-}
+ ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil }
-var (
- goBuildPrefix = []byte("\xff Go build ID: \"")
- goBuildEnd = []byte("\"\n \xff")
-
- elfPrefix = []byte("\x7fELF")
-
- machoPrefixes = [][]byte{
- {0xfe, 0xed, 0xfa, 0xce},
- {0xfe, 0xed, 0xfa, 0xcf},
- {0xce, 0xfa, 0xed, 0xfe},
- {0xcf, 0xfa, 0xed, 0xfe},
+ var err error
+ if dir == "" {
+ dir = base.Cwd
}
-)
-
-var BuildIDReadSize = 32 * 1024 // changed for testing
-
-// ReadBuildIDFromBinary reads the build ID from a binary.
-//
-// ELF binaries store the build ID in a proper PT_NOTE section.
-//
-// Other binary formats are not so flexible. For those, the linker
-// stores the build ID as non-instruction bytes at the very beginning
-// of the text segment, which should appear near the beginning
-// of the file. This is clumsy but fairly portable. Custom locations
-// can be added for other binary types as needed, like we did for ELF.
-func ReadBuildIDFromBinary(filename string) (id string, err error) {
- if filename == "" {
- return "", &os.PathError{Op: "parse", Path: filename, Err: errBuildIDUnknown}
- }
-
- // Read the first 32 kB of the binary file.
- // That should be enough to find the build ID.
- // In ELF files, the build ID is in the leading headers,
- // which are typically less than 4 kB, not to mention 32 kB.
- // In Mach-O files, there's no limit, so we have to parse the file.
- // On other systems, we're trying to read enough that
- // we get the beginning of the text segment in the read.
- // The offset where the text segment begins in a hello
- // world compiled for each different object format today:
- //
- // Plan 9: 0x20
- // Windows: 0x600
- //
- f, err := os.Open(filename)
+ dir, err = filepath.Abs(dir)
if err != nil {
- return "", err
+ base.Fatalf("%s", err)
}
- defer f.Close()
- data := make([]byte, BuildIDReadSize)
- _, err = io.ReadFull(f, data)
- if err == io.ErrUnexpectedEOF {
- err = nil
- }
- if err != nil {
- return "", err
- }
+ bp, err := ctxt.ImportDir(dir, 0)
+ pkg := new(Package)
+ pkg.Internal.Local = true
+ pkg.Internal.Cmdline = true
+ stk.Push("main")
+ pkg.load(&stk, bp, err)
+ stk.Pop()
+ pkg.Internal.LocalPrefix = dirToImportPath(dir)
+ pkg.ImportPath = "command-line-arguments"
+ pkg.Internal.Target = ""
- if bytes.HasPrefix(data, elfPrefix) {
- return readELFGoBuildID(filename, f, data)
- }
- for _, m := range machoPrefixes {
- if bytes.HasPrefix(data, m) {
- return readMachoGoBuildID(filename, f, data)
+ if pkg.Name == "main" {
+ _, elem := filepath.Split(gofiles[0])
+ exe := elem[:len(elem)-len(".go")] + cfg.ExeSuffix
+ if cfg.BuildO == "" {
+ cfg.BuildO = exe
+ }
+ if cfg.GOBIN != "" {
+ pkg.Internal.Target = filepath.Join(cfg.GOBIN, exe)
}
}
- return readRawGoBuildID(filename, data)
-}
-
-// readRawGoBuildID finds the raw build ID stored in text segment data.
-func readRawGoBuildID(filename string, data []byte) (id string, err error) {
- i := bytes.Index(data, goBuildPrefix)
- if i < 0 {
- // Missing. Treat as successful but build ID empty.
- return "", nil
- }
-
- j := bytes.Index(data[i+len(goBuildPrefix):], goBuildEnd)
- if j < 0 {
- return "", &os.PathError{Op: "parse", Path: filename, Err: errBuildIDMalformed}
- }
-
- quoted := data[i+len(goBuildPrefix)-1 : i+len(goBuildPrefix)+j+1]
- id, err = strconv.Unquote(string(quoted))
- if err != nil {
- return "", &os.PathError{Op: "parse", Path: filename, Err: errBuildIDMalformed}
- }
+ pkg.Target = pkg.Internal.Target
+ pkg.Stale = true
+ pkg.StaleReason = "files named on command line"
- return id, nil
+ ComputeStale(pkg)
+ return pkg
}
diff --git a/libgo/go/cmd/go/internal/load/search.go b/libgo/go/cmd/go/internal/load/search.go
new file mode 100644
index 0000000..0c7d9ce
--- /dev/null
+++ b/libgo/go/cmd/go/internal/load/search.go
@@ -0,0 +1,338 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package load
+
+import (
+ "cmd/go/internal/cfg"
+ "fmt"
+ "go/build"
+ "log"
+ "os"
+ "path"
+ "path/filepath"
+ "regexp"
+ "strings"
+)
+
+// allPackages returns all the packages that can be found
+// under the $GOPATH directories and $GOROOT matching pattern.
+// The pattern is either "all" (all packages), "std" (standard packages),
+// "cmd" (standard commands), or a path including "...".
+func allPackages(pattern string) []string {
+ pkgs := MatchPackages(pattern)
+ if len(pkgs) == 0 {
+ fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+ }
+ return pkgs
+}
+
+// allPackagesInFS is like allPackages but is passed a pattern
+// beginning ./ or ../, meaning it should scan the tree rooted
+// at the given directory. There are ... in the pattern too.
+func allPackagesInFS(pattern string) []string {
+ pkgs := MatchPackagesInFS(pattern)
+ if len(pkgs) == 0 {
+ fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+ }
+ return pkgs
+}
+
+// MatchPackages returns a list of package paths matching pattern
+// (see go help packages for pattern syntax).
+func MatchPackages(pattern string) []string {
+ match := func(string) bool { return true }
+ treeCanMatch := func(string) bool { return true }
+ if !IsMetaPackage(pattern) {
+ match = matchPattern(pattern)
+ treeCanMatch = treeCanMatchPattern(pattern)
+ }
+
+ have := map[string]bool{
+ "builtin": true, // ignore pseudo-package that exists only for documentation
+ }
+ if !cfg.BuildContext.CgoEnabled {
+ have["runtime/cgo"] = true // ignore during walk
+ }
+ var pkgs []string
+
+ for _, src := range cfg.BuildContext.SrcDirs() {
+ if (pattern == "std" || pattern == "cmd") && src != cfg.GOROOTsrc {
+ continue
+ }
+ src = filepath.Clean(src) + string(filepath.Separator)
+ root := src
+ if pattern == "cmd" {
+ root += "cmd" + string(filepath.Separator)
+ }
+ filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
+ if err != nil || path == src {
+ return nil
+ }
+
+ want := true
+ // Avoid .foo, _foo, and testdata directory trees.
+ _, elem := filepath.Split(path)
+ if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
+ want = false
+ }
+
+ name := filepath.ToSlash(path[len(src):])
+ if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
+ // The name "std" is only the standard library.
+ // If the name is cmd, it's the root of the command tree.
+ want = false
+ }
+ if !treeCanMatch(name) {
+ want = false
+ }
+
+ if !fi.IsDir() {
+ if fi.Mode()&os.ModeSymlink != 0 && want {
+ if target, err := os.Stat(path); err == nil && target.IsDir() {
+ fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
+ }
+ }
+ return nil
+ }
+ if !want {
+ return filepath.SkipDir
+ }
+
+ if have[name] {
+ return nil
+ }
+ have[name] = true
+ if !match(name) {
+ return nil
+ }
+ pkg, err := cfg.BuildContext.ImportDir(path, 0)
+ if err != nil {
+ if _, noGo := err.(*build.NoGoError); noGo {
+ return nil
+ }
+ }
+
+ // If we are expanding "cmd", skip main
+ // packages under cmd/vendor. At least as of
+ // March, 2017, there is one there for the
+ // vendored pprof tool.
+ if pattern == "cmd" && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" {
+ return nil
+ }
+
+ pkgs = append(pkgs, name)
+ return nil
+ })
+ }
+ return pkgs
+}
+
+// MatchPackagesInFS returns a list of package paths matching pattern,
+// which must begin with ./ or ../
+// (see go help packages for pattern syntax).
+func MatchPackagesInFS(pattern string) []string {
+ // Find directory to begin the scan.
+ // Could be smarter but this one optimization
+ // is enough for now, since ... is usually at the
+ // end of a path.
+ i := strings.Index(pattern, "...")
+ dir, _ := path.Split(pattern[:i])
+
+ // pattern begins with ./ or ../.
+ // path.Clean will discard the ./ but not the ../.
+ // We need to preserve the ./ for pattern matching
+ // and in the returned import paths.
+ prefix := ""
+ if strings.HasPrefix(pattern, "./") {
+ prefix = "./"
+ }
+ match := matchPattern(pattern)
+
+ var pkgs []string
+ filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
+ if err != nil || !fi.IsDir() {
+ return nil
+ }
+ if path == dir {
+ // filepath.Walk starts at dir and recurses. For the recursive case,
+ // the path is the result of filepath.Join, which calls filepath.Clean.
+ // The initial case is not Cleaned, though, so we do this explicitly.
+ //
+ // This converts a path like "./io/" to "io". Without this step, running
+ // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
+ // package, because prepending the prefix "./" to the unclean path would
+ // result in "././io", and match("././io") returns false.
+ path = filepath.Clean(path)
+ }
+
+ // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
+ _, elem := filepath.Split(path)
+ dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
+ if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
+ return filepath.SkipDir
+ }
+
+ name := prefix + filepath.ToSlash(path)
+ if !match(name) {
+ return nil
+ }
+
+ // We keep the directory if we can import it, or if we can't import it
+ // due to invalid Go source files. This means that directories containing
+ // parse errors will be built (and fail) instead of being silently skipped
+ // as not matching the pattern. Go 1.5 and earlier skipped, but that
+ // behavior means people miss serious mistakes.
+ // See golang.org/issue/11407.
+ if p, err := cfg.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) {
+ if _, noGo := err.(*build.NoGoError); !noGo {
+ log.Print(err)
+ }
+ return nil
+ }
+ pkgs = append(pkgs, name)
+ return nil
+ })
+ return pkgs
+}
+
+// treeCanMatchPattern(pattern)(name) reports whether
+// name or children of name can possibly match pattern.
+// Pattern is the same limited glob accepted by matchPattern.
+func treeCanMatchPattern(pattern string) func(name string) bool {
+ wildCard := false
+ if i := strings.Index(pattern, "..."); i >= 0 {
+ wildCard = true
+ pattern = pattern[:i]
+ }
+ return func(name string) bool {
+ return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
+ wildCard && strings.HasPrefix(name, pattern)
+ }
+}
+
+// matchPattern(pattern)(name) reports whether
+// name matches pattern. Pattern is a limited glob
+// pattern in which '...' means 'any string' and there
+// is no other special syntax.
+// Unfortunately, there are two special cases. Quoting "go help packages":
+//
+// First, /... at the end of the pattern can match an empty string,
+// so that net/... matches both net and packages in its subdirectories, like net/http.
+// Second, any slash-separted pattern element containing a wildcard never
+// participates in a match of the "vendor" element in the path of a vendored
+// package, so that ./... does not match packages in subdirectories of
+// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
+// Note, however, that a directory named vendor that itself contains code
+// is not a vendored package: cmd/vendor would be a command named vendor,
+// and the pattern cmd/... matches it.
+func matchPattern(pattern string) func(name string) bool {
+ // Convert pattern to regular expression.
+ // The strategy for the trailing /... is to nest it in an explicit ? expression.
+ // The strategy for the vendor exclusion is to change the unmatchable
+ // vendor strings to a disallowed code point (vendorChar) and to use
+ // "(anything but that codepoint)*" as the implementation of the ... wildcard.
+ // This is a bit complicated but the obvious alternative,
+ // namely a hand-written search like in most shell glob matchers,
+ // is too easy to make accidentally exponential.
+ // Using package regexp guarantees linear-time matching.
+
+ const vendorChar = "\x00"
+
+ if strings.Contains(pattern, vendorChar) {
+ return func(name string) bool { return false }
+ }
+
+ re := regexp.QuoteMeta(pattern)
+ re = replaceVendor(re, vendorChar)
+ switch {
+ case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`):
+ re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)`
+ case re == vendorChar+`/\.\.\.`:
+ re = `(/vendor|/` + vendorChar + `/\.\.\.)`
+ case strings.HasSuffix(re, `/\.\.\.`):
+ re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?`
+ }
+ re = strings.Replace(re, `\.\.\.`, `[^`+vendorChar+`]*`, -1)
+
+ reg := regexp.MustCompile(`^` + re + `$`)
+
+ return func(name string) bool {
+ if strings.Contains(name, vendorChar) {
+ return false
+ }
+ return reg.MatchString(replaceVendor(name, vendorChar))
+ }
+}
+
+// replaceVendor returns the result of replacing
+// non-trailing vendor path elements in x with repl.
+func replaceVendor(x, repl string) string {
+ if !strings.Contains(x, "vendor") {
+ return x
+ }
+ elem := strings.Split(x, "/")
+ for i := 0; i < len(elem)-1; i++ {
+ if elem[i] == "vendor" {
+ elem[i] = repl
+ }
+ }
+ return strings.Join(elem, "/")
+}
+
+// ImportPaths returns the import paths to use for the given command line.
+func ImportPaths(args []string) []string {
+ args = ImportPathsNoDotExpansion(args)
+ var out []string
+ for _, a := range args {
+ if strings.Contains(a, "...") {
+ if build.IsLocalImport(a) {
+ out = append(out, allPackagesInFS(a)...)
+ } else {
+ out = append(out, allPackages(a)...)
+ }
+ continue
+ }
+ out = append(out, a)
+ }
+ return out
+}
+
+// ImportPathsNoDotExpansion returns the import paths to use for the given
+// command line, but it does no ... expansion.
+func ImportPathsNoDotExpansion(args []string) []string {
+ if len(args) == 0 {
+ return []string{"."}
+ }
+ var out []string
+ for _, a := range args {
+ // Arguments are supposed to be import paths, but
+ // as a courtesy to Windows developers, rewrite \ to /
+ // in command-line arguments. Handles .\... and so on.
+ if filepath.Separator == '\\' {
+ a = strings.Replace(a, `\`, `/`, -1)
+ }
+
+ // Put argument in canonical form, but preserve leading ./.
+ if strings.HasPrefix(a, "./") {
+ a = "./" + path.Clean(a)
+ if a == "./." {
+ a = "."
+ }
+ } else {
+ a = path.Clean(a)
+ }
+ if IsMetaPackage(a) {
+ out = append(out, allPackages(a)...)
+ continue
+ }
+ out = append(out, a)
+ }
+ return out
+}
+
+// isMetaPackage checks if name is a reserved package name that expands to multiple packages.
+func IsMetaPackage(name string) bool {
+ return name == "std" || name == "cmd" || name == "all"
+}
diff --git a/libgo/go/cmd/go/testgo.go b/libgo/go/cmd/go/internal/load/testgo.go
similarity index 97%
rename from libgo/go/cmd/go/testgo.go
rename to libgo/go/cmd/go/internal/load/testgo.go
index e507f34..7734048 100644
--- a/libgo/go/cmd/go/testgo.go
+++ b/libgo/go/cmd/go/internal/load/testgo.go
@@ -10,7 +10,7 @@
// +build testgo
-package main
+package load
import "os"
diff --git a/libgo/go/cmd/go/run.go b/libgo/go/cmd/go/internal/run/run.go
similarity index 52%
rename from libgo/go/cmd/go/run.go
rename to libgo/go/cmd/go/internal/run/run.go
index 18387b5..6e276c2 100644
--- a/libgo/go/cmd/go/run.go
+++ b/libgo/go/cmd/go/internal/run/run.go
@@ -2,34 +2,22 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package run implements the ``go run'' command.
+package run
import (
"fmt"
"os"
- "os/exec"
- "runtime"
"strings"
-)
-
-var execCmd []string // -exec flag, for run and test
-func findExecCmd() []string {
- if execCmd != nil {
- return execCmd
- }
- execCmd = []string{} // avoid work the second time
- if goos == runtime.GOOS && goarch == runtime.GOARCH {
- return execCmd
- }
- path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch))
- if err == nil {
- execCmd = []string{path}
- }
- return execCmd
-}
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
+ "cmd/go/internal/work"
+)
-var cmdRun = &Command{
+var CmdRun = &base.Command{
UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
Short: "compile and run Go program",
Long: `
@@ -53,60 +41,60 @@ See also: go build.
}
func init() {
- cmdRun.Run = runRun // break init loop
+ CmdRun.Run = runRun // break init loop
- addBuildFlags(cmdRun)
- cmdRun.Flag.Var((*stringsFlag)(&execCmd), "exec", "")
+ work.AddBuildFlags(CmdRun)
+ CmdRun.Flag.Var((*base.StringsFlag)(&work.ExecCmd), "exec", "")
}
func printStderr(args ...interface{}) (int, error) {
return fmt.Fprint(os.Stderr, args...)
}
-func runRun(cmd *Command, args []string) {
- instrumentInit()
- buildModeInit()
- var b builder
- b.init()
- b.print = printStderr
+func runRun(cmd *base.Command, args []string) {
+ work.InstrumentInit()
+ work.BuildModeInit()
+ var b work.Builder
+ b.Init()
+ b.Print = printStderr
i := 0
for i < len(args) && strings.HasSuffix(args[i], ".go") {
i++
}
files, cmdArgs := args[:i], args[i:]
if len(files) == 0 {
- fatalf("go run: no go files listed")
+ base.Fatalf("go run: no go files listed")
}
for _, file := range files {
if strings.HasSuffix(file, "_test.go") {
- // goFilesPackage is going to assign this to TestGoFiles.
+ // GoFilesPackage is going to assign this to TestGoFiles.
// Reject since it won't be part of the build.
- fatalf("go run: cannot run *_test.go files (%s)", file)
+ base.Fatalf("go run: cannot run *_test.go files (%s)", file)
}
}
- p := goFilesPackage(files)
+ p := load.GoFilesPackage(files)
if p.Error != nil {
- fatalf("%s", p.Error)
+ base.Fatalf("%s", p.Error)
}
- p.omitDWARF = true
+ p.Internal.OmitDebug = true
if len(p.DepsErrors) > 0 {
// Since these are errors in dependencies,
// the same error might show up multiple times,
// once in each package that depends on it.
// Only print each once.
- printed := map[*PackageError]bool{}
+ printed := map[*load.PackageError]bool{}
for _, err := range p.DepsErrors {
if !printed[err] {
printed[err] = true
- errorf("%s", err)
+ base.Errorf("%s", err)
}
}
}
- exitIfErrors()
+ base.ExitIfErrors()
if p.Name != "main" {
- fatalf("go run: cannot run non-main package")
+ base.Fatalf("go run: cannot run non-main package")
}
- p.target = "" // must build - not up to date
+ p.Internal.Target = "" // must build - not up to date
var src string
if len(p.GoFiles) > 0 {
src = p.GoFiles[0]
@@ -116,41 +104,28 @@ func runRun(cmd *Command, args []string) {
// this case could only happen if the provided source uses cgo
// while cgo is disabled.
hint := ""
- if !buildContext.CgoEnabled {
+ if !cfg.BuildContext.CgoEnabled {
hint = " (cgo is disabled)"
}
- fatalf("go run: no suitable source files%s", hint)
+ base.Fatalf("go run: no suitable source files%s", hint)
}
- p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file
- a1 := b.action(modeBuild, modeBuild, p)
- a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
- b.do(a)
+ p.Internal.ExeName = src[:len(src)-len(".go")] // name temporary executable for first go file
+ a1 := b.Action(work.ModeBuild, work.ModeBuild, p)
+ a := &work.Action{Func: buildRunProgram, Args: cmdArgs, Deps: []*work.Action{a1}}
+ b.Do(a)
}
-// runProgram is the action for running a binary that has already
+// buildRunProgram is the action for running a binary that has already
// been compiled. We ignore exit status.
-func (b *builder) runProgram(a *action) error {
- cmdline := stringList(findExecCmd(), a.deps[0].target, a.args)
- if buildN || buildX {
- b.showcmd("", "%s", strings.Join(cmdline, " "))
- if buildN {
+func buildRunProgram(b *work.Builder, a *work.Action) error {
+ cmdline := str.StringList(work.FindExecCmd(), a.Deps[0].Target, a.Args)
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd("", "%s", strings.Join(cmdline, " "))
+ if cfg.BuildN {
return nil
}
}
- runStdin(cmdline)
+ base.RunStdin(cmdline)
return nil
}
-
-// runStdin is like run, but connects Stdin.
-func runStdin(cmdline []string) {
- cmd := exec.Command(cmdline[0], cmdline[1:]...)
- cmd.Stdin = os.Stdin
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- cmd.Env = origEnv
- startSigHandlers()
- if err := cmd.Run(); err != nil {
- errorf("%v", err)
- }
-}
diff --git a/libgo/go/cmd/go/internal/str/str.go b/libgo/go/cmd/go/internal/str/str.go
new file mode 100644
index 0000000..0413ed8
--- /dev/null
+++ b/libgo/go/cmd/go/internal/str/str.go
@@ -0,0 +1,141 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package str provides string manipulation utilities.
+package str
+
+import (
+ "bytes"
+ "fmt"
+ "unicode"
+ "unicode/utf8"
+)
+
+// StringList flattens its arguments into a single []string.
+// Each argument in args must have type string or []string.
+func StringList(args ...interface{}) []string {
+ var x []string
+ for _, arg := range args {
+ switch arg := arg.(type) {
+ case []string:
+ x = append(x, arg...)
+ case string:
+ x = append(x, arg)
+ default:
+ panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
+ }
+ }
+ return x
+}
+
+// ToFold returns a string with the property that
+// strings.EqualFold(s, t) iff ToFold(s) == ToFold(t)
+// This lets us test a large set of strings for fold-equivalent
+// duplicates without making a quadratic number of calls
+// to EqualFold. Note that strings.ToUpper and strings.ToLower
+// do not have the desired property in some corner cases.
+func ToFold(s string) string {
+ // Fast path: all ASCII, no upper case.
+ // Most paths look like this already.
+ for i := 0; i < len(s); i++ {
+ c := s[i]
+ if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' {
+ goto Slow
+ }
+ }
+ return s
+
+Slow:
+ var buf bytes.Buffer
+ for _, r := range s {
+ // SimpleFold(x) cycles to the next equivalent rune > x
+ // or wraps around to smaller values. Iterate until it wraps,
+ // and we've found the minimum value.
+ for {
+ r0 := r
+ r = unicode.SimpleFold(r0)
+ if r <= r0 {
+ break
+ }
+ }
+ // Exception to allow fast path above: A-Z => a-z
+ if 'A' <= r && r <= 'Z' {
+ r += 'a' - 'A'
+ }
+ buf.WriteRune(r)
+ }
+ return buf.String()
+}
+
+// FoldDup reports a pair of strings from the list that are
+// equal according to strings.EqualFold.
+// It returns "", "" if there are no such strings.
+func FoldDup(list []string) (string, string) {
+ clash := map[string]string{}
+ for _, s := range list {
+ fold := ToFold(s)
+ if t := clash[fold]; t != "" {
+ if s > t {
+ s, t = t, s
+ }
+ return s, t
+ }
+ clash[fold] = s
+ }
+ return "", ""
+}
+
+// Contains reports whether x contains s.
+func Contains(x []string, s string) bool {
+ for _, t := range x {
+ if t == s {
+ return true
+ }
+ }
+ return false
+}
+
+func isSpaceByte(c byte) bool {
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r'
+}
+
+// SplitQuotedFields splits s into a list of fields,
+// allowing single or double quotes around elements.
+// There is no unescaping or other processing within
+// quoted fields.
+func SplitQuotedFields(s string) ([]string, error) {
+ // Split fields allowing '' or "" around elements.
+ // Quotes further inside the string do not count.
+ var f []string
+ for len(s) > 0 {
+ for len(s) > 0 && isSpaceByte(s[0]) {
+ s = s[1:]
+ }
+ if len(s) == 0 {
+ break
+ }
+ // Accepted quoted string. No unescaping inside.
+ if s[0] == '"' || s[0] == '\'' {
+ quote := s[0]
+ s = s[1:]
+ i := 0
+ for i < len(s) && s[i] != quote {
+ i++
+ }
+ if i >= len(s) {
+ return nil, fmt.Errorf("unterminated %c string", quote)
+ }
+ f = append(f, s[:i])
+ s = s[i+1:]
+ continue
+ }
+ i := 0
+ for i < len(s) && !isSpaceByte(s[i]) {
+ i++
+ }
+ f = append(f, s[:i])
+ s = s[i:]
+ }
+ return f, nil
+}
diff --git a/libgo/go/cmd/go/test.go b/libgo/go/cmd/go/internal/test/test.go
similarity index 71%
rename from libgo/go/cmd/go/test.go
rename to libgo/go/cmd/go/internal/test/test.go
index 12990fe..c1e66f9e 100644
--- a/libgo/go/cmd/go/test.go
+++ b/libgo/go/cmd/go/internal/test/test.go
@@ -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 main
+package test
import (
"bytes"
@@ -25,16 +25,22 @@ import (
"time"
"unicode"
"unicode/utf8"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
+ "cmd/go/internal/work"
)
// Break init loop.
func init() {
- cmdTest.Run = runTest
+ CmdTest.Run = runTest
}
const testUsage = "test [build/test flags] [packages] [build/test flags & test binary flags]"
-var cmdTest = &Command{
+var CmdTest = &base.Command{
CustomFlags: true,
UsageLine: testUsage,
Short: "test packages",
@@ -53,7 +59,7 @@ followed by detailed output for each failed package.
the file pattern "*_test.go".
Files whose names begin with "_" (including "_test.go") or "." are ignored.
These additional files can contain test functions, benchmark functions, and
-example functions. See 'go help testfunc' for more.
+example functions. See 'go help testfunc' for more.
Each listed package causes the execution of a separate test binary.
Test files that declare a package with the suffix "_test" will be compiled as a
@@ -62,7 +68,7 @@ separate package, and then linked and run with the main test binary.
The go tool will ignore a directory named "testdata", making it available
to hold ancillary data needed by the tests.
-By default, go test needs no arguments. It compiles and tests the package
+By default, go test needs no arguments. It compiles and tests the package
with source in the current directory, including tests, and runs the tests.
The package is built in a temporary directory so it does not interfere with the
@@ -107,7 +113,15 @@ The test binary also accepts flags that control execution of the test; these
flags are also accessible by 'go test'.
`
-var helpTestflag = &Command{
+// Usage prints the usage message for 'go test -h' and exits.
+func Usage() {
+ os.Stderr.WriteString(testUsage + "\n\n" +
+ strings.TrimSpace(testFlag1) + "\n\n\t" +
+ strings.TrimSpace(testFlag2) + "\n")
+ os.Exit(2)
+}
+
+var HelpTestflag = &base.Command{
UsageLine: "testflag",
Short: "description of testing flags",
Long: `
@@ -116,7 +130,7 @@ and flags that apply to the resulting test binary.
Several of the flags control profiling and write an execution profile
suitable for "go tool pprof"; run "go tool pprof -h" for more
-information. The --alloc_space, --alloc_objects, and --show_bytes
+information. The --alloc_space, --alloc_objects, and --show_bytes
options of pprof control how the information is presented.
The following flags are recognized by the 'go test' command and
@@ -128,12 +142,17 @@ control the execution of any test:
const testFlag2 = `
-bench regexp
- Run (sub)benchmarks matching a regular expression.
- The given regular expression is split into smaller ones by
- top-level '/', where each must match the corresponding part of a
- benchmark's identifier.
- By default, no benchmarks run. To run all benchmarks,
- use '-bench .' or '-bench=.'.
+ Run only those benchmarks matching a regular expression.
+ By default, no benchmarks are run.
+ To run all benchmarks, use '-bench .' or '-bench=.'.
+ The regular expression is split by unbracketed slash (/)
+ characters into a sequence of regular expressions, and each
+ part of a benchmark's identifier must match the corresponding
+ element in the sequence, if any. Possible parents of matches
+ are run with b.N=1 to identify sub-benchmarks. For example,
+ given -bench=X/Y, top-level benchmarks matching X are run
+ with b.N=1 to find any sub-benchmarks matching Y, which are
+ then run in full.
-benchtime t
Run enough iterations of each benchmark to take t, specified
@@ -147,6 +166,10 @@ const testFlag2 = `
-cover
Enable coverage analysis.
+ Note that because coverage works by annotating the source
+ code before compilation, compilation and test failures with
+ coverage enabled may report line numbers that don't correspond
+ to the original sources.
-covermode set,count,atomic
Set the mode for coverage analysis for the package[s]
@@ -167,9 +190,14 @@ const testFlag2 = `
-cpu 1,2,4
Specify a list of GOMAXPROCS values for which the tests or
- benchmarks should be executed. The default is the current value
+ benchmarks should be executed. The default is the current value
of GOMAXPROCS.
+ -list regexp
+ List tests, benchmarks, or examples matching the regular expression.
+ No tests, benchmarks or examples will be run. This will only
+ list top-level tests. No subtest or subbenchmarks will be shown.
+
-parallel n
Allow parallel execution of test functions that call t.Parallel.
The value of this flag is the maximum number of tests to run
@@ -181,9 +209,13 @@ const testFlag2 = `
-run regexp
Run only those tests and examples matching the regular expression.
- For tests the regular expression is split into smaller ones by
- top-level '/', where each must match the corresponding part of a
- test's identifier.
+ For tests, the regular expression is split by unbracketed slash (/)
+ characters into a sequence of regular expressions, and each part
+ of a test's identifier must match the corresponding element in
+ the sequence, if any. Note that possible parents of matches are
+ run too, so that -run=X/Y matches and runs and reports the result
+ of all tests matching X, even those without sub-tests matching Y,
+ because it must run them to look for those sub-tests.
-short
Tell long-running tests to shorten their run time.
@@ -191,8 +223,8 @@ const testFlag2 = `
the Go tree can run a sanity check but not spend time running
exhaustive tests.
- -timeout t
- If a test runs longer than t, panic.
+ -timeout d
+ If a test binary runs longer than duration d, panic.
The default is 10 minutes (10m).
-v
@@ -215,7 +247,7 @@ profile the tests during execution:
calling runtime.SetBlockProfileRate with n.
See 'go doc runtime.SetBlockProfileRate'.
The profiler aims to sample, on average, one blocking event every
- n nanoseconds the program spends blocked. By default,
+ n nanoseconds the program spends blocked. By default,
if -test.blockprofile is set without this flag, all blocking events
are recorded, equivalent to -test.blockprofilerate=1.
@@ -233,7 +265,7 @@ profile the tests during execution:
-memprofilerate n
Enable more precise (and expensive) memory profiles by setting
- runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
+ runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
To profile all memory allocations, use -test.memprofilerate=1
and pass --alloc_space flag to the pprof tool.
@@ -312,7 +344,7 @@ In the second example, the argument math is passed through to the test
binary, instead of being interpreted as the package list.
`
-var helpTestfunc = &Command{
+var HelpTestfunc = &base.Command{
UsageLine: "testfunc",
Short: "description of testing functions",
Long: `
@@ -338,8 +370,8 @@ comment is compiled but not executed. An example with no text after
"Output:" is compiled, executed, and expected to produce no output.
Godoc displays the body of ExampleXXX to demonstrate the use
-of the function, constant, or variable XXX. An example of a method M with
-receiver type T or *T is named ExampleT_M. There may be multiple examples
+of the function, constant, or variable XXX. An example of a method M with
+receiver type T or *T is named ExampleT_M. There may be multiple examples
for a given function, constant, or variable, distinguished by a trailing _xxx,
where xxx is a suffix not beginning with an upper case letter.
@@ -374,18 +406,19 @@ See the documentation of the testing package for more information.
}
var (
- testC bool // -c flag
- testCover bool // -cover flag
- testCoverMode string // -covermode flag
- testCoverPaths []string // -coverpkg flag
- testCoverPkgs []*Package // -coverpkg flag
- testO string // -o flag
- testProfile bool // some profiling flag
- testNeedBinary bool // profile needs to keep binary around
- testV bool // -v flag
- testTimeout string // -timeout flag
+ testC bool // -c flag
+ testCover bool // -cover flag
+ testCoverMode string // -covermode flag
+ testCoverPaths []string // -coverpkg flag
+ testCoverPkgs []*load.Package // -coverpkg flag
+ testO string // -o flag
+ testProfile bool // some profiling flag
+ testNeedBinary bool // profile needs to keep binary around
+ testV bool // -v flag
+ testTimeout string // -timeout flag
testArgs []string
testBench bool
+ testList bool
testStreamOutput bool // show output as it is generated
testShowPass bool // show passing output
@@ -399,27 +432,27 @@ var testMainDeps = map[string]bool{
"os": true,
}
-func runTest(cmd *Command, args []string) {
+func runTest(cmd *base.Command, args []string) {
var pkgArgs []string
pkgArgs, testArgs = testFlags(args)
- findExecCmd() // initialize cached result
+ work.FindExecCmd() // initialize cached result
- instrumentInit()
- buildModeInit()
- pkgs := packagesForBuild(pkgArgs)
+ work.InstrumentInit()
+ work.BuildModeInit()
+ pkgs := load.PackagesForBuild(pkgArgs)
if len(pkgs) == 0 {
- fatalf("no packages to test")
+ base.Fatalf("no packages to test")
}
if testC && len(pkgs) != 1 {
- fatalf("cannot use -c flag with multiple packages")
+ base.Fatalf("cannot use -c flag with multiple packages")
}
if testO != "" && len(pkgs) != 1 {
- fatalf("cannot use -o flag with multiple packages")
+ base.Fatalf("cannot use -o flag with multiple packages")
}
if testProfile && len(pkgs) != 1 {
- fatalf("cannot use test profile flag with multiple packages")
+ base.Fatalf("cannot use test profile flag with multiple packages")
}
// If a test timeout was given and is parseable, set our kill timeout
@@ -433,7 +466,7 @@ func runTest(cmd *Command, args []string) {
// show passing test output (after buffering) with -v flag.
// must buffer because tests are running in parallel, and
// otherwise the output will get mixed.
- testShowPass = testV
+ testShowPass = testV || testList
// stream test output (no buffering) when no package has
// been given on the command line (implicit current directory)
@@ -443,18 +476,18 @@ func runTest(cmd *Command, args []string) {
// In these cases, streaming the output produces the same result
// as not streaming, just more immediately.
testStreamOutput = len(pkgArgs) == 0 || testBench ||
- (testShowPass && (len(pkgs) == 1 || buildP == 1))
+ (testShowPass && (len(pkgs) == 1 || cfg.BuildP == 1))
// For 'go test -i -o x.test', we want to build x.test. Imply -c to make the logic easier.
- if buildI && testO != "" {
+ if cfg.BuildI && testO != "" {
testC = true
}
- var b builder
- b.init()
+ var b work.Builder
+ b.Init()
- if buildI {
- buildV = testV
+ if cfg.BuildI {
+ cfg.BuildV = testV
deps := make(map[string]bool)
for dep := range testMainDeps {
@@ -466,10 +499,10 @@ func runTest(cmd *Command, args []string) {
for _, path := range p.Imports {
deps[path] = true
}
- for _, path := range p.vendored(p.TestImports) {
+ for _, path := range p.Vendored(p.TestImports) {
deps[path] = true
}
- for _, path := range p.vendored(p.XTestImports) {
+ for _, path := range p.Vendored(p.XTestImports) {
deps[path] = true
}
}
@@ -478,7 +511,7 @@ func runTest(cmd *Command, args []string) {
if deps["C"] {
delete(deps, "C")
deps["runtime/cgo"] = true
- if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan {
+ if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH && !cfg.BuildRace && !cfg.BuildMSan {
deps["cmd/cgo"] = true
}
}
@@ -493,26 +526,26 @@ func runTest(cmd *Command, args []string) {
}
sort.Strings(all)
- a := &action{}
- for _, p := range packagesForBuild(all) {
- if !reqStdPkgSrc && p.Standard {
+ a := &work.Action{}
+ for _, p := range load.PackagesForBuild(all) {
+ if cfg.BuildToolchainName == "gccgo" && p.Standard {
continue
}
- a.deps = append(a.deps, b.action(modeInstall, modeInstall, p))
+ a.Deps = append(a.Deps, b.Action(work.ModeInstall, work.ModeInstall, p))
}
- b.do(a)
- if !testC || a.failed {
+ b.Do(a)
+ if !testC || a.Failed {
return
}
- b.init()
+ b.Init()
}
- var builds, runs, prints []*action
+ var builds, runs, prints []*work.Action
if testCoverPaths != nil {
// Load packages that were asked about for coverage.
// packagesForBuild exits if the packages cannot be loaded.
- testCoverPkgs = packagesForBuild(testCoverPaths)
+ testCoverPkgs = load.PackagesForBuild(testCoverPaths)
// Warn about -coverpkg arguments that are not actually used.
used := make(map[string]bool)
@@ -536,13 +569,13 @@ func runTest(cmd *Command, args []string) {
}
p.Stale = true // rebuild
p.StaleReason = "rebuild for coverage"
- p.fake = true // do not warn about rebuild
- p.coverMode = testCoverMode
+ p.Internal.Fake = true // do not warn about rebuild
+ p.Internal.CoverMode = testCoverMode
var coverFiles []string
coverFiles = append(coverFiles, p.GoFiles...)
coverFiles = append(coverFiles, p.CgoFiles...)
coverFiles = append(coverFiles, p.TestGoFiles...)
- p.coverVars = declareCoverVars(p.ImportPath, coverFiles...)
+ p.Internal.CoverVars = declareCoverVars(p.ImportPath, coverFiles...)
}
}
@@ -552,7 +585,8 @@ func runTest(cmd *Command, args []string) {
if testCover && testCoverMode == "atomic" {
ensureImport(p, "sync/atomic")
}
- buildTest, runTest, printTest, err := b.test(p)
+
+ buildTest, runTest, printTest, err := builderTest(&b, p)
if err != nil {
str := err.Error()
if strings.HasPrefix(str, "\n") {
@@ -561,9 +595,9 @@ func runTest(cmd *Command, args []string) {
failed := fmt.Sprintf("FAIL\t%s [setup failed]\n", p.ImportPath)
if p.ImportPath != "" {
- errorf("# %s\n%s\n%s", p.ImportPath, str, failed)
+ base.Errorf("# %s\n%s\n%s", p.ImportPath, str, failed)
} else {
- errorf("%s\n%s", str, failed)
+ base.Errorf("%s\n%s", str, failed)
}
continue
}
@@ -573,13 +607,13 @@ func runTest(cmd *Command, args []string) {
}
// Ultimately the goal is to print the output.
- root := &action{deps: prints}
+ root := &work.Action{Deps: prints}
// Force the printing of results to happen in order,
// one at a time.
for i, a := range prints {
if i > 0 {
- a.deps = append(a.deps, prints[i-1])
+ a.Deps = append(a.Deps, prints[i-1])
}
}
@@ -589,40 +623,40 @@ func runTest(cmd *Command, args []string) {
// Later runs must wait for the previous run's print.
for i, run := range runs {
if i == 0 {
- run.deps = append(run.deps, builds...)
+ run.Deps = append(run.Deps, builds...)
} else {
- run.deps = append(run.deps, prints[i-1])
+ run.Deps = append(run.Deps, prints[i-1])
}
}
}
// If we are building any out-of-date packages other
// than those under test, warn.
- okBuild := map[*Package]bool{}
+ okBuild := map[*load.Package]bool{}
for _, p := range pkgs {
okBuild[p] = true
}
warned := false
- for _, a := range actionList(root) {
- if a.p == nil || okBuild[a.p] {
+ for _, a := range work.ActionList(root) {
+ if a.Package == nil || okBuild[a.Package] {
continue
}
- okBuild[a.p] = true // warn at most once
+ okBuild[a.Package] = true // warn at most once
// Don't warn about packages being rebuilt because of
// things like coverage analysis.
- for _, p1 := range a.p.imports {
- if p1.fake {
- a.p.fake = true
+ for _, p1 := range a.Package.Internal.Imports {
+ if p1.Internal.Fake {
+ a.Package.Internal.Fake = true
}
}
- if a.f != nil && !okBuild[a.p] && !a.p.fake && !a.p.local {
+ if a.Func != nil && !okBuild[a.Package] && !a.Package.Internal.Fake && !a.Package.Internal.Local {
if !warned {
fmt.Fprintf(os.Stderr, "warning: building out-of-date packages:\n")
warned = true
}
- fmt.Fprintf(os.Stderr, "\t%s\n", a.p.ImportPath)
+ fmt.Fprintf(os.Stderr, "\t%s\n", a.Package.ImportPath)
}
}
if warned {
@@ -631,42 +665,33 @@ func runTest(cmd *Command, args []string) {
args = " " + args
}
extraOpts := ""
- if buildRace {
+ if cfg.BuildRace {
extraOpts = "-race "
}
- if buildMSan {
+ if cfg.BuildMSan {
extraOpts = "-msan "
}
fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\n\n", extraOpts, args)
}
- b.do(root)
+ b.Do(root)
}
-// ensures that package p imports the named package.
-func ensureImport(p *Package, pkg string) {
- for _, d := range p.deps {
+// ensures that package p imports the named package
+func ensureImport(p *load.Package, pkg string) {
+ for _, d := range p.Internal.Deps {
if d.Name == pkg {
return
}
}
- a := loadPackage(pkg, &importStack{})
+ a := load.LoadPackage(pkg, &load.ImportStack{})
if a.Error != nil {
- fatalf("load %s: %v", pkg, a.Error)
+ base.Fatalf("load %s: %v", pkg, a.Error)
}
- computeStale(a)
-
- p.imports = append(p.imports, a)
-}
+ load.ComputeStale(a)
-func contains(x []string, s string) bool {
- for _, t := range x {
- if t == s {
- return true
- }
- }
- return false
+ p.Internal.Imports = append(p.Internal.Imports, a)
}
var windowsBadWords = []string{
@@ -676,11 +701,11 @@ var windowsBadWords = []string{
"update",
}
-func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) {
+func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, printAction *work.Action, err error) {
if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
- build := b.action(modeBuild, modeBuild, p)
- run := &action{p: p, deps: []*action{build}}
- print := &action{f: (*builder).notest, p: p, deps: []*action{run}}
+ build := b.Action(work.ModeBuild, work.ModeBuild, p)
+ run := &work.Action{Package: p, Deps: []*work.Action{build}}
+ print := &work.Action{Func: builderNoTest, Package: p, Deps: []*work.Action{run}}
return build, run, print, nil
}
@@ -688,14 +713,14 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// ptest - package + test files
// pxtest - package of external test files
// pmain - pkg.test binary
- var ptest, pxtest, pmain *Package
+ var ptest, pxtest, pmain *load.Package
- var imports, ximports []*Package
- var stk importStack
- stk.push(p.ImportPath + " (test)")
+ var imports, ximports []*load.Package
+ var stk load.ImportStack
+ stk.Push(p.ImportPath + " (test)")
for i, path := range p.TestImports {
- p1 := loadImport(path, p.Dir, p, &stk, p.build.TestImportPos[path], useVendor)
- if !reqStdPkgSrc && p1.Standard {
+ p1 := load.LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], load.UseVendor)
+ if cfg.BuildToolchainName == "gccgo" && p1.Standard {
continue
}
if p1.Error != nil {
@@ -706,26 +731,26 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
err.Pos = "" // show full import stack
return nil, nil, nil, err
}
- if contains(p1.Deps, p.ImportPath) || p1.ImportPath == p.ImportPath {
+ 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{
+ err := &load.PackageError{
ImportStack: testImportStack(stk[0], p1, p.ImportPath),
Err: "import cycle not allowed in test",
- isImportCycle: true,
+ IsImportCycle: true,
}
return nil, nil, nil, err
}
p.TestImports[i] = p1.ImportPath
imports = append(imports, p1)
}
- stk.pop()
- stk.push(p.ImportPath + "_test")
+ stk.Pop()
+ stk.Push(p.ImportPath + "_test")
pxtestNeedsPtest := false
for i, path := range p.XTestImports {
- p1 := loadImport(path, p.Dir, p, &stk, p.build.XTestImportPos[path], useVendor)
- if !reqStdPkgSrc && p1.Standard {
+ p1 := load.LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], load.UseVendor)
+ if cfg.BuildToolchainName == "gccgo" && p1.Standard {
continue
}
if p1.Error != nil {
@@ -743,7 +768,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
}
p.XTestImports[i] = p1.ImportPath
}
- stk.pop()
+ stk.Pop()
// Use last element of import path, not package name.
// They differ when package name is "main".
@@ -771,12 +796,12 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// $WORK/unicode/utf8/_test/unicode/utf8.a.
// We write the external test package archive to
// $WORK/unicode/utf8/_test/unicode/utf8_test.a.
- testDir := filepath.Join(b.work, filepath.FromSlash(p.ImportPath+"/_test"))
- ptestObj := buildToolchain.pkgpath(testDir, p)
+ testDir := filepath.Join(b.WorkDir, filepath.FromSlash(p.ImportPath+"/_test"))
+ ptestObj := work.BuildToolchain.Pkgpath(testDir, p)
// Create the directory for the .a files.
ptestDir, _ := filepath.Split(ptestObj)
- if err := b.mkdir(ptestDir); err != nil {
+ if err := b.Mkdir(ptestDir); err != nil {
return nil, nil, nil, err
}
@@ -788,36 +813,36 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// Test package.
if len(p.TestGoFiles) > 0 || localCover || p.Name == "main" {
- ptest = new(Package)
+ ptest = new(load.Package)
*ptest = *p
ptest.GoFiles = nil
ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...)
ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...)
- ptest.target = ""
- ptest.Imports = stringList(p.Imports, p.TestImports)
- ptest.imports = append(append([]*Package{}, p.imports...), imports...)
- ptest.pkgdir = testDir
- ptest.fake = true
- ptest.forceLibrary = true
+ ptest.Internal.Target = ""
+ ptest.Imports = str.StringList(p.Imports, p.TestImports)
+ ptest.Internal.Imports = append(append([]*load.Package{}, p.Internal.Imports...), imports...)
+ ptest.Internal.Pkgdir = testDir
+ ptest.Internal.Fake = true
+ ptest.Internal.ForceLibrary = true
ptest.Stale = true
ptest.StaleReason = "rebuild for test"
- ptest.build = new(build.Package)
- *ptest.build = *p.build
+ ptest.Internal.Build = new(build.Package)
+ *ptest.Internal.Build = *p.Internal.Build
m := map[string][]token.Position{}
- for k, v := range p.build.ImportPos {
+ for k, v := range p.Internal.Build.ImportPos {
m[k] = append(m[k], v...)
}
- for k, v := range p.build.TestImportPos {
+ for k, v := range p.Internal.Build.TestImportPos {
m[k] = append(m[k], v...)
}
- ptest.build.ImportPos = m
+ ptest.Internal.Build.ImportPos = m
if localCover {
- ptest.coverMode = testCoverMode
+ ptest.Internal.CoverMode = testCoverMode
var coverFiles []string
coverFiles = append(coverFiles, ptest.GoFiles...)
coverFiles = append(coverFiles, ptest.CgoFiles...)
- ptest.coverVars = declareCoverVars(ptest.ImportPath, coverFiles...)
+ ptest.Internal.CoverVars = declareCoverVars(ptest.ImportPath, coverFiles...)
}
} else {
ptest = p
@@ -825,69 +850,77 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// External test package.
if len(p.XTestGoFiles) > 0 {
- pxtest = &Package{
- Name: p.Name + "_test",
- ImportPath: p.ImportPath + "_test",
- localPrefix: p.localPrefix,
- Root: p.Root,
- Dir: p.Dir,
- GoFiles: p.XTestGoFiles,
- Imports: p.XTestImports,
- build: &build.Package{
- ImportPos: p.build.XTestImportPos,
+ pxtest = &load.Package{
+ PackagePublic: load.PackagePublic{
+ Name: p.Name + "_test",
+ ImportPath: p.ImportPath + "_test",
+ Root: p.Root,
+ Dir: p.Dir,
+ GoFiles: p.XTestGoFiles,
+ Imports: p.XTestImports,
+ Stale: true,
+ },
+ Internal: load.PackageInternal{
+ LocalPrefix: p.Internal.LocalPrefix,
+ Build: &build.Package{
+ ImportPos: p.Internal.Build.XTestImportPos,
+ },
+ Imports: ximports,
+ Pkgdir: testDir,
+ Fake: true,
+ External: true,
},
- imports: ximports,
- pkgdir: testDir,
- fake: true,
- external: true,
- Stale: true,
}
if pxtestNeedsPtest {
- pxtest.imports = append(pxtest.imports, ptest)
+ pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest)
}
}
// Action for building pkg.test.
- pmain = &Package{
- Name: "main",
- Dir: testDir,
- GoFiles: []string{"_testmain.go"},
- ImportPath: "testmain",
- Root: p.Root,
- build: &build.Package{Name: "main"},
- pkgdir: testDir,
- fake: true,
- Stale: true,
- omitDWARF: !testC && !testNeedBinary,
+ pmain = &load.Package{
+ PackagePublic: load.PackagePublic{
+ Name: "main",
+ Dir: testDir,
+ GoFiles: []string{"_testmain.go"},
+ ImportPath: "testmain",
+ Root: p.Root,
+ Stale: true,
+ },
+ Internal: load.PackageInternal{
+ Build: &build.Package{Name: "main"},
+ Pkgdir: testDir,
+ Fake: true,
+ OmitDebug: !testC && !testNeedBinary,
+ },
}
// The generated main also imports testing, regexp, and os.
- stk.push("testmain")
+ stk.Push("testmain")
for dep := range testMainDeps {
if dep == ptest.ImportPath {
- pmain.imports = append(pmain.imports, ptest)
+ pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
} else {
- p1 := loadImport(dep, "", nil, &stk, nil, 0)
- if !reqStdPkgSrc && p1.Standard {
+ p1 := load.LoadImport(dep, "", nil, &stk, nil, 0)
+ if cfg.BuildToolchainName == "gccgo" && p1.Standard {
continue
}
if p1.Error != nil {
return nil, nil, nil, p1.Error
}
- pmain.imports = append(pmain.imports, p1)
+ pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
}
}
if testCoverPkgs != nil {
// Add imports, but avoid duplicates.
- seen := map[*Package]bool{p: true, ptest: true}
- for _, p1 := range pmain.imports {
+ seen := map[*load.Package]bool{p: true, ptest: true}
+ for _, p1 := range pmain.Internal.Imports {
seen[p1] = true
}
for _, p1 := range testCoverPkgs {
if !seen[p1] {
seen[p1] = true
- pmain.imports = append(pmain.imports, p1)
+ pmain.Internal.Imports = append(pmain.Internal.Imports, p1)
}
}
}
@@ -901,11 +934,11 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
return nil, nil, nil, err
}
if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
- pmain.imports = append(pmain.imports, ptest)
+ pmain.Internal.Imports = append(pmain.Internal.Imports, ptest)
t.ImportTest = true
}
if pxtest != nil {
- pmain.imports = append(pmain.imports, pxtest)
+ pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest)
t.ImportXtest = true
}
@@ -925,23 +958,19 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
recompileForTest(pmain, p, ptest, testDir)
}
- if buildContext.GOOS == "darwin" {
- if buildContext.GOARCH == "arm" || buildContext.GOARCH == "arm64" {
- t.IsIOS = true
- t.NeedOS = true
+ if cfg.BuildContext.GOOS == "darwin" {
+ if cfg.BuildContext.GOARCH == "arm" || cfg.BuildContext.GOARCH == "arm64" {
+ t.NeedCgo = true
}
}
- if t.TestMain == nil {
- t.NeedOS = true
- }
- for _, cp := range pmain.imports {
- if len(cp.coverVars) > 0 {
- t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars})
+ for _, cp := range pmain.Internal.Imports {
+ if len(cp.Internal.CoverVars) > 0 {
+ t.Cover = append(t.Cover, coverInfo{cp, cp.Internal.CoverVars})
}
}
- if !buildN {
+ if !cfg.BuildN {
// writeTestmain writes _testmain.go. This must happen after recompileForTest,
// because recompileForTest modifies XXX.
if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), t); err != nil {
@@ -949,28 +978,28 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
}
}
- computeStale(pmain)
+ load.ComputeStale(pmain)
if ptest != p {
- a := b.action(modeBuild, modeBuild, ptest)
- a.objdir = testDir + string(filepath.Separator) + "_obj_test" + string(filepath.Separator)
- a.objpkg = ptestObj
- a.target = ptestObj
- a.link = false
+ a := b.Action(work.ModeBuild, work.ModeBuild, ptest)
+ a.Objdir = testDir + string(filepath.Separator) + "_obj_test" + string(filepath.Separator)
+ a.Objpkg = ptestObj
+ a.Target = ptestObj
+ a.Link = false
}
if pxtest != nil {
- a := b.action(modeBuild, modeBuild, pxtest)
- a.objdir = testDir + string(filepath.Separator) + "_obj_xtest" + string(filepath.Separator)
- a.objpkg = buildToolchain.pkgpath(testDir, pxtest)
- a.target = a.objpkg
+ a := b.Action(work.ModeBuild, work.ModeBuild, pxtest)
+ a.Objdir = testDir + string(filepath.Separator) + "_obj_xtest" + string(filepath.Separator)
+ a.Objpkg = work.BuildToolchain.Pkgpath(testDir, pxtest)
+ a.Target = a.Objpkg
}
- a := b.action(modeBuild, modeBuild, pmain)
- a.objdir = testDir + string(filepath.Separator)
- a.objpkg = filepath.Join(testDir, "main.a")
- a.target = filepath.Join(testDir, testBinary) + exeSuffix
- if goos == "windows" {
+ a := b.Action(work.ModeBuild, work.ModeBuild, pmain)
+ a.Objdir = testDir + string(filepath.Separator)
+ a.Objpkg = filepath.Join(testDir, "main.a")
+ a.Target = filepath.Join(testDir, testBinary) + cfg.ExeSuffix
+ if cfg.Goos == "windows" {
// There are many reserved words on Windows that,
// if used in the name of an executable, cause Windows
// to try to ask for extra permissions.
@@ -995,7 +1024,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
// we could just do this always on Windows.
for _, bad := range windowsBadWords {
if strings.Contains(testBinary, bad) {
- a.target = filepath.Join(testDir, "test.test") + exeSuffix
+ a.Target = filepath.Join(testDir, "test.test") + cfg.ExeSuffix
break
}
}
@@ -1004,52 +1033,52 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
if testC || testNeedBinary {
// -c or profiling flag: create action to copy binary to ./test.out.
- target := filepath.Join(cwd, testBinary+exeSuffix)
+ target := filepath.Join(base.Cwd, testBinary+cfg.ExeSuffix)
if testO != "" {
target = testO
if !filepath.IsAbs(target) {
- target = filepath.Join(cwd, target)
+ target = filepath.Join(base.Cwd, target)
}
}
- buildAction = &action{
- f: (*builder).install,
- deps: []*action{buildAction},
- p: pmain,
- target: target,
+ buildAction = &work.Action{
+ Func: work.BuildInstallFunc,
+ Deps: []*work.Action{buildAction},
+ Package: pmain,
+ Target: target,
}
runAction = buildAction // make sure runAction != nil even if not running test
}
if testC {
- printAction = &action{p: p, deps: []*action{runAction}} // nop
+ printAction = &work.Action{Package: p, Deps: []*work.Action{runAction}} // nop
} else {
// run test
- runAction = &action{
- f: (*builder).runTest,
- deps: []*action{buildAction},
- p: p,
- ignoreFail: true,
+ runAction = &work.Action{
+ Func: builderRunTest,
+ Deps: []*work.Action{buildAction},
+ Package: p,
+ IgnoreFail: true,
}
- cleanAction := &action{
- f: (*builder).cleanTest,
- deps: []*action{runAction},
- p: p,
+ cleanAction := &work.Action{
+ Func: builderCleanTest,
+ Deps: []*work.Action{runAction},
+ Package: p,
}
- printAction = &action{
- f: (*builder).printTest,
- deps: []*action{cleanAction},
- p: p,
+ printAction = &work.Action{
+ Func: builderPrintTest,
+ Deps: []*work.Action{cleanAction},
+ Package: p,
}
}
return buildAction, runAction, printAction, nil
}
-func testImportStack(top string, p *Package, target string) []string {
+func testImportStack(top string, p *load.Package, target string) []string {
stk := []string{top, p.ImportPath}
Search:
for p.ImportPath != target {
- for _, p1 := range p.imports {
- if p1.ImportPath == target || contains(p1.Deps, target) {
+ for _, p1 := range p.Internal.Imports {
+ if p1.ImportPath == target || str.Contains(p1.Deps, target) {
stk = append(stk, p1.ImportPath)
p = p1
continue Search
@@ -1062,12 +1091,12 @@ Search:
return stk
}
-func recompileForTest(pmain, preal, ptest *Package, testDir string) {
+func recompileForTest(pmain, preal, ptest *load.Package, testDir string) {
// The "test copy" of preal is ptest.
// For each package that depends on preal, make a "test copy"
// that depends on ptest. And so on, up the dependency tree.
- testCopy := map[*Package]*Package{preal: ptest}
- for _, p := range packageList([]*Package{pmain}) {
+ testCopy := map[*load.Package]*load.Package{preal: ptest}
+ for _, p := range load.PackageList([]*load.Package{pmain}) {
// Copy on write.
didSplit := false
split := func() {
@@ -1075,32 +1104,32 @@ func recompileForTest(pmain, preal, ptest *Package, testDir string) {
return
}
didSplit = true
- if p.pkgdir != testDir {
- p1 := new(Package)
+ if p.Internal.Pkgdir != testDir {
+ p1 := new(load.Package)
testCopy[p] = p1
*p1 = *p
- p1.imports = make([]*Package, len(p.imports))
- copy(p1.imports, p.imports)
+ p1.Internal.Imports = make([]*load.Package, len(p.Internal.Imports))
+ copy(p1.Internal.Imports, p.Internal.Imports)
p = p1
- p.pkgdir = testDir
- p.target = ""
- p.fake = true
+ p.Internal.Pkgdir = testDir
+ p.Internal.Target = ""
+ p.Internal.Fake = true
p.Stale = true
p.StaleReason = "depends on package being tested"
}
}
- // Update p.deps and p.imports to use at test copies.
- for i, dep := range p.deps {
+ // Update p.Deps and p.Internal.Imports to use at test copies.
+ for i, dep := range p.Internal.Deps {
if p1 := testCopy[dep]; p1 != nil && p1 != dep {
split()
- p.deps[i] = p1
+ p.Internal.Deps[i] = p1
}
}
- for i, imp := range p.imports {
+ for i, imp := range p.Internal.Imports {
if p1 := testCopy[imp]; p1 != nil && p1 != imp {
split()
- p.imports[i] = p1
+ p.Internal.Imports[i] = p1
}
}
}
@@ -1117,13 +1146,13 @@ func isTestFile(file string) bool {
// declareCoverVars attaches the required cover variables names
// to the files, to be used when annotating the files.
-func declareCoverVars(importPath string, files ...string) map[string]*CoverVar {
- coverVars := make(map[string]*CoverVar)
+func declareCoverVars(importPath string, files ...string) map[string]*load.CoverVar {
+ coverVars := make(map[string]*load.CoverVar)
for _, file := range files {
if isTestFile(file) {
continue
}
- coverVars[file] = &CoverVar{
+ coverVars[file] = &load.CoverVar{
File: filepath.Join(importPath, file),
Var: fmt.Sprintf("GoCover_%d", coverIndex),
}
@@ -1134,29 +1163,29 @@ func declareCoverVars(importPath string, files ...string) map[string]*CoverVar {
var noTestsToRun = []byte("\ntesting: warning: no tests to run\n")
-// runTest is the action for running a test binary.
-func (b *builder) runTest(a *action) error {
- args := stringList(findExecCmd(), a.deps[0].target, testArgs)
- a.testOutput = new(bytes.Buffer)
+// builderRunTest is the action for running a test binary.
+func builderRunTest(b *work.Builder, a *work.Action) error {
+ args := str.StringList(work.FindExecCmd(), a.Deps[0].Target, testArgs)
+ a.TestOutput = new(bytes.Buffer)
- if buildN || buildX {
- b.showcmd("", "%s", strings.Join(args, " "))
- if buildN {
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd("", "%s", strings.Join(args, " "))
+ if cfg.BuildN {
return nil
}
}
- if a.failed {
+ if a.Failed {
// We were unable to build the binary.
- a.failed = false
- fmt.Fprintf(a.testOutput, "FAIL\t%s [build failed]\n", a.p.ImportPath)
- setExitStatus(1)
+ a.Failed = false
+ fmt.Fprintf(a.TestOutput, "FAIL\t%s [build failed]\n", a.Package.ImportPath)
+ base.SetExitStatus(1)
return nil
}
cmd := exec.Command(args[0], args[1:]...)
- cmd.Dir = a.p.Dir
- cmd.Env = envForDir(cmd.Dir, origEnv)
+ cmd.Dir = a.Package.Dir
+ cmd.Env = base.EnvForDir(cmd.Dir, cfg.OrigEnv)
var buf bytes.Buffer
if testStreamOutput {
cmd.Stdout = os.Stdout
@@ -1168,7 +1197,7 @@ func (b *builder) runTest(a *action) error {
// If there are any local SWIG dependencies, we want to load
// the shared library from the build directory.
- if a.p.usesSwig() {
+ if a.Package.UsesSwig() {
env := cmd.Env
found := false
prefix := "LD_LIBRARY_PATH="
@@ -1193,7 +1222,7 @@ func (b *builder) runTest(a *action) error {
// running.
if err == nil {
tick := time.NewTimer(testKillTimeout)
- startSigHandlers()
+ base.StartSigHandlers()
done := make(chan error)
go func() {
done <- cmd.Wait()
@@ -1203,14 +1232,14 @@ func (b *builder) runTest(a *action) error {
case err = <-done:
// ok
case <-tick.C:
- if signalTrace != nil {
+ if base.SignalTrace != nil {
// Send a quit signal in the hope that the program will print
// a stack trace and exit. Give it five seconds before resorting
// to Kill.
- cmd.Process.Signal(signalTrace)
+ cmd.Process.Signal(base.SignalTrace)
select {
case err = <-done:
- fmt.Fprintf(&buf, "*** Test killed with %v: ran too long (%v).\n", signalTrace, testKillTimeout)
+ fmt.Fprintf(&buf, "*** Test killed with %v: ran too long (%v).\n", base.SignalTrace, testKillTimeout)
break Outer
case <-time.After(5 * time.Second):
}
@@ -1226,23 +1255,23 @@ func (b *builder) runTest(a *action) error {
if err == nil {
norun := ""
if testShowPass {
- a.testOutput.Write(out)
+ a.TestOutput.Write(out)
}
if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
norun = " [no tests to run]"
}
- fmt.Fprintf(a.testOutput, "ok \t%s\t%s%s%s\n", a.p.ImportPath, t, coveragePercentage(out), norun)
+ fmt.Fprintf(a.TestOutput, "ok \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun)
return nil
}
- setExitStatus(1)
+ base.SetExitStatus(1)
if len(out) > 0 {
- a.testOutput.Write(out)
+ a.TestOutput.Write(out)
// assume printing the test binary's exit status is superfluous
} else {
- fmt.Fprintf(a.testOutput, "%s\n", err)
+ fmt.Fprintf(a.TestOutput, "%s\n", err)
}
- fmt.Fprintf(a.testOutput, "FAIL\t%s\t%s\n", a.p.ImportPath, t)
+ fmt.Fprintf(a.TestOutput, "FAIL\t%s\t%s\n", a.Package.ImportPath, t)
return nil
}
@@ -1266,29 +1295,29 @@ func coveragePercentage(out []byte) string {
return fmt.Sprintf("\tcoverage: %s", matches[1])
}
-// cleanTest is the action for cleaning up after a test.
-func (b *builder) cleanTest(a *action) error {
- if buildWork {
+// builderCleanTest is the action for cleaning up after a test.
+func builderCleanTest(b *work.Builder, a *work.Action) error {
+ if cfg.BuildWork {
return nil
}
- run := a.deps[0]
- testDir := filepath.Join(b.work, filepath.FromSlash(run.p.ImportPath+"/_test"))
+ run := a.Deps[0]
+ testDir := filepath.Join(b.WorkDir, filepath.FromSlash(run.Package.ImportPath+"/_test"))
os.RemoveAll(testDir)
return nil
}
-// printTest is the action for printing a test result.
-func (b *builder) printTest(a *action) error {
- clean := a.deps[0]
- run := clean.deps[0]
- os.Stdout.Write(run.testOutput.Bytes())
- run.testOutput = nil
+// builderPrintTest is the action for printing a test result.
+func builderPrintTest(b *work.Builder, a *work.Action) error {
+ clean := a.Deps[0]
+ run := clean.Deps[0]
+ os.Stdout.Write(run.TestOutput.Bytes())
+ run.TestOutput = nil
return nil
}
-// notest is the action for testing a package with no test files.
-func (b *builder) notest(a *action) error {
- fmt.Printf("? \t%s\t[no test files]\n", a.p.ImportPath)
+// builderNoTest is the action for testing a package with no test files.
+func builderNoTest(b *work.Builder, a *work.Action) error {
+ fmt.Printf("? \t%s\t[no test files]\n", a.Package.ImportPath)
return nil
}
@@ -1333,12 +1362,12 @@ func isTest(name, prefix string) bool {
}
type coverInfo struct {
- Package *Package
- Vars map[string]*CoverVar
+ Package *load.Package
+ Vars map[string]*load.CoverVar
}
// loadTestFuncs returns the testFuncs describing the tests that will be run.
-func loadTestFuncs(ptest *Package) (*testFuncs, error) {
+func loadTestFuncs(ptest *load.Package) (*testFuncs, error) {
t := &testFuncs{
Package: ptest,
}
@@ -1375,13 +1404,12 @@ type testFuncs struct {
Benchmarks []testFunc
Examples []testFunc
TestMain *testFunc
- Package *Package
+ Package *load.Package
ImportTest bool
NeedTest bool
ImportXtest bool
NeedXtest bool
- NeedOS bool
- IsIOS bool
+ NeedCgo bool
Cover []coverInfo
}
@@ -1393,6 +1421,19 @@ func (t *testFuncs) CoverEnabled() bool {
return testCover
}
+// ImportPath returns the import path of the package being tested, if it is within GOPATH.
+// This is printed by the testing package when running benchmarks.
+func (t *testFuncs) ImportPath() string {
+ pkg := t.Package.ImportPath
+ if strings.HasPrefix(pkg, "_/") {
+ return ""
+ }
+ if pkg == "command-line-arguments" {
+ return ""
+ }
+ return pkg
+}
+
// Covered returns a string describing which packages are being tested for coverage.
// If the covered package is the same as the tested package, it returns the empty string.
// Otherwise it is a comma-separated human-readable list of packages beginning with
@@ -1421,7 +1462,7 @@ var testFileSet = token.NewFileSet()
func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
if err != nil {
- return expandScanner(err)
+ return base.ExpandScanner(err)
}
for _, d := range f.Decls {
n, ok := d.(*ast.FuncDecl)
@@ -1482,7 +1523,7 @@ var testmainTmpl = template.Must(template.New("main").Parse(`
package main
import (
-{{if .NeedOS}}
+{{if not .TestMain}}
"os"
{{end}}
"testing"
@@ -1498,10 +1539,8 @@ import (
_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
{{end}}
-{{if .IsIOS}}
- "os/signal"
+{{if .NeedCgo}}
_ "runtime/cgo"
- "syscall"
{{end}}
)
@@ -1523,6 +1562,10 @@ var examples = []testing.InternalExample{
{{end}}
}
+func init() {
+ testdeps.ImportPath = {{.ImportPath | printf "%q"}}
+}
+
{{if .CoverEnabled}}
// Only updated by init functions, so no need for atomicity.
@@ -1563,32 +1606,6 @@ func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts
{{end}}
func main() {
-{{if .IsIOS}}
- // Send a SIGUSR2, which will be intercepted by LLDB to
- // tell the test harness that installation was successful.
- // See misc/ios/go_darwin_arm_exec.go.
- signal.Notify(make(chan os.Signal), syscall.SIGUSR2)
- syscall.Kill(0, syscall.SIGUSR2)
- signal.Reset(syscall.SIGUSR2)
-
- // The first argument supplied to an iOS test is an offset
- // suffix for the current working directory.
- // Process it here, and remove it from os.Args.
- const hdr = "cwdSuffix="
- if len(os.Args) < 2 || len(os.Args[1]) <= len(hdr) || os.Args[1][:len(hdr)] != hdr {
- panic("iOS test not passed a working directory suffix")
- }
- suffix := os.Args[1][len(hdr):]
- dir, err := os.Getwd()
- if err != nil {
- panic(err)
- }
- if err := os.Chdir(dir + "/" + suffix); err != nil {
- panic(err)
- }
- os.Args = append([]string{os.Args[0]}, os.Args[2:]...)
-{{end}}
-
{{if .CoverEnabled}}
testing.RegisterCover(testing.Cover{
Mode: {{printf "%q" .CoverMode}},
diff --git a/libgo/go/cmd/go/internal/test/testflag.go b/libgo/go/cmd/go/internal/test/testflag.go
new file mode 100644
index 0000000..bff8656
--- /dev/null
+++ b/libgo/go/cmd/go/internal/test/testflag.go
@@ -0,0 +1,211 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package test
+
+import (
+ "flag"
+ "os"
+ "strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/cmdflag"
+ "cmd/go/internal/str"
+ "cmd/go/internal/work"
+)
+
+const cmd = "test"
+
+// The flag handling part of go test is large and distracting.
+// We can't use the flag package because some of the flags from
+// our command line are for us, and some are for 6.out, and
+// some are for both.
+
+// testFlagDefn is the set of flags we process.
+var testFlagDefn = []*cmdflag.Defn{
+ // local.
+ {Name: "c", BoolVar: &testC},
+ {Name: "i", BoolVar: &cfg.BuildI},
+ {Name: "o"},
+ {Name: "cover", BoolVar: &testCover},
+ {Name: "covermode"},
+ {Name: "coverpkg"},
+ {Name: "exec"},
+
+ // Passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
+ {Name: "bench", PassToTest: true},
+ {Name: "benchmem", BoolVar: new(bool), PassToTest: true},
+ {Name: "benchtime", PassToTest: true},
+ {Name: "count", PassToTest: true},
+ {Name: "coverprofile", PassToTest: true},
+ {Name: "cpu", PassToTest: true},
+ {Name: "cpuprofile", PassToTest: true},
+ {Name: "list", PassToTest: true},
+ {Name: "memprofile", PassToTest: true},
+ {Name: "memprofilerate", PassToTest: true},
+ {Name: "blockprofile", PassToTest: true},
+ {Name: "blockprofilerate", PassToTest: true},
+ {Name: "mutexprofile", PassToTest: true},
+ {Name: "mutexprofilefraction", PassToTest: true},
+ {Name: "outputdir", PassToTest: true},
+ {Name: "parallel", PassToTest: true},
+ {Name: "run", PassToTest: true},
+ {Name: "short", BoolVar: new(bool), PassToTest: true},
+ {Name: "timeout", PassToTest: true},
+ {Name: "trace", PassToTest: true},
+ {Name: "v", BoolVar: &testV, PassToTest: true},
+}
+
+// add build flags to testFlagDefn
+func init() {
+ var cmd base.Command
+ work.AddBuildFlags(&cmd)
+ cmd.Flag.VisitAll(func(f *flag.Flag) {
+ if f.Name == "v" {
+ // test overrides the build -v flag
+ return
+ }
+ testFlagDefn = append(testFlagDefn, &cmdflag.Defn{
+ Name: f.Name,
+ Value: f.Value,
+ })
+ })
+}
+
+// testFlags processes the command line, grabbing -x and -c, rewriting known flags
+// to have "test" before them, and reading the command line for the 6.out.
+// Unfortunately for us, we need to do our own flag processing because go test
+// grabs some flags but otherwise its command line is just a holding place for
+// pkg.test's arguments.
+// We allow known flags both before and after the package name list,
+// to allow both
+// go test fmt -custom-flag-for-fmt-test
+// go test -x math
+func testFlags(args []string) (packageNames, passToTest []string) {
+ inPkg := false
+ outputDir := ""
+ var explicitArgs []string
+ for i := 0; i < len(args); i++ {
+ if !strings.HasPrefix(args[i], "-") {
+ if !inPkg && packageNames == nil {
+ // First package name we've seen.
+ inPkg = true
+ }
+ if inPkg {
+ packageNames = append(packageNames, args[i])
+ continue
+ }
+ }
+
+ if inPkg {
+ // Found an argument beginning with "-"; end of package list.
+ inPkg = false
+ }
+
+ f, value, extraWord := cmdflag.Parse(cmd, testFlagDefn, args, i)
+ if f == nil {
+ // This is a flag we do not know; we must assume
+ // that any args we see after this might be flag
+ // arguments, not package names.
+ inPkg = false
+ if packageNames == nil {
+ // make non-nil: we have seen the empty package list
+ packageNames = []string{}
+ }
+ if args[i] == "-args" || args[i] == "--args" {
+ // -args or --args signals that everything that follows
+ // should be passed to the test.
+ explicitArgs = args[i+1:]
+ break
+ }
+ passToTest = append(passToTest, args[i])
+ continue
+ }
+ if f.Value != nil {
+ if err := f.Value.Set(value); err != nil {
+ base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
+ }
+ } else {
+ // Test-only flags.
+ // Arguably should be handled by f.Value, but aren't.
+ switch f.Name {
+ // bool flags.
+ case "c", "i", "v", "cover":
+ cmdflag.SetBool(cmd, f.BoolVar, value)
+ case "o":
+ testO = value
+ testNeedBinary = true
+ case "exec":
+ xcmd, err := str.SplitQuotedFields(value)
+ if err != nil {
+ base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
+ }
+ work.ExecCmd = xcmd
+ case "bench":
+ // record that we saw the flag; don't care about the value
+ testBench = true
+ case "list":
+ testList = true
+ case "timeout":
+ testTimeout = value
+ case "blockprofile", "cpuprofile", "memprofile", "mutexprofile":
+ testProfile = true
+ testNeedBinary = true
+ case "trace":
+ testProfile = true
+ case "coverpkg":
+ testCover = true
+ if value == "" {
+ testCoverPaths = nil
+ } else {
+ testCoverPaths = strings.Split(value, ",")
+ }
+ case "coverprofile":
+ testCover = true
+ testProfile = true
+ case "covermode":
+ switch value {
+ case "set", "count", "atomic":
+ testCoverMode = value
+ default:
+ base.Fatalf("invalid flag argument for -covermode: %q", value)
+ }
+ testCover = true
+ case "outputdir":
+ outputDir = value
+ }
+ }
+ if extraWord {
+ i++
+ }
+ if f.PassToTest {
+ passToTest = append(passToTest, "-test."+f.Name+"="+value)
+ }
+ }
+
+ if testCoverMode == "" {
+ testCoverMode = "set"
+ if cfg.BuildRace {
+ // Default coverage mode is atomic when -race is set.
+ testCoverMode = "atomic"
+ }
+ }
+
+ if cfg.BuildRace && testCoverMode != "atomic" {
+ base.Fatalf(`-covermode must be "atomic", not %q, when -race is enabled`, testCoverMode)
+ }
+
+ // Tell the test what directory we're running in, so it can write the profiles there.
+ if testProfile && outputDir == "" {
+ dir, err := os.Getwd()
+ if err != nil {
+ base.Fatalf("error from os.Getwd: %s", err)
+ }
+ passToTest = append(passToTest, "-test.outputdir", dir)
+ }
+
+ passToTest = append(passToTest, explicitArgs...)
+ return
+}
diff --git a/libgo/go/cmd/go/tool.go b/libgo/go/cmd/go/internal/tool/tool.go
similarity index 58%
rename from libgo/go/cmd/go/tool.go
rename to libgo/go/cmd/go/internal/tool/tool.go
index 6e2c68f..7dd5510 100644
--- a/libgo/go/cmd/go/tool.go
+++ b/libgo/go/cmd/go/internal/tool/tool.go
@@ -2,20 +2,21 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package tool implements the ``go tool'' command.
+package tool
import (
"fmt"
- "go/build"
"os"
"os/exec"
- "path/filepath"
- "runtime"
"sort"
"strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
)
-var cmdTool = &Command{
+var CmdTool = &base.Command{
Run: runTool,
UsageLine: "tool [-n] command [args...]",
Short: "run specified go tool",
@@ -30,53 +31,24 @@ For more about each tool command, see 'go tool command -h'.
`,
}
-var (
- toolGOOS = runtime.GOOS
- toolGOARCH = runtime.GOARCH
- toolIsWindows = toolGOOS == "windows"
- toolDir = build.ToolDir
-
- toolN bool
-)
+var toolN bool
-// List of go tools found in the gccgo tool directory.
+// Return whether tool can be expected in the gccgo tool directory.
// Other binaries could be in the same directory so don't
// show those with the 'go tool' command.
-
-var gccgoTools = []string{"cgo", "fix", "cover", "godoc", "vet"}
-
-func init() {
- cmdTool.Flag.BoolVar(&toolN, "n", false, "")
-}
-
-const toolWindowsExtension = ".exe"
-
-func tool(toolName string) string {
- toolPath := filepath.Join(toolDir, toolName)
- if toolIsWindows {
- toolPath += toolWindowsExtension
- }
- if len(buildToolExec) > 0 {
- return toolPath
+func isGccgoTool(tool string) bool {
+ switch tool {
+ case "cgo", "fix", "cover", "godoc", "vet":
+ return true
}
- // Give a nice message if there is no tool with that name.
- if _, err := os.Stat(toolPath); err != nil {
- if isInGoToolsRepo(toolName) {
- fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName)
- } else {
- fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
- }
- setExitStatus(2)
- exit()
- }
- return toolPath
+ return false
}
-func isInGoToolsRepo(toolName string) bool {
- return false
+func init() {
+ CmdTool.Flag.BoolVar(&toolN, "n", false, "")
}
-func runTool(cmd *Command, args []string) {
+func runTool(cmd *base.Command, args []string) {
if len(args) == 0 {
listTools()
return
@@ -88,11 +60,11 @@ func runTool(cmd *Command, args []string) {
case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
default:
fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
- setExitStatus(2)
+ base.SetExitStatus(2)
return
}
}
- toolPath := tool(toolName)
+ toolPath := base.Tool(toolName)
if toolPath == "" {
return
}
@@ -112,7 +84,7 @@ func runTool(cmd *Command, args []string) {
Stdout: os.Stdout,
Stderr: os.Stderr,
// Set $GOROOT, mainly for go tool dist.
- Env: mergeEnvLists([]string{"GOROOT=" + goroot}, os.Environ()),
+ Env: base.MergeEnvLists([]string{"GOROOT=" + cfg.GOROOT}, os.Environ()),
}
err := toolCmd.Run()
if err != nil {
@@ -121,27 +93,27 @@ func runTool(cmd *Command, args []string) {
// or we're printing command lines too (-x mode).
// Assume if command exited cleanly (even with non-zero status)
// it printed any messages it wanted to print.
- if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX {
+ if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || cfg.BuildX {
fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
}
- setExitStatus(1)
+ base.SetExitStatus(1)
return
}
}
// listTools prints a list of the available tools in the tools directory.
func listTools() {
- f, err := os.Open(toolDir)
+ f, err := os.Open(base.ToolDir)
if err != nil {
fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
- setExitStatus(2)
+ base.SetExitStatus(2)
return
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
- setExitStatus(2)
+ base.SetExitStatus(2)
return
}
@@ -150,24 +122,14 @@ func listTools() {
// Unify presentation by going to lower case.
name = strings.ToLower(name)
// If it's windows, don't show the .exe suffix.
- if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) {
- name = name[:len(name)-len(toolWindowsExtension)]
+ if base.ToolIsWindows && strings.HasSuffix(name, base.ToolWindowsExtension) {
+ name = name[:len(name)-len(base.ToolWindowsExtension)]
}
-
// The tool directory used by gccgo will have other binaries
- // in additions to go tools. Only display go tools for this list.
-
- if buildContext.Compiler == "gccgo" {
- for _, tool := range gccgoTools {
- if tool == name {
- fmt.Println(name)
- }
- }
- } else {
-
- // Not gccgo, list all the tools found in this dir
-
- fmt.Println(name)
+ // in addition to go tools. Only display go tools here.
+ if cfg.BuildToolchainName == "gccgo" && !isGccgoTool(name) {
+ continue
}
+ fmt.Println(name)
}
}
diff --git a/libgo/go/cmd/go/version.go b/libgo/go/cmd/go/internal/version/version.go
similarity index 72%
rename from libgo/go/cmd/go/version.go
rename to libgo/go/cmd/go/internal/version/version.go
index 3045f35..c3f7d73 100644
--- a/libgo/go/cmd/go/version.go
+++ b/libgo/go/cmd/go/internal/version/version.go
@@ -2,21 +2,24 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package main
+// Package version implements the ``go version'' command.
+package version
import (
"fmt"
"runtime"
+
+ "cmd/go/internal/base"
)
-var cmdVersion = &Command{
+var CmdVersion = &base.Command{
Run: runVersion,
UsageLine: "version",
Short: "print Go version",
Long: `Version prints the Go version, as reported by runtime.Version.`,
}
-func runVersion(cmd *Command, args []string) {
+func runVersion(cmd *base.Command, args []string) {
if len(args) != 0 {
cmd.Usage()
}
diff --git a/libgo/go/cmd/go/internal/vet/vet.go b/libgo/go/cmd/go/internal/vet/vet.go
new file mode 100644
index 0000000..ddacd08
--- /dev/null
+++ b/libgo/go/cmd/go/internal/vet/vet.go
@@ -0,0 +1,56 @@
+// Copyright 2011 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 vet implements the ``go vet'' command.
+package vet
+
+import (
+ "path/filepath"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
+)
+
+var CmdVet = &base.Command{
+ Run: runVet,
+ CustomFlags: true,
+ UsageLine: "vet [-n] [-x] [build flags] [vet flags] [packages]",
+ Short: "run go tool vet on packages",
+ Long: `
+Vet runs the Go vet command on the packages named by the import paths.
+
+For more about vet and its flags, see 'go doc cmd/vet'.
+For more about specifying packages, see 'go help packages'.
+
+The -n flag prints commands that would be executed.
+The -x flag prints commands as they are executed.
+
+For more about build flags, see 'go help build'.
+
+See also: go fmt, go fix.
+ `,
+}
+
+func runVet(cmd *base.Command, args []string) {
+ vetFlags, packages := vetFlags(args)
+ for _, p := range load.Packages(packages) {
+ // Vet expects to be given a set of files all from the same package.
+ // Run once for package p and once for package p_test.
+ if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles) > 0 {
+ runVetFiles(p, vetFlags, str.StringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.SFiles))
+ }
+ if len(p.XTestGoFiles) > 0 {
+ runVetFiles(p, vetFlags, str.StringList(p.XTestGoFiles))
+ }
+ }
+}
+
+func runVetFiles(p *load.Package, flags, files []string) {
+ for i := range files {
+ files[i] = filepath.Join(p.Dir, files[i])
+ }
+ base.Run(cfg.BuildToolexec, base.Tool("vet"), flags, base.RelPaths(files))
+}
diff --git a/libgo/go/cmd/go/internal/vet/vetflag.go b/libgo/go/cmd/go/internal/vet/vetflag.go
new file mode 100644
index 0000000..8cd21bb
--- /dev/null
+++ b/libgo/go/cmd/go/internal/vet/vetflag.go
@@ -0,0 +1,99 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package vet
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cmdflag"
+ "cmd/go/internal/work"
+)
+
+const cmd = "vet"
+
+// vetFlagDefn is the set of flags we process.
+var vetFlagDefn = []*cmdflag.Defn{
+ // Note: Some flags, in particular -tags and -v, are known to
+ // vet but also defined as build flags. This works fine, so we
+ // don't define them here but use AddBuildFlags to init them.
+ // However some, like -x, are known to the build but not
+ // to vet. We handle them in vetFlags.
+
+ // local.
+ {Name: "all", BoolVar: new(bool)},
+ {Name: "asmdecl", BoolVar: new(bool)},
+ {Name: "assign", BoolVar: new(bool)},
+ {Name: "atomic", BoolVar: new(bool)},
+ {Name: "bool", BoolVar: new(bool)},
+ {Name: "buildtags", BoolVar: new(bool)},
+ {Name: "cgocall", BoolVar: new(bool)},
+ {Name: "composites", BoolVar: new(bool)},
+ {Name: "copylocks", BoolVar: new(bool)},
+ {Name: "httpresponse", BoolVar: new(bool)},
+ {Name: "lostcancel", BoolVar: new(bool)},
+ {Name: "methods", BoolVar: new(bool)},
+ {Name: "nilfunc", BoolVar: new(bool)},
+ {Name: "printf", BoolVar: new(bool)},
+ {Name: "printfuncs"},
+ {Name: "rangeloops", BoolVar: new(bool)},
+ {Name: "shadow", BoolVar: new(bool)},
+ {Name: "shadowstrict", BoolVar: new(bool)},
+ {Name: "source", BoolVar: new(bool)},
+ {Name: "structtags", BoolVar: new(bool)},
+ {Name: "tests", BoolVar: new(bool)},
+ {Name: "unreachable", BoolVar: new(bool)},
+ {Name: "unsafeptr", BoolVar: new(bool)},
+ {Name: "unusedfuncs"},
+ {Name: "unusedresult", BoolVar: new(bool)},
+ {Name: "unusedstringmethods"},
+}
+
+// add build flags to vetFlagDefn.
+func init() {
+ var cmd base.Command
+ work.AddBuildFlags(&cmd)
+ cmd.Flag.VisitAll(func(f *flag.Flag) {
+ vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{
+ Name: f.Name,
+ Value: f.Value,
+ })
+ })
+}
+
+// vetFlags processes the command line, splitting it at the first non-flag
+// into the list of flags and list of packages.
+func vetFlags(args []string) (passToVet, packageNames []string) {
+ for i := 0; i < len(args); i++ {
+ if !strings.HasPrefix(args[i], "-") {
+ return args[:i], args[i:]
+ }
+
+ f, value, extraWord := cmdflag.Parse(cmd, vetFlagDefn, args, i)
+ if f == nil {
+ fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
+ fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
+ os.Exit(2)
+ }
+ if f.Value != nil {
+ if err := f.Value.Set(value); err != nil {
+ base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
+ }
+ switch f.Name {
+ // Flags known to the build but not to vet, so must be dropped.
+ case "x", "n":
+ args = append(args[:i], args[i+1:]...)
+ i--
+ }
+ }
+ if extraWord {
+ i++
+ }
+ }
+ return args, nil
+}
diff --git a/libgo/go/cmd/go/bootstrap.go b/libgo/go/cmd/go/internal/web/bootstrap.go
similarity index 55%
rename from libgo/go/cmd/go/bootstrap.go
rename to libgo/go/cmd/go/internal/web/bootstrap.go
index 2148d12..d1d4621 100644
--- a/libgo/go/cmd/go/bootstrap.go
+++ b/libgo/go/cmd/go/internal/web/bootstrap.go
@@ -8,7 +8,7 @@
// These stubs avoid importing packages with large dependency
// trees, like the use of "net/http" in vcs.go.
-package main
+package web
import (
"errors"
@@ -17,25 +17,21 @@ import (
var errHTTP = errors.New("no http in bootstrap go command")
-type httpError struct {
- statusCode int
+type HTTPError struct {
+ StatusCode int
}
-func (e *httpError) Error() string {
+func (e *HTTPError) Error() string {
panic("unreachable")
}
-func httpGET(url string) ([]byte, error) {
+func Get(url string) ([]byte, error) {
return nil, errHTTP
}
-func httpsOrHTTP(importPath string, security securityMode) (string, io.ReadCloser, error) {
+func GetMaybeInsecure(importPath string, security SecurityMode) (string, io.ReadCloser, error) {
return "", nil, errHTTP
}
-func parseMetaGoImports(r io.Reader) ([]metaImport, error) {
- panic("unreachable")
-}
-
-func queryEscape(s string) string { panic("unreachable") }
-func openBrowser(url string) bool { panic("unreachable") }
+func QueryEscape(s string) string { panic("unreachable") }
+func OpenBrowser(url string) bool { panic("unreachable") }
diff --git a/libgo/go/cmd/go/http.go b/libgo/go/cmd/go/internal/web/http.go
similarity index 74%
rename from libgo/go/cmd/go/http.go
rename to libgo/go/cmd/go/internal/web/http.go
index dcb4e9f..6e347fb 100644
--- a/libgo/go/cmd/go/http.go
+++ b/libgo/go/cmd/go/internal/web/http.go
@@ -9,10 +9,9 @@
// to avoid needing to build net (and thus use cgo) during the
// bootstrap process.
-package main
+package web
import (
- "cmd/internal/browser"
"crypto/tls"
"fmt"
"io"
@@ -21,6 +20,9 @@ import (
"net/http"
"net/url"
"time"
+
+ "cmd/go/internal/cfg"
+ "cmd/internal/browser"
)
// httpClient is the default HTTP client, but a variable so it can be
@@ -40,25 +42,25 @@ var impatientInsecureHTTPClient = &http.Client{
},
}
-type httpError struct {
+type HTTPError struct {
status string
- statusCode int
+ StatusCode int
url string
}
-func (e *httpError) Error() string {
+func (e *HTTPError) Error() string {
return fmt.Sprintf("%s: %s", e.url, e.status)
}
-// httpGET returns the data from an HTTP GET request for the given URL.
-func httpGET(url string) ([]byte, error) {
+// Get returns the data from an HTTP GET request for the given URL.
+func Get(url string) ([]byte, error) {
resp, err := httpClient.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
- err := &httpError{status: resp.Status, statusCode: resp.StatusCode, url: url}
+ err := &HTTPError{status: resp.Status, StatusCode: resp.StatusCode, url: url}
return nil, err
}
@@ -69,9 +71,9 @@ func httpGET(url string) ([]byte, error) {
return b, nil
}
-// httpsOrHTTP returns the body of either the importPath's
-// https resource or, if unavailable, the http resource.
-func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body io.ReadCloser, err error) {
+// GetMaybeInsecure returns the body of either the importPath's
+// https resource or, if unavailable and permitted by the security mode, the http resource.
+func GetMaybeInsecure(importPath string, security SecurityMode) (urlStr string, body io.ReadCloser, err error) {
fetch := func(scheme string) (urlStr string, res *http.Response, err error) {
u, err := url.Parse(scheme + "://" + importPath)
if err != nil {
@@ -79,10 +81,10 @@ func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body
}
u.RawQuery = "go-get=1"
urlStr = u.String()
- if buildV {
+ if cfg.BuildV {
log.Printf("Fetching %s", urlStr)
}
- if security == insecure && scheme == "https" { // fail earlier
+ if security == Insecure && scheme == "https" { // fail earlier
res, err = impatientInsecureHTTPClient.Get(urlStr)
} else {
res, err = httpClient.Get(urlStr)
@@ -96,10 +98,10 @@ func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body
}
urlStr, res, err := fetch("https")
if err != nil {
- if buildV {
+ if cfg.BuildV {
log.Printf("https fetch failed: %v", err)
}
- if security == insecure {
+ if security == Insecure {
closeBody(res)
urlStr, res, err = fetch("http")
}
@@ -110,11 +112,11 @@ func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body
}
// Note: accepting a non-200 OK here, so people can serve a
// meta import in their http 404 page.
- if buildV {
+ if cfg.BuildV {
log.Printf("Parsing meta tags from %s (status code %d)", urlStr, res.StatusCode)
}
return urlStr, res.Body, nil
}
-func queryEscape(s string) string { return url.QueryEscape(s) }
-func openBrowser(url string) bool { return browser.Open(url) }
+func QueryEscape(s string) string { return url.QueryEscape(s) }
+func OpenBrowser(url string) bool { return browser.Open(url) }
diff --git a/libgo/go/cmd/go/internal/web/security.go b/libgo/go/cmd/go/internal/web/security.go
new file mode 100644
index 0000000..1dc6f1b
--- /dev/null
+++ b/libgo/go/cmd/go/internal/web/security.go
@@ -0,0 +1,16 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package web defines helper routines for accessing HTTP/HTTPS resources.
+package web
+
+// SecurityMode specifies whether a function should make network
+// calls using insecure transports (eg, plain text HTTP).
+// The zero value is "secure".
+type SecurityMode int
+
+const (
+ Secure SecurityMode = iota
+ Insecure
+)
diff --git a/libgo/go/cmd/go/build.go b/libgo/go/cmd/go/internal/work/build.go
similarity index 64%
rename from libgo/go/cmd/go/build.go
rename to libgo/go/cmd/go/internal/work/build.go
index a62bc86..de8c493 100644
--- a/libgo/go/cmd/go/build.go
+++ b/libgo/go/cmd/go/internal/work/build.go
@@ -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 main
+package work
import (
"bufio"
@@ -26,9 +26,15 @@ import (
"strings"
"sync"
"time"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/buildid"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/str"
)
-var cmdBuild = &Command{
+var CmdBuild = &base.Command{
UsageLine: "build [-o output] [-i] [build flags] [packages]",
Short: "compile packages and dependencies",
Long: `
@@ -97,8 +103,8 @@ and test commands:
a suffix to use in the name of the package installation directory,
in order to keep output separate from default builds.
If using the -race flag, the install suffix is automatically set to race
- or, if set explicitly, has _race appended to it. Likewise for the -msan
- flag. Using a -buildmode option that requires non-default compile flags
+ or, if set explicitly, has _race appended to it. Likewise for the -msan
+ flag. Using a -buildmode option that requires non-default compile flags
has a similar effect.
-ldflags 'flag list'
arguments to pass on each go tool link invocation.
@@ -110,16 +116,17 @@ and test commands:
For example, when building with a non-standard configuration,
use -pkgdir to keep generated packages in a separate location.
-tags 'tag list'
- a list of build tags to consider satisfied during the build.
- For more information about build tags, see the description of
+ a space-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.
-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
'cmd args /path/to/asm '.
-The list flags accept a space-separated list of strings. To embed spaces
-in an element in the list, surround it with either single or double quotes.
+All the flags that take a list of arguments accept a space-separated
+list of strings. To embed spaces in an element in the list, surround
+it with either single or double quotes.
For more about specifying packages, see 'go help packages'.
For more about where packages and binaries are installed,
@@ -137,112 +144,85 @@ See also: go install, go get, go clean.
`,
}
+const concurrentGCBackendCompilationEnabledByDefault = true
+
func init() {
// break init cycle
- cmdBuild.Run = runBuild
- cmdInstall.Run = runInstall
+ CmdBuild.Run = runBuild
+ CmdInstall.Run = runInstall
- cmdBuild.Flag.BoolVar(&buildI, "i", false, "")
+ CmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "")
+ CmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file")
- addBuildFlags(cmdBuild)
- addBuildFlags(cmdInstall)
+ AddBuildFlags(CmdBuild)
+ AddBuildFlags(CmdInstall)
}
-// Flags set by multiple commands.
-var buildA bool // -a flag
-var buildN bool // -n flag
-var buildP = runtime.NumCPU() // -p flag
-var buildV bool // -v flag
-var buildX bool // -x flag
-var buildI bool // -i flag
-var buildO = cmdBuild.Flag.String("o", "", "output file")
-var buildWork bool // -work flag
+// Note that flags consulted by other parts of the code
+// (for example, buildV) are in cmd/go/internal/cfg.
+
var buildAsmflags []string // -asmflags flag
var buildGcflags []string // -gcflags flag
-var buildLdflags []string // -ldflags flag
var buildGccgoflags []string // -gccgoflags flag
-var buildRace bool // -race flag
-var buildMSan bool // -msan flag
-var buildToolExec []string // -toolexec flag
-var buildBuildmode string // -buildmode flag
-var buildLinkshared bool // -linkshared flag
-var buildPkgdir string // -pkgdir flag
-
-// Require the source for go std packages
-var reqStdPkgSrc bool
-var buildContext = build.Default
-var buildToolchain toolchain = noToolchain{}
+
+var BuildToolchain toolchain = noToolchain{}
var ldBuildmode string
// buildCompiler implements flag.Var.
// It implements Set by updating both
-// buildToolchain and buildContext.Compiler.
+// BuildToolchain and buildContext.Compiler.
type buildCompiler struct{}
func (c buildCompiler) Set(value string) error {
switch value {
case "gc":
- buildToolchain = gcToolchain{}
+ BuildToolchain = gcToolchain{}
case "gccgo":
- buildToolchain = gccgoToolchain{}
+ BuildToolchain = gccgoToolchain{}
default:
return fmt.Errorf("unknown compiler %q", value)
}
- buildContext.Compiler = value
+ cfg.BuildToolchainName = value
+ cfg.BuildToolchainCompiler = BuildToolchain.compiler
+ cfg.BuildToolchainLinker = BuildToolchain.linker
+ cfg.BuildContext.Compiler = value
return nil
}
func (c buildCompiler) String() string {
- return buildContext.Compiler
+ return cfg.BuildContext.Compiler
}
func init() {
switch build.Default.Compiler {
- case "gc":
- buildToolchain = gcToolchain{}
- case "gccgo":
- buildToolchain = gccgoToolchain{}
+ case "gc", "gccgo":
+ buildCompiler{}.Set(build.Default.Compiler)
}
}
// addBuildFlags adds the flags common to the build, clean, get,
// install, list, run, and test commands.
-func addBuildFlags(cmd *Command) {
- cmd.Flag.BoolVar(&buildA, "a", false, "")
- cmd.Flag.BoolVar(&buildN, "n", false, "")
- cmd.Flag.IntVar(&buildP, "p", buildP, "")
- cmd.Flag.BoolVar(&buildV, "v", false, "")
- cmd.Flag.BoolVar(&buildX, "x", false, "")
-
- cmd.Flag.Var((*stringsFlag)(&buildAsmflags), "asmflags", "")
+func AddBuildFlags(cmd *base.Command) {
+ cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
+ cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
+ cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
+
+ cmd.Flag.Var((*base.StringsFlag)(&buildAsmflags), "asmflags", "")
cmd.Flag.Var(buildCompiler{}, "compiler", "")
- cmd.Flag.StringVar(&buildBuildmode, "buildmode", "default", "")
- cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "")
- cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
- cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "")
- cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "")
- cmd.Flag.BoolVar(&buildLinkshared, "linkshared", false, "")
- cmd.Flag.StringVar(&buildPkgdir, "pkgdir", "", "")
- cmd.Flag.BoolVar(&buildRace, "race", false, "")
- cmd.Flag.BoolVar(&buildMSan, "msan", false, "")
- cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
- cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "")
- cmd.Flag.BoolVar(&buildWork, "work", false, "")
- switch build.Default.Compiler {
- case "gc":
- reqStdPkgSrc = true
- case "gccgo":
- reqStdPkgSrc = false
- }
-}
-
-func addBuildFlagsNX(cmd *Command) {
- cmd.Flag.BoolVar(&buildN, "n", false, "")
- cmd.Flag.BoolVar(&buildX, "x", false, "")
-}
-
-func isSpaceByte(c byte) bool {
- return c == ' ' || c == '\t' || c == '\n' || c == '\r'
+ cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "")
+ cmd.Flag.Var((*base.StringsFlag)(&buildGcflags), "gcflags", "")
+ cmd.Flag.Var((*base.StringsFlag)(&buildGccgoflags), "gccgoflags", "")
+ cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "")
+ cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildLdflags), "ldflags", "")
+ cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "")
+ cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "")
+ cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "")
+ cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildContext.BuildTags), "tags", "")
+ cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
+ cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
}
// fileExtSplit expects a filename and returns the name
@@ -257,58 +237,7 @@ func fileExtSplit(file string) (name, ext string) {
return
}
-type stringsFlag []string
-
-func (v *stringsFlag) Set(s string) error {
- var err error
- *v, err = splitQuotedFields(s)
- if *v == nil {
- *v = []string{}
- }
- return err
-}
-
-func splitQuotedFields(s string) ([]string, error) {
- // Split fields allowing '' or "" around elements.
- // Quotes further inside the string do not count.
- var f []string
- for len(s) > 0 {
- for len(s) > 0 && isSpaceByte(s[0]) {
- s = s[1:]
- }
- if len(s) == 0 {
- break
- }
- // Accepted quoted string. No unescaping inside.
- if s[0] == '"' || s[0] == '\'' {
- quote := s[0]
- s = s[1:]
- i := 0
- for i < len(s) && s[i] != quote {
- i++
- }
- if i >= len(s) {
- return nil, fmt.Errorf("unterminated %c string", quote)
- }
- f = append(f, s[:i])
- s = s[i+1:]
- continue
- }
- i := 0
- for i < len(s) && !isSpaceByte(s[i]) {
- i++
- }
- f = append(f, s[:i])
- s = s[i:]
- }
- return f, nil
-}
-
-func (v *stringsFlag) String() string {
- return ""
-}
-
-func pkgsMain(pkgs []*Package) (res []*Package) {
+func pkgsMain(pkgs []*load.Package) (res []*load.Package) {
for _, p := range pkgs {
if p.Name == "main" {
res = append(res, p)
@@ -317,7 +246,7 @@ func pkgsMain(pkgs []*Package) (res []*Package) {
return res
}
-func pkgsNotMain(pkgs []*Package) (res []*Package) {
+func pkgsNotMain(pkgs []*load.Package) (res []*load.Package) {
for _, p := range pkgs {
if p.Name != "main" {
res = append(res, p)
@@ -326,22 +255,24 @@ func pkgsNotMain(pkgs []*Package) (res []*Package) {
return res
}
-var pkgsFilter = func(pkgs []*Package) []*Package { return pkgs }
+func oneMainPkg(pkgs []*load.Package) []*load.Package {
+ if len(pkgs) != 1 || pkgs[0].Name != "main" {
+ base.Fatalf("-buildmode=%s requires exactly one main package", cfg.BuildBuildmode)
+ }
+ return pkgs
+}
+
+var pkgsFilter = func(pkgs []*load.Package) []*load.Package { return pkgs }
-func buildModeInit() {
- _, gccgo := buildToolchain.(gccgoToolchain)
+func BuildModeInit() {
+ gccgo := cfg.BuildToolchainName == "gccgo"
var codegenArg string
- platform := goos + "/" + goarch
- switch buildBuildmode {
+ platform := cfg.Goos + "/" + cfg.Goarch
+ switch cfg.BuildBuildmode {
case "archive":
pkgsFilter = pkgsNotMain
case "c-archive":
- pkgsFilter = func(p []*Package) []*Package {
- if len(p) != 1 || p[0].Name != "main" {
- fatalf("-buildmode=c-archive requires exactly one main package")
- }
- return p
- }
+ pkgsFilter = oneMainPkg
if gccgo {
codegenArg = "-fPIC"
} else {
@@ -349,7 +280,7 @@ func buildModeInit() {
case "darwin/arm", "darwin/arm64":
codegenArg = "-shared"
default:
- switch goos {
+ switch cfg.Goos {
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
// Use -shared so that the result is
// suitable for inclusion in a PIE or
@@ -358,10 +289,10 @@ func buildModeInit() {
}
}
}
- exeSuffix = ".a"
+ cfg.ExeSuffix = ".a"
ldBuildmode = "c-archive"
case "c-shared":
- pkgsFilter = pkgsMain
+ pkgsFilter = oneMainPkg
if gccgo {
codegenArg = "-fPIC"
} else {
@@ -371,7 +302,7 @@ func buildModeInit() {
codegenArg = "-shared"
case "darwin/amd64", "darwin/386":
default:
- fatalf("-buildmode=c-shared not supported on %s\n", platform)
+ base.Fatalf("-buildmode=c-shared not supported on %s\n", platform)
}
}
ldBuildmode = "c-shared"
@@ -394,6 +325,9 @@ func buildModeInit() {
pkgsFilter = pkgsMain
ldBuildmode = "exe"
case "pie":
+ if cfg.BuildRace {
+ base.Fatalf("-buildmode=pie not supported when -race is enabled")
+ }
if gccgo {
codegenArg = "-fPIE"
} else {
@@ -402,7 +336,7 @@ func buildModeInit() {
"android/amd64", "android/arm", "android/arm64", "android/386":
codegenArg = "-shared"
default:
- fatalf("-buildmode=pie not supported on %s\n", platform)
+ base.Fatalf("-buildmode=pie not supported on %s\n", platform)
}
}
ldBuildmode = "pie"
@@ -414,33 +348,33 @@ func buildModeInit() {
switch platform {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
default:
- fatalf("-buildmode=shared not supported on %s\n", platform)
+ base.Fatalf("-buildmode=shared not supported on %s\n", platform)
}
codegenArg = "-dynlink"
}
- if *buildO != "" {
- fatalf("-buildmode=shared and -o not supported together")
+ if cfg.BuildO != "" {
+ base.Fatalf("-buildmode=shared and -o not supported together")
}
ldBuildmode = "shared"
case "plugin":
- pkgsFilter = pkgsMain
+ pkgsFilter = oneMainPkg
if gccgo {
codegenArg = "-fPIC"
} else {
switch platform {
- case "linux/amd64", "linux/arm", "linux/arm64", "linux/386",
+ case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x",
"android/amd64", "android/arm", "android/arm64", "android/386":
default:
- fatalf("-buildmode=plugin not supported on %s\n", platform)
+ base.Fatalf("-buildmode=plugin not supported on %s\n", platform)
}
codegenArg = "-dynlink"
}
- exeSuffix = ".so"
+ cfg.ExeSuffix = ".so"
ldBuildmode = "plugin"
default:
- fatalf("buildmode=%s not supported", buildBuildmode)
+ base.Fatalf("buildmode=%s not supported", cfg.BuildBuildmode)
}
- if buildLinkshared {
+ if cfg.BuildLinkshared {
if gccgo {
codegenArg = "-fPIC"
} else {
@@ -448,55 +382,60 @@ func buildModeInit() {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
buildAsmflags = append(buildAsmflags, "-D=GOBUILDMODE_shared=1")
default:
- fatalf("-linkshared not supported on %s\n", platform)
+ base.Fatalf("-linkshared not supported on %s\n", platform)
}
codegenArg = "-dynlink"
// TODO(mwhudson): remove -w when that gets fixed in linker.
- buildLdflags = append(buildLdflags, "-linkshared", "-w")
+ cfg.BuildLdflags = append(cfg.BuildLdflags, "-linkshared", "-w")
}
}
if codegenArg != "" {
if gccgo {
- buildGccgoflags = append(buildGccgoflags, codegenArg)
+ buildGccgoflags = append([]string{codegenArg}, buildGccgoflags...)
} else {
- buildAsmflags = append(buildAsmflags, codegenArg)
- buildGcflags = append(buildGcflags, codegenArg)
+ buildAsmflags = append([]string{codegenArg}, buildAsmflags...)
+ buildGcflags = append([]string{codegenArg}, buildGcflags...)
}
// Don't alter InstallSuffix when modifying default codegen args.
- if buildBuildmode != "default" || buildLinkshared {
- if buildContext.InstallSuffix != "" {
- buildContext.InstallSuffix += "_"
+ if cfg.BuildBuildmode != "default" || cfg.BuildLinkshared {
+ if cfg.BuildContext.InstallSuffix != "" {
+ cfg.BuildContext.InstallSuffix += "_"
}
- buildContext.InstallSuffix += codegenArg[1:]
+ cfg.BuildContext.InstallSuffix += codegenArg[1:]
}
}
+ if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") && !gccgo {
+ buildGcflags = append(buildGcflags, "-goversion", runtimeVersion)
+ }
}
-func runBuild(cmd *Command, args []string) {
- instrumentInit()
- buildModeInit()
- var b builder
- b.init()
+var runtimeVersion = runtime.Version()
+
+func runBuild(cmd *base.Command, args []string) {
+ InstrumentInit()
+ BuildModeInit()
+ var b Builder
+ b.Init()
- pkgs := packagesForBuild(args)
+ pkgs := load.PackagesForBuild(args)
- if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" {
- _, *buildO = path.Split(pkgs[0].ImportPath)
- *buildO += exeSuffix
+ if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
+ _, cfg.BuildO = path.Split(pkgs[0].ImportPath)
+ cfg.BuildO += cfg.ExeSuffix
}
// Special case -o /dev/null by not writing at all.
- if *buildO == os.DevNull {
- *buildO = ""
+ if cfg.BuildO == os.DevNull {
+ cfg.BuildO = ""
}
// sanity check some often mis-used options
- switch buildContext.Compiler {
+ switch cfg.BuildContext.Compiler {
case "gccgo":
if len(buildGcflags) != 0 {
fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
}
- if len(buildLdflags) != 0 {
+ if len(cfg.BuildLdflags) != 0 {
fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
}
case "gc":
@@ -505,44 +444,45 @@ func runBuild(cmd *Command, args []string) {
}
}
- depMode := modeBuild
- if buildI {
- depMode = modeInstall
+ depMode := ModeBuild
+ if cfg.BuildI {
+ depMode = ModeInstall
}
- if *buildO != "" {
+ if cfg.BuildO != "" {
if len(pkgs) > 1 {
- fatalf("go build: cannot use -o with multiple packages")
+ base.Fatalf("go build: cannot use -o with multiple packages")
} else if len(pkgs) == 0 {
- fatalf("no packages to build")
+ base.Fatalf("no packages to build")
}
p := pkgs[0]
- p.target = *buildO
+ p.Internal.Target = cfg.BuildO
p.Stale = true // must build - not up to date
p.StaleReason = "build -o flag in use"
- a := b.action(modeInstall, depMode, p)
- b.do(a)
+ a := b.Action(ModeInstall, depMode, p)
+ b.Do(a)
return
}
- var a *action
- if buildBuildmode == "shared" {
- pkgs := pkgsFilter(packages(args))
+ pkgs = pkgsFilter(load.Packages(args))
+
+ var a *Action
+ if cfg.BuildBuildmode == "shared" {
if libName, err := libname(args, pkgs); err != nil {
- fatalf("%s", err.Error())
+ base.Fatalf("%s", err.Error())
} else {
- a = b.libaction(libName, pkgs, modeBuild, depMode)
+ a = b.libaction(libName, pkgs, ModeBuild, depMode)
}
} else {
- a = &action{}
- for _, p := range pkgsFilter(packages(args)) {
- a.deps = append(a.deps, b.action(modeBuild, depMode, p))
+ a = &Action{}
+ for _, p := range pkgs {
+ a.Deps = append(a.Deps, b.Action(ModeBuild, depMode, p))
}
}
- b.do(a)
+ b.Do(a)
}
-var cmdInstall = &Command{
+var CmdInstall = &base.Command{
UsageLine: "install [build flags] [packages]",
Short: "compile and install packages and dependencies",
Long: `
@@ -556,11 +496,6 @@ See also: go build, go get, go clean.
`,
}
-// isMetaPackage checks if name is a reserved package name that expands to multiple packages
-func isMetaPackage(name string) bool {
- return name == "std" || name == "cmd" || name == "all"
-}
-
// libname returns the filename to use for the shared library when using
// -buildmode=shared. The rules we use are:
// Use arguments for special 'meta' packages:
@@ -575,7 +510,7 @@ func isMetaPackage(name string) bool {
// gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
// a/... b/... ---> liba/c,b/d.so - all matching import paths
// Name parts are joined with ','.
-func libname(args []string, pkgs []*Package) (string, error) {
+func libname(args []string, pkgs []*load.Package) (string, error) {
var libname string
appendName := func(arg string) {
if libname == "" {
@@ -586,7 +521,7 @@ func libname(args []string, pkgs []*Package) (string, error) {
}
var haveNonMeta bool
for _, arg := range args {
- if isMetaPackage(arg) {
+ if load.IsMetaPackage(arg) {
appendName(arg)
} else {
haveNonMeta = true
@@ -598,7 +533,7 @@ func libname(args []string, pkgs []*Package) (string, error) {
arg := strings.TrimSuffix(args[0], "/...")
if build.IsLocalImport(arg) {
cwd, _ := os.Getwd()
- bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
+ bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
if bp.ImportPath != "" && bp.ImportPath != "." {
arg = bp.ImportPath
}
@@ -617,73 +552,76 @@ func libname(args []string, pkgs []*Package) (string, error) {
return "lib" + libname + ".so", nil
}
-func runInstall(cmd *Command, args []string) {
- installPackages(args, false)
+func runInstall(cmd *base.Command, args []string) {
+ InstrumentInit()
+ BuildModeInit()
+ InstallPackages(args, false)
}
-func installPackages(args []string, forGet bool) {
- if gobin != "" && !filepath.IsAbs(gobin) {
- fatalf("cannot install, GOBIN must be an absolute path")
+func InstallPackages(args []string, forGet bool) {
+ if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) {
+ base.Fatalf("cannot install, GOBIN must be an absolute path")
}
- instrumentInit()
- buildModeInit()
- pkgs := pkgsFilter(packagesForBuild(args))
+ pkgs := pkgsFilter(load.PackagesForBuild(args))
for _, p := range pkgs {
if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") {
switch {
- case p.gobinSubdir:
- errorf("go install: cannot install cross-compiled binaries when GOBIN is set")
- case p.cmdline:
- errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
+ case p.Internal.GobinSubdir:
+ base.Errorf("go install: cannot install cross-compiled binaries when GOBIN is set")
+ case p.Internal.Cmdline:
+ base.Errorf("go install: no install location for .go files listed on command line (GOBIN not set)")
case p.ConflictDir != "":
- errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
+ base.Errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
default:
- errorf("go install: no install location for directory %s outside GOPATH\n"+
+ base.Errorf("go install: no install location for directory %s outside GOPATH\n"+
"\tFor more details see: 'go help gopath'", p.Dir)
}
}
}
- exitIfErrors()
+ base.ExitIfErrors()
- var b builder
- b.init()
- // Set the behavior for `go get` to not error on packages with test files only.
- b.testFilesOnlyOK = forGet
- var a *action
- if buildBuildmode == "shared" {
+ var b Builder
+ b.Init()
+ var a *Action
+ if cfg.BuildBuildmode == "shared" {
if libName, err := libname(args, pkgs); err != nil {
- fatalf("%s", err.Error())
+ base.Fatalf("%s", err.Error())
} else {
- a = b.libaction(libName, pkgs, modeInstall, modeInstall)
+ a = b.libaction(libName, pkgs, ModeInstall, ModeInstall)
}
} else {
- a = &action{}
- var tools []*action
+ a = &Action{}
+ var tools []*Action
for _, p := range pkgs {
+ // During 'go get', don't attempt (and fail) to install packages with only tests.
+ // TODO(rsc): It's not clear why 'go get' should be different from 'go install' here. See #20760.
+ if forGet && len(p.GoFiles)+len(p.CgoFiles) == 0 && len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 {
+ continue
+ }
// If p is a tool, delay the installation until the end of the build.
// This avoids installing assemblers/compilers that are being executed
// by other steps in the build.
- // cmd/cgo is handled specially in b.action, so that we can
+ // cmd/cgo is handled specially in b.Action, so that we can
// both build and use it in the same 'go install'.
- action := b.action(modeInstall, modeInstall, p)
- if goTools[p.ImportPath] == toTool && p.ImportPath != "cmd/cgo" {
- a.deps = append(a.deps, action.deps...)
- action.deps = append(action.deps, a)
- tools = append(tools, action)
+ Action := b.Action(ModeInstall, ModeInstall, p)
+ if load.GoTools[p.ImportPath] == load.ToTool && p.ImportPath != "cmd/cgo" {
+ a.Deps = append(a.Deps, Action.Deps...)
+ Action.Deps = append(Action.Deps, a)
+ tools = append(tools, Action)
continue
}
- a.deps = append(a.deps, action)
+ a.Deps = append(a.Deps, Action)
}
if len(tools) > 0 {
- a = &action{
- deps: tools,
+ a = &Action{
+ Deps: tools,
}
}
}
- b.do(a)
- exitIfErrors()
+ b.Do(a)
+ base.ExitIfErrors()
// Success. If this command is 'go install' with no arguments
// and the current directory (the implicit argument) is a command,
@@ -698,13 +636,13 @@ func installPackages(args []string, forGet bool) {
// Compute file 'go build' would have created.
// If it exists and is an executable file, remove it.
_, targ := filepath.Split(pkgs[0].ImportPath)
- targ += exeSuffix
+ targ += cfg.ExeSuffix
if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
fi, err := os.Stat(targ)
if err == nil {
m := fi.Mode()
if m.IsRegular() {
- if m&0111 != 0 || goos == "windows" { // windows never sets executable bit
+ if m&0111 != 0 || cfg.Goos == "windows" { // windows never sets executable bit
os.Remove(targ)
}
}
@@ -713,35 +651,15 @@ func installPackages(args []string, forGet bool) {
}
}
-// Global build parameters (used during package load)
-var (
- goarch string
- goos string
- exeSuffix string
- gopath []string
-)
-
-func init() {
- goarch = buildContext.GOARCH
- goos = buildContext.GOOS
-
- if goos == "windows" {
- exeSuffix = ".exe"
- }
- gopath = filepath.SplitList(buildContext.GOPATH)
-}
-
-// A builder holds global state about a build.
+// A Builder holds global state about a build.
// It does not hold per-package state, because we
// build packages in parallel, and the builder is shared.
-type builder struct {
- work string // the temporary work directory (ends in filepath.Separator)
- actionCache map[cacheKey]*action // a cache of already-constructed actions
+type Builder struct {
+ WorkDir string // the temporary work directory (ends in filepath.Separator)
+ actionCache map[cacheKey]*Action // a cache of already-constructed actions
mkdirCache map[string]bool // a cache of created directories
flagCache map[string]bool // a cache of supported compiler flags
- print func(args ...interface{}) (int, error)
-
- testFilesOnlyOK bool // do not error if the packages only have test files
+ Print func(args ...interface{}) (int, error)
output sync.Mutex
scriptDir string // current directory in printed script
@@ -751,168 +669,82 @@ type builder struct {
ready actionQueue
}
-// An action represents a single action in the action graph.
-type action struct {
- p *Package // the package this action works on
- deps []*action // actions that must happen before this one
- triggers []*action // inverse of deps
- cgo *action // action for cgo binary if needed
- args []string // additional args for runProgram
- testOutput *bytes.Buffer // test output buffer
+// NOTE: Much of Action would not need to be exported if not for test.
+// Maybe test functionality should move into this package too?
+
+// An Action represents a single action in the action graph.
+type Action struct {
+ Package *load.Package // the package this action works on
+ Deps []*Action // actions that must happen before this one
+ Func func(*Builder, *Action) error // the action itself (nil = no-op)
+ IgnoreFail bool // whether to run f even if dependencies fail
+ TestOutput *bytes.Buffer // test output buffer
+ Args []string // additional args for runProgram
- f func(*builder, *action) error // the action itself (nil = no-op)
- ignoreFail bool // whether to run f even if dependencies fail
+ triggers []*Action // inverse of deps
+ cgo *Action // action for cgo binary if needed
// Generated files, directories.
- link bool // target is executable, not just package
- pkgdir string // the -I or -L argument to use when importing this package
- objdir string // directory for intermediate objects
- objpkg string // the intermediate package .a file created during the action
- target string // goal of the action: the created package or executable
+ Link bool // target is executable, not just package
+ Pkgdir string // the -I or -L argument to use when importing this package
+ Objdir string // directory for intermediate objects
+ Objpkg string // the intermediate package .a file created during the action
+ Target string // goal of the action: the created package or executable
// Execution state.
pending int // number of deps yet to complete
priority int // relative execution priority
- failed bool // whether the action failed
+ Failed bool // whether the action failed
}
// cacheKey is the key for the action cache.
type cacheKey struct {
- mode buildMode
- p *Package
+ mode BuildMode
+ p *load.Package
shlib string
}
-// buildMode specifies the build mode:
+// BuildMode specifies the build mode:
// are we just building things or also installing the results?
-type buildMode int
+type BuildMode int
const (
- modeBuild buildMode = iota
- modeInstall
-)
-
-var (
- goroot = filepath.Clean(runtime.GOROOT())
- gobin = os.Getenv("GOBIN")
- gorootBin = filepath.Join(goroot, "bin")
- gorootPkg = filepath.Join(goroot, "pkg")
- gorootSrc = filepath.Join(goroot, "src")
+ ModeBuild BuildMode = iota
+ ModeInstall
)
-func (b *builder) init() {
+func (b *Builder) Init() {
var err error
- b.print = func(a ...interface{}) (int, error) {
+ b.Print = func(a ...interface{}) (int, error) {
return fmt.Fprint(os.Stderr, a...)
}
- b.actionCache = make(map[cacheKey]*action)
+ b.actionCache = make(map[cacheKey]*Action)
b.mkdirCache = make(map[string]bool)
- if buildN {
- b.work = "$WORK"
+ if cfg.BuildN {
+ b.WorkDir = "$WORK"
} else {
- b.work, err = ioutil.TempDir("", "go-build")
+ b.WorkDir, err = ioutil.TempDir("", "go-build")
if err != nil {
- fatalf("%s", err)
+ base.Fatalf("%s", err)
}
- if buildX || buildWork {
- fmt.Fprintf(os.Stderr, "WORK=%s\n", b.work)
+ if cfg.BuildX || cfg.BuildWork {
+ fmt.Fprintf(os.Stderr, "WORK=%s\n", b.WorkDir)
}
- if !buildWork {
- workdir := b.work
- atexit(func() { os.RemoveAll(workdir) })
+ if !cfg.BuildWork {
+ workdir := b.WorkDir
+ base.AtExit(func() { os.RemoveAll(workdir) })
}
}
}
-// goFilesPackage creates a package for building a collection of Go files
-// (typically named on the command line). The target is named p.a for
-// package p or named after the first Go file for package main.
-func goFilesPackage(gofiles []string) *Package {
- // TODO: Remove this restriction.
- for _, f := range gofiles {
- if !strings.HasSuffix(f, ".go") {
- fatalf("named files must be .go files")
- }
- }
-
- var stk importStack
- ctxt := buildContext
- ctxt.UseAllFiles = true
-
- // Synthesize fake "directory" that only shows the named files,
- // to make it look like this is a standard package or
- // command directory. So that local imports resolve
- // consistently, the files must all be in the same directory.
- var dirent []os.FileInfo
- var dir string
- for _, file := range gofiles {
- fi, err := os.Stat(file)
- if err != nil {
- fatalf("%s", err)
- }
- if fi.IsDir() {
- fatalf("%s is a directory, should be a Go file", file)
- }
- dir1, _ := filepath.Split(file)
- if dir1 == "" {
- dir1 = "./"
- }
- if dir == "" {
- dir = dir1
- } else if dir != dir1 {
- fatalf("named files must all be in one directory; have %s and %s", dir, dir1)
- }
- dirent = append(dirent, fi)
- }
- ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil }
-
- var err error
- if dir == "" {
- dir = cwd
- }
- dir, err = filepath.Abs(dir)
- if err != nil {
- fatalf("%s", err)
- }
-
- bp, err := ctxt.ImportDir(dir, 0)
- pkg := new(Package)
- pkg.local = true
- pkg.cmdline = true
- stk.push("main")
- pkg.load(&stk, bp, err)
- stk.pop()
- pkg.localPrefix = dirToImportPath(dir)
- pkg.ImportPath = "command-line-arguments"
- pkg.target = ""
-
- if pkg.Name == "main" {
- _, elem := filepath.Split(gofiles[0])
- exe := elem[:len(elem)-len(".go")] + exeSuffix
- if *buildO == "" {
- *buildO = exe
- }
- if gobin != "" {
- pkg.target = filepath.Join(gobin, exe)
- }
- }
-
- pkg.Target = pkg.target
- pkg.Stale = true
- pkg.StaleReason = "files named on command line"
-
- computeStale(pkg)
- return pkg
-}
-
// readpkglist returns the list of packages that were built into the shared library
// at shlibpath. For the native toolchain this list is stored, newline separated, in
// an ELF note with name "Go\x00\x00" and type 1. For GCCGO it is extracted from the
// .go_export section.
-func readpkglist(shlibpath string) (pkgs []*Package) {
- var stk importStack
- if _, gccgo := buildToolchain.(gccgoToolchain); gccgo {
+func readpkglist(shlibpath string) (pkgs []*load.Package) {
+ var stk load.ImportStack
+ if cfg.BuildToolchainName == "gccgo" {
f, _ := elf.Open(shlibpath)
sect := f.Section(".go_export")
data, _ := sect.Data()
@@ -922,28 +754,28 @@ func readpkglist(shlibpath string) (pkgs []*Package) {
if strings.HasPrefix(t, "pkgpath ") {
t = strings.TrimPrefix(t, "pkgpath ")
t = strings.TrimSuffix(t, ";")
- pkgs = append(pkgs, loadPackage(t, &stk))
+ pkgs = append(pkgs, load.LoadPackage(t, &stk))
}
}
} else {
- pkglistbytes, err := readELFNote(shlibpath, "Go\x00\x00", 1)
+ pkglistbytes, err := buildid.ReadELFNote(shlibpath, "Go\x00\x00", 1)
if err != nil {
- fatalf("readELFNote failed: %v", err)
+ base.Fatalf("readELFNote failed: %v", err)
}
scanner := bufio.NewScanner(bytes.NewBuffer(pkglistbytes))
for scanner.Scan() {
t := scanner.Text()
- pkgs = append(pkgs, loadPackage(t, &stk))
+ pkgs = append(pkgs, load.LoadPackage(t, &stk))
}
}
return
}
-// action returns the action for applying the given operation (mode) to the package.
+// Action returns the action for applying the given operation (mode) to the package.
// depMode is the action to use when building dependencies.
// action never looks for p in a shared library, but may find p's dependencies in a
// shared library if buildLinkshared is true.
-func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action {
+func (b *Builder) Action(mode BuildMode, depMode BuildMode, p *load.Package) *Action {
return b.action1(mode, depMode, p, false, "")
}
@@ -951,7 +783,7 @@ func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action
// depMode is the action to use when building dependencies.
// action1 will look for p in a shared library if lookshared is true.
// forShlib is the shared library that p will become part of, if any.
-func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, lookshared bool, forShlib string) *action {
+func (b *Builder) action1(mode BuildMode, depMode BuildMode, p *load.Package, lookshared bool, forShlib string) *Action {
shlib := ""
if lookshared {
shlib = p.Shlib
@@ -963,42 +795,42 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
return a
}
if shlib != "" {
- key2 := cacheKey{modeInstall, nil, shlib}
+ key2 := cacheKey{ModeInstall, nil, shlib}
a = b.actionCache[key2]
if a != nil {
b.actionCache[key] = a
return a
}
pkgs := readpkglist(shlib)
- a = b.libaction(filepath.Base(shlib), pkgs, modeInstall, depMode)
+ a = b.libaction(filepath.Base(shlib), pkgs, ModeInstall, depMode)
b.actionCache[key2] = a
b.actionCache[key] = a
return a
}
- a = &action{p: p, pkgdir: p.build.PkgRoot}
- if p.pkgdir != "" { // overrides p.t
- a.pkgdir = p.pkgdir
+ a = &Action{Package: p, Pkgdir: p.Internal.Build.PkgRoot}
+ if p.Internal.Pkgdir != "" { // overrides p.t
+ a.Pkgdir = p.Internal.Pkgdir
}
b.actionCache[key] = a
- for _, p1 := range p.imports {
+ for _, p1 := range p.Internal.Imports {
if forShlib != "" {
// p is part of a shared library.
if p1.Shlib != "" && p1.Shlib != forShlib {
// p1 is explicitly part of a different shared library.
- // Put the action for that shared library into a.deps.
- a.deps = append(a.deps, b.action1(depMode, depMode, p1, true, p1.Shlib))
+ // Put the action for that shared library into a.Deps.
+ a.Deps = append(a.Deps, b.action1(depMode, depMode, p1, true, p1.Shlib))
} else {
// p1 is (implicitly or not) part of this shared library.
- // Put the action for p1 into a.deps.
- a.deps = append(a.deps, b.action1(depMode, depMode, p1, false, forShlib))
+ // Put the action for p1 into a.Deps.
+ a.Deps = append(a.Deps, b.action1(depMode, depMode, p1, false, forShlib))
}
} else {
// p is not part of a shared library.
// If p1 is in a shared library, put the action for that into
- // a.deps, otherwise put the action for p1 into a.deps.
- a.deps = append(a.deps, b.action1(depMode, depMode, p1, buildLinkshared, p1.Shlib))
+ // a.Deps, otherwise put the action for p1 into a.Deps.
+ a.Deps = append(a.Deps, b.action1(depMode, depMode, p1, cfg.BuildLinkshared, p1.Shlib))
}
}
@@ -1007,15 +839,15 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
// using cgo, to make sure we do not overwrite the binary while
// a package is using it. If this is a cross-build, then the cgo we
// are writing is not the cgo we need to use.
- if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan && reqStdPkgSrc {
- if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !buildLinkshared && buildBuildmode != "shared" {
- var stk importStack
- p1 := loadPackage("cmd/cgo", &stk)
+ if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH && !cfg.BuildRace && !cfg.BuildMSan && cfg.BuildToolchainName != "gccgo" {
+ if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !cfg.BuildLinkshared && cfg.BuildBuildmode != "shared" {
+ var stk load.ImportStack
+ p1 := load.LoadPackage("cmd/cgo", &stk)
if p1.Error != nil {
- fatalf("load cmd/cgo: %v", p1.Error)
+ base.Fatalf("load cmd/cgo: %v", p1.Error)
}
- a.cgo = b.action(depMode, depMode, p1)
- a.deps = append(a.deps, a.cgo)
+ a.cgo = b.Action(depMode, depMode, p1)
+ a.Deps = append(a.Deps, a.cgo)
}
}
@@ -1026,42 +858,42 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
return a
}
// gccgo standard library is "fake" too.
- if _, ok := buildToolchain.(gccgoToolchain); ok {
+ if cfg.BuildToolchainName == "gccgo" {
// the target name is needed for cgo.
- a.target = p.target
+ a.Target = p.Internal.Target
return a
}
}
- if !p.Stale && p.target != "" {
- // p.Stale==false implies that p.target is up-to-date.
+ if !p.Stale && p.Internal.Target != "" {
+ // p.Stale==false implies that p.Internal.Target is up-to-date.
// Record target name for use by actions depending on this one.
- a.target = p.target
+ a.Target = p.Internal.Target
return a
}
- if p.local && p.target == "" {
+ if p.Internal.Local && p.Internal.Target == "" {
// Imported via local path. No permanent target.
- mode = modeBuild
+ mode = ModeBuild
}
- work := p.pkgdir
+ work := p.Internal.Pkgdir
if work == "" {
- work = b.work
+ work = b.WorkDir
}
- a.objdir = filepath.Join(work, a.p.ImportPath, "_obj") + string(filepath.Separator)
- a.objpkg = buildToolchain.pkgpath(work, a.p)
- a.link = p.Name == "main"
+ a.Objdir = filepath.Join(work, a.Package.ImportPath, "_obj") + string(filepath.Separator)
+ a.Objpkg = BuildToolchain.Pkgpath(work, a.Package)
+ a.Link = p.Name == "main"
switch mode {
- case modeInstall:
- a.f = (*builder).install
- a.deps = []*action{b.action1(modeBuild, depMode, p, lookshared, forShlib)}
- a.target = a.p.target
+ case ModeInstall:
+ a.Func = BuildInstallFunc
+ a.Deps = []*Action{b.action1(ModeBuild, depMode, p, lookshared, forShlib)}
+ a.Target = a.Package.Internal.Target
// Install header for cgo in c-archive and c-shared modes.
- if p.usesCgo() && (buildBuildmode == "c-archive" || buildBuildmode == "c-shared") {
- hdrTarget := a.target[:len(a.target)-len(filepath.Ext(a.target))] + ".h"
- if buildContext.Compiler == "gccgo" && *buildO == "" {
+ if p.UsesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
+ hdrTarget := a.Target[:len(a.Target)-len(filepath.Ext(a.Target))] + ".h"
+ if cfg.BuildContext.Compiler == "gccgo" && cfg.BuildO == "" {
// For the header file, remove the "lib"
// added by go/build, so we generate pkg.h
// rather than libpkg.h.
@@ -1069,21 +901,21 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
file = strings.TrimPrefix(file, "lib")
hdrTarget = filepath.Join(dir, file)
}
- ah := &action{
- p: a.p,
- deps: []*action{a.deps[0]},
- f: (*builder).installHeader,
- pkgdir: a.pkgdir,
- objdir: a.objdir,
- target: hdrTarget,
+ ah := &Action{
+ Package: a.Package,
+ Deps: []*Action{a.Deps[0]},
+ Func: (*Builder).installHeader,
+ Pkgdir: a.Pkgdir,
+ Objdir: a.Objdir,
+ Target: hdrTarget,
}
- a.deps = append(a.deps, ah)
+ a.Deps = append(a.Deps, ah)
}
- case modeBuild:
- a.f = (*builder).build
- a.target = a.objpkg
- if a.link {
+ case ModeBuild:
+ a.Func = (*Builder).build
+ a.Target = a.Objpkg
+ if a.Link {
// An executable file. (This is the name of a temporary file.)
// Because we run the temporary file in 'go run' and 'go test',
// the name will show up in ps listings. If the caller has specified
@@ -1092,84 +924,84 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
// naming conflicts. The only possible conflict is if we were
// to create a top-level package named exe.
name := "a.out"
- if p.exeName != "" {
- name = p.exeName
- } else if goos == "darwin" && buildBuildmode == "c-shared" && p.target != "" {
+ if p.Internal.ExeName != "" {
+ name = p.Internal.ExeName
+ } else if cfg.Goos == "darwin" && cfg.BuildBuildmode == "c-shared" && p.Internal.Target != "" {
// On OS X, the linker output name gets recorded in the
// shared library's LC_ID_DYLIB load command.
// The code invoking the linker knows to pass only the final
// path element. Arrange that the path element matches what
// we'll install it as; otherwise the library is only loadable as "a.out".
- _, name = filepath.Split(p.target)
+ _, name = filepath.Split(p.Internal.Target)
}
- a.target = a.objdir + filepath.Join("exe", name) + exeSuffix
+ a.Target = a.Objdir + filepath.Join("exe", name) + cfg.ExeSuffix
}
}
return a
}
-func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode buildMode) *action {
- a := &action{}
+func (b *Builder) libaction(libname string, pkgs []*load.Package, mode, depMode BuildMode) *Action {
+ a := &Action{}
switch mode {
default:
- fatalf("unrecognized mode %v", mode)
+ base.Fatalf("unrecognized mode %v", mode)
- case modeBuild:
- a.f = (*builder).linkShared
- a.target = filepath.Join(b.work, libname)
+ case ModeBuild:
+ a.Func = (*Builder).linkShared
+ a.Target = filepath.Join(b.WorkDir, libname)
for _, p := range pkgs {
- if p.target == "" {
+ if p.Internal.Target == "" {
continue
}
- a.deps = append(a.deps, b.action(depMode, depMode, p))
+ a.Deps = append(a.Deps, b.Action(depMode, depMode, p))
}
- case modeInstall:
+ case ModeInstall:
// Currently build mode shared forces external linking mode, and
// external linking mode forces an import of runtime/cgo (and
// math on arm). So if it was not passed on the command line and
// it is not present in another shared library, add it here.
- _, gccgo := buildToolchain.(gccgoToolchain)
+ gccgo := cfg.BuildToolchainName == "gccgo"
if !gccgo {
seencgo := false
for _, p := range pkgs {
seencgo = seencgo || (p.Standard && p.ImportPath == "runtime/cgo")
}
if !seencgo {
- var stk importStack
- p := loadPackage("runtime/cgo", &stk)
+ var stk load.ImportStack
+ p := load.LoadPackage("runtime/cgo", &stk)
if p.Error != nil {
- fatalf("load runtime/cgo: %v", p.Error)
+ base.Fatalf("load runtime/cgo: %v", p.Error)
}
- computeStale(p)
+ load.ComputeStale(p)
// If runtime/cgo is in another shared library, then that's
// also the shared library that contains runtime, so
// something will depend on it and so runtime/cgo's staleness
// will be checked when processing that library.
if p.Shlib == "" || p.Shlib == libname {
- pkgs = append([]*Package{}, pkgs...)
+ pkgs = append([]*load.Package{}, pkgs...)
pkgs = append(pkgs, p)
}
}
- if goarch == "arm" {
+ if cfg.Goarch == "arm" {
seenmath := false
for _, p := range pkgs {
seenmath = seenmath || (p.Standard && p.ImportPath == "math")
}
if !seenmath {
- var stk importStack
- p := loadPackage("math", &stk)
+ var stk load.ImportStack
+ p := load.LoadPackage("math", &stk)
if p.Error != nil {
- fatalf("load math: %v", p.Error)
+ base.Fatalf("load math: %v", p.Error)
}
- computeStale(p)
+ load.ComputeStale(p)
// If math is in another shared library, then that's
// also the shared library that contains runtime, so
// something will depend on it and so math's staleness
// will be checked when processing that library.
if p.Shlib == "" || p.Shlib == libname {
- pkgs = append([]*Package{}, pkgs...)
+ pkgs = append([]*load.Package{}, pkgs...)
pkgs = append(pkgs, p)
}
}
@@ -1179,67 +1011,67 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
// Figure out where the library will go.
var libdir string
for _, p := range pkgs {
- plibdir := p.build.PkgTargetRoot
+ plibdir := p.Internal.Build.PkgTargetRoot
if gccgo {
plibdir = filepath.Join(plibdir, "shlibs")
}
if libdir == "" {
libdir = plibdir
} else if libdir != plibdir {
- fatalf("multiple roots %s & %s", libdir, plibdir)
+ base.Fatalf("multiple roots %s & %s", libdir, plibdir)
}
}
- a.target = filepath.Join(libdir, libname)
+ a.Target = filepath.Join(libdir, libname)
// Now we can check whether we need to rebuild it.
stale := false
var built time.Time
- if fi, err := os.Stat(a.target); err == nil {
+ if fi, err := os.Stat(a.Target); err == nil {
built = fi.ModTime()
}
for _, p := range pkgs {
- if p.target == "" {
+ if p.Internal.Target == "" {
continue
}
stale = stale || p.Stale
- lstat, err := os.Stat(p.target)
+ lstat, err := os.Stat(p.Internal.Target)
if err != nil || lstat.ModTime().After(built) {
stale = true
}
- a.deps = append(a.deps, b.action1(depMode, depMode, p, false, a.target))
+ a.Deps = append(a.Deps, b.action1(depMode, depMode, p, false, a.Target))
}
if stale {
- a.f = (*builder).install
- buildAction := b.libaction(libname, pkgs, modeBuild, depMode)
- a.deps = []*action{buildAction}
+ a.Func = BuildInstallFunc
+ buildAction := b.libaction(libname, pkgs, ModeBuild, depMode)
+ a.Deps = []*Action{buildAction}
for _, p := range pkgs {
- if p.target == "" {
+ if p.Internal.Target == "" {
continue
}
- shlibnameaction := &action{}
- shlibnameaction.f = (*builder).installShlibname
- shlibnameaction.target = p.target[:len(p.target)-2] + ".shlibname"
- a.deps = append(a.deps, shlibnameaction)
- shlibnameaction.deps = append(shlibnameaction.deps, buildAction)
+ shlibnameaction := &Action{}
+ shlibnameaction.Func = (*Builder).installShlibname
+ shlibnameaction.Target = p.Internal.Target[:len(p.Internal.Target)-2] + ".shlibname"
+ a.Deps = append(a.Deps, shlibnameaction)
+ shlibnameaction.Deps = append(shlibnameaction.Deps, buildAction)
}
}
}
return a
}
-// actionList returns the list of actions in the dag rooted at root
+// ActionList returns the list of actions in the dag rooted at root
// as visited in a depth-first post-order traversal.
-func actionList(root *action) []*action {
- seen := map[*action]bool{}
- all := []*action{}
- var walk func(*action)
- walk = func(a *action) {
+func ActionList(root *Action) []*Action {
+ seen := map[*Action]bool{}
+ all := []*Action{}
+ var walk func(*Action)
+ walk = func(a *Action) {
if seen[a] {
return
}
seen[a] = true
- for _, a1 := range a.deps {
+ for _, a1 := range a.Deps {
walk(a1)
}
all = append(all, a)
@@ -1252,20 +1084,20 @@ func actionList(root *action) []*action {
// This is needed because if package p depends on package q that is in libr.so, the
// action graph looks like p->libr.so->q and so just scanning through p's
// dependencies does not find the import dir for q.
-func allArchiveActions(root *action) []*action {
- seen := map[*action]bool{}
- r := []*action{}
- var walk func(*action)
- walk = func(a *action) {
+func allArchiveActions(root *Action) []*Action {
+ seen := map[*Action]bool{}
+ r := []*Action{}
+ var walk func(*Action)
+ walk = func(a *Action) {
if seen[a] {
return
}
seen[a] = true
- if strings.HasSuffix(a.target, ".so") || a == root {
- for _, a1 := range a.deps {
+ if strings.HasSuffix(a.Target, ".so") || a == root {
+ for _, a1 := range a.Deps {
walk(a1)
}
- } else if strings.HasSuffix(a.target, ".a") {
+ } else if strings.HasSuffix(a.Target, ".a") {
r = append(r, a)
}
}
@@ -1274,15 +1106,22 @@ func allArchiveActions(root *action) []*action {
}
// do runs the action graph rooted at root.
-func (b *builder) do(root *action) {
- /* Commented out for gccgo, which does not have osArchSupportsCgo.
+func (b *Builder) Do(root *Action) {
+ /* Commented for gccgo, which does not have OSArchSupportsCgo.
- if _, ok := osArchSupportsCgo[goos+"/"+goarch]; !ok && buildContext.Compiler == "gc" {
- fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", goos, goarch)
+ if _, ok := cfg.OSArchSupportsCgo[cfg.Goos+"/"+cfg.Goarch]; !ok && cfg.BuildContext.Compiler == "gc" {
+ fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", cfg.Goos, cfg.Goarch)
os.Exit(2)
}
*/
+ for _, tag := range cfg.BuildContext.BuildTags {
+ if strings.Contains(tag, ",") {
+ fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n")
+ os.Exit(2)
+ }
+ }
+
// Build list of all actions, assigning depth-first post-order priority.
// The original implementation here was a true queue
// (using a channel) but it had the effect of getting
@@ -1294,7 +1133,7 @@ func (b *builder) do(root *action) {
// ensure that, all else being equal, the execution prefers
// to do what it would have done first in a simple depth-first
// dependency order traversal.
- all := actionList(root)
+ all := ActionList(root)
for i, a := range all {
a.priority = i
}
@@ -1303,10 +1142,10 @@ func (b *builder) do(root *action) {
// Initialize per-action execution state.
for _, a := range all {
- for _, a1 := range a.deps {
+ for _, a1 := range a.Deps {
a1.triggers = append(a1.triggers, a)
}
- a.pending = len(a.deps)
+ a.pending = len(a.Deps)
if a.pending == 0 {
b.ready.push(a)
b.readySema <- true
@@ -1315,10 +1154,10 @@ func (b *builder) do(root *action) {
// Handle runs a single action and takes care of triggering
// any actions that are runnable as a result.
- handle := func(a *action) {
+ handle := func(a *Action) {
var err error
- if a.f != nil && (!a.failed || a.ignoreFail) {
- err = a.f(b, a)
+ if a.Func != nil && (!a.Failed || a.IgnoreFail) {
+ err = a.Func(b, a)
}
// The actions run in parallel but all the updates to the
@@ -1328,18 +1167,16 @@ func (b *builder) do(root *action) {
if err != nil {
if err == errPrintedOutput {
- setExitStatus(2)
- } else if _, ok := err.(*build.NoGoError); ok && len(a.p.TestGoFiles) > 0 && b.testFilesOnlyOK {
- // Ignore the "no buildable Go source files" error for a package with only test files.
+ base.SetExitStatus(2)
} else {
- errorf("%s", err)
+ base.Errorf("%s", err)
}
- a.failed = true
+ a.Failed = true
}
for _, a0 := range a.triggers {
- if a.failed {
- a0.failed = true
+ if a.Failed {
+ a0.Failed = true
}
if a0.pending--; a0.pending == 0 {
b.ready.push(a0)
@@ -1358,8 +1195,8 @@ func (b *builder) do(root *action) {
// If we are using the -n flag (just printing commands)
// drop the parallelism to 1, both to make the output
// deterministic and because there is no real work anyway.
- par := buildP
- if buildN {
+ par := cfg.BuildP
+ if cfg.BuildN {
par = 1
}
for i := 0; i < par; i++ {
@@ -1378,8 +1215,8 @@ func (b *builder) do(root *action) {
a := b.ready.pop()
b.exec.Unlock()
handle(a)
- case <-interrupted:
- setExitStatus(1)
+ case <-base.Interrupted:
+ base.SetExitStatus(1)
return
}
}
@@ -1390,74 +1227,74 @@ func (b *builder) do(root *action) {
}
// build is the action for building a single package or command.
-func (b *builder) build(a *action) (err error) {
+func (b *Builder) build(a *Action) (err error) {
// Return an error for binary-only package.
// We only reach this if isStale believes the binary form is
// either not present or not usable.
- if a.p.BinaryOnly {
- return fmt.Errorf("missing or invalid package binary for binary-only package %s", a.p.ImportPath)
+ if a.Package.BinaryOnly {
+ return fmt.Errorf("missing or invalid package binary for binary-only package %s", a.Package.ImportPath)
}
// Return an error if the package has CXX files but it's not using
// cgo nor SWIG, since the CXX files can only be processed by cgo
// and SWIG.
- if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
+ if len(a.Package.CXXFiles) > 0 && !a.Package.UsesCgo() && !a.Package.UsesSwig() {
return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG",
- a.p.ImportPath, strings.Join(a.p.CXXFiles, ","))
+ a.Package.ImportPath, strings.Join(a.Package.CXXFiles, ","))
}
// Same as above for Objective-C files
- if len(a.p.MFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
+ if len(a.Package.MFiles) > 0 && !a.Package.UsesCgo() && !a.Package.UsesSwig() {
return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG",
- a.p.ImportPath, strings.Join(a.p.MFiles, ","))
+ a.Package.ImportPath, strings.Join(a.Package.MFiles, ","))
}
// Same as above for Fortran files
- if len(a.p.FFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() {
+ if len(a.Package.FFiles) > 0 && !a.Package.UsesCgo() && !a.Package.UsesSwig() {
return fmt.Errorf("can't build package %s because it contains Fortran files (%s) but it's not using cgo nor SWIG",
- a.p.ImportPath, strings.Join(a.p.FFiles, ","))
+ a.Package.ImportPath, strings.Join(a.Package.FFiles, ","))
}
defer func() {
- if _, ok := err.(*build.NoGoError); err != nil && err != errPrintedOutput && !(ok && b.testFilesOnlyOK && len(a.p.TestGoFiles) > 0) {
- err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
+ if err != nil && err != errPrintedOutput {
+ err = fmt.Errorf("go build %s: %v", a.Package.ImportPath, err)
}
}()
- if buildN {
+ if cfg.BuildN {
// In -n mode, print a banner between packages.
// The banner is five lines so that when changes to
// different sections of the bootstrap script have to
// be merged, the banners give patch something
// to use to find its context.
- b.print("\n#\n# " + a.p.ImportPath + "\n#\n\n")
+ b.Print("\n#\n# " + a.Package.ImportPath + "\n#\n\n")
}
- if buildV {
- b.print(a.p.ImportPath + "\n")
+ if cfg.BuildV {
+ b.Print(a.Package.ImportPath + "\n")
}
// Make build directory.
- obj := a.objdir
- if err := b.mkdir(obj); err != nil {
+ obj := a.Objdir
+ if err := b.Mkdir(obj); err != nil {
return err
}
// make target directory
- dir, _ := filepath.Split(a.target)
+ dir, _ := filepath.Split(a.Target)
if dir != "" {
- if err := b.mkdir(dir); err != nil {
+ if err := b.Mkdir(dir); err != nil {
return err
}
}
var gofiles, cgofiles, objdirCgofiles, cfiles, sfiles, cxxfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string
- gofiles = append(gofiles, a.p.GoFiles...)
- cgofiles = append(cgofiles, a.p.CgoFiles...)
- cfiles = append(cfiles, a.p.CFiles...)
- sfiles = append(sfiles, a.p.SFiles...)
- cxxfiles = append(cxxfiles, a.p.CXXFiles...)
+ gofiles = append(gofiles, a.Package.GoFiles...)
+ cgofiles = append(cgofiles, a.Package.CgoFiles...)
+ cfiles = append(cfiles, a.Package.CFiles...)
+ sfiles = append(sfiles, a.Package.SFiles...)
+ cxxfiles = append(cxxfiles, a.Package.CXXFiles...)
- if a.p.usesCgo() || a.p.usesSwig() {
- if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.p); err != nil {
+ if a.Package.UsesCgo() || a.Package.UsesSwig() {
+ if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.Package); err != nil {
return
}
}
@@ -1465,8 +1302,8 @@ func (b *builder) build(a *action) (err error) {
// Run SWIG on each .swig and .swigcxx file.
// Each run will generate two files, a .go file and a .c or .cxx file.
// The .go file will use import "C" and is to be processed by cgo.
- if a.p.usesSwig() {
- outGo, outC, outCXX, err := b.swig(a.p, obj, pcCFLAGS)
+ if a.Package.UsesSwig() {
+ outGo, outC, outCXX, err := b.swig(a.Package, obj, pcCFLAGS)
if err != nil {
return err
}
@@ -1476,7 +1313,7 @@ func (b *builder) build(a *action) (err error) {
}
// Run cgo.
- if a.p.usesCgo() || a.p.usesSwig() {
+ if a.Package.UsesCgo() || a.Package.UsesSwig() {
// In a package using cgo, cgo compiles the C, C++ and assembly files with gcc.
// There is one exception: runtime/cgo's job is to bridge the
// cgo and non-cgo worlds, so it necessarily has files in both.
@@ -1484,7 +1321,7 @@ func (b *builder) build(a *action) (err error) {
var gccfiles []string
gccfiles = append(gccfiles, cfiles...)
cfiles = nil
- if a.p.Standard && a.p.ImportPath == "runtime/cgo" {
+ if a.Package.Standard && a.Package.ImportPath == "runtime/cgo" {
filter := func(files, nongcc, gcc []string) ([]string, []string) {
for _, f := range files {
if strings.HasPrefix(f, "gcc_") {
@@ -1497,31 +1334,43 @@ func (b *builder) build(a *action) (err error) {
}
sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles)
} else {
+ for _, sfile := range sfiles {
+ data, err := ioutil.ReadFile(filepath.Join(a.Package.Dir, sfile))
+ if err == nil {
+ if bytes.HasPrefix(data, []byte("TEXT")) || bytes.Contains(data, []byte("\nTEXT")) ||
+ bytes.HasPrefix(data, []byte("DATA")) || bytes.Contains(data, []byte("\nDATA")) ||
+ bytes.HasPrefix(data, []byte("GLOBL")) || bytes.Contains(data, []byte("\nGLOBL")) {
+ return fmt.Errorf("package using cgo has Go assembly file %s", sfile)
+ }
+ }
+ }
gccfiles = append(gccfiles, sfiles...)
sfiles = nil
}
- cgoExe := tool("cgo")
- if a.cgo != nil && a.cgo.target != "" {
- cgoExe = a.cgo.target
+ var cgoExe string
+ if a.cgo != nil && a.cgo.Target != "" {
+ cgoExe = a.cgo.Target
+ } else {
+ cgoExe = base.Tool("cgo")
}
- outGo, outObj, err := b.cgo(a, cgoExe, obj, pcCFLAGS, pcLDFLAGS, cgofiles, objdirCgofiles, gccfiles, cxxfiles, a.p.MFiles, a.p.FFiles)
+ outGo, outObj, err := b.cgo(a, cgoExe, obj, pcCFLAGS, pcLDFLAGS, cgofiles, objdirCgofiles, gccfiles, cxxfiles, a.Package.MFiles, a.Package.FFiles)
if err != nil {
return err
}
- if _, ok := buildToolchain.(gccgoToolchain); ok {
- cgoObjects = append(cgoObjects, filepath.Join(a.objdir, "_cgo_flags"))
+ if cfg.BuildToolchainName == "gccgo" {
+ cgoObjects = append(cgoObjects, filepath.Join(a.Objdir, "_cgo_flags"))
}
cgoObjects = append(cgoObjects, outObj...)
gofiles = append(gofiles, outGo...)
}
if len(gofiles) == 0 {
- return &build.NoGoError{Dir: a.p.Dir}
+ return &load.NoGoError{Package: a.Package}
}
// If we're doing coverage, preprocess the .go files and put them in the work directory
- if a.p.coverMode != "" {
+ if a.Package.Internal.CoverMode != "" {
for i, file := range gofiles {
var sourceFile string
var coverFile string
@@ -1533,12 +1382,12 @@ func (b *builder) build(a *action) (err error) {
coverFile = filepath.Join(obj, base)
key = strings.TrimSuffix(base, ".cgo1.go") + ".go"
} else {
- sourceFile = filepath.Join(a.p.Dir, file)
+ sourceFile = filepath.Join(a.Package.Dir, file)
coverFile = filepath.Join(obj, file)
key = file
}
- cover := a.p.coverVars[key]
- if cover == nil || isTestFile(file) {
+ cover := a.Package.Internal.CoverVars[key]
+ if cover == nil || base.IsTestFile(file) {
// Not covering this file.
continue
}
@@ -1553,9 +1402,9 @@ func (b *builder) build(a *action) (err error) {
inc := b.includeArgs("-I", allArchiveActions(a))
// Compile Go.
- ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, len(sfiles) > 0, inc, gofiles)
+ ofile, out, err := BuildToolchain.gc(b, a.Package, a.Objpkg, obj, len(sfiles) > 0, inc, gofiles)
if len(out) > 0 {
- b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out))
+ b.showOutput(a.Package.Dir, a.Package.ImportPath, b.processOutput(out))
if err != nil {
return errPrintedOutput
}
@@ -1563,32 +1412,32 @@ func (b *builder) build(a *action) (err error) {
if err != nil {
return err
}
- if ofile != a.objpkg {
+ if ofile != a.Objpkg {
objects = append(objects, ofile)
}
// Copy .h files named for goos or goarch or goos_goarch
// to names using GOOS and GOARCH.
// For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
- _goos_goarch := "_" + goos + "_" + goarch
- _goos := "_" + goos
- _goarch := "_" + goarch
- for _, file := range a.p.HFiles {
+ _goos_goarch := "_" + cfg.Goos + "_" + cfg.Goarch
+ _goos := "_" + cfg.Goos
+ _goarch := "_" + cfg.Goarch
+ for _, file := range a.Package.HFiles {
name, ext := fileExtSplit(file)
switch {
case strings.HasSuffix(name, _goos_goarch):
targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
- if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
+ if err := b.copyFile(a, obj+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
return err
}
case strings.HasSuffix(name, _goarch):
targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
- if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
+ if err := b.copyFile(a, obj+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
return err
}
case strings.HasSuffix(name, _goos):
targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
- if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
+ if err := b.copyFile(a, obj+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil {
return err
}
}
@@ -1596,7 +1445,7 @@ func (b *builder) build(a *action) (err error) {
for _, file := range cfiles {
out := file[:len(file)-len(".c")] + ".o"
- if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil {
+ if err := BuildToolchain.cc(b, a.Package, obj, obj+out, file); err != nil {
return err
}
objects = append(objects, out)
@@ -1604,7 +1453,7 @@ func (b *builder) build(a *action) (err error) {
// Assemble .s files.
if len(sfiles) > 0 {
- ofiles, err := buildToolchain.asm(b, a.p, obj, sfiles)
+ ofiles, err := BuildToolchain.asm(b, a.Package, obj, sfiles)
if err != nil {
return err
}
@@ -1618,8 +1467,8 @@ func (b *builder) build(a *action) (err error) {
objects = append(objects, cgoObjects...)
// Add system object files.
- for _, syso := range a.p.SysoFiles {
- objects = append(objects, filepath.Join(a.p.Dir, syso))
+ for _, syso := range a.Package.SysoFiles {
+ objects = append(objects, filepath.Join(a.Package.Dir, syso))
}
// Pack into archive in obj directory.
@@ -1628,18 +1477,18 @@ func (b *builder) build(a *action) (err error) {
// If the Go compiler wrote an archive and the package is entirely
// Go sources, there is no pack to execute at all.
if len(objects) > 0 {
- if err := buildToolchain.pack(b, a.p, obj, a.objpkg, objects); err != nil {
+ if err := BuildToolchain.pack(b, a.Package, obj, a.Objpkg, objects); err != nil {
return err
}
}
// Link if needed.
- if a.link {
+ if a.Link {
// The compiler only cares about direct imports, but the
// linker needs the whole dependency tree.
- all := actionList(a)
+ all := ActionList(a)
all = all[:len(all)-1] // drop a
- if err := buildToolchain.ld(b, a, a.target, all, a.objpkg, objects); err != nil {
+ if err := BuildToolchain.ld(b, a, a.Target, all, a.Objpkg, objects); err != nil {
return err
}
}
@@ -1647,10 +1496,10 @@ func (b *builder) build(a *action) (err error) {
return nil
}
-// pkgconfigCmd returns a pkg-config binary name
+// PkgconfigCmd returns a pkg-config binary name
// defaultPkgConfig is defined in zdefaultcc.go, written by cmd/dist.
-func (b *builder) pkgconfigCmd() string {
- return envList("PKG_CONFIG", defaultPkgConfig)[0]
+func (b *Builder) PkgconfigCmd() string {
+ return envList("PKG_CONFIG", cfg.DefaultPkgConfig)[0]
}
// splitPkgConfigOutput parses the pkg-config output into a slice of
@@ -1687,23 +1536,23 @@ func splitPkgConfigOutput(out []byte) []string {
}
// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
-func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err error) {
+func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) {
if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
var out []byte
- out, err = b.runOut(p.Dir, p.ImportPath, nil, b.pkgconfigCmd(), "--cflags", pkgs)
+ out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", pkgs)
if err != nil {
- b.showOutput(p.Dir, b.pkgconfigCmd()+" --cflags "+strings.Join(pkgs, " "), string(out))
- b.print(err.Error() + "\n")
+ b.showOutput(p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pkgs, " "), string(out))
+ b.Print(err.Error() + "\n")
err = errPrintedOutput
return
}
if len(out) > 0 {
cflags = splitPkgConfigOutput(out)
}
- out, err = b.runOut(p.Dir, p.ImportPath, nil, b.pkgconfigCmd(), "--libs", pkgs)
+ out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", pkgs)
if err != nil {
- b.showOutput(p.Dir, b.pkgconfigCmd()+" --libs "+strings.Join(pkgs, " "), string(out))
- b.print(err.Error() + "\n")
+ b.showOutput(p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pkgs, " "), string(out))
+ b.Print(err.Error() + "\n")
err = errPrintedOutput
return
}
@@ -1714,35 +1563,35 @@ func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err e
return
}
-func (b *builder) installShlibname(a *action) error {
- a1 := a.deps[0]
- err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0666)
+func (b *Builder) installShlibname(a *Action) error {
+ a1 := a.Deps[0]
+ err := ioutil.WriteFile(a.Target, []byte(filepath.Base(a1.Target)+"\n"), 0666)
if err != nil {
return err
}
- if buildX {
- b.showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.target), a.target)
+ if cfg.BuildX {
+ b.Showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.Target), a.Target)
}
return nil
}
-func (b *builder) linkShared(a *action) (err error) {
- allactions := actionList(a)
+func (b *Builder) linkShared(a *Action) (err error) {
+ allactions := ActionList(a)
allactions = allactions[:len(allactions)-1]
- return buildToolchain.ldShared(b, a.deps, a.target, allactions)
+ return BuildToolchain.ldShared(b, a.Deps, a.Target, allactions)
}
-// install is the action for installing a single package or executable.
-func (b *builder) install(a *action) (err error) {
+// BuildInstallFunc is the action for installing a single package or executable.
+func BuildInstallFunc(b *Builder, a *Action) (err error) {
defer func() {
if err != nil && err != errPrintedOutput {
- err = fmt.Errorf("go install %s: %v", a.p.ImportPath, err)
+ err = fmt.Errorf("go install %s: %v", a.Package.ImportPath, err)
}
}()
- a1 := a.deps[0]
+ a1 := a.Deps[0]
perm := os.FileMode(0666)
- if a1.link {
- switch buildBuildmode {
+ if a1.Link {
+ switch cfg.BuildBuildmode {
case "c-archive", "c-shared", "plugin":
default:
perm = 0777
@@ -1750,9 +1599,9 @@ func (b *builder) install(a *action) (err error) {
}
// make target directory
- dir, _ := filepath.Split(a.target)
+ dir, _ := filepath.Split(a.Target)
if dir != "" {
- if err := b.mkdir(dir); err != nil {
+ if err := b.Mkdir(dir); err != nil {
return err
}
}
@@ -1761,32 +1610,32 @@ func (b *builder) install(a *action) (err error) {
// garbage down in a large build. On an operating system
// with aggressive buffering, cleaning incrementally like
// this keeps the intermediate objects from hitting the disk.
- if !buildWork {
- defer os.RemoveAll(a1.objdir)
- defer os.Remove(a1.target)
+ if !cfg.BuildWork {
+ defer os.RemoveAll(a1.Objdir)
+ defer os.Remove(a1.Target)
}
- return b.moveOrCopyFile(a, a.target, a1.target, perm, false)
+ return b.moveOrCopyFile(a, a.Target, a1.Target, perm, false)
}
// includeArgs returns the -I or -L directory list for access
// to the results of the list of actions.
-func (b *builder) includeArgs(flag string, all []*action) []string {
+func (b *Builder) includeArgs(flag string, all []*Action) []string {
inc := []string{}
incMap := map[string]bool{
- b.work: true, // handled later
- gorootPkg: true,
- "": true, // ignore empty strings
+ b.WorkDir: true, // handled later
+ cfg.GOROOTpkg: true,
+ "": true, // ignore empty strings
}
// Look in the temporary space for results of test-specific actions.
// This is the $WORK/my/package/_test directory for the
// package being built, so there are few of these.
for _, a1 := range all {
- if a1.p == nil {
+ if a1.Package == nil {
continue
}
- if dir := a1.pkgdir; dir != a1.p.build.PkgRoot && !incMap[dir] {
+ if dir := a1.Pkgdir; dir != a1.Package.Internal.Build.PkgRoot && !incMap[dir] {
incMap[dir] = true
inc = append(inc, flag, dir)
}
@@ -1794,18 +1643,18 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
// Also look in $WORK for any non-test packages that have
// been built but not installed.
- inc = append(inc, flag, b.work)
+ inc = append(inc, flag, b.WorkDir)
// Finally, look in the installed package directories for each action.
// First add the package dirs corresponding to GOPATH entries
// in the original GOPATH order.
need := map[string]*build.Package{}
for _, a1 := range all {
- if a1.p != nil && a1.pkgdir == a1.p.build.PkgRoot {
- need[a1.p.build.Root] = a1.p.build
+ if a1.Package != nil && a1.Pkgdir == a1.Package.Internal.Build.PkgRoot {
+ need[a1.Package.Internal.Build.Root] = a1.Package.Internal.Build
}
}
- for _, root := range gopath {
+ for _, root := range cfg.Gopath {
if p := need[root]; p != nil && !incMap[p.PkgRoot] {
incMap[p.PkgRoot] = true
inc = append(inc, flag, p.PkgTargetRoot)
@@ -1814,12 +1663,12 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
// Then add anything that's left.
for _, a1 := range all {
- if a1.p == nil {
+ if a1.Package == nil {
continue
}
- if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] {
+ if dir := a1.Pkgdir; dir == a1.Package.Internal.Build.PkgRoot && !incMap[dir] {
incMap[dir] = true
- inc = append(inc, flag, a1.p.build.PkgTargetRoot)
+ inc = append(inc, flag, a1.Package.Internal.Build.PkgTargetRoot)
}
}
@@ -1827,15 +1676,24 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
}
// moveOrCopyFile is like 'mv src dst' or 'cp src dst'.
-func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode, force bool) error {
- if buildN {
- b.showcmd("", "mv %s %s", src, dst)
+func (b *Builder) moveOrCopyFile(a *Action, dst, src string, perm os.FileMode, force bool) error {
+ if cfg.BuildN {
+ b.Showcmd("", "mv %s %s", src, dst)
return nil
}
// If we can update the mode and rename to the dst, do it.
// Otherwise fall back to standard copy.
+ // If the destination directory has the group sticky bit set,
+ // we have to copy the file to retain the correct permissions.
+ // https://golang.org/issue/18878
+ if fi, err := os.Stat(filepath.Dir(dst)); err == nil {
+ if fi.IsDir() && (fi.Mode()&os.ModeSetgid) != 0 {
+ return b.copyFile(a, dst, src, perm, force)
+ }
+ }
+
// The perm argument is meant to be adjusted according to umask,
// but we don't know what the umask is.
// Create a dummy file to find out.
@@ -1855,8 +1713,8 @@ func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode, f
if err := os.Chmod(src, mode); err == nil {
if err := os.Rename(src, dst); err == nil {
- if buildX {
- b.showcmd("", "mv %s %s", src, dst)
+ if cfg.BuildX {
+ b.Showcmd("", "mv %s %s", src, dst)
}
return nil
}
@@ -1866,10 +1724,10 @@ func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode, f
}
// copyFile is like 'cp src dst'.
-func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force bool) error {
- if buildN || buildX {
- b.showcmd("", "cp %s %s", src, dst)
- if buildN {
+func (b *Builder) copyFile(a *Action, dst, src string, perm os.FileMode, force bool) error {
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd("", "cp %s %s", src, dst)
+ if cfg.BuildN {
return nil
}
}
@@ -1893,7 +1751,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
}
// On Windows, remove lingering ~ file from last attempt.
- if toolIsWindows {
+ if base.ToolIsWindows {
if _, err := os.Stat(dst + "~"); err == nil {
os.Remove(dst + "~")
}
@@ -1901,7 +1759,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
mayberemovefile(dst)
df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
- if err != nil && toolIsWindows {
+ if err != nil && base.ToolIsWindows {
// Windows does not allow deletion of a binary file
// while it is executing. Try to move it out of the way.
// If the move fails, which is likely, we'll try again the
@@ -1925,31 +1783,31 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
}
// Install the cgo export header file, if there is one.
-func (b *builder) installHeader(a *action) error {
- src := a.objdir + "_cgo_install.h"
+func (b *Builder) installHeader(a *Action) error {
+ src := a.Objdir + "_cgo_install.h"
if _, err := os.Stat(src); os.IsNotExist(err) {
// If the file does not exist, there are no exported
// functions, and we do not install anything.
return nil
}
- dir, _ := filepath.Split(a.target)
+ dir, _ := filepath.Split(a.Target)
if dir != "" {
- if err := b.mkdir(dir); err != nil {
+ if err := b.Mkdir(dir); err != nil {
return err
}
}
- return b.moveOrCopyFile(a, a.target, src, 0666, true)
+ return b.moveOrCopyFile(a, a.Target, src, 0666, true)
}
// cover runs, in effect,
// go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go
-func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error {
- return b.run(a.objdir, "cover "+a.p.ImportPath, nil,
- buildToolExec,
- tool("cover"),
- "-mode", a.p.coverMode,
+func (b *Builder) cover(a *Action, dst, src string, perm os.FileMode, varName string) error {
+ return b.run(a.Objdir, "cover "+a.Package.ImportPath, nil,
+ cfg.BuildToolexec,
+ base.Tool("cover"),
+ "-mode", a.Package.Internal.CoverMode,
"-var", varName,
"-o", dst,
src)
@@ -1999,14 +1857,14 @@ func mayberemovefile(s string) {
// If dir is non-empty and the script is not in dir right now,
// fmtcmd inserts "cd dir\n" before the command.
//
-// fmtcmd replaces the value of b.work with $WORK.
+// fmtcmd replaces the value of b.WorkDir with $WORK.
// fmtcmd replaces the value of goroot with $GOROOT.
// fmtcmd replaces the value of b.gobin with $GOBIN.
//
// fmtcmd replaces the name of the current directory with dot (.)
// but only when it is at the beginning of a space-separated token.
//
-func (b *builder) fmtcmd(dir string, format string, args ...interface{}) string {
+func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string {
cmd := fmt.Sprintf(format, args...)
if dir != "" && dir != "/" {
cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:]
@@ -2015,18 +1873,18 @@ func (b *builder) fmtcmd(dir string, format string, args ...interface{}) string
cmd = "cd " + dir + "\n" + cmd
}
}
- if b.work != "" {
- cmd = strings.Replace(cmd, b.work, "$WORK", -1)
+ if b.WorkDir != "" {
+ cmd = strings.Replace(cmd, b.WorkDir, "$WORK", -1)
}
return cmd
}
// showcmd prints the given command to standard output
// for the implementation of -n or -x.
-func (b *builder) showcmd(dir string, format string, args ...interface{}) {
+func (b *Builder) Showcmd(dir string, format string, args ...interface{}) {
b.output.Lock()
defer b.output.Unlock()
- b.print(b.fmtcmd(dir, format, args...) + "\n")
+ b.Print(b.fmtcmd(dir, format, args...) + "\n")
}
// showOutput prints "# desc" followed by the given output.
@@ -2051,41 +1909,18 @@ func (b *builder) showcmd(dir string, format string, args ...interface{}) {
//
// showOutput also replaces references to the work directory with $WORK.
//
-func (b *builder) showOutput(dir, desc, out string) {
+func (b *Builder) showOutput(dir, desc, out string) {
prefix := "# " + desc
suffix := "\n" + out
- if reldir := shortPath(dir); reldir != dir {
+ if reldir := base.ShortPath(dir); reldir != dir {
suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1)
suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1)
}
- suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1)
+ suffix = strings.Replace(suffix, " "+b.WorkDir, " $WORK", -1)
b.output.Lock()
defer b.output.Unlock()
- b.print(prefix, suffix)
-}
-
-// shortPath returns an absolute or relative name for path, whatever is shorter.
-func shortPath(path string) string {
- if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
- return rel
- }
- return path
-}
-
-// relPaths returns a copy of paths with absolute paths
-// made relative to the current directory if they would be shorter.
-func relPaths(paths []string) []string {
- var out []string
- pwd, _ := os.Getwd()
- for _, p := range paths {
- rel, err := filepath.Rel(pwd, p)
- if err == nil && len(rel) < len(p) {
- p = rel
- }
- out = append(out, p)
- }
- return out
+ b.Print(prefix, suffix)
}
// errPrintedOutput is a special error indicating that a command failed
@@ -2095,17 +1930,17 @@ func relPaths(paths []string) []string {
// print this error.
var errPrintedOutput = errors.New("already printed output - no need to show error")
-var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`)
+var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+(:[0-9]+)?\]`)
var cgoTypeSigRe = regexp.MustCompile(`\b_Ctype_\B`)
// run runs the command given by cmdline in the directory dir.
// If the command fails, run prints information about the failure
// and returns a non-nil error.
-func (b *builder) run(dir string, desc string, env []string, cmdargs ...interface{}) error {
+func (b *Builder) run(dir string, desc string, env []string, cmdargs ...interface{}) error {
out, err := b.runOut(dir, desc, env, cmdargs...)
if len(out) > 0 {
if desc == "" {
- desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " "))
+ desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " "))
}
b.showOutput(dir, desc, b.processOutput(out))
if err != nil {
@@ -2116,7 +1951,7 @@ func (b *builder) run(dir string, desc string, env []string, cmdargs ...interfac
}
// processOutput prepares the output of runOut to be output to the console.
-func (b *builder) processOutput(out []byte) string {
+func (b *Builder) processOutput(out []byte) string {
if out[len(out)-1] != '\n' {
out = append(out, '\n')
}
@@ -2125,7 +1960,7 @@ func (b *builder) processOutput(out []byte) string {
// Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19.
// Replace *[100]_Ctype_foo with *[100]C.foo.
// If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
- if !buildX && cgoLine.MatchString(messages) {
+ if !cfg.BuildX && cgoLine.MatchString(messages) {
messages = cgoLine.ReplaceAllString(messages, "")
messages = cgoTypeSigRe.ReplaceAllString(messages, "C.")
}
@@ -2134,17 +1969,17 @@ func (b *builder) processOutput(out []byte) string {
// runOut runs the command given by cmdline in the directory dir.
// It returns the command output and any errors that occurred.
-func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
- cmdline := stringList(cmdargs...)
- if buildN || buildX {
+func (b *Builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
+ cmdline := str.StringList(cmdargs...)
+ if cfg.BuildN || cfg.BuildX {
var envcmdline string
for i := range env {
envcmdline += env[i]
envcmdline += " "
}
envcmdline += joinUnambiguously(cmdline)
- b.showcmd(dir, "%s", envcmdline)
- if buildN {
+ b.Showcmd(dir, "%s", envcmdline)
+ if cfg.BuildN {
return nil, nil
}
}
@@ -2156,7 +1991,7 @@ func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...inter
cmd.Stdout = &buf
cmd.Stderr = &buf
cmd.Dir = dir
- cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir, os.Environ()))
+ cmd.Env = base.MergeEnvLists(env, base.EnvForDir(cmd.Dir, os.Environ()))
err := cmd.Run()
// cmd.Run will fail on Unix if some other process has the binary
@@ -2177,7 +2012,7 @@ func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...inter
// until the time of the explicit close, and the race would remain.
//
// On Unix systems, this results in ETXTBSY, which formats
- // as "text file busy". Rather than hard-code specific error cases,
+ // as "text file busy". Rather than hard-code specific error cases,
// we just look for that string. If this happens, sleep a little
// and try again. We let this happen three times, with increasing
// sleep lengths: 100+200+400 ms = 0.7 seconds.
@@ -2238,7 +2073,7 @@ func joinUnambiguously(a []string) string {
}
// mkdir makes the named directory.
-func (b *builder) mkdir(dir string) error {
+func (b *Builder) Mkdir(dir string) error {
b.exec.Lock()
defer b.exec.Unlock()
// We can be a little aggressive about being
@@ -2248,9 +2083,9 @@ func (b *builder) mkdir(dir string) error {
}
b.mkdirCache[dir] = true
- if buildN || buildX {
- b.showcmd("", "mkdir -p %s", dir)
- if buildN {
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd("", "mkdir -p %s", dir)
+ if cfg.BuildN {
return nil
}
}
@@ -2280,23 +2115,23 @@ func mkAbs(dir, f string) string {
type toolchain interface {
// gc runs the compiler in a specific directory on a set of files
// and returns the name of the generated output file.
- gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
+ gc(b *Builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
// cc runs the toolchain's C compiler in a directory on a C file
// to produce an output file.
- cc(b *builder, p *Package, objdir, ofile, cfile string) error
+ cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error
// asm runs the assembler in a specific directory on specific files
// and returns a list of named output files.
- asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error)
+ asm(b *Builder, p *load.Package, obj string, sfiles []string) ([]string, error)
// pkgpath builds an appropriate path for a temporary package file.
- pkgpath(basedir string, p *Package) string
+ Pkgpath(basedir string, p *load.Package) string
// pack runs the archive packer in a specific directory to create
// an archive from a set of object files.
// typically it is run in the object directory.
- pack(b *builder, p *Package, objDir, afile string, ofiles []string) error
+ pack(b *Builder, p *load.Package, objDir, afile string, ofiles []string) error
// ld runs the linker to create an executable starting at mainpkg.
- ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error
+ ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error
// ldShared runs the linker to create a shared library containing the pkgs built by toplevelactions
- ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error
+ ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error
compiler() string
linker() string
@@ -2305,7 +2140,7 @@ type toolchain interface {
type noToolchain struct{}
func noCompiler() error {
- log.Fatalf("unknown compiler %q", buildContext.Compiler)
+ log.Fatalf("unknown compiler %q", cfg.BuildContext.Compiler)
return nil
}
@@ -2319,32 +2154,32 @@ func (noToolchain) linker() string {
return ""
}
-func (noToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
+func (noToolchain) gc(b *Builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
return "", nil, noCompiler()
}
-func (noToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
+func (noToolchain) asm(b *Builder, p *load.Package, obj string, sfiles []string) ([]string, error) {
return nil, noCompiler()
}
-func (noToolchain) pkgpath(basedir string, p *Package) string {
+func (noToolchain) Pkgpath(basedir string, p *load.Package) string {
noCompiler()
return ""
}
-func (noToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (noToolchain) pack(b *Builder, p *load.Package, objDir, afile string, ofiles []string) error {
return noCompiler()
}
-func (noToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
+func (noToolchain) ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error {
return noCompiler()
}
-func (noToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error {
+func (noToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error {
return noCompiler()
}
-func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+func (noToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error {
return noCompiler()
}
@@ -2352,14 +2187,14 @@ func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error
type gcToolchain struct{}
func (gcToolchain) compiler() string {
- return tool("compile")
+ return base.Tool("compile")
}
func (gcToolchain) linker() string {
- return tool("link")
+ return base.Tool("link")
}
-func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+func (gcToolchain) gc(b *Builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
if archive != "" {
ofile = archive
} else {
@@ -2371,7 +2206,11 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
if p.Name == "main" {
gcargs[1] = "main"
}
- if p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal")) {
+ if p.Standard {
+ gcargs = append(gcargs, "-std")
+ }
+ compilingRuntime := p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal"))
+ if compilingRuntime {
// runtime compiles with a special gc flag to emit
// additional reflect type data.
gcargs = append(gcargs, "-+")
@@ -2384,18 +2223,22 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.FFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles)
if p.Standard {
switch p.ImportPath {
- case "bytes", "net", "os", "runtime/pprof", "sync", "time":
+ case "bytes", "internal/poll", "net", "os", "runtime/pprof", "sync", "syscall", "time":
extFiles++
}
}
if extFiles == 0 {
gcargs = append(gcargs, "-complete")
}
- if buildContext.InstallSuffix != "" {
- gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix)
+ if cfg.BuildContext.InstallSuffix != "" {
+ gcargs = append(gcargs, "-installsuffix", cfg.BuildContext.InstallSuffix)
+ }
+ if p.Internal.BuildID != "" {
+ gcargs = append(gcargs, "-buildid", p.Internal.BuildID)
}
- if p.buildID != "" {
- gcargs = append(gcargs, "-buildid", p.buildID)
+ platform := cfg.Goos + "/" + cfg.Goarch
+ if p.Internal.OmitDebug || platform == "nacl/amd64p32" || platform == "darwin/arm" || platform == "darwin/arm64" || cfg.Goos == "plan9" {
+ gcargs = append(gcargs, "-dwarf=false")
}
for _, path := range p.Imports {
@@ -2406,13 +2249,34 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
}
}
- args := []interface{}{buildToolExec, tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs}
+ gcflags := buildGcflags
+ if compilingRuntime {
+ // Remove -N, if present.
+ // It is not possible to build the runtime with no optimizations,
+ // because the compiler cannot eliminate enough write barriers.
+ gcflags = make([]string, len(buildGcflags))
+ copy(gcflags, buildGcflags)
+ for i := 0; i < len(gcflags); i++ {
+ if gcflags[i] == "-N" {
+ copy(gcflags[i:], gcflags[i+1:])
+ gcflags = gcflags[:len(gcflags)-1]
+ i--
+ }
+ }
+ }
+ args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", b.WorkDir, gcflags, gcargs, "-D", p.Internal.LocalPrefix, importArgs}
if ofile == archive {
args = append(args, "-pack")
}
if asmhdr {
args = append(args, "-asmhdr", obj+"go_asm.h")
}
+
+ // Add -c=N to use concurrent backend compilation, if possible.
+ if c := gcBackendConcurrency(gcflags); c > 1 {
+ args = append(args, fmt.Sprintf("-c=%d", c))
+ }
+
for _, f := range gofiles {
args = append(args, mkAbs(p.Dir, f))
}
@@ -2421,11 +2285,82 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
return ofile, output, err
}
-func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
+// gcBackendConcurrency returns the backend compiler concurrency level for a package compilation.
+func gcBackendConcurrency(gcflags []string) int {
+ // First, check whether we can use -c at all for this compilation.
+ canDashC := concurrentGCBackendCompilationEnabledByDefault
+
+ switch e := os.Getenv("GO19CONCURRENTCOMPILATION"); e {
+ case "0":
+ canDashC = false
+ case "1":
+ canDashC = true
+ case "":
+ // Not set. Use default.
+ default:
+ log.Fatalf("GO19CONCURRENTCOMPILATION must be 0, 1, or unset, got %q", e)
+ }
+
+ if os.Getenv("GOEXPERIMENT") != "" {
+ // Concurrent compilation is presumed incompatible with GOEXPERIMENTs.
+ canDashC = false
+ }
+
+CheckFlags:
+ for _, flag := range gcflags {
+ // Concurrent compilation is presumed incompatible with any gcflags,
+ // except for a small whitelist of commonly used flags.
+ // If the user knows better, they can manually add their own -c to the gcflags.
+ switch flag {
+ case "-N", "-l", "-S", "-B", "-C", "-I":
+ // OK
+ default:
+ canDashC = false
+ break CheckFlags
+ }
+ }
+
+ if !canDashC {
+ return 1
+ }
+
+ // Decide how many concurrent backend compilations to allow.
+ //
+ // If we allow too many, in theory we might end up with p concurrent processes,
+ // each with c concurrent backend compiles, all fighting over the same resources.
+ // However, in practice, that seems not to happen too much.
+ // Most build graphs are surprisingly serial, so p==1 for much of the build.
+ // Furthermore, concurrent backend compilation is only enabled for a part
+ // of the overall compiler execution, so c==1 for much of the build.
+ // So don't worry too much about that interaction for now.
+ //
+ // However, in practice, setting c above 4 tends not to help very much.
+ // See the analysis in CL 41192.
+ //
+ // TODO(josharian): attempt to detect whether this particular compilation
+ // is likely to be a bottleneck, e.g. when:
+ // - it has no successor packages to compile (usually package main)
+ // - all paths through the build graph pass through it
+ // - critical path scheduling says it is high priority
+ // and in such a case, set c to runtime.NumCPU.
+ // We do this now when p==1.
+ if cfg.BuildP == 1 {
+ // No process parallelism. Max out c.
+ return runtime.NumCPU()
+ }
+ // Some process parallelism. Set c to min(4, numcpu).
+ c := 4
+ if ncpu := runtime.NumCPU(); ncpu < c {
+ c = ncpu
+ }
+ return c
+}
+
+func (gcToolchain) asm(b *Builder, p *load.Package, obj string, sfiles []string) ([]string, error) {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
- inc := filepath.Join(goroot, "pkg", "include")
- args := []interface{}{buildToolExec, tool("asm"), "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags}
- if p.ImportPath == "runtime" && goarch == "386" {
+ inc := filepath.Join(cfg.GOROOT, "pkg", "include")
+ args := []interface{}{cfg.BuildToolexec, base.Tool("asm"), "-trimpath", b.WorkDir, "-I", obj, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, buildAsmflags}
+ if p.ImportPath == "runtime" && cfg.Goarch == "386" {
for _, arg := range buildAsmflags {
if arg == "-dynlink" {
args = append(args, "-D=GOBUILDMODE_shared=1")
@@ -2447,10 +2382,10 @@ func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]s
// toolVerify checks that the command line args writes the same output file
// if run using newTool instead.
// Unused now but kept around for future use.
-func toolVerify(b *builder, p *Package, newTool string, ofile string, args []interface{}) error {
+func toolVerify(b *Builder, p *load.Package, newTool string, ofile string, args []interface{}) error {
newArgs := make([]interface{}, len(args))
copy(newArgs, args)
- newArgs[1] = tool(newTool)
+ newArgs[1] = base.Tool(newTool)
newArgs[3] = ofile + ".new" // x.6 becomes x.6.new
if err := b.run(p.Dir, p.ImportPath, nil, newArgs...); err != nil {
return err
@@ -2464,18 +2399,18 @@ func toolVerify(b *builder, p *Package, newTool string, ofile string, args []int
return err
}
if !bytes.Equal(data1, data2) {
- return fmt.Errorf("%s and %s produced different output files:\n%s\n%s", filepath.Base(args[1].(string)), newTool, strings.Join(stringList(args...), " "), strings.Join(stringList(newArgs...), " "))
+ return fmt.Errorf("%s and %s produced different output files:\n%s\n%s", filepath.Base(args[1].(string)), newTool, strings.Join(str.StringList(args...), " "), strings.Join(str.StringList(newArgs...), " "))
}
os.Remove(ofile + ".new")
return nil
}
-func (gcToolchain) pkgpath(basedir string, p *Package) string {
+func (gcToolchain) Pkgpath(basedir string, p *load.Package) string {
end := filepath.FromSlash(p.ImportPath + ".a")
return filepath.Join(basedir, end)
}
-func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (gcToolchain) pack(b *Builder, p *load.Package, objDir, afile string, ofiles []string) error {
var absOfiles []string
for _, f := range ofiles {
absOfiles = append(absOfiles, mkAbs(objDir, f))
@@ -2484,17 +2419,17 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
// The archive file should have been created by the compiler.
// Since it used to not work that way, verify.
- if !buildN {
+ if !cfg.BuildN {
if _, err := os.Stat(absAfile); err != nil {
- fatalf("os.Stat of archive file failed: %v", err)
+ base.Fatalf("os.Stat of archive file failed: %v", err)
}
}
- if buildN || buildX {
- cmdline := stringList("pack", "r", absAfile, absOfiles)
- b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
+ if cfg.BuildN || cfg.BuildX {
+ cmdline := str.StringList("pack", "r", absAfile, absOfiles)
+ b.Showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
}
- if buildN {
+ if cfg.BuildN {
return nil
}
if err := packInternal(b, absAfile, absOfiles); err != nil {
@@ -2504,7 +2439,7 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
return nil
}
-func packInternal(b *builder, afile string, ofiles []string) error {
+func packInternal(b *Builder, afile string, ofiles []string) error {
dst, err := os.OpenFile(afile, os.O_WRONLY|os.O_APPEND, 0)
if err != nil {
return err
@@ -2584,25 +2519,25 @@ func setextld(ldflags []string, compiler []string) []string {
return ldflags
}
-func (gcToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
+func (gcToolchain) ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error {
importArgs := b.includeArgs("-L", allactions)
- cxx := len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0
+ cxx := len(root.Package.CXXFiles) > 0 || len(root.Package.SwigCXXFiles) > 0
for _, a := range allactions {
- if a.p != nil && (len(a.p.CXXFiles) > 0 || len(a.p.SwigCXXFiles) > 0) {
+ if a.Package != nil && (len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0) {
cxx = true
}
}
var ldflags []string
- if buildContext.InstallSuffix != "" {
- ldflags = append(ldflags, "-installsuffix", buildContext.InstallSuffix)
+ if cfg.BuildContext.InstallSuffix != "" {
+ ldflags = append(ldflags, "-installsuffix", cfg.BuildContext.InstallSuffix)
}
- if root.p.omitDWARF {
- ldflags = append(ldflags, "-w")
+ if root.Package.Internal.OmitDebug {
+ ldflags = append(ldflags, "-s", "-w")
}
- if buildBuildmode == "plugin" {
- pluginpath := root.p.ImportPath
+ if cfg.BuildBuildmode == "plugin" {
+ pluginpath := root.Package.ImportPath
if pluginpath == "command-line-arguments" {
- pluginpath = "plugin/unnamed-" + root.p.buildID
+ pluginpath = "plugin/unnamed-" + root.Package.Internal.BuildID
}
ldflags = append(ldflags, "-pluginpath", pluginpath)
}
@@ -2613,16 +2548,16 @@ func (gcToolchain) ld(b *builder, root *action, out string, allactions []*action
// Else, use the CC environment variable and defaultCC as fallback.
var compiler []string
if cxx {
- compiler = envList("CXX", defaultCXX)
+ compiler = envList("CXX", cfg.DefaultCXX)
} else {
- compiler = envList("CC", defaultCC)
+ compiler = envList("CC", cfg.DefaultCC)
}
ldflags = setextld(ldflags, compiler)
ldflags = append(ldflags, "-buildmode="+ldBuildmode)
- if root.p.buildID != "" {
- ldflags = append(ldflags, "-buildid="+root.p.buildID)
+ if root.Package.Internal.BuildID != "" {
+ ldflags = append(ldflags, "-buildid="+root.Package.Internal.BuildID)
}
- ldflags = append(ldflags, buildLdflags...)
+ ldflags = append(ldflags, cfg.BuildLdflags...)
// On OS X when using external linking to build a shared library,
// the argument passed here to -o ends up recorded in the final
@@ -2632,21 +2567,21 @@ func (gcToolchain) ld(b *builder, root *action, out string, allactions []*action
// run the link in the output directory so that -o can name
// just the final path element.
dir := "."
- if goos == "darwin" && buildBuildmode == "c-shared" {
+ if cfg.Goos == "darwin" && cfg.BuildBuildmode == "c-shared" {
dir, out = filepath.Split(out)
}
- return b.run(dir, root.p.ImportPath, nil, buildToolExec, tool("link"), "-o", out, importArgs, ldflags, mainpkg)
+ return b.run(dir, root.Package.ImportPath, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags, mainpkg)
}
-func (gcToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error {
+func (gcToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error {
importArgs := b.includeArgs("-L", allactions)
- ldflags := []string{"-installsuffix", buildContext.InstallSuffix}
+ ldflags := []string{"-installsuffix", cfg.BuildContext.InstallSuffix}
ldflags = append(ldflags, "-buildmode=shared")
- ldflags = append(ldflags, buildLdflags...)
+ ldflags = append(ldflags, cfg.BuildLdflags...)
cxx := false
for _, a := range allactions {
- if a.p != nil && (len(a.p.CXXFiles) > 0 || len(a.p.SwigCXXFiles) > 0) {
+ if a.Package != nil && (len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0) {
cxx = true
}
}
@@ -2656,58 +2591,71 @@ func (gcToolchain) ldShared(b *builder, toplevelactions []*action, out string, a
// Else, use the CC environment variable and defaultCC as fallback.
var compiler []string
if cxx {
- compiler = envList("CXX", defaultCXX)
+ compiler = envList("CXX", cfg.DefaultCXX)
} else {
- compiler = envList("CC", defaultCC)
+ compiler = envList("CC", cfg.DefaultCC)
}
ldflags = setextld(ldflags, compiler)
for _, d := range toplevelactions {
- if !strings.HasSuffix(d.target, ".a") { // omit unsafe etc and actions for other shared libraries
+ if !strings.HasSuffix(d.Target, ".a") { // omit unsafe etc and actions for other shared libraries
continue
}
- ldflags = append(ldflags, d.p.ImportPath+"="+d.target)
+ ldflags = append(ldflags, d.Package.ImportPath+"="+d.Target)
}
- return b.run(".", out, nil, buildToolExec, tool("link"), "-o", out, importArgs, ldflags)
+ return b.run(".", out, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, importArgs, ldflags)
}
-func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
+func (gcToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error {
return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(p.Dir, cfile))
}
// The Gccgo toolchain.
type gccgoToolchain struct{}
-var gccgoName, gccgoBin string
+var GccgoName, GccgoBin string
+var gccgoErr error
func init() {
- gccgoName = os.Getenv("GCCGO")
- if gccgoName == "" {
- gccgoName = defaultGCCGO
+ GccgoName = os.Getenv("GCCGO")
+ if GccgoName == "" {
+ GccgoName = cfg.DefaultGCCGO
}
- gccgoBin, _ = exec.LookPath(gccgoName)
+ GccgoBin, gccgoErr = exec.LookPath(GccgoName)
}
func (gccgoToolchain) compiler() string {
- return gccgoBin
+ checkGccgoBin()
+ return GccgoBin
}
func (gccgoToolchain) linker() string {
- return gccgoBin
+ checkGccgoBin()
+ return GccgoBin
+}
+
+func checkGccgoBin() {
+ if gccgoErr == nil {
+ return
+ }
+ fmt.Fprintf(os.Stderr, "cmd/go: gccgo: %s\n", gccgoErr)
+ os.Exit(2)
}
-func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+func (tools gccgoToolchain) gc(b *Builder, p *load.Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
out := "_go_.o"
ofile = obj + out
gcargs := []string{"-g"}
gcargs = append(gcargs, b.gccArchArgs()...)
- gcargs = append(gcargs, "-fdebug-prefix-map="+b.work+"=/tmp/go-build")
+ gcargs = append(gcargs, "-fdebug-prefix-map="+b.WorkDir+"=/tmp/go-build")
gcargs = append(gcargs, "-gno-record-gcc-switches")
if pkgpath := gccgoPkgpath(p); pkgpath != "" {
gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath)
}
- if p.localPrefix != "" {
- gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix)
+ if p.Internal.LocalPrefix != "" {
+ gcargs = append(gcargs, "-fgo-relative-import-path="+p.Internal.LocalPrefix)
}
+
+ // Handle vendor directories
savedirs := []string{}
for _, incdir := range importArgs {
if incdir != "-I" {
@@ -2720,7 +2668,7 @@ func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmh
if i := strings.LastIndex(path, "/vendor/"); i >= 0 {
for _, dir := range savedirs {
// Check if the vendor path is already included in dir
- if strings.HasSuffix(dir, path[:i+len("/vendor/")]) {
+ if strings.HasSuffix(dir, path[:i+len("/vendor")]) {
continue
}
// Make sure this vendor path is not already in the list for importArgs
@@ -2757,7 +2705,7 @@ func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmh
}
}
- args := stringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
+ args := str.StringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags)
for _, f := range gofiles {
args = append(args, mkAbs(p.Dir, f))
}
@@ -2766,13 +2714,13 @@ func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmh
return ofile, output, err
}
-func (tools gccgoToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
+func (tools gccgoToolchain) asm(b *Builder, p *load.Package, obj string, sfiles []string) ([]string, error) {
var ofiles []string
for _, sfile := range sfiles {
ofile := obj + sfile[:len(sfile)-len(".s")] + ".o"
ofiles = append(ofiles, ofile)
sfile = mkAbs(p.Dir, sfile)
- defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
+ defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch}
if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
defs = append(defs, `-D`, `GOPKGPATH=`+pkgpath)
}
@@ -2786,14 +2734,14 @@ func (tools gccgoToolchain) asm(b *builder, p *Package, obj string, sfiles []str
return ofiles, nil
}
-func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
+func (gccgoToolchain) Pkgpath(basedir string, p *load.Package) string {
end := filepath.FromSlash(p.ImportPath + ".a")
afile := filepath.Join(basedir, end)
// add "lib" to the final element
return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile))
}
-func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error {
+func (gccgoToolchain) pack(b *Builder, p *load.Package, objDir, afile string, ofiles []string) error {
var absOfiles []string
for _, f := range ofiles {
absOfiles = append(absOfiles, mkAbs(objDir, f))
@@ -2806,7 +2754,7 @@ func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
return nil
}
-func (tools gccgoToolchain) link(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string, buildmode, desc string) error {
+func (tools gccgoToolchain) link(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string, buildmode, desc string) error {
// gccgo needs explicit linking with all package dependencies,
// and all LDFLAGS from cgo dependencies.
apackagePathsSeen := make(map[string]bool)
@@ -2818,10 +2766,10 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
cxx := false
objc := false
fortran := false
- if root.p != nil {
- cxx = len(root.p.CXXFiles) > 0 || len(root.p.SwigCXXFiles) > 0
- objc = len(root.p.MFiles) > 0
- fortran = len(root.p.FFiles) > 0
+ if root.Package != nil {
+ cxx = len(root.Package.CXXFiles) > 0 || len(root.Package.SwigCXXFiles) > 0
+ objc = len(root.Package.MFiles) > 0
+ fortran = len(root.Package.FFiles) > 0
}
readCgoFlags := func(flagsFile string) error {
@@ -2832,14 +2780,35 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
const ldflagsPrefix = "_CGO_LDFLAGS="
for _, line := range strings.Split(string(flags), "\n") {
if strings.HasPrefix(line, ldflagsPrefix) {
- newFlags := strings.Fields(line[len(ldflagsPrefix):])
- for _, flag := range newFlags {
- // Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS
- // but they don't mean anything to the linker so filter
- // them out.
- if flag != "-g" && !strings.HasPrefix(flag, "-O") {
- cgoldflags = append(cgoldflags, flag)
+ line = line[len(ldflagsPrefix):]
+ quote := byte(0)
+ start := true
+ var nl []byte
+ for len(line) > 0 {
+ b := line[0]
+ line = line[1:]
+ if quote == 0 && (b == ' ' || b == '\t') {
+ if len(nl) > 0 {
+ cgoldflags = append(cgoldflags, string(nl))
+ nl = nil
+ }
+ start = true
+ continue
+ } else if b == '"' || b == '\'' {
+ quote = b
+ } else if b == quote {
+ quote = 0
+ } else if quote == 0 && start && b == '-' && strings.HasPrefix(line, "g") {
+ line = line[1:]
+ continue
+ } else if quote == 0 && start && b == '-' && strings.HasPrefix(line, "O") {
+ for len(line) > 0 && line[0] != ' ' && line[0] != '\t' {
+ line = line[1:]
+ }
+ continue
}
+ nl = append(nl, b)
+ start = false
}
}
}
@@ -2847,7 +2816,7 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
}
readAndRemoveCgoFlags := func(archive string) (string, error) {
- newa, err := ioutil.TempFile(b.work, filepath.Base(archive))
+ newa, err := ioutil.TempFile(b.WorkDir, filepath.Base(archive))
if err != nil {
return "", err
}
@@ -2869,7 +2838,7 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
}
newarchive := newa.Name()
- err = b.run(b.work, desc, nil, "ar", "x", newarchive, "_cgo_flags")
+ err = b.run(b.WorkDir, desc, nil, "ar", "x", newarchive, "_cgo_flags")
if err != nil {
return "", err
}
@@ -2877,27 +2846,27 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
if err != nil {
return "", err
}
- err = readCgoFlags(filepath.Join(b.work, "_cgo_flags"))
+ err = readCgoFlags(filepath.Join(b.WorkDir, "_cgo_flags"))
if err != nil {
return "", err
}
return newarchive, nil
}
- actionsSeen := make(map[*action]bool)
+ actionsSeen := make(map[*Action]bool)
// Make a pre-order depth-first traversal of the action graph, taking note of
// whether a shared library action has been seen on the way to an action (the
// construction of the graph means that if any path to a node passes through
// a shared library action, they all do).
- var walk func(a *action, seenShlib bool)
+ var walk func(a *Action, seenShlib bool)
var err error
- walk = func(a *action, seenShlib bool) {
+ walk = func(a *Action, seenShlib bool) {
if actionsSeen[a] {
return
}
actionsSeen[a] = true
- if a.p != nil && !seenShlib {
- if a.p.Standard {
+ if a.Package != nil && !seenShlib {
+ if a.Package.Standard {
return
}
// We record the target of the first time we see a .a file
@@ -2905,12 +2874,12 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
// rather than the 'build' location (which may not exist any
// more). We still need to traverse the dependencies of the
// build action though so saying
- // if apackagePathsSeen[a.p.ImportPath] { return }
+ // if apackagePathsSeen[a.Package.ImportPath] { return }
// doesn't work.
- if !apackagePathsSeen[a.p.ImportPath] {
- apackagePathsSeen[a.p.ImportPath] = true
- target := a.target
- if len(a.p.CgoFiles) > 0 || a.p.usesSwig() {
+ if !apackagePathsSeen[a.Package.ImportPath] {
+ apackagePathsSeen[a.Package.ImportPath] = true
+ target := a.Target
+ if len(a.Package.CgoFiles) > 0 || a.Package.UsesSwig() {
target, err = readAndRemoveCgoFlags(target)
if err != nil {
return
@@ -2919,18 +2888,18 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
afiles = append(afiles, target)
}
}
- if strings.HasSuffix(a.target, ".so") {
- shlibs = append(shlibs, a.target)
+ if strings.HasSuffix(a.Target, ".so") {
+ shlibs = append(shlibs, a.Target)
seenShlib = true
}
- for _, a1 := range a.deps {
+ for _, a1 := range a.Deps {
walk(a1, seenShlib)
if err != nil {
return
}
}
}
- for _, a1 := range root.deps {
+ for _, a1 := range root.Deps {
walk(a1, false)
if err != nil {
return err
@@ -2942,25 +2911,25 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
// The go tool can dig up runtime/cgo from GOROOT and
// think that it should use its CgoLDFLAGS, but gccgo
// doesn't use runtime/cgo.
- if a.p == nil {
+ if a.Package == nil {
continue
}
- if !a.p.Standard {
- cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...)
+ if !a.Package.Standard {
+ cgoldflags = append(cgoldflags, a.Package.CgoLDFLAGS...)
}
- if len(a.p.CgoFiles) > 0 {
+ if len(a.Package.CgoFiles) > 0 {
usesCgo = true
}
- if a.p.usesSwig() {
+ if a.Package.UsesSwig() {
usesCgo = true
}
- if len(a.p.CXXFiles) > 0 || len(a.p.SwigCXXFiles) > 0 {
+ if len(a.Package.CXXFiles) > 0 || len(a.Package.SwigCXXFiles) > 0 {
cxx = true
}
- if len(a.p.MFiles) > 0 {
+ if len(a.Package.MFiles) > 0 {
objc = true
}
- if len(a.p.FFiles) > 0 {
+ if len(a.Package.FFiles) > 0 {
fortran = true
}
}
@@ -2979,11 +2948,11 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
ldflags = append(ldflags, cgoldflags...)
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
- if root.p != nil {
- ldflags = append(ldflags, root.p.CgoLDFLAGS...)
+ if root.Package != nil {
+ ldflags = append(ldflags, root.Package.CgoLDFLAGS...)
}
- ldflags = stringList("-Wl,-(", ldflags, "-Wl,-)")
+ ldflags = str.StringList("-Wl,-(", ldflags, "-Wl,-)")
for _, shlib := range shlibs {
ldflags = append(
@@ -2998,7 +2967,7 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
var realOut string
switch buildmode {
case "exe":
- if usesCgo && goos == "linux" {
+ if usesCgo && cfg.Goos == "linux" {
ldflags = append(ldflags, "-Wl,-E")
}
@@ -3019,8 +2988,8 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
// libffi.
ldflags = append(ldflags, "-Wl,-r", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive")
- if b.gccSupportsNoPie() {
- ldflags = append(ldflags, "-no-pie")
+ if nopie := b.gccNoPie(); nopie != "" {
+ ldflags = append(ldflags, nopie)
}
// We are creating an object file, so we don't want a build ID.
@@ -3037,7 +3006,7 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
ldflags = append(ldflags, "-pie")
default:
- fatalf("-buildmode=%s not supported for gccgo", buildmode)
+ base.Fatalf("-buildmode=%s not supported for gccgo", buildmode)
}
switch buildmode {
@@ -3074,20 +3043,20 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
return nil
}
-func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
- return tools.link(b, root, out, allactions, mainpkg, ofiles, ldBuildmode, root.p.ImportPath)
+func (tools gccgoToolchain) ld(b *Builder, root *Action, out string, allactions []*Action, mainpkg string, ofiles []string) error {
+ return tools.link(b, root, out, allactions, mainpkg, ofiles, ldBuildmode, root.Package.ImportPath)
}
-func (tools gccgoToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error {
- fakeRoot := &action{}
- fakeRoot.deps = toplevelactions
+func (tools gccgoToolchain) ldShared(b *Builder, toplevelactions []*Action, out string, allactions []*Action) error {
+ fakeRoot := &Action{}
+ fakeRoot.Deps = toplevelactions
return tools.link(b, fakeRoot, out, allactions, "", nil, "shared", out)
}
-func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
- inc := filepath.Join(goroot, "pkg", "include")
+func (tools gccgoToolchain) cc(b *Builder, p *load.Package, objdir, ofile, cfile string) error {
+ inc := filepath.Join(cfg.GOROOT, "pkg", "include")
cfile = mkAbs(p.Dir, cfile)
- defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
+ defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch}
defs = append(defs, b.gccArchArgs()...)
if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
@@ -3097,32 +3066,32 @@ func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile stri
}
defs = tools.maybePIC(defs)
if b.gccSupportsFlag("-fdebug-prefix-map=a=b") {
- defs = append(defs, "-fdebug-prefix-map="+b.work+"=/tmp/go-build")
+ defs = append(defs, "-fdebug-prefix-map="+b.WorkDir+"=/tmp/go-build")
}
if b.gccSupportsFlag("-gno-record-gcc-switches") {
defs = append(defs, "-gno-record-gcc-switches")
}
- return b.run(p.Dir, p.ImportPath, nil, envList("CC", defaultCC), "-Wall", "-g",
+ return b.run(p.Dir, p.ImportPath, nil, envList("CC", cfg.DefaultCC), "-Wall", "-g",
"-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile)
}
// maybePIC adds -fPIC to the list of arguments if needed.
func (tools gccgoToolchain) maybePIC(args []string) []string {
- switch buildBuildmode {
+ switch cfg.BuildBuildmode {
case "c-archive", "c-shared", "shared", "plugin":
args = append(args, "-fPIC")
}
return args
}
-func gccgoPkgpath(p *Package) string {
- if p.build.IsCommand() && !p.forceLibrary {
+func gccgoPkgpath(p *load.Package) string {
+ if p.Internal.Build.IsCommand() && !p.Internal.ForceLibrary {
return ""
}
return p.ImportPath
}
-func gccgoCleanPkgpath(p *Package) string {
+func gccgoCleanPkgpath(p *load.Package) string {
clean := func(r rune) rune {
switch {
case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
@@ -3135,25 +3104,28 @@ func gccgoCleanPkgpath(p *Package) string {
}
// gcc runs the gcc C compiler to create an object from a single C file.
-func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
- return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir))
+func (b *Builder) gcc(p *load.Package, out string, flags []string, cfile string) error {
+ return b.ccompile(p, out, flags, cfile, b.GccCmd(p.Dir))
}
// gxx runs the g++ C++ compiler to create an object from a single C++ file.
-func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) error {
- return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir))
+func (b *Builder) gxx(p *load.Package, out string, flags []string, cxxfile string) error {
+ return b.ccompile(p, out, flags, cxxfile, b.GxxCmd(p.Dir))
}
// gfortran runs the gfortran Fortran compiler to create an object from a single Fortran file.
-func (b *builder) gfortran(p *Package, out string, flags []string, ffile string) error {
+func (b *Builder) gfortran(p *load.Package, out string, flags []string, ffile string) error {
return b.ccompile(p, out, flags, ffile, b.gfortranCmd(p.Dir))
}
// ccompile runs the given C or C++ compiler and creates an object from a single source file.
-func (b *builder) ccompile(p *Package, outfile string, flags []string, file string, compiler []string) error {
+func (b *Builder) ccompile(p *load.Package, outfile string, flags []string, file string, compiler []string) error {
file = mkAbs(p.Dir, file)
desc := p.ImportPath
- output, err := b.runOut(p.Dir, desc, nil, compiler, flags, "-o", outfile, "-c", file)
+ if !filepath.IsAbs(outfile) {
+ outfile = filepath.Join(p.Dir, outfile)
+ }
+ output, err := b.runOut(filepath.Dir(file), desc, nil, compiler, flags, "-o", outfile, "-c", filepath.Base(file))
if len(output) > 0 {
// On FreeBSD 11, when we pass -g to clang 3.8 it
// invokes its internal assembler with -dwarf-version=2.
@@ -3186,36 +3158,36 @@ func (b *builder) ccompile(p *Package, outfile string, flags []string, file stri
}
// gccld runs the gcc linker to create an executable from a set of object files.
-func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error {
+func (b *Builder) gccld(p *load.Package, out string, flags []string, obj []string) error {
var cmd []string
if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
- cmd = b.gxxCmd(p.Dir)
+ cmd = b.GxxCmd(p.Dir)
} else {
- cmd = b.gccCmd(p.Dir)
+ cmd = b.GccCmd(p.Dir)
}
return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags)
}
// gccCmd returns a gcc command line prefix
// defaultCC is defined in zdefaultcc.go, written by cmd/dist.
-func (b *builder) gccCmd(objdir string) []string {
- return b.ccompilerCmd("CC", defaultCC, objdir)
+func (b *Builder) GccCmd(objdir string) []string {
+ return b.ccompilerCmd("CC", cfg.DefaultCC, objdir)
}
// gxxCmd returns a g++ command line prefix
// defaultCXX is defined in zdefaultcc.go, written by cmd/dist.
-func (b *builder) gxxCmd(objdir string) []string {
- return b.ccompilerCmd("CXX", defaultCXX, objdir)
+func (b *Builder) GxxCmd(objdir string) []string {
+ return b.ccompilerCmd("CXX", cfg.DefaultCXX, objdir)
}
// gfortranCmd returns a gfortran command line prefix.
-func (b *builder) gfortranCmd(objdir string) []string {
+func (b *Builder) gfortranCmd(objdir string) []string {
return b.ccompilerCmd("FC", "gfortran", objdir)
}
// ccompilerCmd returns a command line prefix for the given environment
// variable and using the default command when the variable is empty.
-func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
+func (b *Builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
// NOTE: env.go's mkEnv knows that the first three
// strings returned are "gcc", "-I", objdir (and cuts them off).
@@ -3225,14 +3197,14 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
// Definitely want -fPIC but on Windows gcc complains
// "-fPIC ignored for target (all code is position independent)"
- if goos != "windows" {
+ if cfg.Goos != "windows" {
a = append(a, "-fPIC")
}
a = append(a, b.gccArchArgs()...)
// gcc-4.5 and beyond require explicit "-pthread" flag
// for multithreading with pthread library.
- if buildContext.CgoEnabled {
- switch goos {
+ if cfg.BuildContext.CgoEnabled {
+ switch cfg.Goos {
case "windows":
a = append(a, "-mthreads")
default:
@@ -3252,7 +3224,7 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
// Tell gcc not to include the work directory in object files.
if b.gccSupportsFlag("-fdebug-prefix-map=a=b") {
- a = append(a, "-fdebug-prefix-map="+b.work+"=/tmp/go-build")
+ a = append(a, "-fdebug-prefix-map="+b.WorkDir+"=/tmp/go-build")
}
// Tell gcc not to include flags in object files, which defeats the
@@ -3264,50 +3236,57 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
// On OS X, some of the compilers behave as if -fno-common
// is always set, and the Mach-O linker in 6l/8l assumes this.
// See https://golang.org/issue/3253.
- if goos == "darwin" {
+ if cfg.Goos == "darwin" {
a = append(a, "-fno-common")
}
// gccgo uses the language-independent exception mechanism to
// handle panics, so it always needs unwind tables.
- if _, ok := buildToolchain.(gccgoToolchain); ok {
+ if cfg.BuildToolchainName == "gccgo" {
a = append(a, "-funwind-tables")
}
return a
}
-// On systems with PIE (position independent executables) enabled by default,
-// -no-pie must be passed when doing a partial link with -Wl,-r. But -no-pie is
-// not supported by all compilers.
-func (b *builder) gccSupportsNoPie() bool {
- return b.gccSupportsFlag("-no-pie")
+// gccNoPie returns the flag to use to request non-PIE. On systems
+// with PIE (position independent executables) enabled by default,
+// -no-pie must be passed when doing a partial link with -Wl,-r.
+// But -no-pie is not supported by all compilers, and clang spells it -nopie.
+func (b *Builder) gccNoPie() string {
+ if b.gccSupportsFlag("-no-pie") {
+ return "-no-pie"
+ }
+ if b.gccSupportsFlag("-nopie") {
+ return "-nopie"
+ }
+ return ""
}
// gccSupportsFlag checks to see if the compiler supports a flag.
-func (b *builder) gccSupportsFlag(flag string) bool {
+func (b *Builder) gccSupportsFlag(flag string) bool {
b.exec.Lock()
defer b.exec.Unlock()
if b, ok := b.flagCache[flag]; ok {
return b
}
if b.flagCache == nil {
- src := filepath.Join(b.work, "trivial.c")
+ src := filepath.Join(b.WorkDir, "trivial.c")
if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
return false
}
b.flagCache = make(map[string]bool)
}
- cmdArgs := append(envList("CC", defaultCC), flag, "-c", "trivial.c")
- if buildN || buildX {
- b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs))
- if buildN {
+ cmdArgs := append(envList("CC", cfg.DefaultCC), flag, "-c", "trivial.c")
+ if cfg.BuildN || cfg.BuildX {
+ b.Showcmd(b.WorkDir, "%s", joinUnambiguously(cmdArgs))
+ if cfg.BuildN {
return false
}
}
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
- cmd.Dir = b.work
- cmd.Env = mergeEnvLists([]string{"LC_ALL=C"}, envForDir(cmd.Dir, os.Environ()))
+ cmd.Dir = b.WorkDir
+ cmd.Env = base.MergeEnvLists([]string{"LC_ALL=C"}, base.EnvForDir(cmd.Dir, os.Environ()))
out, err := cmd.CombinedOutput()
supported := err == nil && !bytes.Contains(out, []byte("unrecognized"))
b.flagCache[flag] = supported
@@ -3315,8 +3294,8 @@ func (b *builder) gccSupportsFlag(flag string) bool {
}
// gccArchArgs returns arguments to pass to gcc based on the architecture.
-func (b *builder) gccArchArgs() []string {
- switch goarch {
+func (b *Builder) gccArchArgs() []string {
+ switch cfg.Goarch {
case "386":
return []string{"-m32"}
case "amd64", "amd64p32":
@@ -3343,23 +3322,23 @@ func envList(key, def string) []string {
return strings.Fields(v)
}
-// Return the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
-func (b *builder) cflags(p *Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
+// CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
+func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
defaults := "-g -O2"
- cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
- cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
- cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
- fflags = stringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS)
- ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
+ cppflags = str.StringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
+ cflags = str.StringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
+ cxxflags = str.StringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
+ fflags = str.StringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS)
+ ldflags = str.StringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
return
}
var cgoRe = regexp.MustCompile(`[/\\:]`)
-func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, objdirCgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
- p := a.p
- cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS := b.cflags(p)
+func (b *Builder) cgo(a *Action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, objdirCgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
+ p := a.Package
+ cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS := b.CFlags(p)
cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
// If we are compiling Objective-C code, then we need to link against libobjc
@@ -3380,7 +3359,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
}
}
- if buildMSan {
+ if cfg.BuildMSan {
cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
}
@@ -3432,7 +3411,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
}
- if _, ok := buildToolchain.(gccgoToolchain); ok {
+ if cfg.BuildToolchainName == "gccgo" {
if b.gccSupportsFlag("-fsplit-stack") {
cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack")
}
@@ -3442,7 +3421,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
}
}
- switch buildBuildmode {
+ switch cfg.BuildBuildmode {
case "c-archive", "c-shared":
// Tell cgo that if there are any exported functions
// it should generate a header file that C code can
@@ -3450,13 +3429,13 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
cgoflags = append(cgoflags, "-exportheader="+obj+"_cgo_install.h")
}
- if err := b.run(p.Dir, p.ImportPath, cgoenv, buildToolExec, cgoExe, srcdirarg, "-objdir", obj, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
+ if err := b.run(p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, srcdirarg, "-objdir", obj, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
return nil, nil, err
}
outGo = append(outGo, gofiles...)
// gcc
- cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
+ cflags := str.StringList(cgoCPPFLAGS, cgoCFLAGS)
for _, cfile := range cfiles {
ofile := obj + cfile[:len(cfile)-1] + "o"
if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil {
@@ -3474,7 +3453,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
outObj = append(outObj, ofile)
}
- cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS)
+ cxxflags := str.StringList(cgoCPPFLAGS, cgoCXXFLAGS)
for _, file := range gxxfiles {
// Append .o to the file, just in case the pkg has file.c and file.cpp
ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o"
@@ -3493,7 +3472,7 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
outObj = append(outObj, ofile)
}
- fflags := stringList(cgoCPPFLAGS, cgoFFLAGS)
+ fflags := str.StringList(cgoCPPFLAGS, cgoFFLAGS)
for _, file := range ffiles {
// Append .o to the file, just in case the pkg has file.c and file.f
ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o"
@@ -3503,8 +3482,8 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
outObj = append(outObj, ofile)
}
- switch buildToolchain.(type) {
- case gcToolchain:
+ switch cfg.BuildToolchainName {
+ case "gc":
importGo := obj + "_cgo_import.go"
if err := b.dynimport(p, obj, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil {
return nil, nil, err
@@ -3517,10 +3496,10 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
}
outObj = []string{ofile}
- case gccgoToolchain:
+ case "gccgo":
defunC := obj + "_cgo_defun.c"
defunObj := obj + "_cgo_defun.o"
- if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
+ if err := BuildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
return nil, nil, err
}
outObj = append(outObj, defunObj)
@@ -3535,19 +3514,19 @@ func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
// dynimport creates a Go source file named importGo containing
// //go:cgo_import_dynamic directives for each symbol or library
// dynamically imported by the object files outObj.
-func (b *builder) dynimport(p *Package, obj, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error {
+func (b *Builder) dynimport(p *load.Package, obj, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error {
cfile := obj + "_cgo_main.c"
ofile := obj + "_cgo_main.o"
if err := b.gcc(p, ofile, cflags, cfile); err != nil {
return err
}
- linkobj := stringList(ofile, outObj, p.SysoFiles)
+ linkobj := str.StringList(ofile, outObj, p.SysoFiles)
dynobj := obj + "_cgo_.o"
// we need to use -pie for Linux/ARM to get accurate imported sym
ldflags := cgoLDFLAGS
- if (goarch == "arm" && goos == "linux") || goos == "android" {
+ if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" {
ldflags = append(ldflags, "-pie")
}
if err := b.gccld(p, dynobj, ldflags, linkobj); err != nil {
@@ -3559,12 +3538,12 @@ func (b *builder) dynimport(p *Package, obj, importGo, cgoExe string, cflags, cg
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = []string{"-dynlinker"} // record path to dynamic linker
}
- return b.run(p.Dir, p.ImportPath, nil, buildToolExec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
+ return b.run(p.Dir, p.ImportPath, nil, cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
}
// collect partially links the object files outObj into a single
// relocatable object file named ofile.
-func (b *builder) collect(p *Package, obj, ofile string, cgoLDFLAGS, outObj []string) error {
+func (b *Builder) collect(p *load.Package, obj, ofile string, cgoLDFLAGS, outObj []string) error {
// When linking relocatable objects, various flags need to be
// filtered out as they are inapplicable and can cause some linkers
// to fail.
@@ -3578,7 +3557,7 @@ func (b *builder) collect(p *Package, obj, ofile string, cgoLDFLAGS, outObj []st
i++
}
// skip "-framework X" on Darwin
- case goos == "darwin" && f == "-framework":
+ case cfg.Goos == "darwin" && f == "-framework":
i++
// skip "*.{dylib,so,dll,o,a}"
case strings.HasSuffix(f, ".dylib"),
@@ -3611,8 +3590,8 @@ func (b *builder) collect(p *Package, obj, ofile string, cgoLDFLAGS, outObj []st
ldflags = append(ldflags, "-Wl,-r", "-nostdlib")
- if b.gccSupportsNoPie() {
- ldflags = append(ldflags, "-no-pie")
+ if flag := b.gccNoPie(); flag != "" {
+ ldflags = append(ldflags, flag)
}
// We are creating an object file, so we don't want a build ID.
@@ -3624,7 +3603,7 @@ func (b *builder) collect(p *Package, obj, ofile string, cgoLDFLAGS, outObj []st
// Run SWIG on all SWIG input files.
// TODO: Don't build a shared library, once SWIG emits the necessary
// pragmas for external linking.
-func (b *builder) swig(p *Package, obj string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) {
+func (b *Builder) swig(p *load.Package, obj string, pcCFLAGS []string) (outGo, outC, outCXX []string, err error) {
if err := b.swigVersionCheck(); err != nil {
return nil, nil, nil, err
}
@@ -3667,7 +3646,7 @@ var (
swigCheck error
)
-func (b *builder) swigDoVersionCheck() error {
+func (b *Builder) swigDoVersionCheck() error {
out, err := b.runOut("", "", nil, "swig", "-version")
if err != nil {
return err
@@ -3720,7 +3699,7 @@ func (b *builder) swigDoVersionCheck() error {
return nil
}
-func (b *builder) swigVersionCheck() error {
+func (b *Builder) swigVersionCheck() error {
swigCheckOnce.Do(func() {
swigCheck = b.swigDoVersionCheck()
})
@@ -3741,20 +3720,20 @@ const i int = 1 << 32
`
// Determine the size of int on the target system for the -intgosize option
-// of swig >= 2.0.9. Run only once.
-func (b *builder) swigDoIntSize(obj string) (intsize string, err error) {
- if buildN {
+// of swig >= 2.0.9. Run only once.
+func (b *Builder) swigDoIntSize(obj string) (intsize string, err error) {
+ if cfg.BuildN {
return "$INTBITS", nil
}
- src := filepath.Join(b.work, "swig_intsize.go")
+ src := filepath.Join(b.WorkDir, "swig_intsize.go")
if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
return
}
srcs := []string{src}
- p := goFilesPackage(srcs)
+ p := load.GoFilesPackage(srcs)
- if _, _, e := buildToolchain.gc(b, p, "", obj, false, nil, srcs); e != nil {
+ if _, _, e := BuildToolchain.gc(b, p, "", obj, false, nil, srcs); e != nil {
return "32", nil
}
return "64", nil
@@ -3762,7 +3741,7 @@ func (b *builder) swigDoIntSize(obj string) (intsize string, err error) {
// Determine the size of int on the target system for the -intgosize option
// of swig >= 2.0.9.
-func (b *builder) swigIntSize(obj string) (intsize string, err error) {
+func (b *Builder) swigIntSize(obj string) (intsize string, err error) {
swigIntSizeOnce.Do(func() {
swigIntSize, swigIntSizeError = b.swigDoIntSize(obj)
})
@@ -3770,13 +3749,13 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
}
// Run SWIG on one SWIG input file.
-func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
- cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.cflags(p)
+func (b *Builder) swigOne(p *load.Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
+ cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.CFlags(p)
var cflags []string
if cxx {
- cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
+ cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
} else {
- cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
+ cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS)
}
n := 5 // length of ".swig"
@@ -3791,7 +3770,7 @@ func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx b
gccExt = "cxx"
}
- _, gccgo := buildToolchain.(gccgoToolchain)
+ gccgo := cfg.BuildToolchainName == "gccgo"
// swig
args := []string{
@@ -3847,8 +3826,8 @@ func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx b
// other than passing a trailing --build-id=none. So that is what we
// do, but only on systems likely to support it, which is to say,
// systems that normally use gold or the GNU linker.
-func (b *builder) disableBuildID(ldflags []string) []string {
- switch goos {
+func (b *Builder) disableBuildID(ldflags []string) []string {
+ switch cfg.Goos {
case "android", "dragonfly", "linux", "netbsd":
ldflags = append(ldflags, "-Wl,--build-id=none")
}
@@ -3856,13 +3835,13 @@ func (b *builder) disableBuildID(ldflags []string) []string {
}
// An actionQueue is a priority queue of actions.
-type actionQueue []*action
+type actionQueue []*Action
// Implement heap.Interface
func (q *actionQueue) Len() int { return len(*q) }
func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] }
func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority }
-func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) }
+func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*Action)) }
func (q *actionQueue) Pop() interface{} {
n := len(*q) - 1
x := (*q)[n]
@@ -3870,50 +3849,75 @@ func (q *actionQueue) Pop() interface{} {
return x
}
-func (q *actionQueue) push(a *action) {
+func (q *actionQueue) push(a *Action) {
heap.Push(q, a)
}
-func (q *actionQueue) pop() *action {
- return heap.Pop(q).(*action)
+func (q *actionQueue) pop() *Action {
+ return heap.Pop(q).(*Action)
}
-func instrumentInit() {
- if !buildRace && !buildMSan {
+func InstrumentInit() {
+ if !cfg.BuildRace && !cfg.BuildMSan {
return
}
- if buildRace && buildMSan {
+ if cfg.BuildRace && cfg.BuildMSan {
fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
os.Exit(2)
}
- if buildMSan && (goos != "linux" || goarch != "amd64") {
- fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", goos, goarch)
+ if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64") {
+ fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
os.Exit(2)
}
- if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" {
+ if cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows" {
fmt.Fprintf(os.Stderr, "go %s: -race and -msan are only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2)
}
- if !buildContext.CgoEnabled {
+ if !cfg.BuildContext.CgoEnabled {
fmt.Fprintf(os.Stderr, "go %s: -race requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0])
os.Exit(2)
}
- if buildRace {
+ if cfg.BuildRace {
buildGcflags = append(buildGcflags, "-race")
- buildLdflags = append(buildLdflags, "-race")
+ cfg.BuildLdflags = append(cfg.BuildLdflags, "-race")
} else {
buildGcflags = append(buildGcflags, "-msan")
- buildLdflags = append(buildLdflags, "-msan")
+ cfg.BuildLdflags = append(cfg.BuildLdflags, "-msan")
}
- if buildContext.InstallSuffix != "" {
- buildContext.InstallSuffix += "_"
+ if cfg.BuildContext.InstallSuffix != "" {
+ cfg.BuildContext.InstallSuffix += "_"
}
- if buildRace {
- buildContext.InstallSuffix += "race"
- buildContext.BuildTags = append(buildContext.BuildTags, "race")
+ if cfg.BuildRace {
+ cfg.BuildContext.InstallSuffix += "race"
+ cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "race")
} else {
- buildContext.InstallSuffix += "msan"
- buildContext.BuildTags = append(buildContext.BuildTags, "msan")
+ cfg.BuildContext.InstallSuffix += "msan"
+ cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "msan")
+ }
+}
+
+// ExecCmd is the command to use to run user binaries.
+// Normally it is empty, meaning run the binaries directly.
+// If cross-compiling and running on a remote system or
+// simulator, it is typically go_GOOS_GOARCH_exec, with
+// the target GOOS and GOARCH substituted.
+// The -exec flag overrides these defaults.
+var ExecCmd []string
+
+// FindExecCmd derives the value of ExecCmd to use.
+// It returns that value and leaves ExecCmd set for direct use.
+func FindExecCmd() []string {
+ if ExecCmd != nil {
+ return ExecCmd
+ }
+ ExecCmd = []string{} // avoid work the second time
+ if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH {
+ return ExecCmd
+ }
+ path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", cfg.Goos, cfg.Goarch))
+ if err == nil {
+ ExecCmd = []string{path}
}
+ return ExecCmd
}
diff --git a/libgo/go/cmd/go/internal/work/build_test.go b/libgo/go/cmd/go/internal/work/build_test.go
new file mode 100644
index 0000000..294b83c
--- /dev/null
+++ b/libgo/go/cmd/go/internal/work/build_test.go
@@ -0,0 +1,227 @@
+// Copyright 2016 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 work
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "strings"
+ "testing"
+
+ "cmd/go/internal/base"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+)
+
+func TestRemoveDevNull(t *testing.T) {
+ fi, err := os.Lstat(os.DevNull)
+ if err != nil {
+ t.Skip(err)
+ }
+ if fi.Mode().IsRegular() {
+ t.Errorf("Lstat(%s).Mode().IsRegular() = true; expected false", os.DevNull)
+ }
+ mayberemovefile(os.DevNull)
+ _, err = os.Lstat(os.DevNull)
+ if err != nil {
+ t.Errorf("mayberemovefile(%s) did remove it; oops", os.DevNull)
+ }
+}
+
+func TestSplitPkgConfigOutput(t *testing.T) {
+ for _, test := range []struct {
+ in []byte
+ want []string
+ }{
+ {[]byte(`-r:foo -L/usr/white\ space/lib -lfoo\ bar -lbar\ baz`), []string{"-r:foo", "-L/usr/white space/lib", "-lfoo bar", "-lbar baz"}},
+ {[]byte(`-lextra\ fun\ arg\\`), []string{`-lextra fun arg\`}},
+ {[]byte(`broken flag\`), []string{"broken", "flag"}},
+ {[]byte("\textra whitespace\r\n"), []string{"extra", "whitespace"}},
+ {[]byte(" \r\n "), nil},
+ } {
+ got := splitPkgConfigOutput(test.in)
+ if !reflect.DeepEqual(got, test.want) {
+ t.Errorf("splitPkgConfigOutput(%v) = %v; want %v", test.in, got, test.want)
+ }
+ }
+}
+
+func TestSharedLibName(t *testing.T) {
+ // TODO(avdva) - make these values platform-specific
+ prefix := "lib"
+ suffix := ".so"
+ testData := []struct {
+ args []string
+ pkgs []*load.Package
+ expected string
+ expectErr bool
+ rootedAt string
+ }{
+ {
+ args: []string{"std"},
+ pkgs: []*load.Package{},
+ expected: "std",
+ },
+ {
+ args: []string{"std", "cmd"},
+ pkgs: []*load.Package{},
+ expected: "std,cmd",
+ },
+ {
+ args: []string{},
+ pkgs: []*load.Package{pkgImportPath("gopkg.in/somelib")},
+ expected: "gopkg.in-somelib",
+ },
+ {
+ args: []string{"./..."},
+ pkgs: []*load.Package{pkgImportPath("somelib")},
+ expected: "somelib",
+ rootedAt: "somelib",
+ },
+ {
+ args: []string{"../somelib", "../somelib"},
+ pkgs: []*load.Package{pkgImportPath("somelib")},
+ expected: "somelib",
+ },
+ {
+ args: []string{"../lib1", "../lib2"},
+ pkgs: []*load.Package{pkgImportPath("gopkg.in/lib1"), pkgImportPath("gopkg.in/lib2")},
+ expected: "gopkg.in-lib1,gopkg.in-lib2",
+ },
+ {
+ args: []string{"./..."},
+ pkgs: []*load.Package{
+ pkgImportPath("gopkg.in/dir/lib1"),
+ pkgImportPath("gopkg.in/lib2"),
+ pkgImportPath("gopkg.in/lib3"),
+ },
+ expected: "gopkg.in",
+ rootedAt: "gopkg.in",
+ },
+ {
+ args: []string{"std", "../lib2"},
+ pkgs: []*load.Package{},
+ expectErr: true,
+ },
+ {
+ args: []string{"all", "./"},
+ pkgs: []*load.Package{},
+ expectErr: true,
+ },
+ {
+ args: []string{"cmd", "fmt"},
+ pkgs: []*load.Package{},
+ expectErr: true,
+ },
+ }
+ for _, data := range testData {
+ func() {
+ if data.rootedAt != "" {
+ tmpGopath, err := ioutil.TempDir("", "gopath")
+ if err != nil {
+ t.Fatal(err)
+ }
+ oldGopath := cfg.BuildContext.GOPATH
+ defer func() {
+ cfg.BuildContext.GOPATH = oldGopath
+ os.Chdir(base.Cwd)
+ err := os.RemoveAll(tmpGopath)
+ if err != nil {
+ t.Error(err)
+ }
+ }()
+ root := filepath.Join(tmpGopath, "src", data.rootedAt)
+ err = os.MkdirAll(root, 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cfg.BuildContext.GOPATH = tmpGopath
+ os.Chdir(root)
+ }
+ computed, err := libname(data.args, data.pkgs)
+ if err != nil {
+ if !data.expectErr {
+ t.Errorf("libname returned an error %q, expected a name", err.Error())
+ }
+ } else if data.expectErr {
+ t.Errorf("libname returned %q, expected an error", computed)
+ } else {
+ expected := prefix + data.expected + suffix
+ if expected != computed {
+ t.Errorf("libname returned %q, expected %q", computed, expected)
+ }
+ }
+ }()
+ }
+}
+
+func pkgImportPath(pkgpath string) *load.Package {
+ return &load.Package{
+ PackagePublic: load.PackagePublic{
+ ImportPath: pkgpath,
+ },
+ }
+}
+
+// When installing packages, the installed package directory should
+// respect the SetGID bit and group name of the destination
+// directory.
+// See https://golang.org/issue/18878.
+func TestRespectSetgidDir(t *testing.T) {
+ if runtime.GOOS == "nacl" {
+ t.Skip("can't set SetGID bit with chmod on nacl")
+ }
+
+ var b Builder
+
+ // Check that `cp` is called instead of `mv` by looking at the output
+ // of `(*Builder).ShowCmd` afterwards as a sanity check.
+ cfg.BuildX = true
+ var cmdBuf bytes.Buffer
+ b.Print = func(a ...interface{}) (int, error) {
+ return cmdBuf.WriteString(fmt.Sprint(a...))
+ }
+
+ setgiddir, err := ioutil.TempDir("", "SetGroupID")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(setgiddir)
+
+ if runtime.GOOS == "freebsd" {
+ err = os.Chown(setgiddir, os.Getuid(), os.Getgid())
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Change setgiddir's permissions to include the SetGID bit.
+ if err := os.Chmod(setgiddir, 0755|os.ModeSetgid); err != nil {
+ t.Fatal(err)
+ }
+
+ pkgfile, err := ioutil.TempFile("", "pkgfile")
+ if err != nil {
+ t.Fatalf("ioutil.TempFile(\"\", \"pkgfile\"): %v", err)
+ }
+ defer os.Remove(pkgfile.Name())
+ defer pkgfile.Close()
+
+ dirGIDFile := filepath.Join(setgiddir, "setgid")
+ if err := b.moveOrCopyFile(nil, dirGIDFile, pkgfile.Name(), 0666, true); err != nil {
+ t.Fatalf("moveOrCopyFile: %v", err)
+ }
+
+ got := strings.TrimSpace(cmdBuf.String())
+ want := b.fmtcmd("", "cp %s %s", pkgfile.Name(), dirGIDFile)
+ if got != want {
+ t.Fatalf("moveOrCopyFile(%q, %q): want %q, got %q", dirGIDFile, pkgfile.Name(), want, got)
+ }
+}
diff --git a/libgo/go/cmd/go/internal/work/testgo.go b/libgo/go/cmd/go/internal/work/testgo.go
new file mode 100644
index 0000000..3e623c6
--- /dev/null
+++ b/libgo/go/cmd/go/internal/work/testgo.go
@@ -0,0 +1,17 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains extra hooks for testing the go command.
+
+// +build testgo
+
+package work
+
+import "os"
+
+func init() {
+ if v := os.Getenv("TESTGO_VERSION"); v != "" {
+ runtimeVersion = v
+ }
+}
diff --git a/libgo/go/cmd/go/main.go b/libgo/go/cmd/go/main.go
index ceeac4d..794ce08 100644
--- a/libgo/go/cmd/go/main.go
+++ b/libgo/go/cmd/go/main.go
@@ -2,141 +2,90 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:generate ./mkalldocs.sh
+
package main
import (
- "bufio"
- "bytes"
"flag"
"fmt"
- "go/build"
- "io"
"log"
"os"
- "os/exec"
- "path"
"path/filepath"
- "regexp"
"runtime"
"strings"
- "sync"
- "text/template"
- "unicode"
- "unicode/utf8"
-)
-
-// A Command is an implementation of a go command
-// like go build or go fix.
-type Command struct {
- // Run runs the command.
- // The args are the arguments after the command name.
- 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.
- UsageLine string
-
- // Short is the short description shown in the 'go help' output.
- Short string
-
- // Long is the long message shown in the 'go help ' output.
- Long string
-
- // Flag is a set of flags specific to this command.
- Flag flag.FlagSet
- // CustomFlags indicates that the command will do its own
- // flag parsing.
- CustomFlags bool
-}
-
-// Name returns the command's name: the first word in the usage line.
-func (c *Command) Name() string {
- name := c.UsageLine
- i := strings.Index(name, " ")
- if i >= 0 {
- name = name[:i]
- }
- return name
-}
-
-func (c *Command) Usage() {
- fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
- fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
- os.Exit(2)
-}
-
-// Runnable reports whether the command can be run; otherwise
-// it is a documentation pseudo-command such as importpath.
-func (c *Command) Runnable() bool {
- return c.Run != nil
-}
-
-// Commands lists the available commands and help topics.
-// The order here is the order in which they are printed by 'go help'.
-var commands = []*Command{
- cmdBuild,
- cmdClean,
- cmdDoc,
- cmdEnv,
- cmdBug,
- cmdFix,
- cmdFmt,
- cmdGenerate,
- cmdGet,
- cmdInstall,
- cmdList,
- cmdRun,
- cmdTest,
- cmdTool,
- cmdVersion,
- cmdVet,
-
- helpC,
- helpBuildmode,
- helpFileType,
- helpGopath,
- helpEnvironment,
- helpImportPath,
- helpPackages,
- helpTestflag,
- helpTestfunc,
-}
-
-var exitStatus = 0
-var exitMu sync.Mutex
+ "cmd/go/internal/base"
+ "cmd/go/internal/bug"
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/clean"
+ "cmd/go/internal/doc"
+ "cmd/go/internal/envcmd"
+ "cmd/go/internal/fix"
+ "cmd/go/internal/fmtcmd"
+ "cmd/go/internal/generate"
+ "cmd/go/internal/get"
+ "cmd/go/internal/help"
+ "cmd/go/internal/list"
+ "cmd/go/internal/run"
+ "cmd/go/internal/test"
+ "cmd/go/internal/tool"
+ "cmd/go/internal/version"
+ "cmd/go/internal/vet"
+ "cmd/go/internal/work"
+)
-func setExitStatus(n int) {
- exitMu.Lock()
- if exitStatus < n {
- exitStatus = n
+func init() {
+ base.Commands = []*base.Command{
+ work.CmdBuild,
+ clean.CmdClean,
+ doc.CmdDoc,
+ envcmd.CmdEnv,
+ bug.CmdBug,
+ fix.CmdFix,
+ fmtcmd.CmdFmt,
+ generate.CmdGenerate,
+ get.CmdGet,
+ work.CmdInstall,
+ list.CmdList,
+ run.CmdRun,
+ test.CmdTest,
+ tool.CmdTool,
+ version.CmdVersion,
+ vet.CmdVet,
+
+ help.HelpC,
+ help.HelpBuildmode,
+ help.HelpFileType,
+ help.HelpGopath,
+ help.HelpEnvironment,
+ help.HelpImportPath,
+ help.HelpPackages,
+ test.HelpTestflag,
+ test.HelpTestfunc,
}
- exitMu.Unlock()
}
-var origEnv []string
-var newEnv []envVar
-
func main() {
_ = go11tag
- flag.Usage = usage
+ flag.Usage = base.Usage
flag.Parse()
log.SetFlags(0)
args := flag.Args()
if len(args) < 1 {
- usage()
+ base.Usage()
}
if args[0] == "help" {
- help(args[1:])
+ help.Help(args[1:])
return
}
// Diagnose common mistake: GOPATH==GOROOT.
// This setting is equivalent to not setting GOPATH at all,
// which is not what most people want when they do it.
- if gopath := buildContext.GOPATH; filepath.Clean(gopath) == filepath.Clean(runtime.GOROOT()) {
+ if gopath := cfg.BuildContext.GOPATH; filepath.Clean(gopath) == filepath.Clean(runtime.GOROOT()) {
fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
} else {
for _, p := range filepath.SplitList(gopath) {
@@ -154,14 +103,12 @@ func main() {
}
}
- if fi, err := os.Stat(goroot); err != nil || !fi.IsDir() {
- // For gccgo this is fine, carry on.
- // Note that this check is imperfect as we have not yet
- // parsed the -compiler flag.
- if runtime.Compiler != "gccgo" {
- fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", goroot)
- os.Exit(2)
- }
+ // For gccgo this is fine, carry on.
+ // Note that this check is imperfect as we have not yet parsed
+ // the -compiler flag.
+ if fi, err := os.Stat(cfg.GOROOT); err != nil || !fi.IsDir() && runtime.Compiler != "gccgo" {
+ fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", cfg.GOROOT)
+ os.Exit(2)
}
// Set environment (GOOS, GOARCH, etc) explicitly.
@@ -169,15 +116,15 @@ func main() {
// the same default computation of these as we do,
// but in practice there might be skew
// This makes sure we all agree.
- origEnv = os.Environ()
- newEnv = mkEnv()
- for _, env := range newEnv {
- if os.Getenv(env.name) != env.value {
- os.Setenv(env.name, env.value)
+ cfg.OrigEnv = os.Environ()
+ cfg.CmdEnv = envcmd.MkEnv()
+ for _, env := range cfg.CmdEnv {
+ if os.Getenv(env.Name) != env.Value {
+ os.Setenv(env.Name, env.Value)
}
}
- for _, cmd := range commands {
+ for _, cmd := range base.Commands {
if cmd.Name() == args[0] && cmd.Runnable() {
cmd.Flag.Usage = func() { cmd.Usage() }
if cmd.CustomFlags {
@@ -187,615 +134,25 @@ func main() {
args = cmd.Flag.Args()
}
cmd.Run(cmd, args)
- exit()
+ base.Exit()
return
}
}
fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0])
- setExitStatus(2)
- exit()
-}
-
-var usageTemplate = `Go is a tool for managing Go source code.
-
-Usage:
-
- go command [arguments]
-
-The commands are:
-{{range .}}{{if .Runnable}}
- {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
-
-Use "go help [command]" for more information about a command.
-
-Additional help topics:
-{{range .}}{{if not .Runnable}}
- {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
-
-Use "go help [topic]" for more information about that topic.
-
-`
-
-var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}}
-
-{{end}}{{.Long | trim}}
-`
-
-var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
-
-{{end}}{{if .Runnable}}Usage:
-
- go {{.UsageLine}}
-
-{{end}}{{.Long | trim}}
-
-
-{{end}}`
-
-// commentWriter writes a Go comment to the underlying io.Writer,
-// using line comment form (//).
-type commentWriter struct {
- W io.Writer
- wroteSlashes bool // Wrote "//" at the beginning of the current line.
-}
-
-func (c *commentWriter) Write(p []byte) (int, error) {
- var n int
- for i, b := range p {
- if !c.wroteSlashes {
- s := "//"
- if b != '\n' {
- s = "// "
- }
- if _, err := io.WriteString(c.W, s); err != nil {
- return n, err
- }
- c.wroteSlashes = true
- }
- n0, err := c.W.Write(p[i : i+1])
- n += n0
- if err != nil {
- return n, err
- }
- if b == '\n' {
- c.wroteSlashes = false
- }
- }
- return len(p), nil
-}
-
-// An errWriter wraps a writer, recording whether a write error occurred.
-type errWriter struct {
- w io.Writer
- err error
+ base.SetExitStatus(2)
+ base.Exit()
}
-func (w *errWriter) Write(b []byte) (int, error) {
- n, err := w.w.Write(b)
- if err != nil {
- w.err = err
- }
- return n, err
+func init() {
+ base.Usage = mainUsage
}
-// tmpl executes the given template text on data, writing the result to w.
-func tmpl(w io.Writer, text string, data interface{}) {
- t := template.New("top")
- t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
- template.Must(t.Parse(text))
- ew := &errWriter{w: w}
- err := t.Execute(ew, data)
- if ew.err != nil {
- // I/O error writing. Ignore write on closed pipe.
- if strings.Contains(ew.err.Error(), "pipe") {
- os.Exit(1)
- }
- fatalf("writing output: %v", ew.err)
- }
- if err != nil {
- panic(err)
- }
-}
-
-func capitalize(s string) string {
- if s == "" {
- return s
- }
- r, n := utf8.DecodeRuneInString(s)
- return string(unicode.ToTitle(r)) + s[n:]
-}
-
-func printUsage(w io.Writer) {
- bw := bufio.NewWriter(w)
- tmpl(bw, usageTemplate, commands)
- bw.Flush()
-}
-
-func usage() {
+func mainUsage() {
// special case "go test -h"
if len(os.Args) > 1 && os.Args[1] == "test" {
- os.Stderr.WriteString(testUsage + "\n\n" +
- strings.TrimSpace(testFlag1) + "\n\n\t" +
- strings.TrimSpace(testFlag2) + "\n")
- os.Exit(2)
+ test.Usage()
}
- printUsage(os.Stderr)
+ help.PrintUsage(os.Stderr)
os.Exit(2)
}
-
-// help implements the 'help' command.
-func help(args []string) {
- if len(args) == 0 {
- printUsage(os.Stdout)
- // not exit 2: succeeded at 'go help'.
- return
- }
- if len(args) != 1 {
- fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
- os.Exit(2) // failed at 'go help'
- }
-
- arg := args[0]
-
- // 'go help documentation' generates doc.go.
- if arg == "documentation" {
- fmt.Println("// Copyright 2011 The Go Authors. All rights reserved.")
- fmt.Println("// Use of this source code is governed by a BSD-style")
- fmt.Println("// license that can be found in the LICENSE file.")
- fmt.Println()
- fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.")
- fmt.Println("// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.")
- fmt.Println()
- buf := new(bytes.Buffer)
- printUsage(buf)
- usage := &Command{Long: buf.String()}
- tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, append([]*Command{usage}, commands...))
- fmt.Println("package main")
- return
- }
-
- for _, cmd := range commands {
- if cmd.Name() == arg {
- tmpl(os.Stdout, helpTemplate, cmd)
- // not exit 2: succeeded at 'go help cmd'.
- return
- }
- }
-
- fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'go help'.\n", arg)
- os.Exit(2) // failed at 'go help cmd'
-}
-
-// importPathsNoDotExpansion returns the import paths to use for the given
-// command line, but it does no ... expansion.
-func importPathsNoDotExpansion(args []string) []string {
- if len(args) == 0 {
- return []string{"."}
- }
- var out []string
- for _, a := range args {
- // Arguments are supposed to be import paths, but
- // as a courtesy to Windows developers, rewrite \ to /
- // in command-line arguments. Handles .\... and so on.
- if filepath.Separator == '\\' {
- a = strings.Replace(a, `\`, `/`, -1)
- }
-
- // Put argument in canonical form, but preserve leading ./.
- if strings.HasPrefix(a, "./") {
- a = "./" + path.Clean(a)
- if a == "./." {
- a = "."
- }
- } else {
- a = path.Clean(a)
- }
- if isMetaPackage(a) {
- out = append(out, allPackages(a)...)
- continue
- }
- out = append(out, a)
- }
- return out
-}
-
-// importPaths returns the import paths to use for the given command line.
-func importPaths(args []string) []string {
- args = importPathsNoDotExpansion(args)
- var out []string
- for _, a := range args {
- if strings.Contains(a, "...") {
- if build.IsLocalImport(a) {
- out = append(out, allPackagesInFS(a)...)
- } else {
- out = append(out, allPackages(a)...)
- }
- continue
- }
- out = append(out, a)
- }
- return out
-}
-
-var atexitFuncs []func()
-
-func atexit(f func()) {
- atexitFuncs = append(atexitFuncs, f)
-}
-
-func exit() {
- for _, f := range atexitFuncs {
- f()
- }
- os.Exit(exitStatus)
-}
-
-func fatalf(format string, args ...interface{}) {
- errorf(format, args...)
- exit()
-}
-
-func errorf(format string, args ...interface{}) {
- log.Printf(format, args...)
- setExitStatus(1)
-}
-
-func exitIfErrors() {
- if exitStatus != 0 {
- exit()
- }
-}
-
-func run(cmdargs ...interface{}) {
- cmdline := stringList(cmdargs...)
- if buildN || buildX {
- fmt.Printf("%s\n", strings.Join(cmdline, " "))
- if buildN {
- return
- }
- }
-
- cmd := exec.Command(cmdline[0], cmdline[1:]...)
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- if err := cmd.Run(); err != nil {
- errorf("%v", err)
- }
-}
-
-// 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.
-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
-}
-
-// matchPattern(pattern)(name) reports whether
-// name matches pattern. Pattern is a limited glob
-// pattern in which '...' means 'any string' and there
-// is no other special syntax.
-func matchPattern(pattern string) func(name string) bool {
- re := regexp.QuoteMeta(pattern)
- re = strings.Replace(re, `\.\.\.`, `.*`, -1)
- // Special case: foo/... matches foo too.
- if strings.HasSuffix(re, `/.*`) {
- re = re[:len(re)-len(`/.*`)] + `(/.*)?`
- }
- reg := regexp.MustCompile(`^` + re + `$`)
- return func(name string) bool {
- return reg.MatchString(name)
- }
-}
-
-// hasPathPrefix reports whether the path s begins with the
-// elements in prefix.
-func hasPathPrefix(s, prefix string) bool {
- switch {
- default:
- return false
- case len(s) == len(prefix):
- return s == prefix
- case len(s) > len(prefix):
- if prefix != "" && prefix[len(prefix)-1] == '/' {
- return strings.HasPrefix(s, prefix)
- }
- return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
- }
-}
-
-// hasFilePathPrefix reports whether the filesystem path s begins with the
-// elements in prefix.
-func hasFilePathPrefix(s, prefix string) bool {
- sv := strings.ToUpper(filepath.VolumeName(s))
- pv := strings.ToUpper(filepath.VolumeName(prefix))
- s = s[len(sv):]
- prefix = prefix[len(pv):]
- switch {
- default:
- return false
- case sv != pv:
- return false
- case len(s) == len(prefix):
- return s == prefix
- case len(s) > len(prefix):
- if prefix != "" && prefix[len(prefix)-1] == filepath.Separator {
- return strings.HasPrefix(s, prefix)
- }
- return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix
- }
-}
-
-// expandPath returns the symlink-expanded form of path.
-func expandPath(p string) string {
- x, err := filepath.EvalSymlinks(p)
- if err == nil {
- return x
- }
- return p
-}
-
-// treeCanMatchPattern(pattern)(name) reports whether
-// name or children of name can possibly match pattern.
-// Pattern is the same limited glob accepted by matchPattern.
-func treeCanMatchPattern(pattern string) func(name string) bool {
- wildCard := false
- if i := strings.Index(pattern, "..."); i >= 0 {
- wildCard = true
- pattern = pattern[:i]
- }
- return func(name string) bool {
- return len(name) <= len(pattern) && hasPathPrefix(pattern, name) ||
- wildCard && strings.HasPrefix(name, pattern)
- }
-}
-
-// allPackages returns all the packages that can be found
-// under the $GOPATH directories and $GOROOT matching pattern.
-// The pattern is either "all" (all packages), "std" (standard packages),
-// "cmd" (standard commands), or a path including "...".
-func allPackages(pattern string) []string {
- pkgs := matchPackages(pattern)
- if len(pkgs) == 0 {
- fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
- }
- return pkgs
-}
-
-func matchPackages(pattern string) []string {
- match := func(string) bool { return true }
- treeCanMatch := func(string) bool { return true }
- if !isMetaPackage(pattern) {
- match = matchPattern(pattern)
- treeCanMatch = treeCanMatchPattern(pattern)
- }
-
- have := map[string]bool{
- "builtin": true, // ignore pseudo-package that exists only for documentation
- }
- if !buildContext.CgoEnabled {
- have["runtime/cgo"] = true // ignore during walk
- }
- var pkgs []string
-
- for _, src := range buildContext.SrcDirs() {
- if (pattern == "std" || pattern == "cmd") && src != gorootSrc {
- continue
- }
- src = filepath.Clean(src) + string(filepath.Separator)
- root := src
- if pattern == "cmd" {
- root += "cmd" + string(filepath.Separator)
- }
- filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
- if err != nil || !fi.IsDir() || path == src {
- return nil
- }
-
- // Avoid .foo, _foo, and testdata directory trees.
- _, elem := filepath.Split(path)
- if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
- return filepath.SkipDir
- }
-
- name := filepath.ToSlash(path[len(src):])
- if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
- // The name "std" is only the standard library.
- // If the name is cmd, it's the root of the command tree.
- return filepath.SkipDir
- }
- if !treeCanMatch(name) {
- return filepath.SkipDir
- }
- if have[name] {
- return nil
- }
- have[name] = true
- if !match(name) {
- return nil
- }
- _, err = buildContext.ImportDir(path, 0)
- if err != nil {
- if _, noGo := err.(*build.NoGoError); noGo {
- return nil
- }
- }
- pkgs = append(pkgs, name)
- return nil
- })
- }
- return pkgs
-}
-
-// allPackagesInFS is like allPackages but is passed a pattern
-// beginning ./ or ../, meaning it should scan the tree rooted
-// at the given directory. There are ... in the pattern too.
-func allPackagesInFS(pattern string) []string {
- pkgs := matchPackagesInFS(pattern)
- if len(pkgs) == 0 {
- fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
- }
- return pkgs
-}
-
-func matchPackagesInFS(pattern string) []string {
- // Find directory to begin the scan.
- // Could be smarter but this one optimization
- // is enough for now, since ... is usually at the
- // end of a path.
- i := strings.Index(pattern, "...")
- dir, _ := path.Split(pattern[:i])
-
- // pattern begins with ./ or ../.
- // path.Clean will discard the ./ but not the ../.
- // We need to preserve the ./ for pattern matching
- // and in the returned import paths.
- prefix := ""
- if strings.HasPrefix(pattern, "./") {
- prefix = "./"
- }
- match := matchPattern(pattern)
-
- var pkgs []string
- filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
- if err != nil || !fi.IsDir() {
- return nil
- }
- if path == dir {
- // filepath.Walk starts at dir and recurses. For the recursive case,
- // the path is the result of filepath.Join, which calls filepath.Clean.
- // The initial case is not Cleaned, though, so we do this explicitly.
- //
- // This converts a path like "./io/" to "io". Without this step, running
- // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io
- // package, because prepending the prefix "./" to the unclean path would
- // result in "././io", and match("././io") returns false.
- path = filepath.Clean(path)
- }
-
- // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..".
- _, elem := filepath.Split(path)
- dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".."
- if dot || strings.HasPrefix(elem, "_") || elem == "testdata" {
- return filepath.SkipDir
- }
-
- name := prefix + filepath.ToSlash(path)
- if !match(name) {
- return nil
- }
-
- // We keep the directory if we can import it, or if we can't import it
- // due to invalid Go source files. This means that directories containing
- // parse errors will be built (and fail) instead of being silently skipped
- // as not matching the pattern. Go 1.5 and earlier skipped, but that
- // behavior means people miss serious mistakes.
- // See golang.org/issue/11407.
- if p, err := buildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) {
- if _, noGo := err.(*build.NoGoError); !noGo {
- log.Print(err)
- }
- return nil
- }
- pkgs = append(pkgs, name)
- return nil
- })
- return pkgs
-}
-
-// stringList's arguments should be a sequence of string or []string values.
-// stringList flattens them into a single []string.
-func stringList(args ...interface{}) []string {
- var x []string
- for _, arg := range args {
- switch arg := arg.(type) {
- case []string:
- x = append(x, arg...)
- case string:
- x = append(x, arg)
- default:
- panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg))
- }
- }
- return x
-}
-
-// toFold returns a string with the property that
-// strings.EqualFold(s, t) iff toFold(s) == toFold(t)
-// This lets us test a large set of strings for fold-equivalent
-// duplicates without making a quadratic number of calls
-// to EqualFold. Note that strings.ToUpper and strings.ToLower
-// have the desired property in some corner cases.
-func toFold(s string) string {
- // Fast path: all ASCII, no upper case.
- // Most paths look like this already.
- for i := 0; i < len(s); i++ {
- c := s[i]
- if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' {
- goto Slow
- }
- }
- return s
-
-Slow:
- var buf bytes.Buffer
- for _, r := range s {
- // SimpleFold(x) cycles to the next equivalent rune > x
- // or wraps around to smaller values. Iterate until it wraps,
- // and we've found the minimum value.
- for {
- r0 := r
- r = unicode.SimpleFold(r0)
- if r <= r0 {
- break
- }
- }
- // Exception to allow fast path above: A-Z => a-z
- if 'A' <= r && r <= 'Z' {
- r += 'a' - 'A'
- }
- buf.WriteRune(r)
- }
- return buf.String()
-}
-
-// foldDup reports a pair of strings from the list that are
-// equal according to strings.EqualFold.
-// It returns "", "" if there are no such strings.
-func foldDup(list []string) (string, string) {
- clash := map[string]string{}
- for _, s := range list {
- fold := toFold(s)
- if t := clash[fold]; t != "" {
- if s > t {
- s, t = t, s
- }
- return s, t
- }
- clash[fold] = s
- }
- return "", ""
-}
diff --git a/libgo/go/cmd/go/match_test.go b/libgo/go/cmd/go/match_test.go
deleted file mode 100644
index e0ad562..0000000
--- a/libgo/go/cmd/go/match_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "testing"
-
-var matchPatternTests = []stringPairTest{
- {"...", "foo", true},
- {"net", "net", true},
- {"net", "net/http", false},
- {"net/http", "net", false},
- {"net/http", "net/http", true},
- {"net...", "netchan", true},
- {"net...", "net", true},
- {"net...", "net/http", true},
- {"net...", "not/http", false},
- {"net/...", "netchan", false},
- {"net/...", "net", true},
- {"net/...", "net/http", true},
- {"net/...", "not/http", false},
-}
-
-func TestMatchPattern(t *testing.T) {
- testStringPairs(t, "matchPattern", matchPatternTests, func(pattern, name string) bool {
- return matchPattern(pattern)(name)
- })
-}
-
-var treeCanMatchPatternTests = []stringPairTest{
- {"...", "foo", true},
- {"net", "net", true},
- {"net", "net/http", false},
- {"net/http", "net", true},
- {"net/http", "net/http", true},
- {"net...", "netchan", true},
- {"net...", "net", true},
- {"net...", "net/http", true},
- {"net...", "not/http", false},
- {"net/...", "netchan", false},
- {"net/...", "net", true},
- {"net/...", "net/http", true},
- {"net/...", "not/http", false},
- {"abc.../def", "abcxyz", true},
- {"abc.../def", "xyxabc", false},
- {"x/y/z/...", "x", true},
- {"x/y/z/...", "x/y", true},
- {"x/y/z/...", "x/y/z", true},
- {"x/y/z/...", "x/y/z/w", true},
- {"x/y/z", "x", true},
- {"x/y/z", "x/y", true},
- {"x/y/z", "x/y/z", true},
- {"x/y/z", "x/y/z/w", false},
- {"x/.../y/z", "x/a/b/c", true},
- {"x/.../y/z", "y/x/a/b/c", false},
-}
-
-func TestChildrenCanMatchPattern(t *testing.T) {
- testStringPairs(t, "treeCanMatchPattern", treeCanMatchPatternTests, func(pattern, name string) bool {
- return treeCanMatchPattern(pattern)(name)
- })
-}
-
-var hasPathPrefixTests = []stringPairTest{
- {"abc", "a", false},
- {"a/bc", "a", true},
- {"a", "a", true},
- {"a/bc", "a/", true},
-}
-
-func TestHasPathPrefix(t *testing.T) {
- testStringPairs(t, "hasPathPrefix", hasPathPrefixTests, hasPathPrefix)
-}
-
-type stringPairTest struct {
- in1 string
- in2 string
- out bool
-}
-
-func testStringPairs(t *testing.T, name string, tests []stringPairTest, f func(string, string) bool) {
- for _, tt := range tests {
- if out := f(tt.in1, tt.in2); out != tt.out {
- t.Errorf("%s(%q, %q) = %v, want %v", name, tt.in1, tt.in2, out, tt.out)
- }
- }
-}
diff --git a/libgo/go/cmd/go/note_test.go b/libgo/go/cmd/go/note_test.go
index 7b5568f..f33efdc 100644
--- a/libgo/go/cmd/go/note_test.go
+++ b/libgo/go/cmd/go/note_test.go
@@ -7,10 +7,11 @@
package main_test
import (
- main "cmd/go"
"go/build"
"runtime"
"testing"
+
+ "cmd/go/internal/buildid"
)
func TestNoteReading(t *testing.T) {
@@ -23,9 +24,9 @@ func TestNoteReading2K(t *testing.T) {
}
// Set BuildIDReadSize to 2kB to exercise Mach-O parsing more strictly.
defer func(old int) {
- main.BuildIDReadSize = old
- }(main.BuildIDReadSize)
- main.BuildIDReadSize = 2 * 1024
+ buildid.BuildIDReadSize = old
+ }(buildid.BuildIDReadSize)
+ buildid.BuildIDReadSize = 2 * 1024
testNoteReading(t)
}
@@ -36,7 +37,7 @@ func testNoteReading(t *testing.T) {
tg.tempFile("hello.go", `package main; func main() { print("hello, world\n") }`)
const buildID = "TestNoteReading-Build-ID"
tg.run("build", "-ldflags", "-buildid="+buildID, "-o", tg.path("hello.exe"), tg.path("hello.go"))
- id, err := main.ReadBuildIDFromBinary(tg.path("hello.exe"))
+ id, err := buildid.ReadBuildIDFromBinary(tg.path("hello.exe"))
if err != nil {
t.Fatalf("reading build ID from hello binary: %v", err)
}
@@ -56,7 +57,7 @@ func testNoteReading(t *testing.T) {
}
tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello.exe"), tg.path("hello.go"))
- id, err = main.ReadBuildIDFromBinary(tg.path("hello.exe"))
+ id, err = buildid.ReadBuildIDFromBinary(tg.path("hello.exe"))
if err != nil {
t.Fatalf("reading build ID from hello binary (linkmode=external): %v", err)
}
diff --git a/libgo/go/cmd/go/pkg_test.go b/libgo/go/cmd/go/pkg_test.go
deleted file mode 100644
index fba1363..0000000
--- a/libgo/go/cmd/go/pkg_test.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
- "reflect"
- "strings"
- "testing"
-)
-
-var foldDupTests = []struct {
- list []string
- f1, f2 string
-}{
- {stringList("math/rand", "math/big"), "", ""},
- {stringList("math", "strings"), "", ""},
- {stringList("strings"), "", ""},
- {stringList("strings", "strings"), "strings", "strings"},
- {stringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"},
-}
-
-func TestFoldDup(t *testing.T) {
- for _, tt := range foldDupTests {
- f1, f2 := foldDup(tt.list)
- if f1 != tt.f1 || f2 != tt.f2 {
- t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2)
- }
- }
-}
-
-var parseMetaGoImportsTests = []struct {
- in string
- out []metaImport
-}{
- {
- ``,
- []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
- },
- {
- `
- `,
- []metaImport{
- {"foo/bar", "git", "https://github.com/rsc/foo/bar"},
- {"baz/quux", "git", "http://github.com/rsc/baz/quux"},
- },
- },
- {
- `
-
- `,
- []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
- },
- {
- `
- `,
- []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
- },
- {
- ``,
- []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
- },
- {
- // XML doesn't like .
- `
Page Not FoundDRAFT
`,
- []metaImport{{"chitin.io/chitin", "git", "https://github.com/chitin-io/chitin"}},
- },
-}
-
-func TestParseMetaGoImports(t *testing.T) {
- for i, tt := range parseMetaGoImportsTests {
- out, err := parseMetaGoImports(strings.NewReader(tt.in))
- if err != nil {
- t.Errorf("test#%d: %v", i, err)
- continue
- }
- if !reflect.DeepEqual(out, tt.out) {
- t.Errorf("test#%d:\n\thave %q\n\twant %q", i, out, tt.out)
- }
- }
-}
-
-func TestSharedLibName(t *testing.T) {
- // TODO(avdva) - make these values platform-specific
- prefix := "lib"
- suffix := ".so"
- testData := []struct {
- args []string
- pkgs []*Package
- expected string
- expectErr bool
- rootedAt string
- }{
- {
- args: []string{"std"},
- pkgs: []*Package{},
- expected: "std",
- },
- {
- args: []string{"std", "cmd"},
- pkgs: []*Package{},
- expected: "std,cmd",
- },
- {
- args: []string{},
- pkgs: []*Package{&Package{ImportPath: "gopkg.in/somelib"}},
- expected: "gopkg.in-somelib",
- },
- {
- args: []string{"./..."},
- pkgs: []*Package{&Package{ImportPath: "somelib"}},
- expected: "somelib",
- rootedAt: "somelib",
- },
- {
- args: []string{"../somelib", "../somelib"},
- pkgs: []*Package{&Package{ImportPath: "somelib"}},
- expected: "somelib",
- },
- {
- args: []string{"../lib1", "../lib2"},
- pkgs: []*Package{&Package{ImportPath: "gopkg.in/lib1"}, &Package{ImportPath: "gopkg.in/lib2"}},
- expected: "gopkg.in-lib1,gopkg.in-lib2",
- },
- {
- args: []string{"./..."},
- pkgs: []*Package{
- &Package{ImportPath: "gopkg.in/dir/lib1"},
- &Package{ImportPath: "gopkg.in/lib2"},
- &Package{ImportPath: "gopkg.in/lib3"},
- },
- expected: "gopkg.in",
- rootedAt: "gopkg.in",
- },
- {
- args: []string{"std", "../lib2"},
- pkgs: []*Package{},
- expectErr: true,
- },
- {
- args: []string{"all", "./"},
- pkgs: []*Package{},
- expectErr: true,
- },
- {
- args: []string{"cmd", "fmt"},
- pkgs: []*Package{},
- expectErr: true,
- },
- }
- for _, data := range testData {
- func() {
- if data.rootedAt != "" {
- tmpGopath, err := ioutil.TempDir("", "gopath")
- if err != nil {
- t.Fatal(err)
- }
- oldGopath := buildContext.GOPATH
- defer func() {
- buildContext.GOPATH = oldGopath
- os.Chdir(cwd)
- err := os.RemoveAll(tmpGopath)
- if err != nil {
- t.Error(err)
- }
- }()
- root := filepath.Join(tmpGopath, "src", data.rootedAt)
- err = os.MkdirAll(root, 0755)
- if err != nil {
- t.Fatal(err)
- }
- buildContext.GOPATH = tmpGopath
- os.Chdir(root)
- }
- computed, err := libname(data.args, data.pkgs)
- if err != nil {
- if !data.expectErr {
- t.Errorf("libname returned an error %q, expected a name", err.Error())
- }
- } else if data.expectErr {
- t.Errorf("libname returned %q, expected an error", computed)
- } else {
- expected := prefix + data.expected + suffix
- if expected != computed {
- t.Errorf("libname returned %q, expected %q", computed, expected)
- }
- }
- }()
- }
-}
diff --git a/libgo/go/cmd/go/script b/libgo/go/cmd/go/script
deleted file mode 100644
index 340a7e8..0000000
--- a/libgo/go/cmd/go/script
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-x() {
- echo '--- ' "$@"
- "$@"
- echo '---'
- echo
-}
-
-x go help
-x go help build
-x go help clean
-x go help install
-x go help fix
-x go help fmt
-x go help get
-x go help list
-x go help test
-x go help version
-x go help vet
-x go help gopath
-x go help importpath
-x go help remote
diff --git a/libgo/go/cmd/go/script.txt b/libgo/go/cmd/go/script.txt
deleted file mode 100644
index a672146..0000000
--- a/libgo/go/cmd/go/script.txt
+++ /dev/null
@@ -1,352 +0,0 @@
---- go help
-usage: go command [arguments]
-
-go manages Go source code.
-
-The commands are:
-
- build compile and install packages and dependencies
- clean remove intermediate objects
- fix run gofix on packages
- fmt run gofmt -w on packages
- get download and install packages and dependencies
- install install packages and dependencies
- list list packages
- test test packages
- version print Go version
- vet run govet on packages
-
-Use "go help [command]" for more information about a command.
-
-Additional help topics:
-
- gopath GOPATH environment variable
- importpath description of import paths
- remote remote import path syntax
-
-Use "go help [topic]" for more information about that topic.
-
----
-
---- go help build
-usage: go build [-n] [-v] [importpath...]
-
-Build compiles the packages named by the import paths,
-along with their dependencies, but it does not install the results.
-
-The -n flag prints the commands but does not run them.
-The -v flag prints the commands.
-
-For more about import paths, see 'go help importpath'.
-
-See also: go install, go get, go clean.
----
-
---- go help clean
-usage: go clean [-nuke] [importpath...]
-
-Clean removes intermediate object files generated during
-the compilation of the packages named by the import paths,
-but by default it does not remove the installed package binaries.
-
-The -nuke flag causes clean to remove the installed package binaries too.
-
-TODO: Clean does not clean dependencies of the packages.
-
-For more about import paths, see 'go help importpath'.
----
-
---- go help install
-usage: go install [-n] [-v] [importpath...]
-
-Install compiles and installs the packages named by the import paths,
-along with their dependencies.
-
-The -n flag prints the commands but does not run them.
-The -v flag prints the commands.
-
-For more about import paths, see 'go help importpath'.
-
-See also: go build, go get, go clean.
----
-
---- go help fix
-usage: go fix [importpath...]
-
-Fix runs the gofix command on the packages named by the import paths.
-
-For more about gofix, see 'godoc gofix'.
-For more about import paths, see 'go help importpath'.
-
-To run gofix with specific options, run gofix itself.
-
-See also: go fmt, go vet.
----
-
---- go help fmt
-usage: go fmt [importpath...]
-
-Fmt runs the command 'gofmt -w' on the packages named by the import paths.
-
-For more about gofmt, see 'godoc gofmt'.
-For more about import paths, see 'go help importpath'.
-
-To run gofmt with specific options, run gofmt itself.
-
-See also: go fix, go vet.
----
-
---- go help get
-usage: go get [importpath...]
-
-Get downloads and installs the packages named by the import paths,
-along with their dependencies.
-
-After downloading the code, 'go get' looks for a tag beginning
-with "go." that corresponds to the local Go version.
-For Go "release.r58" it looks for a tag named "go.r58".
-For "weekly.2011-06-03" it looks for "go.weekly.2011-06-03".
-If the specific "go.X" tag is not found, it uses the latest earlier
-version it can find. Otherwise, it uses the default version for
-the version control system: HEAD for git, tip for Mercurial,
-and so on.
-
-TODO: Explain versions better.
-
-For more about import paths, see 'go help importpath'.
-
-For more about how 'go get' finds source code to
-download, see 'go help remote'.
-
-See also: go build, go install, go clean.
----
-
---- go help list
-usage: go list [-f format] [-json] [importpath...]
-
-List lists the packages named by the import paths.
-
-The default output shows the package name and file system location:
-
- books /home/you/src/google-api-go-client.googlecode.com/hg/books/v1
- oauth /home/you/src/goauth2.googlecode.com/hg/oauth
- sqlite /home/you/src/gosqlite.googlecode.com/hg/sqlite
-
-The -f flag specifies an alternate format for the list,
-using the syntax of package template. The default output
-is equivalent to -f '{{.Name}} {{.Dir}}' The struct
-being passed to the template is:
-
- type Package struct {
- Name string // package name
- Doc string // package documentation string
- GoFiles []string // names of Go source files in package
- ImportPath string // import path denoting package
- Imports []string // import paths used by this package
- Deps []string // all (recursively) imported dependencies
- Dir string // directory containing package sources
- Version string // version of installed package
- }
-
-The -json flag causes the package data to be printed in JSON format.
-
-For more about import paths, see 'go help importpath'.
----
-
---- go help test
-usage: go test [importpath...]
-
-Test runs gotest to test the packages named by the import paths.
-It prints a summary of the test results in the format:
-
- test archive/tar
- FAIL archive/zip
- test compress/gzip
- ...
-
-followed by gotest output for each failed package.
-
-For more about import paths, see 'go help importpath'.
-
-See also: go build, go compile, go vet.
----
-
---- go help version
-usage: go version
-
-Version prints the Go version, as reported by runtime.Version.
----
-
---- go help vet
-usage: go vet [importpath...]
-
-Vet runs the govet command on the packages named by the import paths.
-
-For more about govet, see 'godoc govet'.
-For more about import paths, see 'go help importpath'.
-
-To run govet with specific options, run govet itself.
-
-See also: go fmt, go fix.
----
-
---- go help gopath
-The GOPATH environment variable lists places to look for Go code.
-On Unix, the value is a colon-separated string.
-On Windows, the value is a semicolon-separated string.
-On Plan 9, the value is a list.
-
-GOPATH must be set to build and install packages outside the
-standard Go tree.
-
-Each directory listed in GOPATH must have a prescribed structure:
-
-The src/ directory holds source code. The path below 'src'
-determines the import path or executable name.
-
-The pkg/ directory holds installed package objects.
-As in the Go tree, each target operating system and
-architecture pair has its own subdirectory of pkg
-(pkg/GOOS_GOARCH).
-
-If DIR is a directory listed in the GOPATH, a package with
-source in DIR/src/foo/bar can be imported as "foo/bar" and
-has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
-
-The bin/ directory holds compiled commands.
-Each command is named for its source directory, but only
-the final element, not the entire path. That is, the
-command with source in DIR/src/foo/quux is installed into
-DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped
-so that you can add DIR/bin to your PATH to get at the
-installed commands.
-
-Here's an example directory layout:
-
- GOPATH=/home/user/gocode
-
- /home/user/gocode/
- src/
- foo/
- bar/ (go code in package bar)
- x.go
- quux/ (go code in package main)
- y.go
- bin/
- quux (installed command)
- pkg/
- linux_amd64/
- foo/
- bar.a (installed package object)
-
-Go searches each directory listed in GOPATH to find source code,
-but new packages are always downloaded into the first directory
-in the list.
----
-
---- go help importpath
-Many commands apply to a set of packages named by import paths:
-
- go action [importpath...]
-
-An import path that is a rooted path or that begins with
-a . or .. element is interpreted as a file system path and
-denotes the package in that directory.
-
-Otherwise, the import path P denotes the package found in
-the directory DIR/src/P for some DIR listed in the GOPATH
-environment variable (see 'go help gopath').
-
-If no import paths are given, the action applies to the
-package in the current directory.
-
-The special import path "all" expands to all package directories
-found in all the GOPATH trees. For example, 'go list all'
-lists all the packages on the local system.
-
-An import path can also name a package to be downloaded from
-a remote repository. Run 'go help remote' for details.
-
-Every package in a program must have a unique import path.
-By convention, this is arranged by starting each path with a
-unique prefix that belongs to you. For example, paths used
-internally at Google all begin with 'google', and paths
-denoting remote repositories begin with the path to the code,
-such as 'project.googlecode.com/'.
----
-
---- go help remote
-An import path (see 'go help importpath') denotes a package
-stored in the local file system. Certain import paths also
-describe how to obtain the source code for the package using
-a revision control system.
-
-A few common code hosting sites have special syntax:
-
- BitBucket (Mercurial)
-
- import "bitbucket.org/user/project"
- import "bitbucket.org/user/project/sub/directory"
-
- GitHub (Git)
-
- import "github.com/user/project"
- import "github.com/user/project/sub/directory"
-
- Google Code Project Hosting (Git, Mercurial, Subversion)
-
- import "project.googlecode.com/git"
- import "project.googlecode.com/git/sub/directory"
-
- import "project.googlecode.com/hg"
- import "project.googlecode.com/hg/sub/directory"
-
- import "project.googlecode.com/svn/trunk"
- import "project.googlecode.com/svn/trunk/sub/directory"
-
- Launchpad (Bazaar)
-
- import "launchpad.net/project"
- import "launchpad.net/project/series"
- import "launchpad.net/project/series/sub/directory"
-
- import "launchpad.net/~user/project/branch"
- import "launchpad.net/~user/project/branch/sub/directory"
-
-For code hosted on other servers, an import path of the form
-
- repository.vcs/path
-
-specifies the given repository, with or without the .vcs suffix,
-using the named version control system, and then the path inside
-that repository. The supported version control systems are:
-
- Bazaar .bzr
- Git .git
- Mercurial .hg
- Subversion .svn
-
-For example,
-
- import "example.org/user/foo.hg"
-
-denotes the root directory of the Mercurial repository at
-example.org/user/foo or foo.hg, and
-
- import "example.org/repo.git/foo/bar"
-
-denotes the foo/bar directory of the Git repository at
-example.com/repo or repo.git.
-
-When a version control system supports multiple protocols,
-each is tried in turn when downloading. For example, a Git
-download tries git://, then https://, then http://.
-
-New downloaded packages are written to the first directory
-listed in the GOPATH environment variable (see 'go help gopath').
-
-The go command attempts to download the version of the
-package appropriate for the Go release being used.
-Run 'go help install' for more.
----
-
diff --git a/libgo/go/cmd/go/test.bash b/libgo/go/cmd/go/test.bash
deleted file mode 100644
index 0060ce2..0000000
--- a/libgo/go/cmd/go/test.bash
+++ /dev/null
@@ -1,820 +0,0 @@
-#!/bin/bash
-# Copyright 2012 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.
-
-set -e
-go build -o testgo
-go() {
- echo TEST ERROR: ran go, not testgo: go "$@" >&2
- exit 2
-}
-
-started=false
-TEST() {
- if $started; then
- stop
- fi
- echo TEST: "$@"
- started=true
- ok=true
-}
-stop() {
- if ! $started; then
- echo TEST ERROR: stop missing start >&2
- exit 2
- fi
- started=false
- if $ok; then
- echo PASS
- else
- echo FAIL
- allok=false
- fi
-}
-
-ok=true
-allok=true
-
-unset GOBIN
-unset GOPATH
-unset GOROOT
-
-TEST 'file:line in error messages'
-# Test that error messages have file:line information at beginning of
-# the line. Also test issue 4917: that the error is on stderr.
-d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
-fn=$d/err.go
-echo "package main" > $fn
-echo 'import "bar"' >> $fn
-./testgo run $fn 2>$d/err.out || true
-if ! grep -q "^$fn:" $d/err.out; then
- echo "missing file:line in error message"
- cat $d/err.out
- ok=false
-fi
-rm -r $d
-
-# Test local (./) imports.
-testlocal() {
- local="$1"
- TEST local imports $2 '(easy)'
- ./testgo build -o hello "testdata/$local/easy.go"
- ./hello >hello.out
- if ! grep -q '^easysub\.Hello' hello.out; then
- echo "testdata/$local/easy.go did not generate expected output"
- cat hello.out
- ok=false
- fi
-
- TEST local imports $2 '(easysub)'
- ./testgo build -o hello "testdata/$local/easysub/main.go"
- ./hello >hello.out
- if ! grep -q '^easysub\.Hello' hello.out; then
- echo "testdata/$local/easysub/main.go did not generate expected output"
- cat hello.out
- ok=false
- fi
-
- TEST local imports $2 '(hard)'
- ./testgo build -o hello "testdata/$local/hard.go"
- ./hello >hello.out
- if ! grep -q '^sub\.Hello' hello.out || ! grep -q '^subsub\.Hello' hello.out ; then
- echo "testdata/$local/hard.go did not generate expected output"
- cat hello.out
- ok=false
- fi
-
- rm -f hello.out hello
-
- # Test that go install x.go fails.
- TEST local imports $2 '(go install should fail)'
- if ./testgo install "testdata/$local/easy.go" >/dev/null 2>&1; then
- echo "go install testdata/$local/easy.go succeeded"
- ok=false
- fi
-}
-
-# Test local imports
-testlocal local ''
-
-# Test local imports again, with bad characters in the directory name.
-bad='#$%:, &()*;<=>?\^{}'
-rm -rf "testdata/$bad"
-cp -R testdata/local "testdata/$bad"
-testlocal "$bad" 'with bad characters in path'
-rm -rf "testdata/$bad"
-
-TEST error message for syntax error in test go file says FAIL
-export GOPATH=$(pwd)/testdata
-if ./testgo test syntaxerror 2>testdata/err; then
- echo 'go test syntaxerror succeeded'
- ok=false
-elif ! grep FAIL testdata/err >/dev/null; then
- echo 'go test did not say FAIL:'
- cat testdata/err
- ok=false
-fi
-rm -f ./testdata/err
-unset GOPATH
-
-TEST wildcards do not look in useless directories
-export GOPATH=$(pwd)/testdata
-if ./testgo list ... >testdata/err 2>&1; then
- echo "go list ... succeeded"
- ok=false
-elif ! grep badpkg testdata/err >/dev/null; then
- echo "go list ... failure does not mention badpkg"
- cat testdata/err
- ok=false
-elif ! ./testgo list m... >testdata/err 2>&1; then
- echo "go list m... failed"
- ok=false
-fi
-rm -rf ./testdata/err
-unset GOPATH
-
-# Test tests with relative imports.
-TEST relative imports '(go test)'
-if ! ./testgo test ./testdata/testimport; then
- echo "go test ./testdata/testimport failed"
- ok=false
-fi
-
-# Test installation with relative imports.
-TEST relative imports '(go test -i)'
-if ! ./testgo test -i ./testdata/testimport; then
- echo "go test -i ./testdata/testimport failed"
- ok=false
-fi
-
-# Test tests with relative imports in packages synthesized
-# from Go files named on the command line.
-TEST relative imports in command-line package
-if ! ./testgo test ./testdata/testimport/*.go; then
- echo "go test ./testdata/testimport/*.go failed"
- ok=false
-fi
-
-TEST version control error message includes correct directory
-export GOPATH=$(pwd)/testdata/shadow/root1
-if ./testgo get -u foo 2>testdata/err; then
- echo "go get -u foo succeeded unexpectedly"
- ok=false
-elif ! grep testdata/shadow/root1/src/foo testdata/err >/dev/null; then
- echo "go get -u error does not mention shadow/root1/src/foo:"
- cat testdata/err
- ok=false
-fi
-unset GOPATH
-
-TEST go install fails with no buildable files
-export GOPATH=$(pwd)/testdata
-export CGO_ENABLED=0
-if ./testgo install cgotest 2>testdata/err; then
- echo "go install cgotest succeeded unexpectedly"
-elif ! grep 'no buildable Go source files' testdata/err >/dev/null; then
- echo "go install cgotest did not report 'no buildable Go source files'"
- cat testdata/err
- ok=false
-fi
-unset CGO_ENABLED
-unset GOPATH
-
-# Test that without $GOBIN set, binaries get installed
-# into the GOPATH bin directory.
-TEST install into GOPATH
-rm -rf testdata/bin
-if ! GOPATH=$(pwd)/testdata ./testgo install go-cmd-test; then
- echo "go install go-cmd-test failed"
- ok=false
-elif ! test -x testdata/bin/go-cmd-test; then
- echo "go install go-cmd-test did not write to testdata/bin/go-cmd-test"
- ok=false
-fi
-
-TEST package main_test imports archive not binary
-export GOBIN=$(pwd)/testdata/bin
-mkdir -p $GOBIN
-export GOPATH=$(pwd)/testdata
-touch ./testdata/src/main_test/m.go
-if ! ./testgo test main_test; then
- echo "go test main_test failed without install"
- ok=false
-elif ! ./testgo install main_test; then
- echo "go test main_test failed"
- ok=false
-elif [ "$(./testgo list -f '{{.Stale}}' main_test)" != false ]; then
- echo "after go install, main listed as stale"
- ok=false
-elif ! ./testgo test main_test; then
- echo "go test main_test failed after install"
- ok=false
-fi
-rm -rf $GOBIN
-unset GOBIN
-
-# And with $GOBIN set, binaries get installed to $GOBIN.
-TEST install into GOBIN
-if ! GOBIN=$(pwd)/testdata/bin1 GOPATH=$(pwd)/testdata ./testgo install go-cmd-test; then
- echo "go install go-cmd-test failed"
- ok=false
-elif ! test -x testdata/bin1/go-cmd-test; then
- echo "go install go-cmd-test did not write to testdata/bin1/go-cmd-test"
- ok=false
-fi
-
-# Without $GOBIN set, installing a program outside $GOPATH should fail
-# (there is nowhere to install it).
-TEST install without destination fails
-if ./testgo install testdata/src/go-cmd-test/helloworld.go 2>testdata/err; then
- echo "go install testdata/src/go-cmd-test/helloworld.go should have failed, did not"
- ok=false
-elif ! grep 'no install location for .go files listed on command line' testdata/err; then
- echo "wrong error:"
- cat testdata/err
- ok=false
-fi
-rm -f testdata/err
-
-# With $GOBIN set, should install there.
-TEST install to GOBIN '(command-line package)'
-if ! GOBIN=$(pwd)/testdata/bin1 ./testgo install testdata/src/go-cmd-test/helloworld.go; then
- echo "go install testdata/src/go-cmd-test/helloworld.go failed"
- ok=false
-elif ! test -x testdata/bin1/helloworld; then
- echo "go install testdata/src/go-cmd-test/helloworld.go did not write testdata/bin1/helloworld"
- ok=false
-fi
-
-TEST godoc installs into GOBIN
-d=$(mktemp -d -t testgoXXX)
-export GOPATH=$d
-mkdir $d/gobin
-GOBIN=$d/gobin ./testgo get code.google.com/p/go.tools/cmd/godoc
-if [ ! -x $d/gobin/godoc ]; then
- echo did not install godoc to '$GOBIN'
- GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc
- ok=false
-fi
-
-TEST godoc installs into GOROOT
-GOROOT=$(./testgo env GOROOT)
-rm -f $GOROOT/bin/godoc
-./testgo install code.google.com/p/go.tools/cmd/godoc
-if [ ! -x $GOROOT/bin/godoc ]; then
- echo did not install godoc to '$GOROOT/bin'
- ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc
- ok=false
-fi
-
-TEST cmd/fix installs into tool
-GOOS=$(./testgo env GOOS)
-GOARCH=$(./testgo env GOARCH)
-rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix
-./testgo install cmd/fix
-if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then
- echo 'did not install cmd/fix to $GOROOT/pkg/tool'
- GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix
- ok=false
-fi
-rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix
-GOBIN=$d/gobin ./testgo install cmd/fix
-if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then
- echo 'did not install cmd/fix to $GOROOT/pkg/tool with $GOBIN set'
- GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix
- ok=false
-fi
-
-TEST gopath program installs into GOBIN
-mkdir $d/src/progname
-echo 'package main; func main() {}' >$d/src/progname/p.go
-GOBIN=$d/gobin ./testgo install progname
-if [ ! -x $d/gobin/progname ]; then
- echo 'did not install progname to $GOBIN/progname'
- ./testgo list -f 'Target: {{.Target}}' cmd/api
- ok=false
-fi
-rm -f $d/gobin/progname $d/bin/progname
-
-TEST gopath program installs into GOPATH/bin
-./testgo install progname
-if [ ! -x $d/bin/progname ]; then
- echo 'did not install progname to $GOPATH/bin/progname'
- ./testgo list -f 'Target: {{.Target}}' progname
- ok=false
-fi
-
-unset GOPATH
-rm -rf $d
-
-# Reject relative paths in GOPATH.
-TEST reject relative paths in GOPATH '(command-line package)'
-if GOPATH=. ./testgo build testdata/src/go-cmd-test/helloworld.go; then
- echo 'GOPATH="." go build should have failed, did not'
- ok=false
-fi
-
-TEST reject relative paths in GOPATH
-if GOPATH=:$(pwd)/testdata:. ./testgo build go-cmd-test; then
- echo 'GOPATH=":$(pwd)/testdata:." go build should have failed, did not'
- ok=false
-fi
-
-# issue 4104
-TEST go test with package listed multiple times
-if [ $(./testgo test fmt fmt fmt fmt fmt | wc -l) -ne 1 ] ; then
- echo 'go test fmt fmt fmt fmt fmt tested the same package multiple times'
- ok=false
-fi
-
-# ensure that output of 'go list' is consistent between runs
-TEST go list is consistent
-./testgo list std > test_std.list
-if ! ./testgo list std | cmp -s test_std.list - ; then
- echo "go list std ordering is inconsistent"
- ok=false
-fi
-rm -f test_std.list
-
-# issue 4096. Validate the output of unsuccessful go install foo/quxx
-TEST unsuccessful go install should mention missing package
-if [ $(./testgo install 'foo/quxx' 2>&1 | grep -c 'cannot find package "foo/quxx" in any of') -ne 1 ] ; then
- echo 'go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of'
- ok=false
-fi
-# test GOROOT search failure is reported
-TEST GOROOT search failure reporting
-if [ $(./testgo install 'foo/quxx' 2>&1 | egrep -c 'foo/quxx \(from \$GOROOT\)$') -ne 1 ] ; then
- echo 'go install foo/quxx expected error: .*foo/quxx (from $GOROOT)'
- ok=false
-fi
-# test multiple GOPATH entries are reported separately
-TEST multiple GOPATH entries reported separately
-if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/./src/foo/quxx') -ne 2 ] ; then
- echo 'go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx'
- ok=false
-fi
-# test (from $GOPATH) annotation is reported for the first GOPATH entry
-TEST mention GOPATH in first GOPATH entry
-if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/a/src/foo/quxx \(from \$GOPATH\)$') -ne 1 ] ; then
- echo 'go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)'
- ok=false
-fi
-# but not on the second
-TEST but not the second entry
-if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/b/src/foo/quxx$') -ne 1 ] ; then
- echo 'go install foo/quxx expected error: .*testdata/b/src/foo/quxx'
- ok=false
-fi
-# test missing GOPATH is reported
-TEST missing GOPATH is reported
-if [ $(GOPATH= ./testgo install 'foo/quxx' 2>&1 | egrep -c '\(\$GOPATH not set\)$') -ne 1 ] ; then
- echo 'go install foo/quxx expected error: ($GOPATH not set)'
- ok=false
-fi
-
-# issue 4186. go get cannot be used to download packages to $GOROOT
-# Test that without GOPATH set, go get should fail
-TEST without GOPATH, go get fails
-d=$(mktemp -d -t testgoXXX)
-mkdir -p $d/src/pkg
-if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
- echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset'
- ok=false
-fi
-rm -rf $d
-
-# Test that with GOPATH=$GOROOT, go get should fail
-TEST with GOPATH=GOROOT, go get fails
-d=$(mktemp -d -t testgoXXX)
-mkdir -p $d/src/pkg
-if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
- echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
- ok=false
-fi
-rm -rf $d
-
-TEST ldflags arguments with spaces '(issue 3941)'
-d=$(mktemp -d -t testgoXXX)
-cat >$d/main.go<
hello.out
-if ! grep -q '^hello world' hello.out; then
- echo "ldflags -X main.extern 'hello world' failed. Output:"
- cat hello.out
- ok=false
-fi
-rm -rf $d hello.out
-
-TEST go test -cpuprofile leaves binary behind
-./testgo test -cpuprofile strings.prof strings || ok=false
-if [ ! -x strings.test ]; then
- echo "go test -cpuprofile did not create strings.test"
- ok=false
-fi
-rm -f strings.prof strings.test
-
-TEST symlinks do not confuse go list '(issue 4568)'
-old=$(pwd)
-tmp=$(cd /tmp && pwd -P)
-d=$(TMPDIR=$tmp mktemp -d -t testgoXXX)
-mkdir -p $d/src
-(
- ln -s $d $d/src/dir1
- cd $d/src
- echo package p >dir1/p.go
- export GOPATH=$d
- if [ "$($old/testgo list -f '{{.Root}}' dir1)" != "$d" ]; then
- echo Confused by symlinks.
- echo "Package in current directory $(pwd) should have Root $d"
- env|grep WD
- $old/testgo list -json . dir1
- touch $d/failed
- fi
-)
-if [ -f $d/failed ]; then
- ok=false
-fi
-rm -rf $d
-
-TEST 'install with tags (issue 4515)'
-d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
-mkdir -p $d/src/example/a $d/src/example/b $d/bin
-cat >$d/src/example/a/main.go <$d/src/example/b/main.go <$d/src/example/a/a.go <$d/src/example/a/pkg/pkg.go <$d/src/example/a/Pkg/pkg.go <$d/out; then
- echo go list example/a should have failed, did not.
- ok=false
-elif ! grep "case-insensitive import collision" $d/out >/dev/null; then
- echo go list example/a did not report import collision.
- ok=false
-fi
-cat >$d/src/example/b/file.go <$d/src/example/b/FILE.go <$d/out; then
- echo go list example/b should have failed, did not.
- ok=false
-elif ! grep "case-insensitive file name collision" $d/out >/dev/null; then
- echo go list example/b did not report file name collision.
- ok=false
-fi
-
-TEST go get cover
-./testgo get code.google.com/p/go.tools/cmd/cover || ok=false
-
-unset GOPATH
-rm -rf $d
-
-TEST shadowing logic
-export GOPATH=$(pwd)/testdata/shadow/root1:$(pwd)/testdata/shadow/root2
-
-# The math in root1 is not "math" because the standard math is.
-cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/math)
-if [ "$cdir" != "(_$(pwd)/testdata/shadow/root1/src/math) ($GOROOT/src/pkg/math)" ]; then
- echo shadowed math is not shadowed: "$cdir"
- ok=false
-fi
-
-# The foo in root1 is "foo".
-cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/foo)
-if [ "$cdir" != "(foo) ()" ]; then
- echo unshadowed foo is shadowed: "$cdir"
- ok=false
-fi
-
-# The foo in root2 is not "foo" because the foo in root1 got there first.
-cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root2/src/foo)
-if [ "$cdir" != "(_$(pwd)/testdata/shadow/root2/src/foo) ($(pwd)/testdata/shadow/root1/src/foo)" ]; then
- echo shadowed foo is not shadowed: "$cdir"
- ok=false
-fi
-
-# The error for go install should mention the conflicting directory.
-err=$(! ./testgo install ./testdata/shadow/root2/src/foo 2>&1)
-if [ "$err" != "go install: no install location for $(pwd)/testdata/shadow/root2/src/foo: hidden by $(pwd)/testdata/shadow/root1/src/foo" ]; then
- echo wrong shadowed install error: "$err"
- ok=false
-fi
-
-# Only succeeds if source order is preserved.
-TEST source file name order preserved
-./testgo test testdata/example[12]_test.go || ok=false
-
-# Check that coverage analysis works at all.
-# Don't worry about the exact numbers but require not 0.0%.
-checkcoverage() {
- if grep '[^0-9]0\.0%' testdata/cover.txt >/dev/null; then
- echo 'some coverage results are 0.0%'
- ok=false
- fi
- cat testdata/cover.txt
- rm -f testdata/cover.txt
-}
-
-TEST coverage runs
-./testgo test -short -coverpkg=strings strings regexp >testdata/cover.txt 2>&1 || ok=false
-./testgo test -short -cover strings math regexp >>testdata/cover.txt 2>&1 || ok=false
-checkcoverage
-
-# Check that coverage analysis uses set mode.
-TEST coverage uses set mode
-if ./testgo test -short -cover encoding/binary -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then
- if ! grep -q 'mode: set' testdata/cover.out; then
- ok=false
- fi
- checkcoverage
-else
- ok=false
-fi
-rm -f testdata/cover.out testdata/cover.txt
-
-TEST coverage uses atomic mode for -race.
-if ./testgo test -short -race -cover encoding/binary -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then
- if ! grep -q 'mode: atomic' testdata/cover.out; then
- ok=false
- fi
- checkcoverage
-else
- ok=false
-fi
-rm -f testdata/cover.out
-
-TEST coverage uses actual setting to override even for -race.
-if ./testgo test -short -race -cover encoding/binary -covermode=count -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then
- if ! grep -q 'mode: count' testdata/cover.out; then
- ok=false
- fi
- checkcoverage
-else
- ok=false
-fi
-rm -f testdata/cover.out
-
-TEST coverage with cgo
-d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
-./testgo test -short -cover ./testdata/cgocover >testdata/cover.txt 2>&1 || ok=false
-checkcoverage
-
-TEST cgo depends on syscall
-rm -rf $GOROOT/pkg/*_race
-d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
-export GOPATH=$d
-mkdir -p $d/src/foo
-echo '
-package foo
-//#include
-import "C"
-' >$d/src/foo/foo.go
-./testgo build -race foo || ok=false
-rm -rf $d
-unset GOPATH
-
-TEST cgo shows full path names
-d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
-export GOPATH=$d
-mkdir -p $d/src/x/y/dirname
-echo '
-package foo
-import "C"
-func f() {
-' >$d/src/x/y/dirname/foo.go
-if ./testgo build x/y/dirname >$d/err 2>&1; then
- echo build succeeded unexpectedly.
- ok=false
-elif ! grep x/y/dirname $d/err >/dev/null; then
- echo error did not use full path.
- cat $d/err
- ok=false
-fi
-rm -rf $d
-unset GOPATH
-
-TEST 'cgo handles -Wl,$ORIGIN'
-d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
-export GOPATH=$d
-mkdir -p $d/src/origin
-echo '
-package origin
-// #cgo !darwin LDFLAGS: -Wl,-rpath -Wl,$ORIGIN
-// void f(void) {}
-import "C"
-
-func f() { C.f() }
-' >$d/src/origin/origin.go
-if ! ./testgo build origin; then
- echo build failed
- ok=false
-fi
-rm -rf $d
-unset GOPATH
-
-TEST 'Issue 6480: "go test -c -test.bench=XXX fmt" should not hang'
-if ! ./testgo test -c -test.bench=XXX fmt; then
- echo build test failed
- ok=false
-fi
-rm -f fmt.test
-
-TEST 'Issue 7573: cmd/cgo: undefined reference when linking a C-library using gccgo'
-d=$(mktemp -d -t testgoXXX)
-export GOPATH=$d
-mkdir -p $d/src/cgoref
-ldflags="-L alibpath -lalib"
-echo "
-package main
-// #cgo LDFLAGS: $ldflags
-// void f(void) {}
-import \"C\"
-
-func main() { C.f() }
-" >$d/src/cgoref/cgoref.go
-go_cmds="$(./testgo build -n -compiler gccgo cgoref 2>&1 1>/dev/null)"
-ldflags_count="$(echo "$go_cmds" | egrep -c "^gccgo.*$(echo $ldflags | sed -e 's/-/\\-/g')" || true)"
-if [ "$ldflags_count" -lt 1 ]; then
- echo "No Go-inline "#cgo LDFLAGS:" (\"$ldflags\") passed to gccgo linking stage."
- ok=false
-fi
-rm -rf $d
-unset ldflags_count
-unset go_cmds
-unset ldflags
-unset GOPATH
-
-TEST list template can use context function
-if ! ./testgo list -f "GOARCH: {{context.GOARCH}}"; then
- echo unable to use context in list template
- ok=false
-fi
-
-TEST 'Issue 7108: cmd/go: "go test" should fail if package does not build'
-export GOPATH=$(pwd)/testdata
-if ./testgo test notest >/dev/null 2>&1; then
- echo 'go test notest succeeded, but should fail'
- ok=false
-fi
-unset GOPATH
-
-TEST 'Issue 6844: cmd/go: go test -a foo does not rebuild regexp'
-if ! ./testgo test -x -a -c testdata/dep_test.go 2>deplist; then
- echo "go test -x -a -c testdata/dep_test.go failed"
- ok=false
-elif ! grep -q regexp deplist; then
- echo "go test -x -a -c testdata/dep_test.go did not rebuild regexp"
- ok=false
-fi
-rm -f deplist
-rm -f deps.test
-
-TEST list template can use context function
-if ! ./testgo list -f "GOARCH: {{context.GOARCH}}"; then
- echo unable to use context in list template
- ok=false
-fi
-
-TEST build -i installs dependencies
-d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX)
-export GOPATH=$d
-mkdir -p $d/src/x/y/foo $d/src/x/y/bar
-echo '
-package foo
-func F() {}
-' >$d/src/x/y/foo/foo.go
-echo '
-package bar
-import "x/y/foo"
-func F() { foo.F() }
-' >$d/src/x/y/bar/bar.go
-if ! ./testgo build -v -i x/y/bar &> $d/err; then
- echo build -i failed
- cat $d/err
- ok=false
-elif ! grep x/y/foo $d/err >/dev/null; then
- echo first build -i did not build x/y/foo
- cat $d/err
- ok=false
-fi
-if ! ./testgo build -v -i x/y/bar &> $d/err; then
- echo second build -i failed
- cat $d/err
- ok=false
-elif grep x/y/foo $d/err >/dev/null; then
- echo second build -i built x/y/foo
- cat $d/err
- ok=false
-fi
-rm -rf $d
-unset GOPATH
-
-TEST 'go build in test-only directory fails with a good error'
-if ./testgo build ./testdata/testonly 2>testdata/err.out; then
- echo "go build ./testdata/testonly succeeded, should have failed"
- ok=false
-elif ! grep 'no buildable Go' testdata/err.out >/dev/null; then
- echo "go build ./testdata/testonly produced unexpected error:"
- cat testdata/err.out
- ok=false
-fi
-rm -f testdata/err.out
-
-TEST 'go test detects test-only import cycles'
-export GOPATH=$(pwd)/testdata
-if ./testgo test -c testcycle/p3 2>testdata/err.out; then
- echo "go test testcycle/p3 succeeded, should have failed"
- ok=false
-elif ! grep 'import cycle not allowed in test' testdata/err.out >/dev/null; then
- echo "go test testcycle/p3 produced unexpected error:"
- cat testdata/err.out
- ok=false
-fi
-rm -f testdata/err.out
-unset GOPATH
-
-TEST 'go test foo_test.go works'
-if ! ./testgo test testdata/standalone_test.go; then
- echo "go test testdata/standalone_test.go failed"
- ok=false
-fi
-
-TEST 'go test xtestonly works'
-export GOPATH=$(pwd)/testdata
-./testgo clean -i xtestonly
-if ! ./testgo test xtestonly >/dev/null; then
- echo "go test xtestonly failed"
- ok=false
-fi
-unset GOPATH
-
-
-# clean up
-if $started; then stop; fi
-rm -rf testdata/bin testdata/bin1
-rm -f testgo
-
-if $allok; then
- echo PASS
-else
- echo FAIL
- exit 1
-fi
diff --git a/libgo/go/cmd/go/testdata/src/bench/x_test.go b/libgo/go/cmd/go/testdata/src/bench/x_test.go
new file mode 100644
index 0000000..32cabf8
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/bench/x_test.go
@@ -0,0 +1,6 @@
+package bench
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+}
diff --git a/libgo/go/cmd/go/testdata/src/cgoasm/p.go b/libgo/go/cmd/go/testdata/src/cgoasm/p.go
new file mode 100644
index 0000000..148b47f
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgoasm/p.go
@@ -0,0 +1,8 @@
+package p
+
+/*
+// hi
+*/
+import "C"
+
+func F() {}
diff --git a/libgo/go/cmd/go/testdata/src/cgoasm/p.s b/libgo/go/cmd/go/testdata/src/cgoasm/p.s
new file mode 100644
index 0000000..aaade03
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgoasm/p.s
@@ -0,0 +1,2 @@
+TEXT asm(SB),$0
+ RET
diff --git a/libgo/go/cmd/go/testdata/src/exclude/empty/x.txt b/libgo/go/cmd/go/testdata/src/exclude/empty/x.txt
new file mode 100644
index 0000000..e69de29
diff --git a/libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go b/libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go
new file mode 100644
index 0000000..823aafd
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/exclude/ignore/_x.go
@@ -0,0 +1 @@
+package x
diff --git a/libgo/go/cmd/go/testdata/src/exclude/x.go b/libgo/go/cmd/go/testdata/src/exclude/x.go
new file mode 100644
index 0000000..9affd21
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/exclude/x.go
@@ -0,0 +1,3 @@
+// +build linux,!linux
+
+package x
diff --git a/libgo/go/cmd/go/testdata/src/exclude/x_linux.go b/libgo/go/cmd/go/testdata/src/exclude/x_linux.go
new file mode 100644
index 0000000..41ef6e5
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/exclude/x_linux.go
@@ -0,0 +1,3 @@
+// +build windows
+
+package x
diff --git a/libgo/go/cmd/go/testdata/src/testlist/bench_test.go b/libgo/go/cmd/go/testdata/src/testlist/bench_test.go
new file mode 100644
index 0000000..22f147b
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/testlist/bench_test.go
@@ -0,0 +1,14 @@
+package testlist
+
+import (
+ "fmt"
+ "testing"
+)
+
+func BenchmarkSimplefunc(b *testing.B) {
+ b.StopTimer()
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ _ = fmt.Sprint("Test for bench")
+ }
+}
diff --git a/libgo/go/cmd/go/testdata/src/testlist/example_test.go b/libgo/go/cmd/go/testdata/src/testlist/example_test.go
new file mode 100644
index 0000000..0298dfd
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/testlist/example_test.go
@@ -0,0 +1,21 @@
+package testlist
+
+import (
+ "fmt"
+)
+
+func ExampleSimple() {
+ fmt.Println("Test with Output.")
+
+ // Output: Test with Output.
+}
+
+func ExampleWithEmptyOutput() {
+ fmt.Println("")
+
+ // Output:
+}
+
+func ExampleNoOutput() {
+ _ = fmt.Sprint("Test with no output")
+}
diff --git a/libgo/go/cmd/go/testdata/src/testlist/test_test.go b/libgo/go/cmd/go/testdata/src/testlist/test_test.go
new file mode 100644
index 0000000..bdc09f2
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/testlist/test_test.go
@@ -0,0 +1,10 @@
+package testlist
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestSimple(t *testing.T) {
+ _ = fmt.Sprint("Test simple")
+}
diff --git a/libgo/go/cmd/go/testdata/src/testregexp/x_test.go b/libgo/go/cmd/go/testdata/src/testregexp/x_test.go
new file mode 100644
index 0000000..7573e79
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/testregexp/x_test.go
@@ -0,0 +1,17 @@
+package x
+
+import "testing"
+
+func TestX(t *testing.T) {
+ t.Logf("LOG: X running")
+ t.Run("Y", func(t *testing.T) {
+ t.Logf("LOG: Y running")
+ })
+}
+
+func BenchmarkX(b *testing.B) {
+ b.Logf("LOG: X running N=%d", b.N)
+ b.Run("Y", func(b *testing.B) {
+ b.Logf("LOG: Y running N=%d", b.N)
+ })
+}
diff --git a/libgo/go/cmd/go/testdata/src/testregexp/z_test.go b/libgo/go/cmd/go/testdata/src/testregexp/z_test.go
new file mode 100644
index 0000000..4fd1979
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/testregexp/z_test.go
@@ -0,0 +1,19 @@
+package x
+
+import "testing"
+
+func TestZ(t *testing.T) {
+ t.Logf("LOG: Z running")
+}
+
+func TestXX(t *testing.T) {
+ t.Logf("LOG: XX running")
+}
+
+func BenchmarkZ(b *testing.B) {
+ b.Logf("LOG: Z running N=%d", b.N)
+}
+
+func BenchmarkXX(b *testing.B) {
+ b.Logf("LOG: XX running N=%d", b.N)
+}
diff --git a/libgo/go/cmd/go/testflag.go b/libgo/go/cmd/go/testflag.go
deleted file mode 100644
index fa53bfc..0000000
--- a/libgo/go/cmd/go/testflag.go
+++ /dev/null
@@ -1,294 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
- "flag"
- "fmt"
- "os"
- "strconv"
- "strings"
-)
-
-// The flag handling part of go test is large and distracting.
-// We can't use the flag package because some of the flags from
-// our command line are for us, and some are for 6.out, and
-// some are for both.
-
-// testFlagSpec defines a flag we know about.
-type testFlagSpec struct {
- name string
- boolVar *bool
- flagValue flag.Value
- passToTest bool // pass to Test
- multiOK bool // OK to have multiple instances
- present bool // flag has been seen
-}
-
-// testFlagDefn is the set of flags we process.
-var testFlagDefn = []*testFlagSpec{
- // local.
- {name: "c", boolVar: &testC},
- {name: "i", boolVar: &buildI},
- {name: "o"},
- {name: "cover", boolVar: &testCover},
- {name: "covermode"},
- {name: "coverpkg"},
- {name: "exec"},
-
- // passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
- {name: "bench", passToTest: true},
- {name: "benchmem", boolVar: new(bool), passToTest: true},
- {name: "benchtime", passToTest: true},
- {name: "count", passToTest: true},
- {name: "coverprofile", passToTest: true},
- {name: "cpu", passToTest: true},
- {name: "cpuprofile", passToTest: true},
- {name: "memprofile", passToTest: true},
- {name: "memprofilerate", passToTest: true},
- {name: "blockprofile", passToTest: true},
- {name: "blockprofilerate", passToTest: true},
- {name: "mutexprofile", passToTest: true},
- {name: "mutexprofilefraction", passToTest: true},
- {name: "outputdir", passToTest: true},
- {name: "parallel", passToTest: true},
- {name: "run", passToTest: true},
- {name: "short", boolVar: new(bool), passToTest: true},
- {name: "timeout", passToTest: true},
- {name: "trace", passToTest: true},
- {name: "v", boolVar: &testV, passToTest: true},
-}
-
-// add build flags to testFlagDefn
-func init() {
- var cmd Command
- addBuildFlags(&cmd)
- cmd.Flag.VisitAll(func(f *flag.Flag) {
- if f.Name == "v" {
- // test overrides the build -v flag
- return
- }
- testFlagDefn = append(testFlagDefn, &testFlagSpec{
- name: f.Name,
- flagValue: f.Value,
- })
- })
-}
-
-// testFlags processes the command line, grabbing -x and -c, rewriting known flags
-// to have "test" before them, and reading the command line for the 6.out.
-// Unfortunately for us, we need to do our own flag processing because go test
-// grabs some flags but otherwise its command line is just a holding place for
-// pkg.test's arguments.
-// We allow known flags both before and after the package name list,
-// to allow both
-// go test fmt -custom-flag-for-fmt-test
-// go test -x math
-func testFlags(args []string) (packageNames, passToTest []string) {
- inPkg := false
- outputDir := ""
- var explicitArgs []string
- for i := 0; i < len(args); i++ {
- if !strings.HasPrefix(args[i], "-") {
- if !inPkg && packageNames == nil {
- // First package name we've seen.
- inPkg = true
- }
- if inPkg {
- packageNames = append(packageNames, args[i])
- continue
- }
- }
-
- if inPkg {
- // Found an argument beginning with "-"; end of package list.
- inPkg = false
- }
-
- f, value, extraWord := testFlag(args, i)
- if f == nil {
- // This is a flag we do not know; we must assume
- // that any args we see after this might be flag
- // arguments, not package names.
- inPkg = false
- if packageNames == nil {
- // make non-nil: we have seen the empty package list
- packageNames = []string{}
- }
- if args[i] == "-args" || args[i] == "--args" {
- // -args or --args signals that everything that follows
- // should be passed to the test.
- explicitArgs = args[i+1:]
- break
- }
- passToTest = append(passToTest, args[i])
- continue
- }
- if f.flagValue != nil {
- if err := f.flagValue.Set(value); err != nil {
- fatalf("invalid flag argument for -%s: %v", f.name, err)
- }
- } else {
- // Test-only flags.
- // Arguably should be handled by f.flagValue, but aren't.
- var err error
- switch f.name {
- // bool flags.
- case "c", "i", "v", "cover":
- setBoolFlag(f.boolVar, value)
- case "o":
- testO = value
- testNeedBinary = true
- case "exec":
- execCmd, err = splitQuotedFields(value)
- if err != nil {
- fatalf("invalid flag argument for -%s: %v", f.name, err)
- }
- case "bench":
- // record that we saw the flag; don't care about the value
- testBench = true
- case "timeout":
- testTimeout = value
- case "blockprofile", "cpuprofile", "memprofile", "mutexprofile":
- testProfile = true
- testNeedBinary = true
- case "trace":
- testProfile = true
- case "coverpkg":
- testCover = true
- if value == "" {
- testCoverPaths = nil
- } else {
- testCoverPaths = strings.Split(value, ",")
- }
- case "coverprofile":
- testCover = true
- testProfile = true
- case "covermode":
- switch value {
- case "set", "count", "atomic":
- testCoverMode = value
- default:
- fatalf("invalid flag argument for -covermode: %q", value)
- }
- testCover = true
- case "outputdir":
- outputDir = value
- }
- }
- if extraWord {
- i++
- }
- if f.passToTest {
- passToTest = append(passToTest, "-test."+f.name+"="+value)
- }
- }
-
- if testCoverMode == "" {
- testCoverMode = "set"
- if buildRace {
- // Default coverage mode is atomic when -race is set.
- testCoverMode = "atomic"
- }
- }
-
- // Tell the test what directory we're running in, so it can write the profiles there.
- if testProfile && outputDir == "" {
- dir, err := os.Getwd()
- if err != nil {
- fatalf("error from os.Getwd: %s", err)
- }
- passToTest = append(passToTest, "-test.outputdir", dir)
- }
-
- passToTest = append(passToTest, explicitArgs...)
- return
-}
-
-// testFlag sees if argument i is a known flag and returns its definition, value, and whether it consumed an extra word.
-func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool) {
- arg := args[i]
- if strings.HasPrefix(arg, "--") { // reduce two minuses to one
- arg = arg[1:]
- }
- switch arg {
- case "-?", "-h", "-help":
- usage()
- }
- if arg == "" || arg[0] != '-' {
- return
- }
- name := arg[1:]
- // If there's already "test.", drop it for now.
- name = strings.TrimPrefix(name, "test.")
- equals := strings.Index(name, "=")
- if equals >= 0 {
- value = name[equals+1:]
- name = name[:equals]
- }
- for _, f = range testFlagDefn {
- if name == f.name {
- // Booleans are special because they have modes -x, -x=true, -x=false.
- if f.boolVar != nil || isBoolFlag(f.flagValue) {
- if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag
- value = "true"
- } else {
- // verify it parses
- setBoolFlag(new(bool), value)
- }
- } else { // Non-booleans must have a value.
- extra = equals < 0
- if extra {
- if i+1 >= len(args) {
- testSyntaxError("missing argument for flag " + f.name)
- }
- value = args[i+1]
- }
- }
- if f.present && !f.multiOK {
- testSyntaxError(f.name + " flag may be set only once")
- }
- f.present = true
- return
- }
- }
- f = nil
- return
-}
-
-// isBoolFlag reports whether v is a bool flag.
-func isBoolFlag(v flag.Value) bool {
- vv, ok := v.(interface {
- IsBoolFlag() bool
- })
- if ok {
- return vv.IsBoolFlag()
- }
- return false
-}
-
-// setBoolFlag sets the addressed boolean to the value.
-func setBoolFlag(flag *bool, value string) {
- x, err := strconv.ParseBool(value)
- if err != nil {
- testSyntaxError("illegal bool flag value " + value)
- }
- *flag = x
-}
-
-// setIntFlag sets the addressed integer to the value.
-func setIntFlag(flag *int, value string) {
- x, err := strconv.Atoi(value)
- if err != nil {
- testSyntaxError("illegal int flag value " + value)
- }
- *flag = x
-}
-
-func testSyntaxError(msg string) {
- fmt.Fprintf(os.Stderr, "go test: %s\n", msg)
- fmt.Fprintf(os.Stderr, `run "go help test" or "go help testflag" for more information`+"\n")
- os.Exit(2)
-}
diff --git a/libgo/go/cmd/go/vendor_test.go b/libgo/go/cmd/go/vendor_test.go
index deec02e..739ce5a 100644
--- a/libgo/go/cmd/go/vendor_test.go
+++ b/libgo/go/cmd/go/vendor_test.go
@@ -20,18 +20,18 @@ func TestVendorImports(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...")
+ tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...", "vend/vendor/...", "vend/x/vendor/...")
want := `
vend [vend/vendor/p r]
vend/dir1 []
vend/hello [fmt vend/vendor/strings]
vend/subdir [vend/vendor/p r]
+ vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2]
+ vend/x/invalid [vend/x/invalid/vendor/foo]
vend/vendor/p []
vend/vendor/q []
vend/vendor/strings []
vend/vendor/vend/dir1/dir2 []
- vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2]
- vend/x/invalid [vend/x/invalid/vendor/foo]
vend/x/vendor/p []
vend/x/vendor/p/p [notfound]
vend/x/vendor/r []
diff --git a/libgo/go/cmd/go/vet.go b/libgo/go/cmd/go/vet.go
deleted file mode 100644
index 8e296c8..0000000
--- a/libgo/go/cmd/go/vet.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "path/filepath"
-
-func init() {
- addBuildFlags(cmdVet)
-}
-
-var cmdVet = &Command{
- Run: runVet,
- UsageLine: "vet [-n] [-x] [build flags] [packages]",
- Short: "run go tool vet on packages",
- Long: `
-Vet runs the Go vet command on the packages named by the import paths.
-
-For more about vet, see 'go doc cmd/vet'.
-For more about specifying packages, see 'go help packages'.
-
-To run the vet tool with specific options, run 'go tool vet'.
-
-The -n flag prints commands that would be executed.
-The -x flag prints commands as they are executed.
-
-For more about build flags, see 'go help build'.
-
-See also: go fmt, go fix.
- `,
-}
-
-func runVet(cmd *Command, args []string) {
- for _, p := range packages(args) {
- // Vet expects to be given a set of files all from the same package.
- // Run once for package p and once for package p_test.
- if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles) > 0 {
- runVetFiles(p, stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.SFiles))
- }
- if len(p.XTestGoFiles) > 0 {
- runVetFiles(p, stringList(p.XTestGoFiles))
- }
- }
-}
-
-func runVetFiles(p *Package, files []string) {
- for i := range files {
- files[i] = filepath.Join(p.Dir, files[i])
- }
- run(buildToolExec, tool("vet"), relPaths(files))
-}
diff --git a/libgo/go/cmd/gofmt/doc.go b/libgo/go/cmd/gofmt/doc.go
index 8b22f03..e340665 100644
--- a/libgo/go/cmd/gofmt/doc.go
+++ b/libgo/go/cmd/gofmt/doc.go
@@ -4,7 +4,8 @@
/*
Gofmt formats Go programs.
-It uses tabs (width = 8) for indentation and blanks for alignment.
+It uses tabs for indentation and blanks for alignment.
+Alignment assumes that an editor is using a fixed-width font.
Without an explicit path, it processes the standard input. Given a file,
it operates on that file; given a directory, it operates on all .go files in
@@ -100,4 +101,4 @@ package main
// BUG(rsc): The implementation of -r is a bit slow.
// BUG(gri): If -w fails, the restored original file may not have some of the
-// original file attributes.
+// original file attributes.
diff --git a/libgo/go/cmd/gofmt/gofmt.go b/libgo/go/cmd/gofmt/gofmt.go
index e1ef0dd..d5b7be3 100644
--- a/libgo/go/cmd/gofmt/gofmt.go
+++ b/libgo/go/cmd/gofmt/gofmt.go
@@ -139,11 +139,11 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
}
}
if *doDiff {
- data, err := diff(src, res)
+ data, err := diff(src, res, filename)
if err != nil {
return fmt.Errorf("computing diff: %s", err)
}
- fmt.Printf("diff %s gofmt/%s\n", filename, filename)
+ fmt.Printf("diff -u %s %s\n", filepath.ToSlash(filename+".orig"), filepath.ToSlash(filename))
out.Write(data)
}
}
@@ -225,32 +225,76 @@ func gofmtMain() {
}
}
-func diff(b1, b2 []byte) (data []byte, err error) {
- f1, err := ioutil.TempFile("", "gofmt")
+func writeTempFile(dir, prefix string, data []byte) (string, error) {
+ file, err := ioutil.TempFile(dir, prefix)
+ if err != nil {
+ return "", err
+ }
+ _, err = file.Write(data)
+ if err1 := file.Close(); err == nil {
+ err = err1
+ }
+ if err != nil {
+ os.Remove(file.Name())
+ return "", err
+ }
+ return file.Name(), nil
+}
+
+func diff(b1, b2 []byte, filename string) (data []byte, err error) {
+ f1, err := writeTempFile("", "gofmt", b1)
if err != nil {
return
}
- defer os.Remove(f1.Name())
- defer f1.Close()
+ defer os.Remove(f1)
- f2, err := ioutil.TempFile("", "gofmt")
+ f2, err := writeTempFile("", "gofmt", b2)
if err != nil {
return
}
- defer os.Remove(f2.Name())
- defer f2.Close()
+ defer os.Remove(f2)
- f1.Write(b1)
- f2.Write(b2)
+ cmd := "diff"
+ if runtime.GOOS == "plan9" {
+ cmd = "/bin/ape/diff"
+ }
- data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
+ data, err = exec.Command(cmd, "-u", f1, f2).CombinedOutput()
if len(data) > 0 {
// diff exits with a non-zero status when the files don't match.
// Ignore that failure as long as we get output.
- err = nil
+ return replaceTempFilename(data, filename)
}
return
+}
+// replaceTempFilename replaces temporary filenames in diff with actual one.
+//
+// --- /tmp/gofmt316145376 2017-02-03 19:13:00.280468375 -0500
+// +++ /tmp/gofmt617882815 2017-02-03 19:13:00.280468375 -0500
+// ...
+// ->
+// --- path/to/file.go.orig 2017-02-03 19:13:00.280468375 -0500
+// +++ path/to/file.go 2017-02-03 19:13:00.280468375 -0500
+// ...
+func replaceTempFilename(diff []byte, filename string) ([]byte, error) {
+ bs := bytes.SplitN(diff, []byte{'\n'}, 3)
+ if len(bs) < 3 {
+ return nil, fmt.Errorf("got unexpected diff for %s", filename)
+ }
+ // Preserve timestamps.
+ var t0, t1 []byte
+ if i := bytes.LastIndexByte(bs[0], '\t'); i != -1 {
+ t0 = bs[0][i:]
+ }
+ if i := bytes.LastIndexByte(bs[1], '\t'); i != -1 {
+ t1 = bs[1][i:]
+ }
+ // Always print filepath with slash separator.
+ f := filepath.ToSlash(filename)
+ bs[0] = []byte(fmt.Sprintf("--- %s%s", f+".orig", t0))
+ bs[1] = []byte(fmt.Sprintf("+++ %s%s", f, t1))
+ return bytes.Join(bs, []byte{'\n'}), nil
}
const chmodSupported = runtime.GOOS != "windows"
diff --git a/libgo/go/cmd/gofmt/gofmt_test.go b/libgo/go/cmd/gofmt/gofmt_test.go
index b7ca9e8..16b653b 100644
--- a/libgo/go/cmd/gofmt/gofmt_test.go
+++ b/libgo/go/cmd/gofmt/gofmt_test.go
@@ -9,7 +9,9 @@ import (
"flag"
"io/ioutil"
"os"
+ "os/exec"
"path/filepath"
+ "runtime"
"strings"
"testing"
"text/scanner"
@@ -110,7 +112,7 @@ func runTest(t *testing.T, in, out string) {
}
t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in)
- d, err := diff(expected, got)
+ d, err := diff(expected, got, in)
if err == nil {
t.Errorf("%s", d)
}
@@ -184,3 +186,69 @@ func TestBackupFile(t *testing.T) {
}
t.Logf("Created: %s", name)
}
+
+func TestDiff(t *testing.T) {
+ if _, err := exec.LookPath("diff"); err != nil {
+ t.Skipf("skip test on %s: diff command is required", runtime.GOOS)
+ }
+ in := []byte("first\nsecond\n")
+ out := []byte("first\nthird\n")
+ filename := "difftest.txt"
+ b, err := diff(in, out, filename)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if runtime.GOOS == "windows" {
+ b = bytes.Replace(b, []byte{'\r', '\n'}, []byte{'\n'}, -1)
+ }
+
+ bs := bytes.SplitN(b, []byte{'\n'}, 3)
+ line0, line1 := bs[0], bs[1]
+
+ if prefix := "--- difftest.txt.orig"; !bytes.HasPrefix(line0, []byte(prefix)) {
+ t.Errorf("diff: first line should start with `%s`\ngot: %s", prefix, line0)
+ }
+
+ if prefix := "+++ difftest.txt"; !bytes.HasPrefix(line1, []byte(prefix)) {
+ t.Errorf("diff: second line should start with `%s`\ngot: %s", prefix, line1)
+ }
+
+ want := `@@ -1,2 +1,2 @@
+ first
+-second
++third
+`
+
+ if got := string(bs[2]); got != want {
+ t.Errorf("diff: got:\n%s\nwant:\n%s", got, want)
+ }
+}
+
+func TestReplaceTempFilename(t *testing.T) {
+ diff := []byte(`--- /tmp/tmpfile1 2017-02-08 00:53:26.175105619 +0900
++++ /tmp/tmpfile2 2017-02-08 00:53:38.415151275 +0900
+@@ -1,2 +1,2 @@
+ first
+-second
++third
+`)
+ want := []byte(`--- path/to/file.go.orig 2017-02-08 00:53:26.175105619 +0900
++++ path/to/file.go 2017-02-08 00:53:38.415151275 +0900
+@@ -1,2 +1,2 @@
+ first
+-second
++third
+`)
+ // Check path in diff output is always slash regardless of the
+ // os.PathSeparator (`/` or `\`).
+ sep := string(os.PathSeparator)
+ filename := strings.Join([]string{"path", "to", "file.go"}, sep)
+ got, err := replaceTempFilename(diff, filename)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(got, want) {
+ t.Errorf("os.PathSeparator='%s': replacedDiff:\ngot:\n%s\nwant:\n%s", sep, got, want)
+ }
+}
diff --git a/libgo/go/cmd/gofmt/rewrite.go b/libgo/go/cmd/gofmt/rewrite.go
index 550492b..79b7858 100644
--- a/libgo/go/cmd/gofmt/rewrite.go
+++ b/libgo/go/cmd/gofmt/rewrite.go
@@ -66,10 +66,10 @@ func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File {
if !val.IsValid() {
return reflect.Value{}
}
+ val = apply(rewriteVal, val)
for k := range m {
delete(m, k)
}
- val = apply(rewriteVal, val)
if match(m, pat, val) {
val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos()))
}
diff --git a/libgo/go/cmd/internal/browser/browser.go b/libgo/go/cmd/internal/browser/browser.go
index 897086f..6867c85 100644
--- a/libgo/go/cmd/internal/browser/browser.go
+++ b/libgo/go/cmd/internal/browser/browser.go
@@ -9,6 +9,7 @@ import (
"os"
"os/exec"
"runtime"
+ "time"
)
// Commands returns a list of possible commands to use to open a url.
@@ -23,7 +24,10 @@ func Commands() [][]string {
case "windows":
cmds = append(cmds, []string{"cmd", "/c", "start"})
default:
- cmds = append(cmds, []string{"xdg-open"})
+ if os.Getenv("DISPLAY") != "" {
+ // xdg-open is only for use in a desktop environment.
+ cmds = append(cmds, []string{"xdg-open"})
+ }
}
cmds = append(cmds,
[]string{"chrome"},
@@ -38,9 +42,26 @@ func Commands() [][]string {
func Open(url string) bool {
for _, args := range Commands() {
cmd := exec.Command(args[0], append(args[1:], url)...)
- if cmd.Start() == nil {
+ if cmd.Start() == nil && appearsSuccessful(cmd, 3*time.Second) {
return true
}
}
return false
}
+
+// appearsSuccessful reports whether the command appears to have run successfully.
+// If the command runs longer than the timeout, it's deemed successful.
+// If the command runs within the timeout, it's deemed successful if it exited cleanly.
+func appearsSuccessful(cmd *exec.Cmd, timeout time.Duration) bool {
+ errc := make(chan error, 1)
+ go func() {
+ errc <- cmd.Wait()
+ }()
+
+ select {
+ case <-time.After(timeout):
+ return true
+ case err := <-errc:
+ return err == nil
+ }
+}
diff --git a/libgo/go/cmd/internal/objabi/autotype.go b/libgo/go/cmd/internal/objabi/autotype.go
new file mode 100644
index 0000000..17c4293
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/autotype.go
@@ -0,0 +1,37 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package objabi
+
+// Auto.name
+const (
+ A_AUTO = 1 + iota
+ A_PARAM
+)
diff --git a/libgo/go/cmd/internal/objabi/doc.go b/libgo/go/cmd/internal/objabi/doc.go
new file mode 100644
index 0000000..7bd5ff6
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/doc.go
@@ -0,0 +1,120 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// NOTE: There are *three* independent implementations of this object
+// file format in the Go source tree:
+//
+// - cmd/internal/goobj/read.go (used by cmd/addr2line, cmd/nm, cmd/objdump, cmd/pprof)
+// - cmd/internal/obj/objfile.go (used by cmd/asm and cmd/compile)
+// - cmd/link/internal/objfile.go (used by cmd/link)
+//
+// When changing the object file format, remember to change all three.
+
+// Originally, Go object files were Plan 9 object files, but no longer.
+// Now they are more like standard object files, in that each symbol is defined
+// by an associated memory image (bytes) and a list of relocations to apply
+// during linking. We do not (yet?) use a standard file format, however.
+// For now, the format is chosen to be as simple as possible to read and write.
+// It may change for reasons of efficiency, or we may even switch to a
+// standard file format if there are compelling benefits to doing so.
+// See golang.org/s/go13linker for more background.
+//
+// The file format is:
+//
+// - magic header: "\x00\x00go19ld"
+// - byte 1 - version number
+// - sequence of strings giving dependencies (imported packages)
+// - empty string (marks end of sequence)
+// - sequence of symbol references used by the defined symbols
+// - byte 0xff (marks end of sequence)
+// - sequence of integer lengths:
+// - total data length
+// - total number of relocations
+// - total number of pcdata
+// - total number of automatics
+// - total number of funcdata
+// - total number of files
+// - data, the content of the defined symbols
+// - sequence of defined symbols
+// - byte 0xff (marks end of sequence)
+// - magic footer: "\xff\xffgo19ld"
+//
+// All integers are stored in a zigzag varint format.
+// See golang.org/s/go12symtab for a definition.
+//
+// Data blocks and strings are both stored as an integer
+// followed by that many bytes.
+//
+// A symbol reference is a string name followed by a version.
+//
+// A symbol points to other symbols using an index into the symbol
+// reference sequence. Index 0 corresponds to a nil symbol pointer.
+// In the symbol layout described below "symref index" stands for this
+// index.
+//
+// Each symbol is laid out as the following fields:
+//
+// - byte 0xfe (sanity check for synchronization)
+// - type [byte]
+// - name & version [symref index]
+// - flags [int]
+// 1<<0 dupok
+// 1<<1 local
+// 1<<2 add to typelink table
+// - size [int]
+// - gotype [symref index]
+// - p [data block]
+// - nr [int]
+// - r [nr relocations, sorted by off]
+//
+// If type == STEXT, there are a few more fields:
+//
+// - args [int]
+// - locals [int]
+// - nosplit [int]
+// - flags [int]
+// 1<<0 leaf
+// 1<<1 C function
+// 1<<2 function may call reflect.Type.Method
+// 1<<3 function compiled with -shared
+// - nlocal [int]
+// - local [nlocal automatics]
+// - pcln [pcln table]
+//
+// Each relocation has the encoding:
+//
+// - off [int]
+// - siz [int]
+// - type [int]
+// - add [int]
+// - sym [symref index]
+//
+// Each local has the encoding:
+//
+// - asym [symref index]
+// - offset [int]
+// - type [int]
+// - gotype [symref index]
+//
+// The pcln table has the encoding:
+//
+// - pcsp [data block]
+// - pcfile [data block]
+// - pcline [data block]
+// - pcinline [data block]
+// - npcdata [int]
+// - pcdata [npcdata data blocks]
+// - nfuncdata [int]
+// - funcdata [nfuncdata symref index]
+// - funcdatasym [nfuncdata ints]
+// - nfile [int]
+// - file [nfile symref index]
+// - ninlinedcall [int]
+// - inlinedcall [ninlinedcall int symref int symref]
+//
+// The file layout and meaning of type integers are architecture-independent.
+//
+// TODO(rsc): The file format is good for a first pass but needs work.
+// - There are SymID in the object file that should really just be strings.
+package objabi
diff --git a/libgo/go/cmd/internal/objabi/flag.go b/libgo/go/cmd/internal/objabi/flag.go
new file mode 100644
index 0000000..e349b41
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/flag.go
@@ -0,0 +1,115 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package objabi
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strconv"
+)
+
+func Flagfn2(string, string, func(string, string)) { panic("flag") }
+
+func Flagcount(name, usage string, val *int) {
+ flag.Var((*count)(val), name, usage)
+}
+
+func Flagint32(name, usage string, val *int32) {
+ flag.Var((*int32Value)(val), name, usage)
+}
+
+func Flagint64(name, usage string, val *int64) {
+ flag.Int64Var(val, name, *val, usage)
+}
+
+func Flagstr(name, usage string, val *string) {
+ flag.StringVar(val, name, *val, usage)
+}
+
+func Flagfn0(name, usage string, f func()) {
+ flag.Var(fn0(f), name, usage)
+}
+
+func Flagfn1(name, usage string, f func(string)) {
+ flag.Var(fn1(f), name, usage)
+}
+
+func Flagprint(fd int) {
+ if fd == 1 {
+ flag.CommandLine.SetOutput(os.Stdout)
+ }
+ flag.PrintDefaults()
+}
+
+func Flagparse(usage func()) {
+ flag.Usage = usage
+ flag.Parse()
+}
+
+// count is a flag.Value that is like a flag.Bool and a flag.Int.
+// If used as -name, it increments the count, but -name=x sets the count.
+// Used for verbose flag -v.
+type count int
+
+func (c *count) String() string {
+ return fmt.Sprint(int(*c))
+}
+
+func (c *count) Set(s string) error {
+ switch s {
+ case "true":
+ *c++
+ case "false":
+ *c = 0
+ default:
+ n, err := strconv.Atoi(s)
+ if err != nil {
+ return fmt.Errorf("invalid count %q", s)
+ }
+ *c = count(n)
+ }
+ return nil
+}
+
+func (c *count) IsBoolFlag() bool {
+ return true
+}
+
+type int32Value int32
+
+func (i *int32Value) Set(s string) error {
+ v, err := strconv.ParseInt(s, 0, 64)
+ *i = int32Value(v)
+ return err
+}
+
+func (i *int32Value) Get() interface{} { return int32(*i) }
+
+func (i *int32Value) String() string { return fmt.Sprint(*i) }
+
+type fn0 func()
+
+func (f fn0) Set(s string) error {
+ f()
+ return nil
+}
+
+func (f fn0) Get() interface{} { return nil }
+
+func (f fn0) String() string { return "" }
+
+func (f fn0) IsBoolFlag() bool {
+ return true
+}
+
+type fn1 func(string)
+
+func (f fn1) Set(s string) error {
+ f(s)
+ return nil
+}
+
+func (f fn1) String() string { return "" }
diff --git a/libgo/go/cmd/internal/objabi/funcdata.go b/libgo/go/cmd/internal/objabi/funcdata.go
new file mode 100644
index 0000000..80874ed
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/funcdata.go
@@ -0,0 +1,25 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package objabi
+
+// This file defines the IDs for PCDATA and FUNCDATA instructions
+// in Go binaries.
+//
+// These must agree with ../../../runtime/funcdata.h and
+// ../../../runtime/symtab.go.
+
+const (
+ PCDATA_StackMapIndex = 0
+ PCDATA_InlTreeIndex = 1
+ FUNCDATA_ArgsPointerMaps = 0
+ FUNCDATA_LocalsPointerMaps = 1
+ FUNCDATA_InlTree = 2
+
+ // ArgsSizeUnknown is set in Func.argsize to mark all functions
+ // whose argument size is unknown (C vararg functions, and
+ // assembly code without an explicit specification).
+ // This value is generated by the compiler, assembler, or linker.
+ ArgsSizeUnknown = -0x80000000
+)
diff --git a/libgo/go/cmd/internal/objabi/head.go b/libgo/go/cmd/internal/objabi/head.go
new file mode 100644
index 0000000..ff19606
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/head.go
@@ -0,0 +1,104 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package objabi
+
+import "fmt"
+
+// HeadType is the executable header type.
+type HeadType uint8
+
+const (
+ Hunknown HeadType = iota
+ Hdarwin
+ Hdragonfly
+ Hfreebsd
+ Hlinux
+ Hnacl
+ Hnetbsd
+ Hopenbsd
+ Hplan9
+ Hsolaris
+ Hwindows
+)
+
+func (h *HeadType) Set(s string) error {
+ switch s {
+ case "darwin":
+ *h = Hdarwin
+ case "dragonfly":
+ *h = Hdragonfly
+ case "freebsd":
+ *h = Hfreebsd
+ case "linux", "android":
+ *h = Hlinux
+ case "nacl":
+ *h = Hnacl
+ case "netbsd":
+ *h = Hnetbsd
+ case "openbsd":
+ *h = Hopenbsd
+ case "plan9":
+ *h = Hplan9
+ case "solaris":
+ *h = Hsolaris
+ case "windows":
+ *h = Hwindows
+ default:
+ return fmt.Errorf("invalid headtype: %q", s)
+ }
+ return nil
+}
+
+func (h *HeadType) String() string {
+ switch *h {
+ case Hdarwin:
+ return "darwin"
+ case Hdragonfly:
+ return "dragonfly"
+ case Hfreebsd:
+ return "freebsd"
+ case Hlinux:
+ return "linux"
+ case Hnacl:
+ return "nacl"
+ case Hnetbsd:
+ return "netbsd"
+ case Hopenbsd:
+ return "openbsd"
+ case Hplan9:
+ return "plan9"
+ case Hsolaris:
+ return "solaris"
+ case Hwindows:
+ return "windows"
+ }
+ return fmt.Sprintf("HeadType(%d)", *h)
+}
diff --git a/libgo/go/cmd/internal/objabi/line.go b/libgo/go/cmd/internal/objabi/line.go
new file mode 100644
index 0000000..ed509b7
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/line.go
@@ -0,0 +1,82 @@
+// Copyright 2009 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 objabi
+
+import (
+ "os"
+ "path/filepath"
+)
+
+// WorkingDir returns the current working directory
+// (or "/???" if the directory cannot be identified),
+// with "/" as separator.
+func WorkingDir() string {
+ var path string
+ path, _ = os.Getwd()
+ if path == "" {
+ path = "/???"
+ }
+ return filepath.ToSlash(path)
+}
+
+// AbsFile returns the absolute filename for file in the given directory.
+// It also removes a leading pathPrefix, or else rewrites a leading $GOROOT
+// prefix to the literal "$GOROOT".
+// If the resulting path is the empty string, the result is "??".
+func AbsFile(dir, file, pathPrefix string) string {
+ abs := file
+ if dir != "" && !filepath.IsAbs(file) {
+ abs = filepath.Join(dir, file)
+ }
+
+ if pathPrefix != "" && hasPathPrefix(abs, pathPrefix) {
+ if abs == pathPrefix {
+ abs = ""
+ } else {
+ abs = abs[len(pathPrefix)+1:]
+ }
+ } else if hasPathPrefix(abs, GOROOT) {
+ abs = "$GOROOT" + abs[len(GOROOT):]
+ }
+ if abs == "" {
+ abs = "??"
+ }
+
+ return filepath.Clean(abs)
+}
+
+// Does s have t as a path prefix?
+// That is, does s == t or does s begin with t followed by a slash?
+// For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true.
+// Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true.
+// We do not allow full Unicode case folding, for fear of causing more confusion
+// or harm than good. (For an example of the kinds of things that can go wrong,
+// see http://article.gmane.org/gmane.linux.kernel/1853266.)
+func hasPathPrefix(s string, t string) bool {
+ if len(t) > len(s) {
+ return false
+ }
+ var i int
+ for i = 0; i < len(t); i++ {
+ cs := int(s[i])
+ ct := int(t[i])
+ if 'A' <= cs && cs <= 'Z' {
+ cs += 'a' - 'A'
+ }
+ if 'A' <= ct && ct <= 'Z' {
+ ct += 'a' - 'A'
+ }
+ if cs == '\\' {
+ cs = '/'
+ }
+ if ct == '\\' {
+ ct = '/'
+ }
+ if cs != ct {
+ return false
+ }
+ }
+ return i >= len(s) || s[i] == '/' || s[i] == '\\'
+}
diff --git a/libgo/go/cmd/internal/objabi/path.go b/libgo/go/cmd/internal/objabi/path.go
new file mode 100644
index 0000000..2a42179
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/path.go
@@ -0,0 +1,41 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package objabi
+
+import "strings"
+
+// PathToPrefix converts raw string to the prefix that will be used in the
+// symbol table. All control characters, space, '%' and '"', as well as
+// non-7-bit clean bytes turn into %xx. The period needs escaping only in the
+// last segment of the path, and it makes for happier users if we escape that as
+// little as possible.
+func PathToPrefix(s string) string {
+ slash := strings.LastIndex(s, "/")
+ // check for chars that need escaping
+ n := 0
+ for r := 0; r < len(s); r++ {
+ if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
+ n++
+ }
+ }
+
+ // quick exit
+ if n == 0 {
+ return s
+ }
+
+ // escape
+ const hex = "0123456789abcdef"
+ p := make([]byte, 0, len(s)+2*n)
+ for r := 0; r < len(s); r++ {
+ if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
+ p = append(p, '%', hex[c>>4], hex[c&0xF])
+ } else {
+ p = append(p, c)
+ }
+ }
+
+ return string(p)
+}
diff --git a/libgo/go/cmd/internal/objabi/path_test.go b/libgo/go/cmd/internal/objabi/path_test.go
new file mode 100644
index 0000000..05d7fb4
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/path_test.go
@@ -0,0 +1,33 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package objabi
+
+import "testing"
+
+func TestPathToPrefix(t *testing.T) {
+ tests := []struct {
+ Path string
+ Expected string
+ }{{"foo/bar/v1", "foo/bar/v1"},
+ {"foo/bar/v.1", "foo/bar/v%2e1"},
+ {"f.o.o/b.a.r/v1", "f.o.o/b.a.r/v1"},
+ {"f.o.o/b.a.r/v.1", "f.o.o/b.a.r/v%2e1"},
+ {"f.o.o/b.a.r/v..1", "f.o.o/b.a.r/v%2e%2e1"},
+ {"f.o.o/b.a.r/v..1.", "f.o.o/b.a.r/v%2e%2e1%2e"},
+ {"f.o.o/b.a.r/v%1", "f.o.o/b.a.r/v%251"},
+ {"runtime", "runtime"},
+ {"sync/atomic", "sync/atomic"},
+ {"golang.org/x/tools/godoc", "golang.org/x/tools/godoc"},
+ {"foo.bar/baz.quux", "foo.bar/baz%2equux"},
+ {"", ""},
+ {"%foo%bar", "%25foo%25bar"},
+ {"\x01\x00\x7Fâº", "%01%00%7f%e2%98%ba"},
+ }
+ for _, tc := range tests {
+ if got := PathToPrefix(tc.Path); got != tc.Expected {
+ t.Errorf("expected PathToPrefix(%s) = %s, got %s", tc.Path, tc.Expected, got)
+ }
+ }
+}
diff --git a/libgo/go/cmd/internal/objabi/reloctype.go b/libgo/go/cmd/internal/objabi/reloctype.go
new file mode 100644
index 0000000..179f049
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/reloctype.go
@@ -0,0 +1,200 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package objabi
+
+type RelocType int32
+
+//go:generate stringer -type=RelocType
+const (
+ R_ADDR RelocType = 1 + iota
+ // R_ADDRPOWER relocates a pair of "D-form" instructions (instructions with 16-bit
+ // immediates in the low half of the instruction word), usually addis followed by
+ // another add or a load, inserting the "high adjusted" 16 bits of the address of
+ // the referenced symbol into the immediate field of the first instruction and the
+ // low 16 bits into that of the second instruction.
+ R_ADDRPOWER
+ // R_ADDRARM64 relocates an adrp, add pair to compute the address of the
+ // referenced symbol.
+ R_ADDRARM64
+ // R_ADDRMIPS (only used on mips/mips64) resolves to the low 16 bits of an external
+ // address, by encoding it into the instruction.
+ R_ADDRMIPS
+ // R_ADDROFF resolves to a 32-bit offset from the beginning of the section
+ // holding the data being relocated to the referenced symbol.
+ R_ADDROFF
+ // R_WEAKADDROFF resolves just like R_ADDROFF but is a weak relocation.
+ // A weak relocation does not make the symbol it refers to reachable,
+ // and is only honored by the linker if the symbol is in some other way
+ // reachable.
+ R_WEAKADDROFF
+ R_SIZE
+ R_CALL
+ R_CALLARM
+ R_CALLARM64
+ R_CALLIND
+ R_CALLPOWER
+ // R_CALLMIPS (only used on mips64) resolves to non-PC-relative target address
+ // of a CALL (JAL) instruction, by encoding the address into the instruction.
+ R_CALLMIPS
+ R_CONST
+ R_PCREL
+ // R_TLS_LE, used on 386, amd64, and ARM, resolves to the offset of the
+ // thread-local symbol from the thread local base and is used to implement the
+ // "local exec" model for tls access (r.Sym is not set on intel platforms but is
+ // set to a TLS symbol -- runtime.tlsg -- in the linker when externally linking).
+ R_TLS_LE
+ // R_TLS_IE, used 386, amd64, and ARM resolves to the PC-relative offset to a GOT
+ // slot containing the offset from the thread-local symbol from the thread local
+ // base and is used to implemented the "initial exec" model for tls access (r.Sym
+ // is not set on intel platforms but is set to a TLS symbol -- runtime.tlsg -- in
+ // the linker when externally linking).
+ R_TLS_IE
+ R_GOTOFF
+ R_PLT0
+ R_PLT1
+ R_PLT2
+ R_USEFIELD
+ // R_USETYPE resolves to an *rtype, but no relocation is created. The
+ // linker uses this as a signal that the pointed-to type information
+ // should be linked into the final binary, even if there are no other
+ // direct references. (This is used for types reachable by reflection.)
+ R_USETYPE
+ // R_METHODOFF resolves to a 32-bit offset from the beginning of the section
+ // holding the data being relocated to the referenced symbol.
+ // It is a variant of R_ADDROFF used when linking from the uncommonType of a
+ // *rtype, and may be set to zero by the linker if it determines the method
+ // text is unreachable by the linked program.
+ R_METHODOFF
+ R_POWER_TOC
+ R_GOTPCREL
+ // R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address
+ // of a JMP instruction, by encoding the address into the instruction.
+ // The stack nosplit check ignores this since it is not a function call.
+ R_JMPMIPS
+ // R_DWARFREF resolves to the offset of the symbol from its section.
+ R_DWARFREF
+
+ // Platform dependent relocations. Architectures with fixed width instructions
+ // have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be
+ // stuffed into a 32-bit instruction, so an address needs to be spread across
+ // several instructions, and in turn this requires a sequence of relocations, each
+ // updating a part of an instruction. This leads to relocation codes that are
+ // inherently processor specific.
+
+ // Arm64.
+
+ // Set a MOV[NZ] immediate field to bits [15:0] of the offset from the thread
+ // local base to the thread local variable defined by the referenced (thread
+ // local) symbol. Error if the offset does not fit into 16 bits.
+ R_ARM64_TLS_LE
+
+ // Relocates an ADRP; LD64 instruction sequence to load the offset between
+ // the thread local base and the thread local variable defined by the
+ // referenced (thread local) symbol from the GOT.
+ R_ARM64_TLS_IE
+
+ // R_ARM64_GOTPCREL relocates an adrp, ld64 pair to compute the address of the GOT
+ // slot of the referenced symbol.
+ R_ARM64_GOTPCREL
+
+ // PPC64.
+
+ // R_POWER_TLS_LE is used to implement the "local exec" model for tls
+ // access. It resolves to the offset of the thread-local symbol from the
+ // thread pointer (R13) and inserts this value into the low 16 bits of an
+ // instruction word.
+ R_POWER_TLS_LE
+
+ // R_POWER_TLS_IE is used to implement the "initial exec" model for tls access. It
+ // relocates a D-form, DS-form instruction sequence like R_ADDRPOWER_DS. It
+ // inserts to the offset of GOT slot for the thread-local symbol from the TOC (the
+ // GOT slot is filled by the dynamic linker with the offset of the thread-local
+ // symbol from the thread pointer (R13)).
+ R_POWER_TLS_IE
+
+ // R_POWER_TLS marks an X-form instruction such as "MOVD 0(R13)(R31*1), g" as
+ // accessing a particular thread-local symbol. It does not affect code generation
+ // but is used by the system linker when relaxing "initial exec" model code to
+ // "local exec" model code.
+ R_POWER_TLS
+
+ // R_ADDRPOWER_DS is similar to R_ADDRPOWER above, but assumes the second
+ // instruction is a "DS-form" instruction, which has an immediate field occupying
+ // bits [15:2] of the instruction word. Bits [15:2] of the address of the
+ // relocated symbol are inserted into this field; it is an error if the last two
+ // bits of the address are not 0.
+ R_ADDRPOWER_DS
+
+ // R_ADDRPOWER_PCREL relocates a D-form, DS-form instruction sequence like
+ // R_ADDRPOWER_DS but inserts the offset of the GOT slot for the referenced symbol
+ // from the TOC rather than the symbol's address.
+ R_ADDRPOWER_GOT
+
+ // R_ADDRPOWER_PCREL relocates two D-form instructions like R_ADDRPOWER, but
+ // inserts the displacement from the place being relocated to the address of the
+ // the relocated symbol instead of just its address.
+ R_ADDRPOWER_PCREL
+
+ // R_ADDRPOWER_TOCREL relocates two D-form instructions like R_ADDRPOWER, but
+ // inserts the offset from the TOC to the address of the relocated symbol
+ // rather than the symbol's address.
+ R_ADDRPOWER_TOCREL
+
+ // R_ADDRPOWER_TOCREL relocates a D-form, DS-form instruction sequence like
+ // R_ADDRPOWER_DS but inserts the offset from the TOC to the address of the the
+ // relocated symbol rather than the symbol's address.
+ R_ADDRPOWER_TOCREL_DS
+
+ // R_PCRELDBL relocates s390x 2-byte aligned PC-relative addresses.
+ // TODO(mundaym): remove once variants can be serialized - see issue 14218.
+ R_PCRELDBL
+
+ // R_ADDRMIPSU (only used on mips/mips64) resolves to the sign-adjusted "upper" 16
+ // bits (bit 16-31) of an external address, by encoding it into the instruction.
+ R_ADDRMIPSU
+ // R_ADDRMIPSTLS (only used on mips64) resolves to the low 16 bits of a TLS
+ // address (offset from thread pointer), by encoding it into the instruction.
+ R_ADDRMIPSTLS
+)
+
+// IsDirectJump returns whether r is a relocation for a direct jump.
+// A direct jump is a CALL or JMP instruction that takes the target address
+// as immediate. The address is embedded into the instruction, possibly
+// with limited width.
+// An indirect jump is a CALL or JMP instruction that takes the target address
+// in register or memory.
+func (r RelocType) IsDirectJump() bool {
+ switch r {
+ case R_CALL, R_CALLARM, R_CALLARM64, R_CALLPOWER, R_CALLMIPS, R_JMPMIPS:
+ return true
+ }
+ return false
+}
diff --git a/libgo/go/cmd/internal/objabi/reloctype_string.go b/libgo/go/cmd/internal/objabi/reloctype_string.go
new file mode 100644
index 0000000..182d03f
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/reloctype_string.go
@@ -0,0 +1,17 @@
+// Code generated by "stringer -type=RelocType"; DO NOT EDIT.
+
+package objabi
+
+import "fmt"
+
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLS"
+
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 129, 136, 144, 152, 160, 166, 172, 178, 188, 197, 208, 219, 229, 238, 248, 262, 276, 292, 306, 320, 331, 345, 360, 377, 395, 416, 426, 437, 450}
+
+func (i RelocType) String() string {
+ i -= 1
+ if i < 0 || i >= RelocType(len(_RelocType_index)-1) {
+ return fmt.Sprintf("RelocType(%d)", i+1)
+ }
+ return _RelocType_name[_RelocType_index[i]:_RelocType_index[i+1]]
+}
diff --git a/libgo/go/cmd/internal/objabi/stack.go b/libgo/go/cmd/internal/objabi/stack.go
new file mode 100644
index 0000000..1143393
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/stack.go
@@ -0,0 +1,20 @@
+// Copyright 2011 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 objabi
+
+// For the linkers. Must match Go definitions.
+
+const (
+ STACKSYSTEM = 0
+ StackSystem = STACKSYSTEM
+ StackBig = 4096
+ StackGuard = 880*stackGuardMultiplier + StackSystem
+ StackSmall = 128
+ StackLimit = StackGuard - StackSystem - StackSmall
+)
+
+const (
+ StackPreempt = -1314 // 0xfff...fade
+)
diff --git a/libgo/go/cmd/internal/objabi/symkind.go b/libgo/go/cmd/internal/objabi/symkind.go
new file mode 100644
index 0000000..b037e9e
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/symkind.go
@@ -0,0 +1,60 @@
+// Derived from Inferno utils/6l/l.h and related files.
+// https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
+//
+// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
+// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
+// Portions Copyright © 1997-1999 Vita Nuova Limited
+// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+// Portions Copyright © 2004,2006 Bruce Ellis
+// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
+// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+// Portions Copyright © 2009 The Go Authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package objabi
+
+// A SymKind describes the kind of memory represented by a symbol.
+type SymKind uint8
+
+// Defined SymKind values.
+//
+// TODO(rsc): Give idiomatic Go names.
+//go:generate stringer -type=SymKind
+const (
+ // An otherwise invalid zero value for the type
+ Sxxx SymKind = iota
+ // Executable instructions
+ STEXT
+ // Read only static data
+ SRODATA
+ // Static data that does not contain any pointers
+ SNOPTRDATA
+ // Static data
+ SDATA
+ // Statically data that is initially all 0s
+ SBSS
+ // Statically data that is initially all 0s and does not contain pointers
+ SNOPTRBSS
+ // Thread-local data that is initally all 0s
+ STLSBSS
+ // Debugging data
+ SDWARFINFO
+ SDWARFRANGE
+)
diff --git a/libgo/go/cmd/internal/objabi/symkind_string.go b/libgo/go/cmd/internal/objabi/symkind_string.go
new file mode 100644
index 0000000..5123dc7
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/symkind_string.go
@@ -0,0 +1,16 @@
+// Code generated by "stringer -type=SymKind"; DO NOT EDIT.
+
+package objabi
+
+import "fmt"
+
+const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGE"
+
+var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72}
+
+func (i SymKind) String() string {
+ if i >= SymKind(len(_SymKind_index)-1) {
+ return fmt.Sprintf("SymKind(%d)", i)
+ }
+ return _SymKind_name[_SymKind_index[i]:_SymKind_index[i+1]]
+}
diff --git a/libgo/go/cmd/internal/objabi/typekind.go b/libgo/go/cmd/internal/objabi/typekind.go
new file mode 100644
index 0000000..f0e6f47
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/typekind.go
@@ -0,0 +1,41 @@
+// Copyright 2012 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 objabi
+
+// Must match runtime and reflect.
+// Included by cmd/gc.
+
+const (
+ KindBool = 1 + iota
+ KindInt
+ KindInt8
+ KindInt16
+ KindInt32
+ KindInt64
+ KindUint
+ KindUint8
+ KindUint16
+ KindUint32
+ KindUint64
+ KindUintptr
+ KindFloat32
+ KindFloat64
+ KindComplex64
+ KindComplex128
+ KindArray
+ KindChan
+ KindFunc
+ KindInterface
+ KindMap
+ KindPtr
+ KindSlice
+ KindString
+ KindStruct
+ KindUnsafePointer
+ KindDirectIface = 1 << 5
+ KindGCProg = 1 << 6
+ KindNoPointers = 1 << 7
+ KindMask = (1 << 5) - 1
+)
diff --git a/libgo/go/cmd/internal/objabi/util.go b/libgo/go/cmd/internal/objabi/util.go
new file mode 100644
index 0000000..1da0502
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/util.go
@@ -0,0 +1,119 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package objabi
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "strings"
+)
+
+func envOr(key, value string) string {
+ if x := os.Getenv(key); x != "" {
+ return x
+ }
+ return value
+}
+
+var (
+ GOROOT = envOr("GOROOT", defaultGOROOT)
+ GOARCH = envOr("GOARCH", defaultGOARCH)
+ GOOS = envOr("GOOS", defaultGOOS)
+ GO386 = envOr("GO386", defaultGO386)
+ GOARM = goarm()
+ Version = version
+)
+
+func goarm() int {
+ switch v := envOr("GOARM", defaultGOARM); v {
+ case "5":
+ return 5
+ case "6":
+ return 6
+ case "7":
+ return 7
+ }
+ // Fail here, rather than validate at multiple call sites.
+ log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.")
+ panic("unreachable")
+}
+
+func Getgoextlinkenabled() string {
+ return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED)
+}
+
+func init() {
+ for _, f := range strings.Split(goexperiment, ",") {
+ if f != "" {
+ addexp(f)
+ }
+ }
+}
+
+func Framepointer_enabled(goos, goarch string) bool {
+ return framepointer_enabled != 0 && goarch == "amd64" && goos != "nacl"
+}
+
+func addexp(s string) {
+ // Could do general integer parsing here, but the runtime copy doesn't yet.
+ v := 1
+ name := s
+ if len(name) > 2 && name[:2] == "no" {
+ v = 0
+ name = name[2:]
+ }
+ for i := 0; i < len(exper); i++ {
+ if exper[i].name == name {
+ if exper[i].val != nil {
+ *exper[i].val = v
+ }
+ return
+ }
+ }
+
+ fmt.Printf("unknown experiment %s\n", s)
+ os.Exit(2)
+}
+
+var (
+ framepointer_enabled int = 1
+ Fieldtrack_enabled int
+ Preemptibleloops_enabled int
+ Clobberdead_enabled int
+)
+
+// Toolchain experiments.
+// These are controlled by the GOEXPERIMENT environment
+// variable recorded when the toolchain is built.
+// This list is also known to cmd/gc.
+var exper = []struct {
+ name string
+ val *int
+}{
+ {"fieldtrack", &Fieldtrack_enabled},
+ {"framepointer", &framepointer_enabled},
+ {"preemptibleloops", &Preemptibleloops_enabled},
+ {"clobberdead", &Clobberdead_enabled},
+}
+
+var defaultExpstring = Expstring()
+
+func DefaultExpstring() string {
+ return defaultExpstring
+}
+
+func Expstring() string {
+ buf := "X"
+ for i := range exper {
+ if *exper[i].val != 0 {
+ buf += "," + exper[i].name
+ }
+ }
+ if buf == "X" {
+ buf += ",none"
+ }
+ return "X:" + buf[2:]
+}
diff --git a/libgo/go/cmd/internal/objabi/zbootstrap.go b/libgo/go/cmd/internal/objabi/zbootstrap.go
new file mode 100644
index 0000000..56450fa
--- /dev/null
+++ b/libgo/go/cmd/internal/objabi/zbootstrap.go
@@ -0,0 +1,15 @@
+// auto generated by go tool dist
+
+package objabi
+
+import "runtime"
+
+const defaultGOROOT = `/home/iant/go1.9`
+const defaultGO386 = `sse2`
+const defaultGOARM = `5`
+const defaultGOOS = runtime.GOOS
+const defaultGOARCH = runtime.GOARCH
+const defaultGO_EXTLINK_ENABLED = ``
+const version = `go1.9rc2`
+const stackGuardMultiplier = 1
+const goexperiment = ``
diff --git a/libgo/go/compress/bzip2/bzip2_test.go b/libgo/go/compress/bzip2/bzip2_test.go
index 95fb1895..a6c3080 100644
--- a/libgo/go/compress/bzip2/bzip2_test.go
+++ b/libgo/go/compress/bzip2/bzip2_test.go
@@ -204,6 +204,12 @@ func TestMTF(t *testing.T) {
}
}
+var (
+ digits = mustLoadFile("testdata/e.txt.bz2")
+ twain = mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.bz2")
+ random = mustLoadFile("testdata/random.data.bz2")
+)
+
func benchmarkDecode(b *testing.B, compressed []byte) {
// Determine the uncompressed size of testfile.
uncompressedSize, err := io.Copy(ioutil.Discard, NewReader(bytes.NewReader(compressed)))
@@ -221,18 +227,6 @@ func benchmarkDecode(b *testing.B, compressed []byte) {
}
}
-func BenchmarkDecodeDigits(b *testing.B) {
- digits := mustLoadFile("testdata/e.txt.bz2")
- b.ResetTimer()
- benchmarkDecode(b, digits)
-}
-func BenchmarkDecodeTwain(b *testing.B) {
- twain := mustLoadFile("testdata/Mark.Twain-Tom.Sawyer.txt.bz2")
- b.ResetTimer()
- benchmarkDecode(b, twain)
-}
-func BenchmarkDecodeRand(b *testing.B) {
- random := mustLoadFile("testdata/random.data.bz2")
- b.ResetTimer()
- benchmarkDecode(b, random)
-}
+func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
+func BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) }
+func BenchmarkDecodeRand(b *testing.B) { benchmarkDecode(b, random) }
diff --git a/libgo/go/compress/bzip2/huffman.go b/libgo/go/compress/bzip2/huffman.go
index 9d574b9..dbba9a5 100644
--- a/libgo/go/compress/bzip2/huffman.go
+++ b/libgo/go/compress/bzip2/huffman.go
@@ -108,10 +108,6 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) {
codes := huffmanCodes(make([]huffmanCode, len(lengths)))
for i := len(pairs) - 1; i >= 0; i-- {
if length > pairs[i].length {
- // If the code length decreases we shift in order to
- // zero any bits beyond the end of the code.
- length >>= 32 - pairs[i].length
- length <<= 32 - pairs[i].length
length = pairs[i].length
}
codes[i].code = code
diff --git a/libgo/go/compress/flate/huffman_code.go b/libgo/go/compress/flate/huffman_code.go
index bdcbd82..891537e 100644
--- a/libgo/go/compress/flate/huffman_code.go
+++ b/libgo/go/compress/flate/huffman_code.go
@@ -6,6 +6,7 @@ package flate
import (
"math"
+ "math/bits"
"sort"
)
@@ -342,3 +343,7 @@ func (s byFreq) Less(i, j int) bool {
}
func (s byFreq) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+func reverseBits(number uint16, bitLength byte) uint16 {
+ return bits.Reverse16(number << (16 - bitLength))
+}
diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go
index 9a8c4fc..faa33cc 100644
--- a/libgo/go/compress/flate/inflate.go
+++ b/libgo/go/compress/flate/inflate.go
@@ -10,6 +10,7 @@ package flate
import (
"bufio"
"io"
+ mathbits "math/bits"
"strconv"
"sync"
)
@@ -176,7 +177,7 @@ func (h *huffmanDecoder) init(bits []int) bool {
link := nextcode[huffmanChunkBits+1] >> 1
h.links = make([][]uint32, huffmanNumChunks-link)
for j := uint(link); j < huffmanNumChunks; j++ {
- reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8
+ reverse := int(mathbits.Reverse16(uint16(j)))
reverse >>= uint(16 - huffmanChunkBits)
off := j - uint(link)
if sanity && h.chunks[reverse] != 0 {
@@ -194,7 +195,7 @@ func (h *huffmanDecoder) init(bits []int) bool {
code := nextcode[n]
nextcode[n]++
chunk := uint32(i<>8]) | int(reverseByte[code&0xff])<<8
+ reverse := int(mathbits.Reverse16(uint16(code)))
reverse >>= uint(16 - n)
if n <= huffmanChunkBits {
for off := reverse; off < len(h.chunks); off += 1 << uint(n) {
@@ -556,7 +557,7 @@ readLiteral:
return
}
}
- dist = int(reverseByte[(f.b&0x1F)<<3])
+ dist = int(mathbits.Reverse8(uint8(f.b & 0x1F << 3)))
f.b >>= 5
f.nb -= 5
} else {
diff --git a/libgo/go/compress/flate/reverse_bits.go b/libgo/go/compress/flate/reverse_bits.go
deleted file mode 100644
index 6b22290..0000000
--- a/libgo/go/compress/flate/reverse_bits.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2009 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 flate
-
-var reverseByte = [256]byte{
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
- 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
- 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
- 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
- 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
- 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
- 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
- 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
- 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
- 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
- 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
- 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
- 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
- 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
- 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
- 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
- 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-}
-
-func reverseUint16(v uint16) uint16 {
- return uint16(reverseByte[v>>8]) | uint16(reverseByte[v&0xFF])<<8
-}
-
-func reverseBits(number uint16, bitLength byte) uint16 {
- return reverseUint16(number << (16 - bitLength))
-}
diff --git a/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go
index aafb442..0cc44c5 100644
--- a/libgo/go/compress/gzip/gzip.go
+++ b/libgo/go/compress/gzip/gzip.go
@@ -222,8 +222,9 @@ func (z *Writer) Flush() error {
return z.err
}
-// Close closes the Writer, flushing any unwritten data to the underlying
-// io.Writer, but does not close the underlying io.Writer.
+// Close closes the Writer by flushing any unwritten data to the underlying
+// io.Writer and writing the GZIP footer.
+// It does not close the underlying io.Writer.
func (z *Writer) Close() error {
if z.err != nil {
return z.err
diff --git a/libgo/go/compress/lzw/reader.go b/libgo/go/compress/lzw/reader.go
index 9eef2b2..1be52d5 100644
--- a/libgo/go/compress/lzw/reader.go
+++ b/libgo/go/compress/lzw/reader.go
@@ -57,8 +57,14 @@ type decoder struct {
// The next two codes mean clear and EOF.
// Other valid codes are in the range [lo, hi] where lo := clear + 2,
// with the upper bound incrementing on each code seen.
- // overflow is the code at which hi overflows the code width.
+ //
+ // overflow is the code at which hi overflows the code width. It always
+ // equals 1 << width.
+ //
// last is the most recently seen code, or decoderInvalidCode.
+ //
+ // An invariant is that
+ // (hi < overflow) || (hi == overflow && last == decoderInvalidCode)
clear, eof, hi, overflow, last uint16
// Each code c in [lo, hi] expands to two or more bytes. For c != hi:
@@ -163,7 +169,7 @@ loop:
break loop
case code <= d.hi:
c, i := code, len(d.output)-1
- if code == d.hi {
+ if code == d.hi && d.last != decoderInvalidCode {
// code == hi is a special case which expands to the last expansion
// followed by the head of the last expansion. To find the head, we walk
// the prefix chain until we find a literal code.
@@ -196,6 +202,10 @@ loop:
if d.hi >= d.overflow {
if d.width == maxWidth {
d.last = decoderInvalidCode
+ // Undo the d.hi++ a few lines above, so that (1) we maintain
+ // the invariant that d.hi <= d.overflow, and (2) d.hi does not
+ // eventually overflow a uint16.
+ d.hi--
} else {
d.width++
d.overflow <<= 1
diff --git a/libgo/go/compress/lzw/reader_test.go b/libgo/go/compress/lzw/reader_test.go
index 6b9f9a3..f8974de 100644
--- a/libgo/go/compress/lzw/reader_test.go
+++ b/libgo/go/compress/lzw/reader_test.go
@@ -120,6 +120,103 @@ func TestReader(t *testing.T) {
}
}
+type devZero struct{}
+
+func (devZero) Read(p []byte) (int, error) {
+ for i := range p {
+ p[i] = 0
+ }
+ return len(p), nil
+}
+
+func TestHiCodeDoesNotOverflow(t *testing.T) {
+ r := NewReader(devZero{}, LSB, 8)
+ d := r.(*decoder)
+ buf := make([]byte, 1024)
+ oldHi := uint16(0)
+ for i := 0; i < 100; i++ {
+ if _, err := io.ReadFull(r, buf); err != nil {
+ t.Fatalf("i=%d: %v", i, err)
+ }
+ // The hi code should never decrease.
+ if d.hi < oldHi {
+ t.Fatalf("i=%d: hi=%d decreased from previous value %d", i, d.hi, oldHi)
+ }
+ oldHi = d.hi
+ }
+}
+
+// TestNoLongerSavingPriorExpansions tests the decoder state when codes other
+// than clear codes continue to be seen after decoder.hi and decoder.width
+// reach their maximum values (4095 and 12), i.e. after we no longer save prior
+// expansions. In particular, it tests seeing the highest possible code, 4095.
+func TestNoLongerSavingPriorExpansions(t *testing.T) {
+ // Iterations is used to calculate how many input bits are needed to get
+ // the decoder.hi and decoder.width values up to their maximum.
+ iterations := []struct {
+ width, n int
+ }{
+ // The final term is 257, not 256, as NewReader initializes d.hi to
+ // d.clear+1 and the clear code is 256.
+ {9, 512 - 257},
+ {10, 1024 - 512},
+ {11, 2048 - 1024},
+ {12, 4096 - 2048},
+ }
+ nCodes, nBits := 0, 0
+ for _, e := range iterations {
+ nCodes += e.n
+ nBits += e.n * e.width
+ }
+ if nCodes != 3839 {
+ t.Fatalf("nCodes: got %v, want %v", nCodes, 3839)
+ }
+ if nBits != 43255 {
+ t.Fatalf("nBits: got %v, want %v", nBits, 43255)
+ }
+
+ // Construct our input of 43255 zero bits (which gets d.hi and d.width up
+ // to 4095 and 12), followed by 0xfff (4095) as 12 bits, followed by 0x101
+ // (EOF) as 12 bits.
+ //
+ // 43255 = 5406*8 + 7, and codes are read in LSB order. The final bytes are
+ // therefore:
+ //
+ // xwwwwwww xxxxxxxx yyyyyxxx zyyyyyyy
+ // 10000000 11111111 00001111 00001000
+ //
+ // or split out:
+ //
+ // .0000000 ........ ........ ........ w = 0x000
+ // 1....... 11111111 .....111 ........ x = 0xfff
+ // ........ ........ 00001... .0001000 y = 0x101
+ //
+ // The 12 'w' bits (not all are shown) form the 3839'th code, with value
+ // 0x000. Just after decoder.read returns that code, d.hi == 4095 and
+ // d.last == 0.
+ //
+ // The 12 'x' bits form the 3840'th code, with value 0xfff or 4095. Just
+ // after decoder.read returns that code, d.hi == 4095 and d.last ==
+ // decoderInvalidCode.
+ //
+ // The 12 'y' bits form the 3841'st code, with value 0x101, the EOF code.
+ //
+ // The 'z' bit is unused.
+ in := make([]byte, 5406)
+ in = append(in, 0x80, 0xff, 0x0f, 0x08)
+
+ r := NewReader(bytes.NewReader(in), LSB, 8)
+ nDecoded, err := io.Copy(ioutil.Discard, r)
+ if err != nil {
+ t.Fatalf("Copy: %v", err)
+ }
+ // nDecoded should be 3841: 3839 literal codes and then 2 decoded bytes
+ // from 1 non-literal code. The EOF code contributes 0 decoded bytes.
+ if nDecoded != int64(nCodes+2) {
+ t.Fatalf("nDecoded: got %v, want %v", nDecoded, nCodes+2)
+ }
+}
+
func BenchmarkDecoder(b *testing.B) {
buf, err := ioutil.ReadFile("../testdata/e.txt")
if err != nil {
diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go
index 7110c51..b2c6427 100644
--- a/libgo/go/container/heap/heap.go
+++ b/libgo/go/container/heap/heap.go
@@ -72,8 +72,9 @@ func Remove(h Interface, i int) interface{} {
n := h.Len() - 1
if n != i {
h.Swap(i, n)
- down(h, i, n)
- up(h, i)
+ if !down(h, i, n) {
+ up(h, i)
+ }
}
return h.Pop()
}
@@ -107,7 +108,7 @@ func down(h Interface, i0, n int) bool {
break
}
j := j1 // left child
- if j2 := j1 + 1; j2 < n && !h.Less(j1, j2) {
+ if j2 := j1 + 1; j2 < n && h.Less(j2, j1) {
j = j2 // = 2*i + 2 // right child
}
if !h.Less(j, i) {
diff --git a/libgo/go/context/context.go b/libgo/go/context/context.go
index 0aa7c24..892ff27 100644
--- a/libgo/go/context/context.go
+++ b/libgo/go/context/context.go
@@ -96,10 +96,11 @@ type Context interface {
// a Done channel for cancelation.
Done() <-chan struct{}
- // Err returns a non-nil error value after Done is closed. Err returns
- // Canceled if the context was canceled or DeadlineExceeded if the
- // context's deadline passed. No other values for Err are defined.
- // After Done is closed, successive calls to Err return the same value.
+ // If Done is not yet closed, Err returns nil.
+ // If Done is closed, Err returns a non-nil error explaining why:
+ // Canceled if the context was canceled
+ // or DeadlineExceeded if the context's deadline passed.
+ // After Err returns a non-nil error, successive calls to Err return the same error.
Err() error
// Value returns the value associated with this context for key, or nil
@@ -234,10 +235,7 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx {
- return cancelCtx{
- Context: parent,
- done: make(chan struct{}),
- }
+ return cancelCtx{Context: parent}
}
// propagateCancel arranges for child to be canceled when parent is.
@@ -306,20 +304,32 @@ type canceler interface {
Done() <-chan struct{}
}
+// closedchan is a reusable closed channel.
+var closedchan = make(chan struct{})
+
+func init() {
+ close(closedchan)
+}
+
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
- done chan struct{} // closed by the first cancel call.
-
- mu sync.Mutex
+ mu sync.Mutex // protects following fields
+ done chan struct{} // created lazily, closed by first cancel call
children map[canceler]struct{} // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
func (c *cancelCtx) Done() <-chan struct{} {
- return c.done
+ c.mu.Lock()
+ if c.done == nil {
+ c.done = make(chan struct{})
+ }
+ d := c.done
+ c.mu.Unlock()
+ return d
}
func (c *cancelCtx) Err() error {
@@ -344,7 +354,11 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) {
return // already canceled
}
c.err = err
- close(c.done)
+ if c.done == nil {
+ c.done = closedchan
+ } else {
+ close(c.done)
+ }
for child := range c.children {
// NOTE: acquiring the child's lock while holding parent's lock.
child.cancel(false, err)
diff --git a/libgo/go/context/context_test.go b/libgo/go/context/context_test.go
index b5e599f..548476f 100644
--- a/libgo/go/context/context_test.go
+++ b/libgo/go/context/context_test.go
@@ -428,7 +428,7 @@ func XTestAllocs(t testingT, testingShort func() bool, testingAllocsPerRun func(
limit := test.limit
if runtime.Compiler == "gccgo" {
// gccgo does not yet do escape analysis.
- // TOOD(iant): Remove this when gccgo does do escape analysis.
+ // TODO(iant): Remove this when gccgo does do escape analysis.
limit = test.gccgoLimit
}
numRuns := 100
diff --git a/libgo/go/crypto/aes/cipher_generic.go b/libgo/go/crypto/aes/cipher_generic.go
index 2c8d299..98169bf 100644
--- a/libgo/go/crypto/aes/cipher_generic.go
+++ b/libgo/go/crypto/aes/cipher_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// -build !amd64,!s390x
+// -build !amd64,!s390x,!ppc64le
package aes
diff --git a/libgo/go/crypto/aes/cipher_ppc64le.go b/libgo/go/crypto/aes/cipher_ppc64le.go
new file mode 100644
index 0000000..1d16fe0
--- /dev/null
+++ b/libgo/go/crypto/aes/cipher_ppc64le.go
@@ -0,0 +1,82 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package aes
+
+import (
+ "crypto/cipher"
+)
+
+// defined in asm_ppc64le.s
+
+//go:noescape
+
+func setEncryptKeyAsm(key *byte, keylen int, enc *uint32) int
+
+//go:noescape
+
+func setDecryptKeyAsm(key *byte, keylen int, dec *uint32) int
+
+//go:noescape
+
+func doEncryptKeyAsm(key *byte, keylen int, dec *uint32) int
+
+//go:noescape
+
+func encryptBlockAsm(dst, src *byte, enc *uint32)
+
+//go:noescape
+
+func decryptBlockAsm(dst, src *byte, dec *uint32)
+
+type aesCipherAsm struct {
+ aesCipher
+}
+
+func newCipher(key []byte) (cipher.Block, error) {
+ n := 64 // size is fixed for all and round value is stored inside it too
+ c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}}
+ k := len(key)
+
+ ret := 0
+ ret += setEncryptKeyAsm(&key[0], k*8, &c.enc[0])
+ ret += setDecryptKeyAsm(&key[0], k*8, &c.dec[0])
+
+ if ret > 0 {
+ return nil, KeySizeError(k)
+ }
+
+ return &c, nil
+}
+
+func (c *aesCipherAsm) BlockSize() int { return BlockSize }
+
+func (c *aesCipherAsm) Encrypt(dst, src []byte) {
+ if len(src) < BlockSize {
+ panic("crypto/aes: input not full block")
+ }
+ if len(dst) < BlockSize {
+ panic("crypto/aes: output not full block")
+ }
+ encryptBlockAsm(&dst[0], &src[0], &c.enc[0])
+}
+
+func (c *aesCipherAsm) Decrypt(dst, src []byte) {
+ if len(src) < BlockSize {
+ panic("crypto/aes: input not full block")
+ }
+ if len(dst) < BlockSize {
+ panic("crypto/aes: output not full block")
+ }
+ decryptBlockAsm(&dst[0], &src[0], &c.dec[0])
+}
+
+// expandKey is used by BenchmarkExpand to ensure that the asm implementation
+// of key expansion is used for the benchmark when it is available.
+func expandKey(key []byte, enc, dec []uint32) {
+ setEncryptKeyAsm(&key[0], len(key)*8, &enc[0])
+ setDecryptKeyAsm(&key[0], len(key)*8, &dec[0])
+}
diff --git a/libgo/go/crypto/crypto.go b/libgo/go/crypto/crypto.go
index a80ebd3..b4d6cdc 100644
--- a/libgo/go/crypto/crypto.go
+++ b/libgo/go/crypto/crypto.go
@@ -21,40 +21,48 @@ func (h Hash) HashFunc() Hash {
}
const (
- MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
- MD5 // import crypto/md5
- SHA1 // import crypto/sha1
- SHA224 // import crypto/sha256
- SHA256 // import crypto/sha256
- SHA384 // import crypto/sha512
- SHA512 // import crypto/sha512
- MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
- RIPEMD160 // import golang.org/x/crypto/ripemd160
- SHA3_224 // import golang.org/x/crypto/sha3
- SHA3_256 // import golang.org/x/crypto/sha3
- SHA3_384 // import golang.org/x/crypto/sha3
- SHA3_512 // import golang.org/x/crypto/sha3
- SHA512_224 // import crypto/sha512
- SHA512_256 // import crypto/sha512
+ MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
+ MD5 // import crypto/md5
+ SHA1 // import crypto/sha1
+ SHA224 // import crypto/sha256
+ SHA256 // import crypto/sha256
+ SHA384 // import crypto/sha512
+ SHA512 // import crypto/sha512
+ MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
+ RIPEMD160 // import golang.org/x/crypto/ripemd160
+ SHA3_224 // import golang.org/x/crypto/sha3
+ SHA3_256 // import golang.org/x/crypto/sha3
+ SHA3_384 // import golang.org/x/crypto/sha3
+ SHA3_512 // import golang.org/x/crypto/sha3
+ SHA512_224 // import crypto/sha512
+ SHA512_256 // import crypto/sha512
+ BLAKE2s_256 // import golang.org/x/crypto/blake2s
+ BLAKE2b_256 // import golang.org/x/crypto/blake2b
+ BLAKE2b_384 // import golang.org/x/crypto/blake2b
+ BLAKE2b_512 // import golang.org/x/crypto/blake2b
maxHash
)
var digestSizes = []uint8{
- MD4: 16,
- MD5: 16,
- SHA1: 20,
- SHA224: 28,
- SHA256: 32,
- SHA384: 48,
- SHA512: 64,
- SHA512_224: 28,
- SHA512_256: 32,
- SHA3_224: 28,
- SHA3_256: 32,
- SHA3_384: 48,
- SHA3_512: 64,
- MD5SHA1: 36,
- RIPEMD160: 20,
+ MD4: 16,
+ MD5: 16,
+ SHA1: 20,
+ SHA224: 28,
+ SHA256: 32,
+ SHA384: 48,
+ SHA512: 64,
+ SHA512_224: 28,
+ SHA512_256: 32,
+ SHA3_224: 28,
+ SHA3_256: 32,
+ SHA3_384: 48,
+ SHA3_512: 64,
+ MD5SHA1: 36,
+ RIPEMD160: 20,
+ BLAKE2s_256: 32,
+ BLAKE2b_256: 32,
+ BLAKE2b_384: 48,
+ BLAKE2b_512: 64,
}
// Size returns the length, in bytes, of a digest resulting from the given hash
diff --git a/libgo/go/crypto/des/block.go b/libgo/go/crypto/des/block.go
index 99338d6..21e6d4e 100644
--- a/libgo/go/crypto/des/block.go
+++ b/libgo/go/crypto/des/block.go
@@ -4,25 +4,29 @@
package des
-import (
- "encoding/binary"
-)
+import "encoding/binary"
func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
b := binary.BigEndian.Uint64(src)
b = permuteInitialBlock(b)
left, right := uint32(b>>32), uint32(b)
- var subkey uint64
- for i := 0; i < 16; i++ {
- if decrypt {
- subkey = subkeys[15-i]
- } else {
- subkey = subkeys[i]
- }
+ left = (left << 1) | (left >> 31)
+ right = (right << 1) | (right >> 31)
- left, right = right, left^feistel(right, subkey)
+ if decrypt {
+ for i := 0; i < 8; i++ {
+ left, right = feistel(left, right, subkeys[15-2*i], subkeys[15-(2*i+1)])
+ }
+ } else {
+ for i := 0; i < 8; i++ {
+ left, right = feistel(left, right, subkeys[2*i], subkeys[2*i+1])
+ }
}
+
+ left = (left << 31) | (left >> 1)
+ right = (right << 31) | (right >> 1)
+
// switch left & right and perform final permutation
preOutput := (uint64(right) << 32) | uint64(left)
binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
@@ -39,19 +43,34 @@ func decryptBlock(subkeys []uint64, dst, src []byte) {
}
// DES Feistel function
-func feistel(right uint32, key uint64) (result uint32) {
- sBoxLocations := key ^ expandBlock(right)
- var sBoxResult uint32
- for i := uint8(0); i < 8; i++ {
- sBoxLocation := uint8(sBoxLocations>>42) & 0x3f
- sBoxLocations <<= 6
- // row determined by 1st and 6th bit
- // column is middle four bits
- row := (sBoxLocation & 0x1) | ((sBoxLocation & 0x20) >> 4)
- column := (sBoxLocation >> 1) & 0xf
- sBoxResult ^= feistelBox[i][16*row+column]
- }
- return sBoxResult
+func feistel(l, r uint32, k0, k1 uint64) (lout, rout uint32) {
+ var t uint32
+
+ t = r ^ uint32(k0>>32)
+ l ^= feistelBox[7][t&0x3f] ^
+ feistelBox[5][(t>>8)&0x3f] ^
+ feistelBox[3][(t>>16)&0x3f] ^
+ feistelBox[1][(t>>24)&0x3f]
+
+ t = ((r << 28) | (r >> 4)) ^ uint32(k0)
+ l ^= feistelBox[6][(t)&0x3f] ^
+ feistelBox[4][(t>>8)&0x3f] ^
+ feistelBox[2][(t>>16)&0x3f] ^
+ feistelBox[0][(t>>24)&0x3f]
+
+ t = l ^ uint32(k1>>32)
+ r ^= feistelBox[7][t&0x3f] ^
+ feistelBox[5][(t>>8)&0x3f] ^
+ feistelBox[3][(t>>16)&0x3f] ^
+ feistelBox[1][(t>>24)&0x3f]
+
+ t = ((l << 28) | (l >> 4)) ^ uint32(k1)
+ r ^= feistelBox[6][(t)&0x3f] ^
+ feistelBox[4][(t>>8)&0x3f] ^
+ feistelBox[2][(t>>16)&0x3f] ^
+ feistelBox[0][(t>>24)&0x3f]
+
+ return l, r
}
// feistelBox[s][16*i+j] contains the output of permutationFunction
@@ -73,27 +92,22 @@ func init() {
for j := 0; j < 16; j++ {
f := uint64(sBoxes[s][i][j]) << (4 * (7 - uint(s)))
f = permuteBlock(f, permutationFunction[:])
- feistelBox[s][16*i+j] = uint32(f)
+
+ // Row is determined by the 1st and 6th bit.
+ // Column is the middle four bits.
+ row := uint8(((i & 2) << 4) | i&1)
+ col := uint8(j << 1)
+ t := row | col
+
+ // The rotation was performed in the feistel rounds, being factored out and now mixed into the feistelBox.
+ f = (f << 1) | (f >> 31)
+
+ feistelBox[s][t] = uint32(f)
}
}
}
}
-// expandBlock expands an input block of 32 bits,
-// producing an output block of 48 bits.
-func expandBlock(src uint32) (block uint64) {
- // rotate the 5 highest bits to the right.
- src = (src << 5) | (src >> 27)
- for i := 0; i < 8; i++ {
- block <<= 6
- // take the 6 bits on the right
- block |= uint64(src) & (1<<6 - 1)
- // advance by 4 bits.
- src = (src << 4) | (src >> 28)
- }
- return
-}
-
// permuteInitialBlock is equivalent to the permutation defined
// by initialPermutation.
func permuteInitialBlock(block uint64) uint64 {
@@ -218,6 +232,24 @@ func (c *desCipher) generateSubkeys(keyBytes []byte) {
// combine halves to form 56-bit input to PC2
pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i])
// apply PC2 permutation to 7 byte input
- c.subkeys[i] = permuteBlock(pc2Input, permutedChoice2[:])
+ c.subkeys[i] = unpack(permuteBlock(pc2Input, permutedChoice2[:]))
}
}
+
+// Expand 48-bit input to 64-bit, with each 6-bit block padded by extra two bits at the top.
+// By doing so, we can have the input blocks (four bits each), and the key blocks (six bits each) well-aligned without
+// extra shifts/rotations for alignments.
+func unpack(x uint64) uint64 {
+ var result uint64
+
+ result = ((x>>(6*1))&0xff)<<(8*0) |
+ ((x>>(6*3))&0xff)<<(8*1) |
+ ((x>>(6*5))&0xff)<<(8*2) |
+ ((x>>(6*7))&0xff)<<(8*3) |
+ ((x>>(6*0))&0xff)<<(8*4) |
+ ((x>>(6*2))&0xff)<<(8*5) |
+ ((x>>(6*4))&0xff)<<(8*6) |
+ ((x>>(6*6))&0xff)<<(8*7)
+
+ return result
+}
diff --git a/libgo/go/crypto/des/cipher.go b/libgo/go/crypto/des/cipher.go
index 2f929ca..46af5b0 100644
--- a/libgo/go/crypto/des/cipher.go
+++ b/libgo/go/crypto/des/cipher.go
@@ -6,6 +6,7 @@ package des
import (
"crypto/cipher"
+ "encoding/binary"
"strconv"
)
@@ -61,13 +62,51 @@ func NewTripleDESCipher(key []byte) (cipher.Block, error) {
func (c *tripleDESCipher) BlockSize() int { return BlockSize }
func (c *tripleDESCipher) Encrypt(dst, src []byte) {
- c.cipher1.Encrypt(dst, src)
- c.cipher2.Decrypt(dst, dst)
- c.cipher3.Encrypt(dst, dst)
+ b := binary.BigEndian.Uint64(src)
+ b = permuteInitialBlock(b)
+ left, right := uint32(b>>32), uint32(b)
+
+ left = (left << 1) | (left >> 31)
+ right = (right << 1) | (right >> 31)
+
+ for i := 0; i < 8; i++ {
+ left, right = feistel(left, right, c.cipher1.subkeys[2*i], c.cipher1.subkeys[2*i+1])
+ }
+ for i := 0; i < 8; i++ {
+ right, left = feistel(right, left, c.cipher2.subkeys[15-2*i], c.cipher2.subkeys[15-(2*i+1)])
+ }
+ for i := 0; i < 8; i++ {
+ left, right = feistel(left, right, c.cipher3.subkeys[2*i], c.cipher3.subkeys[2*i+1])
+ }
+
+ left = (left << 31) | (left >> 1)
+ right = (right << 31) | (right >> 1)
+
+ preOutput := (uint64(right) << 32) | uint64(left)
+ binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
}
func (c *tripleDESCipher) Decrypt(dst, src []byte) {
- c.cipher3.Decrypt(dst, src)
- c.cipher2.Encrypt(dst, dst)
- c.cipher1.Decrypt(dst, dst)
+ b := binary.BigEndian.Uint64(src)
+ b = permuteInitialBlock(b)
+ left, right := uint32(b>>32), uint32(b)
+
+ left = (left << 1) | (left >> 31)
+ right = (right << 1) | (right >> 31)
+
+ for i := 0; i < 8; i++ {
+ left, right = feistel(left, right, c.cipher3.subkeys[15-2*i], c.cipher3.subkeys[15-(2*i+1)])
+ }
+ for i := 0; i < 8; i++ {
+ right, left = feistel(right, left, c.cipher2.subkeys[2*i], c.cipher2.subkeys[2*i+1])
+ }
+ for i := 0; i < 8; i++ {
+ left, right = feistel(left, right, c.cipher1.subkeys[15-2*i], c.cipher1.subkeys[15-(2*i+1)])
+ }
+
+ left = (left << 31) | (left >> 1)
+ right = (right << 31) | (right >> 1)
+
+ preOutput := (uint64(right) << 32) | uint64(left)
+ binary.BigEndian.PutUint64(dst, permuteFinalBlock(preOutput))
}
diff --git a/libgo/go/crypto/des/const.go b/libgo/go/crypto/des/const.go
index 2bd485e..a20879d 100644
--- a/libgo/go/crypto/des/const.go
+++ b/libgo/go/crypto/des/const.go
@@ -5,6 +5,9 @@
// Package des implements the Data Encryption Standard (DES) and the
// Triple Data Encryption Algorithm (TDEA) as defined
// in U.S. Federal Information Processing Standards Publication 46-3.
+//
+// DES is cryptographically broken and should not be used for secure
+// applications.
package des
// Used to perform an initial permutation of a 64-bit input block.
diff --git a/libgo/go/crypto/des/des_test.go b/libgo/go/crypto/des/des_test.go
index 2bd525a..690a49f 100644
--- a/libgo/go/crypto/des/des_test.go
+++ b/libgo/go/crypto/des/des_test.go
@@ -1526,17 +1526,6 @@ func TestFinalPermute(t *testing.T) {
}
}
-func TestExpandBlock(t *testing.T) {
- for i := uint(0); i < 32; i++ {
- bit := uint32(1) << i
- got := expandBlock(bit)
- want := permuteBlock(uint64(bit), expansionFunction[:])
- if got != want {
- t.Errorf("expand(%x) = %x, want %x", bit, got, want)
- }
- }
-}
-
func BenchmarkEncrypt(b *testing.B) {
tt := encryptDESTests[0]
c, err := NewCipher(tt.key)
@@ -1564,3 +1553,31 @@ func BenchmarkDecrypt(b *testing.B) {
c.Decrypt(out, tt.out)
}
}
+
+func BenchmarkTDESEncrypt(b *testing.B) {
+ tt := encryptTripleDESTests[0]
+ c, err := NewTripleDESCipher(tt.key)
+ if err != nil {
+ b.Fatal("NewCipher:", err)
+ }
+ out := make([]byte, len(tt.in))
+ b.SetBytes(int64(len(out)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ c.Encrypt(out, tt.in)
+ }
+}
+
+func BenchmarkTDESDecrypt(b *testing.B) {
+ tt := encryptTripleDESTests[0]
+ c, err := NewTripleDESCipher(tt.key)
+ if err != nil {
+ b.Fatal("NewCipher:", err)
+ }
+ out := make([]byte, len(tt.out))
+ b.SetBytes(int64(len(out)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ c.Decrypt(out, tt.out)
+ }
+}
diff --git a/libgo/go/crypto/dsa/dsa_test.go b/libgo/go/crypto/dsa/dsa_test.go
index 8600059..7fc246b 100644
--- a/libgo/go/crypto/dsa/dsa_test.go
+++ b/libgo/go/crypto/dsa/dsa_test.go
@@ -82,12 +82,17 @@ func fromHex(s string) *big.Int {
}
func TestSignAndVerify(t *testing.T) {
- var priv PrivateKey
- priv.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
- priv.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F422B9C1", 16)
- priv.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
- priv.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
- priv.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A", 16)
+ priv := PrivateKey{
+ PublicKey: PublicKey{
+ Parameters: Parameters{
+ P: fromHex("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF"),
+ Q: fromHex("E1D3391245933D68A0714ED34BBCB7A1F422B9C1"),
+ G: fromHex("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA"),
+ },
+ Y: fromHex("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2"),
+ },
+ X: fromHex("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A"),
+ }
testSignAndVerify(t, 0, &priv)
}
diff --git a/libgo/go/crypto/md5/md5.go b/libgo/go/crypto/md5/md5.go
index ce58d5e..b682f00 100644
--- a/libgo/go/crypto/md5/md5.go
+++ b/libgo/go/crypto/md5/md5.go
@@ -5,6 +5,9 @@
//go:generate go run gen.go -full -output md5block.go
// Package md5 implements the MD5 hash algorithm as defined in RFC 1321.
+//
+// MD5 is cryptographically broken and should not be used for secure
+// applications.
package md5
import (
diff --git a/libgo/go/crypto/rand/rand_linux.go b/libgo/go/crypto/rand/rand_linux.go
index 472daa7..8a4c757 100644
--- a/libgo/go/crypto/rand/rand_linux.go
+++ b/libgo/go/crypto/rand/rand_linux.go
@@ -6,34 +6,20 @@ package rand
import (
"internal/syscall/unix"
- "sync"
)
func init() {
altGetRandom = getRandomLinux
}
-var (
- once sync.Once
- useSyscall bool
-)
-
-func pickStrategy() {
- // Test whether we should use the system call or /dev/urandom.
- // We'll fall back to urandom if:
- // - the kernel is too old (before 3.17)
- // - the machine has no entropy available (early boot + no hardware
- // entropy source?) and we want to avoid blocking later.
- var buf [1]byte
- n, err := unix.GetRandom(buf[:], unix.GRND_NONBLOCK)
- useSyscall = n == 1 && err == nil
-}
-
+// If the kernel is too old (before 3.17) to support the getrandom syscall(),
+// unix.GetRandom will immediately return ENOSYS and we will then fall back to
+// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS
+// result so we only suffer the syscall overhead once in this case.
+// If the kernel supports the getrandom() syscall, unix.GetRandom will block
+// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK).
+// In this case, unix.GetRandom will not return an error.
func getRandomLinux(p []byte) (ok bool) {
- once.Do(pickStrategy)
- if !useSyscall {
- return false
- }
n, err := unix.GetRandom(p, 0)
return n == len(p) && err == nil
}
diff --git a/libgo/go/crypto/rand/util.go b/libgo/go/crypto/rand/util.go
index 592c57e..4dd1711 100644
--- a/libgo/go/crypto/rand/util.go
+++ b/libgo/go/crypto/rand/util.go
@@ -107,16 +107,23 @@ func Int(rand io.Reader, max *big.Int) (n *big.Int, err error) {
if max.Sign() <= 0 {
panic("crypto/rand: argument to Int is <= 0")
}
- k := (max.BitLen() + 7) / 8
-
- // b is the number of bits in the most significant byte of max.
- b := uint(max.BitLen() % 8)
+ n = new(big.Int)
+ n.Sub(max, n.SetUint64(1))
+ // bitLen is the maximum bit length needed to encode a value < max.
+ bitLen := n.BitLen()
+ if bitLen == 0 {
+ // the only valid result is 0
+ return
+ }
+ // k is the maximum byte length needed to encode a value < max.
+ k := (bitLen + 7) / 8
+ // b is the number of bits in the most significant byte of max-1.
+ b := uint(bitLen % 8)
if b == 0 {
b = 8
}
bytes := make([]byte, k)
- n = new(big.Int)
for {
_, err = io.ReadFull(rand, bytes)
diff --git a/libgo/go/crypto/rand/util_test.go b/libgo/go/crypto/rand/util_test.go
index 48a2c3f..685624e 100644
--- a/libgo/go/crypto/rand/util_test.go
+++ b/libgo/go/crypto/rand/util_test.go
@@ -5,7 +5,10 @@
package rand_test
import (
+ "bytes"
"crypto/rand"
+ "fmt"
+ "io"
"math/big"
mathrand "math/rand"
"testing"
@@ -45,6 +48,56 @@ func TestInt(t *testing.T) {
}
}
+type countingReader struct {
+ r io.Reader
+ n int
+}
+
+func (r *countingReader) Read(p []byte) (n int, err error) {
+ n, err = r.r.Read(p)
+ r.n += n
+ return n, err
+}
+
+// Test that Int reads only the necessary number of bytes from the reader for
+// max at each bit length
+func TestIntReads(t *testing.T) {
+ for i := 0; i < 32; i++ {
+ max := int64(1 << uint64(i))
+ t.Run(fmt.Sprintf("max=%d", max), func(t *testing.T) {
+ reader := &countingReader{r: rand.Reader}
+
+ _, err := rand.Int(reader, big.NewInt(max))
+ if err != nil {
+ t.Fatalf("Can't generate random value: %d, %v", max, err)
+ }
+ expected := (i + 7) / 8
+ if reader.n != expected {
+ t.Errorf("Int(reader, %d) should read %d bytes, but it read: %d", max, expected, reader.n)
+ }
+ })
+ }
+}
+
+// Test that Int does not mask out valid return values
+func TestIntMask(t *testing.T) {
+ for max := 1; max <= 256; max++ {
+ t.Run(fmt.Sprintf("max=%d", max), func(t *testing.T) {
+ for i := 0; i < max; i++ {
+ var b bytes.Buffer
+ b.WriteByte(byte(i))
+ n, err := rand.Int(&b, big.NewInt(int64(max)))
+ if err != nil {
+ t.Fatalf("Can't generate random value: %d, %v", max, err)
+ }
+ if n.Int64() != int64(i) {
+ t.Errorf("Int(reader, %d) should have returned value of %d, but it returned: %v", max, i, n)
+ }
+ }
+ })
+ }
+}
+
func testIntPanics(t *testing.T, b *big.Int) {
defer func() {
if err := recover(); err == nil {
diff --git a/libgo/go/crypto/rc4/rc4.go b/libgo/go/crypto/rc4/rc4.go
index bd04aee..772af0e 100644
--- a/libgo/go/crypto/rc4/rc4.go
+++ b/libgo/go/crypto/rc4/rc4.go
@@ -4,11 +4,11 @@
// Package rc4 implements RC4 encryption, as defined in Bruce Schneier's
// Applied Cryptography.
+//
+// RC4 is cryptographically broken and should not be used for secure
+// applications.
package rc4
-// BUG(agl): RC4 is in common use but has design weaknesses that make
-// it a poor choice for new protocols.
-
import "strconv"
// A Cipher is an instance of RC4 using a particular key.
diff --git a/libgo/go/crypto/sha1/sha1.go b/libgo/go/crypto/sha1/sha1.go
index fbb2f94..6b17214 100644
--- a/libgo/go/crypto/sha1/sha1.go
+++ b/libgo/go/crypto/sha1/sha1.go
@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174.
+// Package sha1 implements the SHA-1 hash algorithm as defined in RFC 3174.
+//
+// SHA-1 is cryptographically broken and should not be used for secure
+// applications.
package sha1
import (
@@ -14,10 +17,10 @@ func init() {
crypto.RegisterHash(crypto.SHA1, New)
}
-// The size of a SHA1 checksum in bytes.
+// The size of a SHA-1 checksum in bytes.
const Size = 20
-// The blocksize of SHA1 in bytes.
+// The blocksize of SHA-1 in bytes.
const BlockSize = 64
const (
@@ -189,7 +192,7 @@ func (d *digest) constSum() [Size]byte {
return digest
}
-// Sum returns the SHA1 checksum of the data.
+// Sum returns the SHA-1 checksum of the data.
func Sum(data []byte) [Size]byte {
var d digest
d.Reset()
diff --git a/libgo/go/crypto/sha1/sha1_test.go b/libgo/go/crypto/sha1/sha1_test.go
index 3e59a5d..faa9916 100644
--- a/libgo/go/crypto/sha1/sha1_test.go
+++ b/libgo/go/crypto/sha1/sha1_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// SHA1 hash algorithm. See RFC 3174.
+// SHA-1 hash algorithm. See RFC 3174.
package sha1
diff --git a/libgo/go/crypto/sha1/sha1block.go b/libgo/go/crypto/sha1/sha1block.go
index fde3c98..1d37544 100644
--- a/libgo/go/crypto/sha1/sha1block.go
+++ b/libgo/go/crypto/sha1/sha1block.go
@@ -11,7 +11,7 @@ const (
_K3 = 0xCA62C1D6
)
-// blockGeneric is a portable, pure Go version of the SHA1 block step.
+// blockGeneric is a portable, pure Go version of the SHA-1 block step.
// It's used by sha1block_generic.go and tests.
func blockGeneric(dig *digest, p []byte) {
var w [16]uint32
diff --git a/libgo/go/crypto/sha1/sha1block_amd64.go b/libgo/go/crypto/sha1/sha1block_amd64.go
index 8ef8b1f..2d7a314 100644
--- a/libgo/go/crypto/sha1/sha1block_amd64.go
+++ b/libgo/go/crypto/sha1/sha1block_amd64.go
@@ -6,18 +6,18 @@
package sha1
-//go:noescape
+import "internal/cpu"
+//go:noescape
func blockAVX2(dig *digest, p []byte)
//go:noescape
func blockAMD64(dig *digest, p []byte)
-func checkAVX2() bool
-var hasAVX2 = checkAVX2()
+var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI1 && cpu.X86.HasBMI2
func block(dig *digest, p []byte) {
- if hasAVX2 && len(p) >= 256 {
+ if useAVX2 && len(p) >= 256 {
// blockAVX2 calculates sha1 for 2 block per iteration
// it also interleaves precalculation for next block.
// So it may read up-to 192 bytes past end of p
diff --git a/libgo/go/crypto/sha1/sha1block_s390x.go b/libgo/go/crypto/sha1/sha1block_s390x.go
index 9edcbb0..55a2359 100644
--- a/libgo/go/crypto/sha1/sha1block_s390x.go
+++ b/libgo/go/crypto/sha1/sha1block_s390x.go
@@ -7,7 +7,7 @@
package sha1
// featureCheck reports whether the CPU supports the
-// SHA1 compute intermediate message digest (KIMD)
+// SHA-1 compute intermediate message digest (KIMD)
// function code.
func featureCheck() bool
diff --git a/libgo/go/crypto/sha256/sha256block_amd64.go b/libgo/go/crypto/sha256/sha256block_amd64.go
new file mode 100644
index 0000000..b311a12
--- /dev/null
+++ b/libgo/go/crypto/sha256/sha256block_amd64.go
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package sha256
+
+import "internal/cpu"
+
+var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
diff --git a/libgo/go/crypto/sha512/sha512block_amd64.go b/libgo/go/crypto/sha512/sha512block_amd64.go
new file mode 100644
index 0000000..0ce599b
--- /dev/null
+++ b/libgo/go/crypto/sha512/sha512block_amd64.go
@@ -0,0 +1,26 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+// +build amd64
+
+package sha512
+
+import "internal/cpu"
+
+//go:noescape
+func blockAVX2(dig *digest, p []byte)
+
+//go:noescape
+func blockAMD64(dig *digest, p []byte)
+
+var useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI1 && cpu.X86.HasBMI2
+
+func block(dig *digest, p []byte) {
+ if useAVX2 {
+ blockAVX2(dig, p)
+ } else {
+ blockAMD64(dig, p)
+ }
+}
diff --git a/libgo/go/crypto/sha512/sha512block_decl.go b/libgo/go/crypto/sha512/sha512block_decl.go
index 3859a40..3d098c5 100644
--- a/libgo/go/crypto/sha512/sha512block_decl.go
+++ b/libgo/go/crypto/sha512/sha512block_decl.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build ignore
-// +build amd64 s390x ppc64le
+// +build s390x ppc64le
package sha512
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index de833a9..5860838 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -163,8 +163,8 @@ type ConnectionState struct {
HandshakeComplete bool // TLS handshake is complete
DidResume bool // connection resumes a previous TLS connection
CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
- NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos)
- NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server
+ NegotiatedProtocol string // negotiated next protocol (not guaranteed to be from Config.NextProtos)
+ NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server (client side only)
ServerName string // server name requested by client, if any (server side only)
PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
@@ -174,9 +174,9 @@ type ConnectionState struct {
// TLSUnique contains the "tls-unique" channel binding value (see RFC
// 5929, section 3). For resumed sessions this value will be nil
// because resumption does not include enough context (see
- // https://secure-resumption.com/#channelbindings). This will change in
- // future versions of Go once the TLS master-secret fix has been
- // standardized and implemented.
+ // https://mitls.org/pages/attacks/3SHAKE#channelbindings). This will
+ // change in future versions of Go once the TLS master-secret fix has
+ // been standardized and implemented.
TLSUnique []byte
}
@@ -206,7 +206,8 @@ type ClientSessionState struct {
// ClientSessionCache is a cache of ClientSessionState objects that can be used
// by a client to resume a TLS session with a given server. ClientSessionCache
// implementations should expect to be called concurrently from different
-// goroutines.
+// goroutines. Only ticket-based resumption is supported, not SessionID-based
+// resumption.
type ClientSessionCache interface {
// Get searches for a ClientSessionState associated with the given key.
// On return, ok is true if one was found.
@@ -508,17 +509,13 @@ type Config struct {
serverInitOnce sync.Once // guards calling (*Config).serverInit
- // mutex protects sessionTicketKeys and originalConfig.
+ // mutex protects sessionTicketKeys.
mutex sync.RWMutex
// sessionTicketKeys contains zero or more ticket keys. If the length
// is zero, SessionTicketsDisabled must be true. The first key is used
// for new tickets and any subsequent keys can be used to decrypt old
// tickets.
sessionTicketKeys []ticketKey
- // originalConfig is set to the Config that was passed to Server if
- // this Config is returned by a GetConfigForClient callback. It's used
- // by serverInit in order to copy session ticket keys if needed.
- originalConfig *Config
}
// ticketKeyNameLen is the number of bytes of identifier that is prepended to
@@ -550,7 +547,7 @@ func ticketKeyFromBytes(b [32]byte) (key ticketKey) {
func (c *Config) Clone() *Config {
// Running serverInit ensures that it's safe to read
// SessionTicketsDisabled.
- c.serverInitOnce.Do(c.serverInit)
+ c.serverInitOnce.Do(func() { c.serverInit(nil) })
var sessionTicketKeys []ticketKey
c.mutex.RLock()
@@ -584,20 +581,17 @@ func (c *Config) Clone() *Config {
Renegotiation: c.Renegotiation,
KeyLogWriter: c.KeyLogWriter,
sessionTicketKeys: sessionTicketKeys,
- // originalConfig is deliberately not duplicated.
}
}
-func (c *Config) serverInit() {
+// serverInit is run under c.serverInitOnce to do initialization of c. If c was
+// returned by a GetConfigForClient callback then the argument should be the
+// Config that was passed to Server, otherwise it should be nil.
+func (c *Config) serverInit(originalConfig *Config) {
if c.SessionTicketsDisabled || len(c.ticketKeys()) != 0 {
return
}
- var originalConfig *Config
- c.mutex.Lock()
- originalConfig, c.originalConfig = c.originalConfig, nil
- c.mutex.Unlock()
-
alreadySet := false
for _, b := range c.SessionTicketKey {
if b != 0 {
@@ -947,9 +941,7 @@ func initDefaultCipherSuites() {
}
varDefaultCipherSuites = make([]uint16, 0, len(cipherSuites))
- for _, topCipher := range topCipherSuites {
- varDefaultCipherSuites = append(varDefaultCipherSuites, topCipher)
- }
+ varDefaultCipherSuites = append(varDefaultCipherSuites, topCipherSuites...)
NextCipherSuite:
for _, suite := range cipherSuites {
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index 03895a7..e6d85aa 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -1206,10 +1206,10 @@ func (c *Conn) Close() error {
var alertErr error
c.handshakeMutex.Lock()
- defer c.handshakeMutex.Unlock()
if c.handshakeComplete {
alertErr = c.closeNotify()
}
+ c.handshakeMutex.Unlock()
if err := c.conn.Close(); err != nil {
return err
diff --git a/libgo/go/crypto/tls/conn_test.go b/libgo/go/crypto/tls/conn_test.go
index 5e5c7a2..e27c541 100644
--- a/libgo/go/crypto/tls/conn_test.go
+++ b/libgo/go/crypto/tls/conn_test.go
@@ -138,7 +138,7 @@ func runDynamicRecordSizingTest(t *testing.T, config *Config) {
tlsConn := Client(clientConn, config)
if err := tlsConn.Handshake(); err != nil {
- t.Errorf("Error from client handshake: %s", err)
+ t.Errorf("Error from client handshake: %v", err)
return
}
@@ -147,12 +147,12 @@ func runDynamicRecordSizingTest(t *testing.T, config *Config) {
var recordSizes []int
for {
- n, err := clientConn.Read(recordHeader[:])
+ n, err := io.ReadFull(clientConn, recordHeader[:])
if err == io.EOF {
break
}
if err != nil || n != len(recordHeader) {
- t.Errorf("Error from client read: %s", err)
+ t.Errorf("io.ReadFull = %d, %v", n, err)
return
}
@@ -161,9 +161,9 @@ func runDynamicRecordSizingTest(t *testing.T, config *Config) {
record = make([]byte, length)
}
- n, err = clientConn.Read(record[:length])
+ n, err = io.ReadFull(clientConn, record[:length])
if err != nil || n != length {
- t.Errorf("Error from client read: %s", err)
+ t.Errorf("io.ReadFull = %d, %v", n, err)
return
}
@@ -241,3 +241,34 @@ func TestDynamicRecordSizingWithAEAD(t *testing.T) {
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
runDynamicRecordSizingTest(t, config)
}
+
+// hairpinConn is a net.Conn that makes a âhairpinâ call when closed, back into
+// the tls.Conn which is calling it.
+type hairpinConn struct {
+ net.Conn
+ tlsConn *Conn
+}
+
+func (conn *hairpinConn) Close() error {
+ conn.tlsConn.ConnectionState()
+ return nil
+}
+
+func TestHairpinInClose(t *testing.T) {
+ // This tests that the underlying net.Conn can call back into the
+ // tls.Conn when being closed without deadlocking.
+ client, server := net.Pipe()
+ defer server.Close()
+ defer client.Close()
+
+ conn := &hairpinConn{client, nil}
+ tlsConn := Server(conn, &Config{
+ GetCertificate: func(*ClientHelloInfo) (*Certificate, error) {
+ panic("unreachable")
+ },
+ })
+ conn.tlsConn = tlsConn
+
+ // This call should not deadlock.
+ tlsConn.Close()
+}
diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go
index 83f9916..8ee2b59 100644
--- a/libgo/go/crypto/tls/generate_cert.go
+++ b/libgo/go/crypto/tls/generate_cert.go
@@ -33,7 +33,7 @@ var (
validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
- ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521")
+ ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521")
)
func publicKey(priv interface{}) interface{} {
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index 6eda18d..a4ca5d3 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -815,7 +815,7 @@ func hostnameInSNI(name string) string {
if net.ParseIP(host) != nil {
return ""
}
- if len(name) > 0 && name[len(name)-1] == '.' {
+ for len(name) > 0 && name[len(name)-1] == '.' {
name = name[:len(name)-1]
}
return name
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index 694bd91..0c7581f 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -4,7 +4,10 @@
package tls
-import "bytes"
+import (
+ "bytes"
+ "strings"
+)
type clientHelloMsg struct {
raw []byte
@@ -393,6 +396,12 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
}
if nameType == 0 {
m.serverName = string(d[:nameLen])
+ // An SNI value may not include a
+ // trailing dot. See
+ // https://tools.ietf.org/html/rfc6066#section-3.
+ if strings.HasSuffix(m.serverName, ".") {
+ return false
+ }
break
}
d = d[nameLen:]
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index f1154d4..7add97c 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"math/rand"
"reflect"
+ "strings"
"testing"
"testing/quick"
)
@@ -123,6 +124,9 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value {
}
if rand.Intn(10) > 5 {
m.serverName = randomString(rand.Intn(255), rand)
+ for strings.HasSuffix(m.serverName, ".") {
+ m.serverName = m.serverName[:len(m.serverName)-1]
+ }
}
m.ocspStapling = rand.Intn(10) > 5
m.supportedPoints = randomBytes(rand.Intn(5)+1, rand)
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index b786c30..ae32848 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -40,7 +40,7 @@ type serverHandshakeState struct {
func (c *Conn) serverHandshake() error {
// If this is the first server handshake, we generate a random key to
// encrypt the tickets with.
- c.config.serverInitOnce.Do(c.config.serverInit)
+ c.config.serverInitOnce.Do(func() { c.config.serverInit(nil) })
hs := serverHandshakeState{
c: c,
@@ -129,11 +129,7 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
c.sendAlert(alertInternalError)
return false, err
} else if newConfig != nil {
- newConfig.mutex.Lock()
- newConfig.originalConfig = c.config
- newConfig.mutex.Unlock()
-
- newConfig.serverInitOnce.Do(newConfig.serverInit)
+ newConfig.serverInitOnce.Do(func() { newConfig.serverInit(c.config) })
c.config = newConfig
}
}
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index bcd3d43..63845c1 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -137,6 +137,10 @@ func TestNoRC4ByDefault(t *testing.T) {
testClientHelloFailure(t, serverConfig, clientHello, "no cipher suite supported by both client and server")
}
+func TestRejectSNIWithTrailingDot(t *testing.T) {
+ testClientHelloFailure(t, testConfig, &clientHelloMsg{vers: VersionTLS12, serverName: "foo.com."}, "unexpected message")
+}
+
func TestDontSelectECDSAWithRSAKey(t *testing.T) {
// Test that, even when both sides support an ECDSA cipher suite, it
// won't be selected if the server's private key doesn't support it.
diff --git a/libgo/go/crypto/x509/pkcs1.go b/libgo/go/crypto/x509/pkcs1.go
index df20a44..73bc762 100644
--- a/libgo/go/crypto/x509/pkcs1.go
+++ b/libgo/go/crypto/x509/pkcs1.go
@@ -35,6 +35,12 @@ type pkcs1AdditionalRSAPrime struct {
Coeff *big.Int
}
+// pkcs1PublicKey reflects the ASN.1 structure of a PKCS#1 public key.
+type pkcs1PublicKey struct {
+ N *big.Int
+ E int
+}
+
// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) {
var priv pkcs1PrivateKey
@@ -113,9 +119,3 @@ func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
b, _ := asn1.Marshal(priv)
return b
}
-
-// rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
-type rsaPublicKey struct {
- N *big.Int
- E int
-}
diff --git a/libgo/go/crypto/x509/root_bsd.go b/libgo/go/crypto/x509/root_bsd.go
index 9317283..137193389 100644
--- a/libgo/go/crypto/x509/root_bsd.go
+++ b/libgo/go/crypto/x509/root_bsd.go
@@ -8,7 +8,8 @@ package x509
// Possible certificate files; stop after finding one.
var certFiles = []string{
- "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
+ "/usr/local/etc/ssl/cert.pem", // FreeBSD
"/etc/ssl/cert.pem", // OpenBSD
+ "/usr/local/share/certs/ca-root-nss.crt", // DragonFly
"/etc/openssl/certs/ca-certificates.crt", // NetBSD
}
diff --git a/libgo/go/crypto/x509/root_darwin.go b/libgo/go/crypto/x509/root_darwin.go
index 66cdb5e..bc35a1c 100644
--- a/libgo/go/crypto/x509/root_darwin.go
+++ b/libgo/go/crypto/x509/root_darwin.go
@@ -16,6 +16,7 @@ import (
"io/ioutil"
"os"
"os/exec"
+ "os/user"
"path/filepath"
"strings"
"sync"
@@ -61,7 +62,26 @@ func execSecurityRoots() (*CertPool, error) {
println(fmt.Sprintf("crypto/x509: %d certs have a trust policy", len(hasPolicy)))
}
- cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
+ args := []string{"find-certificate", "-a", "-p",
+ "/System/Library/Keychains/SystemRootCertificates.keychain",
+ "/Library/Keychains/System.keychain",
+ }
+
+ u, err := user.Current()
+ if err != nil {
+ if debugExecDarwinRoots {
+ println(fmt.Sprintf("crypto/x509: get current user: %v", err))
+ }
+ } else {
+ args = append(args,
+ filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain"),
+
+ // Fresh installs of Sierra use a slightly different path for the login keychain
+ filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain-db"),
+ )
+ }
+
+ cmd := exec.Command("/usr/bin/security", args...)
data, err := cmd.Output()
if err != nil {
return nil, err
diff --git a/libgo/go/crypto/x509/root_unix.go b/libgo/go/crypto/x509/root_unix.go
index c44a524..0547460 100644
--- a/libgo/go/crypto/x509/root_unix.go
+++ b/libgo/go/crypto/x509/root_unix.go
@@ -16,28 +16,52 @@ import (
var certDirectories = []string{
"/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
"/system/etc/security/cacerts", // Android
+ "/usr/local/share/certs", // FreeBSD
+ "/etc/pki/tls/certs", // Fedora/RHEL
+ "/etc/openssl/certs", // NetBSD
"/var/ssl/certs", // AIX
}
+const (
+ // certFileEnv is the environment variable which identifies where to locate
+ // the SSL certificate file. If set this overrides the system default.
+ certFileEnv = "SSL_CERT_FILE"
+
+ // certDirEnv is the environment variable which identifies which directory
+ // to check for SSL certificate files. If set this overrides the system default.
+ certDirEnv = "SSL_CERT_DIR"
+)
+
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
return nil, nil
}
func loadSystemRoots() (*CertPool, error) {
roots := NewCertPool()
+
+ files := certFiles
+ if f := os.Getenv(certFileEnv); f != "" {
+ files = []string{f}
+ }
+
var firstErr error
- for _, file := range certFiles {
+ for _, file := range files {
data, err := ioutil.ReadFile(file)
if err == nil {
roots.AppendCertsFromPEM(data)
- return roots, nil
+ break
}
if firstErr == nil && !os.IsNotExist(err) {
firstErr = err
}
}
- for _, directory := range certDirectories {
+ dirs := certDirectories
+ if d := os.Getenv(certDirEnv); d != "" {
+ dirs = []string{d}
+ }
+
+ for _, directory := range dirs {
fis, err := ioutil.ReadDir(directory)
if err != nil {
if firstErr == nil && !os.IsNotExist(err) {
@@ -57,5 +81,9 @@ func loadSystemRoots() (*CertPool, error) {
}
}
+ if len(roots.certs) > 0 {
+ return roots, nil
+ }
+
return nil, firstErr
}
diff --git a/libgo/go/crypto/x509/root_unix_test.go b/libgo/go/crypto/x509/root_unix_test.go
new file mode 100644
index 0000000..03f935d
--- /dev/null
+++ b/libgo/go/crypto/x509/root_unix_test.go
@@ -0,0 +1,127 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build dragonfly freebsd linux netbsd openbsd solaris
+
+package x509
+
+import (
+ "fmt"
+ "os"
+ "testing"
+)
+
+const (
+ testDir = "testdata"
+ testDirCN = "test-dir"
+ testFile = "test-file.crt"
+ testFileCN = "test-file"
+ testMissing = "missing"
+)
+
+func TestEnvVars(t *testing.T) {
+ testCases := []struct {
+ name string
+ fileEnv string
+ dirEnv string
+ files []string
+ dirs []string
+ cns []string
+ }{
+ {
+ // Environment variables override the default locations preventing fall through.
+ name: "override-defaults",
+ fileEnv: testMissing,
+ dirEnv: testMissing,
+ files: []string{testFile},
+ dirs: []string{testDir},
+ cns: nil,
+ },
+ {
+ // File environment overrides default file locations.
+ name: "file",
+ fileEnv: testFile,
+ dirEnv: "",
+ files: nil,
+ dirs: nil,
+ cns: []string{testFileCN},
+ },
+ {
+ // Directory environment overrides default directory locations.
+ name: "dir",
+ fileEnv: "",
+ dirEnv: testDir,
+ files: nil,
+ dirs: nil,
+ cns: []string{testDirCN},
+ },
+ {
+ // File & directory environment overrides both default locations.
+ name: "file+dir",
+ fileEnv: testFile,
+ dirEnv: testDir,
+ files: nil,
+ dirs: nil,
+ cns: []string{testFileCN, testDirCN},
+ },
+ {
+ // Environment variable empty / unset uses default locations.
+ name: "empty-fall-through",
+ fileEnv: "",
+ dirEnv: "",
+ files: []string{testFile},
+ dirs: []string{testDir},
+ cns: []string{testFileCN, testDirCN},
+ },
+ }
+
+ // Save old settings so we can restore before the test ends.
+ origCertFiles, origCertDirectories := certFiles, certDirectories
+ origFile, origDir := os.Getenv(certFileEnv), os.Getenv(certDirEnv)
+ defer func() {
+ certFiles = origCertFiles
+ certDirectories = origCertDirectories
+ os.Setenv(certFileEnv, origFile)
+ os.Setenv(certDirEnv, origDir)
+ }()
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ if err := os.Setenv(certFileEnv, tc.fileEnv); err != nil {
+ t.Fatalf("setenv %q failed: %v", certFileEnv, err)
+ }
+ if err := os.Setenv(certDirEnv, tc.dirEnv); err != nil {
+ t.Fatalf("setenv %q failed: %v", certDirEnv, err)
+ }
+
+ certFiles, certDirectories = tc.files, tc.dirs
+
+ r, err := loadSystemRoots()
+ if err != nil {
+ t.Fatal("unexpected failure:", err)
+ }
+
+ if r == nil {
+ if tc.cns == nil {
+ // Expected nil
+ return
+ }
+ t.Fatal("nil roots")
+ }
+
+ // Verify that the returned certs match, otherwise report where the mismatch is.
+ for i, cn := range tc.cns {
+ if i >= len(r.certs) {
+ t.Errorf("missing cert %v @ %v", cn, i)
+ } else if r.certs[i].Subject.CommonName != cn {
+ fmt.Printf("%#v\n", r.certs[0].Subject)
+ t.Errorf("unexpected cert common name %q, want %q", r.certs[i].Subject.CommonName, cn)
+ }
+ }
+ if len(r.certs) > len(tc.cns) {
+ t.Errorf("got %v certs, which is more than %v wanted", len(r.certs), len(tc.cns))
+ }
+ })
+ }
+}
diff --git a/libgo/go/crypto/x509/test-file.crt b/libgo/go/crypto/x509/test-file.crt
new file mode 100644
index 0000000..caa83b9
--- /dev/null
+++ b/libgo/go/crypto/x509/test-file.crt
@@ -0,0 +1,32 @@
+-----BEGIN CERTIFICATE-----
+MIIFbTCCA1WgAwIBAgIJAN338vEmMtLsMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNV
+BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz
+dHMxEjAQBgNVBAMMCXRlc3QtZmlsZTAeFw0xNzAyMDEyMzUyMDhaFw0yNzAxMzAy
+MzUyMDhaME0xCzAJBgNVBAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYD
+VQQKDAxHb2xhbmcgVGVzdHMxEjAQBgNVBAMMCXRlc3QtZmlsZTCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBAPMGiLjdiffQo3Xc8oUe7wsDhSaAJFOhO6Qs
+i0xYrYl7jmCuz9rGD2fdgk5cLqGazKuQ6fIFzHXFU2BKs4CWXt9KO0KFEhfvZeuW
+jG5d7C1ZUiuKOrPqjKVu8SZtFPc7y7Ke7msXzY+Z2LLyiJJ93LCMq4+cTSGNXVlI
+KqUxhxeoD5/QkUPyQy/ilu3GMYfx/YORhDP6Edcuskfj8wRh1UxBejP8YPMvI6St
+cE2GkxoEGqDWnQ/61F18te6WI3MD29tnKXOkXVhnSC+yvRLljotW2/tAhHKBG4tj
+iQWT5Ri4Wrw2tXxPKRLsVWc7e1/hdxhnuvYpXkWNhKsm002jzkFXlzfEwPd8nZdw
+5aT6gPUBN2AAzdoqZI7E200i0orEF7WaSoMfjU1tbHvExp3vyAPOfJ5PS2MQ6W03
+Zsy5dTVH+OBH++rkRzQCFcnIv/OIhya5XZ9KX9nFPgBEP7Xq2A+IjH7B6VN/S/bv
+8lhp2V+SQvlew9GttKC4hKuPsl5o7+CMbcqcNUdxm9gGkN8epGEKCuix97bpNlxN
+fHZxHE5+8GMzPXMkCD56y5TNKR6ut7JGHMPtGl5lPCLqzG/HzYyFgxsDfDUu2B0A
+GKj0lGpnLfGqwhs2/s3jpY7+pcvVQxEpvVTId5byDxu1ujP4HjO/VTQ2P72rE8Ft
+C6J2Av0tAgMBAAGjUDBOMB0GA1UdDgQWBBTLT/RbyfBB/Pa07oBnaM+QSJPO9TAf
+BgNVHSMEGDAWgBTLT/RbyfBB/Pa07oBnaM+QSJPO9TAMBgNVHRMEBTADAQH/MA0G
+CSqGSIb3DQEBCwUAA4ICAQB3sCntCcQwhMgRPPyvOCMyTcQ/Iv+cpfxz2Ck14nlx
+AkEAH2CH0ov5GWTt07/ur3aa5x+SAKi0J3wTD1cdiw4U/6Uin6jWGKKxvoo4IaeK
+SbM8w/6eKx6UbmHx7PA/eRABY9tTlpdPCVgw7/o3WDr03QM+IAtatzvaCPPczake
+pbdLwmBZB/v8V+6jUajy6jOgdSH0PyffGnt7MWgDETmNC6p/Xigp5eh+C8Fb4NGT
+xgHES5PBC+sruWp4u22bJGDKTvYNdZHsnw/CaKQWNsQqwisxa3/8N5v+PCff/pxl
+r05pE3PdHn9JrCl4iWdVlgtiI9BoPtQyDfa/OEFaScE8KYR8LxaAgdgp3zYncWls
+BpwQ6Y/A2wIkhlD9eEp5Ib2hz7isXOs9UwjdriKqrBXqcIAE5M+YIk3+KAQKxAtd
+4YsK3CSJ010uphr12YKqlScj4vuKFjuOtd5RyyMIxUG3lrrhAu2AzCeKCLdVgA8+
+75FrYMApUdvcjp4uzbBoED4XRQlx9kdFHVbYgmE/+yddBYJM8u4YlgAL0hW2/D8p
+z9JWIfxVmjJnBnXaKGBuiUyZ864A3PJndP6EMMo7TzS2CDnfCYuJjvI0KvDjFNmc
+rQA04+qfMSEz3nmKhbbZu4eYLzlADhfH8tT4GMtXf71WLA5AUHGf2Y4+HIHTsmHG
+vQ==
+-----END CERTIFICATE-----
diff --git a/libgo/go/crypto/x509/testdata/test-dir.crt b/libgo/go/crypto/x509/testdata/test-dir.crt
new file mode 100644
index 0000000..b7fc9c5
--- /dev/null
+++ b/libgo/go/crypto/x509/testdata/test-dir.crt
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIJAL8a/lsnspOqMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV
+BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz
+dHMxETAPBgNVBAMMCHRlc3QtZGlyMB4XDTE3MDIwMTIzNTAyN1oXDTI3MDEzMDIz
+NTAyN1owTDELMAkGA1UEBhMCVUsxEzARBgNVBAgMClRlc3QtU3RhdGUxFTATBgNV
+BAoMDEdvbGFuZyBUZXN0czERMA8GA1UEAwwIdGVzdC1kaXIwggIiMA0GCSqGSIb3
+DQEBAQUAA4ICDwAwggIKAoICAQDzBoi43Yn30KN13PKFHu8LA4UmgCRToTukLItM
+WK2Je45grs/axg9n3YJOXC6hmsyrkOnyBcx1xVNgSrOAll7fSjtChRIX72Xrloxu
+XewtWVIrijqz6oylbvEmbRT3O8uynu5rF82Pmdiy8oiSfdywjKuPnE0hjV1ZSCql
+MYcXqA+f0JFD8kMv4pbtxjGH8f2DkYQz+hHXLrJH4/MEYdVMQXoz/GDzLyOkrXBN
+hpMaBBqg1p0P+tRdfLXuliNzA9vbZylzpF1YZ0gvsr0S5Y6LVtv7QIRygRuLY4kF
+k+UYuFq8NrV8TykS7FVnO3tf4XcYZ7r2KV5FjYSrJtNNo85BV5c3xMD3fJ2XcOWk
++oD1ATdgAM3aKmSOxNtNItKKxBe1mkqDH41NbWx7xMad78gDznyeT0tjEOltN2bM
+uXU1R/jgR/vq5Ec0AhXJyL/ziIcmuV2fSl/ZxT4ARD+16tgPiIx+welTf0v27/JY
+adlfkkL5XsPRrbSguISrj7JeaO/gjG3KnDVHcZvYBpDfHqRhCgrosfe26TZcTXx2
+cRxOfvBjMz1zJAg+esuUzSkerreyRhzD7RpeZTwi6sxvx82MhYMbA3w1LtgdABio
+9JRqZy3xqsIbNv7N46WO/qXL1UMRKb1UyHeW8g8btboz+B4zv1U0Nj+9qxPBbQui
+dgL9LQIDAQABo1AwTjAdBgNVHQ4EFgQUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwHwYD
+VR0jBBgwFoAUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwDAYDVR0TBAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAgEAvEVnUYsIOt87rggmLPqEueynkuQ+562M8EDHSQl82zbe
+xDCxeg3DvPgKb+RvaUdt1362z/szK10SoeMgx6+EQLoV9LiVqXwNqeYfixrhrdw3
+ppAhYYhymdkbUQCEMHypmXP1vPhAz4o8Bs+eES1M+zO6ErBiD7SqkmBElT+GixJC
+6epC9ZQFs+dw3lPlbiZSsGE85sqc3VAs0/JgpL/pb1/Eg4s0FUhZD2C2uWdSyZGc
+g0/v3aXJCp4j/9VoNhI1WXz3M45nysZIL5OQgXymLqJElQa1pZ3Wa4i/nidvT4AT
+Xlxc/qijM8set/nOqp7hVd5J0uG6qdwLRILUddZ6OpXd7ZNi1EXg+Bpc7ehzGsDt
+3UFGzYXDjxYnK2frQfjLS8stOQIqSrGthW6x0fdkVx0y8BByvd5J6+JmZl4UZfzA
+m99VxXSt4B9x6BvnY7ktzcFDOjtuLc4B/7yg9fv1eQuStA4cHGGAttsCg1X/Kx8W
+PvkkeH0UWDZ9vhH9K36703z89da6MWF+bz92B0+4HoOmlVaXRkvblsNaynJnL0LC
+Ayry7QBxuh5cMnDdRwJB3AVJIiJ1GVpb7aGvBOnx+s2lwRv9HWtghb+cbwwktx1M
+JHyBf3GZNSWTpKY7cD8V+NnBv3UuioOVVo+XAU4LF/bYUjdRpxWADJizNtZrtFo=
+-----END CERTIFICATE-----
diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go
index 29345a1..2b4f39d 100644
--- a/libgo/go/crypto/x509/verify.go
+++ b/libgo/go/crypto/x509/verify.go
@@ -87,7 +87,7 @@ func (h HostnameError) Error() string {
valid += san.String()
}
} else {
- if len(c.DNSNames) > 0 {
+ if c.hasSANExtension() {
valid = strings.Join(c.DNSNames, ", ")
} else {
valid = c.Subject.CommonName
@@ -166,7 +166,7 @@ const (
func matchNameConstraint(domain, constraint string) bool {
// The meaning of zero length constraints is not specified, but this
- // code follows NSS and accepts them as valid for everything.
+ // code follows NSS and accepts them as matching everything.
if len(constraint) == 0 {
return true
}
@@ -220,6 +220,12 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
}
}
+ for _, constraint := range c.ExcludedDNSDomains {
+ if matchNameConstraint(opts.DNSName, constraint) {
+ return CertificateInvalidError{c, CANotAuthorizedForThisName}
+ }
+ }
+
// KeyUsage status flags are ignored. From Engineering Security, Peter
// Gutmann: A European government CA marked its signing certificates as
// being valid for encryption only, but no-one noticed. Another
@@ -482,7 +488,7 @@ func (c *Certificate) VerifyHostname(h string) error {
lowered := toLowerCaseASCII(h)
- if len(c.DNSNames) > 0 {
+ if c.hasSANExtension() {
for _, match := range c.DNSNames {
if matchHostnames(toLowerCaseASCII(match), lowered) {
return nil
diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go
index 15c40914..335c477 100644
--- a/libgo/go/crypto/x509/verify_test.go
+++ b/libgo/go/crypto/x509/verify_test.go
@@ -263,6 +263,39 @@ var verifyTests = []verifyTest{
errorCallback: expectSubjectIssuerMismatcthError,
},
+ {
+ // An X.509 v1 certificate should not be accepted as an
+ // intermediate.
+ leaf: x509v1TestLeaf,
+ intermediates: []string{x509v1TestIntermediate},
+ roots: []string{x509v1TestRoot},
+ currentTime: 1481753183,
+ systemSkip: true,
+
+ errorCallback: expectNotAuthorizedError,
+ },
+ {
+ // If any SAN extension is present (even one without any DNS
+ // names), the CN should be ignored.
+ leaf: ignoreCNWithSANLeaf,
+ dnsName: "foo.example.com",
+ roots: []string{ignoreCNWithSANRoot},
+ currentTime: 1486684488,
+ systemSkip: true,
+
+ errorCallback: expectHostnameError,
+ },
+ {
+ // Test that excluded names are respected.
+ leaf: excludedNamesLeaf,
+ dnsName: "bender.local",
+ intermediates: []string{excludedNamesIntermediate},
+ roots: []string{excludedNamesRoot},
+ currentTime: 1486684488,
+ systemSkip: true,
+
+ errorCallback: expectNameConstraintsError,
+ },
}
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -330,6 +363,22 @@ func expectSubjectIssuerMismatcthError(t *testing.T, i int, err error) (ok bool)
return true
}
+func expectNameConstraintsError(t *testing.T, i int, err error) (ok bool) {
+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != CANotAuthorizedForThisName {
+ t.Errorf("#%d: error was not a CANotAuthorizedForThisName: %s", i, err)
+ return false
+ }
+ return true
+}
+
+func expectNotAuthorizedError(t *testing.T, i int, err error) (ok bool) {
+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NotAuthorizedToSign {
+ t.Errorf("#%d: error was not a NotAuthorizedToSign: %s", i, err)
+ return false
+ }
+ return true
+}
+
func certificateFromPEM(pemBytes string) (*Certificate, error) {
block, _ := pem.Decode([]byte(pemBytes))
if block == nil {
@@ -1269,6 +1318,174 @@ vEA4PCJprUYmoj3q9MKSSRYDlq5kIbl87mSRR4GqtAwJKxIasvOvULOxziQ=
-----END CERTIFICATE-----
`
+const x509v1TestRoot = `
+-----BEGIN CERTIFICATE-----
+MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE
+ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENBMB4XDTE1MDEwMTAwMDAwMFoXDTI1
+MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENB
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1
+siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw
++QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD
+JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE
+EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAcIwqeNUpQr9cOcYm
+YjpGpYkQ6b248xijCK7zI+lOeWN89zfSXn1AvfsC9pSdTMeDklWktbF/Ad0IN8Md
+h2NtN34ard0hEfHc8qW8mkXdsysVmq6cPvFYaHz+dBtkHuHDoy8YQnC0zdN/WyYB
+/1JmacUUofl+HusHuLkDxmadogI=
+-----END CERTIFICATE-----`
+
+const x509v1TestIntermediate = `
+-----BEGIN CERTIFICATE-----
+MIIByjCCATMCCQCCdEMsT8ykqTANBgkqhkiG9w0BAQsFADAjMQ8wDQYDVQQKEwZH
+b2xhbmcxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTUwMTAxMDAwMDAwWhcNMjUwMTAx
+MDAwMDAwWjAwMQ8wDQYDVQQKEwZHb2xhbmcxHTAbBgNVBAMTFFguNTA5djEgaW50
+ZXJtZWRpYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ2QyniAOT+5YL
+jeinEBJr3NsC/Q2QJ/VKmgvp+xRxuKTHJiVmxVijmp0vWg8AWfkmuE4p3hXQbbqM
+k5yxrk1n60ONhim2L4VXriEvCE7X2OXhTmBls5Ufr7aqIgPMikwjScCXwz8E8qI8
+UxyAhnjeJwMYBU8TuwBImSd4LBHoQQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAIab
+DRG6FbF9kL9jb/TDHkbVBk+sl/Pxi4/XjuFyIALlARgAkeZcPmL5tNW1ImHkwsHR
+zWE77kJDibzd141u21ZbLsKvEdUJXjla43bdyMmEqf5VGpC3D4sFt3QVH7lGeRur
+x5Wlq1u3YDL/j6s1nU2dQ3ySB/oP7J+vQ9V4QeM+
+-----END CERTIFICATE-----`
+
+const x509v1TestLeaf = `
+-----BEGIN CERTIFICATE-----
+MIICMzCCAZygAwIBAgIJAPo99mqJJrpJMA0GCSqGSIb3DQEBCwUAMDAxDzANBgNV
+BAoTBkdvbGFuZzEdMBsGA1UEAxMUWC41MDl2MSBpbnRlcm1lZGlhdGUwHhcNMTUw
+MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjArMQ8wDQYDVQQKEwZHb2xhbmcxGDAW
+BgNVBAMTD2Zvby5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEApUh60Z+a5/oKJxG//Dn8CihSo2CJHNIIO3zEJZ1EeNSMZCynaIR6D3IPZEIR
++RG2oGt+f5EEukAPYxwasp6VeZEezoQWJ+97nPCT6DpwLlWp3i2MF8piK2R9vxkG
+Z5n0+HzYk1VM8epIrZFUXSMGTX8w1y041PX/yYLxbdEifdcCAwEAAaNaMFgwDgYD
+VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNV
+HRMBAf8EAjAAMBkGA1UdDgQSBBBFozXe0SnzAmjy+1U6M/cvMA0GCSqGSIb3DQEB
+CwUAA4GBADYzYUvaToO/ucBskPdqXV16AaakIhhSENswYVSl97/sODaxsjishKq9
+5R7siu+JnIFotA7IbBe633p75xEnLN88X626N/XRFG9iScLzpj0o0PWXBUiB+fxL
+/jt8qszOXCv2vYdUTPNuPqufXLWMoirpuXrr1liJDmedCcAHepY/
+-----END CERTIFICATE-----`
+
+const ignoreCNWithSANRoot = `
+-----BEGIN CERTIFICATE-----
+MIIDPzCCAiegAwIBAgIIJkzCwkNrPHMwDQYJKoZIhvcNAQELBQAwMDEQMA4GA1UE
+ChMHVEVTVElORzEcMBoGA1UEAxMTKipUZXN0aW5nKiogUm9vdCBDQTAeFw0xNTAx
+MDEwMDAwMDBaFw0yNTAxMDEwMDAwMDBaMDAxEDAOBgNVBAoTB1RFU1RJTkcxHDAa
+BgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQC4YAf5YqlXGcikvbMWtVrNICt+V/NNWljwfvSKdg4Inm7k6BwW
+P6y4Y+n4qSYIWNU4iRkdpajufzctxQCO6ty13iw3qVktzcC5XBIiS6ymiRhhDgnY
+VQqyakVGw9MxrPwdRZVlssUv3Hmy6tU+v5Ok31SLY5z3wKgYWvSyYs0b8bKNU8kf
+2FmSHnBN16lxGdjhe3ji58F/zFMr0ds+HakrLIvVdFcQFAnQopM8FTHpoWNNzGU3
+KaiO0jBbMFkd6uVjVnuRJ+xjuiqi/NWwiwQA+CEr9HKzGkxOF8nAsHamdmO1wW+w
+OsCrC0qWQ/f5NTOVATTJe0vj88OMTvo3071VAgMBAAGjXTBbMA4GA1UdDwEB/wQE
+AwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUw
+AwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOC
+AQEAGOn3XjxHyHbXLKrRmpwV447B7iNBXR5VlhwOgt1kWaHDL2+8f/9/h0HMkB6j
+fC+/yyuYVqYuOeavqMGVrh33D2ODuTQcFlOx5lXukP46j3j+Lm0jjZ1qNX7vlP8I
+VlUXERhbelkw8O4oikakwIY9GE8syuSgYf+VeBW/lvuAZQrdnPfabxe05Tre6RXy
+nJHMB1q07YHpbwIkcV/lfCE9pig2nPXTLwYZz9cl46Ul5RCpPUi+IKURo3x8y0FU
+aSLjI/Ya0zwUARMmyZ3RRGCyhIarPb20mKSaMf1/Nb23pS3k1QgmZhk5pAnXYsWu
+BJ6bvwEAasFiLGP6Zbdmxb2hIA==
+-----END CERTIFICATE-----`
+
+const ignoreCNWithSANLeaf = `
+-----BEGIN CERTIFICATE-----
+MIIDaTCCAlGgAwIBAgIJAONakvRTxgJhMA0GCSqGSIb3DQEBCwUAMDAxEDAOBgNV
+BAoTB1RFU1RJTkcxHDAaBgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwHhcNMTUw
+MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjAsMRAwDgYDVQQKEwdURVNUSU5HMRgw
+FgYDVQQDEw9mb28uZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDBqskp89V/JMIBBqcauKSOVLcMyIE/t0jgSWVrsI4sksBTabLsfMdS
+ui2n+dHQ1dRBuw3o4g4fPrWwS3nMnV3pZUHEn2TPi5N1xkjTaxObXgKIY2GKmFP3
+rJ9vYqHT6mT4K93kCHoRcmJWWySc7S3JAOhTcdB4G+tIdQJN63E+XRYQQfNrn5HZ
+hxQoOzaguHFx+ZGSD4Ntk6BSZz5NfjqCYqYxe+iCpTpEEYhIpi8joSPSmkTMTxBW
+S1W2gXbYNQ9KjNkGM6FnQsUJrSPMrWs4v3UB/U88N5LkZeF41SqD9ySFGwbGajFV
+nyzj12+4K4D8BLhlOc0Eo/F/8GwOwvmxAgMBAAGjgYkwgYYwDgYDVR0PAQH/BAQD
+AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAA
+MBkGA1UdDgQSBBCjeab27q+5pV43jBGANOJ1MBsGA1UdIwQUMBKAEEA31wH7QC+4
+HH5UBCeMWQEwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAGZfZ
+ErTVxxpIg64s22mQpXSk/72THVQsfsKHzlXmztM0CJzH8ccoN67ZqKxJCfdiE/FI
+Emb6BVV4cGPeIKpcxaM2dwX/Y+Y0JaxpQJvqLxs+EByRL0gPP3shgg86WWCjYLxv
+AgOn862d/JXGDrC9vIlQ/DDQcyL5g0JV5UjG2G9TUigbnrXxBw7BoWK6wmoSaHnR
+sZKEHSs3RUJvm7qqpA9Yfzm9jg+i9j32zh1xFacghAOmFRFXa9eCVeigZ/KK2mEY
+j2kBQyvnyKsXHLAKUoUOpd6t/1PHrfXnGj+HmzZNloJ/BZ1kiWb4eLvMljoLGkZn
+xZbqP3Krgjj4XNaXjg==
+-----END CERTIFICATE-----`
+
+const excludedNamesLeaf = `
+-----BEGIN CERTIFICATE-----
+MIID4DCCAsigAwIBAgIHDUSFtJknhzANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UE
+BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
+MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
+ICgzNzM0NTE1NTYyODA2Mzk3KTEhMB8GA1UEAwwYSW50ZXJtZWRpYXRlIENBIGZv
+ciAzMzkyMB4XDTE3MDIwODIxMTUwNFoXDTE4MDIwODIwMjQ1OFowgZAxCzAJBgNV
+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlMb3MgR2F0b3Mx
+FDASBgNVBAoMC05ldGZsaXggSW5jMS0wKwYDVQQLDCRQbGF0Zm9ybSBTZWN1cml0
+eSAoMzczNDUxNTc0ODUwMjY5NikxEzARBgNVBAMMCjE3Mi4xNi4wLjEwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ0oP1bMv6bOeqcKbzinnGpNOpenhA
+zdFFsgea62znWsH3Wg4+1Md8uPCqlaQIsaJQKZHc50eKD3bg0Io7c6kxHkBQr1b8
+Q7cGeK3CjdqG3NwS/aizzrLKOwL693hFwwy7JY7GGCvogbhyQRKn6iV0U9zMm7bu
+/9pQVV/wx8u01u2uAlLttjyQ5LJkxo5t8cATFVqxdN5J9eY//VSDiTwXnlpQITBP
+/Ow+zYuZ3kFlzH3CtCOhOEvNG3Ar1NvP3Icq35PlHV+Eki4otnKfixwByoiGpqCB
+UEIY04VrZJjwBxk08y/3jY2B3VLYGgi+rryyCxIqkB7UpSNPMMWSG4UpAgMBAAGj
+LzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0RBBYwFIIMYmVuZGVyLmxvY2FshwSsEAAB
+MA0GCSqGSIb3DQEBCwUAA4IBAQCLW3JO8L7LKByjzj2RciPjCGH5XF87Wd20gYLq
+sNKcFwCIeyZhnQy5aZ164a5G9AIk2HLvH6HevBFPhA9Ivmyv/wYEfnPd1VcFkpgP
+hDt8MCFJ8eSjCyKdtZh1MPMLrLVymmJV+Rc9JUUYM9TIeERkpl0rskcO1YGewkYt
+qKlWE+0S16+pzsWvKn831uylqwIb8ANBPsCX4aM4muFBHavSWAHgRO+P+yXVw8Q+
+VQDnMHUe5PbZd1/+1KKVs1K/CkBCtoHNHp1d/JT+2zUQJphwja9CcgfFdVhSnHL4
+oEEOFtqVMIuQfR2isi08qW/JGOHc4sFoLYB8hvdaxKWSE19A
+-----END CERTIFICATE-----
+`
+
+const excludedNamesIntermediate = `
+-----BEGIN CERTIFICATE-----
+MIIDzTCCArWgAwIBAgIHDUSFqYeczDANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UE
+BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
+MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
+ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBmb3IgMzM5
+MjAeFw0xNzAyMDgyMTE1MDRaFw0xODAyMDgyMDI0NThaMIGeMQswCQYDVQQGEwJV
+UzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJTG9zIEdhdG9zMRQwEgYD
+VQQKDAtOZXRmbGl4IEluYzEtMCsGA1UECwwkUGxhdGZvcm0gU2VjdXJpdHkgKDM3
+MzQ1MTU1NjI4MDYzOTcpMSEwHwYDVQQDDBhJbnRlcm1lZGlhdGUgQ0EgZm9yIDMz
+OTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCOyEs6tJ/t9emQTvlx
+3FS7uJSou5rKkuqVxZdIuYQ+B2ZviBYUnMRT9bXDB0nsVdKZdp0hdchdiwNXDG/I
+CiWu48jkcv/BdynVyayOT+0pOJSYLaPYpzBx1Pb9M5651ct9GSbj6Tz0ChVonoIE
+1AIZ0kkebucZRRFHd0xbAKVRKyUzPN6HJ7WfgyauUp7RmlC35wTmrmARrFohQLlL
+7oICy+hIQePMy9x1LSFTbPxZ5AUUXVC3eUACU3vLClF/Xs8XGHebZpUXCdMQjOGS
+nq1eFguFHR1poSB8uSmmLqm4vqUH9CDhEgiBAC8yekJ8//kZQ7lUEqZj3YxVbk+Y
+E4H5AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+ADxrnmNX5gWChgX9K5fYwhFDj5ofxZXAKVQk+WjmkwMcmCx3dtWSm++Wdksj/ZlA
+V1cLW3ohWv1/OAZuOlw7sLf98aJpX+UUmIYYQxDubq+4/q7VA7HzEf2k/i/oN1NI
+JgtrhpPcZ/LMO6k7DYx0qlfYq8pTSfd6MI4LnWKgLc+JSPJJjmvspgio2ZFcnYr7
+A264BwLo6v1Mos1o1JUvFFcp4GANlw0XFiWh7JXYRl8WmS5DoouUC+aNJ3lmyF6z
+LbIjZCSfgZnk/LK1KU1j91FI2bc2ULYZvAC1PAg8/zvIgxn6YM2Q7ZsdEgWw0FpS
+zMBX1/lk4wkFckeUIlkD55Y=
+-----END CERTIFICATE-----`
+
+const excludedNamesRoot = `
+-----BEGIN CERTIFICATE-----
+MIIEGTCCAwGgAwIBAgIHDUSFpInn/zANBgkqhkiG9w0BAQsFADCBozELMAkGA1UE
+BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
+MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
+ICgzNzMxNTA5NDM3NDYyNDg1KTEmMCQGA1UEAwwdTmFtZSBDb25zdHJhaW50cyBU
+ZXN0IFJvb3QgQ0EwHhcNMTcwMjA4MjExNTA0WhcNMTgwMjA4MjAyNDU4WjCBmTEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBH
+YXRvczEUMBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNl
+Y3VyaXR5ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBm
+b3IgMzM5MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJymcnX29ekc
+7+MLyr8QuAzoHWznmGdDd2sITwWRjM89/21cdlHCGKSpULUNdFp9HDLWvYECtxt+
+8TuzKiQz7qAerzGUT1zI5McIjHy0e/i4xIkfiBiNeTCuB/N9QRbZlcfM80ErkaA4
+gCAFK8qZAcWkHIl6e+KaQFMPLKk9kckgAnVDHEJe8oLNCogCJ15558b65g05p9eb
+5Lg+E98hoPRTQaDwlz3CZPfTTA2EiEZInSi8qzodFCbTpJUVTbiVUH/JtVjlibbb
+smdcx5PORK+8ZJkhLEh54AjaWOX4tB/7Tkk8stg2VBmrIARt/j4UVj7cTrIWU3bV
+m8TwHJG+YgsCAwEAAaNaMFgwDwYDVR0TAQH/BAUwAwEB/zBFBgNVHR4EPjA8oBww
+CocICgEAAP//AAAwDoIMYmVuZGVyLmxvY2FsoRwwCocICgEAAP//AAAwDoIMYmVu
+ZGVyLmxvY2FsMA0GCSqGSIb3DQEBCwUAA4IBAQAMjbheffPxtSKSv9NySW+8qmHs
+n7Mb5GGyCFu+cMZSoSaabstbml+zHEFJvWz6/1E95K4F8jKhAcu/CwDf4IZrSD2+
+Hee0DolVSQhZpnHgPyj7ZATz48e3aJaQPUlhCEOh0wwF4Y0N4FV0t7R6woLylYRZ
+yU1yRHUqUYpN0DWFpsPbBqgM6uUAVO2ayBFhPgWUaqkmSbZ/Nq7isGvknaTmcIwT
+6mOAFN0qFb4RGzfGJW7x6z7KCULS7qVDp6fU3tRoScHFEgRubks6jzQ1W5ooSm4o
++NQCZDd5eFeU8PpNX7rgaYE4GPq+EEmLVCBYmdctr8QVdqJ//8Xu3+1phjDy
+-----END CERTIFICATE-----`
+
var unknownAuthorityErrorTests = []struct {
cert string
expected string
@@ -1294,7 +1511,7 @@ func TestUnknownAuthorityError(t *testing.T) {
hintCert: c,
}
actual := uae.Error()
- if strings.Compare(actual, tt.expected) != 0 {
+ if actual != tt.expected {
t.Errorf("#%d: UnknownAuthorityError.Error() response invalid actual: %s expected: %s", i, actual, tt.expected)
}
}
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index 949ce01..fdc7c53 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -3,6 +3,10 @@
// license that can be found in the LICENSE file.
// Package x509 parses X.509-encoded keys and certificates.
+//
+// On UNIX systems the environment variables SSL_CERT_FILE and SSL_CERT_DIR
+// can be used to override the system default locations for the SSL certificate
+// file and SSL certificate files directory, respectively.
package x509
import (
@@ -59,7 +63,7 @@ func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) {
func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) {
switch pub := pub.(type) {
case *rsa.PublicKey:
- publicKeyBytes, err = asn1.Marshal(rsaPublicKey{
+ publicKeyBytes, err = asn1.Marshal(pkcs1PublicKey{
N: pub.N,
E: pub.E,
})
@@ -69,9 +73,7 @@ func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorith
publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
// This is a NULL parameters value which is required by
// https://tools.ietf.org/html/rfc3279#section-2.3.1.
- publicKeyAlgorithm.Parameters = asn1.RawValue{
- Tag: 5,
- }
+ publicKeyAlgorithm.Parameters = asn1.NullRawValue
case *ecdsa.PublicKey:
publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
oid, ok := oidFromNamedCurve(pub.Curve)
@@ -355,10 +357,8 @@ func rsaPSSParameters(hashFunc crypto.Hash) asn1.RawValue {
params := pssParameters{
Hash: pkix.AlgorithmIdentifier{
- Algorithm: hashOID,
- Parameters: asn1.RawValue{
- Tag: 5, /* ASN.1 NULL */
- },
+ Algorithm: hashOID,
+ Parameters: asn1.NullRawValue,
},
MGF: pkix.AlgorithmIdentifier{
Algorithm: oidMGF1,
@@ -368,10 +368,8 @@ func rsaPSSParameters(hashFunc crypto.Hash) asn1.RawValue {
}
mgf1Params := pkix.AlgorithmIdentifier{
- Algorithm: hashOID,
- Parameters: asn1.RawValue{
- Tag: 5, /* ASN.1 NULL */
- },
+ Algorithm: hashOID,
+ Parameters: asn1.NullRawValue,
}
var err error
@@ -418,11 +416,10 @@ func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm
// https://tools.ietf.org/html/rfc3447#section-8.1), that the
// salt length matches the hash length, and that the trailer
// field has the default value.
- asn1NULL := []byte{0x05, 0x00}
- if !bytes.Equal(params.Hash.Parameters.FullBytes, asn1NULL) ||
+ if !bytes.Equal(params.Hash.Parameters.FullBytes, asn1.NullBytes) ||
!params.MGF.Algorithm.Equal(oidMGF1) ||
!mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) ||
- !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1NULL) ||
+ !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1.NullBytes) ||
params.TrailerField != 1 {
return UnknownSignatureAlgorithm
}
@@ -668,13 +665,28 @@ type Certificate struct {
ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages.
UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package.
- BasicConstraintsValid bool // if true then the next two fields are valid.
+ // BasicConstraintsValid indicates whether IsCA, MaxPathLen,
+ // and MaxPathLenZero are valid.
+ BasicConstraintsValid bool
IsCA bool
- MaxPathLen int
- // MaxPathLenZero indicates that BasicConstraintsValid==true and
- // MaxPathLen==0 should be interpreted as an actual maximum path length
- // of zero. Otherwise, that combination is interpreted as MaxPathLen
- // not being set.
+
+ // MaxPathLen and MaxPathLenZero indicate the presence and
+ // value of the BasicConstraints' "pathLenConstraint".
+ //
+ // When parsing a certificate, a positive non-zero MaxPathLen
+ // means that the field was specified, -1 means it was unset,
+ // and MaxPathLenZero being true mean that the field was
+ // explicitly set to zero. The case of MaxPathLen==0 with MaxPathLenZero==false
+ // should be treated equivalent to -1 (unset).
+ //
+ // When generating a certificate, an unset pathLenConstraint
+ // can be requested with either MaxPathLen == -1 or using the
+ // zero value for both MaxPathLen and MaxPathLenZero.
+ MaxPathLen int
+ // MaxPathLenZero indicates that BasicConstraintsValid==true
+ // and MaxPathLen==0 should be interpreted as an actual
+ // maximum path length of zero. Otherwise, that combination is
+ // interpreted as MaxPathLen not being set.
MaxPathLenZero bool
SubjectKeyId []byte
@@ -692,6 +704,7 @@ type Certificate struct {
// Name constraints
PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
PermittedDNSDomains []string
+ ExcludedDNSDomains []string
// CRL Distribution Points
CRLDistributionPoints []string
@@ -723,6 +736,10 @@ func (c *Certificate) Equal(other *Certificate) bool {
return bytes.Equal(c.Raw, other.Raw)
}
+func (c *Certificate) hasSANExtension() bool {
+ return oidInExtensions(oidExtensionSubjectAltName, c.Extensions)
+}
+
// Entrust have a broken root certificate (CN=Entrust.net Certification
// Authority (2048)) which isn't marked as a CA certificate and is thus invalid
// according to PKIX.
@@ -924,20 +941,17 @@ type distributionPointName struct {
RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
}
-// asn1Null is the ASN.1 encoding of a NULL value.
-var asn1Null = []byte{5, 0}
-
func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
asn1Data := keyData.PublicKey.RightAlign()
switch algo {
case RSA:
// RSA public keys must have a NULL in the parameters
// (https://tools.ietf.org/html/rfc3279#section-2.3.1).
- if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1Null) {
+ if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1.NullBytes) {
return nil, errors.New("x509: RSA key missing NULL parameters")
}
- p := new(rsaPublicKey)
+ p := new(pkcs1PublicKey)
rest, err := asn1.Unmarshal(asn1Data, p)
if err != nil {
return nil, err
@@ -1150,7 +1164,7 @@ func parseCertificate(in *certificate) (*Certificate, error) {
out.IsCA = constraints.IsCA
out.MaxPathLen = constraints.MaxPathLen
out.MaxPathLenZero = out.MaxPathLen == 0
-
+ // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285)
case 17:
out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(e.Value)
if err != nil {
@@ -1185,19 +1199,27 @@ func parseCertificate(in *certificate) (*Certificate, error) {
return nil, errors.New("x509: trailing data after X.509 NameConstraints")
}
- if len(constraints.Excluded) > 0 && e.Critical {
- return out, UnhandledCriticalExtension{}
- }
-
- for _, subtree := range constraints.Permitted {
- if len(subtree.Name) == 0 {
- if e.Critical {
- return out, UnhandledCriticalExtension{}
+ getDNSNames := func(subtrees []generalSubtree, isCritical bool) (dnsNames []string, err error) {
+ for _, subtree := range subtrees {
+ if len(subtree.Name) == 0 {
+ if isCritical {
+ return nil, UnhandledCriticalExtension{}
+ }
+ continue
}
- continue
+ dnsNames = append(dnsNames, subtree.Name)
}
- out.PermittedDNSDomains = append(out.PermittedDNSDomains, subtree.Name)
+
+ return dnsNames, nil
+ }
+
+ if out.PermittedDNSDomains, err = getDNSNames(constraints.Permitted, e.Critical); err != nil {
+ return out, err
+ }
+ if out.ExcludedDNSDomains, err = getDNSNames(constraints.Excluded, e.Critical); err != nil {
+ return out, err
}
+ out.PermittedDNSDomainsCritical = e.Critical
case 31:
// RFC 5280, 4.2.1.13
@@ -1451,7 +1473,7 @@ func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP) (derBy
return asn1.Marshal(rawValues)
}
-func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
+func buildExtensions(template *Certificate, authorityKeyId []byte) (ret []pkix.Extension, err error) {
ret = make([]pkix.Extension, 10 /* maximum number of elements. */)
n := 0
@@ -1525,9 +1547,9 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.AuthorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) {
+ if len(authorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) {
ret[n].Id = oidExtensionAuthorityKeyId
- ret[n].Value, err = asn1.Marshal(authKeyId{template.AuthorityKeyId})
+ ret[n].Value, err = asn1.Marshal(authKeyId{authorityKeyId})
if err != nil {
return
}
@@ -1581,16 +1603,22 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
n++
}
- if len(template.PermittedDNSDomains) > 0 &&
+ if (len(template.PermittedDNSDomains) > 0 || len(template.ExcludedDNSDomains) > 0) &&
!oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) {
ret[n].Id = oidExtensionNameConstraints
ret[n].Critical = template.PermittedDNSDomainsCritical
var out nameConstraints
+
out.Permitted = make([]generalSubtree, len(template.PermittedDNSDomains))
for i, permitted := range template.PermittedDNSDomains {
out.Permitted[i] = generalSubtree{Name: permitted}
}
+ out.Excluded = make([]generalSubtree, len(template.ExcludedDNSDomains))
+ for i, excluded := range template.ExcludedDNSDomains {
+ out.Excluded[i] = generalSubtree{Name: excluded}
+ }
+
ret[n].Value, err = asn1.Marshal(out)
if err != nil {
return
@@ -1646,9 +1674,7 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori
pubType = RSA
hashFunc = crypto.SHA256
sigAlgo.Algorithm = oidSignatureSHA256WithRSA
- sigAlgo.Parameters = asn1.RawValue{
- Tag: 5,
- }
+ sigAlgo.Parameters = asn1.NullRawValue
case *ecdsa.PublicKey:
pubType = ECDSA
@@ -1706,11 +1732,12 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori
return
}
-// CreateCertificate creates a new certificate based on a template. The
-// following members of template are used: SerialNumber, Subject, NotBefore,
-// NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
-// IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
-// PermittedDNSDomains, SignatureAlgorithm.
+// CreateCertificate creates a new certificate based on a template.
+// The following members of template are used: AuthorityKeyId,
+// BasicConstraintsValid, DNSNames, ExcludedDNSDomains, ExtKeyUsage,
+// IsCA, KeyUsage, MaxPathLen, MaxPathLenZero, NotAfter, NotBefore,
+// PermittedDNSDomains, PermittedDNSDomainsCritical, SerialNumber,
+// SignatureAlgorithm, Subject, SubjectKeyId, and UnknownExtKeyUsage.
//
// The certificate is signed by parent. If parent is equal to template then the
// certificate is self-signed. The parameter pub is the public key of the
@@ -1720,6 +1747,10 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori
//
// All keys types that are implemented via crypto.Signer are supported (This
// includes *rsa.PublicKey and *ecdsa.PublicKey.)
+//
+// The AuthorityKeyId will be taken from the SubjectKeyId of parent, if any,
+// unless the resulting certificate is self-signed. Otherwise the value from
+// template will be used.
func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) (cert []byte, err error) {
key, ok := priv.(crypto.Signer)
if !ok {
@@ -1750,11 +1781,12 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
return
}
+ authorityKeyId := template.AuthorityKeyId
if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 {
- template.AuthorityKeyId = parent.SubjectKeyId
+ authorityKeyId = parent.SubjectKeyId
}
- extensions, err := buildExtensions(template)
+ extensions, err := buildExtensions(template, authorityKeyId)
if err != nil {
return
}
@@ -2025,10 +2057,10 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error)
return ret, nil
}
-// CreateCertificateRequest creates a new certificate request based on a template.
-// The following members of template are used: Subject, Attributes,
-// SignatureAlgorithm, Extensions, DNSNames, EmailAddresses, and IPAddresses.
-// The private key is the private key of the signer.
+// CreateCertificateRequest creates a new certificate request based on a
+// template. The following members of template are used: Attributes, DNSNames,
+// EmailAddresses, ExtraExtensions, IPAddresses, SignatureAlgorithm, and
+// Subject. The private key is the private key of the signer.
//
// The returned slice is the certificate request in DER encoding.
//
diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go
index b085dad..2d1acf9 100644
--- a/libgo/go/crypto/x509/x509_test.go
+++ b/libgo/go/crypto/x509/x509_test.go
@@ -405,6 +405,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
PermittedDNSDomains: []string{".example.com", "example.com"},
+ ExcludedDNSDomains: []string{"bar.example.com"},
CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
@@ -442,6 +443,10 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
t.Errorf("%s: failed to parse name constraints: %#v", test.name, cert.PermittedDNSDomains)
}
+ if len(cert.ExcludedDNSDomains) != 1 || cert.ExcludedDNSDomains[0] != "bar.example.com" {
+ t.Errorf("%s: failed to parse name constraint exclusions: %#v", test.name, cert.ExcludedDNSDomains)
+ }
+
if cert.Subject.CommonName != commonName {
t.Errorf("%s: subject wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Subject.CommonName, commonName)
}
diff --git a/libgo/go/database/sql/convert.go b/libgo/go/database/sql/convert.go
index ea2f377..4983181 100644
--- a/libgo/go/database/sql/convert.go
+++ b/libgo/go/database/sql/convert.go
@@ -12,6 +12,7 @@ import (
"fmt"
"reflect"
"strconv"
+ "sync"
"time"
"unicode"
"unicode/utf8"
@@ -37,86 +38,180 @@ func validateNamedValueName(name string) error {
return fmt.Errorf("name %q does not begin with a letter", name)
}
+func driverNumInput(ds *driverStmt) int {
+ ds.Lock()
+ defer ds.Unlock() // in case NumInput panics
+ return ds.si.NumInput()
+}
+
+// ccChecker wraps the driver.ColumnConverter and allows it to be used
+// as if it were a NamedValueChecker. If the driver ColumnConverter
+// is not present then the NamedValueChecker will return driver.ErrSkip.
+type ccChecker struct {
+ sync.Locker
+ cci driver.ColumnConverter
+ want int
+}
+
+func (c ccChecker) CheckNamedValue(nv *driver.NamedValue) error {
+ if c.cci == nil {
+ return driver.ErrSkip
+ }
+ // The column converter shouldn't be called on any index
+ // it isn't expecting. The final error will be thrown
+ // in the argument converter loop.
+ index := nv.Ordinal - 1
+ if c.want <= index {
+ return nil
+ }
+
+ // First, see if the value itself knows how to convert
+ // itself to a driver type. For example, a NullString
+ // struct changing into a string or nil.
+ if vr, ok := nv.Value.(driver.Valuer); ok {
+ sv, err := callValuerValue(vr)
+ if err != nil {
+ return err
+ }
+ if !driver.IsValue(sv) {
+ return fmt.Errorf("non-subset type %T returned from Value", sv)
+ }
+ nv.Value = sv
+ }
+
+ // Second, ask the column to sanity check itself. For
+ // example, drivers might use this to make sure that
+ // an int64 values being inserted into a 16-bit
+ // integer field is in range (before getting
+ // truncated), or that a nil can't go into a NOT NULL
+ // column before going across the network to get the
+ // same error.
+ var err error
+ arg := nv.Value
+ c.Lock()
+ nv.Value, err = c.cci.ColumnConverter(index).ConvertValue(arg)
+ c.Unlock()
+ if err != nil {
+ return err
+ }
+ if !driver.IsValue(nv.Value) {
+ return fmt.Errorf("driver ColumnConverter error converted %T to unsupported type %T", arg, nv.Value)
+ }
+ return nil
+}
+
+// defaultCheckNamedValue wraps the default ColumnConverter to have the same
+// function signature as the CheckNamedValue in the driver.NamedValueChecker
+// interface.
+func defaultCheckNamedValue(nv *driver.NamedValue) (err error) {
+ nv.Value, err = driver.DefaultParameterConverter.ConvertValue(nv.Value)
+ return err
+}
+
// driverArgs converts arguments from callers of Stmt.Exec and
// Stmt.Query into driver Values.
//
// The statement ds may be nil, if no statement is available.
-func driverArgs(ds *driverStmt, args []interface{}) ([]driver.NamedValue, error) {
+func driverArgs(ci driver.Conn, ds *driverStmt, args []interface{}) ([]driver.NamedValue, error) {
nvargs := make([]driver.NamedValue, len(args))
+
+ // -1 means the driver doesn't know how to count the number of
+ // placeholders, so we won't sanity check input here and instead let the
+ // driver deal with errors.
+ want := -1
+
var si driver.Stmt
+ var cc ccChecker
if ds != nil {
si = ds.si
+ want = driverNumInput(ds)
+ cc.Locker = ds.Locker
+ cc.want = want
}
- cc, ok := si.(driver.ColumnConverter)
- // Normal path, for a driver.Stmt that is not a ColumnConverter.
+ // Check all types of interfaces from the start.
+ // Drivers may opt to use the NamedValueChecker for special
+ // argument types, then return driver.ErrSkip to pass it along
+ // to the column converter.
+ nvc, ok := si.(driver.NamedValueChecker)
if !ok {
- for n, arg := range args {
- var err error
- nv := &nvargs[n]
- nv.Ordinal = n + 1
- if np, ok := arg.(NamedArg); ok {
- if err := validateNamedValueName(np.Name); err != nil {
- return nil, err
- }
- arg = np.Value
- nvargs[n].Name = np.Name
- }
- nv.Value, err = driver.DefaultParameterConverter.ConvertValue(arg)
-
- if err != nil {
- return nil, fmt.Errorf("sql: converting Exec argument %s type: %v", describeNamedValue(nv), err)
- }
- }
- return nvargs, nil
+ nvc, ok = ci.(driver.NamedValueChecker)
+ }
+ cci, ok := si.(driver.ColumnConverter)
+ if ok {
+ cc.cci = cci
}
- // Let the Stmt convert its own arguments.
- for n, arg := range args {
+ // Loop through all the arguments, checking each one.
+ // If no error is returned simply increment the index
+ // and continue. However if driver.ErrRemoveArgument
+ // is returned the argument is not included in the query
+ // argument list.
+ var err error
+ var n int
+ for _, arg := range args {
nv := &nvargs[n]
- nv.Ordinal = n + 1
if np, ok := arg.(NamedArg); ok {
- if err := validateNamedValueName(np.Name); err != nil {
+ if err = validateNamedValueName(np.Name); err != nil {
return nil, err
}
arg = np.Value
nv.Name = np.Name
}
- // First, see if the value itself knows how to convert
- // itself to a driver type. For example, a NullString
- // struct changing into a string or nil.
- if vr, ok := arg.(driver.Valuer); ok {
- sv, err := callValuerValue(vr)
- if err != nil {
- return nil, fmt.Errorf("sql: argument %s from Value: %v", describeNamedValue(nv), err)
- }
- if !driver.IsValue(sv) {
- return nil, fmt.Errorf("sql: argument %s: non-subset type %T returned from Value", describeNamedValue(nv), sv)
- }
- arg = sv
+ nv.Ordinal = n + 1
+ nv.Value = arg
+
+ // Checking sequence has four routes:
+ // A: 1. Default
+ // B: 1. NamedValueChecker 2. Column Converter 3. Default
+ // C: 1. NamedValueChecker 3. Default
+ // D: 1. Column Converter 2. Default
+ //
+ // The only time a Column Converter is called is first
+ // or after NamedValueConverter. If first it is handled before
+ // the nextCheck label. Thus for repeats tries only when the
+ // NamedValueConverter is selected should the Column Converter
+ // be used in the retry.
+ checker := defaultCheckNamedValue
+ nextCC := false
+ switch {
+ case nvc != nil:
+ nextCC = cci != nil
+ checker = nvc.CheckNamedValue
+ case cci != nil:
+ checker = cc.CheckNamedValue
}
- // Second, ask the column to sanity check itself. For
- // example, drivers might use this to make sure that
- // an int64 values being inserted into a 16-bit
- // integer field is in range (before getting
- // truncated), or that a nil can't go into a NOT NULL
- // column before going across the network to get the
- // same error.
- var err error
- ds.Lock()
- nv.Value, err = cc.ColumnConverter(n).ConvertValue(arg)
- ds.Unlock()
- if err != nil {
+ nextCheck:
+ err = checker(nv)
+ switch err {
+ case nil:
+ n++
+ continue
+ case driver.ErrRemoveArgument:
+ nvargs = nvargs[:len(nvargs)-1]
+ continue
+ case driver.ErrSkip:
+ if nextCC {
+ nextCC = false
+ checker = cc.CheckNamedValue
+ } else {
+ checker = defaultCheckNamedValue
+ }
+ goto nextCheck
+ default:
return nil, fmt.Errorf("sql: converting argument %s type: %v", describeNamedValue(nv), err)
}
- if !driver.IsValue(nv.Value) {
- return nil, fmt.Errorf("sql: for argument %s, driver ColumnConverter error converted %T to unsupported type %T",
- describeNamedValue(nv), arg, nv.Value)
- }
+ }
+
+ // Check the length of arguments after convertion to allow for omitted
+ // arguments.
+ if want != -1 && len(nvargs) != want {
+ return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(nvargs))
}
return nvargs, nil
+
}
// convertAssign copies to dest the value in src, converting it if possible.
@@ -270,6 +365,11 @@ func convertAssign(dest, src interface{}) error {
return nil
}
+ // The following conversions use a string value as an intermediate representation
+ // to convert between various numeric types.
+ //
+ // This also allows scanning into user defined types such as "type Int int64".
+ // For symmetry, also check for string destination types.
switch dv.Kind() {
case reflect.Ptr:
if src == nil {
@@ -306,6 +406,15 @@ func convertAssign(dest, src interface{}) error {
}
dv.SetFloat(f64)
return nil
+ case reflect.String:
+ switch v := src.(type) {
+ case string:
+ dv.SetString(v)
+ return nil
+ case []byte:
+ dv.SetString(string(v))
+ return nil
+ }
}
return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
diff --git a/libgo/go/database/sql/convert_test.go b/libgo/go/database/sql/convert_test.go
index 4dfab1f..cfe52d7 100644
--- a/libgo/go/database/sql/convert_test.go
+++ b/libgo/go/database/sql/convert_test.go
@@ -10,6 +10,7 @@ import (
"reflect"
"runtime"
"strings"
+ "sync"
"testing"
"time"
)
@@ -17,9 +18,11 @@ import (
var someTime = time.Unix(123, 0)
var answer int64 = 42
-type userDefined float64
-
-type userDefinedSlice []int
+type (
+ userDefined float64
+ userDefinedSlice []int
+ userDefinedString string
+)
type conversionTest struct {
s, d interface{} // source and destination
@@ -39,6 +42,7 @@ type conversionTest struct {
wantptr *int64 // if non-nil, *d's pointed value must be equal to *wantptr
wantnil bool // if true, *d must be *int64(nil)
wantusrdef userDefined
+ wantusrstr userDefinedString
}
// Target variables for scanning into.
@@ -171,6 +175,7 @@ var conversionTests = []conversionTest{
{s: int64(123), d: new(userDefined), wantusrdef: 123},
{s: "1.5", d: new(userDefined), wantusrdef: 1.5},
{s: []byte{1, 2, 3}, d: new(userDefinedSlice), wanterr: `unsupported Scan, storing driver.Value type []uint8 into type *sql.userDefinedSlice`},
+ {s: "str", d: new(userDefinedString), wantusrstr: "str"},
// Other errors
{s: complex(1, 2), d: &scanstr, wanterr: `unsupported Scan, storing driver.Value type complex128 into type *string`},
@@ -260,6 +265,9 @@ func TestConversions(t *testing.T) {
if ct.wantusrdef != 0 && ct.wantusrdef != *ct.d.(*userDefined) {
errf("want userDefined %f, got %f", ct.wantusrdef, *ct.d.(*userDefined))
}
+ if len(ct.wantusrstr) != 0 && ct.wantusrstr != *ct.d.(*userDefinedString) {
+ errf("want userDefined %q, got %q", ct.wantusrstr, *ct.d.(*userDefinedString))
+ }
}
}
@@ -461,8 +469,8 @@ func TestDriverArgs(t *testing.T) {
},
}
for i, tt := range tests {
- ds := new(driverStmt)
- got, err := driverArgs(ds, tt.args)
+ ds := &driverStmt{Locker: &sync.Mutex{}, si: stubDriverStmt{nil}}
+ got, err := driverArgs(nil, ds, tt.args)
if err != nil {
t.Errorf("test[%d]: %v", i, err)
continue
diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go
index d66196f..0262ca2 100644
--- a/libgo/go/database/sql/driver/driver.go
+++ b/libgo/go/database/sql/driver/driver.go
@@ -262,9 +262,39 @@ type StmtQueryContext interface {
QueryContext(ctx context.Context, args []NamedValue) (Rows, error)
}
+// ErrRemoveArgument may be returned from NamedValueChecker to instruct the
+// sql package to not pass the argument to the driver query interface.
+// Return when accepting query specific options or structures that aren't
+// SQL query arguments.
+var ErrRemoveArgument = errors.New("driver: remove argument from query")
+
+// NamedValueChecker may be optionally implemented by Conn or Stmt. It provides
+// the driver more control to handle Go and database types beyond the default
+// Values types allowed.
+//
+// The sql package checks for value checkers in the following order,
+// stopping at the first found match: Stmt.NamedValueChecker, Conn.NamedValueChecker,
+// Stmt.ColumnConverter, DefaultParameterConverter.
+//
+// If CheckNamedValue returns ErrRemoveArgument, the NamedValue will not be included in
+// the final query arguments. This may be used to pass special options to
+// the query itself.
+//
+// If ErrSkip is returned the column converter error checking
+// path is used for the argument. Drivers may wish to return ErrSkip after
+// they have exhausted their own special cases.
+type NamedValueChecker interface {
+ // CheckNamedValue is called before passing arguments to the driver
+ // and is called in place of any ColumnConverter. CheckNamedValue must do type
+ // validation and conversion as appropriate for the driver.
+ CheckNamedValue(*NamedValue) error
+}
+
// ColumnConverter may be optionally implemented by Stmt if the
// statement is aware of its own columns' types and can convert from
// any type to a driver Value.
+//
+// Deprecated: Drivers should implement NamedValueChecker.
type ColumnConverter interface {
// ColumnConverter returns a ValueConverter for the provided
// column index. If the type of a specific column isn't known
diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go
index 4b15f5b..4dcd096 100644
--- a/libgo/go/database/sql/fakedb_test.go
+++ b/libgo/go/database/sql/fakedb_test.go
@@ -58,9 +58,10 @@ type fakeDriver struct {
type fakeDB struct {
name string
- mu sync.Mutex
- tables map[string]*table
- badConn bool
+ mu sync.Mutex
+ tables map[string]*table
+ badConn bool
+ allowAny bool
}
type table struct {
@@ -83,11 +84,20 @@ type row struct {
cols []interface{} // must be same size as its table colname + coltype
}
+type memToucher interface {
+ // touchMem reads & writes some memory, to help find data races.
+ touchMem()
+}
+
type fakeConn struct {
db *fakeDB // where to return ourselves to
currTx *fakeTx
+ // Every operation writes to line to enable the race detector
+ // check for data races.
+ line int64
+
// Stats for tests:
mu sync.Mutex
stmtsMade int
@@ -99,6 +109,10 @@ type fakeConn struct {
stickyBad bool
}
+func (c *fakeConn) touchMem() {
+ c.line++
+}
+
func (c *fakeConn) incrStat(v *int) {
c.mu.Lock()
*v++
@@ -116,6 +130,7 @@ type boundCol struct {
}
type fakeStmt struct {
+ memToucher
c *fakeConn
q string // just for debugging
@@ -298,6 +313,7 @@ func (c *fakeConn) Begin() (driver.Tx, error) {
if c.currTx != nil {
return nil, errors.New("already in a transaction")
}
+ c.touchMem()
c.currTx = &fakeTx{c: c}
return c.currTx, nil
}
@@ -339,6 +355,7 @@ func (c *fakeConn) Close() (err error) {
drv.mu.Unlock()
}
}()
+ c.touchMem()
if c.currTx != nil {
return errors.New("can't close fakeConn; in a Transaction")
}
@@ -352,12 +369,14 @@ func (c *fakeConn) Close() (err error) {
return nil
}
-func checkSubsetTypes(args []driver.NamedValue) error {
+func checkSubsetTypes(allowAny bool, args []driver.NamedValue) error {
for _, arg := range args {
switch arg.Value.(type) {
case int64, float64, bool, nil, []byte, string, time.Time:
default:
- return fmt.Errorf("fakedb_test: invalid argument ordinal %[1]d: %[2]v, type %[2]T", arg.Ordinal, arg.Value)
+ if !allowAny {
+ return fmt.Errorf("fakedb_test: invalid argument ordinal %[1]d: %[2]v, type %[2]T", arg.Ordinal, arg.Value)
+ }
}
}
return nil
@@ -373,7 +392,7 @@ func (c *fakeConn) ExecContext(ctx context.Context, query string, args []driver.
// just to check that all the args are of the proper types.
// ErrSkip is returned so the caller acts as if we didn't
// implement this at all.
- err := checkSubsetTypes(args)
+ err := checkSubsetTypes(c.db.allowAny, args)
if err != nil {
return nil, err
}
@@ -390,7 +409,7 @@ func (c *fakeConn) QueryContext(ctx context.Context, query string, args []driver
// just to check that all the args are of the proper types.
// ErrSkip is returned so the caller acts as if we didn't
// implement this at all.
- err := checkSubsetTypes(args)
+ err := checkSubsetTypes(c.db.allowAny, args)
if err != nil {
return nil, err
}
@@ -524,13 +543,14 @@ func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stm
return nil, driver.ErrBadConn
}
+ c.touchMem()
var firstStmt, prev *fakeStmt
for _, query := range strings.Split(query, ";") {
parts := strings.Split(query, "|")
if len(parts) < 1 {
return nil, errf("empty query")
}
- stmt := &fakeStmt{q: query, c: c}
+ stmt := &fakeStmt{q: query, c: c, memToucher: c}
if firstStmt == nil {
firstStmt = stmt
}
@@ -612,6 +632,7 @@ func (s *fakeStmt) Close() error {
if s.c.db == nil {
panic("in fakeStmt.Close, conn's db is nil (already closed)")
}
+ s.touchMem()
if !s.closed {
s.c.incrStat(&s.c.stmtsClosed)
s.closed = true
@@ -642,10 +663,11 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d
return nil, driver.ErrBadConn
}
- err := checkSubsetTypes(args)
+ err := checkSubsetTypes(s.c.db.allowAny, args)
if err != nil {
return nil, err
}
+ s.touchMem()
if s.wait > 0 {
time.Sleep(s.wait)
@@ -753,11 +775,12 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (
return nil, driver.ErrBadConn
}
- err := checkSubsetTypes(args)
+ err := checkSubsetTypes(s.c.db.allowAny, args)
if err != nil {
return nil, err
}
+ s.touchMem()
db := s.c.db
if len(args) != s.placeholders {
panic("error in pkg db; should only get here if size is correct")
@@ -853,11 +876,12 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (
}
cursor := &rowsCursor{
- posRow: -1,
- rows: setMRows,
- cols: setColumns,
- colType: setColType,
- errPos: -1,
+ parentMem: s.c,
+ posRow: -1,
+ rows: setMRows,
+ cols: setColumns,
+ colType: setColType,
+ errPos: -1,
}
return cursor, nil
}
@@ -877,6 +901,7 @@ func (tx *fakeTx) Commit() error {
if hookCommitBadConn != nil && hookCommitBadConn() {
return driver.ErrBadConn
}
+ tx.c.touchMem()
return nil
}
@@ -888,16 +913,18 @@ func (tx *fakeTx) Rollback() error {
if hookRollbackBadConn != nil && hookRollbackBadConn() {
return driver.ErrBadConn
}
+ tx.c.touchMem()
return nil
}
type rowsCursor struct {
- cols [][]string
- colType [][]string
- posSet int
- posRow int
- rows [][]*row
- closed bool
+ parentMem memToucher
+ cols [][]string
+ colType [][]string
+ posSet int
+ posRow int
+ rows [][]*row
+ closed bool
// errPos and err are for making Next return early with error.
errPos int
@@ -907,6 +934,16 @@ type rowsCursor struct {
// the original slice's first byte address. we clone them
// just so we're able to corrupt them on close.
bytesClone map[*byte][]byte
+
+ // Every operation writes to line to enable the race detector
+ // check for data races.
+ // This is separate from the fakeConn.line to allow for drivers that
+ // can start multiple queries on the same transaction at the same time.
+ line int64
+}
+
+func (rc *rowsCursor) touchMem() {
+ rc.line++
}
func (rc *rowsCursor) Close() error {
@@ -915,6 +952,8 @@ func (rc *rowsCursor) Close() error {
bs[0] = 255 // first byte corrupted
}
}
+ rc.touchMem()
+ rc.parentMem.touchMem()
rc.closed = true
return nil
}
@@ -937,6 +976,7 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
if rc.closed {
return errors.New("fakedb: cursor is closed")
}
+ rc.touchMem()
rc.posRow++
if rc.posRow == rc.errPos {
return rc.err
@@ -970,10 +1010,12 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
}
func (rc *rowsCursor) HasNextResultSet() bool {
+ rc.touchMem()
return rc.posSet < len(rc.rows)-1
}
func (rc *rowsCursor) NextResultSet() error {
+ rc.touchMem()
if rc.HasNextResultSet() {
rc.posSet++
rc.posRow = -1
@@ -1004,6 +1046,12 @@ func (fakeDriverString) ConvertValue(v interface{}) (driver.Value, error) {
return fmt.Sprintf("%v", v), nil
}
+type anyTypeConverter struct{}
+
+func (anyTypeConverter) ConvertValue(v interface{}) (driver.Value, error) {
+ return v, nil
+}
+
func converterForType(typ string) driver.ValueConverter {
switch typ {
case "bool":
@@ -1030,6 +1078,8 @@ func converterForType(typ string) driver.ValueConverter {
return driver.Null{Converter: driver.DefaultParameterConverter}
case "datetime":
return driver.DefaultParameterConverter
+ case "any":
+ return anyTypeConverter{}
}
panic("invalid fakedb column type of " + typ)
}
@@ -1056,6 +1106,8 @@ func colTypeToReflectType(typ string) reflect.Type {
return reflect.TypeOf(NullFloat64{})
case "datetime":
return reflect.TypeOf(time.Time{})
+ case "any":
+ return reflect.TypeOf(new(interface{})).Elem()
}
panic("invalid fakedb column type of " + typ)
}
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go
index f8a8844..c609fe4 100644
--- a/libgo/go/database/sql/sql.go
+++ b/libgo/go/database/sql/sql.go
@@ -278,6 +278,27 @@ type Scanner interface {
Scan(src interface{}) error
}
+// Out may be used to retrieve OUTPUT value parameters from stored procedures.
+//
+// Not all drivers and databases support OUTPUT value parameters.
+//
+// Example usage:
+//
+// var outArg string
+// _, err := db.ExecContext(ctx, "ProcName", sql.Named("Arg1", Out{Dest: &outArg}))
+type Out struct {
+ _Named_Fields_Required struct{}
+
+ // Dest is a pointer to the value that will be set to the result of the
+ // stored procedure's OUTPUT parameter.
+ Dest interface{}
+
+ // In is whether the parameter is an INOUT parameter. If so, the input value to the stored
+ // procedure is the dereferenced value of Dest's pointer, which is then replaced with
+ // the output value.
+ In bool
+}
+
// ErrNoRows is returned by Scan when QueryRow doesn't return a
// row. In such a case, QueryRow returns a placeholder *Row value that
// defers this error until a Scan.
@@ -372,11 +393,19 @@ func (dc *driverConn) expired(timeout time.Duration) bool {
return dc.createdAt.Add(timeout).Before(nowFunc())
}
-func (dc *driverConn) prepareLocked(ctx context.Context, query string) (*driverStmt, error) {
+// prepareLocked prepares the query on dc. When cg == nil the dc must keep track of
+// the prepared statements in a pool.
+func (dc *driverConn) prepareLocked(ctx context.Context, cg stmtConnGrabber, query string) (*driverStmt, error) {
si, err := ctxDriverPrepare(ctx, dc.ci, query)
if err != nil {
return nil, err
}
+ ds := &driverStmt{Locker: dc, si: si}
+
+ // No need to manage open statements if there is a single connection grabber.
+ if cg != nil {
+ return ds, nil
+ }
// Track each driverConn's open statements, so we can close them
// before closing the conn.
@@ -385,9 +414,7 @@ func (dc *driverConn) prepareLocked(ctx context.Context, query string) (*driverS
if dc.openStmt == nil {
dc.openStmt = make(map[*driverStmt]bool)
}
- ds := &driverStmt{Locker: dc, si: si}
dc.openStmt[ds] = true
-
return ds, nil
}
@@ -583,6 +610,17 @@ func Open(driverName, dataSourceName string) (*DB, error) {
return db, nil
}
+func (db *DB) pingDC(ctx context.Context, dc *driverConn, release func(error)) error {
+ var err error
+ if pinger, ok := dc.ci.(driver.Pinger); ok {
+ withLock(dc, func() {
+ err = pinger.Ping(ctx)
+ })
+ }
+ release(err)
+ return err
+}
+
// PingContext verifies a connection to the database is still alive,
// establishing a connection if necessary.
func (db *DB) PingContext(ctx context.Context) error {
@@ -602,11 +640,7 @@ func (db *DB) PingContext(ctx context.Context) error {
return err
}
- if pinger, ok := dc.ci.(driver.Pinger); ok {
- err = pinger.Ping(ctx)
- }
- db.putConn(dc, err)
- return err
+ return db.pingDC(ctx, dc, dc.releaseConn)
}
// Ping verifies a connection to the database is still alive,
@@ -975,9 +1009,9 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn
db: db,
createdAt: nowFunc(),
ci: ci,
+ inUse: true,
}
db.addDepLocked(dc, dc)
- dc.inUse = true
db.mu.Unlock()
return dc, nil
}
@@ -1137,22 +1171,39 @@ func (db *DB) prepare(ctx context.Context, query string, strategy connReuseStrat
if err != nil {
return nil, err
}
+ return db.prepareDC(ctx, dc, dc.releaseConn, nil, query)
+}
+
+// prepareDC prepares a query on the driverConn and calls release before
+// returning. When cg == nil it implies that a connection pool is used, and
+// when cg != nil only a single driver connection is used.
+func (db *DB) prepareDC(ctx context.Context, dc *driverConn, release func(error), cg stmtConnGrabber, query string) (*Stmt, error) {
var ds *driverStmt
+ var err error
+ defer func() {
+ release(err)
+ }()
withLock(dc, func() {
- ds, err = dc.prepareLocked(ctx, query)
+ ds, err = dc.prepareLocked(ctx, cg, query)
})
if err != nil {
- db.putConn(dc, err)
return nil, err
}
stmt := &Stmt{
- db: db,
- query: query,
- css: []connStmt{{dc, ds}},
- lastNumClosed: atomic.LoadUint64(&db.numClosed),
+ db: db,
+ query: query,
+ cg: cg,
+ cgds: ds,
+ }
+
+ // When cg == nil this statement will need to keep track of various
+ // connections they are prepared on and record the stmt dependency on
+ // the DB.
+ if cg == nil {
+ stmt.css = []connStmt{{dc, ds}}
+ stmt.lastNumClosed = atomic.LoadUint64(&db.numClosed)
+ db.addDep(stmt, stmt)
}
- db.addDep(stmt, stmt)
- db.putConn(dc, nil)
return stmt, nil
}
@@ -1179,18 +1230,21 @@ func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
return db.ExecContext(context.Background(), query, args...)
}
-func (db *DB) exec(ctx context.Context, query string, args []interface{}, strategy connReuseStrategy) (res Result, err error) {
+func (db *DB) exec(ctx context.Context, query string, args []interface{}, strategy connReuseStrategy) (Result, error) {
dc, err := db.conn(ctx, strategy)
if err != nil {
return nil, err
}
+ return db.execDC(ctx, dc, dc.releaseConn, query, args)
+}
+
+func (db *DB) execDC(ctx context.Context, dc *driverConn, release func(error), query string, args []interface{}) (res Result, err error) {
defer func() {
- db.putConn(dc, err)
+ release(err)
}()
-
if execer, ok := dc.ci.(driver.Execer); ok {
var dargs []driver.NamedValue
- dargs, err = driverArgs(nil, args)
+ dargs, err = driverArgs(dc.ci, nil, args)
if err != nil {
return nil, err
}
@@ -1215,7 +1269,7 @@ func (db *DB) exec(ctx context.Context, query string, args []interface{}, strate
}
ds := &driverStmt{Locker: dc, si: si}
defer ds.Close()
- return resultFromStatement(ctx, ds, args...)
+ return resultFromStatement(ctx, dc.ci, ds, args...)
}
// QueryContext executes a query that returns rows, typically a SELECT.
@@ -1242,19 +1296,21 @@ func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
}
func (db *DB) query(ctx context.Context, query string, args []interface{}, strategy connReuseStrategy) (*Rows, error) {
- ci, err := db.conn(ctx, strategy)
+ dc, err := db.conn(ctx, strategy)
if err != nil {
return nil, err
}
- return db.queryConn(ctx, ci, ci.releaseConn, query, args)
+ return db.queryDC(ctx, nil, dc, dc.releaseConn, query, args)
}
-// queryConn executes a query on the given connection.
+// queryDC executes a query on the given connection.
// The connection gets released by the releaseConn function.
-func (db *DB) queryConn(ctx context.Context, dc *driverConn, releaseConn func(error), query string, args []interface{}) (*Rows, error) {
+// The ctx context is from a query method and the txctx context is from an
+// optional transaction context.
+func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []interface{}) (*Rows, error) {
if queryer, ok := dc.ci.(driver.Queryer); ok {
- dargs, err := driverArgs(nil, args)
+ dargs, err := driverArgs(dc.ci, nil, args)
if err != nil {
releaseConn(err)
return nil, err
@@ -1275,7 +1331,7 @@ func (db *DB) queryConn(ctx context.Context, dc *driverConn, releaseConn func(er
releaseConn: releaseConn,
rowsi: rowsi,
}
- rows.initContextClose(ctx)
+ rows.initContextClose(ctx, txctx)
return rows, nil
}
}
@@ -1291,7 +1347,7 @@ func (db *DB) queryConn(ctx context.Context, dc *driverConn, releaseConn func(er
}
ds := &driverStmt{Locker: dc, si: si}
- rowsi, err := rowsiFromStatement(ctx, ds, args...)
+ rowsi, err := rowsiFromStatement(ctx, dc.ci, ds, args...)
if err != nil {
ds.Close()
releaseConn(err)
@@ -1306,13 +1362,16 @@ func (db *DB) queryConn(ctx context.Context, dc *driverConn, releaseConn func(er
rowsi: rowsi,
closeStmt: ds,
}
- rows.initContextClose(ctx)
+ rows.initContextClose(ctx, txctx)
return rows, nil
}
// QueryRowContext executes a query that is expected to return at most one row.
// QueryRowContext always returns a non-nil value. Errors are deferred until
// Row's Scan method is called.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
rows, err := db.QueryContext(ctx, query, args...)
return &Row{rows: rows, err: err}
@@ -1321,6 +1380,9 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa
// QueryRow executes a query that is expected to return at most one row.
// QueryRow always returns a non-nil value. Errors are deferred until
// Row's Scan method is called.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
func (db *DB) QueryRow(query string, args ...interface{}) *Row {
return db.QueryRowContext(context.Background(), query, args...)
}
@@ -1361,12 +1423,17 @@ func (db *DB) begin(ctx context.Context, opts *TxOptions, strategy connReuseStra
if err != nil {
return nil, err
}
+ return db.beginDC(ctx, dc, dc.releaseConn, opts)
+}
+
+// beginDC starts a transaction. The provided dc must be valid and ready to use.
+func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error), opts *TxOptions) (tx *Tx, err error) {
var txi driver.Tx
withLock(dc, func() {
txi, err = ctxDriverBegin(ctx, opts, dc.ci)
})
if err != nil {
- db.putConn(dc, err)
+ release(err)
return nil, err
}
@@ -1374,11 +1441,12 @@ func (db *DB) begin(ctx context.Context, opts *TxOptions, strategy connReuseStra
// The cancel function in Tx will be called after done is set to true.
ctx, cancel := context.WithCancel(ctx)
tx = &Tx{
- db: db,
- dc: dc,
- txi: txi,
- cancel: cancel,
- ctx: ctx,
+ db: db,
+ dc: dc,
+ releaseConn: release,
+ txi: txi,
+ cancel: cancel,
+ ctx: ctx,
}
go tx.awaitDone()
return tx, nil
@@ -1389,6 +1457,189 @@ func (db *DB) Driver() driver.Driver {
return db.driver
}
+// ErrConnDone is returned by any operation that is performed on a connection
+// that has already been committed or rolled back.
+var ErrConnDone = errors.New("database/sql: connection is already closed")
+
+// Conn returns a single connection by either opening a new connection
+// or returning an existing connection from the connection pool. Conn will
+// block until either a connection is returned or ctx is canceled.
+// Queries run on the same Conn will be run in the same database session.
+//
+// Every Conn must be returned to the database pool after use by
+// calling Conn.Close.
+func (db *DB) Conn(ctx context.Context) (*Conn, error) {
+ var dc *driverConn
+ var err error
+ for i := 0; i < maxBadConnRetries; i++ {
+ dc, err = db.conn(ctx, cachedOrNewConn)
+ if err != driver.ErrBadConn {
+ break
+ }
+ }
+ if err == driver.ErrBadConn {
+ dc, err = db.conn(ctx, cachedOrNewConn)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ conn := &Conn{
+ db: db,
+ dc: dc,
+ }
+ return conn, nil
+}
+
+type releaseConn func(error)
+
+// Conn represents a single database session rather a pool of database
+// sessions. Prefer running queries from DB unless there is a specific
+// need for a continuous single database session.
+//
+// A Conn must call Close to return the connection to the database pool
+// and may do so concurrently with a running query.
+//
+// After a call to Close, all operations on the
+// connection fail with ErrConnDone.
+type Conn struct {
+ db *DB
+
+ // closemu prevents the connection from closing while there
+ // is an active query. It is held for read during queries
+ // and exclusively during close.
+ closemu sync.RWMutex
+
+ // dc is owned until close, at which point
+ // it's returned to the connection pool.
+ dc *driverConn
+
+ // done transitions from 0 to 1 exactly once, on close.
+ // Once done, all operations fail with ErrConnDone.
+ // Use atomic operations on value when checking value.
+ done int32
+}
+
+func (c *Conn) grabConn(context.Context) (*driverConn, releaseConn, error) {
+ if atomic.LoadInt32(&c.done) != 0 {
+ return nil, nil, ErrConnDone
+ }
+ c.closemu.RLock()
+ return c.dc, c.closemuRUnlockCondReleaseConn, nil
+}
+
+// PingContext verifies the connection to the database is still alive.
+func (c *Conn) PingContext(ctx context.Context) error {
+ dc, release, err := c.grabConn(ctx)
+ if err != nil {
+ return err
+ }
+ return c.db.pingDC(ctx, dc, release)
+}
+
+// ExecContext executes a query without returning any rows.
+// The args are for any placeholder parameters in the query.
+func (c *Conn) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) {
+ dc, release, err := c.grabConn(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return c.db.execDC(ctx, dc, release, query, args)
+}
+
+// QueryContext executes a query that returns rows, typically a SELECT.
+// The args are for any placeholder parameters in the query.
+func (c *Conn) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
+ dc, release, err := c.grabConn(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return c.db.queryDC(ctx, nil, dc, release, query, args)
+}
+
+// QueryRowContext executes a query that is expected to return at most one row.
+// QueryRowContext always returns a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
+func (c *Conn) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
+ rows, err := c.QueryContext(ctx, query, args...)
+ return &Row{rows: rows, err: err}
+}
+
+// PrepareContext creates a prepared statement for later queries or executions.
+// Multiple queries or executions may be run concurrently from the
+// returned statement.
+// The caller must call the statement's Close method
+// when the statement is no longer needed.
+//
+// The provided context is used for the preparation of the statement, not for the
+// execution of the statement.
+func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
+ dc, release, err := c.grabConn(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return c.db.prepareDC(ctx, dc, release, c, query)
+}
+
+// BeginTx starts a transaction.
+//
+// The provided context is used until the transaction is committed or rolled back.
+// If the context is canceled, the sql package will roll back
+// the transaction. Tx.Commit will return an error if the context provided to
+// BeginTx is canceled.
+//
+// The provided TxOptions is optional and may be nil if defaults should be used.
+// If a non-default isolation level is used that the driver doesn't support,
+// an error will be returned.
+func (c *Conn) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) {
+ dc, release, err := c.grabConn(ctx)
+ if err != nil {
+ return nil, err
+ }
+ return c.db.beginDC(ctx, dc, release, opts)
+}
+
+// closemuRUnlockCondReleaseConn read unlocks closemu
+// as the sql operation is done with the dc.
+func (c *Conn) closemuRUnlockCondReleaseConn(err error) {
+ c.closemu.RUnlock()
+ if err == driver.ErrBadConn {
+ c.close(err)
+ }
+}
+
+func (c *Conn) txCtx() context.Context {
+ return nil
+}
+
+func (c *Conn) close(err error) error {
+ if !atomic.CompareAndSwapInt32(&c.done, 0, 1) {
+ return ErrConnDone
+ }
+
+ // Lock around releasing the driver connection
+ // to ensure all queries have been stopped before doing so.
+ c.closemu.Lock()
+ defer c.closemu.Unlock()
+
+ c.dc.releaseConn(err)
+ c.dc = nil
+ c.db = nil
+ return err
+}
+
+// Close returns the connection to the connection pool.
+// All operations after a Close will return with ErrConnDone.
+// Close is safe to call concurrently with other operations and will
+// block until all other operations finish. It may be useful to first
+// cancel any used context and then call close directly after.
+func (c *Conn) Close() error {
+ return c.close(nil)
+}
+
// Tx is an in-progress database transaction.
//
// A transaction must end with a call to Commit or Rollback.
@@ -1412,6 +1663,10 @@ type Tx struct {
dc *driverConn
txi driver.Tx
+ // releaseConn is called once the Tx is closed to release
+ // any held driverConn back to the pool.
+ releaseConn func(error)
+
// done transitions from 0 to 1 exactly once, on Commit
// or Rollback. once done, all operations fail with
// ErrTxDone.
@@ -1425,7 +1680,7 @@ type Tx struct {
v []*Stmt
}
- // cancel is called after done transitions from false to true.
+ // cancel is called after done transitions from 0 to 1.
cancel func()
// ctx lives for the life of the transaction.
@@ -1457,11 +1712,12 @@ var ErrTxDone = errors.New("sql: Transaction has already been committed or rolle
// close returns the connection to the pool and
// must only be called by Tx.rollback or Tx.Commit.
func (tx *Tx) close(err error) {
+ tx.cancel()
+
tx.closemu.Lock()
defer tx.closemu.Unlock()
- tx.db.putConn(tx.dc, err)
- tx.cancel()
+ tx.releaseConn(err)
tx.dc = nil
tx.txi = nil
}
@@ -1470,19 +1726,36 @@ func (tx *Tx) close(err error) {
// a successful call to (*Tx).grabConn. For tests.
var hookTxGrabConn func()
-func (tx *Tx) grabConn(ctx context.Context) (*driverConn, error) {
+func (tx *Tx) grabConn(ctx context.Context) (*driverConn, releaseConn, error) {
select {
default:
case <-ctx.Done():
- return nil, ctx.Err()
+ return nil, nil, ctx.Err()
}
+
+ // closeme.RLock must come before the check for isDone to prevent the Tx from
+ // closing while a query is executing.
+ tx.closemu.RLock()
if tx.isDone() {
- return nil, ErrTxDone
+ tx.closemu.RUnlock()
+ return nil, nil, ErrTxDone
}
if hookTxGrabConn != nil { // test hook
hookTxGrabConn()
}
- return tx.dc, nil
+ return tx.dc, tx.closemuRUnlockRelease, nil
+}
+
+func (tx *Tx) txCtx() context.Context {
+ return tx.ctx
+}
+
+// closemuRUnlockRelease is used as a func(error) method value in
+// ExecContext and QueryContext. Unlocking in the releaseConn keeps
+// the driver conn from being returned to the connection pool until
+// the Rows has been closed.
+func (tx *Tx) closemuRUnlockRelease(error) {
+ tx.closemu.RUnlock()
}
// Closes all Stmts prepared for this transaction.
@@ -1540,7 +1813,7 @@ func (tx *Tx) Rollback() error {
return tx.rollback(false)
}
-// Prepare creates a prepared statement for use within a transaction.
+// PrepareContext creates a prepared statement for use within a transaction.
//
// The returned statement operates within the transaction and will be closed
// when the transaction has been committed or rolled back.
@@ -1551,44 +1824,15 @@ func (tx *Tx) Rollback() error {
// for the execution of the returned statement. The returned statement
// will run in the transaction context.
func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
- tx.closemu.RLock()
- defer tx.closemu.RUnlock()
-
- // TODO(bradfitz): We could be more efficient here and either
- // provide a method to take an existing Stmt (created on
- // perhaps a different Conn), and re-create it on this Conn if
- // necessary. Or, better: keep a map in DB of query string to
- // Stmts, and have Stmt.Execute do the right thing and
- // re-prepare if the Conn in use doesn't have that prepared
- // statement. But we'll want to avoid caching the statement
- // in the case where we only call conn.Prepare implicitly
- // (such as in db.Exec or tx.Exec), but the caller package
- // can't be holding a reference to the returned statement.
- // Perhaps just looking at the reference count (by noting
- // Stmt.Close) would be enough. We might also want a finalizer
- // on Stmt to drop the reference count.
- dc, err := tx.grabConn(ctx)
+ dc, release, err := tx.grabConn(ctx)
if err != nil {
return nil, err
}
- var si driver.Stmt
- withLock(dc, func() {
- si, err = ctxDriverPrepare(ctx, dc.ci, query)
- })
+ stmt, err := tx.db.prepareDC(ctx, dc, release, tx, query)
if err != nil {
return nil, err
}
-
- stmt := &Stmt{
- db: tx.db,
- tx: tx,
- txds: &driverStmt{
- Locker: dc,
- si: si,
- },
- query: query,
- }
tx.stmts.Lock()
tx.stmts.v = append(tx.stmts.v, stmt)
tx.stmts.Unlock()
@@ -1618,34 +1862,67 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
// The returned statement operates within the transaction and will be closed
// when the transaction has been committed or rolled back.
func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt {
- tx.closemu.RLock()
- defer tx.closemu.RUnlock()
-
- // TODO(bradfitz): optimize this. Currently this re-prepares
- // each time. This is fine for now to illustrate the API but
- // we should really cache already-prepared statements
- // per-Conn. See also the big comment in Tx.Prepare.
+ dc, release, err := tx.grabConn(ctx)
+ if err != nil {
+ return &Stmt{stickyErr: err}
+ }
+ defer release(nil)
if tx.db != stmt.db {
return &Stmt{stickyErr: errors.New("sql: Tx.Stmt: statement from different database used")}
}
- dc, err := tx.grabConn(ctx)
- if err != nil {
- return &Stmt{stickyErr: err}
- }
var si driver.Stmt
- withLock(dc, func() {
- si, err = ctxDriverPrepare(ctx, dc.ci, stmt.query)
- })
+ var parentStmt *Stmt
+ stmt.mu.Lock()
+ if stmt.closed || stmt.cg != nil {
+ // If the statement has been closed or already belongs to a
+ // transaction, we can't reuse it in this connection.
+ // Since tx.StmtContext should never need to be called with a
+ // Stmt already belonging to tx, we ignore this edge case and
+ // re-prepare the statement in this case. No need to add
+ // code-complexity for this.
+ stmt.mu.Unlock()
+ withLock(dc, func() {
+ si, err = ctxDriverPrepare(ctx, dc.ci, stmt.query)
+ })
+ if err != nil {
+ return &Stmt{stickyErr: err}
+ }
+ } else {
+ stmt.removeClosedStmtLocked()
+ // See if the statement has already been prepared on this connection,
+ // and reuse it if possible.
+ for _, v := range stmt.css {
+ if v.dc == dc {
+ si = v.ds.si
+ break
+ }
+ }
+
+ stmt.mu.Unlock()
+
+ if si == nil {
+ cs, err := stmt.prepareOnConnLocked(ctx, dc)
+ if err != nil {
+ return &Stmt{stickyErr: err}
+ }
+ si = cs.si
+ }
+ parentStmt = stmt
+ }
+
txs := &Stmt{
db: tx.db,
- tx: tx,
- txds: &driverStmt{
+ cg: tx,
+ cgds: &driverStmt{
Locker: dc,
si: si,
},
- query: stmt.query,
- stickyErr: err,
+ parentStmt: parentStmt,
+ query: stmt.query,
+ }
+ if parentStmt != nil {
+ tx.db.addDep(parentStmt, txs)
}
tx.stmts.Lock()
tx.stmts.v = append(tx.stmts.v, txs)
@@ -1672,42 +1949,11 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
// ExecContext executes a query that doesn't return rows.
// For example: an INSERT and UPDATE.
func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) {
- tx.closemu.RLock()
- defer tx.closemu.RUnlock()
-
- dc, err := tx.grabConn(ctx)
+ dc, release, err := tx.grabConn(ctx)
if err != nil {
return nil, err
}
-
- if execer, ok := dc.ci.(driver.Execer); ok {
- dargs, err := driverArgs(nil, args)
- if err != nil {
- return nil, err
- }
- var resi driver.Result
- withLock(dc, func() {
- resi, err = ctxDriverExec(ctx, execer, query, dargs)
- })
- if err == nil {
- return driverResult{dc, resi}, nil
- }
- if err != driver.ErrSkip {
- return nil, err
- }
- }
-
- var si driver.Stmt
- withLock(dc, func() {
- si, err = ctxDriverPrepare(ctx, dc.ci, query)
- })
- if err != nil {
- return nil, err
- }
- ds := &driverStmt{Locker: dc, si: si}
- defer ds.Close()
-
- return resultFromStatement(ctx, ds, args...)
+ return tx.db.execDC(ctx, dc, release, query, args)
}
// Exec executes a query that doesn't return rows.
@@ -1718,15 +1964,12 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
// QueryContext executes a query that returns rows, typically a SELECT.
func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
- tx.closemu.RLock()
- defer tx.closemu.RUnlock()
-
- dc, err := tx.grabConn(ctx)
+ dc, release, err := tx.grabConn(ctx)
if err != nil {
return nil, err
}
- releaseConn := func(error) {}
- return tx.db.queryConn(ctx, dc, releaseConn, query, args)
+
+ return tx.db.queryDC(ctx, tx.ctx, dc, release, query, args)
}
// Query executes a query that returns rows, typically a SELECT.
@@ -1737,6 +1980,9 @@ func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
// QueryRowContext executes a query that is expected to return at most one row.
// QueryRowContext always returns a non-nil value. Errors are deferred until
// Row's Scan method is called.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
rows, err := tx.QueryContext(ctx, query, args...)
return &Row{rows: rows, err: err}
@@ -1745,6 +1991,9 @@ func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interfa
// QueryRow executes a query that is expected to return at most one row.
// QueryRow always returns a non-nil value. Errors are deferred until
// Row's Scan method is called.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
return tx.QueryRowContext(context.Background(), query, args...)
}
@@ -1755,6 +2004,24 @@ type connStmt struct {
ds *driverStmt
}
+// stmtConnGrabber represents a Tx or Conn that will return the underlying
+// driverConn and release function.
+type stmtConnGrabber interface {
+ // grabConn returns the driverConn and the associated release function
+ // that must be called when the operation completes.
+ grabConn(context.Context) (*driverConn, releaseConn, error)
+
+ // txCtx returns the transaction context if available.
+ // The returned context should be selected on along with
+ // any query context when awaiting a cancel.
+ txCtx() context.Context
+}
+
+var (
+ _ stmtConnGrabber = &Tx{}
+ _ stmtConnGrabber = &Conn{}
+)
+
// Stmt is a prepared statement.
// A Stmt is safe for concurrent use by multiple goroutines.
type Stmt struct {
@@ -1765,17 +2032,29 @@ type Stmt struct {
closemu sync.RWMutex // held exclusively during close, for read otherwise.
- // If in a transaction, else both nil:
- tx *Tx
- txds *driverStmt
+ // If Stmt is prepared on a Tx or Conn then cg is present and will
+ // only ever grab a connection from cg.
+ // If cg is nil then the Stmt must grab an arbitrary connection
+ // from db and determine if it must prepare the stmt again by
+ // inspecting css.
+ cg stmtConnGrabber
+ cgds *driverStmt
+
+ // parentStmt is set when a transaction-specific statement
+ // is requested from an identical statement prepared on the same
+ // conn. parentStmt is used to track the dependency of this statement
+ // on its originating ("parent") statement so that parentStmt may
+ // be closed by the user without them having to know whether or not
+ // any transactions are still using it.
+ parentStmt *Stmt
mu sync.Mutex // protects the rest of the fields
closed bool
// css is a list of underlying driver statement interfaces
// that are valid on particular connections. This is only
- // used if tx == nil and one is found that has idle
- // connections. If tx != nil, txsi is always used.
+ // used if cg == nil and one is found that has idle
+ // connections. If cg != nil, cgds is always used.
css []connStmt
// lastNumClosed is copied from db.numClosed when Stmt is created
@@ -1790,8 +2069,12 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er
defer s.closemu.RUnlock()
var res Result
- for i := 0; i < maxBadConnRetries; i++ {
- _, releaseConn, ds, err := s.connStmt(ctx)
+ strategy := cachedOrNewConn
+ for i := 0; i < maxBadConnRetries+1; i++ {
+ if i == maxBadConnRetries {
+ strategy = alwaysNewConn
+ }
+ dc, releaseConn, ds, err := s.connStmt(ctx, strategy)
if err != nil {
if err == driver.ErrBadConn {
continue
@@ -1799,7 +2082,7 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, er
return nil, err
}
- res, err = resultFromStatement(ctx, ds, args...)
+ res, err = resultFromStatement(ctx, dc.ci, ds, args...)
releaseConn(err)
if err != driver.ErrBadConn {
return res, err
@@ -1814,23 +2097,8 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
return s.ExecContext(context.Background(), args...)
}
-func driverNumInput(ds *driverStmt) int {
- ds.Lock()
- defer ds.Unlock() // in case NumInput panics
- return ds.si.NumInput()
-}
-
-func resultFromStatement(ctx context.Context, ds *driverStmt, args ...interface{}) (Result, error) {
- want := driverNumInput(ds)
-
- // -1 means the driver doesn't know how to count the number of
- // placeholders, so we won't sanity check input here and instead let the
- // driver deal with errors.
- if want != -1 && len(args) != want {
- return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(args))
- }
-
- dargs, err := driverArgs(ds, args)
+func resultFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...interface{}) (Result, error) {
+ dargs, err := driverArgs(ci, ds, args)
if err != nil {
return nil, err
}
@@ -1874,7 +2142,7 @@ func (s *Stmt) removeClosedStmtLocked() {
// connStmt returns a free driver connection on which to execute the
// statement, a function to call to release the connection, and a
// statement bound to that connection.
-func (s *Stmt) connStmt(ctx context.Context) (ci *driverConn, releaseConn func(error), ds *driverStmt, err error) {
+func (s *Stmt) connStmt(ctx context.Context, strategy connReuseStrategy) (dc *driverConn, releaseConn func(error), ds *driverStmt, err error) {
if err = s.stickyErr; err != nil {
return
}
@@ -1885,22 +2153,21 @@ func (s *Stmt) connStmt(ctx context.Context) (ci *driverConn, releaseConn func(e
return
}
- // In a transaction, we always use the connection that the
- // transaction was created on.
- if s.tx != nil {
+ // In a transaction or connection, we always use the connection that the
+ // the stmt was created on.
+ if s.cg != nil {
s.mu.Unlock()
- ci, err = s.tx.grabConn(ctx) // blocks, waiting for the connection.
+ dc, releaseConn, err = s.cg.grabConn(ctx) // blocks, waiting for the connection.
if err != nil {
return
}
- releaseConn = func(error) {}
- return ci, releaseConn, s.txds, nil
+ return dc, releaseConn, s.cgds, nil
}
s.removeClosedStmtLocked()
s.mu.Unlock()
- dc, err := s.db.conn(ctx, cachedOrNewConn)
+ dc, err = s.db.conn(ctx, strategy)
if err != nil {
return nil, nil, nil, err
}
@@ -1916,18 +2183,28 @@ func (s *Stmt) connStmt(ctx context.Context) (ci *driverConn, releaseConn func(e
// No luck; we need to prepare the statement on this connection
withLock(dc, func() {
- ds, err = dc.prepareLocked(ctx, s.query)
+ ds, err = s.prepareOnConnLocked(ctx, dc)
})
if err != nil {
- s.db.putConn(dc, err)
+ dc.releaseConn(err)
return nil, nil, nil, err
}
+
+ return dc, dc.releaseConn, ds, nil
+}
+
+// prepareOnConnLocked prepares the query in Stmt s on dc and adds it to the list of
+// open connStmt on the statement. It assumes the caller is holding the lock on dc.
+func (s *Stmt) prepareOnConnLocked(ctx context.Context, dc *driverConn) (*driverStmt, error) {
+ si, err := dc.prepareLocked(ctx, s.cg, s.query)
+ if err != nil {
+ return nil, err
+ }
+ cs := connStmt{dc, si}
s.mu.Lock()
- cs := connStmt{dc, ds}
s.css = append(s.css, cs)
s.mu.Unlock()
-
- return dc, dc.releaseConn, ds, nil
+ return cs.ds, nil
}
// QueryContext executes a prepared query statement with the given arguments
@@ -1937,8 +2214,12 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er
defer s.closemu.RUnlock()
var rowsi driver.Rows
- for i := 0; i < maxBadConnRetries; i++ {
- dc, releaseConn, ds, err := s.connStmt(ctx)
+ strategy := cachedOrNewConn
+ for i := 0; i < maxBadConnRetries+1; i++ {
+ if i == maxBadConnRetries {
+ strategy = alwaysNewConn
+ }
+ dc, releaseConn, ds, err := s.connStmt(ctx, strategy)
if err != nil {
if err == driver.ErrBadConn {
continue
@@ -1946,7 +2227,7 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er
return nil, err
}
- rowsi, err = rowsiFromStatement(ctx, ds, args...)
+ rowsi, err = rowsiFromStatement(ctx, dc.ci, ds, args...)
if err == nil {
// Note: ownership of ci passes to the *Rows, to be freed
// with releaseConn.
@@ -1955,12 +2236,21 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er
rowsi: rowsi,
// releaseConn set below
}
+ // addDep must be added before initContextClose or it could attempt
+ // to removeDep before it has been added.
s.db.addDep(s, rows)
+
+ // releaseConn must be set before initContextClose or it could
+ // release the connection before it is set.
rows.releaseConn = func(err error) {
releaseConn(err)
s.db.removeDep(s, rows)
}
- rows.initContextClose(ctx)
+ var txctx context.Context
+ if s.cg != nil {
+ txctx = s.cg.txCtx()
+ }
+ rows.initContextClose(ctx, txctx)
return rows, nil
}
@@ -1978,7 +2268,7 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
return s.QueryContext(context.Background(), args...)
}
-func rowsiFromStatement(ctx context.Context, ds *driverStmt, args ...interface{}) (driver.Rows, error) {
+func rowsiFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...interface{}) (driver.Rows, error) {
var want int
withLock(ds, func() {
want = ds.si.NumInput()
@@ -1991,7 +2281,7 @@ func rowsiFromStatement(ctx context.Context, ds *driverStmt, args ...interface{}
return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", want, len(args))
}
- dargs, err := driverArgs(ds, args)
+ dargs, err := driverArgs(ci, ds, args)
if err != nil {
return nil, err
}
@@ -2054,13 +2344,21 @@ func (s *Stmt) Close() error {
return nil
}
s.closed = true
+ txds := s.cgds
+ s.cgds = nil
+
s.mu.Unlock()
- if s.tx != nil {
- return s.txds.Close()
+ if s.cg == nil {
+ return s.db.removeDep(s, s)
}
- return s.db.removeDep(s, s)
+ if s.parentStmt != nil {
+ // If parentStmt is set, we must not close s.txds since it's stored
+ // in the css array of the parentStmt.
+ return s.db.removeDep(s.parentStmt, s)
+ }
+ return txds.Close()
}
func (s *Stmt) finalClose() error {
@@ -2107,18 +2405,28 @@ type Rows struct {
lasterr error // non-nil only if closed is true
// lastcols is only used in Scan, Next, and NextResultSet which are expected
- // not not be called concurrently.
+ // not to be called concurrently.
lastcols []driver.Value
}
-func (rs *Rows) initContextClose(ctx context.Context) {
+func (rs *Rows) initContextClose(ctx, txctx context.Context) {
ctx, rs.cancel = context.WithCancel(ctx)
- go rs.awaitDone(ctx)
+ go rs.awaitDone(ctx, txctx)
}
-// awaitDone blocks until the rows are closed or the context canceled.
-func (rs *Rows) awaitDone(ctx context.Context) {
- <-ctx.Done()
+// awaitDone blocks until either ctx or txctx is canceled. The ctx is provided
+// from the query context and is canceled when the query Rows is closed.
+// If the query was issued in a transaction, the transaction's context
+// is also provided in txctx to ensure Rows is closed if the Tx is closed.
+func (rs *Rows) awaitDone(ctx, txctx context.Context) {
+ var txctxDone <-chan struct{}
+ if txctx != nil {
+ txctxDone = txctx.Done()
+ }
+ select {
+ case <-ctx.Done():
+ case <-txctxDone:
+ }
rs.close(ctx.Err())
}
@@ -2407,7 +2715,7 @@ func (rs *Rows) Scan(dest ...interface{}) error {
}
// rowsCloseHook returns a function so tests may install the
-// hook throug a test only mutex.
+// hook through a test only mutex.
var rowsCloseHook = func() func(*Rows, *error) { return nil }
// Close closes the Rows, preventing further enumeration. If Next is called
@@ -2431,7 +2739,9 @@ func (rs *Rows) close(err error) error {
rs.lasterr = err
}
- err = rs.rowsi.Close()
+ withLock(rs.dc, func() {
+ err = rs.rowsi.Close()
+ })
if fn := rowsCloseHook(); fn != nil {
fn(rs, &err)
}
diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go
index 381aafc..c935eb4 100644
--- a/libgo/go/database/sql/sql_test.go
+++ b/libgo/go/database/sql/sql_test.go
@@ -139,6 +139,7 @@ func closeDB(t testing.TB, db *DB) {
t.Errorf("Error closing fakeConn: %v", err)
}
})
+ db.mu.Lock()
for i, dc := range db.freeConn {
if n := len(dc.openStmt); n > 0 {
// Just a sanity check. This is legal in
@@ -149,6 +150,8 @@ func closeDB(t testing.TB, db *DB) {
t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n)
}
}
+ db.mu.Unlock()
+
err := db.Close()
if err != nil {
t.Fatalf("error closing DB: %v", err)
@@ -322,7 +325,7 @@ func TestQueryContext(t *testing.T) {
select {
case <-ctx.Done():
if err := ctx.Err(); err != context.Canceled {
- t.Fatalf("context err = %v; want context.Canceled", ctx.Err())
+ t.Fatalf("context err = %v; want context.Canceled", err)
}
default:
t.Fatalf("context err = nil; want context.Canceled")
@@ -413,7 +416,7 @@ func TestTxContextWait(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
- ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*15)
+ ctx, cancel := context.WithTimeout(context.Background(), 15*time.Millisecond)
defer cancel()
tx, err := db.BeginTx(ctx, nil)
@@ -590,13 +593,13 @@ func TestPoolExhaustOnCancel(t *testing.T) {
saturate.Wait()
// Now cancel the request while it is waiting.
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
+ ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
for i := 0; i < max; i++ {
ctxReq, cancelReq := context.WithCancel(ctx)
go func() {
- time.Sleep(time.Millisecond * 100)
+ time.Sleep(100 * time.Millisecond)
cancelReq()
}()
err := db.PingContext(ctxReq)
@@ -874,7 +877,7 @@ func TestStatementClose(t *testing.T) {
msg string
}{
{&Stmt{stickyErr: want}, "stickyErr not propagated"},
- {&Stmt{tx: &Tx{}, txds: &driverStmt{Locker: &sync.Mutex{}, si: stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"},
+ {&Stmt{cg: &Tx{}, cgds: &driverStmt{Locker: &sync.Mutex{}, si: stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"},
}
for _, test := range tests {
if err := test.stmt.Close(); err != want {
@@ -1024,6 +1027,196 @@ func TestTxStmt(t *testing.T) {
}
}
+func TestTxStmtPreparedOnce(t *testing.T) {
+ db := newTestDB(t, "")
+ defer closeDB(t, db)
+ exec(t, db, "CREATE|t1|name=string,age=int32")
+
+ prepares0 := numPrepares(t, db)
+
+ // db.Prepare increments numPrepares.
+ stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+ if err != nil {
+ t.Fatalf("Stmt, err = %v, %v", stmt, err)
+ }
+ defer stmt.Close()
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatalf("Begin = %v", err)
+ }
+
+ txs1 := tx.Stmt(stmt)
+ txs2 := tx.Stmt(stmt)
+
+ _, err = txs1.Exec("Go", 7)
+ if err != nil {
+ t.Fatalf("Exec = %v", err)
+ }
+ txs1.Close()
+
+ _, err = txs2.Exec("Gopher", 8)
+ if err != nil {
+ t.Fatalf("Exec = %v", err)
+ }
+ txs2.Close()
+
+ err = tx.Commit()
+ if err != nil {
+ t.Fatalf("Commit = %v", err)
+ }
+
+ if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
+ t.Errorf("executed %d Prepare statements; want 1", prepares)
+ }
+}
+
+func TestTxStmtClosedRePrepares(t *testing.T) {
+ db := newTestDB(t, "")
+ defer closeDB(t, db)
+ exec(t, db, "CREATE|t1|name=string,age=int32")
+
+ prepares0 := numPrepares(t, db)
+
+ // db.Prepare increments numPrepares.
+ stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+ if err != nil {
+ t.Fatalf("Stmt, err = %v, %v", stmt, err)
+ }
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatalf("Begin = %v", err)
+ }
+ err = stmt.Close()
+ if err != nil {
+ t.Fatalf("stmt.Close() = %v", err)
+ }
+ // tx.Stmt increments numPrepares because stmt is closed.
+ txs := tx.Stmt(stmt)
+ if txs.stickyErr != nil {
+ t.Fatal(txs.stickyErr)
+ }
+ if txs.parentStmt != nil {
+ t.Fatal("expected nil parentStmt")
+ }
+ _, err = txs.Exec(`Eric`, 82)
+ if err != nil {
+ t.Fatalf("txs.Exec = %v", err)
+ }
+
+ err = txs.Close()
+ if err != nil {
+ t.Fatalf("txs.Close = %v", err)
+ }
+
+ tx.Rollback()
+
+ if prepares := numPrepares(t, db) - prepares0; prepares != 2 {
+ t.Errorf("executed %d Prepare statements; want 2", prepares)
+ }
+}
+
+func TestParentStmtOutlivesTxStmt(t *testing.T) {
+ db := newTestDB(t, "")
+ defer closeDB(t, db)
+ exec(t, db, "CREATE|t1|name=string,age=int32")
+
+ // Make sure everything happens on the same connection.
+ db.SetMaxOpenConns(1)
+
+ prepares0 := numPrepares(t, db)
+
+ // db.Prepare increments numPrepares.
+ stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+ if err != nil {
+ t.Fatalf("Stmt, err = %v, %v", stmt, err)
+ }
+ defer stmt.Close()
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatalf("Begin = %v", err)
+ }
+ txs := tx.Stmt(stmt)
+ if len(stmt.css) != 1 {
+ t.Fatalf("len(stmt.css) = %v; want 1", len(stmt.css))
+ }
+ err = txs.Close()
+ if err != nil {
+ t.Fatalf("txs.Close() = %v", err)
+ }
+ err = tx.Rollback()
+ if err != nil {
+ t.Fatalf("tx.Rollback() = %v", err)
+ }
+ // txs must not be valid.
+ _, err = txs.Exec("Suzan", 30)
+ if err == nil {
+ t.Fatalf("txs.Exec(), expected err")
+ }
+ // Stmt must still be valid.
+ _, err = stmt.Exec("Janina", 25)
+ if err != nil {
+ t.Fatalf("stmt.Exec() = %v", err)
+ }
+
+ if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
+ t.Errorf("executed %d Prepare statements; want 1", prepares)
+ }
+}
+
+// Test that tx.Stmt called with a statement already
+// associated with tx as argument re-prepares the same
+// statement again.
+func TestTxStmtFromTxStmtRePrepares(t *testing.T) {
+ db := newTestDB(t, "")
+ defer closeDB(t, db)
+ exec(t, db, "CREATE|t1|name=string,age=int32")
+ prepares0 := numPrepares(t, db)
+ // db.Prepare increments numPrepares.
+ stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+ if err != nil {
+ t.Fatalf("Stmt, err = %v, %v", stmt, err)
+ }
+ defer stmt.Close()
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatalf("Begin = %v", err)
+ }
+ txs1 := tx.Stmt(stmt)
+
+ // tx.Stmt(txs1) increments numPrepares because txs1 already
+ // belongs to a transaction (albeit the same transaction).
+ txs2 := tx.Stmt(txs1)
+ if txs2.stickyErr != nil {
+ t.Fatal(txs2.stickyErr)
+ }
+ if txs2.parentStmt != nil {
+ t.Fatal("expected nil parentStmt")
+ }
+ _, err = txs2.Exec(`Eric`, 82)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = txs1.Close()
+ if err != nil {
+ t.Fatalf("txs1.Close = %v", err)
+ }
+ err = txs2.Close()
+ if err != nil {
+ t.Fatalf("txs1.Close = %v", err)
+ }
+ err = tx.Rollback()
+ if err != nil {
+ t.Fatalf("tx.Rollback = %v", err)
+ }
+
+ if prepares := numPrepares(t, db) - prepares0; prepares != 2 {
+ t.Errorf("executed %d Prepare statements; want 2", prepares)
+ }
+}
+
// Issue: https://golang.org/issue/2784
// This test didn't fail before because we got lucky with the fakedb driver.
// It was failing, and now not, in github.com/bradfitz/go-sql-test
@@ -1108,6 +1301,69 @@ func TestTxErrBadConn(t *testing.T) {
}
}
+func TestConnQuery(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ conn, err := db.Conn(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+
+ var name string
+ err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", 3).Scan(&name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if name != "Chris" {
+ t.Fatalf("unexpected result, got %q want Chris", name)
+ }
+
+ err = conn.PingContext(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestConnTx(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ conn, err := db.Conn(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+
+ tx, err := conn.BeginTx(ctx, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ insertName, insertAge := "Nancy", 33
+ _, err = tx.ExecContext(ctx, "INSERT|people|name=?,age=?,photo=APHOTO", insertName, insertAge)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = tx.Commit()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var selectName string
+ err = conn.QueryRowContext(ctx, "SELECT|people|name|age=?", insertAge).Scan(&selectName)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if selectName != insertName {
+ t.Fatalf("got %q want %q", selectName, insertName)
+ }
+}
+
// Tests fix for issue 2542, that we release a lock when querying on
// a closed connection.
func TestIssue2542Deadlock(t *testing.T) {
@@ -1831,8 +2087,8 @@ func TestConnMaxLifetime(t *testing.T) {
}
// Expire first conn
- offset = time.Second * 11
- db.SetConnMaxLifetime(time.Second * 10)
+ offset = 11 * time.Second
+ db.SetConnMaxLifetime(10 * time.Second)
if err != nil {
t.Fatal(err)
}
@@ -2078,9 +2334,13 @@ func TestStmtCloseOrder(t *testing.T) {
// Test cases where there's more than maxBadConnRetries bad connections in the
// pool (issue 8834)
func TestManyErrBadConn(t *testing.T) {
- manyErrBadConnSetup := func() *DB {
+ manyErrBadConnSetup := func(first ...func(db *DB)) *DB {
db := newTestDB(t, "people")
+ for _, f := range first {
+ f(db)
+ }
+
nconn := maxBadConnRetries + 1
db.SetMaxIdleConns(nconn)
db.SetMaxOpenConns(nconn)
@@ -2148,6 +2408,128 @@ func TestManyErrBadConn(t *testing.T) {
if err = stmt.Close(); err != nil {
t.Fatal(err)
}
+
+ // Stmt.Exec
+ db = manyErrBadConnSetup(func(db *DB) {
+ stmt, err = db.Prepare("INSERT|people|name=Julia,age=19")
+ if err != nil {
+ t.Fatal(err)
+ }
+ })
+ defer closeDB(t, db)
+ _, err = stmt.Exec()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err = stmt.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Stmt.Query
+ db = manyErrBadConnSetup(func(db *DB) {
+ stmt, err = db.Prepare("SELECT|people|age,name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ })
+ defer closeDB(t, db)
+ rows, err = stmt.Query()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err = rows.Close(); err != nil {
+ t.Fatal(err)
+ }
+ if err = stmt.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ // Conn
+ db = manyErrBadConnSetup()
+ defer closeDB(t, db)
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ conn, err := db.Conn(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = conn.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Ping
+ db = manyErrBadConnSetup()
+ defer closeDB(t, db)
+ err = db.PingContext(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+// TestIssue20575 ensures the Rows from query does not block
+// closing a transaction. Ensure Rows is closed while closing a trasaction.
+func TestIssue20575(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
+ defer cancel()
+ _, err = tx.QueryContext(ctx, "SELECT|people|age,name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Do not close Rows from QueryContext.
+ err = tx.Rollback()
+ if err != nil {
+ t.Fatal(err)
+ }
+ select {
+ default:
+ case <-ctx.Done():
+ t.Fatal("timeout: failed to rollback query without closing rows:", ctx.Err())
+ }
+}
+
+// TestIssue20622 tests closing the transaction before rows is closed, requires
+// the race detector to fail.
+func TestIssue20622(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ tx, err := db.BeginTx(ctx, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ rows, err := tx.Query("SELECT|people|age,name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ count := 0
+ for rows.Next() {
+ count++
+ var age int
+ var name string
+ if err := rows.Scan(&age, &name); err != nil {
+ t.Fatal("scan failed", err)
+ }
+
+ if count == 1 {
+ cancel()
+ }
+ time.Sleep(100 * time.Millisecond)
+ }
+ rows.Close()
+ tx.Commit()
}
// golang.org/issue/5718
@@ -2751,7 +3133,7 @@ func TestIssue18429(t *testing.T) {
if err != nil {
return
}
- // This is expected to give a cancel error many, but not all the time.
+ // This is expected to give a cancel error most, but not all the time.
// Test failure will happen with a panic or other race condition being
// reported.
rows, _ := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|")
@@ -2766,6 +3148,46 @@ func TestIssue18429(t *testing.T) {
wg.Wait()
}
+// TestIssue20160 attempts to test a short context life on a stmt Query.
+func TestIssue20160(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ ctx := context.Background()
+ sem := make(chan bool, 20)
+ var wg sync.WaitGroup
+
+ const milliWait = 30
+
+ stmt, err := db.PrepareContext(ctx, "SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer stmt.Close()
+
+ for i := 0; i < 100; i++ {
+ sem <- true
+ wg.Add(1)
+ go func() {
+ defer func() {
+ <-sem
+ wg.Done()
+ }()
+ ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond)
+ defer cancel()
+
+ // This is expected to give a cancel error most, but not all the time.
+ // Test failure will happen with a panic or other race condition being
+ // reported.
+ rows, _ := stmt.QueryContext(ctx)
+ if rows != nil {
+ rows.Close()
+ }
+ }()
+ }
+ wg.Wait()
+}
+
// TestIssue18719 closes the context right before use. The sql.driverConn
// will nil out the ci on close in a lock, but if another process uses it right after
// it will panic with on the nil ref.
@@ -2788,7 +3210,7 @@ func TestIssue18719(t *testing.T) {
// Wait for the context to cancel and tx to rollback.
for tx.isDone() == false {
- time.Sleep(time.Millisecond * 3)
+ time.Sleep(3 * time.Millisecond)
}
}
defer func() { hookTxGrabConn = nil }()
@@ -2807,19 +3229,64 @@ func TestIssue18719(t *testing.T) {
// canceled context.
cancel()
- waitForRowsClose(t, rows, 5*time.Second)
+}
+
+func TestIssue20647(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ conn, err := db.Conn(ctx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+
+ stmt, err := conn.PrepareContext(ctx, "SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer stmt.Close()
+
+ rows1, err := stmt.QueryContext(ctx)
+ if err != nil {
+ t.Fatal("rows1", err)
+ }
+ defer rows1.Close()
+
+ rows2, err := stmt.QueryContext(ctx)
+ if err != nil {
+ t.Fatal("rows2", err)
+ }
+ defer rows2.Close()
+
+ if rows1.dc != rows2.dc {
+ t.Fatal("stmt prepared on Conn does not use same connection")
+ }
}
func TestConcurrency(t *testing.T) {
- doConcurrentTest(t, new(concurrentDBQueryTest))
- doConcurrentTest(t, new(concurrentDBExecTest))
- doConcurrentTest(t, new(concurrentStmtQueryTest))
- doConcurrentTest(t, new(concurrentStmtExecTest))
- doConcurrentTest(t, new(concurrentTxQueryTest))
- doConcurrentTest(t, new(concurrentTxExecTest))
- doConcurrentTest(t, new(concurrentTxStmtQueryTest))
- doConcurrentTest(t, new(concurrentTxStmtExecTest))
- doConcurrentTest(t, new(concurrentRandomTest))
+ list := []struct {
+ name string
+ ct concurrentTest
+ }{
+ {"Query", new(concurrentDBQueryTest)},
+ {"Exec", new(concurrentDBExecTest)},
+ {"StmtQuery", new(concurrentStmtQueryTest)},
+ {"StmtExec", new(concurrentStmtExecTest)},
+ {"TxQuery", new(concurrentTxQueryTest)},
+ {"TxExec", new(concurrentTxExecTest)},
+ {"TxStmtQuery", new(concurrentTxStmtQueryTest)},
+ {"TxStmtExec", new(concurrentTxStmtExecTest)},
+ {"Random", new(concurrentRandomTest)},
+ }
+ for _, item := range list {
+ t.Run(item.name, func(t *testing.T) {
+ doConcurrentTest(t, item.ct)
+ })
+ }
}
func TestConnectionLeak(t *testing.T) {
@@ -2874,6 +3341,131 @@ func TestConnectionLeak(t *testing.T) {
wg.Wait()
}
+type nvcDriver struct {
+ fakeDriver
+ skipNamedValueCheck bool
+}
+
+func (d *nvcDriver) Open(dsn string) (driver.Conn, error) {
+ c, err := d.fakeDriver.Open(dsn)
+ fc := c.(*fakeConn)
+ fc.db.allowAny = true
+ return &nvcConn{fc, d.skipNamedValueCheck}, err
+}
+
+type nvcConn struct {
+ *fakeConn
+ skipNamedValueCheck bool
+}
+
+type decimal struct {
+ value int
+}
+
+type doNotInclude struct{}
+
+var _ driver.NamedValueChecker = &nvcConn{}
+
+func (c *nvcConn) CheckNamedValue(nv *driver.NamedValue) error {
+ if c.skipNamedValueCheck {
+ return driver.ErrSkip
+ }
+ switch v := nv.Value.(type) {
+ default:
+ return driver.ErrSkip
+ case Out:
+ switch ov := v.Dest.(type) {
+ default:
+ return errors.New("unkown NameValueCheck OUTPUT type")
+ case *string:
+ *ov = "from-server"
+ nv.Value = "OUT:*string"
+ }
+ return nil
+ case decimal, []int64:
+ return nil
+ case doNotInclude:
+ return driver.ErrRemoveArgument
+ }
+}
+
+func TestNamedValueChecker(t *testing.T) {
+ Register("NamedValueCheck", &nvcDriver{})
+ db, err := Open("NamedValueCheck", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ _, err = db.ExecContext(ctx, "WIPE")
+ if err != nil {
+ t.Fatal("exec wipe", err)
+ }
+
+ _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any,str1=string,out1=string,array1=any")
+ if err != nil {
+ t.Fatal("exec create", err)
+ }
+
+ o1 := ""
+ _, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A,str1=?,out1=?O1,array1=?", Named("A", decimal{123}), "hello", Named("O1", Out{Dest: &o1}), []int64{42, 128, 707}, doNotInclude{})
+ if err != nil {
+ t.Fatal("exec insert", err)
+ }
+ var (
+ str1 string
+ dec1 decimal
+ arr1 []int64
+ )
+ err = db.QueryRowContext(ctx, "SELECT|keys|dec1,str1,array1|").Scan(&dec1, &str1, &arr1)
+ if err != nil {
+ t.Fatal("select", err)
+ }
+
+ list := []struct{ got, want interface{} }{
+ {o1, "from-server"},
+ {dec1, decimal{123}},
+ {str1, "hello"},
+ {arr1, []int64{42, 128, 707}},
+ }
+
+ for index, item := range list {
+ if !reflect.DeepEqual(item.got, item.want) {
+ t.Errorf("got %#v wanted %#v for index %d", item.got, item.want, index)
+ }
+ }
+}
+
+func TestNamedValueCheckerSkip(t *testing.T) {
+ Register("NamedValueCheckSkip", &nvcDriver{skipNamedValueCheck: true})
+ db, err := Open("NamedValueCheckSkip", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ _, err = db.ExecContext(ctx, "WIPE")
+ if err != nil {
+ t.Fatal("exec wipe", err)
+ }
+
+ _, err = db.ExecContext(ctx, "CREATE|keys|dec1=any")
+ if err != nil {
+ t.Fatal("exec create", err)
+ }
+
+ _, err = db.ExecContext(ctx, "INSERT|keys|dec1=?A", Named("A", decimal{123}))
+ if err == nil {
+ t.Fatalf("expected error with bad argument, got %v", err)
+ }
+}
+
// badConn implements a bad driver.Conn, for TestBadDriver.
// The Exec method panics.
type badConn struct{}
@@ -2965,6 +3557,24 @@ func TestPing(t *testing.T) {
}
}
+// Issue 18101.
+func TestTypedString(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ type Str string
+ var scanned Str
+
+ err := db.QueryRow("SELECT|people|name|name=?", "Alice").Scan(&scanned)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expected := Str("Alice")
+ if scanned != expected {
+ t.Errorf("expected %+v, got %+v", expected, scanned)
+ }
+}
+
func BenchmarkConcurrentDBExec(b *testing.B) {
b.ReportAllocs()
ct := new(concurrentDBExecTest)
diff --git a/libgo/go/debug/dwarf/export_test.go b/libgo/go/debug/dwarf/export_test.go
new file mode 100644
index 0000000..b8a25ff
--- /dev/null
+++ b/libgo/go/debug/dwarf/export_test.go
@@ -0,0 +1,7 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package dwarf
+
+var PathJoin = pathJoin
diff --git a/libgo/go/debug/dwarf/line.go b/libgo/go/debug/dwarf/line.go
index ed82fee..4e6e142 100644
--- a/libgo/go/debug/dwarf/line.go
+++ b/libgo/go/debug/dwarf/line.go
@@ -9,6 +9,7 @@ import (
"fmt"
"io"
"path"
+ "strings"
)
// A LineReader reads a sequence of LineEntry structures from a DWARF
@@ -247,10 +248,10 @@ func (r *LineReader) readHeader() error {
if len(directory) == 0 {
break
}
- if !path.IsAbs(directory) {
+ if !pathIsAbs(directory) {
// Relative paths are implicitly relative to
// the compilation directory.
- directory = path.Join(r.directories[0], directory)
+ directory = pathJoin(r.directories[0], directory)
}
r.directories = append(r.directories, directory)
}
@@ -283,11 +284,11 @@ func (r *LineReader) readFileEntry() (bool, error) {
}
off := r.buf.off
dirIndex := int(r.buf.uint())
- if !path.IsAbs(name) {
+ if !pathIsAbs(name) {
if dirIndex >= len(r.directories) {
return false, DecodeError{"line", off, "directory index too large"}
}
- name = path.Join(r.directories[dirIndex], name)
+ name = pathJoin(r.directories[dirIndex], name)
}
mtime := r.buf.uint()
length := int(r.buf.uint())
@@ -588,3 +589,68 @@ func (r *LineReader) SeekPC(pc uint64, entry *LineEntry) error {
*entry = next
}
}
+
+// pathIsAbs returns whether path is an absolute path (or "full path
+// name" in DWARF parlance). This is in "whatever form makes sense for
+// the host system", so this accepts both UNIX-style and DOS-style
+// absolute paths. We avoid the filepath package because we want this
+// to behave the same regardless of our host system and because we
+// don't know what system the paths came from.
+func pathIsAbs(path string) bool {
+ _, path = splitDrive(path)
+ return len(path) > 0 && (path[0] == '/' || path[0] == '\\')
+}
+
+// pathJoin joins dirname and filename. filename must be relative.
+// DWARF paths can be UNIX-style or DOS-style, so this handles both.
+func pathJoin(dirname, filename string) string {
+ if len(dirname) == 0 {
+ return filename
+ }
+ // dirname should be absolute, which means we can determine
+ // whether it's a DOS path reasonably reliably by looking for
+ // a drive letter or UNC path.
+ drive, dirname := splitDrive(dirname)
+ if drive == "" {
+ // UNIX-style path.
+ return path.Join(dirname, filename)
+ }
+ // DOS-style path.
+ drive2, filename := splitDrive(filename)
+ if drive2 != "" {
+ if strings.ToLower(drive) != strings.ToLower(drive2) {
+ // Different drives. There's not much we can
+ // do here, so just ignore the directory.
+ return drive2 + filename
+ }
+ // Drives are the same. Ignore drive on filename.
+ }
+ if !(strings.HasSuffix(dirname, "/") || strings.HasSuffix(dirname, `\`)) && dirname != "" {
+ dirname += `\`
+ }
+ return drive + dirname + filename
+}
+
+// splitDrive splits the DOS drive letter or UNC share point from
+// path, if any. path == drive + rest
+func splitDrive(path string) (drive, rest string) {
+ if len(path) >= 2 && path[1] == ':' {
+ if c := path[0]; 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
+ return path[:2], path[2:]
+ }
+ }
+ if len(path) > 3 && (path[0] == '\\' || path[0] == '/') && (path[1] == '\\' || path[1] == '/') {
+ // Normalize the path so we can search for just \ below.
+ npath := strings.Replace(path, "/", `\`, -1)
+ // Get the host part, which must be non-empty.
+ slash1 := strings.IndexByte(npath[2:], '\\') + 2
+ if slash1 > 2 {
+ // Get the mount-point part, which must be non-empty.
+ slash2 := strings.IndexByte(npath[slash1+1:], '\\') + slash1 + 1
+ if slash2 > slash1 {
+ return path[:slash2], path[slash2:]
+ }
+ }
+ }
+ return "", path
+}
diff --git a/libgo/go/debug/dwarf/line_test.go b/libgo/go/debug/dwarf/line_test.go
index cc363f5..11a2544 100644
--- a/libgo/go/debug/dwarf/line_test.go
+++ b/libgo/go/debug/dwarf/line_test.go
@@ -7,6 +7,7 @@ package dwarf_test
import (
. "debug/dwarf"
"io"
+ "strings"
"testing"
)
@@ -46,6 +47,46 @@ func TestLineELFGCC(t *testing.T) {
testLineTable(t, want, elfData(t, "testdata/line-gcc.elf"))
}
+func TestLineGCCWindows(t *testing.T) {
+ // Generated by:
+ // > gcc --version
+ // gcc (tdm64-1) 4.9.2
+ // > gcc -g -o line-gcc-win.bin line1.c C:\workdir\go\src\debug\dwarf\testdata\line2.c
+
+ toWindows := func(lf *LineFile) *LineFile {
+ lf2 := *lf
+ lf2.Name = strings.Replace(lf2.Name, "/home/austin/go.dev/", "C:\\workdir\\go\\", -1)
+ lf2.Name = strings.Replace(lf2.Name, "/", "\\", -1)
+ return &lf2
+ }
+ file1C := toWindows(file1C)
+ file1H := toWindows(file1H)
+ file2C := toWindows(file2C)
+
+ // Line table based on objdump --dwarf=rawline,decodedline
+ want := []LineEntry{
+ {Address: 0x401530, File: file1H, Line: 2, IsStmt: true},
+ {Address: 0x401538, File: file1H, Line: 5, IsStmt: true},
+ {Address: 0x401541, File: file1H, Line: 6, IsStmt: true, Discriminator: 3},
+ {Address: 0x40154b, File: file1H, Line: 5, IsStmt: true, Discriminator: 3},
+ {Address: 0x40154f, File: file1H, Line: 5, IsStmt: false, Discriminator: 1},
+ {Address: 0x401555, File: file1H, Line: 7, IsStmt: true},
+ {Address: 0x40155b, File: file1C, Line: 6, IsStmt: true},
+ {Address: 0x401563, File: file1C, Line: 6, IsStmt: true},
+ {Address: 0x401568, File: file1C, Line: 7, IsStmt: true},
+ {Address: 0x40156d, File: file1C, Line: 8, IsStmt: true},
+ {Address: 0x401572, File: file1C, Line: 9, IsStmt: true},
+ {Address: 0x401578, EndSequence: true},
+
+ {Address: 0x401580, File: file2C, Line: 4, IsStmt: true},
+ {Address: 0x401588, File: file2C, Line: 5, IsStmt: true},
+ {Address: 0x401595, File: file2C, Line: 6, IsStmt: true},
+ {Address: 0x40159b, EndSequence: true},
+ }
+
+ testLineTable(t, want, peData(t, "testdata/line-gcc-win.bin"))
+}
+
func TestLineELFClang(t *testing.T) {
// Generated by:
// # clang --version | head -n1
@@ -183,6 +224,11 @@ func testLineTable(t *testing.T, want []LineEntry, d *Data) {
}
t.Fatal("lr.Next:", err)
}
+ // Ignore sources from the Windows build environment.
+ if strings.HasPrefix(line.File.Name, "C:\\crossdev\\") ||
+ strings.HasPrefix(line.File.Name, "C:/crossdev/") {
+ continue
+ }
got = append(got, line)
}
}
@@ -227,3 +273,42 @@ func dumpLines(t *testing.T, lines []LineEntry) {
t.Logf(" %+v File:%+v", l, l.File)
}
}
+
+type joinTest struct {
+ dirname, filename string
+ path string
+}
+
+var joinTests = []joinTest{
+ {"a", "b", "a/b"},
+ {"a", "", "a"},
+ {"", "b", "b"},
+ {"/a", "b", "/a/b"},
+ {"/a/", "b", "/a/b"},
+
+ {`C:\Windows\`, `System32`, `C:\Windows\System32`},
+ {`C:\Windows\`, ``, `C:\Windows\`},
+ {`C:\`, `Windows`, `C:\Windows`},
+ {`C:\Windows\`, `C:System32`, `C:\Windows\System32`},
+ {`C:\Windows`, `a/b`, `C:\Windows\a/b`},
+ {`\\host\share\`, `foo`, `\\host\share\foo`},
+ {`\\host\share\`, `foo\bar`, `\\host\share\foo\bar`},
+ {`//host/share/`, `foo/bar`, `//host/share/foo/bar`},
+
+ // The following are "best effort". We shouldn't see relative
+ // base directories in DWARF, but these test that pathJoin
+ // doesn't fail miserably if it sees one.
+ {`C:`, `a`, `C:a`},
+ {`C:`, `a\b`, `C:a\b`},
+ {`C:.`, `a`, `C:.\a`},
+ {`C:a`, `b`, `C:a\b`},
+}
+
+func TestPathJoin(t *testing.T) {
+ for _, test := range joinTests {
+ got := PathJoin(test.dirname, test.filename)
+ if test.path != got {
+ t.Errorf("pathJoin(%q, %q) = %q, want %q", test.dirname, test.filename, got, test.path)
+ }
+ }
+}
diff --git a/libgo/go/debug/dwarf/testdata/line-gcc-win.bin b/libgo/go/debug/dwarf/testdata/line-gcc-win.bin
new file mode 100644
index 0000000000000000000000000000000000000000..583ad44dd07dabb77cadb01043a45e50295ae7d4
GIT binary patch
literal 133202
zcmeFa34B!5**|{noja2mNHP;hAZ#)~z@UH$n}LE(mVrqPBqRaBZ3xK(QnQT71cFNq
z4Opim7Tm3VX
zyfmqHLsN%8+TOOly{^SyU)S2&7W1!*_}e>M{Y|a@vdS8NOIt%^Rz}9KJQa0SP>6=B
zvPAUWscXbln)szth-2bZFza*Db^gX_DmMDj_OV)Hd$NlKx&H@`vz!Yl{%OwIMtdYgR1M6$9Nn
z9zT>tDmThu|M*4K+F1>Cu{tn!kVgT&lsB_7iHA=>RQ1hjmx9NrECGDo_)f#u_JLer
zR#eJy8Btd52(xTLAOoTxFsn<-`6#`$_)>?Njj!#)a_c%eh_!YYexf!{8`&+QeY2Wm
zd|cPv@TC0Bw+Vqne0{S@t80n7fqtmal>S)+lAnMG^v#MjbGj_o3qO(z;A{H?#M-_y
z=1N94<$pK6RL3QfXa1sIO3o-;!0^64IP`rM-w?jGPeAxe&X`lkoL`NFvjYuG?Kf<2
zL$lo6c`Ub_F57PHL$OdKeN0Ow{odMJ#XcQ63(f3
zObQPj5YzzxrvX}Ex*fbV$L4b<`cUJRqGjjBx)5kDyy7``g@s6nZGEwGpG2<`{WW+1
zLI?H^;M0EwI$J1_a~#1!aUIkfCgm(c;DiscTt=*fi2M4pSlanVbm*QUEfy*43-#>J
z-}fZtvHznnLLB{O|yFL=IGf<0X^1RDpTvP5@3hYN1&qkw7P
zomihmD8=0%$qYi{SzfjzBOzZw&
zaZ1^iC`j0`loLsbitI^ZiDu`=CIh#zwtYmUn@+hbA-cws-IwcYYrucUfZU
z(F=qKZg0-hmes#qzV~;IiujTKhem_9?YE)$bD_lIXCdId_B`~?!q*#<&sQS-SN&gx
zTxfe#3&r2*zl`X3*)LJP>|cfAd&}d;LOuJm{tobq7yRPNm&<$Jc7OIj*-Ru(k~2St
zc>5!=Le4saY9gl+tVG5d{8ClNeH97kA_h5&Nw@=fNMwu!8F%L57u{m(_YqklM<;Zs
zb9jFSQcE~LJRdP^*-sto{ENaD7GF?&;XdyZWqE6lIQfx4eW5o@N232h51nlBZGS>D
zJvkA$|CLb|^L;Rpv&EdjjA?NCpM>wWfdek;0^V(hA>f@z&(s$kM}7z(+anZzbs(pw
zMTjFyiMIoBjFEBZa1OZmVQ)iBN3MZ?u<-38hyO7!5Z~Kh58e*Q%ke8n!rU$U&qELE
zf9|7!fgSL~croO7m&5YNnCL%^phIr!?%cl*HQ1ktAn^2GxX+B#6he2uW=1
z@l~Xf$O>(D{sILF)o1SrX$J=mhqh0+XF7$Y;Z}%u%e=l~e<*Q@8#&vYi=Rt;{r{28
z9>_*PXnSZaM#vUKfqY$_mtP)#r#$`|=vbb={|*T5@a7}&!ai?4C!dexk@2qcFWN`>
zLvpK;+|ir86T2xr;3mRfOychWABk~?X8E0j8V@#)i;;FD73vSZ*?gC
z1FFl_6&SPER-k@2(CD4t|ISECHsf6ct3YXr_l!e6p5l)Cd-6)eAoL;&p{((r_9?Y;IrDr3UA9sFS7_b`&VD-ynn1wU-h
z4kfDGWr_3L%e0>Zd%y4qB#V3YYLLk-UT~!Ir=j@I`hQ8|$hN-n_y-TGzX<4t43f{ef!8lG|E8EGK4^Ve~^z({%rsG7!Ht?%PDe1
z>xR!g@To|Y<-7aOBG2s^o4`QD_n!eME8Kd%Ru-?KDyJEiAM~|}3DXhPw%21hq4-NgvlkF`B
z%b%f4P(31G!r}dPjk`iST%o<$^8uz2;oVw{h`d+n`0e??@7;PC69MnGi$Ii5@2iOa
zu_FGbig;hhp%w3OQ-R{agZ)7a&ML|FZzP<5TuHNF;d{vBwU49HD-!c2Zr}{Oh`gkO
zJUT{>|2@y6gYL`y%)BQM#Jl}!YOwfgA&2vR;Dm46q1Z1&iI7`$zxW5m13y9k^==)3
z?4a4VL26n2NGP$gKa^N@uq|}<$+s;Akwg`@6&_$YmK?CiO
zy)KyoXZNR4;D->9!MI-cO73^TO|A#jZlLEae}AC|MTdudRAN?)WH!VN>p+r_f
zFOK&WZ#fKKfAN;%rKL;#-mTDI3hug?BE4VSLWp{>w+Fw1dvR>`rp4TQW7E0kb{3nx
zww^|B?zPipuZ>MpJ$4V$z+krDe?InK+&{cqze5pnA9)j_&Y3G@js9HDQ~vWq1Bcc8
z!2LV+nN6FxZ^s^${rU%HH+h?OI!LwibX)&;jn<3wL><|JluglRm1wM$8ZR!p{z1;%
zk&7TF$Itgl42<}HLm!b#7JeSQTZR@KVo&jMoK*En{ax
z{K(sb`k$?TP9on|;468YKnC%?1D+gRcIn!>S9-o7q?;L&B7JtGymY=4W>(BgrV7^z+(b26`ChPeN
zU~->Gx!g1RYrmR#>*=5lU}i@viqL|6vC*Nw{V)`tkU?FB44FDg6xQR$-Us3qGQ2bA!!k=QHRETBWKSGn9
z4=s2jHigy`e>)h8&*Skg?))+jN>=K;Uf%QKh5kd0KSISkGe>3o=u64*Wu>_giiYAZ
zqY5j~)dzCMQl1hM&O}vUQy<#C@-_7Qft=yQrq$$L@7B8nWjlD7YM}@;){(DaT7C_S
zRIHM*&JXtUavA%D<5ds^6NP^j+9I_68%Tu&=UoT_YbDI;9z*mUaJ~eJ1~Dv{4uOQ|
z{TLNP@!&C#yCr#iAm=)Y2JJnOGJ7|`K#mu`Pf;Y;V-MtP0qWm?sU?&M<|48ddV;rO
z5gT{vAdhsRr*N00`4Eea+@22{v61G0iA|(AUiIGwJw}o*_XpIY=OFE#B0c6hz^dq;
z5A@hbtj1yiOBg#AYX1p8Yo@g49U^DJpJTrYB^>mG>v#^Z6alOAZF`vh=}7VDlWKfP
z-T%?}SU@|3M8*oNDEps&hr0Z6ETT}qv5j&DyOIXrL`DG#+(rV4j2WO=rvFRCAVpFI
zR;KwhqVcY#hQsjwabN#N4pc$jyteC)fWdKt@g^Fke+G%8#e4P_oWBp%u^;PU>LWhM
zvFeZNw|^-;msls<(C7Vj-`^-uzBx)D=uFan4IGvuNT|LT`n|n{eOnfghA*c7d0$~)
zR1}1yDbFP%UyiJo<9VeqV<7K2e;FmA97beWKj8?R&B5Jx8?A_Vjqg
z_KFws%MyX~@&yMg;(Ir_9U-*9_uGeK*OXte;DyfL6!!fYdt__BKpO>`k>W4+Kj}n1
zdycy|jl-jH1J)6R1C3iggWQaxsjvt0$3@|Ng=h&2K>vX{>CZ>;(cnJ|)z_eGKleUS
zg1lXzBX89%^u4`3e?;Dl>q6Tv-n}veh!OBcb}zMNl8*x@`VteI@3#Qw*q$A2e<`3zan7mTg)jjI<(If=YSb`^0jW
z_lYIh+rEds>B^10$_-}3(TLCHzgKdqKjsNx(D#Qh)`xnYMGZaM**~bVWq-ix#g$DaZQwnd#UvAuTHtK6s
z2rDISr0|9NlKn9hf4~1V>>v>H8=?B8ixM}a?Laosjb4dk0(zgey~k-&1A*^`v=4zh
zM;v|BdLDcJld3N}@mcI5JJS*+>5v<@?Y%4ikoa7BNc+1zQEuoi`KfK{O+FD5!N>1)T3g
zkj`IV4A@DrY|qG~SX7~TjU`lnN;qG~B!W1+@a6~2)c3@H5`X2XTvUOy6Ff$HVKgQd
z35()Ip?H)O1WzFBK+f-2d*S>N%|_cZ?jk2X;c|9LeFHg}$O1n(96e9IN3Yw#&qKm_
zA;ge+mJ&$L4;YEJXPgV)ft+m|f6i$XBidtpLSOJ&XU5TrvIG>puf?WfZxc$CpvZll
zZz0fR4s;6wnUV5*9p8&3kuMZ4@%58A4}$MkQtWLIJo;mfApR;w;eFs9{RQvmXxb@n
zAA>2Zb6CRp2t1HPqcx}OOE~Y4ymblZ4WMW}`X(ao1%1HzdHm96Am?dlI*z`Oa7I~L
z?H>*}F9hT{nTBlyYXTm~`6&tia!3DB^z)Q|!A556<2Yn5);A6N8FjVCwIY(2gAgQ!`NkVLT&r@IEB6f*@5{M+_C0X3QzOyCL8uK@_wbbFv
zR;0bXt=*qrR=KRWeED=?d3Q9muJ3HFYj28e_UG4>FNGg}DmO;j8=KoU`P=JS*GJ6Y
zm8*i)ODZbQoi3{C+G9<1&Hm=Ljt+lYqranReQQ%=6V8g&NBsF!6_qulC>Nr(E%vce
zwU!j*HsE+!q@%Mr=Eu>qSX-OFqouC785AEpi$vjx;zSz!`74)~nYmcmdU0#pCRIAl
zcetf4wgH9BpT5vPwS!KpP3_2^x_*X#>iX$^e|~!;wy~~xF#sNzw|+b@FcaTh_&$K|
z)A+uK?=SFOhI-jFbJP5}bm%SC)DrPG)-^SEwnrAqC#|@l0XgdMPmTIF)OGk<+x$%}
zb?YNDJ0kV5rnXk$_pfSdk9F2Hujq`lZ|1=2)b|Ul;S&S+Q{D@neOn
zYHy1nE;Hn&rq~95Jr3RZ3%aIuk(^ofXh)>8p$(PS+*V&lY16^ISX+Htvmb5PL5!&l
zv&`|~WZ~8|#n6tIM(pxtzRdGwChqPEFxlN9-Kr_lWhQ77#%ojL3!;PlyHor_DYz^J2U76T($a^eeGu-u_~wJAGue~z4S_Czdp^D!K$F{rZwz!d+}rT&2Hgvn&bM3x
zdN+~MtGv(?!@`f?&J98g6@NxGYRQ~_QPF-
z?+nlZxT7W`eb9cmFnx
zK76}C?}qydzL%3c++X9{4f+_|c~fy#4RiqR8~9!g`Y_xnun^w>x&ZFQ`1XR1!ufQBq<)R%muUmMvk-}Y&w$>GORvCTzL64H@
zLt9grA7Ko53txJk$W8S(@EniFm;A}q+zzLEgyGPj)na<~5H#h*{8D;fQ+Sj|jJnz-
zd|gg4e1joezt#)1weWK}glnCm)6+!y*X%ilf0oCY^+<+eSb=A)JDS$#Jm@&g>6_&p
z<`TnZy9%6Zji{qa@6(*RaL(2W2Gt3rQKHhIyiu5TTbN-^=deRAhoeAWJ1Fkda1?hn
z;x^MZ%W1l4hDe*uu|&CCW}0T6KF;5sj@v2RB}Rc`tsa&2oPzCfnDM6M2if`b^M6qd
zEb2}cw&;s^mbYM@wDFz>?}0BQW$e_h9*G`P?u*JjtlamMo4!@bjaTk0<%X2ITDdXh
zUZdP^DEDdQ9#rlhmHQ9nj^8HZ&r@!Za+fG~opNK!HOsJ7;a$qTPq|Mi_j%?1NV&gN
z?t97|c9o1NTe*{!J43nim0P0R&nmZ8xfdz7QMpm&b}9D@%KegZZ&2GQ
zYM^@PnZ(N{^2!^;Ase@LLwlsI0Zif35x%0XBNim3AJ)c%YhuvYbwI|3V@XqUgeY-0`P4SmUtHP-y_XR0>*cM;bzL*`La7-&$59cf+js(7e8<5`
zuPSH|+uB=5Bgm0O+Oa~Zjx|GdwxqL_)nv7G>zX4%CvIt7GzRrrX&b5pZ%}%OSJBpX
zac9&NMrE~cM(M~$Dc4rEZfa^piSIOOBC(aN8|qpcnj;OtuKGxnG+`(e>Q_8q)HFvT
zQSp>f8)TjoRi86nRx$b7w@nYm&R;5R@$+ZyR=iis6K>mxDJ%GR~7?-13%O{n8Y>qb#SblbXcBkD(p
z^MIP`+gdlWKW**8;f_cwTo;XoW1FK9TEsJ_vjgRldQa@uM7XZLrJ=c1Tn4J8V||#D
z728F)UQ&M-;YNCY7iW1ijvAHJ0=sG$8pMmmIz6m%I@=NMY-OIys9V?89uwIHx-U3F
zOf+O%1x91Ey{R?UD9$t*+arjx#Aw`vjt=S)gH*UAz1e7qwA4q@dRvWXXRJern+(zz
z*Ws+py+%i@y*bi~`H863`j)8pfw9qymLB!)|Gw`z!RqC~iaE1qp@Ar=Y^3$?{u}womBo+
zXq%*buabv~VaSin&*QU9`93A@7*g8Ie|3Q=e^AL^K%4#{J~IA?&NSr$-}HF>oYJ(#{c?B%X>R!
zS}AXi>vw%j{7|!^|8!ky%BPA+|I;o%x&IpMI%Rr8htK%J$^D=CSby0bEj?!VgKD1o
zUTQ)LOZniJOnGzO8+KCpGrnxf?^g5V9Us$xvOd20RZ~7STABXWzh?SZ&DH-3JmVftY0T!8^DyXoGFY&;~#V7r*eDdS`WqO}|%JetSe|+5Y{xRA3
zl>Kk2f!i^X%c04w!7Ar3m1bH0Oc+@46YFe^EM6aJjkGt_1JIJfprH2Rj-f8_(!yuRjBOCV3cQ=EgZQ*Ehv%3@ltB%il;>
zWL7=)X8|s%cHyAY1>u-*OnDSCx;qVfqV+gJf}hS-+7IA}1ojf}aVC9;
z;poI~G}caG&!Mo6O%x%)b^oBK^t6r**r23DV>mfBL&iq5;l3T>hMQii)Qz;1RMRMb
zyt9Je5ZTh)Rsb%K;l2#R@SQb(y%u*y)*yC*5UjMN4VFWnAYe
zrujI@Uea8LEue8d^NqAS5S?*@rxT7lDWuMt2;)Z2g9z?(E$?hu7iq^4oVpgM71|NO
zO&mdPG7RnWX-`OJQH+~CRT%gD!tFNPGm$M%xU_P4ZE$t1IA|DKTw@WbtEw>6hW)?s
z1=pRN#j4p7_b_(5s^&<%m9fuNHCN(ojB{O8^CZ5CvENlSU*az^&UdMey(;k4E~cA0EK8922}vF(I5;~1I$5#FjxyPA8o*31HhT6b_P*b
zbzK)~nL(GUx*p&b2Hmde27p@`T7*>|)RhpC)14&fp$I
z0B{F`-LC2)Vcf~|9#{1OVe~TH=c+D5X}-$f1pt)hYYYwopfqND42}=`y9XUs8@>uUtG4#)$oeKIjnHC!t}|#Vbtn&N-S)O-
zVeI8#y~gme$hyw;7W-Ld-(w6XwNwetl+|yjZR2$IvCnS1&yx1G7WUiEetV>!^(d);
z`A;il-I!dG>z65RP-pmzPvlRtV>n^wc{_*3<@tGtofwx%99)uc0BtQ6|CmN_gmo
zfx~ZgG+s1;5QwEni{frEYNkQ9D;bfT3J!Kd}+9ztLWz2smlU`K?BYW!Q$N%9XX{%MtiH`aBnI&7lgZ0pX<)$4i5Y
zmlh~YiHxct0zRX+Lf&wX!>=>EtZ;TwF*I^z&R$?wMcXD}1f3qx!WC*-zd;yFoW~KX
zTVzO4W2rL+UmuA-gKt(T5>Au&WfOaak81r56Ni!BZvjT|sO>fy+B#Wn=reeXR?u*}
z(}Wo5fJO^P{F)lVQFDB>G;wKHpAHejU5MZ8D*Sj;e&$d$yn)<9Xchc({sht!UcGEt
zxTbhjFkD<6ES`fUmu@t>p29+xM>X{ObKBY*gweudjc`HL8td$kyjJGvuG+fwlF{a(
zvKg*woM&v`7-_(>8fBK##p>G1D4p^X#w8rkrI?M4Q2Ys_okuTB4W!tufl`?sN?~-c
zY`PWaY+=NhmFX(OHFK3JbSH=QF)tZ-BTHsmfiXmEV%8{gbnfDCxe|t#)pcAfjLpm&
z?^;5Si8(A_yuH-*AX>`rTHVrO<6h>X#_k<%78)bZwMJxs9w#u
z-}N?zA6E#9Z5nhQV2FMeSzlMbSs33+CWi6vK^OI^UP>C3`Vgbtgisy38TAoD`5tC;
zkPve62&2P@&0j!K86^Izs=Ck5To%E3=0_2fV_usKw@O+
zNyb$YBU4W?UMn%O^&Q4hiIK6V8Fx#JtbLd94oyBTG%)kyqlwYzkoWL_oV%nsRs)^9
zFz)3J3XJxVocowF<`8Yr_yIf{BRIz}2G6>=A}|iPXbA9Ki(X2X|FJ;kpg}~gag19$
zwE7t|N+_SNc&29Pvl+B}n4tTwj@0wx^st9A
z=texZ!X4{2?$2}%$H|`MWFIgd$XrMO=Ylt)BQO}0R&{V`Ifl(*`?Abu+{c3B-lX)#
z1rPy6Pq8BUhcZ7$F^1TPfZnz{lZM7zQ;lyt%$Ovf&Af>umo#A&Mh}=U_GQxGnY&6J
zxE03!OkU_Y!^>;KwdEzE$oOvNtaOyon#C$GkqYA(nQMt&->p;W(2S??Wtcs=<
zm<)_Q=J{MTo$G3p)n*;$TAAoL%C_HC+>Z0R?RD*&S7KnPYQr={kIeHdlaJ+4bE7a0
za3;_--Bf@Kl{w=DE>A|4iNBXwgS;B)XE+or#?fmLFdoi%5bx-^
zA~YHx=0U|P>S%_y6F@hCAG1=QSF
z$C-MDIl17pZES5rGcXNd%*%9x4Pdkl38v}pZLbsx)>Ct(M_brW(JGWXmB+yWe~tb4saPqP?q)}
ziCxZMN!niWxq`()X;6d;kL#2-_1a^@HZH!7XBs!)x!61)T)K=WuRL4J_f3V?`NP|_yLYUweYtX
zs1|;Zi=bNgAqG{lg?BSpEnE0u25V&tKf+OOkS+WugJ#*nk8uk}&1d(-mNFh66-0xY
z1Lcqch3LD6o5Vb7cEijkC$}0jwp%k^9CagPFkZk$O~(?1@e=1kxag#WIfA{+bH!BG!$`e)+T%w|$T7{B7QO`qC|ns8}xMMX(*={ds49Q!th{WE^E
z-7u!eO&g8Qa?@tGGr`TIX=Va>(<)1h50x*ksV!b!8VqAEXJQTq^TKqLrFB
zk7#U(IPR$gR+?xUAzJy=mM;s6KCb$bipmnPmr2AFEMA7o%t@>Uiyth}#Xg%?uq<3z
z@>#5l#C}UA$$O4@6rU;eJabBy;I>tYvb3TG`l%O~#yg)i&}}2MO7(j(G*FncG{9wA
z#fvb}?WgdvPP$dT*Hj0Wi0*FgDyY(6^(xd)cem^^6&1myXu*L2?m6WWE-S7%2Qo6|
z+BH={VgL$9xM~&Nj87k}V`TwQP9T?5MU#y5>&A`2pn{b)pKeOOUX5(w4te&iiB{?9
zH_&S)laHf+8|k;Vfu0z~F(*2KB~Q6EFvr3$eV~uaBU+|_E~ZfU^gGW$@bNfbrOum)
z{ET~Er7W-wA>&?7e?lv?^djRv@^DYUk*`9LasLry*hgTt$asK2?gaU2s>t{jK|dba
zpCUjG>jcAiJfI@Xe8fR8FN`foUBmj0OE%FyS>L8V3a(@FSRtk=RS$Ti#+-&YO@DD}
zxHecK@|T+@3u`0TLf+{=3&9+Qn?mP>%W2a{C%z&LrEM)xphd7>#RhnN#N1Ho?>b2B
z=y-rq!|)uV<8)+XfCuw}T^LjmfEXk>l_H8jVyVLcXObw%DfH74D+9js-
z3u*C3+w~WuH8avh?=RE4xI(*xbdFl}OgiJoHK(;RXT{7$EG>lA!D#i&X4}si^g|$CmdpRvy
z6*M_(wI{HMm=;}LD>+yUYjqkenv*;%hO~8>4|3uRlptI$PaQK+Gqi0z{N~b30YYE2lyM4E8*&TAMBA
zZc*&pzi{@LOQD$B}CSeUsng5DKBv!eKt>i9f%<
zPMXf&3hfQ5yWJ}8Q`GSSZP$j~{m54xjc
z=fTe}XlgBEZTN~#ye=-ZUz08GFyucIz|THE#fir`%tte|Khwjq63H)UB-Itv7}{Tm
zwV7D0c$l#s)c#8OdkEh}`FQSrr!wk8bo9~wLT}(LK8mp^)r$rb7lO<|jAy5M&dGsK
z3w-b?C)$m;d+xh&>%C`&+
zK6je}7XWO47&?<4L$A19@jJO!tR|i~bA?Tq1h1gTOP@f#yR!pC(-k=U(MD>|P~QIp
zzsr$m;4l@jEN4W3y?-cEaty-_{$*W?c}z030(3lW_B?I1Rv_kIp*(LyKFYqNK&D@I
z@%gtZ#v@deyA^l^U?C)sLv&J~Oi|3gPk9f(d;WJ+Nrs;a(62xaf#Iqo^8n_qP~dEU
zZ8A!&Qp{~r>~q1sUFM}oTOsB?Y2!bhZAvi{A2{CkG5;>By?n&^t1;^pqExJdzwd7UIx1hJ8BdeVcZ0G)B4Et(IPf>BZ|JUKMF;Xz7$3
zx|ZUMdUM-4*1Fa;V`LzUmhe_k1n_HWiH6k~a&6{J=3(2@)Z9>ChZTu7SBhB+u~vI9
z9(C!kd-_J2ht1g3nf3I`s4l>yWyMA)cIB{1F2=X?ufBz5nNF*=6GdpC!@Gl-Q>f!)
z<2S@{V{Qzug9Z&-U+q-Vv6?B?W1uBdn>JgPK%R-$3MsR`zhb*{9^xn`@vf$DozNE2
zyTKA&DzwiK^3kqnizQZ1Vv9B^vHCE?7Aw@SxiyTxHsZpE=@9)oDEx&McpAbvua4x1
z<+1y9u(4yAQ1TP_7;Z`cX-cmM7ExL$c`TI+5$jC=El9ckthqqJTM^V(!W+t4QE_+y
zLugBB(~p_z(g3>n5Teb|(iS!8gnsNNQQyajw$e@)(zw-~w!Y{!1p$haGAi@c*4%(a
zaWrOGUbXWsL-L=MzR`L)@itN=<6+n#LtDPlsPtb?h4(nz%71BiS^4s%=VHTzEp9~x
z_I@QR!7Hu}VbdtICaQsR%mo_M1hI|=T!a$FIT$Mcxx6q+@kgU5@6|(icXYOy-fL35
zu`0nl7Q8$37J)Z)T)_lU6ET%928%bPAJVU;
z5Qt0`18n=N9T|@tqcHS?p79o0%_*86R(I%N--3sk{|b^2|+WKmk6YU
z_eEe)$H+f@1tLc07h1(KcGI_0j5KX=dw6Mp;U9#OZ^UGsSz&uqCjBa!zGT}~@B@oY
zQH#*#(=6qsr;mR`HNOFqHd~`PK#C)2TmaNbw<)P79d9r-MMPGUcptem#2m~WsR#5<
zdNxmJv=1o6!Mf6g7hu14aYIx41?$@`z_Gjw8t9141r3|(+8Zyxg+j3gGDW5yJzH_YuJ0atzOye-mD!cr#aJiEQofPzZH5<|tOCN2QI0Fq}h_C+F3P1awFMPL38eN<}U#7yVocjVe2g$}+@HhN!ZC&w)-k0^wRQY~DN20==qgF^u!)`~UN+)@>c*
zI@wt*{bLUlr6^4G8y`bAcAi9G>arB34xxw8bWW(kl){uqsW2sq6sGJ#VM;D3OxcCP
zlw4Ank}DOaL`j7y^DKoaA*C>75muNIWhqPvSPD}Dmco<(DNI>{6sD4Z!c-Dan6d~I
zrjh}LDKki6DmkPuB}ytxiLw-?1Xy88giT>e&{UWbJxF0n45cuYq*Ry^Z7NKOHdUlk
z2_zM!glq~^f=XdZq@^&Gz*Lwfy^_k&{oHJ%R88`pW8PqeDTQT)DHBRzO7sv4Q({vK
znhH}XMpkPmObJ*DQ7E%h@lC;#-i#CSB?^eS>GW^x@X)eA
z80+Y%z;u?h);aH)Ny8gk>zwyeaN*{V&imNIjoG14IPbp=9zFuIh4TRdxo)W8aLQab
zzeUh59PT-YX&4O{o<=%=xeV7az*sM|;T7<3xU2CyoKmO*kxoBg(&|3L+y=MTH9<*b
zUgO~0Z4P|J5T%c{>mLY}iOdQulVb7_0ize4ha6XxpkGwQ^ChKD`$)>&y-GWNip+;)$tPgLj3pdkQWj*&vl-A)6j9a_>DguLq$VVVkIk%Wa@OY%;c%+ga%4LF5)f%3
z!*G3O^p(JwRU0;U(CtcAK^BdsTxF`Wz%o~hnTN?o9;2?onH73%Qypy2cP$uwJsw@p
zayqi%S~z+EA{L%yO^Zb=GJ~*6m3-TkJZUqfGZu0+o%`b({F0t}DQ7pT{~fZTS?l
zPqxiRYDH0X9k`>AeRGq(WC(8M7e3)z%D&@0=E?19d(g7c52L_-%X3i3AbU>s;B>~I
z)7Gvf9A%yurjC}U)QM~9=!a1yPB&GuH)UCxcHKPvbaF3MBQqKhP@{N?sQqL*mmkUJ8QqM#};}J|POFe#K_z_et
zOFfea=Z#D*OFfe*x_qJYvec7DPery{`^=e?m%4@qw(>2au}h33vk)0I785jtZW>bL
z{4MP%VO+M=65fb~-&sCHk)5tB*-lY)Y=+Td>EL)m9M4EvU*mvOIUzikCy5mc$j_cH
zW3A|?Sow_~q_s>&%n(A$WyID>
z(^f-k(YQ`%ET)!lx~Y|&Zt6DU=ty7`7a)Y8G$HF+jk%($qtfA{?V`8b#^X9TcoJEH
zUN_+sbT4H2x}QNp-?@6?x$0J&@A}Y%+ZFgRz>CPqBsw-yRUDw`09I&)lW-K}95L~7
zd#Hp08Cc=|jYF-#A{>%*QfA^#Mt@
z@?;x6_7_y_)OAApHmzEwq8mIx-C!zgR(t3n6Vs~E;Jqq|b;Q9(+w~1>RZjgJyt+{4
zQ#XP5I}!LBD)9wWUcL`WJfK1yrVtt07bwUq@c#mV>BKyZUN>~?+;QdUr64vV?CBLC
z`a$>|xdBMv#1u;PJ1|jGD6^P2NAW)g{)`J0$UxMnJ&KBI#a$p~+^D=Ju@`s&;s3GX
zRiX|9%t!6NplVoGl^=EAb
zvIS=~S_LLm7;CXBZNpl;31w)c
z;Dee^<@0?!ko3`ZjYn@Q*n~4H@(jQsjbcZ?Q+u((mYN9O5z~Ie{5dFIK0W1)Djq+C
zwZmEhFZ0a47yQ{z(9b^nOee3?4}w~SK&QP4f?M+)5F5~Dr@O%JL6J_+0r4`3eCkaf
zsfeQ#@m}p6oFCziV-P`IDW3@HT<3t8dDFN6mxFpOYE$pT?`j-il#vC-O5Z+;>;>(t
zOchzH8QFDaWRFv1=PU8Skrm;{+A-y`m=nW|_lW6qKl1$=!c7;b%+pQ>q5{sPQg~Fh
z3TU{DYFvUTlsc7QDG^kH&w-dZWyliDrG&Ub<|+TR6xB1Dj+*A^wwuvCY(_`#9L}s8
zGP*()*~7}Wmm=G*Rhp6g&5UduaVT$RftdNTAtOWH{0}J~>hG-(86SD
z6r4N3LqH=X9)ySG^HHlr=7q!6E0@zt1L3Ng;L5T}ES4%NOT!g-8JbQ&6}*ZRPAU{!
zUPgk2N|687$T~nZo4E6B8V^tHE6Ab~7t7!nWKuPtt^ge-6hXUJnh}a<<}D&5e`rz_
z3#`jNJy-B!O|wH0#al!(RngBNBNoaVNQVcs&zKrBT-&PZVM$wivHU9~p?!nq1R8OR
zXu3dVAyySE$3i8-8(Hm}w2)Y&j;>G!sMd>!kh!CcC6!THuab%IyFoY;&Qr~2b7(zQ
zfbRCmC~)dA*Q+Bl(BGuqPWKhGhH1V^Ub?gg<@%p_3c_&LqSBpV{J7pnE}_ndfKIc$
za;COBx9B@PUi2Y1UKWs-{Fc%gKK(k+cv8kC+4AKq{d(pbo)U!7Z}3nG?xc{}Y4jUC
zUq*1B`-Gd7^qV+>++-O0%}V;s9-3hMVi+EP(MV#r?Peu?3l7I1Id!v={smVzXHng(
zr1vm(yVcD~`c}q1x4KzL-^MuCt!`G*uVUwSxN6@y3b8FE9qZl@B#oz^ECzs0Z^K|7`z66(tMr4VSu?pznein
zz&xRUgTXO3-D;$Nlfm)yckqx3EhFV-CB4rz1zk!wl!tkRlD?ON^%@z2ZdTHtW%fNr
zM(WK<`absAZTB&6N7DDR-yZ2_JxcOsCH*<}>`U>q!amR5bhDDuk1obTC9hI4uK5jR
z-PDif!^5(EI!yiO+30~#SK`;aSIO8(yptW$aoAO%G>*wM@P3N(S%y*5<#h84r0R|#{Spr7QcQVEklxPE
zF$T#&cMRzrESqk{iOwHmR;HU2p5}{ZogCW7JnN1jeIrX|TY>SgY+}|ZbDZkpaJdr7
zJBIYl%p31cxnoGb)a62z`rWvbCwa$^ewm9JqBp}VG@ilBUDOu6n#fGOV@SWkRSB=G
zUQNH>^(G!fw|Xr~e}JKIt2>7DZzU7MNbsPGTD+H%Mx{Q)Xg48L$8JV_giyYR866~q
zoIJwlFd+;Fk1{%z0fceyF-8~(05S4C&d|pYgVMJd`Wa$edV*mALmHa)Fb+tJEIrA%
zN@8T{DaLChMz+4gI4UtR_B7*eiIKJMGR7T4+_h1`FLzL2
z^Nu0?KIUXUkA5p-n1iv5V;BPsy?Muwe!!K5=QPb)sxDc%oE7o7RqY3^I}pTOLZ{%Z
z>G?(O37Fkm8!X;S%ro5bKLA+iuD{GYJf-Fu*os(x#Z`uQy=`c|17@BwMW*eFGkJND
zev5~e9+~#b&y>$sJRcyW;imBRrAhKyBmE&y5tf8ZfkQu=qfB=XHgMNsJ~k_b
zUc$au)|lb!W(vKOeaEYX80;zbpkj3)$@@q|drcp`ymJV|=ljVGo|
zlJ^`p<>2$AB*n%PCY14n=pl?J#I~O&m14?xLclVfu%u}`Az(M25VjdlY|t{E5YKKr
zafHLsFih6rM!e7@JO#@!SdK-Xz%83)Y+c5Nc-(zZe2i0oI*98AE?
zZR^<{t4$!5HjcN}m5p*Jrwttx8>f($K5hwJa%)cWh)XRrw29>H7^kL#%0_DuYrTx^
zr_m9sRD0gENg2r6cyn`K6AVd>xw)4X+C{YgH22frK;h`4?YaXxf(f*V)Gneuu@##|2NIK6k3>;pI1Y1F@XksZ7t1m5rjOYtf?bf7sLD7?P|9sv^tV483FAN
zF28~LX&QvVQOrBzM
z?1dt4k@DkQUtkklW*00Fle%nvO?JORG3i#D-!?N{%1@z~`jE}fs)a&Z1E;)OG>7W2
zPX&65i-MZn)s0q|MmlG-4@^4qNXp~5TB+0~f;Im>uwrQ4%
zW~0ab8r-~BR2sjd_WGLw9|3$8Ng<~m$J&wrqQqxX*C_!eW+LD^=}oqhQ+pMk#rrOi
zLX%-K*a-3QbT}t@mMz(TpB3me=D$PlvHI_Pq?Lqy7kr*7=Du9yIb)*C4z>DN^jNF%(FLa{znLaqn%GZ+3yqeVV=$WAZ5q8lJ%9;;n=GQ>Z8XO?lMUT)_
z5_i#aCB#$s;;cDx`N?Qg@e(+SU048BYU&?%+>8d(lXc=r^~Xv1uk$?f%qN!n_4W1i
z`W-UgZT35^RkS&(*wh36A839Z$-{TX>OREvZ+s!n(ifdf9b|g}V6Yy=aPP#3<#eSi
zwe=hKgPnGgrMBBzYU9-{`jeM5tb5c_n@G9TCW@BY>|&`+E-kg$#ZsGGT56Lkm)bHeC_Khm*A73G`nN{zkA(-OCVefMFi1rf{Zj~B
z3y}Vi3UnPrGiXU;W(C?4%tibP_B{V2nfiDu<^aUKixm4?$dMREt2Fa&Ep7I3uyFXg
zLk9FwrZ*r=mKcG*SHv50mMt@#PP~IzW@ly)b0jW{p#NHQ)@l@6Hr1XGotWPYaR?^z
zPiB@`-x2QUjM6b34ArTB;FO2yxgl3j2=AtI^63~(Z)
zEvp^DxlWkcq}7fd$0CB#YDaJ(L20!kxQL*%+7Ud9ptRZ%3=ou7JAx(7q}7g6Dsw8U
z9pxjY@sUMQAr6RL5>ceS}cHhZ!9tgq%FW=rAER
z7*e=n!+_XeNC<-vAR7z``WUjokf5I-8w?2+Fq8&E!U2hqr6)O|Dv6P)rx>r57}@#`
z0%^1dr
zbep}9rs;IM0dXW4#?S^tI{N5LH6T*Yz(Qk?0g-rybFcxCcz8IghO!_A5wXMlDsq^0
zF2v3UN^EZl)tukaUt+N67tS7yZ8JL_=_crvAn
zsA{oySOF66OLh!(N0K(%ToV5T^7PSmjl`mOY`wfgNt?SAN&XBwk8vIN4;1`C1vIsk
zx?|_=E63rMn#Ov%w_<(;x+7j;9iLEJ3>|Sypc@5uUnx#`R58JT3};3ioL}G3Sl84{
zSG{ZN{gdH^&xia=8MzsohKU$L>n|=#P&OKL-!_n##>jC>ATVqiY`Dgc9Gxg;QDU}Va4K!@xHGr!SrM@#X
ze&OT*=kJItAogEs%Ou9HP+o52h>F^Q-xd1C4HNk8$nn=J?^5Zl6@X7Ne0!-G3sAnk
zu?tRtzA*}?2=;~XKUYClnL)+)KPc8ElI3wkO9FyF<3F4%sW^MBaAn1>?(V)^_{9{-
zZzYXm7PTwYofHor})Ao0q`Z;$ao_~55D*u1;U%yks>6RzL
zVC|lvVF)n)a??C`uWY!-Vg^fdsY3~a{^r4%IrdDN-rS4v>n7`;
z=Ox7MxtxB862sK_4hm-d{|#2$`A*;1YzKy0j8*M1%Q$Kt&2VOoJwm~UC+ETBE33{C
z?CBnE1uJjGHIBkLlKH+QzZCaZmS8OG5YBA&%N;HchnyE_Z=-)p5YC*jlv)4q)YBNw
zQS6Z?T=FnRY5|<1$5MHR@)ge0xNPbQcx`Mp1k<4tvt6x;yHxp2jfYSN8J+Ogs(+4r
zWF(lREM;^vc^$~iC@I*4R!h>EQ49<#52A8V@5{mPCSxXDo6xSMn9V2X3=+f#FRVa6
z<>RETrKFz3VD01NuBGJOCCEu$OG%y%Jy=$7N`S*YgkeF9I3H)8dZw8V5b^PRXtFY5lSbAHRLpo1UAAd|s`1@5<<7cA`6T)OET85>}
zGO7i8(y5EfafrIJ5D((l
z5NBq6Qd1jWB`g1VI)X|4zc88o({tCqK5LmHmwO@Anj0$vn5yVf))n}seMt3*jlH^V
zcvvx*xUg6C2FXX49WMC=Ha_1woG$rd5FhdxlJ8S|aXPxSA$ELXEryGo`7y?FWZ(bz
z7PA%%CtD(XtTob+VusXiyd7<7oWu<2w9JsY&xuxlr%#UWtkxfuo;pFn;DXzX@(?vkQtH~$_yzS+RSN$tQ~J3SG_Vrl8zHbXL@%#cJ6VTL5O
z{luRXQ)Wm4mKl;IO*13`yBU(O%?xRSmKl5&7ik>+PU_7V#D=`r-I4Ki_~I(?O9MOzdMK?Eh53eeN9IA6%~!I+_!_O@Nom~b
zNXAF{lbjA5t8)w&Jdx)WsJM^HQC4MSV|{%y?rXNB)1|auN%J307-GbTPilfQZ`H?e
z`2seOI!wSOOKAQFP!_x#ttM`VybVcw3tU4i`o!`aRyY46&(m;%P&cvA(nvexajZ?r
z@co?O#!oE6U9qkh{TBc-yp=Po{tLkMP0nsKCA&Z3{rrwkEW5Zty_M|S$nL=@0c25#
z@9{5AA5!+sySP5~x-I>L>$ZlxT}zk!366EU*8c~KpnvXKW<&kwK{zIieENHOr~5Me
zy82PjkDYLx?mHoq=1!S+^&1a??K#Q3JItDQar~!|#up5NYThMM&bvg>yvr`;U2c~^31-X%)TyF^*@E&-l*iLlMP1kHJu=t1)?G1R;(NjdKlZO*$yTk|e~
zhCgZ@@z3W?yNf5qiZbDrdF$W)hFYEvopFCwh>w^ITfbs0uH-}?$g
z05T9w7M+I0Ur*#EWxS(oz&BHYE(AD727sD53##ayYqOwo-nl_|7b=;%A>%#A27DJN
z@H~7jw~`xiiDDylzRAStrsvf>@nh8Tg+AR%2-X7rXuIA(46161D8NA!FFUTpI>11D
zd@dPQ6E*axe`3j{>cOqmYQ153bKQ-Ro<+)Y6xG~xWOy_Y0-6*4s~of0#-9Z*r+X}Z
z$E4oN?c7c8(Nf)xCIZ?MUhZf)RC}Xo*dx;k7B^;O<0y$c$&-lDOwkV#piGTPy|~-?
zAjM0yDH9lnzde*mjFQod-=i9EKmZ4VKN&qW-JylcEikS1<^`z0^goe7yekQRIs|%ZRu9+KTBwIxh-%
zIxmWH=S5*(=S2Y3dC8#cyeQ0_7ln1_MG@0^QOwhMQB-wa6x5xUjBw{=lDwT4;~3bJ
zLX}jW>AVO_bY3E$Ixh-`bY2AZP8ube>bxkTJ1>FBofk#CofpMDotG!7J1>HHJFmFB
znl-Py9mZSGzdzN7x1xL0p-v^#0D?^%y%$Wk@H49AbB{-pOXU}w$YjchWmPpEFA}Hj
ziEEgOWlB|5H89X!@)D-HN@@l*3*5$bSSC9I@F#iBeSa`dmr3ItIE~+rsp=k4E9psm
ze8P^7Pi~2x{Y6yiE$rX_JuYeH#Xaxd-T<5OPzd+ktDtvzD1>{*KM|bY!<~%;?JU)y
z5boi-0FA}BQzrdtuAVUc=i^4b=i~Zb&5?*C4dDUu{_08Oo+NgY#mXbULaP7eoD^wZ
zr?@>6Cy(ZdDUOQf6C+Ep>=B=dK)${v9v7!9;G;94~bYF#j<_CeptjOiPZKiodOv9k^sd4!e9^U?t?)4vVav5tbLz?
zeMP_~12%*=a9$BE3QZ=xWl~*97QXnFZ&iKR)A5
zNNEw`AcA!PC-%gQe}$Y@JNYCoN)$qNWt`qYi8!vCl5Yq-GLJnugOtMWO#La}Le5y6
z(hJnfQF6`wA8o7y{i=xWv2{4%L7K1x@8&4g+$5Gm23hf!AS?6NG_%q!HN
zt2giO-!<6RBF-m_RfyDhp)N!uqKtDy!sJ5vUUW-_zVK}CQ+vi@=L!lXMc*I_3q@oa
z*VoH+Y*E?wP%W+yy5*#K-HR=EJId(%-J%~;G1m%;j-cqou9IwYp@E#SRM~^bm`}OO
zFjf>2KSR^m(nzNwCmWRT@Lu_~*xhBd*rNsU30wbw65givw+&|T8UF5cR(*$#Ipu&3jX~M7T#FOfJ-~t;OCM
zp)V))QIS|uNV{*gbV-6o1gx~se7PALDWk)}$_tedB>V7%oY>V7J1US9g?O!<_JBVo
zz!i`O1h9oJxW;8W^y;56_DyeP11=yAZXPV*7o&Tn*ly2($=YRv1g%Ux7v;A#2yqX+2Bp9
z!Hu2tRmbN=QlnvqZ^w3G$3#-ACy6tCL8R;~Y#40s#0T5r1l-tP2!4BX`)%6Oj&IDV
z(V}`^6p4L>WM;L!S#;QRux#w1GTIrN;ihFbme|8()Tr1^g(BR7#uST>fd)@n)(ND^
z%9(A(Ft;vQTi4W#<`|E}o-2zNpglIzr<^(3wif$_VAm0r%8urF;q>wfgAV9#MQbkC
zJo-wHoh++B*|GR%K%Z-2Fr3&w3))liVwcUl9*EY_>#@}{$!YqIUXQI2FzsUk$BZwE
zT{3eoW_yL=ThiF2GwEbsxEnfpJ$Cs_I=dw<{oECz9QLewXG^sJml!{-Q<5U3)RW>l
zQzW)lq?Vgh@1Y{G8j(83*oQZ3?M&)H5<1bBvrZ%~kS>0mCK==e
zG$GcDXVZDRXNcZm)odZkE!kcih|}J;t~WcBYv~yt*zLqF5lLF2^_v>EV0S`oU2{!S
zeIs2hRvKG5do^}QmVAWf(Xv0gOk~O{#F2@(I1()ZjS`n-#?}ZpdNMltK6bf?O@=KQ
za#sjg3ERC*E>ZldKm|TnO8U>+IVUE{Ur`
zE#o=oY*EllA^6WCKc(cbG4nYEZvtFmS6~G(hj1&FA7M>@2jp`yB(`;k-DlH$Qy
z7M)uyX!vS5`)mazn+juCoiduCxm1
zN3urYAZx8*tOZR-ex`pj2`!`W-=i7%1{j%_-i%|)Z@v$}qO+N=L&kh=A-)bHWsxx5
zcTq_&YhgUMlJPu+G{N^?RsIR^8o6EaP2nKl9}Vyg^T2babxgrgV!~NiO{orSL_Cpu
zHsIx$l-|b)L6DxLu&^B9MDCTODI6rdNa3+InRNZo=D`6vd7dT&^#e7-*(`Pg3zvp7
z>&cx}tDNTJ+WFXgGcVJk&h~$Rc=-uLAz6EnqSIk_oc?*TKH2(@kqA>2${5$Ff~$%3
zFHSLm^KaWahaWTCa`A#90zVh5~u_BmY7C#jx2
zh$^HZv7NQ)s-zQnin_yhBT2N!`xW&AB!XuOKv@}mhzMR%xU9ipA%b5hD2reif}j)Y
z9UOCkdSm#j4?mtplhX^-CE1f!-Ul4=NsCDg&Jw@}I&cBNqz0R0k>oOCY-f}}qrMZFlxk{ez~0;XmiihjOYq#Gwr=gV_4sPK
zWiD;b%@
zd>l{Kkscaq7{vbe2D>>k6`ejFWgW0(J+U^ZWTR7{_?JF(2%7s0-h
zPkbv@{$wtl{}j*1$1%g%A;V%;z$fQ#*^9-L?v@@13Tt^ob7{r2L=@1R?r+cZ;N}M>
zmJ{G|aM#OK9G?3rsyp;ZVvjY3@rY>%=_YpF-2Wk|#xI2gV_}F+Y>&{M8`Q2d>CfOT
zko7YBEm(&?g=BCJ4xkf*JT&Fh?(}}_4~fjV4ynB4ui&^=X5KvjPX>+?NszXj$#Mt#
z{EGmOPsSD+=ZfAz}+mv
z_-L%}9Yn#IN{4Q+d+8?#p2$6Ki(y8CkFTBYoP*B&fO0=PH@TQn{{gALMQZ6sRO$>l
z{&mXI3eW^J0C74Ld(@eKX>dJYdheXtyK;r8M|)?du7?vjk6gwHmGvgUA~AW+B#icj
zxXvSStvDA^DY5fNVviy|8!Na}kQ2Fpuxl4$r0|9+XeZqJ>ypLDvKcs_ZG%&G#(CAE
z_$fg4vtC-MlKfyOf^=Y2Ad6dl_M|;^sHQqpt1?D(9exQyvJTZ$hofL{b|#zNBbi=H
zDtnV)Xb}=rL!fIHVQM(23j3cDPB`}~Q=dZWPQdcS!8h_o%E-B-y8`#9
z!kJGWE8wL`{+A=Hqy)K912ye}^~tS*Sy@OExE#S1w;s
zc@ZuKJMbDN6M0Ul;M6bJ-0(npO?P@Ao$c*_oZGVLTM&D$4tBi1Htz`krG3@(4t?ExmQ9StlqugBS8A0iLN&T-j
z-T1v|8+pDLsj*&CFKGvjud^4!AKd3!AGx&%p#Fi)g~JqJFIA#)f*@cCfw~ds8%3&bzK5xn7XL2j~qA
z*tMcDHf_186}wkVTwZs&slFN4oYri>77WTT$snx5?vGT>rp8nfC)TcQN^S<-dJt=qD#DYbDMl-*FjslLT2H%U-e%hkyy
z@Y+`8c@xy8wT56qh{jjwy&O$$AL%k5!x_U6N$e+~g
zNjlG;v~FEfU0tJdzJb=Ywxm{7UAXFEI_L`y0q0oY!Z&RtSK%7qElqT{vb0lYu}NDG
zi$Jp!jw#hlwLxQPaF!Sh0&c_Gaw(ODEiemu<+lkoR5==!*rTk`mio~elQmaDzDf)A
zo0~Ul%ql-7?YL^FYi@=bwqV1Sv&^4Nyi}#uwxt?d@iu6=NhEV@0@HA~q{U|PEf9ip
z;TS0Enzn2bNGn2-AXv2lt=YNAU`Vg-GdH+0i3}yIG?-*5QV}UH#>Jr+x`0(CIeAs<
z@{3lErix3(K=fSAY&LD;q#?ii~WElmw|o1M!|Li2|DbuG)BD-2|N9W|`h7Fvjtv^Li|Cp^6}8s4TY
zaQ&*KkVkO-+LOL6iF@D3!_~JsU-Q5{-Ya!A)>Z19$33Z{X>VGVx~e{zg5^BnN!q-H
zwstlq>zk7B=ni%$>Sn}!HH`*jultlYRdKpiG+gIzLXtMr%l`jqPnxP2$q^s97-G_}
zXk|)y)319H$(CAcHmqOkJR5+bW>wB}9w606njN_s=Nq0R=_-{?!l6_8^H%!0WCN&S
z^do%f+D-M&-+FM=_yQWJtyg!AqwzI6Cp|b)BEnRhzw^LZw_BB1zUfIz)^6Me%}P^p
z{@#<)0F65@V6{aI>S&DZ8PuJOOvdP3NHN)jaSyqEf4q_8rbciIMSxbV#nxd`wE(t~
z&C6k$h_7wFI@zd3Wdb0$h*|55B{BM3Fo#BkEqD1GP7Dvwk<^&RM&qtLQe|JFiw=nb
zmIm-vy@ZB%x9njDUkVpABabLNfn_4RBp(>uJAm5^^Yuxp?)gVB{EfdKQureN70^U6
zg5xxNCyPc)3O+%J?t#VCGzX(}?;)ensVe=jN{2Pmoafe%InVEYGTDzk5=-U!LVr8%
zj?88;)wvDx+GuJM`eqChsLO-H5leEy%&>dgi9{X;)A)EWFwxwBHI6*z3xBw(^bTN2
ztrvGeogW*ZEe4ZcpLnjO5zd~Y)#s3lEIIW=+1U@gwyNk|YEF9zW
zf+GES0owC@SaB)DUT^hz0R`pf1r(ys3&bxzFQ8xgyg>Zo^8)&%&kN{ReqKN!`FVkW
z>CX!&ramtaDB|-13hB=aD55_vpospwfFksHfxw{83uFMF7svoUFAymByg&l*d4T}X
z=LHf%pBGR_eqKN!{doaJ#ODPR@O)lCQU1Ju!svdQYSHCllfe
z$cYqx9;obuu)Zjs$UP-8^U&CtCsF3tln2Awiposa3{ItWb#s((gQm_PGstd@Y0t$5642pgqWb!HCl&P=M#$mUp96dpS+oSr2
zSp4r%!b~cG3m8XO)7wM=J9PnPA^yM5??eKTsgZNy(~I2r)X22_5?ZIMaEgj92LKJB
z45wCJT69@a{d9EgX8=xt*z|}SFDe2&7D05<6p0k8pS}vVnU82OrO9ZVa={uzo*3sT
zoZ=uER#D{1jOgTZQO7BYDoQ{Tn-N(!tA08WIwOWmc;yy}$oSOxh%ZIq(`Gn?gZE<;
zfH_kh$}!_yk)v#Sq)3yVInxsJ-#vEPgA}V>V$_Rl_rO(P^
zk%-iJiy)FY*xZrOa3QMsV1$YmNDGiwY@%nQ)+9F};)=@16|;osV^p(*$Z$?f3mV(j
z&{L9Xgpd|aM`Sf>zNpgi=fg&ri$tx?uLOsLzi^f;?Sdk-$HfX-v~U)wzqR4aHpQi6S#(yKN?EXf?4x
zj4>N)JOG&5a)=C5_w8mQo0cs_K6s(g$$62S92eAf(
zv)*uf#Vpd;hKpeF_4Dy(qc@49ex(9H#S*u{TkvY3s7+o_{d5W3tgS#WKxDRPJYi50
zuTcVt$rWIRDzVj@l`=MYGfEssyNol9(_nM(nSyJoL>0>8mK)=iJIVN(d_$RKcK2E^
z5K7Htb4@l$I*^HgL9ZrVQl4&`!b)S@W+!R5(0;xafUV8AznK)6>RvI6Dr|TUW5aOn
zGn4VMu^T>B{{4;%2fMOMC&yLb_3(w#T^1RaJ6XEiDP9@)G+gYF02(7)G?z~GFEIk4
z=u~bY(>$$xx&+>}b`~|hQcX$NsgKqSPidf4hK$Nh%#>wN0p+>?s7u=GEWe=1s%L8~
z)f})Jf%FxkFt31IlD!+JULwz!V2m{~Ng7r@bz*TXc40*YrlTRT7kaz6B5oFwxmir{
zc0t7^D+H{KQy6Ut8|_pL7v!dC>H=-LU+JaZZfFKjJ>5{5w;P&i{J!io%9VaauQN;O
zLquj%cXB3sfk1bH`xLcVKy!0R)Mt6LiTFID%>-+c9MXJ`sVtE8dA6YmepvQi%VnQ)q3L2)c=^J{Y*QWC39PiO`C?7HXdq6$MA|*ZS7fP|=v0sE
zzf_k3Ahn3gG?wZ!sJg2q(AziaBPxfC|?_=uvPX*FeBlSV5^?-W1(zQ
zMIw(L#7*Y$;}p|4XgFEyZC7V-yDH&!HPt&1oaP+}atjf*Tq*~GGrX;^%s9oFx~+-E
zRnBd2mWGRZ&DPZvXc$Ry8=z{=@ypw1GIL?iYA8q}92}|6IVn2NSOi5Ah^(=#ug^&t(jJ}pRCrccAOjm)W`o#}}}
z;d7*hsZGrFsP`-hMl(6+8z^VkaY3foN4rNSn8g`Y1c
z$8q+?1=3s!wcLanyc2TBZL(K7JolSo{1aTR;UB{j(>3!TUKuy;U-!Bx8VV|LOtbpv
z>D)(`$|>Uv(>s>&WNjw*&b|R(faolb4xloxLJ{>SR7!r1^hk3}jbvLp%P$1#E{#rt
zlZ$YDNZC(fd(LNjj(cg59~r%1?U;mp=dr_zX}HiI`8CgQE+6cu-T`CMAh7~ziK36C
zwopWq(Eta*Jg#xDzgtXdi$UQ^v(EF%*o?k;6^IR83q}a6fCW~l;nLv!%GI3G4o-;9^IDU=QY
zou98Sm9;j87RH&Efbf7=qU3JQ?*X~_#ku*(Wl6o-=k3Vg{Kyx2dcn!UQ|j(-j7gfw
z2U`%mBubm=l{dT6X~r#L`O>HoGhsw@%bj6-r1GaY06;FI2}g)|FHc)AE0YPcwM5Az
zecBGVNt&K1Qe?<9{8X#HWaczc^P~p*HP3WK*ui``qgfzlQ)<*n98`GPfgW~}>d%#K
zccHf=3_Cq!!G&ksNjzef#ymNuwv#|IhX6ozl*drh|D7
znGMZvJk~g0>(VouUEl@!U76@XOcBzb`1>$yPK9bA%QNG66M|W!aW`ki!+Id?2H|M@
z&dxYNuTzS%-zi|f!;=TtNYKNb0>f|Rg^kx2vXSLWBa6#+SD>pP+HWEI@gfZu{iGQQ
z3c<^j7a9pFdq#gK&GL*&r7)k5hd~;14fvm_eup!S41yXPt=z*a3Qq?YKpxR!2{X)$
zyv(FXan9sUipDel`-~-lCHTrN>ih=IA`ks%>H_f_`L_cTcCOm__-0s-QK
zn1P%OqHx5JB%`}+YR5
z#t;9s`%jVFQTN^(qi091+#j#IHU5TsSE%&a+N5
zFZ!Tc^rAbA;^I$VS%1skKL;#t((99Y-S0WM_!XC2J{({0%ro_CzI6Bd+z;QBOMNTd
z9k1%_xn<<@K#aJ%Uw5lt8NBvExA4e=@#Povg6dCV#M009zwVa3{tw;mJ&_~s12^65
ze)q;Bn`S@Lwtcx<5U-S>XbjC`JA@Q<@C}{aU>tm|oL&Zr;*r4)3X*WEW>kyN^jpA&
z`#$>fQDSJ)#z{SS(e%x2ZEev>DDh%oMIE|J$!dm4!pAlKVEwVlm
zmet#iPN4;yww4Twqz__KJ?TE2bT$Ou(Ug4VjFzO$8DSFDQB^N@dL(lBbCJuV5y*nR
zh>beUr>SxdPD92a8ha!|MD&CqS{ijhkZ#tAI+Mu{{;~MQ2|KcWxwUf~*?U|GT$*wv
z&WoOki95Emv~_oPuZbt8@0og6{F?a3+&QmAYi79V`0<|)yG4hG
z-;Mw1SG1k;P)5|5_eUjE$9uqqG>APo=uNnGuxtE0B3|c?sB!Lya34T+apR57=tci?g|eBC(!NqCHz)f8~tzlS@%qRUOTx>v*#+v7is-{$_C6W{1QeA99F
zStp0z!}0A0t@Uk_#NVS=73J>Nfl_eT-Fw`<`=(a+tX$e1
ze$m|a!W4z1#WaPy)A4Tx^fLqqp9Y5$69^T~6K*HqX
z4etE-YIoO>q+3ww?%jB?TfExcx4PC%#Gih|-5gK2|9s;skGdE}ZN_srMVxZUw1J#JZi+8TF%{K(Kjcc}Fmx8(R5_u(7kN3z59
z?t3H0qcjfrrD%au{u7?Cr;aH|(_5Hvf(`M+bJ~i$j(cafm&dyv>G{!z9_hcvee9-q*MGY+M5M!~1AC+ROyl%W^!B(D9tb;*$cnG6$L%yesghJSk5njW_#x-#Mx=G?uN`$ydUM{fAs=enPXuW{ej
z`nhNcWL6+#_S_$r%=CS}V9sYTV@b^8;mG+U&Q=ZQJ&{PGJL_$ogZmUKDuFh)yN}5ZQGyPzWu7p+pZp_|JS&~
zU2f6wA7A-XF>)^xLj0fc+SnFwn#xH@|qEy%@ho4MzG
z^*?{)rVTrnKA)>`TOM$i;cTLXCJm8j8x2Y0q(vO}daSoJw0+UN=cXJ+lsR`_C4#HnUn4k(q`md=
zccHJje&dD~6d(VE``a74+;>HC?*H6a>E0H}#piX$&vjo1@Gb!V9l(#^cYl0i!nWuq7jt-wT`YfqELee+K~U=eC_a>B6w?KF`&J$}nEMOIp9~4!?3Jg+J@Bz$d&{y1mEUB}d%mBN*s?9y6Q0
zH@nl1xPz_kR7`_gqYI(lHlg0rw$x;fYa*rY6@_mJQ|hT4N#r?*2@RW1Vxof4Ncm(Z
zG=j*21>J2`!&i29SFLGSus|%KeOQpbbE2fd9$dBeC@6dvGVak)7^mRSD5x4dn)8(4
zRl0ZeEunMqX&sxK%uc}_jWhmFdujTtnHL_-cg-ZD>+mP)T!g=;g~n-VQm6Z62gZe?
ze1s?mTj