diff --git a/cmd/cover.go b/cmd/cover.go index c8eef85..a9ae61c 100644 --- a/cmd/cover.go +++ b/cmd/cover.go @@ -19,9 +19,8 @@ package cmd import ( "github.com/qiniu/goc/pkg/cover" log "github.com/sirupsen/logrus" - "github.com/spf13/viper" - "github.com/spf13/cobra" + "github.com/spf13/viper" ) var coverCmd = &cobra.Command{ diff --git a/cmd/run.go b/cmd/run.go new file mode 100644 index 0000000..6cc0187 --- /dev/null +++ b/cmd/run.go @@ -0,0 +1,73 @@ +/* + Copyright 2020 Qiniu Cloud (qiniu.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package cmd + +import ( + "fmt" + "io/ioutil" + "net" + + "github.com/qiniu/goc/pkg/build" + "github.com/qiniu/goc/pkg/cover" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +var runCmd = &cobra.Command{ + Use: "run", + Short: "Run covers and runs the named main Go package", + Long: `Run covers and runs the named main Go package, +It is exactly behave as 'go run .' in addition of some internal goc features.`, + Example: ` +goc run . +`, + Run: func(cmd *cobra.Command, args []string) { + gocBuild := build.NewBuild(buildFlags, packages, buildOutput) + gocBuild.GoRunExecFlag = goRunExecFlag + gocBuild.GoRunArguments = goRunArguments + defer func() { + if !debugGoc { + gocBuild.Clean() + } + }() + // start goc server + var l = newLocalListener() + go cover.GocServer(ioutil.Discard).RunListener(l) + gocServer := fmt.Sprintf("http://%s", l.Addr().String()) + fmt.Printf("[goc] goc server started: %s \n", gocServer) + + // execute covers for the target source with original buildFlags and new GOPATH( tmp:original ) + cover.Execute(buildFlags, gocBuild.NewGOPATH, gocBuild.TmpDir, mode, gocServer) + + gocBuild.Run() + }, +} + +func init() { + addRunFlags(runCmd.Flags()) + rootCmd.AddCommand(runCmd) +} + +func newLocalListener() net.Listener { + l, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + if l, err = net.Listen("tcp6", "[::1]:0"); err != nil { + log.Fatalf("failed to listen on a port: %v", err) + } + } + return l +} diff --git a/pkg/build/build.go b/pkg/build/build.go index 854461b..983ddb2 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -35,10 +35,17 @@ type Build struct { TmpDir string // the temporary directory to build the project TmpWorkingDir string // the working directory in the temporary directory, which is corresponding to the current directory in the project directory IsMod bool // determine whether it is a Mod project - BuildFlags string // Build flags - Packages string // Packages that needs to build Root string // Project Root Target string // the binary name that go build generate + + // keep compatible with go commands: + // go run [build flags] [-exec xprog] package [arguments...] + // go build [-o output] [-i] [build flags] [packages] + // go install [-i] [build flags] [packages] + BuildFlags string // Build flags + Packages string // Packages that needs to build + GoRunExecFlag string // for the -exec flags in go run command + GoRunArguments string // for the '[arguments]' parameters in go run command } // NewBuild creates a Build struct which can build from goc temporary directory, @@ -108,7 +115,26 @@ func (b *Build) determineOutputDir(outputDir string) string { func (b *Build) validatePackageForBuild() bool { if b.Packages == "." { return true - } else { - return false + } + return false +} + +// Run excutes the main package in addition with the internal goc features +func (b *Build) Run() { + cmd := exec.Command("/bin/bash", "-c", "go run "+b.BuildFlags+" "+b.GoRunExecFlag+" "+b.Packages+" "+b.GoRunArguments) + cmd.Dir = b.TmpWorkingDir + + if b.NewGOPATH != "" { + // Change to temp GOPATH for go install command + cmd.Env = append(os.Environ(), fmt.Sprintf("GOPATH=%v", b.NewGOPATH)) + } + + log.Printf("go build cmd is: %v", cmd.Args) + out, err := cmd.CombinedOutput() + if err != nil { + log.Fatalf("Fail to execute: %v. The error is: %v, the stdout/stderr is: %v", cmd.Args, err, string(out)) + } + if len(out) > 0 { + fmt.Println(string(out)) } } diff --git a/pkg/build/gomodules.go b/pkg/build/gomodules.go index f593c8d..502a226 100644 --- a/pkg/build/gomodules.go +++ b/pkg/build/gomodules.go @@ -17,9 +17,8 @@ package build import ( - log "github.com/sirupsen/logrus" - "github.com/otiai10/copy" + log "github.com/sirupsen/logrus" ) func (b *Build) cpGoModulesProject() { diff --git a/pkg/build/install.go b/pkg/build/install.go index cb11720..8ab25d3 100644 --- a/pkg/build/install.go +++ b/pkg/build/install.go @@ -18,9 +18,10 @@ package build import ( "fmt" - log "github.com/sirupsen/logrus" "os" "os/exec" + + log "github.com/sirupsen/logrus" ) // NewInstall creates a Build struct which can install from goc temporary directory @@ -59,7 +60,6 @@ func (b *Build) Install() { func (b *Build) validatePackageForInstall() bool { if b.Packages == "." || b.Packages == "./..." { return true - } else { - return false } + return false } diff --git a/pkg/build/legacy.go b/pkg/build/legacy.go index ed6244a..962dea7 100644 --- a/pkg/build/legacy.go +++ b/pkg/build/legacy.go @@ -17,12 +17,12 @@ package build import ( - log "github.com/sirupsen/logrus" "os" "path/filepath" "github.com/otiai10/copy" "github.com/qiniu/goc/pkg/cover" + log "github.com/sirupsen/logrus" ) func (b *Build) cpLegacyProject() { diff --git a/pkg/build/tmpfolder.go b/pkg/build/tmpfolder.go index aff30bd..b80632f 100644 --- a/pkg/build/tmpfolder.go +++ b/pkg/build/tmpfolder.go @@ -23,9 +23,8 @@ import ( "path/filepath" "strings" - log "github.com/sirupsen/logrus" - "github.com/qiniu/goc/pkg/cover" + log "github.com/sirupsen/logrus" ) func (b *Build) MvProjectsToTmp() { diff --git a/pkg/cover/server.go b/pkg/cover/server.go index 93e9038..0545f1f 100644 --- a/pkg/cover/server.go +++ b/pkg/cover/server.go @@ -19,7 +19,6 @@ package cover import ( "bytes" "fmt" - log "github.com/sirupsen/logrus" "io" "io/ioutil" "net" @@ -27,6 +26,8 @@ import ( "net/url" "os" + log "github.com/sirupsen/logrus" + "github.com/gin-gonic/gin" "golang.org/x/tools/cover" "k8s.io/test-infra/gopherage/pkg/cov"