From b02d49c2be7a9ebd0c6ee03efeebff631939993a Mon Sep 17 00:00:00 2001 From: lyyyuna Date: Thu, 18 Jun 2020 16:20:54 +0800 Subject: [PATCH] enhance error handling --- cmd/build.go | 14 +++++------ cmd/build_test.go | 8 +++--- cmd/commonflags.go | 6 ++--- cmd/install.go | 10 ++++---- cmd/install_test.go | 13 ++++++---- cmd/list.go | 2 +- cmd/root.go | 9 +++++-- cmd/run.go | 9 +++++-- pkg/build/build.go | 35 ++++++++++++++++---------- pkg/build/build_test.go | 9 ++++--- pkg/build/errors.go | 1 + pkg/build/install.go | 19 +++++++++----- pkg/build/install_test.go | 5 ++-- pkg/build/tmpfolder.go | 25 +++++++++++++------ pkg/build/tmpfolder_test.go | 10 ++++---- pkg/cover/cover.go | 49 ++++++++++++++++++++++++++----------- 16 files changed, 143 insertions(+), 81 deletions(-) diff --git a/cmd/build.go b/cmd/build.go index 9bc6869..7bbec8f 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -17,7 +17,7 @@ package cmd import ( - "log" + log "github.com/sirupsen/logrus" "github.com/qiniu/goc/pkg/build" "github.com/qiniu/goc/pkg/cover" @@ -28,7 +28,7 @@ var buildCmd = &cobra.Command{ Use: "build", Short: "Do cover for all go files and execute go build command", Long: ` -First of all, this build command will copy the project code and its necessary dependencies to a temporary directory, then do cover for the target in this temporary directory, finally go build command will be executed and binaries generated to their original place. +Build command will copy the project code and its necessary dependencies to a temporary directory, then do cover for the target, binaries will be generated to their original place. `, Example: ` # Build the current binary with cover variables injected. The binary will be generated in the current folder. @@ -44,7 +44,7 @@ goc build --output /to/this/path goc build --buildflags="-ldflags '-extldflags -static' -tags='embed kodo'" `, Run: func(cmd *cobra.Command, args []string) { - runBuild() + runBuild(args) }, } @@ -52,14 +52,14 @@ 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") + buildCmd.Flags().StringVar(&buildOutput, "output", "", "it forces build to write the resulting executable to the named output file") rootCmd.AddCommand(buildCmd) } -func runBuild() { - gocBuild, err := build.NewBuild(buildFlags, packages, buildOutput) +func runBuild(args []string) { + gocBuild, err := build.NewBuild(buildFlags, args, buildOutput) if err != nil { - log.Fatalf("Fail to NewBuild: %v", err) + log.Fatalf("Fail to build: %v", err) } // remove temporary directory if needed defer gocBuild.Clean() diff --git a/cmd/build_test.go b/cmd/build_test.go index db005d6..407f8e5 100644 --- a/cmd/build_test.go +++ b/cmd/build_test.go @@ -17,13 +17,14 @@ package cmd import ( - "github.com/stretchr/testify/assert" "os" "os/exec" "path/filepath" "strings" "testing" "time" + + "github.com/stretchr/testify/assert" ) var baseDir string @@ -42,8 +43,9 @@ func TestGeneratedBinary(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - buildFlags, packages, buildOutput = "", ".", "" - runBuild() + buildFlags, buildOutput = "", "" + args := []string{"."} + runBuild(args) obj := filepath.Join(".", "simple-project") fInfo, err := os.Lstat(obj) diff --git a/cmd/commonflags.go b/cmd/commonflags.go index f18f622..65a6bce 100644 --- a/cmd/commonflags.go +++ b/cmd/commonflags.go @@ -11,8 +11,8 @@ var ( mode string debugGoc bool buildFlags string - packages string - appArgs string + // packages string + appArgs string goRunExecFlag string goRunArguments string @@ -35,14 +35,12 @@ func addCommonFlags(cmdset *pflag.FlagSet) { func addBuildFlags(cmdset *pflag.FlagSet) { addCommonFlags(cmdset) - cmdset.StringVar(&packages, "packages", ".", "specify the package name, only . and ./... are supported") // bind to viper viper.BindPFlags(cmdset) } func addRunFlags(cmdset *pflag.FlagSet) { addBuildFlags(cmdset) - cmdset.Lookup("packages").Usage = "specify the package name, only ., ./... and *.go are supported" cmdset.StringVar(&appArgs, "appargs", "", "specify the application's arguments") cmdset.StringVar(&goRunExecFlag, "exec", "", "same as -exec flag in 'go run' command") cmdset.StringVar(&goRunArguments, "arguments", "", "same as 'arguments' in 'go run' command") diff --git a/cmd/install.go b/cmd/install.go index 028230f..be9b7c2 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -27,7 +27,7 @@ var installCmd = &cobra.Command{ Use: "install", Short: "Do cover for all go files and execute go install command", Long: ` -First of all, this install command will copy the project code and its necessary dependencies to a temporary directory, then do cover for the target in this temporary directory, finally go install command will be executed and binaries generated to their original place. +Install command will copy the project code and its necessary dependencies to a temporary directory, then do cover for the target, binaries will be generated to their original place. `, Example: ` # Install all binaries with cover variables injected. The binary will be installed in $GOPATH/bin or $HOME/go/bin if directory existed. @@ -40,7 +40,7 @@ goc install --center=http://127.0.0.1:7777 goc build --buildflags="-ldflags '-extldflags -static' -tags='embed kodo'" `, Run: func(cmd *cobra.Command, args []string) { - runInstall() + runInstall(args) }, } @@ -49,10 +49,10 @@ func init() { rootCmd.AddCommand(installCmd) } -func runInstall() { - gocBuild, err := build.NewInstall(buildFlags, packages) +func runInstall(args []string) { + gocBuild, err := build.NewInstall(buildFlags, args) if err != nil { - log.Fatalf("Fail to NewInstall: %v", err) + log.Fatalf("Fail to install: %v", err) } // remove temporary directory if needed defer gocBuild.Clean() diff --git a/cmd/install_test.go b/cmd/install_test.go index 150d098..a64a221 100644 --- a/cmd/install_test.go +++ b/cmd/install_test.go @@ -17,13 +17,14 @@ package cmd import ( - "github.com/stretchr/testify/assert" "os" "os/exec" "path/filepath" "strings" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestInstalledBinaryForMod(t *testing.T) { @@ -36,8 +37,9 @@ func TestInstalledBinaryForMod(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - buildFlags, packages, buildOutput = "", ".", "" - runInstall() + buildFlags, buildOutput = "", "" + args := []string{"."} + runInstall(args) obj := filepath.Join(gopath, "bin", "simple-project") fInfo, err := os.Lstat(obj) @@ -64,8 +66,9 @@ func TestInstalledBinaryForLegacy(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - buildFlags, packages, buildOutput = "", ".", "" - runInstall() + buildFlags, buildOutput = "", "" + args := []string{"."} + runInstall(args) obj := filepath.Join(gopath, "bin", "simple_gopath_project") fInfo, err := os.Lstat(obj) diff --git a/cmd/list.go b/cmd/list.go index 194d486..5698596 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -42,6 +42,6 @@ goc list [flags] } func init() { - listCmd.Flags().StringVarP(¢er, "center", "", "http://127.0.0.1:7777", "cover profile host center") + addBasicFlags(listCmd.Flags()) rootCmd.AddCommand(listCmd) } diff --git a/cmd/root.go b/cmd/root.go index b0d50d1..09be748 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,7 +17,6 @@ package cmd import ( - "io/ioutil" "path/filepath" "runtime" "strconv" @@ -49,7 +48,13 @@ Find more information at: }) if debugGoc == false { // we only need log in debug mode - log.SetOutput(ioutil.Discard) + log.SetLevel(log.FatalLevel) + log.SetFormatter(&log.TextFormatter{ + DisableTimestamp: true, + CallerPrettyfier: func(f *runtime.Frame) (string, string) { + return "", "" + }, + }) } }, } diff --git a/cmd/run.go b/cmd/run.go index db65cd3..fe7ad4e 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -36,7 +36,10 @@ It is exactly behave as 'go run .' in addition of some internal goc features.`, goc run . `, Run: func(cmd *cobra.Command, args []string) { - gocBuild, _ := build.NewBuild(buildFlags, packages, buildOutput) + gocBuild, err := build.NewBuild(buildFlags, args, buildOutput) + if err != nil { + log.Fatalf("Fail to run: %v", err) + } gocBuild.GoRunExecFlag = goRunExecFlag gocBuild.GoRunArguments = goRunArguments defer gocBuild.Clean() @@ -53,7 +56,9 @@ goc run . // 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() + if err := gocBuild.Run(); err != nil { + log.Fatalln("Fail to run: %v", err) + } }, } diff --git a/pkg/build/build.go b/pkg/build/build.go index d8e2319..ec743a5 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -53,17 +53,23 @@ type Build struct { // 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, error) { +func NewBuild(buildflags string, args []string, outputDir string) (*Build, error) { + if len(args) > 1 { + log.Errorln(ErrTooManyArgs) + return nil, ErrTooManyArgs + } // buildflags = buildflags + " -o " + outputDir b := &Build{ BuildFlags: buildflags, - Packages: packages, + Packages: strings.Join(args, " "), } if false == b.validatePackageForBuild() { log.Errorln(ErrWrongPackageTypeForBuild) return nil, ErrWrongPackageTypeForBuild } - b.MvProjectsToTmp() + if err := b.MvProjectsToTmp(); err != nil { + return nil, err + } dir, err := b.determineOutputDir(outputDir) b.Target = dir if err != nil { @@ -90,13 +96,13 @@ func (b *Build) Build() error { err := cmd.Start() if err != nil { log.Errorf("Fail to execute: %v. The error is: %v", cmd.Args, err) - return fmt.Errorf("fail to execute: %v: %w", cmd.Args, err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) } if err = cmd.Wait(); err != nil { log.Errorf("go build failed. The error is: %v", err) - return fmt.Errorf("go build faileds: %w", err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) } - log.Println("Go build exit successful.") + log.Infoln("Go build exit successful.") return nil } @@ -110,7 +116,7 @@ func (b *Build) determineOutputDir(outputDir string) (string, error) { curWorkingDir, err := os.Getwd() if err != nil { log.Errorf("Cannot get current working directory: %v", err) - return "", fmt.Errorf("cannot get current working directory: %w", err) + return "", err } if outputDir == "" { @@ -125,21 +131,21 @@ func (b *Build) determineOutputDir(outputDir string) (string, error) { abs, err := filepath.Abs(outputDir) if err != nil { log.Errorf("Fail to transform the path: %v to absolute path: %v", outputDir, err) - return "", fmt.Errorf("fail to transform the path %v to absolute path: %w", outputDir, err) + return "", err } return abs, nil } // validatePackageForBuild only allow . as package name func (b *Build) validatePackageForBuild() bool { - if b.Packages == "." { + if b.Packages == "." || b.Packages == "" { return true } return false } // Run excutes the main package in addition with the internal goc features -func (b *Build) Run() { +func (b *Build) Run() error { cmd := exec.Command("/bin/bash", "-c", "go run "+b.BuildFlags+" "+b.GoRunExecFlag+" "+b.Packages+" "+b.GoRunArguments) cmd.Dir = b.TmpWorkingDir @@ -148,16 +154,19 @@ func (b *Build) Run() { cmd.Env = append(os.Environ(), fmt.Sprintf("GOPATH=%v", b.NewGOPATH)) } - log.Printf("go build cmd is: %v", cmd.Args) + log.Infof("go build cmd is: %v", cmd.Args) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Start() if err != nil { - log.Fatalf("Fail to start command: %v. The error is: %v", cmd.Args, err) + log.Errorf("Fail to start command: %v. The error is: %v", cmd.Args, err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) } if err = cmd.Wait(); err != nil { - log.Fatalf("Fail to execute command: %v. The error is: %v", cmd.Args, err) + log.Errorf("Fail to go run: %v. The error is: %v", cmd.Args, err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) } + return nil } diff --git a/pkg/build/build_test.go b/pkg/build/build_test.go index fa25263..853978f 100644 --- a/pkg/build/build_test.go +++ b/pkg/build/build_test.go @@ -17,10 +17,11 @@ package build import ( - "github.com/stretchr/testify/assert" "os" "path/filepath" "testing" + + "github.com/stretchr/testify/assert" ) func TestInvalidPackage(t *testing.T) { @@ -32,7 +33,7 @@ func TestInvalidPackage(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - _, err := NewBuild("", "example.com/simple-project", "") + _, err := NewBuild("", []string{"example.com/simple-project"}, "") assert.Equal(t, err, ErrWrongPackageTypeForBuild, "the package name should be invalid") } @@ -44,8 +45,8 @@ func TestBasicBuildForModProject(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - buildFlags, packages, buildOutput := "", ".", "" - gocBuild, err := NewBuild(buildFlags, packages, buildOutput) + buildFlags, args, buildOutput := "", []string{"."}, "" + gocBuild, err := NewBuild(buildFlags, args, buildOutput) assert.Equal(t, err, nil, "should create temporary directory successfully") err = gocBuild.Build() diff --git a/pkg/build/errors.go b/pkg/build/errors.go index c46cec7..eef49b5 100644 --- a/pkg/build/errors.go +++ b/pkg/build/errors.go @@ -9,6 +9,7 @@ var ( ErrGocShouldExecInProject = errors.New("goc not executed in project directory") ErrWrongPackageTypeForInstall = errors.New("packages only support \".\" and \"./...\"") ErrWrongPackageTypeForBuild = errors.New("packages only support \".\"") + ErrTooManyArgs = errors.New("too many args") ErrWrongCallSequence = errors.New("function should be called in a specified sequence") ErrNoplaceToInstall = errors.New("no go env") ) diff --git a/pkg/build/install.go b/pkg/build/install.go index 5d20687..c6b9fa5 100644 --- a/pkg/build/install.go +++ b/pkg/build/install.go @@ -20,21 +20,28 @@ import ( "fmt" "os" "os/exec" + "strings" log "github.com/sirupsen/logrus" ) // NewInstall creates a Build struct which can install from goc temporary directory -func NewInstall(buildflags string, packages string) (*Build, error) { +func NewInstall(buildflags string, args []string) (*Build, error) { + if len(args) > 1 { + log.Errorf("Too many args") + return nil, ErrTooManyArgs + } b := &Build{ BuildFlags: buildflags, - Packages: packages, + Packages: strings.Join(args, " "), } if false == b.validatePackageForInstall() { log.Errorln(ErrWrongPackageTypeForInstall) return nil, ErrWrongPackageTypeForInstall } - b.MvProjectsToTmp() + if err := b.MvProjectsToTmp(); err != nil { + return nil, err + } return b, nil } @@ -61,18 +68,18 @@ func (b *Build) Install() error { err = cmd.Start() if err != nil { log.Errorf("Fail to execute: %v. The error is: %v", cmd.Args, err) - return fmt.Errorf("fail to execute: %v: %w", cmd.Args, err) + return err } if err = cmd.Wait(); err != nil { log.Errorf("go install failed. The error is: %v", err) - return fmt.Errorf("go install failed: %w", err) + return err } log.Infof("Go install successful. Binary installed in: %v", whereToInstall) return nil } func (b *Build) validatePackageForInstall() bool { - if b.Packages == "." || b.Packages == "./..." { + if b.Packages == "." || b.Packages == "" || b.Packages == "./..." { return true } return false diff --git a/pkg/build/install_test.go b/pkg/build/install_test.go index 9108b3f..8f08b71 100644 --- a/pkg/build/install_test.go +++ b/pkg/build/install_test.go @@ -1,10 +1,11 @@ package build import ( - "github.com/stretchr/testify/assert" "os" "path/filepath" "testing" + + "github.com/stretchr/testify/assert" ) func TestBasicInstallForModProject(t *testing.T) { @@ -15,7 +16,7 @@ func TestBasicInstallForModProject(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - buildFlags, packages := "", "." + buildFlags, packages := "", []string{"."} gocBuild, err := NewInstall(buildFlags, packages) assert.Equal(t, err, nil, "should create temporary directory successfully") diff --git a/pkg/build/tmpfolder.go b/pkg/build/tmpfolder.go index 166035e..f9f48a6 100644 --- a/pkg/build/tmpfolder.go +++ b/pkg/build/tmpfolder.go @@ -29,15 +29,24 @@ import ( "github.com/spf13/viper" ) -func (b *Build) MvProjectsToTmp() { +func (b *Build) MvProjectsToTmp() error { listArgs := []string{"-json"} if len(b.BuildFlags) != 0 { listArgs = append(listArgs, b.BuildFlags) } listArgs = append(listArgs, "./...") - b.Pkgs = cover.ListPackages(".", strings.Join(listArgs, " "), "") + var err error + b.Pkgs, err = cover.ListPackages(".", strings.Join(listArgs, " "), "") + if err != nil { + log.Errorln(err) + return err + } - b.mvProjectsToTmp() + err = b.mvProjectsToTmp() + if err != nil { + log.Errorf("Fail to move the project to temporary directory") + return err + } b.OriGOPATH = os.Getenv("GOPATH") if b.IsMod == true { b.NewGOPATH = "" @@ -53,8 +62,8 @@ func (b *Build) MvProjectsToTmp() { if b.Root == "" && b.IsMod == false { b.NewGOPATH = b.OriGOPATH } - log.Printf("New GOPATH: %v", b.NewGOPATH) - return + log.Infof("New GOPATH: %v", b.NewGOPATH) + return nil } func (b *Build) mvProjectsToTmp() error { @@ -84,7 +93,7 @@ func (b *Build) mvProjectsToTmp() error { b.TmpWorkingDir, err = b.getTmpwd() if err != nil { log.Errorf("fail to get workding directory in temporary directory: %v", err) - return fmt.Errorf("fail to get workding directory in temporary directory: %w", err) + return fmt.Errorf("getTmpwd failed with error: %w", err) } // issue #14 // if b.Root == "", then the project is non-standard project @@ -109,7 +118,7 @@ func TmpFolderName(path string) string { sum := sha256.Sum256([]byte(path)) h := fmt.Sprintf("%x", sum[:6]) - return "goc-" + h + return "goc-build-" + h } // traversePkgsList travse the Build.Pkgs list @@ -128,7 +137,7 @@ func (b *Build) traversePkgsList() (isMod bool, root string, err error) { isMod = true return } - log.Error("should not reach here") + log.Error(ErrShouldNotReached) err = ErrShouldNotReached return } diff --git a/pkg/build/tmpfolder_test.go b/pkg/build/tmpfolder_test.go index ed4f4b8..2021c78 100644 --- a/pkg/build/tmpfolder_test.go +++ b/pkg/build/tmpfolder_test.go @@ -39,7 +39,7 @@ func TestNewDirParseInLegacyProject(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - b, _ := NewInstall("", ".") + b, _ := NewInstall("", []string{"."}) if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -48,7 +48,7 @@ func TestNewDirParseInLegacyProject(t *testing.T) { t.Fatalf("The New GOPATH is wrong. newgopath: %v, tmpdir: %v", b.NewGOPATH, b.TmpDir) } - b, _ = NewBuild("", ".", "") + b, _ = NewBuild("", []string{"."}, "") if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -67,7 +67,7 @@ func TestNewDirParseInModProject(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - b, _ := NewInstall("", ".") + b, _ := NewInstall("", []string{"."}) if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -76,7 +76,7 @@ func TestNewDirParseInModProject(t *testing.T) { t.Fatalf("The New GOPATH is wrong. newgopath: %v, tmpdir: %v", b.NewGOPATH, b.TmpDir) } - b, _ = NewBuild("", ".", "") + b, _ = NewBuild("", []string{"."}, "") if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -96,7 +96,7 @@ func TestLegacyProjectNotInGoPATH(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - b, _ := NewBuild("", ".", "") + b, _ := NewBuild("", []string{"."}, "") if b.OriGOPATH != b.NewGOPATH { t.Fatalf("New GOPATH should be same with old GOPATH, for this kind of project. New: %v, old: %v", b.NewGOPATH, b.OriGOPATH) } diff --git a/pkg/cover/cover.go b/pkg/cover/cover.go index e28ae66..688095f 100644 --- a/pkg/cover/cover.go +++ b/pkg/cover/cover.go @@ -21,6 +21,7 @@ import ( "bytes" "crypto/sha256" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -37,6 +38,11 @@ import ( "github.com/sirupsen/logrus" ) +var ( + ErrCoverPkgFailed = errors.New("fail to inject code to project") + ErrCoverListFailed = errors.New("fail to list package dependencies") +) + // TestCover is a collection of all counters type TestCover struct { Mode string @@ -114,9 +120,10 @@ type PackageError struct { } //Execute execute go tool cover for all the .go files in the target folder -func Execute(args, newGopath, target, mode, center string) { +func Execute(args, newGopath, target, mode, center string) error { if !isDirExist(target) { - log.Fatalf("target directory %s not exist", target) + log.Errorf("Target directory %s not exist", target) + return ErrCoverPkgFailed } listArgs := []string{"-json"} @@ -124,7 +131,11 @@ func Execute(args, newGopath, target, mode, center string) { listArgs = append(listArgs, args) } listArgs = append(listArgs, "./...") - pkgs := ListPackages(target, strings.Join(listArgs, " "), newGopath) + pkgs, err := ListPackages(target, strings.Join(listArgs, " "), newGopath) + if err != nil { + log.Errorf("Fail to list all packages, the error: %v", err) + return err + } var seen = make(map[string]*PackageCover) var seenCache = make(map[string]*PackageCover) @@ -134,7 +145,8 @@ func Execute(args, newGopath, target, mode, center string) { // inject the main package mainCover, err := AddCounters(pkg, mode, newGopath) if err != nil { - log.Fatalf("failed to add counters for pkg %s, err: %v", pkg.ImportPath, err) + log.Errorf("failed to add counters for pkg %s, err: %v", pkg.ImportPath, err) + return ErrCoverPkgFailed } // new a testcover for this service @@ -158,7 +170,7 @@ func Execute(args, newGopath, target, mode, center string) { if hasInternalPath(dep) { //scan exist cache cover to tc.CacheCover if cache, ok := seenCache[dep]; ok { - log.Printf("cache cover exist: %s", cache.Package.ImportPath) + log.Infof("cache cover exist: %s", cache.Package.ImportPath) tc.CacheCover[cache.Package.Dir] = cache continue } @@ -166,7 +178,8 @@ func Execute(args, newGopath, target, mode, center string) { // add counter for internal package inPkgCover, err := AddCounters(depPkg, mode, newGopath) if err != nil { - log.Fatalf("failed to add counters for internal pkg %s, err: %v", depPkg.ImportPath, err) + log.Errorf("failed to add counters for internal pkg %s, err: %v", depPkg.ImportPath, err) + return ErrCoverPkgFailed } parentDir := getInternalParent(depPkg.Dir) parentImportPath := getInternalParent(depPkg.ImportPath) @@ -212,7 +225,8 @@ func Execute(args, newGopath, target, mode, center string) { packageCover, err := AddCounters(depPkg, mode, newGopath) if err != nil { - log.Fatalf("failed to add counters for pkg %s, err: %v", depPkg.ImportPath, err) + log.Errorf("failed to add counters for pkg %s, err: %v", depPkg.ImportPath, err) + return err } tc.DepsCover = append(tc.DepsCover, packageCover) seen[dep] = packageCover @@ -220,21 +234,25 @@ func Execute(args, newGopath, target, mode, center string) { } if errs := InjectCacheCounters(internalPkgCache, tc.CacheCover); len(errs) > 0 { - log.Fatalf("failed to inject cache counters for package: %s, err: %v", pkg.ImportPath, errs) + log.Errorf("failed to inject cache counters for package: %s, err: %v", pkg.ImportPath, errs) + return ErrCoverPkgFailed } // inject Http Cover APIs var httpCoverApis = fmt.Sprintf("%s/http_cover_apis_auto_generated.go", pkg.Dir) if err := InjectCountersHandlers(tc, httpCoverApis); err != nil { - log.Fatalf("failed to inject counters for package: %s, err: %v", pkg.ImportPath, err) + log.Errorf("failed to inject counters for package: %s, err: %v", pkg.ImportPath, err) + return ErrCoverPkgFailed } } } + + return nil } // 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 { +func ListPackages(dir string, args string, newgopath string) (map[string]*Package, error) { cmd := exec.Command("/bin/bash", "-c", "go list "+args) log.Printf("go list cmd is: %v", cmd.Args) cmd.Dir = dir @@ -243,7 +261,8 @@ 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.Errorf("excute `go list -json ./...` command failed, err: %v, out: %v", err, string(out)) + return nil, ErrCoverListFailed } dec := json.NewDecoder(bytes.NewReader(out)) @@ -254,10 +273,12 @@ func ListPackages(dir string, args string, newgopath string) map[string]*Package if err == io.EOF { break } - log.Fatalf("reading go list output: %v", err) + log.Errorf("reading go list output: %v", err) + return nil, ErrCoverListFailed } if pkg.Error != nil { - log.Fatalf("list package %s failed with output: %v", pkg.ImportPath, pkg.Error) + log.Errorf("list package %s failed with output: %v", pkg.ImportPath, pkg.Error) + return nil, ErrCoverPkgFailed } // for _, err := range pkg.DepsErrors { @@ -266,7 +287,7 @@ func ListPackages(dir string, args string, newgopath string) map[string]*Package pkgs[pkg.ImportPath] = &pkg } - return pkgs + return pkgs, nil } // AddCounters add counters for all go files under the package