diff --git a/realize.go b/realize.go index 35bec6a..c3e4eee 100644 --- a/realize.go +++ b/realize.go @@ -542,50 +542,6 @@ func setup(c *cli.Context) (err error) { return nil }, }, - { - Before: func(d interact.Context) error { - d.SetDef(false, realize.Green.Regular("(n)")) - return nil - }, - Quest: interact.Quest{ - Options: realize.Yellow.Regular("[y/n]"), - Msg: "Enable go fix", - Resolve: func(d interact.Context) bool { - val, _ := d.Ans().Bool() - return val - }, - }, - Subs: []*interact.Question{ - { - Before: func(d interact.Context) error { - d.SetDef("", realize.Green.Regular("(none)")) - return nil - }, - Quest: interact.Quest{ - Options: realize.Yellow.Regular("[string]"), - Msg: "Fix additional arguments", - }, - Action: func(d interact.Context) interface{} { - val, err := d.Ans().String() - if err != nil { - return d.Err() - } - if val != "" { - r.Schema.Projects[len(r.Schema.Projects)-1].Tools.Fix.Args = append(r.Schema.Projects[len(r.Schema.Projects)-1].Tools.Fix.Args, val) - } - return nil - }, - }, - }, - Action: func(d interact.Context) interface{} { - val, err := d.Ans().Bool() - if err != nil { - return d.Err() - } - r.Schema.Projects[len(r.Schema.Projects)-1].Tools.Fix.Status = val - return nil - }, - }, { Before: func(d interact.Context) error { d.SetDef(false, realize.Green.Regular("(n)")) diff --git a/realize/cli.go b/realize/cli.go index 8e38f3a..1bffaca 100644 --- a/realize/cli.go +++ b/realize/cli.go @@ -3,14 +3,15 @@ package realize import ( "fmt" "github.com/fsnotify/fsnotify" + "github.com/go-siris/siris/core/errors" "go/build" "log" "os" "os/signal" "path/filepath" "strings" + "sync" "time" - "github.com/go-siris/siris/core/errors" ) var ( @@ -71,11 +72,11 @@ func init() { } // Stop realize workflow -func (r *Realize) Stop() error{ - if r.exit != nil{ +func (r *Realize) Stop() error { + if r.exit != nil { close(r.exit) return nil - }else{ + } else { return errors.New("exit chan undefined") } } @@ -83,22 +84,19 @@ func (r *Realize) Stop() error{ // Start realize workflow func (r *Realize) Start() error { if len(r.Schema.Projects) > 0 { + var wg sync.WaitGroup r.exit = make(chan os.Signal, 1) signal.Notify(r.exit, os.Interrupt) + wg.Add(len(r.Schema.Projects)) for k := range r.Schema.Projects { r.Schema.Projects[k].parent = r - go r.Schema.Projects[k].Watch(r.exit) + go r.Schema.Projects[k].Watch(&wg) } - for { - select { - case <-r.exit: - return nil - } - } - return nil - }else{ + wg.Wait() + } else { return errors.New("there are no projects") } + return nil } // Prefix a given string with tool name diff --git a/realize/cli_test.go b/realize/cli_test.go index a856f35..406826c 100644 --- a/realize/cli_test.go +++ b/realize/cli_test.go @@ -22,10 +22,10 @@ func TestRealize_Stop(t *testing.T) { func TestRealize_Start(t *testing.T) { r := Realize{} err := r.Start() - if err == nil{ + if err == nil { t.Error("Error expected") } - r.Projects = append(r.Projects,Project{Name:"test"}) + r.Projects = append(r.Projects, Project{Name: "test"}) go func() { time.Sleep(100) close(r.exit) @@ -35,7 +35,7 @@ func TestRealize_Start(t *testing.T) { } }() err = r.Start() - if err != nil{ + if err != nil { t.Error("Unexpected error", err) } } diff --git a/realize/projects.go b/realize/projects.go index abb2343..e9a5368 100644 --- a/realize/projects.go +++ b/realize/projects.go @@ -15,6 +15,7 @@ import ( "regexp" "strconv" "strings" + "sync" "time" ) @@ -270,7 +271,7 @@ func (p *Project) Reload(path string, stop <-chan bool) { } // Watch a project -func (p *Project) Watch(exit chan os.Signal) { +func (p *Project) Watch(wg *sync.WaitGroup) { var err error // change channel p.stop = make(chan bool) @@ -304,7 +305,7 @@ L: close(p.stop) p.stop = make(chan bool) p.Change(event) - go p.Reload( "", p.stop) + go p.Reload("", p.stop) } default: if p.Validate(event.Name, true) { @@ -331,11 +332,12 @@ L: } case err := <-p.watcher.Errors(): p.Err(err) - case <-exit: + case <-p.parent.exit: p.After() break L } } + wg.Done() } // Validate a file path @@ -462,17 +464,12 @@ func (p *Project) cmd(stop <-chan bool, flag string, global bool) { return case r := <-result: msg = fmt.Sprintln(p.pname(p.Name, 5), ":", Green.Bold("Command"), Green.Bold("\"")+r.Name+Green.Bold("\"")) - out = BufferOut{Time: time.Now(), Text: r.Name, Type: flag} if r.Err != nil { - p.stamp("error", out, msg, "") out = BufferOut{Time: time.Now(), Text: r.Err.Error(), Type: flag} - p.stamp("error", out, "", fmt.Sprintln(Red.Regular(r.Err.Error()))) - } - if r.Out != "" { - out = BufferOut{Time: time.Now(), Text: r.Out, Type: flag} - p.stamp("log", out, "", fmt.Sprintln(r.Out)) + p.stamp("error", out, msg, fmt.Sprint(Red.Regular(r.Err.Error()))) } else { - p.stamp("log", out, msg, "") + out = BufferOut{Time: time.Now(), Text: r.Out, Type: flag} + p.stamp("log", out, msg, fmt.Sprint(r.Out)) } } } diff --git a/realize/projects_test.go b/realize/projects_test.go index 0ce21aa..49ab4a5 100644 --- a/realize/projects_test.go +++ b/realize/projects_test.go @@ -3,16 +3,17 @@ package realize import ( "bytes" "errors" + "github.com/fsnotify/fsnotify" "log" "os" - "strings" - "testing" - "github.com/fsnotify/fsnotify" "os/signal" + "strings" + "sync" + "testing" "time" ) -func TestProject_After(t *testing.T) /**/{ +func TestProject_After(t *testing.T) /**/ { var buf bytes.Buffer log.SetOutput(&buf) r := Realize{} @@ -85,7 +86,7 @@ func TestProject_Change(t *testing.T) { r.Change = func(context Context) { log.Println(context.Event.Name) } - event := fsnotify.Event{Name:"test",Op:fsnotify.Write} + event := fsnotify.Event{Name: "test", Op: fsnotify.Write} r.Projects[0].Change(event) if !strings.Contains(buf.String(), event.Name) { t.Error("Unexpected error") @@ -100,12 +101,12 @@ func TestProject_Reload(t *testing.T) { parent: &r, }) input := "test/path" - r.Projects[0].watcher, _ = NewFileWatcher(false,0) + r.Projects[0].watcher, _ = NewFileWatcher(false, 0) r.Reload = func(context Context) { log.Println(context.Path) } stop := make(chan bool) - r.Projects[0].Reload(input,stop) + r.Projects[0].Reload(input, stop) if !strings.Contains(buf.String(), input) { t.Error("Unexpected error") } @@ -113,14 +114,14 @@ func TestProject_Reload(t *testing.T) { func TestProject_Validate(t *testing.T) { data := map[string]bool{ - "": false, - "/test/.path/": false, - "./test/path/": false, - "/test/path/test.html": false, - "/test/path/test.go": false, - "/test/ignore/test.go": false, + "": false, + "/test/.path/": false, + "./test/path/": false, + "/test/path/test.html": false, + "/test/path/test.go": false, + "/test/ignore/test.go": false, "/test/check/notexist.go": false, - "/test/check/exist.go": false, + "/test/check/exist.go": false, } r := Realize{} r.Projects = append(r.Projects, Project{ @@ -130,22 +131,26 @@ func TestProject_Validate(t *testing.T) { }, }) for i, v := range data { - if r.Projects[0].Validate(i,true) != v{ - t.Error("Unexpected error",i,"expected",v) + if r.Projects[0].Validate(i, true) != v { + t.Error("Unexpected error", i, "expected", v) } } } func TestProject_Watch(t *testing.T) { + var wg sync.WaitGroup r := Realize{} r.Projects = append(r.Projects, Project{ parent: &r, }) r.exit = make(chan os.Signal, 2) signal.Notify(r.exit, os.Interrupt) - go func(){ + go func() { time.Sleep(100) close(r.exit) }() - r.Projects[0].Watch(r.exit) -} \ No newline at end of file + wg.Add(1) + // test before after and file change + r.Projects[0].Watch(&wg) + wg.Wait() +} diff --git a/realize/schema.go b/realize/schema.go index 4dcfbac..36cedf1 100644 --- a/realize/schema.go +++ b/realize/schema.go @@ -76,14 +76,14 @@ func (s *Schema) New(c *cli.Context) Project { } // Filter project list by field -func (s *Schema) Filter(field string, value interface{}) []Project{ +func (s *Schema) Filter(field string, value interface{}) []Project { result := []Project{} - for _, item := range s.Projects{ + for _, item := range s.Projects { v := reflect.ValueOf(item) for i := 0; i < v.NumField(); i++ { if v.Type().Field(i).Name == field { if reflect.DeepEqual(v.Field(i).Interface(), value) { - result = append(result,item) + result = append(result, item) } } } diff --git a/realize/schema_test.go b/realize/schema_test.go index 5e6c16f..b07f725 100644 --- a/realize/schema_test.go +++ b/realize/schema_test.go @@ -1,26 +1,26 @@ package realize import ( - "testing" "flag" "gopkg.in/urfave/cli.v2" "path/filepath" + "testing" ) func TestSchema_Add(t *testing.T) { r := Realize{} - p := Project{Name:"test"} + p := Project{Name: "test"} r.Add(p) - if len(r.Schema.Projects) != 1{ - t.Error("Unexpected error there are",len(r.Schema.Projects),"instead one") + if len(r.Schema.Projects) != 1 { + t.Error("Unexpected error there are", len(r.Schema.Projects), "instead one") } r.Add(p) - if len(r.Schema.Projects) != 1{ - t.Error("Unexpected error there are",len(r.Schema.Projects),"instead one") + if len(r.Schema.Projects) != 1 { + t.Error("Unexpected error there are", len(r.Schema.Projects), "instead one") } - r.Add(Project{Name:"testing"}) - if len(r.Schema.Projects) != 2{ - t.Error("Unexpected error there are",len(r.Schema.Projects),"instead two") + r.Add(Project{Name: "testing"}) + if len(r.Schema.Projects) != 2 { + t.Error("Unexpected error there are", len(r.Schema.Projects), "instead two") } } @@ -29,15 +29,15 @@ func TestSchema_Remove(t *testing.T) { r.Schema.Projects = []Project{ { Name: "test", - },{ + }, { Name: "testing", - },{ + }, { Name: "testing", }, } r.Remove("testing") - if len(r.Schema.Projects) != 2{ - t.Error("Unexpected errore there are",len(r.Schema.Projects),"instead one") + if len(r.Schema.Projects) != 2 { + t.Error("Unexpected errore there are", len(r.Schema.Projects), "instead one") } } @@ -55,28 +55,28 @@ func TestSchema_New(t *testing.T) { c := cli.NewContext(nil, set, nil) set.Parse([]string{"--fmt", "--install", "--run", "--build", "--generate", "--test", "--vet"}) p := r.New(c) - if p.Name != filepath.Base(Wdir()){ - t.Error("Unexpected error",p.Name,"instead",filepath.Base(Wdir())) + if p.Name != filepath.Base(Wdir()) { + t.Error("Unexpected error", p.Name, "instead", filepath.Base(Wdir())) } - if !p.Tools.Install.Status{ + if !p.Tools.Install.Status { t.Error("Install should be enabled") } - if !p.Tools.Fmt.Status{ + if !p.Tools.Fmt.Status { t.Error("Fmt should be enabled") } - if !p.Tools.Run.Status{ + if !p.Tools.Run.Status { t.Error("Run should be enabled") } - if !p.Tools.Build.Status{ + if !p.Tools.Build.Status { t.Error("Build should be enabled") } - if !p.Tools.Generate.Status{ + if !p.Tools.Generate.Status { t.Error("Generate should be enabled") } - if !p.Tools.Test.Status{ + if !p.Tools.Test.Status { t.Error("Test should be enabled") } - if !p.Tools.Vet.Status{ + if !p.Tools.Vet.Status { t.Error("Vet should be enabled") } } @@ -86,19 +86,19 @@ func TestSchema_Filter(t *testing.T) { r.Schema.Projects = []Project{ { Name: "test", - },{ + }, { Name: "test", }, { Name: "example", }, } - result := r.Filter("Name","test") - if len(result) != 2{ + result := r.Filter("Name", "test") + if len(result) != 2 { t.Error("Expected two project") } - result = r.Filter("Name","example") - if len(result) != 1{ + result = r.Filter("Name", "example") + if len(result) != 1 { t.Error("Expected one project") } -} \ No newline at end of file +} diff --git a/realize/server_test.go b/realize/server_test.go index 31ff27a..f331c04 100644 --- a/realize/server_test.go +++ b/realize/server_test.go @@ -1,10 +1,11 @@ package realize import ( - "testing" "net/http" "runtime" + "testing" ) + func TestServer_Start(t *testing.T) { s := Server{ Host: "localhost", @@ -39,7 +40,7 @@ func TestServer_Open(t *testing.T) { "linux": "xdg-open", } key := runtime.GOOS - if _, ok:= cmd[key]; !ok{ + if _, ok := cmd[key]; !ok { t.Error("System not supported") } -} \ No newline at end of file +} diff --git a/realize/settings_test.go b/realize/settings_test.go index 6a56a91..b941700 100644 --- a/realize/settings_test.go +++ b/realize/settings_test.go @@ -1,11 +1,11 @@ package realize import ( + "io/ioutil" + "math/rand" + "os" "testing" "time" - "math/rand" - "io/ioutil" - "os" ) // Rand is used for generate a random string @@ -98,4 +98,4 @@ func TestSettings_Create(t *testing.T) { } f := s.Create(p, "io_test") os.Remove(f.Name()) -} \ No newline at end of file +} diff --git a/realize/settings_unix_test.go b/realize/settings_unix_test.go index 68289fa..8d01d0a 100644 --- a/realize/settings_unix_test.go +++ b/realize/settings_unix_test.go @@ -1,4 +1,5 @@ // +build !windows + package realize import ( @@ -11,4 +12,4 @@ func TestSettings_Flimit(t *testing.T) { if err := s.Flimit(); err != nil { t.Error("Unable to increase limit", err) } -} \ No newline at end of file +} diff --git a/realize/tools.go b/realize/tools.go index a4d93ea..89b974e 100644 --- a/realize/tools.go +++ b/realize/tools.go @@ -24,7 +24,6 @@ type Tool struct { // Tools go type Tools struct { - Fix Tool `yaml:"fix,omitempty" json:"fix,omitempty"` Clean Tool `yaml:"clean,omitempty" json:"clean,omitempty"` Vet Tool `yaml:"vet,omitempty" json:"vet,omitempty"` Fmt Tool `yaml:"fmt,omitempty" json:"fmt,omitempty"` @@ -52,17 +51,10 @@ func (t *Tools) Setup() { t.Generate.cmd = replace([]string{"go", "generate"}, t.Generate.Method) t.Generate.Args = split([]string{}, t.Generate.Args) } - // go fix - if t.Fix.Status { - t.Fix.name = "Fix" - t.Fix.isTool = true - t.Fix.cmd = replace([]string{"go fix"}, t.Fix.Method) - t.Fix.Args = split([]string{}, t.Fix.Args) - } // go fmt if t.Fmt.Status { if len(t.Fmt.Args) == 0 { - t.Fmt.Args = []string{"-s", "-w", "-e", "./"} + t.Fmt.Args = []string{"-s", "-w", "-e"} } t.Fmt.name = "Fmt" t.Fmt.isTool = true @@ -99,44 +91,46 @@ func (t *Tools) Setup() { // Exec a go tool func (t *Tool) Exec(path string, stop <-chan bool) (response Response) { - if t.dir && filepath.Ext(path) != "" { - path = filepath.Dir(path) - } - if strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "") { - args := []string{} - if strings.HasSuffix(path, ".go") { - args = append(t.Args, path) + if t.dir { + if filepath.Ext(path) != "" { path = filepath.Dir(path) } - if s := ext(path); s == "" || s == "go" { - var out, stderr bytes.Buffer - done := make(chan error) - args = append(t.cmd, t.Args...) - cmd := exec.Command(args[0], args[1:]...) - if t.Dir != "" { - cmd.Dir, _ = filepath.Abs(t.Dir) + } else if !strings.HasSuffix(path, ".go") { + return + } + args := []string{} + if strings.HasSuffix(path, ".go") { + args = append(t.Args, path) + path = filepath.Dir(path) + } + if s := ext(path); s == "" || s == "go" { + var out, stderr bytes.Buffer + done := make(chan error) + args = append(t.cmd, args...) + cmd := exec.Command(args[0], args[1:]...) + if t.Dir != "" { + cmd.Dir, _ = filepath.Abs(t.Dir) + } else { + cmd.Dir = path + } + cmd.Stdout = &out + cmd.Stderr = &stderr + // Start command + cmd.Start() + go func() { done <- cmd.Wait() }() + // Wait a result + select { + case <-stop: + // Stop running command + cmd.Process.Kill() + case err := <-done: + // Command completed + response.Name = t.name + if err != nil { + response.Err = errors.New(stderr.String() + out.String()) } else { - cmd.Dir = path - } - cmd.Stdout = &out - cmd.Stderr = &stderr - // Start command - cmd.Start() - go func() { done <- cmd.Wait() }() - // Wait a result - select { - case <-stop: - // Stop running command - cmd.Process.Kill() - case err := <-done: - // Command completed - response.Name = t.name - if err != nil { - response.Err = errors.New(stderr.String() + out.String()) - } else { - if t.Output { - response.Out = out.String() - } + if t.Output { + response.Out = out.String() } } } diff --git a/realize/tools_test.go b/realize/tools_test.go index d2ac204..661e964 100644 --- a/realize/tools_test.go +++ b/realize/tools_test.go @@ -6,20 +6,20 @@ func TestTools_Setup(t *testing.T) { tools := Tools{ Clean: Tool{ Status: true, - name: "test", + name: "test", isTool: false, Method: "test", - Args: []string{"arg"}, + Args: []string{"arg"}, }, } tools.Setup() - if tools.Clean.name == "test"{ + if tools.Clean.name == "test" { t.Error("Unexpected value") } - if tools.Clean.Method != "test"{ + if tools.Clean.Method != "test" { t.Error("Unexpected value") } - if !tools.Clean.isTool{ + if !tools.Clean.isTool { t.Error("Unexpected value") } -} \ No newline at end of file +} diff --git a/realize/utils.go b/realize/utils.go index 14a1034..72da59e 100644 --- a/realize/utils.go +++ b/realize/utils.go @@ -56,7 +56,7 @@ func ext(path string) string { for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- { if path[i] == '.' { ext = path[i:] - if index := strings.LastIndex(ext,"."); index > 0{ + if index := strings.LastIndex(ext, "."); index > 0 { ext = ext[index:] } } @@ -82,4 +82,4 @@ func Wdir() string { log.Fatal(err.Error()) } return dir -} \ No newline at end of file +} diff --git a/realize/utils_test.go b/realize/utils_test.go index 1f75063..b0d2b07 100644 --- a/realize/utils_test.go +++ b/realize/utils_test.go @@ -64,19 +64,19 @@ func TestWdir(t *testing.T) { } } -func TestExt(t *testing.T){ +func TestExt(t *testing.T) { paths := map[string]string{ - "/test/a/b/c": "", - "/test/a/ac.go": "go", + "/test/a/b/c": "", + "/test/a/ac.go": "go", "/test/a/ac.test.go": "go", "/test/a/ac_test.go": "go", "/test/./ac_test.go": "go", - "/test/a/.test": "test", - "/test/a/.": "", + "/test/a/.test": "test", + "/test/a/.": "", } for i, v := range paths { - if ext(i) != v{ - t.Error("Wrong extension",ext(i),v) + if ext(i) != v { + t.Error("Wrong extension", ext(i), v) } }