From 3717c2d29fd599cd504213498388c5fefdf0e26a Mon Sep 17 00:00:00 2001 From: lyyyuna Date: Sat, 13 Jun 2020 18:15:51 +0800 Subject: [PATCH] refactor build/install command --- cmd/build.go | 83 ++++++------------------------------ cmd/clear.go | 2 +- cmd/cover.go | 2 +- cmd/init.go | 2 +- cmd/install.go | 5 ++- cmd/profile.go | 2 +- cmd/root.go | 22 ++++++++-- go.mod | 2 +- go.sum | 3 ++ pkg/build/binarymove.go | 77 ---------------------------------- pkg/build/build.go | 90 +++++++++++++++++++++++++++++++++------- pkg/build/gomodules.go | 3 +- pkg/build/install.go | 25 ++++++++++- pkg/build/legacy.go | 2 +- pkg/build/tmpfolder.go | 22 +++++++--- pkg/cover/cover.go | 6 +-- pkg/cover/cover_test.go | 2 +- pkg/cover/server.go | 2 +- pkg/cover/store.go | 2 +- pkg/qiniu/qnPresubmit.go | 2 +- 20 files changed, 167 insertions(+), 189 deletions(-) delete mode 100644 pkg/build/binarymove.go diff --git a/cmd/build.go b/cmd/build.go index dd0f726..076c2a5 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -17,14 +17,7 @@ package cmd import ( - "flag" - "fmt" - "log" - "os" - "os/exec" - "path/filepath" - "strings" - + "github.com/qiniu/goc/pkg/build" "github.com/spf13/cobra" ) @@ -50,74 +43,22 @@ goc build -- -o /to/this/path goc build -- -ldflags "-extldflags -static" -tags="embed kodo" `, Run: func(cmd *cobra.Command, args []string) { - + gocbuild := build.NewBuild(buildFlags, packages, buildOutput) + // remove temporary directory if needed + defer gocbuild.RemoveTmpDir() + // doCover with original buildFlags, with new GOPATH( tmp:original ) + // in the tmp directory + doCover(buildFlags, gocbuild.NewGOPATH, gocbuild.TmpDir) + // do install in the temporary directory + gocbuild.Build() return - /* - gocbuild := build.NewInstall(buildFlags, packages) - newgopath, newwd, tmpdir, _ := gocbuild.MvProjectsToTmp() - doCover("args", newgopath, tmpdir) - newArgs, modified := modifyOutputArg(args) - doBuild(newArgs, newgopath, newwd) - - // if not modified - // find the binary in temp build dir - // and copy them into original dir - if false == modified { - // build.MvBinaryToOri(pkgs, tmpdir) - } - - */ }, } +var buildOutput string + func init() { addBuildFlags(buildCmd.Flags()) + buildCmd.Flags().StringVar(&buildOutput, "output", "", "it forces build to write the resulting executable or object to the named output file or directory") rootCmd.AddCommand(buildCmd) } - -func doBuild(args []string, newgopath string, newworkingdir string) { - log.Println("Go building in temp...") - newArgs := []string{"build"} - newArgs = append(newArgs, args...) - cmd := exec.Command("go", newArgs...) - cmd.Dir = newworkingdir - - if newgopath != "" { - // Change to temp GOPATH for go install command - cmd.Env = append(os.Environ(), fmt.Sprintf("GOPATH=%v", newgopath)) - } - - out, err := cmd.CombinedOutput() - if err != nil { - log.Fatalf("Fail to execute: go build %v. The error is: %v, the stdout/stderr is: %v", strings.Join(args, " "), err, string(out)) - } - log.Println("Go build exit successful.") -} - -// As we build in the temp build dir, we have to modify the "-o output", -// if output is a relative path, transform it to abspath -func modifyOutputArg(args []string) (newArgs []string, modified bool) { - var output string - fs := flag.NewFlagSet("goc-build", flag.PanicOnError) - fs.StringVar(&output, "o", "", "output dir") - - // parse the go args after "--" - fs.Parse(args) - - // skip if output is not present - if output == "" { - modified = false - newArgs = args - return - } - - abs, err := filepath.Abs(output) - if err != nil { - log.Fatalf("Fail to transform the path: %v to absolute path, the error is: %v", output, err) - } - - // the second -o arg will overwrite the first one - newArgs = append(args, "-o", abs) - modified = true - return -} diff --git a/cmd/clear.go b/cmd/clear.go index c6d5fb1..8e1bc93 100644 --- a/cmd/clear.go +++ b/cmd/clear.go @@ -18,7 +18,7 @@ package cmd import ( "fmt" - "log" + log "github.com/sirupsen/logrus" "os" "github.com/qiniu/goc/pkg/cover" diff --git a/cmd/cover.go b/cmd/cover.go index cc81ab0..b139ff4 100644 --- a/cmd/cover.go +++ b/cmd/cover.go @@ -19,7 +19,7 @@ package cmd import ( "fmt" "github.com/spf13/viper" - "log" + log "github.com/sirupsen/logrus" "os" "strings" diff --git a/cmd/init.go b/cmd/init.go index 2084301..cd7e0f0 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -17,7 +17,7 @@ package cmd import ( - "log" + log "github.com/sirupsen/logrus" "github.com/qiniu/goc/pkg/cover" "github.com/spf13/cobra" diff --git a/cmd/install.go b/cmd/install.go index abc8aa2..d30d0a7 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -41,11 +41,12 @@ goc build --buildflags="-ldflags '-extldflags -static' -tags='embed kodo'" `, Run: func(cmd *cobra.Command, args []string) { gocbuild := build.NewInstall(buildFlags, packages) - gocbuild.MvProjectsToTmp() + // remove temporary directory if needed + defer gocbuild.RemoveTmpDir() // doCover with original buildFlags, with new GOPATH( tmp:original ) // in the tmp directory doCover(buildFlags, gocbuild.NewGOPATH, gocbuild.TmpDir) - // + // do install in the temporary directory gocbuild.Install() }, } diff --git a/cmd/profile.go b/cmd/profile.go index cef1c3e..2817a2f 100644 --- a/cmd/profile.go +++ b/cmd/profile.go @@ -20,7 +20,7 @@ import ( "bytes" "fmt" "io" - "log" + log "github.com/sirupsen/logrus" "os" "github.com/qiniu/goc/pkg/cover" diff --git a/cmd/root.go b/cmd/root.go index 717ef9b..3974e4c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,10 +17,13 @@ package cmd import ( - "io/ioutil" - "log" - + log "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/spf13/viper" + "io/ioutil" + "path/filepath" + "runtime" + "strconv" ) var rootCmd = &cobra.Command{ @@ -32,7 +35,17 @@ Find more information at: https://github.com/qiniu/goc `, PersistentPreRun: func(cmd *cobra.Command, args []string) { - log.SetFlags(log.LstdFlags | log.Lshortfile) + log.SetReportCaller(true) + log.SetFormatter(&log.TextFormatter{ + FullTimestamp: true, + CallerPrettyfier: func(f *runtime.Frame) (string, string) { + dirname, filename := filepath.Split(f.File) + lastelem := filepath.Base(dirname) + filename = filepath.Join(lastelem, filename) + line := strconv.Itoa(f.Line) + return "", "[" + filename + ":" + line + "]" + }, + }) if debugGoc == false { // we only need log in debug mode log.SetOutput(ioutil.Discard) @@ -43,6 +56,7 @@ Find more information at: func init() { rootCmd.PersistentFlags().BoolVar(&debugGoc, "debuggoc", false, "turn goc into debug mode") rootCmd.PersistentFlags().MarkHidden("debuggoc") + viper.BindPFlags(rootCmd.PersistentFlags()) } // Execute the goc tool diff --git a/go.mod b/go.mod index bdc4484..b6fec6a 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/onsi/gomega v1.8.1 github.com/otiai10/copy v1.0.2 github.com/qiniu/api.v7/v7 v7.5.0 - github.com/sirupsen/logrus v1.4.2 + github.com/sirupsen/logrus v1.6.0 github.com/spf13/cobra v1.0.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.6.2 diff --git a/go.sum b/go.sum index 20cc21b..23b3c55 100644 --- a/go.sum +++ b/go.sum @@ -461,6 +461,7 @@ github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= @@ -652,6 +653,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= diff --git a/pkg/build/binarymove.go b/pkg/build/binarymove.go deleted file mode 100644 index 12d9cbe..0000000 --- a/pkg/build/binarymove.go +++ /dev/null @@ -1,77 +0,0 @@ -/* - 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 build - -import ( - "log" - "os" - "path/filepath" - - "github.com/otiai10/copy" - "github.com/qiniu/goc/pkg/cover" -) - -func (b *Build) MvBinaryToOri(pkgs map[string]*cover.Package) { - for _, pkg := range b.Pkgs { - if pkg.Name == "main" { - _, binaryTarget := filepath.Split(pkg.Target) - - binaryTmpPath := filepath.Join(b.TmpWorkingDir) - - if false == checkIfFileExist(binaryTmpPath) { - continue - } - - curwd, err := os.Getwd() - if err != nil { - log.Fatalf("Cannot get current working directoy, the error is: %v", err) - } - binaryOriPath := filepath.Join(curwd, binaryTarget) - - if checkIfFileExist(binaryOriPath) { - // if we have file in the original place with same name, - // but this file is not a binary, - // then we skip it - if false == checkIfExecutable(binaryOriPath) { - log.Printf("Skipping binary: %v, as we find a file in the original place with same name but not executable.", binaryOriPath) - continue - } - } - - log.Printf("Generating binary: %v", binaryOriPath) - if err = copy.Copy(binaryTmpPath, binaryOriPath); err != nil { - log.Println(err) - } - } - } -} - -func checkIfExecutable(path string) bool { - fileInfo, err := os.Lstat(path) - if err != nil { - return false - } - return fileInfo.Mode()&0100 != 0 -} - -func checkIfFileExist(path string) bool { - fileInfo, err := os.Stat(path) - if os.IsNotExist(err) { - return false - } - return !fileInfo.IsDir() -} diff --git a/pkg/build/build.go b/pkg/build/build.go index 8a7dd3e..d4c0ebd 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -16,25 +16,87 @@ package build -import "github.com/qiniu/goc/pkg/cover" +import ( + "fmt" + "github.com/qiniu/goc/pkg/cover" + log "github.com/sirupsen/logrus" + "os" + "os/exec" + "path/filepath" +) // Build is to describe the building/installing process of a goc build/install type Build struct { - Pkgs map[string]*cover.Package // - NewGOPATH string - OriGOPATH string - TmpDir string - TmpWorkingDir string - IsMod bool - BuildFlags string - Packages string - Root string // Project Root + Pkgs map[string]*cover.Package // Pkg list parsed from "go list -json ./..." command + NewGOPATH string // the new GOPATH + OriGOPATH string // the original GOPATH + 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 } -func NewInstall(buildflags string, packages string) *Build { - return &Build{ +// NewBuild creates a Build struct which can build from goc temporary directory, +// and generate binary in current working directory +func NewBuild(buildflags string, packages string, outputDir string) *Build { + // buildflags = buildflags + " -o " + outputDir + b := &Build{ BuildFlags: buildflags, - Packages: packages, + Packages: packages, + } + if false == b.validatePackageForBuild() { + log.Fatalln("packages only support \".\"") + } + b.Target = b.determineOutputDir(outputDir) + b.MvProjectsToTmp() + return b +} + +func (b *Build) Build() { + log.Infoln("Go building in temp...") + // new -o will overwrite previous ones + b.BuildFlags = b.BuildFlags + " -o " + b.Target + cmd := exec.Command("/bin/bash", "-c", "go build "+b.BuildFlags+" "+b.Packages) + 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)) + } + + 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)) + } + log.Println("Go build exit successful.") +} + +// determineOutputDir, as we only allow . as package name, +// the binary name is always same as the directory name of current directory +func (b *Build) determineOutputDir(outputDir string) string { + curWorkingDir, err := os.Getwd() + if err != nil { + log.Fatalf("Cannot get current working directory, the err: %v.", err) + } + // if + if outputDir == "" { + return curWorkingDir + } + abs, err := filepath.Abs(outputDir) + if err != nil { + log.Fatalf("Fail to transform the path: %v to absolute path, the error is: %v", outputDir, err) + } + return abs +} + +// validatePackageForBuild only allow . as package name +func (b *Build) validatePackageForBuild() bool { + if b.Packages == "." { + return true + } else { + return false } } - diff --git a/pkg/build/gomodules.go b/pkg/build/gomodules.go index 092856a..493a252 100644 --- a/pkg/build/gomodules.go +++ b/pkg/build/gomodules.go @@ -17,7 +17,8 @@ package build import ( - "log" + log "github.com/sirupsen/logrus" + "github.com/otiai10/copy" ) diff --git a/pkg/build/install.go b/pkg/build/install.go index bdf7b97..cb11720 100644 --- a/pkg/build/install.go +++ b/pkg/build/install.go @@ -18,14 +18,27 @@ package build import ( "fmt" - "log" + log "github.com/sirupsen/logrus" "os" "os/exec" ) +// NewInstall creates a Build struct which can install from goc temporary directory +func NewInstall(buildflags string, packages string) *Build { + b := &Build{ + BuildFlags: buildflags, + Packages: packages, + } + if false == b.validatePackageForInstall() { + log.Fatalln("packages only support . and ./...") + } + b.MvProjectsToTmp() + return b +} + func (b *Build) Install() { log.Println("Go building in temp...") - cmd := exec.Command("/bin/bash", "-c", "go install " + b.BuildFlags + " " + b.Packages) + cmd := exec.Command("/bin/bash", "-c", "go install "+b.BuildFlags+" "+b.Packages) cmd.Dir = b.TmpWorkingDir // Change the temp GOBIN, to force binary install to original place @@ -42,3 +55,11 @@ func (b *Build) Install() { } log.Printf("Go install successful. Binary installed in: %v", b.findWhereToInstall()) } + +func (b *Build) validatePackageForInstall() bool { + if b.Packages == "." || b.Packages == "./..." { + return true + } else { + return false + } +} diff --git a/pkg/build/legacy.go b/pkg/build/legacy.go index a4d4e08..13a499f 100644 --- a/pkg/build/legacy.go +++ b/pkg/build/legacy.go @@ -17,7 +17,7 @@ package build import ( - "log" + log "github.com/sirupsen/logrus" "os" "path/filepath" diff --git a/pkg/build/tmpfolder.go b/pkg/build/tmpfolder.go index efaafad..a43a35f 100644 --- a/pkg/build/tmpfolder.go +++ b/pkg/build/tmpfolder.go @@ -19,7 +19,8 @@ package build import ( "crypto/sha256" "fmt" - "log" + log "github.com/sirupsen/logrus" + "github.com/spf13/viper" "os" "path/filepath" "strings" @@ -27,7 +28,7 @@ import ( "github.com/qiniu/goc/pkg/cover" ) -func (b *Build) MvProjectsToTmp() (newGopath string, newWorkingDir string, tmpBuildDir string, pkgs map[string]*cover.Package) { +func (b *Build) MvProjectsToTmp() { listArgs := []string{"-json"} if len(b.BuildFlags) != 0 { listArgs = append(listArgs, b.BuildFlags) @@ -36,13 +37,13 @@ func (b *Build) MvProjectsToTmp() (newGopath string, newWorkingDir string, tmpBu b.Pkgs = cover.ListPackages(".", strings.Join(listArgs, " "), "") b.mvProjectsToTmp() - oriGopath := os.Getenv("GOPATH") + b.OriGOPATH = os.Getenv("GOPATH") if b.IsMod == true { b.NewGOPATH = "" - } else if oriGopath == "" { + } else if b.OriGOPATH == "" { b.NewGOPATH = b.TmpDir } else { - b.NewGOPATH = fmt.Sprintf("%v:%v", b.TmpDir, oriGopath) + b.NewGOPATH = fmt.Sprintf("%v:%v", b.TmpDir, b.OriGOPATH) } log.Printf("New GOPATH: %v", b.NewGOPATH) return @@ -88,6 +89,8 @@ func TmpFolderName(path string) string { // false go mod func (b *Build) checkIfLegacyProject() bool { for _, v := range b.Pkgs { + // get root + b.Root = v.Root if v.Module == nil { return true } @@ -145,3 +148,12 @@ func (b *Build) findWhereToInstall() string { } return filepath.Join(os.Getenv("HOME"), "go", "bin") } + +func (b *Build) RemoveTmpDir() { + debuggoc := viper.GetBool("debuggoc") + if debuggoc == false { + if b.TmpDir != "" { + os.RemoveAll(b.TmpDir) + } + } +} diff --git a/pkg/cover/cover.go b/pkg/cover/cover.go index 70e165c..d06b558 100644 --- a/pkg/cover/cover.go +++ b/pkg/cover/cover.go @@ -22,9 +22,9 @@ import ( "crypto/sha256" "encoding/json" "fmt" + log "github.com/sirupsen/logrus" "io" "io/ioutil" - "log" "os" "os/exec" "path" @@ -115,7 +115,7 @@ type PackageError struct { // ListPackages list all packages under specific via go list command // The argument newgopath is if you need to go list in a different GOPATH func ListPackages(dir string, args string, newgopath string) map[string]*Package { - cmd := exec.Command("/bin/bash", "-c", "go list " + args) + cmd := exec.Command("/bin/bash", "-c", "go list "+args) log.Printf("go list cmd is: %v", cmd.Args) cmd.Dir = dir if newgopath != "" { @@ -123,7 +123,7 @@ func ListPackages(dir string, args string, newgopath string) map[string]*Package } out, err := cmd.CombinedOutput() if err != nil { - log.Fatalf("excute `go list -json ./...` command failed, err: %v, out: %v", err, string(out)) + log.Fatalf("excute `go list -json ./...` command failed, err: %v, out: %v", err, string(out)) } dec := json.NewDecoder(bytes.NewReader(out)) diff --git a/pkg/cover/cover_test.go b/pkg/cover/cover_test.go index 27081d6..05dfb3d 100644 --- a/pkg/cover/cover_test.go +++ b/pkg/cover/cover_test.go @@ -18,7 +18,7 @@ package cover import ( "fmt" - "log" + log "github.com/sirupsen/logrus" "os" "os/exec" "path/filepath" diff --git a/pkg/cover/server.go b/pkg/cover/server.go index debe0e1..de96123 100644 --- a/pkg/cover/server.go +++ b/pkg/cover/server.go @@ -21,7 +21,7 @@ import ( "fmt" "io" "io/ioutil" - "log" + log "github.com/sirupsen/logrus" "net" "net/http" "net/url" diff --git a/pkg/cover/store.go b/pkg/cover/store.go index 2d6f971..f69d51f 100644 --- a/pkg/cover/store.go +++ b/pkg/cover/store.go @@ -19,7 +19,7 @@ package cover import ( "bufio" "fmt" - "log" + log "github.com/sirupsen/logrus" "os" "strings" "sync" diff --git a/pkg/qiniu/qnPresubmit.go b/pkg/qiniu/qnPresubmit.go index fdd75aa..203cb88 100644 --- a/pkg/qiniu/qnPresubmit.go +++ b/pkg/qiniu/qnPresubmit.go @@ -19,7 +19,7 @@ package qiniu import ( "encoding/json" "fmt" - "log" + log "github.com/sirupsen/logrus" "os" "path" "sort"