mirror of https://github.com/golang/go.git
[release-branch.go1.11] Merge branch 'master' into release-branch.go1.11
Change-Id: I4f09f847c7304e37df8388b45aa8d6281a677de3
This commit is contained in:
commit
673a05e4df
|
|
@ -44,18 +44,16 @@ control repositories.
|
|||
<h3 id="Workspaces">Workspaces</h3>
|
||||
|
||||
<p>
|
||||
A workspace is a directory hierarchy with three directories at its root:
|
||||
A workspace is a directory hierarchy with two directories at its root:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><code>src</code> contains Go source files,
|
||||
<li><code>pkg</code> contains package objects, and
|
||||
<li><code>src</code> contains Go source files, and
|
||||
<li><code>bin</code> contains executable commands.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The <code>go</code> tool builds source packages and installs the resulting
|
||||
binaries to the <code>pkg</code> and <code>bin</code> directories.
|
||||
The <code>go</code> tool builds and installs binaries to the <code>bin</code> directory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -72,10 +70,6 @@ To give you an idea of how a workspace looks in practice, here's an example:
|
|||
bin/
|
||||
hello # command executable
|
||||
outyet # command executable
|
||||
pkg/
|
||||
linux_amd64/
|
||||
github.com/golang/example/
|
||||
stringutil.a # package object
|
||||
src/
|
||||
<a href="https://github.com/golang/example/">github.com/golang/example/</a>
|
||||
.git/ # Git repository metadata
|
||||
|
|
@ -374,9 +368,8 @@ $ <b>go build</b>
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
This won't produce an output file. To do that, you must use <code>go
|
||||
install</code>, which places the package object inside the <code>pkg</code>
|
||||
directory of the workspace.
|
||||
This won't produce an output file.
|
||||
Instead it saves the compiled package in the local build cache.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -400,19 +393,13 @@ func main() {
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
Whenever the <code>go</code> tool installs a package or binary, it also
|
||||
installs whatever dependencies it has.
|
||||
So when you install the <code>hello</code> program
|
||||
Install the <code>hello</code> program:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ <b>go install github.com/user/hello</b>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
the <code>stringutil</code> package will be installed as well, automatically.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Running the new version of the program, you should see a new, reversed message:
|
||||
</p>
|
||||
|
|
@ -429,10 +416,6 @@ After the steps above, your workspace should look like this:
|
|||
<pre>
|
||||
bin/
|
||||
hello # command executable
|
||||
pkg/
|
||||
linux_amd64/ # this will reflect your OS and architecture
|
||||
github.com/user/
|
||||
stringutil.a # package object
|
||||
src/
|
||||
github.com/user/
|
||||
hello/
|
||||
|
|
@ -441,22 +424,6 @@ src/
|
|||
reverse.go # package source
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Note that <code>go install</code> placed the <code>stringutil.a</code> object
|
||||
in a directory inside <code>pkg/linux_amd64</code> that mirrors its source
|
||||
directory.
|
||||
This is so that future invocations of the <code>go</code> tool can find the
|
||||
package object and avoid recompiling the package unnecessarily.
|
||||
The <code>linux_amd64</code> part is there to aid in cross-compilation,
|
||||
and will reflect the operating system and architecture of your system.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Go command executables are statically linked; the package objects need not
|
||||
be present to run Go programs.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="PackageNames">Package names</h3>
|
||||
|
||||
<p>
|
||||
|
|
@ -597,12 +564,6 @@ tree should now look like this:
|
|||
<pre>
|
||||
bin/
|
||||
hello # command executable
|
||||
pkg/
|
||||
linux_amd64/
|
||||
github.com/golang/example/
|
||||
stringutil.a # package object
|
||||
github.com/user/
|
||||
stringutil.a # package object
|
||||
src/
|
||||
github.com/golang/example/
|
||||
.git/ # Git repository metadata
|
||||
|
|
|
|||
|
|
@ -167,7 +167,18 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<h3 id="gopackages">Package loading</h3>
|
||||
|
||||
<p>
|
||||
TODO: Note about go/build versus golang.org/x/tools/go/packages.
|
||||
The new package
|
||||
<a href="https://godoc.org/golang.org/x/tools/go/packages"><code>golang.org/x/tools/go/packages</code></a>
|
||||
provides a simple API for locating and loading packages of Go source code.
|
||||
Although not yet part of the standard library, for many tasks it
|
||||
effectively replaces the <a href="/pkg/go/build"><code>go/build</code></a>
|
||||
package, whose API is unable to fully support modules.
|
||||
Because it runs an external query command such as
|
||||
<a href="/cmd/go/#hdr-List_packages"><code>go list</code></a>
|
||||
to obtain information about Go packages, it enables the construction of
|
||||
analysis tools that work equally well with alternative build systems
|
||||
such as <a href="https://bazel.build">Bazel</a>
|
||||
and <a href="https://buckbuild.com">Buck</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="gocache">Build cache requirement</h3>
|
||||
|
|
@ -262,9 +273,8 @@ func f(v interface{}) {
|
|||
|
||||
This is useful, for example, to call <code>String</code> methods
|
||||
when paused at a breakpoint.
|
||||
<!-- TODO(austin): Make sure methods calls are actually supported by Delve -->
|
||||
|
||||
This is currently only supported by Delve.
|
||||
This is currently only supported by Delve (version 1.1.0 and up).
|
||||
</p>
|
||||
|
||||
<h3 id="test">Test</h3>
|
||||
|
|
@ -793,7 +803,7 @@ for k := range m {
|
|||
|
||||
<!-- CL 101715 was reverted -->
|
||||
|
||||
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
||||
<dl id="runtime-again"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
||||
<dd>
|
||||
|
||||
<p><!-- CL 70993 -->
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@ type ptabEntry struct {
|
|||
|
||||
// runtime interface and reflection data structures
|
||||
var (
|
||||
signatsetmu sync.Mutex // protects signatset
|
||||
signatmu sync.Mutex // protects signatset and signatslice
|
||||
signatset = make(map[*types.Type]struct{})
|
||||
signatslice []*types.Type
|
||||
|
||||
itabs []itabEntry
|
||||
ptabs []ptabEntry
|
||||
|
|
@ -960,9 +961,9 @@ func typesymprefix(prefix string, t *types.Type) *types.Sym {
|
|||
|
||||
// This function is for looking up type-related generated functions
|
||||
// (e.g. eq and hash). Make sure they are indeed generated.
|
||||
signatsetmu.Lock()
|
||||
signatmu.Lock()
|
||||
addsignat(t)
|
||||
signatsetmu.Unlock()
|
||||
signatmu.Unlock()
|
||||
|
||||
//print("algsym: %s -> %+S\n", p, s);
|
||||
|
||||
|
|
@ -974,9 +975,9 @@ func typenamesym(t *types.Type) *types.Sym {
|
|||
Fatalf("typenamesym %v", t)
|
||||
}
|
||||
s := typesym(t)
|
||||
signatsetmu.Lock()
|
||||
signatmu.Lock()
|
||||
addsignat(t)
|
||||
signatsetmu.Unlock()
|
||||
signatmu.Unlock()
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
@ -1447,7 +1448,10 @@ func itabsym(it *obj.LSym, offset int64) *obj.LSym {
|
|||
|
||||
// addsignat ensures that a runtime type descriptor is emitted for t.
|
||||
func addsignat(t *types.Type) {
|
||||
signatset[t] = struct{}{}
|
||||
if _, ok := signatset[t]; !ok {
|
||||
signatset[t] = struct{}{}
|
||||
signatslice = append(signatslice, t)
|
||||
}
|
||||
}
|
||||
|
||||
func addsignats(dcls []*Node) {
|
||||
|
|
@ -1462,14 +1466,15 @@ func addsignats(dcls []*Node) {
|
|||
func dumpsignats() {
|
||||
// Process signatset. Use a loop, as dtypesym adds
|
||||
// entries to signatset while it is being processed.
|
||||
signats := make([]typeAndStr, len(signatset))
|
||||
for len(signatset) > 0 {
|
||||
signats := make([]typeAndStr, len(signatslice))
|
||||
for len(signatslice) > 0 {
|
||||
signats = signats[:0]
|
||||
// Transfer entries to a slice and sort, for reproducible builds.
|
||||
for t := range signatset {
|
||||
for _, t := range signatslice {
|
||||
signats = append(signats, typeAndStr{t: t, short: typesymname(t), regular: t.String()})
|
||||
delete(signatset, t)
|
||||
}
|
||||
signatslice = signatslice[:0]
|
||||
sort.Sort(typesByString(signats))
|
||||
for _, ts := range signats {
|
||||
t := ts.t
|
||||
|
|
|
|||
|
|
@ -3515,6 +3515,10 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
|||
break
|
||||
}
|
||||
closure = s.expr(fn)
|
||||
if thearch.LinkArch.Family == sys.Wasm {
|
||||
// TODO(neelance): On other architectures this should be eliminated by the optimization steps
|
||||
s.nilCheck(closure)
|
||||
}
|
||||
case OCALLMETH:
|
||||
if fn.Op != ODOTMETH {
|
||||
Fatalf("OCALLMETH: n.Left not an ODOTMETH: %v", fn)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
// cache build and test caching
|
||||
// environment environment variables
|
||||
// filetype file types
|
||||
// go.mod the go.mod file
|
||||
// gopath GOPATH environment variable
|
||||
// gopath-get legacy GOPATH go get
|
||||
// goproxy module proxy protocol
|
||||
|
|
@ -622,24 +623,25 @@
|
|||
// to -f '{{.ImportPath}}'. The struct being passed to the template is:
|
||||
//
|
||||
// type Package struct {
|
||||
// Dir string // directory containing package sources
|
||||
// ImportPath string // import path of package in dir
|
||||
// ImportComment string // path in import comment on package statement
|
||||
// Name string // package name
|
||||
// Doc string // package documentation string
|
||||
// Target string // install path
|
||||
// Shlib string // the shared library that contains this package (only set when -linkshared)
|
||||
// Goroot bool // is this package in the Go root?
|
||||
// Standard bool // is this package part of the standard Go library?
|
||||
// Stale bool // would 'go install' do anything for this package?
|
||||
// StaleReason string // explanation for Stale==true
|
||||
// Root string // Go root or Go path dir containing this package
|
||||
// ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
// BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
// ForTest string // package is only for use in named test
|
||||
// DepOnly bool // package is only a dependency, not explicitly listed
|
||||
// Export string // file containing export data (when using -export)
|
||||
// Module *Module // info about package's containing module, if any (can be nil)
|
||||
// Dir string // directory containing package sources
|
||||
// ImportPath string // import path of package in dir
|
||||
// ImportComment string // path in import comment on package statement
|
||||
// Name string // package name
|
||||
// Doc string // package documentation string
|
||||
// Target string // install path
|
||||
// Shlib string // the shared library that contains this package (only set when -linkshared)
|
||||
// Goroot bool // is this package in the Go root?
|
||||
// Standard bool // is this package part of the standard Go library?
|
||||
// Stale bool // would 'go install' do anything for this package?
|
||||
// StaleReason string // explanation for Stale==true
|
||||
// Root string // Go root or Go path dir containing this package
|
||||
// ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
// BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
// ForTest string // package is only for use in named test
|
||||
// Export string // file containing export data (when using -export)
|
||||
// Module *Module // info about package's containing module, if any (can be nil)
|
||||
// Match []string // command-line patterns matching this package
|
||||
// DepOnly bool // package is only a dependency, not explicitly listed
|
||||
//
|
||||
// // Source files
|
||||
// GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
||||
|
|
@ -722,7 +724,8 @@
|
|||
// The -compiled flag causes list to set CompiledGoFiles to the Go source
|
||||
// files presented to the compiler. Typically this means that it repeats
|
||||
// the files listed in GoFiles and then also adds the Go code generated
|
||||
// by processing CgoFiles and SwigFiles.
|
||||
// by processing CgoFiles and SwigFiles. The Imports list contains the
|
||||
// union of all imports from both GoFiles and CompiledGoFiles.
|
||||
//
|
||||
// The -deps flag causes list to iterate over not just the named packages
|
||||
// but also all their dependencies. It visits them in a depth-first post-order
|
||||
|
|
@ -842,7 +845,7 @@
|
|||
// module paths match the pattern.
|
||||
// A query of the form path@version specifies the result of that query,
|
||||
// which is not limited to active modules.
|
||||
// See 'go help module' for more about module queries.
|
||||
// See 'go help modules' for more about module queries.
|
||||
//
|
||||
// The template function "module" takes a single string argument
|
||||
// that must be a module path or query and returns the specified
|
||||
|
|
@ -873,7 +876,6 @@
|
|||
//
|
||||
// download download modules to local cache
|
||||
// edit edit go.mod from tools or scripts
|
||||
// fix make go.mod semantically consistent
|
||||
// graph print module requirement graph
|
||||
// init initialize new module in current directory
|
||||
// tidy add missing and remove unused modules
|
||||
|
|
@ -912,7 +914,7 @@
|
|||
// Dir string // absolute path to cached source root directory
|
||||
// }
|
||||
//
|
||||
// See 'go help module' for more about module queries.
|
||||
// See 'go help modules' for more about module queries.
|
||||
//
|
||||
//
|
||||
// Edit go.mod from tools or scripts
|
||||
|
|
@ -997,52 +999,6 @@
|
|||
// by invoking 'go mod edit' with -require, -exclude, and so on.
|
||||
//
|
||||
//
|
||||
// Make go.mod semantically consistent
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// go mod fix
|
||||
//
|
||||
// Fix updates go.mod to use canonical version identifiers and
|
||||
// to be semantically consistent. For example, consider this go.mod file:
|
||||
//
|
||||
// module M
|
||||
//
|
||||
// require (
|
||||
// A v1
|
||||
// B v1.0.0
|
||||
// C v1.0.0
|
||||
// D v1.2.3
|
||||
// E dev
|
||||
// )
|
||||
//
|
||||
// exclude D v1.2.3
|
||||
//
|
||||
// First, fix rewrites non-canonical version identifiers to semver form, so
|
||||
// A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the latest
|
||||
// commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1.
|
||||
//
|
||||
// Next, fix updates requirements to respect exclusions, so the requirement
|
||||
// on the excluded D v1.2.3 is updated to use the next available version of D,
|
||||
// perhaps D v1.2.4 or D v1.3.0.
|
||||
//
|
||||
// Finally, fix removes redundant or misleading requirements.
|
||||
// For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0, then go.mod's
|
||||
// requirement of B v1.0.0 is misleading (superseded by A's need for v1.2.0),
|
||||
// and its requirement of C v1.0.0 is redundant (implied by A's need for the
|
||||
// same version), so both will be removed. If module M contains packages
|
||||
// that directly import packages from B or C, then the requirements will be
|
||||
// kept but updated to the actual versions being used.
|
||||
//
|
||||
// Although fix runs the fix-up operation in isolation, the fix-up also
|
||||
// runs automatically any time a go command uses the module graph,
|
||||
// to update go.mod to reflect reality. Because the module graph defines
|
||||
// the meaning of import statements, any commands that load packages
|
||||
// also use and therefore fix the module graph. For example,
|
||||
// go build, go get, go install, go list, go test, go mod graph, go mod tidy,
|
||||
// and other commands all effectively imply go mod fix.
|
||||
//
|
||||
//
|
||||
// Print module requirement graph
|
||||
//
|
||||
// Usage:
|
||||
|
|
@ -1619,6 +1575,73 @@
|
|||
// command.
|
||||
//
|
||||
//
|
||||
// The go.mod file
|
||||
//
|
||||
// A module version is defined by a tree of source files, with a go.mod
|
||||
// file in its root. When the go command is run, it looks in the current
|
||||
// directory and then successive parent directories to find the go.mod
|
||||
// marking the root of the main (current) module.
|
||||
//
|
||||
// The go.mod file itself is line-oriented, with // comments but
|
||||
// no /* */ comments. Each line holds a single directive, made up of a
|
||||
// verb followed by arguments. For example:
|
||||
//
|
||||
// module my/thing
|
||||
// require other/thing v1.0.2
|
||||
// require new/thing v2.3.4
|
||||
// exclude old/thing v1.2.3
|
||||
// replace bad/thing v1.4.5 => good/thing v1.4.5
|
||||
//
|
||||
// The verbs are module, to define the module path; require, to require
|
||||
// a particular module at a given version or later; exclude, to exclude
|
||||
// a particular module version from use; and replace, to replace a module
|
||||
// version with a different module version. Exclude and replace apply only
|
||||
// in the main module's go.mod and are ignored in dependencies.
|
||||
// See https://research.swtch.com/vgo-mvs for details.
|
||||
//
|
||||
// The leading verb can be factored out of adjacent lines to create a block,
|
||||
// like in Go imports:
|
||||
//
|
||||
// require (
|
||||
// new/thing v2.3.4
|
||||
// old/thing v1.2.3
|
||||
// )
|
||||
//
|
||||
// The go.mod file is designed both to be edited directly and to be
|
||||
// easily updated by tools. The 'go mod edit' command can be used to
|
||||
// parse and edit the go.mod file from programs and tools.
|
||||
// See 'go help mod edit'.
|
||||
//
|
||||
// The go command automatically updates go.mod each time it uses the
|
||||
// module graph, to make sure go.mod always accurately reflects reality
|
||||
// and is properly formatted.
|
||||
//
|
||||
// The update rewrites non-canonical version identifiers to semver form,
|
||||
// so A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the
|
||||
// latest commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1.
|
||||
//
|
||||
// The update modifies requirements to respect exclusions, so the
|
||||
// requirement on the excluded D v1.2.3 is updated to use the next
|
||||
// available version of D, perhaps D v1.2.4 or D v1.3.0.
|
||||
//
|
||||
// The update removes redundant or misleading requirements.
|
||||
// For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0,
|
||||
// then go.mod's requirement of B v1.0.0 is misleading (superseded by
|
||||
// A's need for v1.2.0), and its requirement of C v1.0.0 is redundant
|
||||
// (implied by A's need for the same version), so both will be removed.
|
||||
// If module M contains packages that directly import packages from B or
|
||||
// C, then the requirements will be kept but updated to the actual
|
||||
// versions being used.
|
||||
//
|
||||
// Finally, the update reformats the go.mod in a canonical formatting, so
|
||||
// that future mechanical changes will result in minimal diffs.
|
||||
//
|
||||
// Because the module graph defines the meaning of import statements, any
|
||||
// commands that load packages also use and therefore update go.mod,
|
||||
// including go build, go get, go install, go list, go test, go mod graph,
|
||||
// go mod tidy, and go mod why.
|
||||
//
|
||||
//
|
||||
// GOPATH environment variable
|
||||
//
|
||||
// The Go path is used to resolve import statements.
|
||||
|
|
@ -2094,7 +2117,7 @@
|
|||
// The go.mod file can also specify replacements and excluded versions
|
||||
// that only apply when building the module directly; they are ignored
|
||||
// when the module is incorporated into a larger build.
|
||||
// For more about the go.mod file, see https://research.swtch.com/vgo-module.
|
||||
// For more about the go.mod file, see 'go help go.mod'.
|
||||
//
|
||||
// To start a new module, simply create a go.mod file in the root of the
|
||||
// module's directory tree, containing only a module statement.
|
||||
|
|
@ -2349,8 +2372,6 @@
|
|||
// about how source code in version control systems is mapped to
|
||||
// module file trees.
|
||||
//
|
||||
// TODO: Add documentation to go command.
|
||||
//
|
||||
// Module downloading and verification
|
||||
//
|
||||
// The go command maintains, in the main module's root directory alongside
|
||||
|
|
|
|||
|
|
@ -1291,6 +1291,7 @@ func TestGetGitDefaultBranch(t *testing.T) {
|
|||
tg.grepStdout(`\* another-branch`, "not on correct default branch")
|
||||
}
|
||||
|
||||
// Security issue. Don't disable. See golang.org/issue/22125.
|
||||
func TestAccidentalGitCheckout(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
|
|
@ -1301,13 +1302,17 @@ func TestAccidentalGitCheckout(t *testing.T) {
|
|||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempDir("src")
|
||||
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
|
||||
tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git")
|
||||
tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
|
||||
|
||||
tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
|
||||
tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
|
||||
if _, err := os.Stat(tg.path("SrC")); err == nil {
|
||||
// This case only triggers on a case-insensitive file system.
|
||||
tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
|
||||
tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
|
||||
|
|
@ -3527,24 +3532,43 @@ func TestImportLocal(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGoGetInsecure(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
test := func(t *testing.T, modules bool) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.failSSH()
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.makeTempdir()
|
||||
tg.failSSH()
|
||||
|
||||
const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p"
|
||||
if modules {
|
||||
tg.setenv("GOPATH", tg.path("gp"))
|
||||
tg.tempFile("go.mod", "module m")
|
||||
tg.cd(tg.path("."))
|
||||
tg.setenv("GO111MODULE", "on")
|
||||
} else {
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GO111MODULE", "off")
|
||||
}
|
||||
|
||||
// Try go get -d of HTTP-only repo (should fail).
|
||||
tg.runFail("get", "-d", repo)
|
||||
const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p"
|
||||
|
||||
// Try again with -insecure (should succeed).
|
||||
tg.run("get", "-d", "-insecure", repo)
|
||||
// Try go get -d of HTTP-only repo (should fail).
|
||||
tg.runFail("get", "-d", repo)
|
||||
|
||||
// Try updating without -insecure (should fail).
|
||||
tg.runFail("get", "-d", "-u", "-f", repo)
|
||||
// Try again with -insecure (should succeed).
|
||||
tg.run("get", "-d", "-insecure", repo)
|
||||
|
||||
// Try updating without -insecure (should fail).
|
||||
tg.runFail("get", "-d", "-u", "-f", repo)
|
||||
|
||||
if modules {
|
||||
tg.run("list", "-m", "...")
|
||||
tg.grepStdout("insecure.go-get-issue", "should find insecure module")
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("gopath", func(t *testing.T) { test(t, false) })
|
||||
t.Run("modules", func(t *testing.T) { test(t, true) })
|
||||
}
|
||||
|
||||
func TestGoGetUpdateInsecure(t *testing.T) {
|
||||
|
|
@ -4187,9 +4211,10 @@ func TestGoGetUpdateWithWildcard(t *testing.T) {
|
|||
tg.setenv("GOPATH", tg.path("."))
|
||||
const aPkgImportPath = "github.com/tmwh/go-get-issue-14450/a"
|
||||
tg.run("get", aPkgImportPath)
|
||||
tg.run("get", "-u", ".../")
|
||||
tg.grepStderrNot("cannot find package", "did not update packages given wildcard path")
|
||||
tg.runFail("get", "-u", ".../")
|
||||
tg.grepStderr("cannot find package.*d-dependency/e", "should have detected e missing")
|
||||
|
||||
// Even though get -u failed, the source for others should be downloaded.
|
||||
var expectedPkgPaths = []string{
|
||||
"src/github.com/tmwh/go-get-issue-14450/b",
|
||||
"src/github.com/tmwh/go-get-issue-14450-b-dependency/c",
|
||||
|
|
@ -5647,37 +5672,6 @@ func TestRelativePkgdir(t *testing.T) {
|
|||
tg.run("build", "-i", "-pkgdir=.", "runtime")
|
||||
}
|
||||
|
||||
func TestGcflagsPatterns(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo has no standard packages")
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.setenv("GOCACHE", "off")
|
||||
|
||||
tg.run("build", "-n", "-v", "-gcflags= \t\r\n -e", "fmt")
|
||||
tg.grepStderr("^# fmt", "did not rebuild fmt")
|
||||
tg.grepStderrNot("^# reflect", "incorrectly rebuilt reflect")
|
||||
|
||||
tg.run("build", "-n", "-v", "-gcflags=-e", "fmt", "reflect")
|
||||
tg.grepStderr("^# fmt", "did not rebuild fmt")
|
||||
tg.grepStderr("^# reflect", "did not rebuild reflect")
|
||||
tg.grepStderrNot("^# runtime", "incorrectly rebuilt runtime")
|
||||
|
||||
tg.run("build", "-n", "-x", "-v", "-gcflags= \t\r\n reflect \t\r\n = \t\r\n -N", "fmt")
|
||||
tg.grepStderr("^# fmt", "did not rebuild fmt")
|
||||
tg.grepStderr("^# reflect", "did not rebuild reflect")
|
||||
tg.grepStderr("compile.* -N .*-p reflect", "did not build reflect with -N flag")
|
||||
tg.grepStderrNot("compile.* -N .*-p fmt", "incorrectly built fmt with -N flag")
|
||||
|
||||
tg.run("test", "-c", "-n", "-gcflags=-N", "-ldflags=-X=x.y=z", "strings")
|
||||
tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag")
|
||||
tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag")
|
||||
|
||||
tg.run("test", "-c", "-n", "-gcflags=strings=-N", "-ldflags=strings=-X=x.y=z", "strings")
|
||||
tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag")
|
||||
tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag")
|
||||
}
|
||||
|
||||
func TestGoTestMinusN(t *testing.T) {
|
||||
// Intent here is to verify that 'go test -n' works without crashing.
|
||||
// This reuses flag_test.go, but really any test would do.
|
||||
|
|
|
|||
|
|
@ -163,9 +163,8 @@ func runGet(cmd *base.Command, args []string) {
|
|||
if *getT {
|
||||
mode |= load.GetTestDeps
|
||||
}
|
||||
args = downloadPaths(args)
|
||||
for _, arg := range args {
|
||||
download(arg, nil, &stk, mode)
|
||||
for _, pkg := range downloadPaths(args) {
|
||||
download(pkg, nil, &stk, mode)
|
||||
}
|
||||
base.ExitIfErrors()
|
||||
|
||||
|
|
@ -184,8 +183,7 @@ func runGet(cmd *base.Command, args []string) {
|
|||
// This leads to duplicated loads of the standard packages.
|
||||
load.ClearCmdCache()
|
||||
|
||||
args = load.ImportPaths(args)
|
||||
load.PackagesForBuild(args)
|
||||
pkgs := load.PackagesForBuild(args)
|
||||
|
||||
// Phase 3. Install.
|
||||
if *getD {
|
||||
|
|
@ -195,7 +193,7 @@ func runGet(cmd *base.Command, args []string) {
|
|||
return
|
||||
}
|
||||
|
||||
work.InstallPackages(args)
|
||||
work.InstallPackages(args, pkgs)
|
||||
}
|
||||
|
||||
// downloadPaths prepares the list of paths to pass to download.
|
||||
|
|
@ -203,34 +201,21 @@ func runGet(cmd *base.Command, args []string) {
|
|||
// for a particular pattern, downloadPaths leaves it in the result list,
|
||||
// in the hope that we can figure out the repository from the
|
||||
// initial ...-free prefix.
|
||||
func downloadPaths(args []string) []string {
|
||||
for _, arg := range args {
|
||||
func downloadPaths(patterns []string) []string {
|
||||
for _, arg := range patterns {
|
||||
if strings.Contains(arg, "@") {
|
||||
base.Fatalf("go: cannot use path@version syntax in GOPATH mode")
|
||||
}
|
||||
}
|
||||
|
||||
args = load.ImportPathsForGoGet(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
if strings.Contains(a, "...") {
|
||||
var expand []string
|
||||
// Use matchPackagesInFS to avoid printing
|
||||
// warnings. They will be printed by the
|
||||
// eventual call to importPaths instead.
|
||||
if build.IsLocalImport(a) {
|
||||
expand = search.MatchPackagesInFS(a)
|
||||
} else {
|
||||
expand = search.MatchPackages(a)
|
||||
}
|
||||
if len(expand) > 0 {
|
||||
out = append(out, expand...)
|
||||
continue
|
||||
}
|
||||
var pkgs []string
|
||||
for _, m := range search.ImportPathsQuiet(patterns) {
|
||||
if len(m.Pkgs) == 0 && strings.Contains(m.Pattern, "...") {
|
||||
pkgs = append(pkgs, m.Pattern)
|
||||
} else {
|
||||
pkgs = append(pkgs, m.Pkgs...)
|
||||
}
|
||||
out = append(out, a)
|
||||
}
|
||||
return out
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// downloadCache records the import paths we have already
|
||||
|
|
@ -255,7 +240,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
|||
}
|
||||
load1 := func(path string, mode int) *load.Package {
|
||||
if parent == nil {
|
||||
return load.LoadPackage(path, stk)
|
||||
return load.LoadPackageNoFlags(path, stk)
|
||||
}
|
||||
return load.LoadImport(path, parent.Dir, parent, stk, nil, mode|load.ResolveModule)
|
||||
}
|
||||
|
|
@ -311,9 +296,9 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
|||
// for p has been replaced in the package cache.
|
||||
if wildcardOkay && strings.Contains(arg, "...") {
|
||||
if build.IsLocalImport(arg) {
|
||||
args = search.MatchPackagesInFS(arg)
|
||||
args = search.MatchPackagesInFS(arg).Pkgs
|
||||
} else {
|
||||
args = search.MatchPackages(arg)
|
||||
args = search.MatchPackages(arg).Pkgs
|
||||
}
|
||||
isWildcard = true
|
||||
}
|
||||
|
|
@ -344,7 +329,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int)
|
|||
base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), files))
|
||||
|
||||
// The imports might have changed, so reload again.
|
||||
p = load.ReloadPackage(arg, stk)
|
||||
p = load.ReloadPackageNoFlags(arg, stk)
|
||||
if p.Error != nil {
|
||||
base.Errorf("%s", p.Error)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]stri
|
|||
imports := make(map[string]bool)
|
||||
testImports := make(map[string]bool)
|
||||
numFiles := 0
|
||||
Files:
|
||||
for _, name := range files {
|
||||
r, err := os.Open(name)
|
||||
if err != nil {
|
||||
|
|
@ -48,6 +49,19 @@ func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]stri
|
|||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("reading %s: %v", name, err)
|
||||
}
|
||||
|
||||
// import "C" is implicit requirement of cgo tag.
|
||||
// When listing files on the command line (explicitFiles=true)
|
||||
// we do not apply build tag filtering but we still do apply
|
||||
// cgo filtering, so no explicitFiles check here.
|
||||
// Why? Because we always have, and it's not worth breaking
|
||||
// that behavior now.
|
||||
for _, path := range list {
|
||||
if path == `"C"` && !tags["cgo"] && !tags["*"] {
|
||||
continue Files
|
||||
}
|
||||
}
|
||||
|
||||
if !explicitFiles && !ShouldBuild(data, tags) {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,24 +47,25 @@ syntax of package template. The default output is equivalent
|
|||
to -f '{{.ImportPath}}'. The struct being passed to the template is:
|
||||
|
||||
type Package struct {
|
||||
Dir string // directory containing package sources
|
||||
ImportPath string // import path of package in dir
|
||||
ImportComment string // path in import comment on package statement
|
||||
Name string // package name
|
||||
Doc string // package documentation string
|
||||
Target string // install path
|
||||
Shlib string // the shared library that contains this package (only set when -linkshared)
|
||||
Goroot bool // is this package in the Go root?
|
||||
Standard bool // is this package part of the standard Go library?
|
||||
Stale bool // would 'go install' do anything for this package?
|
||||
StaleReason string // explanation for Stale==true
|
||||
Root string // Go root or Go path dir containing this package
|
||||
ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
ForTest string // package is only for use in named test
|
||||
DepOnly bool // package is only a dependency, not explicitly listed
|
||||
Export string // file containing export data (when using -export)
|
||||
Module *Module // info about package's containing module, if any (can be nil)
|
||||
Dir string // directory containing package sources
|
||||
ImportPath string // import path of package in dir
|
||||
ImportComment string // path in import comment on package statement
|
||||
Name string // package name
|
||||
Doc string // package documentation string
|
||||
Target string // install path
|
||||
Shlib string // the shared library that contains this package (only set when -linkshared)
|
||||
Goroot bool // is this package in the Go root?
|
||||
Standard bool // is this package part of the standard Go library?
|
||||
Stale bool // would 'go install' do anything for this package?
|
||||
StaleReason string // explanation for Stale==true
|
||||
Root string // Go root or Go path dir containing this package
|
||||
ConflictDir string // this directory shadows Dir in $GOPATH
|
||||
BinaryOnly bool // binary-only package: cannot be recompiled from sources
|
||||
ForTest string // package is only for use in named test
|
||||
Export string // file containing export data (when using -export)
|
||||
Module *Module // info about package's containing module, if any (can be nil)
|
||||
Match []string // command-line patterns matching this package
|
||||
DepOnly bool // package is only a dependency, not explicitly listed
|
||||
|
||||
// Source files
|
||||
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
||||
|
|
@ -268,7 +269,7 @@ A pattern containing "..." specifies the active modules whose
|
|||
module paths match the pattern.
|
||||
A query of the form path@version specifies the result of that query,
|
||||
which is not limited to active modules.
|
||||
See 'go help module' for more about module queries.
|
||||
See 'go help modules' for more about module queries.
|
||||
|
||||
The template function "module" takes a single string argument
|
||||
that must be a module path or query and returns the specified
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ package load
|
|||
|
||||
import (
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/search"
|
||||
"cmd/go/internal/str"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
|
@ -92,52 +91,3 @@ func (f *PerPackageFlag) For(p *Package) []string {
|
|||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
var (
|
||||
cmdlineMatchers []func(*Package) bool
|
||||
cmdlineMatcherLiterals []func(*Package) bool
|
||||
)
|
||||
|
||||
// SetCmdlinePatterns records the set of patterns given on the command line,
|
||||
// for use by the PerPackageFlags.
|
||||
func SetCmdlinePatterns(args []string) {
|
||||
setCmdlinePatterns(args, base.Cwd)
|
||||
}
|
||||
|
||||
func setCmdlinePatterns(args []string, cwd string) {
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
cmdlineMatchers = nil // allow reset for testing
|
||||
cmdlineMatcherLiterals = nil
|
||||
for _, arg := range args {
|
||||
cmdlineMatchers = append(cmdlineMatchers, MatchPackage(arg, cwd))
|
||||
}
|
||||
for _, arg := range args {
|
||||
if !strings.Contains(arg, "...") && !search.IsMetaPackage(arg) {
|
||||
cmdlineMatcherLiterals = append(cmdlineMatcherLiterals, MatchPackage(arg, cwd))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isCmdlinePkg reports whether p is a package listed on the command line.
|
||||
func isCmdlinePkg(p *Package) bool {
|
||||
for _, m := range cmdlineMatchers {
|
||||
if m(p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isCmdlinePkgLiteral reports whether p is a package listed as
|
||||
// a literal package argument on the command line
|
||||
// (as opposed to being the result of expanding a wildcard).
|
||||
func isCmdlinePkgLiteral(p *Package) bool {
|
||||
for _, m := range cmdlineMatcherLiterals {
|
||||
if m(p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,11 @@ var (
|
|||
ModBinDir func() string // return effective bin directory
|
||||
ModLookup func(path string) (dir, realPath string, err error) // lookup effective meaning of import
|
||||
ModPackageModuleInfo func(path string) *modinfo.ModulePublic // return module info for Package struct
|
||||
ModImportPaths func(args []string) []string // expand import paths
|
||||
ModImportPaths func(args []string) []*search.Match // expand import paths
|
||||
ModPackageBuildInfo func(main string, deps []string) string // return module info to embed in binary
|
||||
ModInfoProg func(info string) []byte // wrap module info in .go code for binary
|
||||
ModImportFromFiles func([]string) // update go.mod to add modules for imports in these files
|
||||
ModDirImportPath func(string) string // return effective import path for directory
|
||||
)
|
||||
|
||||
var IgnoreImports bool // control whether we ignore imports in packages
|
||||
|
|
@ -60,15 +61,17 @@ type PackagePublic struct {
|
|||
Doc string `json:",omitempty"` // package documentation string
|
||||
Target string `json:",omitempty"` // installed target for this package (may be executable)
|
||||
Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared)
|
||||
Goroot bool `json:",omitempty"` // is this package found in the Go root?
|
||||
Standard bool `json:",omitempty"` // is this package part of the standard Go library?
|
||||
Root string `json:",omitempty"` // Go root or Go path dir containing this package
|
||||
ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory
|
||||
BinaryOnly bool `json:",omitempty"` // package cannot be recompiled
|
||||
ForTest string `json:",omitempty"` // package is only for use in named test
|
||||
DepOnly bool `json:",omitempty"` // package is only as a dependency, not explicitly listed
|
||||
Export string `json:",omitempty"` // file containing export data (set by go list -export)
|
||||
Module *modinfo.ModulePublic `json:",omitempty"` // info about package's module, if any
|
||||
Match []string `json:",omitempty"` // command-line patterns matching this package
|
||||
Goroot bool `json:",omitempty"` // is this package found in the Go root?
|
||||
Standard bool `json:",omitempty"` // is this package part of the standard Go library?
|
||||
DepOnly bool `json:",omitempty"` // package is only as a dependency, not explicitly listed
|
||||
BinaryOnly bool `json:",omitempty"` // package cannot be recompiled
|
||||
Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies?
|
||||
|
||||
// Stale and StaleReason remain here *only* for the list command.
|
||||
// They are only initialized in preparation for list execution.
|
||||
|
|
@ -107,7 +110,7 @@ type PackagePublic struct {
|
|||
Deps []string `json:",omitempty"` // all (recursively) imported dependencies
|
||||
|
||||
// Error information
|
||||
Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies?
|
||||
// Incomplete is above, packed into the other bools
|
||||
Error *PackageError `json:",omitempty"` // error loading this package (not dependencies)
|
||||
DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
|
||||
|
||||
|
|
@ -374,15 +377,17 @@ func ClearPackageCachePartial(args []string) {
|
|||
}
|
||||
}
|
||||
|
||||
// reloadPackage is like loadPackage but makes sure
|
||||
// ReloadPackageNoFlags is like LoadPackageNoFlags but makes sure
|
||||
// not to use the package cache.
|
||||
func ReloadPackage(arg string, stk *ImportStack) *Package {
|
||||
// It is only for use by GOPATH-based "go get".
|
||||
// TODO(rsc): When GOPATH-based "go get" is removed, delete this function.
|
||||
func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package {
|
||||
p := packageCache[arg]
|
||||
if p != nil {
|
||||
delete(packageCache, p.Dir)
|
||||
delete(packageCache, p.ImportPath)
|
||||
}
|
||||
return LoadPackage(arg, stk)
|
||||
return LoadPackageNoFlags(arg, stk)
|
||||
}
|
||||
|
||||
// dirToImportPath returns the pseudo-import path we use for a package
|
||||
|
|
@ -431,6 +436,9 @@ const (
|
|||
// 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.
|
||||
// It returns a *Package describing the package found in that directory.
|
||||
// LoadImport does not set tool flags and should only be used by
|
||||
// this package, as part of a bigger load operation, and by GOPATH-based "go get".
|
||||
// TODO(rsc): When GOPATH-based "go get" is removed, unexport this function.
|
||||
func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
|
||||
stk.Push(path)
|
||||
defer stk.Pop()
|
||||
|
|
@ -560,11 +568,11 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo
|
|||
}
|
||||
|
||||
// Checked on every import because the rules depend on the code doing the importing.
|
||||
if perr := disallowInternal(srcDir, parentPath, p, stk); perr != p {
|
||||
if perr := disallowInternal(srcDir, parent, parentPath, p, stk); perr != p {
|
||||
return setErrorPos(perr, importPos)
|
||||
}
|
||||
if mode&ResolveImport != 0 {
|
||||
if perr := disallowVendor(srcDir, parentPath, origPath, p, stk); perr != p {
|
||||
if perr := disallowVendor(srcDir, parent, parentPath, origPath, p, stk); perr != p {
|
||||
return setErrorPos(perr, importPos)
|
||||
}
|
||||
}
|
||||
|
|
@ -925,7 +933,7 @@ func reusePackage(p *Package, stk *ImportStack) *Package {
|
|||
// 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, importerPath string, p *Package, stk *ImportStack) *Package {
|
||||
func disallowInternal(srcDir string, importer *Package, importerPath 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
|
||||
|
|
@ -983,10 +991,16 @@ func disallowInternal(srcDir, importerPath string, p *Package, stk *ImportStack)
|
|||
return p
|
||||
}
|
||||
} else {
|
||||
// p is in a module, so make it available based on the import path instead
|
||||
// p is in a module, so make it available based on the importer's import path instead
|
||||
// of the file path (https://golang.org/issue/23970).
|
||||
parent := p.ImportPath[:i]
|
||||
if str.HasPathPrefix(importerPath, parent) {
|
||||
if importerPath == "." {
|
||||
// The importer is a list of command-line files.
|
||||
// Pretend that the import path is the import path of the
|
||||
// directory containing them.
|
||||
importerPath = ModDirImportPath(importer.Dir)
|
||||
}
|
||||
parentOfInternal := p.ImportPath[:i]
|
||||
if str.HasPathPrefix(importerPath, parentOfInternal) {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
|
@ -1024,7 +1038,7 @@ func findInternal(path string) (index int, ok bool) {
|
|||
// 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, importerPath, path string, p *Package, stk *ImportStack) *Package {
|
||||
func disallowVendor(srcDir string, importer *Package, importerPath, 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
|
||||
|
|
@ -1033,26 +1047,18 @@ func disallowVendor(srcDir, importerPath, path string, p *Package, stk *ImportSt
|
|||
return p
|
||||
}
|
||||
|
||||
if p.Standard && ModPackageModuleInfo != nil && importerPath != "" {
|
||||
// Modules must not import vendor packages in the standard library,
|
||||
// but the usual vendor visibility check will not catch them
|
||||
// because the module loader presents them with an ImportPath starting
|
||||
// with "golang_org/" instead of "vendor/".
|
||||
if mod := ModPackageModuleInfo(importerPath); mod != nil {
|
||||
dir := p.Dir
|
||||
if relDir, err := filepath.Rel(p.Root, p.Dir); err == nil {
|
||||
dir = relDir
|
||||
}
|
||||
if _, ok := FindVendor(filepath.ToSlash(dir)); ok {
|
||||
perr := *p
|
||||
perr.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: "use of vendored package " + path + " not allowed",
|
||||
}
|
||||
perr.Incomplete = true
|
||||
return &perr
|
||||
}
|
||||
// Modules must not import vendor packages in the standard library,
|
||||
// but the usual vendor visibility check will not catch them
|
||||
// because the module loader presents them with an ImportPath starting
|
||||
// with "golang_org/" instead of "vendor/".
|
||||
if p.Standard && !importer.Standard && strings.HasPrefix(p.ImportPath, "golang_org") {
|
||||
perr := *p
|
||||
perr.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: "use of vendored package " + path + " not allowed",
|
||||
}
|
||||
perr.Incomplete = true
|
||||
return &perr
|
||||
}
|
||||
|
||||
if perr := disallowVendorVisibility(srcDir, p, stk); perr != p {
|
||||
|
|
@ -1185,27 +1191,6 @@ var foldPath = make(map[string]string)
|
|||
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||
p.copyBuild(bp)
|
||||
|
||||
// Decide whether p was listed on the command line.
|
||||
// Given that load is called while processing the command line,
|
||||
// you might think we could simply pass a flag down into load
|
||||
// saying whether we are loading something named on the command
|
||||
// line or something to satisfy an import. But the first load of a
|
||||
// package named on the command line may be as a dependency
|
||||
// of an earlier package named on the command line, not when we
|
||||
// get to that package during command line processing.
|
||||
// For example "go test fmt reflect" will load reflect as a dependency
|
||||
// of fmt before it attempts to load as a command-line argument.
|
||||
// Because loads are cached, the later load will be a no-op,
|
||||
// so it is important that the first load can fill in CmdlinePkg correctly.
|
||||
// Hence the call to a separate matching check here.
|
||||
p.Internal.CmdlinePkg = isCmdlinePkg(p)
|
||||
p.Internal.CmdlinePkgLiteral = isCmdlinePkgLiteral(p)
|
||||
|
||||
p.Internal.Asmflags = BuildAsmflags.For(p)
|
||||
p.Internal.Gcflags = BuildGcflags.For(p)
|
||||
p.Internal.Ldflags = BuildLdflags.For(p)
|
||||
p.Internal.Gccgoflags = BuildGccgoflags.For(p)
|
||||
|
||||
// The localPrefix is the path we interpret ./ imports relative to.
|
||||
// Synthesized main packages sometimes override this.
|
||||
if p.Internal.Local {
|
||||
|
|
@ -1740,11 +1725,31 @@ func ClearCmdCache() {
|
|||
}
|
||||
}
|
||||
|
||||
// LoadPackage loads the package named by arg.
|
||||
func LoadPackage(arg string, stk *ImportStack) *Package {
|
||||
p := loadPackage(arg, stk)
|
||||
setToolFlags(p)
|
||||
return p
|
||||
}
|
||||
|
||||
// LoadPackageNoFlags is like LoadPackage
|
||||
// but does not guarantee that the build tool flags are set in the result.
|
||||
// It is only for use by GOPATH-based "go get"
|
||||
// and is only appropriate for preliminary loading of packages.
|
||||
// A real load using LoadPackage or (more likely)
|
||||
// Packages, PackageAndErrors, or PackagesForBuild
|
||||
// must be done before passing the package to any build
|
||||
// steps, so that the tool flags can be set properly.
|
||||
// TODO(rsc): When GOPATH-based "go get" is removed, delete this function.
|
||||
func LoadPackageNoFlags(arg string, stk *ImportStack) *Package {
|
||||
return loadPackage(arg, stk)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
|
@ -1829,54 +1834,64 @@ 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 {
|
||||
if len(args) > 0 && strings.HasSuffix(args[0], ".go") {
|
||||
return []*Package{GoFilesPackage(args)}
|
||||
func PackagesAndErrors(patterns []string) []*Package {
|
||||
if len(patterns) > 0 && strings.HasSuffix(patterns[0], ".go") {
|
||||
return []*Package{GoFilesPackage(patterns)}
|
||||
}
|
||||
|
||||
args = ImportPaths(args)
|
||||
matches := ImportPaths(patterns)
|
||||
var (
|
||||
pkgs []*Package
|
||||
stk ImportStack
|
||||
seenArg = make(map[string]bool)
|
||||
seenPkg = make(map[*Package]bool)
|
||||
)
|
||||
|
||||
for _, arg := range args {
|
||||
if seenArg[arg] {
|
||||
continue
|
||||
for _, m := range matches {
|
||||
for _, pkg := range m.Pkgs {
|
||||
p := loadPackage(pkg, &stk)
|
||||
p.Match = append(p.Match, m.Pattern)
|
||||
p.Internal.CmdlinePkg = true
|
||||
if m.Literal {
|
||||
// Note: do not set = m.Literal unconditionally
|
||||
// because maybe we'll see p matching both
|
||||
// a literal and also a non-literal pattern.
|
||||
p.Internal.CmdlinePkgLiteral = true
|
||||
}
|
||||
if seenPkg[p] {
|
||||
continue
|
||||
}
|
||||
seenPkg[p] = true
|
||||
pkgs = append(pkgs, p)
|
||||
}
|
||||
seenArg[arg] = true
|
||||
pkg := LoadPackage(arg, &stk)
|
||||
if seenPkg[pkg] {
|
||||
continue
|
||||
}
|
||||
seenPkg[pkg] = true
|
||||
pkgs = append(pkgs, pkg)
|
||||
}
|
||||
|
||||
// Now that CmdlinePkg is set correctly,
|
||||
// compute the effective flags for all loaded packages
|
||||
// (not just the ones matching the patterns but also
|
||||
// their dependencies).
|
||||
setToolFlags(pkgs...)
|
||||
|
||||
return pkgs
|
||||
}
|
||||
|
||||
func ImportPaths(args []string) []string {
|
||||
if cmdlineMatchers == nil {
|
||||
SetCmdlinePatterns(search.CleanImportPaths(args))
|
||||
func setToolFlags(pkgs ...*Package) {
|
||||
for _, p := range PackageList(pkgs) {
|
||||
p.Internal.Asmflags = BuildAsmflags.For(p)
|
||||
p.Internal.Gcflags = BuildGcflags.For(p)
|
||||
p.Internal.Ldflags = BuildLdflags.For(p)
|
||||
p.Internal.Gccgoflags = BuildGccgoflags.For(p)
|
||||
}
|
||||
}
|
||||
|
||||
func ImportPaths(args []string) []*search.Match {
|
||||
if ModInit(); cfg.ModulesEnabled {
|
||||
return ModImportPaths(args)
|
||||
}
|
||||
return search.ImportPaths(args)
|
||||
}
|
||||
|
||||
func ImportPathsForGoGet(args []string) []string {
|
||||
if cmdlineMatchers == nil {
|
||||
SetCmdlinePatterns(search.CleanImportPaths(args))
|
||||
}
|
||||
return search.ImportPathsNoDotExpansion(args)
|
||||
}
|
||||
|
||||
// packagesForBuild is like 'packages' but fails if any of
|
||||
// the packages or their dependencies have errors
|
||||
// PackagesForBuild is like Packages but exits
|
||||
// if any of the packages or their dependencies have errors
|
||||
// (cannot be built).
|
||||
func PackagesForBuild(args []string) []*Package {
|
||||
pkgs := PackagesAndErrors(args)
|
||||
|
|
@ -1924,7 +1939,6 @@ func PackagesForBuild(args []string) []*Package {
|
|||
func GoFilesPackage(gofiles []string) *Package {
|
||||
ModInit()
|
||||
|
||||
// TODO: Remove this restriction.
|
||||
for _, f := range gofiles {
|
||||
if !strings.HasSuffix(f, ".go") {
|
||||
base.Fatalf("named files must be .go files")
|
||||
|
|
@ -1976,6 +1990,11 @@ func GoFilesPackage(gofiles []string) *Package {
|
|||
}
|
||||
|
||||
bp, err := ctxt.ImportDir(dir, 0)
|
||||
if ModDirImportPath != nil {
|
||||
// Use the effective import path of the directory
|
||||
// for deciding visibility during pkg.load.
|
||||
bp.ImportPath = ModDirImportPath(dir)
|
||||
}
|
||||
pkg := new(Package)
|
||||
pkg.Internal.Local = true
|
||||
pkg.Internal.CmdlineFiles = true
|
||||
|
|
@ -1985,6 +2004,7 @@ func GoFilesPackage(gofiles []string) *Package {
|
|||
pkg.Internal.LocalPrefix = dirToImportPath(dir)
|
||||
pkg.ImportPath = "command-line-arguments"
|
||||
pkg.Target = ""
|
||||
pkg.Match = gofiles
|
||||
|
||||
if pkg.Name == "main" {
|
||||
_, elem := filepath.Split(gofiles[0])
|
||||
|
|
@ -1999,5 +2019,7 @@ func GoFilesPackage(gofiles []string) *Package {
|
|||
}
|
||||
}
|
||||
|
||||
setToolFlags(pkg)
|
||||
|
||||
return pkg
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ package load
|
|||
|
||||
import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"cmd/go/internal/search"
|
||||
|
|
@ -28,13 +27,7 @@ func MatchPackage(pattern, cwd string) func(*Package) bool {
|
|||
}
|
||||
dir = filepath.Join(cwd, dir)
|
||||
if pattern == "" {
|
||||
return func(p *Package) bool {
|
||||
// TODO(rsc): This is wrong. See golang.org/issue/25878.
|
||||
if runtime.GOOS != "windows" {
|
||||
return p.Dir == dir
|
||||
}
|
||||
return strings.EqualFold(p.Dir, dir)
|
||||
}
|
||||
return func(p *Package) bool { return p.Dir == dir }
|
||||
}
|
||||
matchPath := search.MatchPattern(pattern)
|
||||
return func(p *Package) bool {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ corresponding to this Go struct:
|
|||
Dir string // absolute path to cached source root directory
|
||||
}
|
||||
|
||||
See 'go help module' for more about module queries.
|
||||
See 'go help modules' for more about module queries.
|
||||
`,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// go mod fix
|
||||
|
||||
package modcmd
|
||||
|
||||
import (
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/modload"
|
||||
)
|
||||
|
||||
var cmdFix = &base.Command{
|
||||
UsageLine: "go mod fix",
|
||||
Short: "make go.mod semantically consistent",
|
||||
Long: `
|
||||
Fix updates go.mod to use canonical version identifiers and
|
||||
to be semantically consistent. For example, consider this go.mod file:
|
||||
|
||||
module M
|
||||
|
||||
require (
|
||||
A v1
|
||||
B v1.0.0
|
||||
C v1.0.0
|
||||
D v1.2.3
|
||||
E dev
|
||||
)
|
||||
|
||||
exclude D v1.2.3
|
||||
|
||||
First, fix rewrites non-canonical version identifiers to semver form, so
|
||||
A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the latest
|
||||
commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1.
|
||||
|
||||
Next, fix updates requirements to respect exclusions, so the requirement
|
||||
on the excluded D v1.2.3 is updated to use the next available version of D,
|
||||
perhaps D v1.2.4 or D v1.3.0.
|
||||
|
||||
Finally, fix removes redundant or misleading requirements.
|
||||
For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0, then go.mod's
|
||||
requirement of B v1.0.0 is misleading (superseded by A's need for v1.2.0),
|
||||
and its requirement of C v1.0.0 is redundant (implied by A's need for the
|
||||
same version), so both will be removed. If module M contains packages
|
||||
that directly import packages from B or C, then the requirements will be
|
||||
kept but updated to the actual versions being used.
|
||||
|
||||
Although fix runs the fix-up operation in isolation, the fix-up also
|
||||
runs automatically any time a go command uses the module graph,
|
||||
to update go.mod to reflect reality. Because the module graph defines
|
||||
the meaning of import statements, any commands that load packages
|
||||
also use and therefore fix the module graph. For example,
|
||||
go build, go get, go install, go list, go test, go mod graph, go mod tidy,
|
||||
and other commands all effectively imply go mod fix.
|
||||
`,
|
||||
Run: runFix,
|
||||
}
|
||||
|
||||
func runFix(cmd *base.Command, args []string) {
|
||||
if len(args) != 0 {
|
||||
base.Fatalf("go mod fix: fix takes no arguments")
|
||||
}
|
||||
modload.LoadBuildList() // writes go.mod
|
||||
}
|
||||
|
|
@ -21,7 +21,6 @@ See 'go help modules' for an overview of module functionality.
|
|||
Commands: []*base.Command{
|
||||
cmdDownload,
|
||||
cmdEdit,
|
||||
cmdFix,
|
||||
cmdGraph,
|
||||
cmdInit,
|
||||
cmdTidy,
|
||||
|
|
|
|||
|
|
@ -44,10 +44,11 @@ func runTidy(cmd *base.Command, args []string) {
|
|||
|
||||
// LoadALL adds missing modules.
|
||||
// Remove unused modules.
|
||||
used := map[module.Version]bool{modload.Target: true}
|
||||
used := make(map[module.Version]bool)
|
||||
for _, pkg := range modload.LoadALL() {
|
||||
used[modload.PackageModule(pkg)] = true
|
||||
}
|
||||
used[modload.Target] = true // note: LoadALL initializes Target
|
||||
|
||||
inGoMod := make(map[string]bool)
|
||||
for _, r := range modload.ModFile().Require {
|
||||
|
|
|
|||
|
|
@ -100,20 +100,22 @@ func runWhy(cmd *base.Command, args []string) {
|
|||
sep = "\n"
|
||||
}
|
||||
} else {
|
||||
pkgs := modload.ImportPaths(args) // resolve to packages
|
||||
loadALL() // rebuild graph, from main module (not from named packages)
|
||||
matches := modload.ImportPaths(args) // resolve to packages
|
||||
loadALL() // rebuild graph, from main module (not from named packages)
|
||||
sep := ""
|
||||
for _, path := range pkgs {
|
||||
why := modload.Why(path)
|
||||
if why == "" {
|
||||
vendoring := ""
|
||||
if *whyVendor {
|
||||
vendoring = " to vendor"
|
||||
for _, m := range matches {
|
||||
for _, path := range m.Pkgs {
|
||||
why := modload.Why(path)
|
||||
if why == "" {
|
||||
vendoring := ""
|
||||
if *whyVendor {
|
||||
vendoring = " to vendor"
|
||||
}
|
||||
why = "(main module does not need" + vendoring + " package " + path + ")\n"
|
||||
}
|
||||
why = "(main module does not need" + vendoring + " package " + path + ")\n"
|
||||
fmt.Printf("%s# %s\n%s", sep, path, why)
|
||||
sep = "\n"
|
||||
}
|
||||
fmt.Printf("%s# %s\n%s", sep, path, why)
|
||||
sep = "\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,28 +61,36 @@ func TestConvertLegacyConfig(t *testing.T) {
|
|||
vers string
|
||||
gomod string
|
||||
}{
|
||||
{
|
||||
// Gopkg.lock parsing.
|
||||
"github.com/golang/dep", "v0.4.0",
|
||||
`module github.com/golang/dep
|
||||
/*
|
||||
Different versions of git seem to find or not find
|
||||
github.com/Masterminds/semver's a93e51b5a57e,
|
||||
which is an unmerged pull request.
|
||||
We'd rather not provide access to unmerged pull requests,
|
||||
so the line is removed from the golden file here,
|
||||
but some git commands still find it somehow.
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver v0.0.0-20170726230514-a93e51b5a57e
|
||||
github.com/Masterminds/vcs v1.11.1
|
||||
github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/go-yaml/yaml v0.0.0-20170407172122-cd8b52f8269e
|
||||
github.com/golang/protobuf v0.0.0-20170901042739-5afd06f9d81a
|
||||
github.com/jmank88/nuts v0.3.0
|
||||
github.com/nightlyone/lockfile v0.0.0-20170707060451-e83dc5e7bba0
|
||||
github.com/pelletier/go-toml v0.0.0-20171218135716-b8b5e7696574
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/sdboyer/constext v0.0.0-20170321163424-836a14457353
|
||||
golang.org/x/net v0.0.0-20170828231752-66aacef3dd8a
|
||||
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea
|
||||
)`,
|
||||
},
|
||||
{
|
||||
// Gopkg.lock parsing.
|
||||
"github.com/golang/dep", "v0.4.0",
|
||||
`module github.com/golang/dep
|
||||
|
||||
require (
|
||||
github.com/Masterminds/vcs v1.11.1
|
||||
github.com/armon/go-radix v0.0.0-20160115234725-4239b77079c7
|
||||
github.com/boltdb/bolt v1.3.1
|
||||
github.com/go-yaml/yaml v0.0.0-20170407172122-cd8b52f8269e
|
||||
github.com/golang/protobuf v0.0.0-20170901042739-5afd06f9d81a
|
||||
github.com/jmank88/nuts v0.3.0
|
||||
github.com/nightlyone/lockfile v0.0.0-20170707060451-e83dc5e7bba0
|
||||
github.com/pelletier/go-toml v0.0.0-20171218135716-b8b5e7696574
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/sdboyer/constext v0.0.0-20170321163424-836a14457353
|
||||
golang.org/x/net v0.0.0-20170828231752-66aacef3dd8a
|
||||
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea
|
||||
)`,
|
||||
},
|
||||
*/
|
||||
|
||||
// TODO: https://github.com/docker/distribution uses vendor.conf
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,17 @@ import (
|
|||
"cmd/go/internal/str"
|
||||
)
|
||||
|
||||
// A VCSError indicates an error using a version control system.
|
||||
// The implication of a VCSError is that we know definitively where
|
||||
// to get the code, but we can't access it due to the error.
|
||||
// The caller should report this error instead of continuing to probe
|
||||
// other possible module paths.
|
||||
type VCSError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *VCSError) Error() string { return e.Err.Error() }
|
||||
|
||||
func NewRepo(vcs, remote string) (Repo, error) {
|
||||
type key struct {
|
||||
vcs string
|
||||
|
|
@ -33,6 +44,9 @@ func NewRepo(vcs, remote string) (Repo, error) {
|
|||
}
|
||||
c := vcsRepoCache.Do(key{vcs, remote}, func() interface{} {
|
||||
repo, err := newVCSRepo(vcs, remote)
|
||||
if err != nil {
|
||||
err = &VCSError{err}
|
||||
}
|
||||
return cached{repo, err}
|
||||
}).(cached)
|
||||
|
||||
|
|
|
|||
|
|
@ -228,10 +228,9 @@ var codeRepoTests = []struct {
|
|||
path: "swtch.com/testmod",
|
||||
rev: "v1.0.0",
|
||||
version: "v1.0.0",
|
||||
name: "v1.0.0",
|
||||
short: "v1.0.0",
|
||||
time: time.Date(1972, 7, 18, 12, 34, 56, 0, time.UTC),
|
||||
gomod: "module \"swtch.com/testmod\"\n",
|
||||
// NO name or short - we intentionally ignore those in the proxy protocol
|
||||
time: time.Date(1972, 7, 18, 12, 34, 56, 0, time.UTC),
|
||||
gomod: "module \"swtch.com/testmod\"\n",
|
||||
},
|
||||
{
|
||||
// redirect to googlesource
|
||||
|
|
|
|||
|
|
@ -216,7 +216,11 @@ func lookup(path string) (r Repo, err error) {
|
|||
return lookupProxy(path)
|
||||
}
|
||||
|
||||
rr, err := get.RepoRootForImportPath(path, get.PreferMod, web.Secure)
|
||||
security := web.Secure
|
||||
if get.Insecure {
|
||||
security = web.Insecure
|
||||
}
|
||||
rr, err := get.RepoRootForImportPath(path, get.PreferMod, security)
|
||||
if err != nil {
|
||||
// We don't know where to find code for a module with this path.
|
||||
return nil, err
|
||||
|
|
@ -237,6 +241,9 @@ func lookup(path string) (r Repo, err error) {
|
|||
func lookupCodeRepo(rr *get.RepoRoot) (codehost.Repo, error) {
|
||||
code, err := codehost.NewRepo(rr.VCS, rr.Repo)
|
||||
if err != nil {
|
||||
if _, ok := err.(*codehost.VCSError); ok {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("lookup %s: %v", rr.Root, err)
|
||||
}
|
||||
return code, nil
|
||||
|
|
@ -254,7 +261,11 @@ func ImportRepoRev(path, rev string) (Repo, *RevInfo, error) {
|
|||
// Note: Because we are converting a code reference from a legacy
|
||||
// version control system, we ignore meta tags about modules
|
||||
// and use only direct source control entries (get.IgnoreMod).
|
||||
rr, err := get.RepoRootForImportPath(path, get.IgnoreMod, web.Secure)
|
||||
security := web.Secure
|
||||
if get.Insecure {
|
||||
security = web.Insecure
|
||||
}
|
||||
rr, err := get.RepoRootForImportPath(path, get.IgnoreMod, security)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
|
|||
arrow = 1
|
||||
}
|
||||
if len(args) < arrow+2 || len(args) > arrow+3 || args[arrow] != "=>" {
|
||||
fmt.Fprintf(errs, "%s:%d: usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory", f.Syntax.Name, line.Start.Line, verb, verb)
|
||||
fmt.Fprintf(errs, "%s:%d: usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory\n", f.Syntax.Name, line.Start.Line, verb, verb)
|
||||
return
|
||||
}
|
||||
s, err := parseString(&args[0])
|
||||
|
|
@ -287,11 +287,11 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
|
|||
nv := ""
|
||||
if len(args) == arrow+2 {
|
||||
if !IsDirectoryPath(ns) {
|
||||
fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)", f.Syntax.Name, line.Start.Line)
|
||||
fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)\n", f.Syntax.Name, line.Start.Line)
|
||||
return
|
||||
}
|
||||
if filepath.Separator == '/' && strings.Contains(ns, `\`) {
|
||||
fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)", f.Syntax.Name, line.Start.Line)
|
||||
fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)\n", f.Syntax.Name, line.Start.Line)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -303,7 +303,7 @@ func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, f
|
|||
return
|
||||
}
|
||||
if IsDirectoryPath(ns) {
|
||||
fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version", f.Syntax.Name, line.Start.Line, ns)
|
||||
fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version\n", f.Syntax.Name, line.Start.Line, ns)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ func runGet(cmd *base.Command, args []string) {
|
|||
// and a list of install targets (for the "go install" at the end).
|
||||
var tasks []*task
|
||||
var install []string
|
||||
for _, arg := range search.CleanImportPaths(args) {
|
||||
for _, arg := range search.CleanPatterns(args) {
|
||||
// Argument is module query path@vers, or else path with implicit @latest.
|
||||
path := arg
|
||||
vers := ""
|
||||
|
|
@ -519,8 +519,9 @@ func runGet(cmd *base.Command, args []string) {
|
|||
// Note that 'go get -u' without any arguments results in len(install) == 1:
|
||||
// search.CleanImportPaths returns "." for empty args.
|
||||
work.BuildInit()
|
||||
var pkgs []string
|
||||
for _, p := range load.PackagesAndErrors(install) {
|
||||
pkgs := load.PackagesAndErrors(install)
|
||||
var todo []*load.Package
|
||||
for _, p := range pkgs {
|
||||
// Ignore "no Go source files" errors for 'go get' operations on modules.
|
||||
if p.Error != nil {
|
||||
if len(args) == 0 && getU != "" && strings.HasPrefix(p.Error.Err, "no Go files") {
|
||||
|
|
@ -534,14 +535,14 @@ func runGet(cmd *base.Command, args []string) {
|
|||
continue
|
||||
}
|
||||
}
|
||||
pkgs = append(pkgs, p.ImportPath)
|
||||
todo = append(todo, p)
|
||||
}
|
||||
|
||||
// If -d was specified, we're done after the download: no build.
|
||||
// (The load.PackagesAndErrors is what did the download
|
||||
// of the named packages and their dependencies.)
|
||||
if len(pkgs) > 0 && !*getD {
|
||||
work.InstallPackages(pkgs)
|
||||
if len(todo) > 0 && !*getD {
|
||||
work.InstallPackages(install, todo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ package modload
|
|||
|
||||
import "cmd/go/internal/base"
|
||||
|
||||
// TODO(rsc): The links out to research.swtch.com here should all be
|
||||
// replaced eventually with links to proper documentation.
|
||||
// TODO(rsc): The "module code layout" section needs to be written.
|
||||
|
||||
var HelpModules = &base.Command{
|
||||
UsageLine: "modules",
|
||||
|
|
@ -81,7 +80,7 @@ depends on specific versions of golang.org/x/text and gopkg.in/yaml.v2:
|
|||
The go.mod file can also specify replacements and excluded versions
|
||||
that only apply when building the module directly; they are ignored
|
||||
when the module is incorporated into a larger build.
|
||||
For more about the go.mod file, see https://research.swtch.com/vgo-module.
|
||||
For more about the go.mod file, see 'go help go.mod'.
|
||||
|
||||
To start a new module, simply create a go.mod file in the root of the
|
||||
module's directory tree, containing only a module statement.
|
||||
|
|
@ -336,8 +335,6 @@ For now, see https://research.swtch.com/vgo-module for information
|
|||
about how source code in version control systems is mapped to
|
||||
module file trees.
|
||||
|
||||
TODO: Add documentation to go command.
|
||||
|
||||
Module downloading and verification
|
||||
|
||||
The go command maintains, in the main module's root directory alongside
|
||||
|
|
@ -381,3 +378,73 @@ top-level vendor directory is used; vendor directories in other locations
|
|||
are still ignored.
|
||||
`,
|
||||
}
|
||||
|
||||
var HelpGoMod = &base.Command{
|
||||
UsageLine: "go.mod",
|
||||
Short: "the go.mod file",
|
||||
Long: `
|
||||
A module version is defined by a tree of source files, with a go.mod
|
||||
file in its root. When the go command is run, it looks in the current
|
||||
directory and then successive parent directories to find the go.mod
|
||||
marking the root of the main (current) module.
|
||||
|
||||
The go.mod file itself is line-oriented, with // comments but
|
||||
no /* */ comments. Each line holds a single directive, made up of a
|
||||
verb followed by arguments. For example:
|
||||
|
||||
module my/thing
|
||||
require other/thing v1.0.2
|
||||
require new/thing v2.3.4
|
||||
exclude old/thing v1.2.3
|
||||
replace bad/thing v1.4.5 => good/thing v1.4.5
|
||||
|
||||
The verbs are module, to define the module path; require, to require
|
||||
a particular module at a given version or later; exclude, to exclude
|
||||
a particular module version from use; and replace, to replace a module
|
||||
version with a different module version. Exclude and replace apply only
|
||||
in the main module's go.mod and are ignored in dependencies.
|
||||
See https://research.swtch.com/vgo-mvs for details.
|
||||
|
||||
The leading verb can be factored out of adjacent lines to create a block,
|
||||
like in Go imports:
|
||||
|
||||
require (
|
||||
new/thing v2.3.4
|
||||
old/thing v1.2.3
|
||||
)
|
||||
|
||||
The go.mod file is designed both to be edited directly and to be
|
||||
easily updated by tools. The 'go mod edit' command can be used to
|
||||
parse and edit the go.mod file from programs and tools.
|
||||
See 'go help mod edit'.
|
||||
|
||||
The go command automatically updates go.mod each time it uses the
|
||||
module graph, to make sure go.mod always accurately reflects reality
|
||||
and is properly formatted.
|
||||
|
||||
The update rewrites non-canonical version identifiers to semver form,
|
||||
so A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the
|
||||
latest commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1.
|
||||
|
||||
The update modifies requirements to respect exclusions, so the
|
||||
requirement on the excluded D v1.2.3 is updated to use the next
|
||||
available version of D, perhaps D v1.2.4 or D v1.3.0.
|
||||
|
||||
The update removes redundant or misleading requirements.
|
||||
For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0,
|
||||
then go.mod's requirement of B v1.0.0 is misleading (superseded by
|
||||
A's need for v1.2.0), and its requirement of C v1.0.0 is redundant
|
||||
(implied by A's need for the same version), so both will be removed.
|
||||
If module M contains packages that directly import packages from B or
|
||||
C, then the requirements will be kept but updated to the actual
|
||||
versions being used.
|
||||
|
||||
Finally, the update reformats the go.mod in a canonical formatting, so
|
||||
that future mechanical changes will result in minimal diffs.
|
||||
|
||||
Because the module graph defines the meaning of import statements, any
|
||||
commands that load packages also use and therefore update go.mod,
|
||||
including go build, go get, go install, go list, go test, go mod graph,
|
||||
go mod tidy, and go mod why.
|
||||
`,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/modfetch/codehost"
|
||||
"cmd/go/internal/module"
|
||||
"cmd/go/internal/par"
|
||||
"cmd/go/internal/search"
|
||||
|
|
@ -133,6 +134,9 @@ func Import(path string) (m module.Version, dir string, err error) {
|
|||
|
||||
m, _, err = QueryPackage(path, "latest", Allowed)
|
||||
if err != nil {
|
||||
if _, ok := err.(*codehost.VCSError); ok {
|
||||
return module.Version{}, "", err
|
||||
}
|
||||
return module.Version{}, "", &ImportMissingError{ImportPath: path}
|
||||
}
|
||||
return m, "", &ImportMissingError{ImportPath: path, Module: m}
|
||||
|
|
|
|||
|
|
@ -150,8 +150,20 @@ func Init() {
|
|||
ModRoot = cwd
|
||||
} else {
|
||||
ModRoot, _ = FindModuleRoot(cwd, "", MustUseModules)
|
||||
if ModRoot == "" && !MustUseModules {
|
||||
return
|
||||
if !MustUseModules {
|
||||
if ModRoot == "" {
|
||||
return
|
||||
}
|
||||
if search.InDir(ModRoot, os.TempDir()) == "." {
|
||||
// If you create /tmp/go.mod for experimenting,
|
||||
// then any tests that create work directories under /tmp
|
||||
// will find it and get modules when they're not expecting them.
|
||||
// It's a bit of a peculiar thing to disallow but quite mysterious
|
||||
// when it happens. See golang.org/issue/26708.
|
||||
ModRoot = ""
|
||||
fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir())
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,6 +175,7 @@ func Init() {
|
|||
load.ModPackageBuildInfo = PackageBuildInfo
|
||||
load.ModInfoProg = ModInfoProg
|
||||
load.ModImportFromFiles = ImportFromFiles
|
||||
load.ModDirImportPath = DirImportPath
|
||||
|
||||
search.SetModRoot(ModRoot)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"cmd/go/internal/par"
|
||||
"cmd/go/internal/search"
|
||||
"cmd/go/internal/semver"
|
||||
"cmd/go/internal/str"
|
||||
)
|
||||
|
||||
// buildList is the list of modules to use for building packages.
|
||||
|
|
@ -50,24 +51,46 @@ var loaded *loader
|
|||
|
||||
// ImportPaths returns the set of packages matching the args (patterns),
|
||||
// adding modules to the build list as needed to satisfy new imports.
|
||||
func ImportPaths(args []string) []string {
|
||||
func ImportPaths(patterns []string) []*search.Match {
|
||||
InitMod()
|
||||
|
||||
cleaned := search.CleanImportPaths(args)
|
||||
var matches []*search.Match
|
||||
for _, pattern := range search.CleanPatterns(patterns) {
|
||||
m := &search.Match{
|
||||
Pattern: pattern,
|
||||
Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern),
|
||||
}
|
||||
if m.Literal {
|
||||
m.Pkgs = []string{pattern}
|
||||
}
|
||||
matches = append(matches, m)
|
||||
}
|
||||
|
||||
fsDirs := make([][]string, len(matches))
|
||||
loaded = newLoader()
|
||||
var paths []string
|
||||
loaded.load(func() []string {
|
||||
var roots []string
|
||||
paths = nil
|
||||
for _, pkg := range cleaned {
|
||||
updateMatches := func(iterating bool) {
|
||||
for i, m := range matches {
|
||||
switch {
|
||||
case build.IsLocalImport(pkg) || filepath.IsAbs(pkg):
|
||||
list := []string{pkg}
|
||||
if strings.Contains(pkg, "...") {
|
||||
// TODO: Where is the go.mod cutoff?
|
||||
list = warnPattern(pkg, search.AllPackagesInFS(pkg))
|
||||
case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern):
|
||||
// Evaluate list of file system directories on first iteration.
|
||||
if fsDirs[i] == nil {
|
||||
var dirs []string
|
||||
if m.Literal {
|
||||
dirs = []string{m.Pattern}
|
||||
} else {
|
||||
dirs = search.MatchPackagesInFS(m.Pattern).Pkgs
|
||||
}
|
||||
fsDirs[i] = dirs
|
||||
}
|
||||
for _, pkg := range list {
|
||||
|
||||
// Make a copy of the directory list and translate to import paths.
|
||||
// Note that whether a directory corresponds to an import path
|
||||
// changes as the build list is updated, and a directory can change
|
||||
// from not being in the build list to being in it and back as
|
||||
// the exact version of a particular module increases during
|
||||
// the loader iterations.
|
||||
m.Pkgs = str.StringList(fsDirs[i])
|
||||
for i, pkg := range m.Pkgs {
|
||||
dir := pkg
|
||||
if !filepath.IsAbs(dir) {
|
||||
dir = filepath.Join(cwd, pkg)
|
||||
|
|
@ -93,38 +116,67 @@ func ImportPaths(args []string) []string {
|
|||
} else if path := pathInModuleCache(dir); path != "" {
|
||||
pkg = path
|
||||
} else {
|
||||
base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
|
||||
continue
|
||||
pkg = ""
|
||||
if !iterating {
|
||||
base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
|
||||
}
|
||||
}
|
||||
roots = append(roots, pkg)
|
||||
paths = append(paths, pkg)
|
||||
info, err := os.Stat(dir)
|
||||
if err != nil || !info.IsDir() {
|
||||
// If the directory does not exist,
|
||||
// don't turn it into an import path
|
||||
// that will trigger a lookup.
|
||||
pkg = ""
|
||||
if !iterating {
|
||||
if err != nil {
|
||||
base.Errorf("go: no such directory %v", m.Pattern)
|
||||
} else {
|
||||
base.Errorf("go: %s is not a directory", m.Pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
m.Pkgs[i] = pkg
|
||||
}
|
||||
|
||||
case pkg == "all":
|
||||
case strings.Contains(m.Pattern, "..."):
|
||||
m.Pkgs = matchPackages(m.Pattern, loaded.tags, true, buildList)
|
||||
|
||||
case m.Pattern == "all":
|
||||
loaded.testAll = true
|
||||
// TODO: Don't print warnings multiple times.
|
||||
roots = append(roots, warnPattern("all", matchPackages("...", loaded.tags, false, []module.Version{Target}))...)
|
||||
paths = append(paths, "all") // will expand after load completes
|
||||
if iterating {
|
||||
// Enumerate the packages in the main module.
|
||||
// We'll load the dependencies as we find them.
|
||||
m.Pkgs = matchPackages("...", loaded.tags, false, []module.Version{Target})
|
||||
} else {
|
||||
// Starting with the packages in the main module,
|
||||
// enumerate the full list of "all".
|
||||
m.Pkgs = loaded.computePatternAll(m.Pkgs)
|
||||
}
|
||||
|
||||
case search.IsMetaPackage(pkg): // std, cmd
|
||||
list := search.AllPackages(pkg)
|
||||
roots = append(roots, list...)
|
||||
paths = append(paths, list...)
|
||||
case search.IsMetaPackage(m.Pattern): // std, cmd
|
||||
if len(m.Pkgs) == 0 {
|
||||
m.Pkgs = search.MatchPackages(m.Pattern).Pkgs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case strings.Contains(pkg, "..."):
|
||||
// TODO: Don't we need to reevaluate this one last time once the build list stops changing?
|
||||
list := warnPattern(pkg, matchPackages(pkg, loaded.tags, true, buildList))
|
||||
roots = append(roots, list...)
|
||||
paths = append(paths, list...)
|
||||
|
||||
default:
|
||||
roots = append(roots, pkg)
|
||||
paths = append(paths, pkg)
|
||||
loaded.load(func() []string {
|
||||
var roots []string
|
||||
updateMatches(true)
|
||||
for _, m := range matches {
|
||||
for _, pkg := range m.Pkgs {
|
||||
if pkg != "" {
|
||||
roots = append(roots, pkg)
|
||||
}
|
||||
}
|
||||
}
|
||||
return roots
|
||||
})
|
||||
|
||||
// One last pass to finalize wildcards.
|
||||
updateMatches(false)
|
||||
|
||||
// A given module path may be used as itself or as a replacement for another
|
||||
// module, but not both at the same time. Otherwise, the aliasing behavior is
|
||||
// too subtle (see https://golang.org/issue/26607), and we don't want to
|
||||
|
|
@ -142,33 +194,10 @@ func ImportPaths(args []string) []string {
|
|||
}
|
||||
}
|
||||
base.ExitIfErrors()
|
||||
|
||||
WriteGoMod()
|
||||
|
||||
// Process paths to produce final paths list.
|
||||
// Remove duplicates and expand "all".
|
||||
have := make(map[string]bool)
|
||||
var final []string
|
||||
for _, path := range paths {
|
||||
if have[path] {
|
||||
continue
|
||||
}
|
||||
have[path] = true
|
||||
if path == "all" {
|
||||
for _, pkg := range loaded.pkgs {
|
||||
if e, ok := pkg.err.(*ImportMissingError); ok && e.Module.Path == "" {
|
||||
continue // Package doesn't actually exist, so don't report it.
|
||||
}
|
||||
if !have[pkg.path] {
|
||||
have[pkg.path] = true
|
||||
final = append(final, pkg.path)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
final = append(final, path)
|
||||
}
|
||||
return final
|
||||
search.WarnUnmatched(matches)
|
||||
return matches
|
||||
}
|
||||
|
||||
// pathInModuleCache returns the import path of the directory dir,
|
||||
|
|
@ -219,6 +248,28 @@ func ImportFromFiles(gofiles []string) {
|
|||
WriteGoMod()
|
||||
}
|
||||
|
||||
// DirImportPath returns the effective import path for dir,
|
||||
// provided it is within the main module, or else returns ".".
|
||||
func DirImportPath(dir string) string {
|
||||
if !filepath.IsAbs(dir) {
|
||||
dir = filepath.Join(cwd, dir)
|
||||
} else {
|
||||
dir = filepath.Clean(dir)
|
||||
}
|
||||
|
||||
if dir == ModRoot {
|
||||
return Target.Path
|
||||
}
|
||||
if strings.HasPrefix(dir, ModRoot+string(filepath.Separator)) {
|
||||
suffix := filepath.ToSlash(dir[len(ModRoot):])
|
||||
if strings.HasPrefix(suffix, "/vendor/") {
|
||||
return strings.TrimPrefix(suffix, "/vendor/")
|
||||
}
|
||||
return Target.Path + suffix
|
||||
}
|
||||
return "."
|
||||
}
|
||||
|
||||
// LoadBuildList loads and returns the build list from go.mod.
|
||||
// The loading of the build list happens automatically in ImportPaths:
|
||||
// LoadBuildList need only be called if ImportPaths is not
|
||||
|
|
@ -581,6 +632,35 @@ func (ld *loader) doPkg(item interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// computePatternAll returns the list of packages matching pattern "all",
|
||||
// starting with a list of the import paths for the packages in the main module.
|
||||
func (ld *loader) computePatternAll(paths []string) []string {
|
||||
seen := make(map[*loadPkg]bool)
|
||||
var all []string
|
||||
var walk func(*loadPkg)
|
||||
walk = func(pkg *loadPkg) {
|
||||
if seen[pkg] {
|
||||
return
|
||||
}
|
||||
seen[pkg] = true
|
||||
if pkg.testOf == nil {
|
||||
all = append(all, pkg.path)
|
||||
}
|
||||
for _, p := range pkg.imports {
|
||||
walk(p)
|
||||
}
|
||||
if p := pkg.test; p != nil {
|
||||
walk(p)
|
||||
}
|
||||
}
|
||||
for _, path := range paths {
|
||||
walk(ld.pkg(path, false))
|
||||
}
|
||||
sort.Strings(all)
|
||||
|
||||
return all
|
||||
}
|
||||
|
||||
// scanDir is like imports.ScanDir but elides known magic imports from the list,
|
||||
// so that we do not go looking for packages that don't really exist.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package modload
|
|||
|
||||
import (
|
||||
"cmd/go/internal/modfetch"
|
||||
"cmd/go/internal/modfetch/codehost"
|
||||
"cmd/go/internal/module"
|
||||
"cmd/go/internal/semver"
|
||||
"fmt"
|
||||
|
|
@ -223,6 +224,11 @@ func QueryPackage(path, query string, allowed func(module.Version) bool) (module
|
|||
for p := path; p != "."; p = pathpkg.Dir(p) {
|
||||
info, err := Query(p, query, allowed)
|
||||
if err != nil {
|
||||
if _, ok := err.(*codehost.VCSError); ok {
|
||||
// A VCSError means we know where to find the code,
|
||||
// we just can't. Abort search.
|
||||
return module.Version{}, nil, err
|
||||
}
|
||||
if finalErr == errMissing {
|
||||
finalErr = err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,32 +17,22 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// AllPackages returns all the packages that can be found
|
||||
// A Match represents the result of matching a single package pattern.
|
||||
type Match struct {
|
||||
Pattern string // the pattern itself
|
||||
Literal bool // whether it is a literal (no wildcards)
|
||||
Pkgs []string // matching packages (dirs or import paths)
|
||||
}
|
||||
|
||||
// MatchPackages returns all the packages that can be found
|
||||
// under the $GOPATH directories and $GOROOT matching pattern.
|
||||
// The pattern is either "all" (all packages), "std" (standard packages),
|
||||
// "cmd" (standard commands), or a path including "...".
|
||||
func AllPackages(pattern string) []string {
|
||||
pkgs := MatchPackages(pattern)
|
||||
if len(pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
|
||||
func MatchPackages(pattern string) *Match {
|
||||
m := &Match{
|
||||
Pattern: pattern,
|
||||
Literal: false,
|
||||
}
|
||||
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) {
|
||||
|
|
@ -56,7 +46,6 @@ func MatchPackages(pattern string) []string {
|
|||
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 {
|
||||
|
|
@ -123,11 +112,11 @@ func MatchPackages(pattern string) []string {
|
|||
return nil
|
||||
}
|
||||
|
||||
pkgs = append(pkgs, name)
|
||||
m.Pkgs = append(m.Pkgs, name)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return pkgs
|
||||
return m
|
||||
}
|
||||
|
||||
var modRoot string
|
||||
|
|
@ -136,10 +125,16 @@ func SetModRoot(dir string) {
|
|||
modRoot = dir
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// MatchPackagesInFS 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.
|
||||
// (See go help packages for pattern syntax.)
|
||||
func MatchPackagesInFS(pattern string) *Match {
|
||||
m := &Match{
|
||||
Pattern: pattern,
|
||||
Literal: false,
|
||||
}
|
||||
|
||||
// Find directory to begin the scan.
|
||||
// Could be smarter but this one optimization
|
||||
// is enough for now, since ... is usually at the
|
||||
|
|
@ -168,7 +163,6 @@ func MatchPackagesInFS(pattern string) []string {
|
|||
}
|
||||
}
|
||||
|
||||
var pkgs []string
|
||||
filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil || !fi.IsDir() {
|
||||
return nil
|
||||
|
|
@ -218,10 +212,10 @@ func MatchPackagesInFS(pattern string) []string {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
pkgs = append(pkgs, name)
|
||||
m.Pkgs = append(m.Pkgs, name)
|
||||
return nil
|
||||
})
|
||||
return pkgs
|
||||
return m
|
||||
}
|
||||
|
||||
// TreeCanMatchPattern(pattern)(name) reports whether
|
||||
|
|
@ -308,36 +302,53 @@ func replaceVendor(x, repl string) string {
|
|||
return strings.Join(elem, "/")
|
||||
}
|
||||
|
||||
// ImportPaths returns the import paths to use for the given command line.
|
||||
func ImportPaths(args []string) []string {
|
||||
args = CleanImportPaths(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
// WarnUnmatched warns about patterns that didn't match any packages.
|
||||
func WarnUnmatched(matches []*Match) {
|
||||
for _, m := range matches {
|
||||
if len(m.Pkgs) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "go: warning: %q matched no packages\n", m.Pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ImportPaths returns the matching paths to use for the given command line.
|
||||
// It calls ImportPathsQuiet and then WarnUnmatched.
|
||||
func ImportPaths(patterns []string) []*Match {
|
||||
matches := ImportPathsQuiet(patterns)
|
||||
WarnUnmatched(matches)
|
||||
return matches
|
||||
}
|
||||
|
||||
// ImportPathsQuiet is like ImportPaths but does not warn about patterns with no matches.
|
||||
func ImportPathsQuiet(patterns []string) []*Match {
|
||||
var out []*Match
|
||||
for _, a := range CleanPatterns(patterns) {
|
||||
if IsMetaPackage(a) {
|
||||
out = append(out, AllPackages(a)...)
|
||||
out = append(out, MatchPackages(a))
|
||||
continue
|
||||
}
|
||||
if strings.Contains(a, "...") {
|
||||
if build.IsLocalImport(a) {
|
||||
out = append(out, AllPackagesInFS(a)...)
|
||||
out = append(out, MatchPackagesInFS(a))
|
||||
} else {
|
||||
out = append(out, AllPackages(a)...)
|
||||
out = append(out, MatchPackages(a))
|
||||
}
|
||||
continue
|
||||
}
|
||||
out = append(out, a)
|
||||
out = append(out, &Match{Pattern: a, Literal: true, Pkgs: []string{a}})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// CleanImportPaths returns the import paths to use for the given
|
||||
// command line, but it does no wildcard expansion.
|
||||
func CleanImportPaths(args []string) []string {
|
||||
if len(args) == 0 {
|
||||
// CleanPatterns returns the patterns to use for the given
|
||||
// command line. It canonicalizes the patterns but does not
|
||||
// evaluate any matches.
|
||||
func CleanPatterns(patterns []string) []string {
|
||||
if len(patterns) == 0 {
|
||||
return []string{"."}
|
||||
}
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
for _, a := range patterns {
|
||||
// Arguments are supposed to be import paths, but
|
||||
// as a courtesy to Windows developers, rewrite \ to /
|
||||
// in command-line arguments. Handles .\... and so on.
|
||||
|
|
@ -359,22 +370,6 @@ func CleanImportPaths(args []string) []string {
|
|||
return out
|
||||
}
|
||||
|
||||
// ImportPathsNoDotExpansion returns the import paths to use for the given
|
||||
// command line, but it does no ... expansion.
|
||||
// TODO(rsc): Delete once old go get is gone.
|
||||
func ImportPathsNoDotExpansion(args []string) []string {
|
||||
args = CleanImportPaths(args)
|
||||
var out []string
|
||||
for _, a := range args {
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -414,7 +414,7 @@ func libname(args []string, pkgs []*load.Package) (string, error) {
|
|||
|
||||
func runInstall(cmd *base.Command, args []string) {
|
||||
BuildInit()
|
||||
InstallPackages(args)
|
||||
InstallPackages(args, load.PackagesForBuild(args))
|
||||
}
|
||||
|
||||
// omitTestOnly returns pkgs with test-only packages removed.
|
||||
|
|
@ -434,12 +434,12 @@ func omitTestOnly(pkgs []*load.Package) []*load.Package {
|
|||
return list
|
||||
}
|
||||
|
||||
func InstallPackages(args []string) {
|
||||
func InstallPackages(patterns []string, pkgs []*load.Package) {
|
||||
if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) {
|
||||
base.Fatalf("cannot install, GOBIN must be an absolute path")
|
||||
}
|
||||
|
||||
pkgs := omitTestOnly(pkgsFilter(load.PackagesForBuild(args)))
|
||||
pkgs = omitTestOnly(pkgsFilter(pkgs))
|
||||
for _, p := range pkgs {
|
||||
if p.Target == "" {
|
||||
switch {
|
||||
|
|
@ -500,7 +500,7 @@ func InstallPackages(args []string) {
|
|||
// tools above did not apply, and a is just a simple Action
|
||||
// with a list of Deps, one per package named in pkgs,
|
||||
// the same as in runBuild.
|
||||
a = b.buildmodeShared(ModeInstall, ModeInstall, args, pkgs, a)
|
||||
a = b.buildmodeShared(ModeInstall, ModeInstall, patterns, pkgs, a)
|
||||
}
|
||||
|
||||
b.Do(a)
|
||||
|
|
@ -515,7 +515,7 @@ func InstallPackages(args []string) {
|
|||
// One way to view this behavior is that it is as if 'go install' first
|
||||
// runs 'go build' and the moves the generated file to the install dir.
|
||||
// See issue 9645.
|
||||
if len(args) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
|
||||
if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
|
||||
// Compute file 'go build' would have created.
|
||||
// If it exists and is an executable file, remove it.
|
||||
_, targ := filepath.Split(pkgs[0].ImportPath)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ func init() {
|
|||
help.HelpCache,
|
||||
help.HelpEnvironment,
|
||||
help.HelpFileType,
|
||||
modload.HelpGoMod,
|
||||
help.HelpGopath,
|
||||
get.HelpGopathGet,
|
||||
modfetch.HelpGoproxy,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
[!gc] skip 'using -gcflags and -ldflags'
|
||||
|
||||
# -gcflags=-e applies to named packages, not dependencies
|
||||
go build -n -v -gcflags=-e z1 z2
|
||||
stderr 'compile.* -e .*-p z1'
|
||||
stderr 'compile.* -e .*-p z2'
|
||||
stderr 'compile.* -p y'
|
||||
! stderr 'compile.* -e .*-p [^z]'
|
||||
|
||||
# -gcflags can specify package=flags, and can be repeated; last match wins
|
||||
go build -n -v -gcflags=-e -gcflags=z1=-N z1 z2
|
||||
stderr 'compile.* -N .*-p z1'
|
||||
! stderr 'compile.* -e .*-p z1'
|
||||
! stderr 'compile.* -N .*-p z2'
|
||||
stderr 'compile.* -e .*-p z2'
|
||||
stderr 'compile.* -p y'
|
||||
! stderr 'compile.* -e .*-p [^z]'
|
||||
! stderr 'compile.* -N .*-p [^z]'
|
||||
|
||||
# -gcflags can have arbitrary spaces around the flags
|
||||
go build -n -v -gcflags=' z1 = -e ' z1
|
||||
stderr 'compile.* -e .*-p z1'
|
||||
|
||||
# -ldflags for implicit test package applies to test binary
|
||||
go test -c -n -gcflags=-N -ldflags=-X=x.y=z z1
|
||||
stderr 'compile.* -N .*z_test.go'
|
||||
stderr 'link.* -X=x.y=z'
|
||||
|
||||
# -ldflags for explicit test package applies to test binary
|
||||
go test -c -n -gcflags=z1=-N -ldflags=z1=-X=x.y=z z1
|
||||
stderr 'compile.* -N .*z_test.go'
|
||||
stderr 'link.* -X=x.y=z'
|
||||
|
||||
# -ldflags applies to link of command
|
||||
go build -n -ldflags=-X=math.pi=3 my/cmd/prog
|
||||
stderr 'link.* -X=math.pi=3'
|
||||
|
||||
# -ldflags applies to link of command even with strange directory name
|
||||
go build -n -ldflags=-X=math.pi=3 my/cmd/prog/
|
||||
stderr 'link.* -X=math.pi=3'
|
||||
|
||||
# -ldflags applies to current directory
|
||||
cd my/cmd/prog
|
||||
go build -n -ldflags=-X=math.pi=3
|
||||
stderr 'link.* -X=math.pi=3'
|
||||
|
||||
# -ldflags applies to current directory even if GOPATH is funny
|
||||
[windows] cd $WORK/GoPath/src/my/cmd/prog
|
||||
[darwin] cd $WORK/GoPath/src/my/cmd/prog
|
||||
go build -n -ldflags=-X=math.pi=3
|
||||
stderr 'link.* -X=math.pi=3'
|
||||
|
||||
-- z1/z.go --
|
||||
package z1
|
||||
import _ "y"
|
||||
import _ "z2"
|
||||
|
||||
-- z1/z_test.go --
|
||||
package z1_test
|
||||
import "testing"
|
||||
func Test(t *testing.T) {}
|
||||
|
||||
-- z2/z.go --
|
||||
package z2
|
||||
|
||||
-- y/y.go --
|
||||
package y
|
||||
|
||||
-- my/cmd/prog/prog.go --
|
||||
package main
|
||||
func main() {}
|
||||
|
|
@ -65,6 +65,15 @@ cd $GOPATH/foo/bar/baz
|
|||
go env GOMOD
|
||||
! stdout .+
|
||||
|
||||
# GO111MODULE=auto should ignore and warn about /tmp/go.mod
|
||||
env GO111MODULE=auto
|
||||
cp $GOPATH/src/x/y/z/go.mod $WORK/tmp/go.mod
|
||||
mkdir $WORK/tmp/mydir
|
||||
cd $WORK/tmp/mydir
|
||||
go env GOMOD
|
||||
! stdout .+
|
||||
stderr '^go: warning: ignoring go.mod in system temp root '
|
||||
|
||||
-- $GOPATH/src/x/y/z/go.mod --
|
||||
module x/y/z
|
||||
-- $GOPATH/src/x/y/z/w/w.txt --
|
||||
|
|
|
|||
|
|
@ -28,6 +28,18 @@ stdout ^m/vendor$
|
|||
stdout ^m/y$
|
||||
! stdout ^m/y/z
|
||||
|
||||
# non-existent directory should not prompt lookups
|
||||
! go build -mod=readonly example.com/nonexist
|
||||
stderr 'import lookup disabled'
|
||||
|
||||
! go build -mod=readonly ./nonexist
|
||||
! stderr 'import lookup disabled'
|
||||
stderr '^go: no such directory ./nonexist'
|
||||
|
||||
! go build -mod=readonly ./go.mod
|
||||
! stderr 'import lookup disabled'
|
||||
stderr '^go: ./go.mod is not a directory'
|
||||
|
||||
-- x/go.mod --
|
||||
module m
|
||||
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ grep 'rsc.io/quote v1.5.1' go.mod
|
|||
go mod edit -require rsc.io/quote@23179ee
|
||||
grep 'rsc.io/quote 23179ee' go.mod
|
||||
|
||||
# but go mod fix fixes them
|
||||
go mod fix
|
||||
# but other commands fix them
|
||||
go mod graph
|
||||
grep 'rsc.io/quote v1.5.1' go.mod
|
||||
|
||||
-- go.mod --
|
||||
|
|
|
|||
|
|
@ -9,11 +9,14 @@ go list -f '{{.ImportPath}}' $GOROOT/src/math
|
|||
stdout ^math$
|
||||
go list -f '{{.ImportPath}}' .
|
||||
stdout ^x$
|
||||
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
||||
stderr '^go: no such directory.*quote@v1.5.2'
|
||||
go mod download rsc.io/quote@v1.5.2
|
||||
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2
|
||||
stdout '^rsc.io/quote$'
|
||||
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0
|
||||
stdout '^rsc.io/sampler$'
|
||||
go get rsc.io/sampler@v1.3.1
|
||||
go get -d rsc.io/sampler@v1.3.1
|
||||
go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.1
|
||||
stdout '^rsc.io/sampler$'
|
||||
! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0
|
||||
|
|
|
|||
|
|
@ -5,43 +5,34 @@ cd m
|
|||
# 'go list all' should list all of the packages used (directly or indirectly) by
|
||||
# the packages in the main module, but no other packages from the standard
|
||||
# library or active modules.
|
||||
go list all
|
||||
stdout example.com/m/useunicode
|
||||
stdout example.com/m/useunsafe
|
||||
[cgo] stdout example.com/m/useC
|
||||
[!cgo] ! stdout example.com/m/useC
|
||||
stdout '^unicode$'
|
||||
stdout '^unsafe$'
|
||||
! stdout index/suffixarray
|
||||
|
||||
#
|
||||
# 'go list ...' should list packages in all active modules and the standard library.
|
||||
# But not cmd/* - see golang.org/issue/26924.
|
||||
go list ...
|
||||
stdout example.com/unused/useerrors
|
||||
stdout example.com/m/useunsafe
|
||||
[cgo] stdout example.com/m/useC
|
||||
[!cgo] ! stdout example.com/m/useC
|
||||
stdout '^unicode$'
|
||||
stdout '^unsafe$'
|
||||
stdout index/suffixarray
|
||||
! stdout cmd/pprof
|
||||
|
||||
# 'go list example.com/m/...' should list packages in all modules that begin with
|
||||
# "example.com/m/".
|
||||
go list example.com/m/...
|
||||
stdout example.com/m/useunicode
|
||||
stdout example.com/m/useunsafe
|
||||
! stdout example.com/[^m]
|
||||
! stdout ^[^e]
|
||||
[cgo] stdout example.com/m/useC
|
||||
[!cgo] ! stdout example.com/m/useC
|
||||
|
||||
#
|
||||
# 'go list example.com/m/...' should list packages in all modules that begin with 'example.com/m/'.
|
||||
#
|
||||
# 'go list ./...' should list only packages in the current module, not other active modules.
|
||||
go list ./...
|
||||
stdout example.com/m/useunicode
|
||||
stdout example.com/m/useunsafe
|
||||
[cgo] stdout example.com/m/useC
|
||||
#
|
||||
# Warnings about unmatched patterns should only be printed once.
|
||||
#
|
||||
# And the go command should be able to keep track of all this!
|
||||
go list -f '{{.ImportPath}}: {{.Match}}' all ... example.com/m/... ./... ./xyz...
|
||||
stdout 'example.com/m/useunicode: \[all \.\.\. example.com/m/... ./...\]'
|
||||
stdout 'example.com/m/useunsafe: \[all \.\.\. example.com/m/... ./...\]'
|
||||
[cgo] stdout 'example.com/m/useC: \[all \.\.\. example.com/m/... ./...\]'
|
||||
[!cgo] ! stdout example.com/m/useC
|
||||
stdout 'example.com/unused/useerrors: \[\.\.\.\]' # but not "all"
|
||||
stdout 'example.com/m/nested/useencoding: \[\.\.\. example.com/m/...\]' # but NOT "all" or "./..."
|
||||
stdout '^unicode: \[all \.\.\.\]'
|
||||
stdout '^unsafe: \[all \.\.\.\]'
|
||||
stdout 'index/suffixarray: \[\.\.\.\]'
|
||||
! stdout cmd/pprof # golang.org/issue/26924
|
||||
|
||||
stderr -count=1 '^go: warning: "./xyz..." matched no packages$'
|
||||
|
||||
env CGO_ENABLED=0
|
||||
go list -f '{{.ImportPath}}: {{.Match}}' all ... example.com/m/... ./... ./xyz...
|
||||
! stdout example.com/m/useC
|
||||
|
||||
-- m/go.mod --
|
||||
module example.com/m
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
go list -e -f '{{.Incomplete}}' runbad1.go
|
||||
stdout true
|
||||
! go run runbad1.go
|
||||
stderr 'use of internal package m/x/internal not allowed'
|
||||
|
||||
go list -e -f '{{.Incomplete}}' runbad2.go
|
||||
stdout true
|
||||
! go run runbad2.go
|
||||
stderr 'use of internal package m/x/internal/y not allowed'
|
||||
|
||||
go list -e -f '{{.Incomplete}}' runok.go
|
||||
stdout false
|
||||
go run runok.go
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
-- x/internal/internal.go --
|
||||
package internal
|
||||
|
||||
-- x/internal/y/y.go --
|
||||
package y
|
||||
|
||||
-- internal/internal.go --
|
||||
package internal
|
||||
|
||||
-- internal/z/z.go --
|
||||
package z
|
||||
|
||||
-- runbad1.go --
|
||||
package main
|
||||
import _ "m/x/internal"
|
||||
func main() {}
|
||||
|
||||
-- runbad2.go --
|
||||
package main
|
||||
import _ "m/x/internal/y"
|
||||
func main() {}
|
||||
|
||||
-- runok.go --
|
||||
package main
|
||||
import _ "m/internal"
|
||||
import _ "m/internal/z"
|
||||
func main() {}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# Test that go run does not get confused by conflict
|
||||
# between go.mod's module path and what you'd
|
||||
# expect from GOPATH. golang.org/issue/26046.
|
||||
|
||||
env GO111MODULE=on
|
||||
|
||||
cd $GOPATH/src/example.com/hello
|
||||
go run main.go
|
||||
|
||||
-- $GOPATH/src/example.com/hello/go.mod --
|
||||
module example.com/hello/v2
|
||||
|
||||
-- $GOPATH/src/example.com/hello/main.go --
|
||||
package main
|
||||
func main() {}
|
||||
|
|
@ -10,6 +10,10 @@ go list -m all
|
|||
stdout '^w.1 v1.2.0'
|
||||
stdout '^z.1 v1.2.0'
|
||||
|
||||
# empty tidy should not crash
|
||||
cd triv
|
||||
go mod tidy
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
|
|
@ -55,3 +59,6 @@ module z
|
|||
|
||||
-- z/sub/sub.go --
|
||||
package sub
|
||||
|
||||
-- triv/go.mod --
|
||||
module triv
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
[exec:bzr] skip 'tests NOT having bzr'
|
||||
[!net] skip
|
||||
|
||||
env GO111MODULE=on
|
||||
env GOPROXY=
|
||||
|
||||
! go list launchpad.net/gocheck
|
||||
stderr '"bzr": executable file not found'
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
|
@ -259,6 +259,20 @@ func checkPrintfFwd(pkg *Package, w *printfWrapper, call *ast.CallExpr, kind int
|
|||
}
|
||||
|
||||
if !call.Ellipsis.IsValid() {
|
||||
typ, ok := pkg.types[call.Fun].Type.(*types.Signature)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if len(call.Args) > typ.Params().Len() {
|
||||
// If we're passing more arguments than what the
|
||||
// print/printf function can take, adding an ellipsis
|
||||
// would break the program. For example:
|
||||
//
|
||||
// func foo(arg1 string, arg2 ...interface{} {
|
||||
// fmt.Printf("%s %v", arg1, arg2)
|
||||
// }
|
||||
return
|
||||
}
|
||||
if !vcfg.VetxOnly {
|
||||
desc := "printf"
|
||||
if kind == kindPrint {
|
||||
|
|
|
|||
|
|
@ -446,6 +446,10 @@ func (*ptrStringer) BadWrapf(x int, format string, args ...interface{}) string {
|
|||
return fmt.Sprintf(format, args) // ERROR "missing ... in args forwarded to printf-like function"
|
||||
}
|
||||
|
||||
func (*ptrStringer) WrapfFalsePositive(x int, arg1 string, arg2 ...interface{}) string {
|
||||
return fmt.Sprintf("%s %v", arg1, arg2)
|
||||
}
|
||||
|
||||
type embeddedStringer struct {
|
||||
foo string
|
||||
ptrStringer
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ func heading(line string) string {
|
|||
}
|
||||
|
||||
// exclude lines with illegal characters. we allow "(),"
|
||||
if strings.ContainsAny(line, ".;:!?+*/=[]{}_^°&§~%#@<\">\\") {
|
||||
if strings.ContainsAny(line, ";:!?+*/=[]{}_^°&§~%#@<\">\\") {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
|
@ -248,6 +248,18 @@ func heading(line string) string {
|
|||
b = b[i+2:]
|
||||
}
|
||||
|
||||
// allow "." when followed by non-space
|
||||
for b := line;; {
|
||||
i := strings.IndexRune(b, '.')
|
||||
if i < 0 {
|
||||
break
|
||||
}
|
||||
if i+1 >= len(b) || b[i+1] == ' ' {
|
||||
return "" // not followed by non-space
|
||||
}
|
||||
b = b[i+1:]
|
||||
}
|
||||
|
||||
return line
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,10 @@ import (
|
|||
|
||||
// Print as many newlines as necessary (but at least min newlines) to get to
|
||||
// the current line. ws is printed before the first line break. If newSection
|
||||
// is set, the first line break is printed as formfeed. Returns true if any
|
||||
// line break was printed; returns false otherwise.
|
||||
// is set, the first line break is printed as formfeed. Returns 0 if no line
|
||||
// breaks were printed, returns 1 if there was exactly one newline printed,
|
||||
// and returns a value > 1 if there was a formfeed or more than one newline
|
||||
// printed.
|
||||
//
|
||||
// TODO(gri): linebreak may add too many lines if the next statement at "line"
|
||||
// is preceded by comments because the computation of n assumes
|
||||
|
|
@ -43,7 +45,7 @@ import (
|
|||
// linebreaks. At the moment there is no easy way to know about
|
||||
// future (not yet interspersed) comments in this function.
|
||||
//
|
||||
func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (printedBreak bool) {
|
||||
func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (nbreaks int) {
|
||||
n := nlimit(line - p.pos.Line)
|
||||
if n < min {
|
||||
n = min
|
||||
|
|
@ -53,11 +55,12 @@ func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (prin
|
|||
if newSection {
|
||||
p.print(formfeed)
|
||||
n--
|
||||
nbreaks = 2
|
||||
}
|
||||
nbreaks += n
|
||||
for ; n > 0; n-- {
|
||||
p.print(newline)
|
||||
}
|
||||
printedBreak = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -173,7 +176,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
|
|||
// The first linebreak is always a formfeed since this section must not
|
||||
// depend on any previous formatting.
|
||||
prevBreak := -1 // index of last expression that was followed by a linebreak
|
||||
if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) {
|
||||
if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) > 0 {
|
||||
ws = ignore
|
||||
prevBreak = 0
|
||||
}
|
||||
|
|
@ -221,36 +224,19 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
|
|||
// If the previous line and the current line had single-
|
||||
// line-expressions and the key sizes are small or the
|
||||
// ratio between the current key and the geometric mean
|
||||
// does not exceed a threshold, align columns and do not use
|
||||
// formfeed.
|
||||
// If the previous line was an empty line, break the alignment.
|
||||
// (The text/tabwriter will break alignment after an empty line
|
||||
// even if we don't do anything here, but we can't see that; yet
|
||||
// we need to reset the variables used in the geomean
|
||||
// computation after an alignment break. Do it explicitly
|
||||
// instead so we're aware of the break. Was issue #26352.)
|
||||
// if the previous key sizes does not exceed a threshold,
|
||||
// align columns and do not use formfeed.
|
||||
if prevSize > 0 && size > 0 {
|
||||
const smallSize = 40
|
||||
switch {
|
||||
case prevLine+1 < line:
|
||||
useFF = true
|
||||
case count == 0, prevSize <= smallSize && size <= smallSize:
|
||||
if count == 0 || prevSize <= smallSize && size <= smallSize {
|
||||
useFF = false
|
||||
default:
|
||||
} else {
|
||||
const r = 2.5 // threshold
|
||||
geomean := math.Exp(lnsum / float64(count)) // count > 0
|
||||
ratio := float64(size) / geomean
|
||||
useFF = r*ratio <= 1 || r <= ratio
|
||||
}
|
||||
}
|
||||
if useFF {
|
||||
lnsum = 0
|
||||
count = 0
|
||||
}
|
||||
if size > 0 {
|
||||
lnsum += math.Log(float64(size))
|
||||
count++
|
||||
}
|
||||
|
||||
needsLinebreak := 0 < prevLine && prevLine < line
|
||||
if i > 0 {
|
||||
|
|
@ -266,11 +252,20 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
|
|||
// Lines are broken using newlines so comments remain aligned
|
||||
// unless useFF is set or there are multiple expressions on
|
||||
// the same line in which case formfeed is used.
|
||||
if p.linebreak(line, 0, ws, useFF || prevBreak+1 < i) {
|
||||
nbreaks := p.linebreak(line, 0, ws, useFF || prevBreak+1 < i)
|
||||
if nbreaks > 0 {
|
||||
ws = ignore
|
||||
prevBreak = i
|
||||
needsBlank = false // we got a line break instead
|
||||
}
|
||||
// If there was a new section or more than one new line
|
||||
// (which means that the tabwriter will implicitly break
|
||||
// the section), reset the geomean variables since we are
|
||||
// starting a new group of elements with the next element.
|
||||
if nbreaks > 1 {
|
||||
lnsum = 0
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
if needsBlank {
|
||||
p.print(blank)
|
||||
|
|
@ -290,6 +285,11 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
|
|||
p.expr0(x, depth)
|
||||
}
|
||||
|
||||
if size > 0 {
|
||||
lnsum += math.Log(float64(size))
|
||||
count++
|
||||
}
|
||||
|
||||
prevLine = line
|
||||
}
|
||||
|
||||
|
|
@ -347,7 +347,7 @@ func (p *printer) parameters(fields *ast.FieldList) {
|
|||
p.print(token.COMMA)
|
||||
}
|
||||
// separator if needed (linebreak or blank)
|
||||
if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) {
|
||||
if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) > 0 {
|
||||
// break line if the opening "(" or previous parameter ended on a different line
|
||||
ws = ignore
|
||||
} else if i > 0 {
|
||||
|
|
@ -718,7 +718,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) {
|
|||
if xline != yline && xline > 0 && yline > 0 {
|
||||
// at least one line break, but respect an extra empty line
|
||||
// in the source
|
||||
if p.linebreak(yline, 1, ws, true) {
|
||||
if p.linebreak(yline, 1, ws, true) > 0 {
|
||||
ws = ignore
|
||||
printBlank = false // no blank after line break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,9 +131,42 @@ func main() {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Examples from issue #26352.
|
||||
|
||||
var _ = map[int]string{
|
||||
1: "",
|
||||
|
||||
12345678901234567890123456789: "",
|
||||
12345678901234567890123456789012345678: "",
|
||||
}
|
||||
|
||||
func f() {
|
||||
_ = map[int]string{
|
||||
1: "",
|
||||
|
||||
12345678901234567: "",
|
||||
12345678901234567890123456789012345678901: "",
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Examples from issue #26930.
|
||||
|
||||
var _ = S{
|
||||
F1: []string{},
|
||||
F2____: []string{},
|
||||
}
|
||||
|
||||
var _ = S{
|
||||
F1: []string{},
|
||||
F2____: []string{},
|
||||
}
|
||||
|
||||
var _ = S{
|
||||
F1____: []string{},
|
||||
F2: []string{},
|
||||
}
|
||||
|
||||
var _ = S{
|
||||
F1____: []string{},
|
||||
F2: []string{},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,9 +131,49 @@ func main() {
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Examples from issue #26352.
|
||||
|
||||
var _ = map[int]string{
|
||||
1: "",
|
||||
|
||||
12345678901234567890123456789: "",
|
||||
12345678901234567890123456789012345678: "",
|
||||
}
|
||||
|
||||
func f() {
|
||||
_ = map[int]string{
|
||||
1: "",
|
||||
|
||||
12345678901234567: "",
|
||||
12345678901234567890123456789012345678901: "",
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Examples from issue #26930.
|
||||
|
||||
var _ = S{
|
||||
F1: []string{
|
||||
},
|
||||
F2____: []string{},
|
||||
}
|
||||
|
||||
var _ = S{
|
||||
F1: []string{
|
||||
|
||||
|
||||
},
|
||||
F2____: []string{},
|
||||
}
|
||||
|
||||
var _ = S{
|
||||
F1____: []string{
|
||||
},
|
||||
F2: []string{},
|
||||
}
|
||||
|
||||
var _ = S{
|
||||
F1____: []string{
|
||||
|
||||
},
|
||||
F2: []string{},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -478,7 +478,12 @@ func (f *File) Chown(uid, gid int) error {
|
|||
}
|
||||
|
||||
func tempDir() string {
|
||||
return "/tmp"
|
||||
dir := Getenv("TMPDIR")
|
||||
if dir == "" {
|
||||
dir = "/tmp"
|
||||
}
|
||||
return dir
|
||||
|
||||
}
|
||||
|
||||
// Chdir changes the current working directory to the file,
|
||||
|
|
|
|||
|
|
@ -842,11 +842,11 @@ var (
|
|||
lfenceBeforeRdtsc bool
|
||||
|
||||
// Set in runtime.cpuinit.
|
||||
support_erms bool
|
||||
support_popcnt bool
|
||||
support_sse2 bool
|
||||
support_sse41 bool
|
||||
arm64_support_atomics bool
|
||||
support_erms bool
|
||||
support_popcnt bool
|
||||
support_sse2 bool
|
||||
support_sse41 bool
|
||||
arm64_support_atomics bool
|
||||
|
||||
goarm uint8 // set by cmd/link on arm systems
|
||||
framepointer_enabled bool // set by cmd/link
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
|
|||
CMPQ AX, $-1
|
||||
JNE ok
|
||||
CALL libc_error(SB)
|
||||
MOVQ (AX), DX // errno
|
||||
MOVLQSX (AX), DX // errno
|
||||
XORL AX, AX
|
||||
ok:
|
||||
MOVQ AX, 32(BX)
|
||||
|
|
@ -371,7 +371,7 @@ TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
|
|||
CMPQ AX, $-1
|
||||
JNE ok
|
||||
CALL libc_error(SB)
|
||||
MOVQ (AX), AX // errno
|
||||
MOVLQSX (AX), AX // errno
|
||||
NEGQ AX // caller wants it as a negative error code
|
||||
ok:
|
||||
POPQ BP
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
|
|||
CMP R0, R2
|
||||
BNE ok
|
||||
BL libc_error(SB)
|
||||
MOVD (R0), R1
|
||||
MOVW (R0), R1
|
||||
MOVD $0, R0
|
||||
ok:
|
||||
MOVD R0, 32(R19) // ret 1 p
|
||||
|
|
@ -277,7 +277,7 @@ TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
|
|||
CMP R0, R2
|
||||
BNE ok
|
||||
BL libc_error(SB)
|
||||
MOVD (R0), R0 // errno
|
||||
MOVW (R0), R0 // errno
|
||||
NEG R0, R0 // caller wants it as a negative error code
|
||||
ok:
|
||||
RET
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
// run
|
||||
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Check that calling a nil func causes a proper panic.
|
||||
|
||||
package main
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
panic("panic expected")
|
||||
}
|
||||
}()
|
||||
|
||||
var f func()
|
||||
f()
|
||||
}
|
||||
Loading…
Reference in New Issue