diff --git a/README.md b/README.md index cd31651..79ba459 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ It only covers the most common items, and tries to guess sensible defaults. Press ^C at any time to quit. tool: (go_install) go_build Do you want to continue?[y/n] y -package: (main) github.com/voidint/gbb/build +importpath: (main) github.com/voidint/gbb/build variable: Date value: {{.Date}} Do you want to continue?[y/n] y @@ -219,7 +219,7 @@ About to write to /Users/voidint/cloud/workspace/go/lib/src/github.com/voidint/g { "version": "0.2.0", "tool": "go build", - "package": "github.com/voidint/gbb/build", + "importpath": "github.com/voidint/gbb/build", "variables": [ { "variable": "Date", @@ -261,7 +261,7 @@ commit: db8b606cfc2b24a24e2e09acac24a52c47b68401 { "version": "0.2.0", "tool": "go build", - "package": "github.com/voidint/gbb/build", + "importpath": "github.com/voidint/gbb/build", "variables": [ { "variable": "Date", @@ -289,6 +289,10 @@ commit: db8b606cfc2b24a24e2e09acac24a52c47b68401 ## changelog +### 0.4.0 - +- `gbb.json`中的配置项`package`重命名为`importpath`。[#9](https://github.com/voidint/gbb/issues/9) +- 新增命令行选项`--config`用于自定义配置文件路径。[#16](https://github.com/voidint/gbb/issues/16) + ### 0.3.0 - 2017/01/09 - 若开启debug模式`gbb --debug`,那么变量表达式求值过程详情也一并输出。[#12](https://github.com/voidint/gbb/issues/12) [#6](https://github.com/voidint/gbb/issues/6) - 变量表达式首字母大写。[#11](https://github.com/voidint/gbb/issues/11) diff --git a/tool/builder.go b/tool/builder.go index 6db72cf..ebe9172 100644 --- a/tool/builder.go +++ b/tool/builder.go @@ -35,44 +35,25 @@ func Build(conf *config.Config, dir string) error { // buildDir 切换到指定工作目录,调用指定的编译工具进行编译。 func buildDir(conf *config.Config, dir string) (err error) { - wd, err := os.Getwd() - if err != nil { + if err = chdir(dir, conf.Debug); err != nil { return err } - if wd != dir { - if conf.Debug { - fmt.Printf("==> cd %s\n", dir) - } - if err = os.Chdir(dir); err != nil { - return err - } - } cmdArgs := strings.Fields(conf.Tool) // go install ==> []string{"go", "install"} - var buf bytes.Buffer - for i := range conf.Variables { - varName := strings.TrimSpace(conf.Variables[i].Variable) - varExpr := strings.TrimSpace(conf.Variables[i].Value) - - if conf.Debug { - fmt.Printf("==> eval(%q)\n", varExpr) - } - val, err := variable.Eval(varExpr, conf.Debug) + mainPkg, err := isMainPkg(dir) + if err != nil { + return err + } + if mainPkg { + flags, err := ldflags(conf) if err != nil { return err } - if conf.Debug { - fmt.Println(val) - } - buf.WriteString(fmt.Sprintf(`-X "%s.%s=%s"`, conf.Importpath, varName, val)) - if i < len(conf.Variables)-1 { - buf.WriteByte(' ') + if flags != "" { + cmdArgs = append(cmdArgs, "-ldflags", flags) } } - if buf.Len() > 0 { - cmdArgs = append(cmdArgs, "-ldflags", buf.String()) - } if conf.Debug { fmt.Print("==> ", cmdArgs[0]) @@ -92,3 +73,42 @@ func buildDir(conf *config.Config, dir string) (err error) { cmd.Stderr = os.Stderr return cmd.Run() } + +func chdir(dir string, debug bool) (err error) { + wd, err := os.Getwd() + if err != nil { + return err + } + if wd == dir { + return nil + } + + if debug { + fmt.Printf("==> cd %s\n", dir) + } + return os.Chdir(dir) +} + +func ldflags(conf *config.Config) (flags string, err error) { + var buf bytes.Buffer + for i := range conf.Variables { + varName := strings.TrimSpace(conf.Variables[i].Variable) + varExpr := strings.TrimSpace(conf.Variables[i].Value) + + if conf.Debug { + fmt.Printf("==> eval(%q)\n", varExpr) + } + val, err := variable.Eval(varExpr, conf.Debug) + if err != nil { + return "", err + } + if conf.Debug { + fmt.Println(val) + } + buf.WriteString(fmt.Sprintf(`-X "%s.%s=%s"`, conf.Importpath, varName, val)) + if i < len(conf.Variables)-1 { + buf.WriteByte(' ') + } + } + return buf.String(), nil +} diff --git a/tool/golang.go b/tool/golang.go index b8cc721..349727e 100644 --- a/tool/golang.go +++ b/tool/golang.go @@ -4,7 +4,6 @@ import ( "go/ast" "go/parser" "go/token" - "io/ioutil" "os" "path/filepath" "runtime" @@ -27,7 +26,7 @@ func NewGoBuilder(conf *config.Config) *GoBuilder { // Build 切换到指定工作目录后调用编译工具编译。 func (b *GoBuilder) Build(rootDir string) error { - paths, err := walkMainDir(rootDir) + paths, err := walkPkgs(rootDir) if err != nil { return err } @@ -40,7 +39,7 @@ func (b *GoBuilder) Build(rootDir string) error { } // 查找root及其子孙目录下所有的main包路径 -func walkMainDir(rootDir string) (paths []string, err error) { +func walkMainPkgs(rootDir string) (paths []string, err error) { return paths, filepath.Walk(rootDir, func(path string, info os.FileInfo, e error) error { if e != nil { return e @@ -92,7 +91,7 @@ func hasMain(srcfile string) (bool, error) { return false, nil } -func walkPkgDir(rootDir string) (paths []string, err error) { +func walkPkgs(rootDir string) (paths []string, err error) { return paths, filepath.Walk(rootDir, func(path string, info os.FileInfo, e error) error { if e != nil { return e @@ -120,22 +119,45 @@ func walkPkgDir(rootDir string) (paths []string, err error) { // isGoPkg 判断路径是否是golang的包 func isGoPkg(path string) (yes bool, err error) { - path = strings.TrimSpace(path) + // path = strings.TrimSpace(path) + // if path == "" { + // return false, nil + // } + // infos, err := ioutil.ReadDir(path) + // if err != nil { + // return false, err + // } + + // for i := range infos { + // if infos[i].IsDir() { + // continue + // } + // if ext := filepath.Ext(infos[i].Name()); ext == ".go" { // TODO 排除go test目录 + // return true, nil + // } + // } + // return false, nil + if path == "" { return false, nil } - infos, err := ioutil.ReadDir(path) + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, path, nil, 0) if err != nil { return false, err } + return len(pkgs) > 0, nil +} - for i := range infos { - if infos[i].IsDir() { - continue - } - if ext := filepath.Ext(infos[i].Name()); ext == ".go" { // TODO 排除go test目录 - return true, nil - } +func isMainPkg(path string) (yes bool, err error) { + if path == "" { + return false, nil } - return false, nil + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, path, nil, 0) + if err != nil { + return false, err + } + _, yes = pkgs["main"] + return yes, nil } diff --git a/tool/golang_test.go b/tool/golang_test.go index 665a5b3..45421f5 100644 --- a/tool/golang_test.go +++ b/tool/golang_test.go @@ -32,13 +32,13 @@ func TestHasMain(t *testing.T) { }) } -func TestWalkMainDir(t *testing.T) { +func TestWalkMainPkgs(t *testing.T) { Convey("遍历根目录及其子目录查找包含main函数的源代码文件路径", t, func() { dir, err := os.Getwd() So(err, ShouldBeNil) So(strings.HasSuffix(dir, filepath.Join("src", "github.com", "voidint", "gbb", "tool")), ShouldBeTrue) workspace := strings.TrimRight(dir, fmt.Sprintf("%ctool", os.PathSeparator)) - paths, err := walkMainDir(workspace) + paths, err := walkMainPkgs(workspace) So(err, ShouldBeNil) So(paths, ShouldNotBeEmpty) So(len(paths), ShouldEqual, 1) @@ -46,17 +46,17 @@ func TestWalkMainDir(t *testing.T) { }) } -func TestWalkPkgDir(t *testing.T) { +func TestWalkPkgs(t *testing.T) { Convey("查找指定目录及其子目录下所有满足golang包的目录路径", t, func() { wd, err := os.Getwd() So(err, ShouldBeNil) - paths, err := walkPkgDir(wd) + paths, err := walkPkgs(wd) So(err, ShouldBeNil) So(paths, ShouldNotBeEmpty) So(len(paths), ShouldEqual, 1) So(paths[0], ShouldEqual, wd) - paths, err = walkPkgDir(strings.TrimRight(wd, "tool")) + paths, err = walkPkgs(strings.TrimRight(wd, "tool")) So(err, ShouldBeNil) So(paths, ShouldNotBeEmpty) So(len(paths), ShouldEqual, 7) @@ -75,7 +75,7 @@ func TestWalkPkgDir(t *testing.T) { }) defer monkey.Unpatch(isGoPkg) - paths, err := walkPkgDir(wd) + paths, err := walkPkgs(wd) So(err, ShouldNotBeNil) So(err, ShouldEqual, ErrIsGoPkg) So(paths, ShouldBeEmpty) @@ -130,3 +130,61 @@ func TestIsGoPkg(t *testing.T) { }) }) } + +func TestIsMainPkg(t *testing.T) { + Convey("检查指定路径是否是main包", t, func() { + wd, err := os.Getwd() + So(err, ShouldBeNil) + So(wd, ShouldNotBeBlank) + + Convey("合法路径", func() { + Convey("非main包且不包含子包", func() { + yes, err := isMainPkg(wd) + So(err, ShouldBeNil) + So(yes, ShouldBeFalse) + }) + Convey("非main包且包含子包", func() { + path := filepath.Join( + strings.TrimRight(wd, "tool"), + "vendor", "github.com", "smartystreets", "assertions", + ) + yes, err := isMainPkg(path) + So(err, ShouldBeNil) + So(yes, ShouldBeFalse) + }) + + Convey("main包", func() { + yes, err := isMainPkg(strings.TrimRight(wd, "tool")) + So(err, ShouldBeNil) + So(yes, ShouldBeTrue) + }) + }) + + Convey("非法路径", func() { + Convey("路径为空", func() { + yes, err := isMainPkg("") + So(err, ShouldBeNil) + So(yes, ShouldBeFalse) + }) + Convey("路径非目录", func() { + yes, err := isMainPkg(filepath.Join(wd, "golang_test.go")) + So(err, ShouldNotBeNil) + So(yes, ShouldBeFalse) + }) + Convey("路径不存在", func() { + yes, err := isMainPkg(filepath.Join(wd, "not_exist_dir")) + So(err, ShouldNotBeNil) + So(yes, ShouldBeFalse) + }) + Convey("路径下不包含go源文件(非包路径)", func() { + path := filepath.Join( + strings.TrimRight(wd, "tool"), + "vendor", "github.com", + ) + yes, err := isMainPkg(path) + So(err, ShouldBeNil) + So(yes, ShouldBeFalse) + }) + }) + }) +}