✨ feat: 添加 goc run 命令
This commit is contained in:
parent
29c6644362
commit
1574d9784c
47
cmd/run.go
Normal file
47
cmd/run.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 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 (
|
||||||
|
"github.com/qiniu/goc/v2/pkg/build"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var runCmd = &cobra.Command{
|
||||||
|
Use: "run",
|
||||||
|
Run: runAction,
|
||||||
|
|
||||||
|
DisableFlagParsing: true, // run 命令需要用原生 go 的方式处理 flags
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
runCmd.Flags().StringVarP(&gocmode, "gocmode", "", "count", "coverage mode: set, count, atomic, watch")
|
||||||
|
runCmd.Flags().StringVarP(&gochost, "gochost", "", "127.0.0.1:7777", "specify the host of the goc sever")
|
||||||
|
rootCmd.AddCommand(runCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runAction(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
|
sets := build.CustomParseCmdAndArgs(cmd, args)
|
||||||
|
|
||||||
|
b := build.NewRun(
|
||||||
|
build.WithHost(gochost),
|
||||||
|
build.WithMode(gocmode),
|
||||||
|
build.WithFlagSets(sets),
|
||||||
|
build.WithArgs(args),
|
||||||
|
build.WithBuild(),
|
||||||
|
build.WithDebug(globalDebug),
|
||||||
|
)
|
||||||
|
b.Run()
|
||||||
|
}
|
@ -14,7 +14,9 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/qiniu/goc/v2/pkg/log"
|
||||||
"github.com/qiniu/goc/v2/pkg/server"
|
"github.com/qiniu/goc/v2/pkg/server"
|
||||||
|
"github.com/qiniu/goc/v2/pkg/server/store"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -40,5 +42,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func serve(cmd *cobra.Command, args []string) {
|
func serve(cmd *cobra.Command, args []string) {
|
||||||
server.RunGocServerUntilExit(serverHost, serverStore)
|
s, err := store.NewFileStore(serverStore)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("cannot create store for goc server: %v", err)
|
||||||
|
}
|
||||||
|
server.RunGocServerUntilExit(serverHost, s)
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,15 @@ The [goc flags] can be placed in anywhere in the command line.
|
|||||||
However, other flags' order are same with the go official command.
|
However, other flags' order are same with the go official command.
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var runUsage string = `Usage:
|
||||||
|
goc run [build flags] [goc flags] [packages] [arguments...]
|
||||||
|
|
||||||
|
[build flags] are same with go official command, you can copy them here directly.
|
||||||
|
|
||||||
|
The [goc flags] can be placed in anywhere in the command line.
|
||||||
|
However, other flags' order are same with the go official command.
|
||||||
|
`
|
||||||
|
|
||||||
const (
|
const (
|
||||||
GO_BUILD = iota
|
GO_BUILD = iota
|
||||||
GO_INSTALL
|
GO_INSTALL
|
||||||
@ -131,6 +140,40 @@ func (b *Build) buildCmdArgsParse() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Build) runCmdArgsParse() {
|
||||||
|
args := b.Args
|
||||||
|
allFlagSets := b.FlagSets
|
||||||
|
|
||||||
|
// 重写 help
|
||||||
|
helpFlag := allFlagSets.Lookup("help")
|
||||||
|
|
||||||
|
if helpFlag.Changed {
|
||||||
|
printGoHelp(runUsage)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除 help flag
|
||||||
|
args = findAndDelHelpFlag(args)
|
||||||
|
|
||||||
|
// 必须手动调用
|
||||||
|
// 由于关闭了 cobra 的 flag parse,root PersistentPreRun 调用时,log.NewLogger 并没有拿到 debug 值
|
||||||
|
log.NewLogger(b.Debug)
|
||||||
|
|
||||||
|
curWd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("fail to get current working directory: %v", err)
|
||||||
|
}
|
||||||
|
b.CurWd = curWd
|
||||||
|
|
||||||
|
// 获取除 goc flags 之外的 args
|
||||||
|
// 删除 cobra 定义的 flag
|
||||||
|
allFlagSets.Visit(func(f *pflag.Flag) {
|
||||||
|
args = findAndDelGocFlag(args, f.Name, f.Value.String())
|
||||||
|
})
|
||||||
|
|
||||||
|
b.GoArgs = args
|
||||||
|
}
|
||||||
|
|
||||||
func findAndDelGocFlag(a []string, x string, v string) []string {
|
func findAndDelGocFlag(a []string, x string, v string) []string {
|
||||||
new := make([]string, 0, len(a))
|
new := make([]string, 0, len(a))
|
||||||
x = "--" + x
|
x = "--" + x
|
||||||
|
88
pkg/build/run.go
Normal file
88
pkg/build/run.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/signal"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/qiniu/goc/v2/pkg/log"
|
||||||
|
"github.com/qiniu/goc/v2/pkg/server"
|
||||||
|
"github.com/qiniu/goc/v2/pkg/server/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRun(opts ...gocOption) *Build {
|
||||||
|
b := &Build{}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 解析 goc 命令行和 go 命令行
|
||||||
|
b.runCmdArgsParse()
|
||||||
|
// 2. 解析 go 包位置
|
||||||
|
// b.getPackagesDir()
|
||||||
|
// 3. 读取工程元信息:go.mod, pkgs list ...
|
||||||
|
b.readProjectMetaInfo()
|
||||||
|
// 4. 展示元信息
|
||||||
|
b.displayProjectMetaInfo()
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run starts go run
|
||||||
|
//
|
||||||
|
// 1. copy project to temp,
|
||||||
|
// 2. inject cover variables and functions into the project,
|
||||||
|
// 3. run the project in temp.
|
||||||
|
func (b *Build) Run() {
|
||||||
|
// 1. 拷贝至临时目录
|
||||||
|
b.copyProjectToTmp()
|
||||||
|
defer b.clean()
|
||||||
|
|
||||||
|
log.Donef("project copied to temporary directory")
|
||||||
|
|
||||||
|
// 2. update go.mod file if needed
|
||||||
|
b.updateGoModFile()
|
||||||
|
// 3. inject cover vars
|
||||||
|
b.Inject()
|
||||||
|
// 4. run in the temp project
|
||||||
|
go func() {
|
||||||
|
ch := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(ch, os.Interrupt)
|
||||||
|
<-ch
|
||||||
|
b.clean()
|
||||||
|
}()
|
||||||
|
b.doRunInTemp()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Build) doRunInTemp() {
|
||||||
|
log.Infof("running the injected project")
|
||||||
|
|
||||||
|
s := store.NewFakeStore()
|
||||||
|
go func() {
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
err := server.RunGocServerUntilExit(b.Host, s)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("goc server fail to run: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
args := []string{"run"}
|
||||||
|
args = append(args, b.GoArgs...)
|
||||||
|
cmd := exec.Command("go", args...)
|
||||||
|
cmd.Dir = b.TmpWd
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
log.Infof("go run cmd is: %v, in path [%v]", nicePrintArgs(cmd.Args), cmd.Dir)
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
log.Errorf("fail to execute go run: %v", err)
|
||||||
|
}
|
||||||
|
if err := cmd.Wait(); err != nil {
|
||||||
|
log.Errorf("fail to execute go run: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
log.Donef("go run done")
|
||||||
|
}
|
@ -96,12 +96,7 @@ type gocWatchClient struct {
|
|||||||
once sync.Once
|
once sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunGocServerUntilExit(host string, path string) {
|
func RunGocServerUntilExit(host string, s store.Store) error {
|
||||||
s, err := store.NewFileStore(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("cannot create store for goc server: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
gs := gocServer{
|
gs := gocServer{
|
||||||
store: s,
|
store: s,
|
||||||
upgrader: websocket.Upgrader{
|
upgrader: websocket.Upgrader{
|
||||||
@ -136,7 +131,7 @@ func RunGocServerUntilExit(host string, path string) {
|
|||||||
|
|
||||||
go gs.watchLoop()
|
go gs.watchLoop()
|
||||||
|
|
||||||
r.Run(host)
|
return r.Run(host)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *gocServer) register(c *gin.Context) {
|
func (gs *gocServer) register(c *gin.Context) {
|
||||||
|
Loading…
Reference in New Issue
Block a user