Просмотр исходного кода

goctl add plugin support (#243)

* add plugin support

* add plugin support

* add plugin support

* add plugin support

* add plugin support

* add plugin support

* add plugin support

* add plugin support

* add plugin support

* add plugin support

* add plugin support

* remove no need

* add plugin support

* rename

* rename

* add plugin support

* refactor

* update plugin

* refactor

* refactor

* refactor

* update plugin

* newline

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
kingxt 4 лет назад
Родитель
Сommit
cecd4b1b75

+ 25 - 0
tools/goctl/goctl.go

@@ -20,6 +20,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/docker"
 	"github.com/tal-tech/go-zero/tools/goctl/kube"
 	model "github.com/tal-tech/go-zero/tools/goctl/model/sql/command"
+	"github.com/tal-tech/go-zero/tools/goctl/plugin"
 	rpc "github.com/tal-tech/go-zero/tools/goctl/rpc/cli"
 	"github.com/tal-tech/go-zero/tools/goctl/tpl"
 	"github.com/urfave/cli"
@@ -186,6 +187,30 @@ var (
 					},
 					Action: ktgen.KtCommand,
 				},
+				{
+					Name:  "plugin",
+					Usage: "custom file generator",
+					Flags: []cli.Flag{
+						cli.StringFlag{
+							Name:  "plugin",
+							Usage: "the plugin file",
+						},
+						cli.StringFlag{
+							Name:  "dir",
+							Usage: "the target directory",
+						},
+						cli.StringFlag{
+							Name:  "api",
+							Usage: "the api file",
+						},
+						cli.StringFlag{
+							Name:     "style",
+							Required: false,
+							Usage:    "the file naming format, see [https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/readme.md]",
+						},
+					},
+					Action: plugin.PluginCommand,
+				},
 			},
 		},
 		{

+ 20 - 0
tools/goctl/plugin/demo/goctlplugin.go

@@ -0,0 +1,20 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/tal-tech/go-zero/tools/goctl/plugin"
+)
+
+func main() {
+	plugin, err := plugin.NewPlugin()
+	if err != nil {
+		panic(err)
+	}
+
+	if plugin.Api != nil {
+		fmt.Printf("api: %+v \n", plugin.Api)
+	}
+	fmt.Printf("dir: %s \n", plugin.Dir)
+	fmt.Println("Enjoy anything you want.")
+}

+ 166 - 0
tools/goctl/plugin/plugin.go

@@ -0,0 +1,166 @@
+package plugin
+
+import (
+	"bytes"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+
+	"github.com/tal-tech/go-zero/tools/goctl/api/parser"
+	"github.com/tal-tech/go-zero/tools/goctl/api/spec"
+	"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
+	"github.com/tal-tech/go-zero/tools/goctl/util"
+	"github.com/urfave/cli"
+)
+
+const (
+	pluginArg = "_plugin"
+)
+
+type Plugin struct {
+	Api   *spec.ApiSpec
+	Style string
+	Dir   string
+}
+
+func PluginCommand(c *cli.Context) error {
+	ex, err := os.Executable()
+	if err != nil {
+		panic(err)
+	}
+
+	var plugin = c.String("plugin")
+	if len(plugin) == 0 {
+		return errors.New("missing plugin")
+	}
+
+	transferData, err := prepareArgs(c)
+	if err != nil {
+		return err
+	}
+
+	bin, download, err := getCommand(plugin)
+	if err != nil {
+		return err
+	}
+	if download {
+		defer func() {
+			_ = os.Remove(bin)
+		}()
+	}
+
+	content, err := execx.Run(bin, filepath.Dir(ex), bytes.NewBuffer(transferData))
+	if err != nil {
+		return err
+	}
+
+	fmt.Println(content)
+	return nil
+}
+
+func prepareArgs(c *cli.Context) ([]byte, error) {
+	apiPath := c.String("api")
+
+	var transferData Plugin
+	if len(apiPath) > 0 && util.FileExists(apiPath) {
+		p, err := parser.NewParser(apiPath)
+		if err != nil {
+			return nil, err
+		}
+
+		api, err := p.Parse()
+		if err != nil {
+			return nil, err
+		}
+
+		transferData.Api = api
+	}
+
+	dirAbs, err := filepath.Abs(c.String("dir"))
+	if err != nil {
+		return nil, err
+	}
+
+	transferData.Dir = dirAbs
+	transferData.Style = c.String("style")
+	data, err := json.Marshal(transferData)
+	if err != nil {
+		return nil, err
+	}
+
+	return data, nil
+}
+
+func getCommand(arg string) (string, bool, error) {
+	p, err := exec.LookPath(arg)
+	if err == nil {
+		abs, err := filepath.Abs(p)
+		if err != nil {
+			return "", false, err
+		}
+		return abs, false, nil
+	}
+
+	var defaultErr = errors.New("invalid plugin value " + arg)
+	if strings.HasPrefix(arg, "http") {
+		items := strings.Split(arg, "/")
+		if len(items) == 0 {
+			return "", false, defaultErr
+		}
+
+		filename, err := filepath.Abs(pluginArg + items[len(items)-1])
+		if err != nil {
+			return "", false, err
+		}
+
+		err = downloadFile(filename, arg)
+		if err != nil {
+			return "", false, err
+		}
+
+		os.Chmod(filename, os.ModePerm)
+		return filename, true, nil
+	}
+	return arg, false, nil
+}
+
+func downloadFile(filepath string, url string) error {
+	resp, err := http.Get(url)
+	if err != nil {
+		return err
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+
+	out, err := os.Create(filepath)
+	if err != nil {
+		return err
+	}
+	defer func() {
+		_ = out.Close()
+	}()
+
+	_, err = io.Copy(out, resp.Body)
+	return err
+}
+
+func NewPlugin() (*Plugin, error) {
+	var plugin Plugin
+	content, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		return nil, err
+	}
+	err = json.Unmarshal(content, &plugin)
+	if err != nil {
+		return nil, err
+	}
+	return &plugin, nil
+}

+ 4 - 1
tools/goctl/rpc/execx/execx.go

@@ -12,7 +12,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/vars"
 )
 
-func Run(arg string, dir string) (string, error) {
+func Run(arg string, dir string, in ...*bytes.Buffer) (string, error) {
 	goos := runtime.GOOS
 	var cmd *exec.Cmd
 	switch goos {
@@ -28,6 +28,9 @@ func Run(arg string, dir string) (string, error) {
 	}
 	stdout := new(bytes.Buffer)
 	stderr := new(bytes.Buffer)
+	if len(in) > 0 {
+		cmd.Stdin = in[0]
+	}
 	cmd.Stdout = stdout
 	cmd.Stderr = stderr
 	err := cmd.Run()

+ 9 - 0
tools/goctl/util/string.go

@@ -17,3 +17,12 @@ func Untitle(s string) string {
 
 	return strings.ToLower(s[:1]) + s[1:]
 }
+
+func Index(slice []string, item string) int {
+	for i, _ := range slice {
+		if slice[i] == item {
+			return i
+		}
+	}
+	return -1
+}