From 456697ea99ff673157ad0df1308eef08163b5207 Mon Sep 17 00:00:00 2001 From: John Guo Date: Mon, 28 Feb 2022 17:48:52 +0800 Subject: [PATCH] improve cli command install --- cmd/gf/internal/cmd/cmd_build.go | 12 ++++++- cmd/gf/internal/cmd/cmd_docker.go | 1 + cmd/gf/internal/service/install.go | 54 +++++++++++++++++++----------- util/gconv/gconv_slice_any.go | 9 ++--- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/cmd/gf/internal/cmd/cmd_build.go b/cmd/gf/internal/cmd/cmd_build.go index 9a42ca5f1..871b49673 100644 --- a/cmd/gf/internal/cmd/cmd_build.go +++ b/cmd/gf/internal/cmd/cmd_build.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "os" "regexp" "runtime" "strings" @@ -119,6 +120,7 @@ type cBuildInput struct { Mod string `short:"m" name:"mod" brief:"like \"-mod\" option of \"go build\", use \"-m none\" to disable go module"` Cgo bool `short:"c" name:"cgo" brief:"enable or disable cgo feature, it's disabled in default" orphan:"true"` VarMap g.Map `short:"r" name:"varMap" brief:"custom built embedded variable into binary"` + Exit bool `name:"exit" brief:"exit building when any error occurs, default is false" orphan:"true"` Pack string `name:"pack" brief:"pack specified folder into temporary go file before building and removes it after built"` } type cBuildOutput struct{} @@ -254,7 +256,14 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd) mlog.Print(cmdShow) if result, err := gproc.ShellExec(cmd); err != nil { - mlog.Printf("failed to build, os:%s, arch:%s, error:\n%s\n", system, arch, gstr.Trim(result)) + mlog.Printf( + "failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n", + system, arch, gstr.Trim(result), + `you may use command option "--debug" to enable debug info and check the details`, + ) + if in.Exit { + os.Exit(1) + } } else { mlog.Debug(gstr.Trim(result)) } @@ -264,6 +273,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e } } } + buildDone: mlog.Print("done!") return diff --git a/cmd/gf/internal/cmd/cmd_docker.go b/cmd/gf/internal/cmd/cmd_docker.go index e4368ca4d..dd96854ab 100644 --- a/cmd/gf/internal/cmd/cmd_docker.go +++ b/cmd/gf/internal/cmd/cmd_docker.go @@ -81,6 +81,7 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput } // Binary build. + in.Build += " --exit" if in.Main != "" { if err = gproc.ShellRun(fmt.Sprintf(`gf build %s %s`, in.Main, in.Build)); err != nil { return diff --git a/cmd/gf/internal/service/install.go b/cmd/gf/internal/service/install.go index 3448b6ce5..c5d3fec86 100644 --- a/cmd/gf/internal/service/install.go +++ b/cmd/gf/internal/service/install.go @@ -32,7 +32,7 @@ type serviceInstallAvailablePath struct { func (s serviceInstall) Run(ctx context.Context) (err error) { // Ask where to install. - paths := s.getInstallPathsData() + paths := s.getAvailablePaths() if len(paths) <= 0 { mlog.Printf("no path detected, you can manually install gf by copying the binary to path folder.") return @@ -43,16 +43,21 @@ func (s serviceInstall) Run(ctx context.Context) (err error) { // Print all paths status and determine the default selectedID value. var ( selectedID = -1 + newPaths []serviceInstallAvailablePath pathSet = gset.NewStrSet() // Used for repeated items filtering. ) - for id, aPath := range paths { - if !pathSet.AddIfNotExist(aPath.dirPath) { + for _, path := range paths { + if !pathSet.AddIfNotExist(path.dirPath) { continue } - mlog.Printf(" %2d | %8t | %9t | %s", id, aPath.writable, aPath.installed, aPath.dirPath) + newPaths = append(newPaths, path) + } + paths = newPaths + for id, path := range paths { + mlog.Printf(" %2d | %8t | %9t | %s", id, path.writable, path.installed, path.dirPath) if selectedID == -1 { // Use the previously installed path as the most priority choice. - if aPath.installed { + if path.installed { selectedID = id } } @@ -61,6 +66,7 @@ func (s serviceInstall) Run(ctx context.Context) (err error) { if selectedID == -1 { // Order by choosing priority. commonPaths := garray.NewStrArrayFrom(g.SliceStr{ + s.getGoPathBin(), `/usr/local/bin`, `/usr/bin`, `/usr/sbin`, @@ -121,10 +127,10 @@ func (s serviceInstall) Run(ctx context.Context) (err error) { } // Uninstall the old binary. - for _, aPath := range paths { + for _, path := range paths { // Do not delete myself. - if aPath.filePath != "" && aPath.filePath != dstPath.filePath && gfile.SelfPath() != aPath.filePath { - _ = gfile.Remove(aPath.filePath) + if path.filePath != "" && path.filePath != dstPath.filePath && gfile.SelfPath() != path.filePath { + _ = gfile.Remove(path.filePath) } } return @@ -132,7 +138,7 @@ func (s serviceInstall) Run(ctx context.Context) (err error) { // IsInstalled checks and returns whether the binary is installed. func (s serviceInstall) IsInstalled() bool { - paths := s.getInstallPathsData() + paths := s.getAvailablePaths() for _, aPath := range paths { if aPath.installed { return true @@ -141,11 +147,26 @@ func (s serviceInstall) IsInstalled() bool { return false } -// GetInstallPathsData returns the installation paths data for the binary. -func (s serviceInstall) getInstallPathsData() []serviceInstallAvailablePath { - var folderPaths []serviceInstallAvailablePath - // Pre generate binaryFileName. - binaryFileName := "gf" + gfile.Ext(gfile.SelfPath()) +// getGoPathBinFilePath retrieves ad returns the GOPATH/bin path for binary. +func (s serviceInstall) getGoPathBin() string { + if goPath := genv.Get(`GOPATH`).String(); goPath != "" { + return gfile.Join(goPath, "bin") + } + return "" +} + +// getAvailablePaths returns the installation paths data for the binary. +func (s serviceInstall) getAvailablePaths() []serviceInstallAvailablePath { + var ( + folderPaths []serviceInstallAvailablePath + binaryFileName = "gf" + gfile.Ext(gfile.SelfPath()) + ) + // $GOPATH/bin + if goPathBin := s.getGoPathBin(); goPathBin != "" { + folderPaths = s.checkAndAppendToAvailablePath( + folderPaths, goPathBin, binaryFileName, + ) + } switch runtime.GOOS { case "darwin": darwinInstallationCheckPaths := []string{"/usr/local/bin"} @@ -157,11 +178,6 @@ func (s serviceInstall) getInstallPathsData() []serviceInstallAvailablePath { fallthrough default: - // $GOPATH/bin - gopath := gfile.Join(runtime.GOROOT(), "bin") - folderPaths = s.checkAndAppendToAvailablePath( - folderPaths, gopath, binaryFileName, - ) // Search and find the writable directory path. envPath := genv.Get("PATH", genv.Get("Path").String()).String() if gstr.Contains(envPath, ";") { diff --git a/util/gconv/gconv_slice_any.go b/util/gconv/gconv_slice_any.go index d4f73f610..092d19694 100644 --- a/util/gconv/gconv_slice_any.go +++ b/util/gconv/gconv_slice_any.go @@ -22,13 +22,10 @@ func Interfaces(any interface{}) []interface{} { if any == nil { return nil } - if r, ok := any.([]interface{}); ok { - return r - } - var ( - array []interface{} = nil - ) + var array []interface{} switch value := any.(type) { + case []interface{}: + array = value case []string: array = make([]interface{}, len(value)) for k, v := range value {