]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: add support for 'go run pkg' or 'go run .'
authorRuss Cox <rsc@golang.org>
Wed, 25 Apr 2018 17:03:03 +0000 (13:03 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 10 May 2018 19:15:27 +0000 (19:15 +0000)
To date, go run has required a list of .go files.
This CL allows in place of that list a single import path
or a directory name or a pattern matching a single patckage.
This allows 'go run pkg' or 'go run dir', most importantly 'go run .'.

The discussion in #22726 gives more motivation.
The basic idea is that you can already run 'go test .'
but if you're developing a command it's pretty awkward
to iterate at the same speed. This lets you do that,
by using 'go run . [args]'.

Fixes #22726.

Change-Id: Ibfc8172a4f752588ad96df0a6b0928e9b61fa27f
Reviewed-on: https://go-review.googlesource.com/109341
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
src/cmd/go/alldocs.go
src/cmd/go/go_test.go
src/cmd/go/internal/run/run.go
src/cmd/go/testdata/src/hello/hello.go [new file with mode: 0644]

index fa0d57f16b157e3e3ce9849dc047654786af4a22..8cccbf4de00ea4a8ddb082db0b77cadfbc2f968d 100644 (file)
 //
 // Usage:
 //
-//     go run [build flags] [-exec xprog] gofiles... [arguments...]
+//     go run [build flags] [-exec xprog] package [arguments...]
 //
-// Run compiles and runs the main package comprising the named Go source files.
-// A Go source file is defined to be a file ending in a literal ".go" suffix.
+// Run compiles and runs the named main Go package.
+// Typically the package is specified as a list of .go source files,
+// but it may also be an import path, file system path, or pattern
+// matching a single known package, as in 'go run .' or 'go run my/cmd'.
 //
 // By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
 // If the -exec flag is given, 'go run' invokes the binary using xprog:
 // The exit status of Run is not the exit status of the compiled binary.
 //
 // For more about build flags, see 'go help build'.
+// For more about specifying packages, see 'go help packages'.
 //
 // See also: go build.
 //
index 06948525adc178443ad995aad40df6c15d199534..33fbc2cc48ca6eb67b5cbe6763d37d35f17e5aaa 100644 (file)
@@ -1273,6 +1273,18 @@ func TestRunInternal(t *testing.T) {
        tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package not allowed`, "unexpected error for run/bad.go")
 }
 
+func TestRunPkg(t *testing.T) {
+       tg := testgo(t)
+       defer tg.cleanup()
+       dir := filepath.Join(tg.pwd(), "testdata")
+       tg.setenv("GOPATH", dir)
+       tg.run("run", "hello")
+       tg.grepStderr("hello, world", "did not find hello, world")
+       tg.cd(filepath.Join(dir, "src/hello"))
+       tg.run("run", ".")
+       tg.grepStderr("hello, world", "did not find hello, world")
+}
+
 func testMove(t *testing.T, vcs, url, base, config string) {
        testenv.MustHaveExternalNetwork(t)
 
index 6ff20900953a5e72fc3713a0d8b4d849ca145ee8..8460d1fac6aacd76ce15c88a7e20e65b35ec5b90 100644 (file)
@@ -18,11 +18,13 @@ import (
 )
 
 var CmdRun = &base.Command{
-       UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
+       UsageLine: "run [build flags] [-exec xprog] package [arguments...]",
        Short:     "compile and run Go program",
        Long: `
-Run compiles and runs the main package comprising the named Go source files.
-A Go source file is defined to be a file ending in a literal ".go" suffix.
+Run compiles and runs the named main Go package.
+Typically the package is specified as a list of .go source files,
+but it may also be an import path, file system path, or pattern
+matching a single known package, as in 'go run .' or 'go run my/cmd'.
 
 By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
 If the -exec flag is given, 'go run' invokes the binary using xprog:
@@ -37,6 +39,7 @@ available.
 The exit status of Run is not the exit status of the compiled binary.
 
 For more about build flags, see 'go help build'.
+For more about specifying packages, see 'go help packages'.
 
 See also: go build.
        `,
@@ -62,18 +65,33 @@ func runRun(cmd *base.Command, args []string) {
        for i < len(args) && strings.HasSuffix(args[i], ".go") {
                i++
        }
-       files, cmdArgs := args[:i], args[i:]
-       if len(files) == 0 {
-               base.Fatalf("go run: no go files listed")
-       }
-       for _, file := range files {
-               if strings.HasSuffix(file, "_test.go") {
-                       // GoFilesPackage is going to assign this to TestGoFiles.
-                       // Reject since it won't be part of the build.
-                       base.Fatalf("go run: cannot run *_test.go files (%s)", file)
+       var p *load.Package
+       if i > 0 {
+               files := args[:i]
+               for _, file := range files {
+                       if strings.HasSuffix(file, "_test.go") {
+                               // GoFilesPackage is going to assign this to TestGoFiles.
+                               // Reject since it won't be part of the build.
+                               base.Fatalf("go run: cannot run *_test.go files (%s)", file)
+                       }
+               }
+               p = load.GoFilesPackage(files)
+       } else if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
+               pkgs := load.PackagesAndErrors(args[:1])
+               if len(pkgs) > 1 {
+                       var names []string
+                       for _, p := range pkgs {
+                               names = append(names, p.ImportPath)
+                       }
+                       base.Fatalf("go run: pattern %s matches multiple packages:\n\t%s", args[0], strings.Join(names, "\n\t"))
                }
+               p = pkgs[0]
+               i++
+       } else {
+               base.Fatalf("go run: no go files listed")
        }
-       p := load.GoFilesPackage(files)
+       cmdArgs := args[i:]
+
        if p.Error != nil {
                base.Fatalf("%s", p.Error)
        }
diff --git a/src/cmd/go/testdata/src/hello/hello.go b/src/cmd/go/testdata/src/hello/hello.go
new file mode 100644 (file)
index 0000000..73d83e6
--- /dev/null
@@ -0,0 +1,5 @@
+package main
+
+func main() {
+       println("hello, world")
+}