diff --git a/realize.go b/realize.go index 2042088..c925635 100644 --- a/realize.go +++ b/realize.go @@ -17,14 +17,13 @@ import ( const ( appVersion = "1.3" - - config = "realize.yaml" - outputs = "outputs.log" - errs = "errors.log" - logs = "logs.log" - host = "localhost" - port = 5001 - interval = 200 + config = "realize.yaml" + outputs = "outputs.log" + errs = "errors.log" + logs = "logs.log" + host = "localhost" + port = 5001 + interval = 200 ) // Cli commands @@ -195,7 +194,7 @@ func main() { Questions: []*interact.Question{ { Before: func(d interact.Context) error { - if _, err := os.Stat(".realize/" + config); err != nil { + if _, err := os.Stat(settings.Dir + config); err != nil { d.Skip() } d.SetDef(false, style.Green.Regular("(n)")) @@ -462,7 +461,25 @@ func main() { if err != nil { return d.Err() } - r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Fmt = val + r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Cmds.Fmt = val + return nil + }, + }, + { + Before: func(d interact.Context) error { + d.SetDef(true, style.Green.Regular("(y)")) + return nil + }, + Quest: interact.Quest{ + Options: style.Yellow.Regular("[y/n]"), + Msg: "Enable go vet", + }, + Action: func(d interact.Context) interface{} { + val, err := d.Ans().Bool() + if err != nil { + return d.Err() + } + r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Cmds.Vet = val return nil }, }, @@ -480,7 +497,7 @@ func main() { if err != nil { return d.Err() } - r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Test = val + r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Cmds.Test = val return nil }, }, @@ -498,7 +515,7 @@ func main() { if err != nil { return d.Err() } - r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Generate = val + r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Cmds.Generate = val return nil }, }, @@ -516,7 +533,7 @@ func main() { if err != nil { return d.Err() } - r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Bin = val + r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Cmds.Bin.Status = val return nil }, }, @@ -534,7 +551,7 @@ func main() { if err != nil { return d.Err() } - r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Build = val + r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Cmds.Build.Status = val return nil }, }, @@ -552,7 +569,7 @@ func main() { if err != nil { return d.Err() } - r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Run = val + r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Cmds.Run = val return nil }, }, @@ -674,7 +691,7 @@ func main() { if err != nil { return d.Err() } - r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Params = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Params, val) + r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Args = append(r.Blueprint.Projects[len(r.Blueprint.Projects)-1].Args, val) d.Reload() return nil }, diff --git a/settings/io.go b/settings/io.go index e3fc2c3..d622ee8 100644 --- a/settings/io.go +++ b/settings/io.go @@ -26,8 +26,8 @@ func (s Settings) Write(name string, data []byte) error { // Create a new file and return its pointer func (s Settings) Create(path string, name string) *os.File { var file string - if _, err := os.Stat(".realize/"); err == nil { - file = filepath.Join(path, ".realize/", name) + if _, err := os.Stat(Dir); err == nil { + file = filepath.Join(path, Dir, name) } else { file = filepath.Join(path, name) } diff --git a/settings/settings.go b/settings/settings.go index 58ae93a..41a4054 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -7,6 +7,8 @@ import ( yaml "gopkg.in/yaml.v2" ) +var Dir = ".realize/" + // Settings defines a group of general settings type Settings struct { Config `yaml:",inline" json:"config"` @@ -46,8 +48,8 @@ type Resources struct { // Read from config file func (s *Settings) Read(out interface{}) error { localConfigPath := s.Resources.Config - if _, err := os.Stat(".realize/" + s.Resources.Config); err == nil { - localConfigPath = ".realize/" + s.Resources.Config + if _, err := os.Stat(Dir + s.Resources.Config); err == nil { + localConfigPath = Dir + s.Resources.Config } content, err := s.Stream(localConfigPath) if err == nil { @@ -64,20 +66,20 @@ func (s *Settings) Record(out interface{}) error { if err != nil { return err } - if _, err := os.Stat(".realize/"); os.IsNotExist(err) { - if err = os.Mkdir(".realize/", 0770); err != nil { + if _, err := os.Stat(Dir); os.IsNotExist(err) { + if err = os.Mkdir(Dir, 0770); err != nil { return s.Write(s.Resources.Config, y) } } - return s.Write(".realize/"+s.Resources.Config, y) + return s.Write(Dir+s.Resources.Config, y) } return nil } // Remove realize folder func (s *Settings) Remove() error { - if _, err := os.Stat(".realize/"); !os.IsNotExist(err) { - return os.RemoveAll(".realize/") + if _, err := os.Stat(Dir); !os.IsNotExist(err) { + return os.RemoveAll(Dir) } return nil } diff --git a/watcher/cmd.go b/watcher/cmd.go index 5f88012..a67d6e7 100644 --- a/watcher/cmd.go +++ b/watcher/cmd.go @@ -3,10 +3,9 @@ package watcher import ( "errors" "fmt" - "strings" - "github.com/tockins/realize/style" cli "gopkg.in/urfave/cli.v2" + "strings" ) // Run launches the toolchain for each project @@ -15,7 +14,41 @@ func (h *Blueprint) Run() error { if err == nil { // loop projects wg.Add(len(h.Projects)) - for k := range h.Projects { + for k, element := range h.Projects { + tools := tools{} + if element.Cmds.Fmt { + tools.Fmt = tool{ + status: &h.Projects[k].Cmds.Fmt, + cmd: "gofmt", + options: []string{"-s", "-w", "-e"}, + name: "Go Fmt", + } + } + if element.Cmds.Generate { + tools.Generate = tool{ + status: &h.Projects[k].Cmds.Generate, + cmd: "go", + options: []string{"generate"}, + name: "Go Generate", + } + } + if element.Cmds.Test { + tools.Test = tool{ + status: &h.Projects[k].Cmds.Test, + cmd: "go", + options: []string{"test"}, + name: "Go Test", + } + } + if element.Cmds.Vet { + tools.Vet = tool{ + status: &h.Projects[k].Cmds.Vet, + cmd: "go", + options: []string{"vet"}, + name: "Go Vet", + } + } + h.Projects[k].tools = tools h.Projects[k].parent = h h.Projects[k].path = h.Projects[k].Path if h.Legacy.Status { @@ -33,15 +66,23 @@ func (h *Blueprint) Run() error { // Add a new project func (h *Blueprint) Add(p *cli.Context) error { project := Project{ - Name: h.Name(p.String("name"), p.String("path")), - Path: h.Path(p.String("path")), - Fmt: !p.Bool("no-fmt"), - Generate: p.Bool("generate"), - Test: p.Bool("test"), - Build: p.Bool("build"), - Bin: !p.Bool("no-bin"), - Run: !p.Bool("no-run"), - Params: argsParam(p), + Name: h.Name(p.String("name"), p.String("path")), + Path: h.Path(p.String("path")), + Cmds: Cmds{ + + Vet: p.Bool("vet"), + Fmt: !p.Bool("no-fmt"), + Test: p.Bool("test"), + Generate: p.Bool("generate"), + Build: Cmd{ + Status: p.Bool("build"), + }, + Bin: Cmd{ + Status: !p.Bool("no-bin"), + }, + Run: !p.Bool("no-run"), + }, + Args: argsParam(p), Watcher: Watcher{ Paths: []string{"/"}, Ignore: []string{"vendor"}, @@ -94,14 +135,14 @@ func (h *Blueprint) List() error { name := style.Magenta.Bold("[") + strings.ToUpper(val.Name) + style.Magenta.Bold("]") fmt.Println(name, style.Yellow.Regular("Base Path"), ":", style.Magenta.Regular(val.Path)) - fmt.Println(name, style.Yellow.Regular("Fmt"), ":", style.Magenta.Regular(val.Fmt)) - fmt.Println(name, style.Yellow.Regular("Generate"), ":", style.Magenta.Regular(val.Generate)) - fmt.Println(name, style.Yellow.Regular("Test"), ":", style.Magenta.Regular(val.Test)) - fmt.Println(name, style.Yellow.Regular("Install"), ":", style.Magenta.Regular(val.Bin)) - fmt.Println(name, style.Yellow.Regular("Build"), ":", style.Magenta.Regular(val.Build)) - fmt.Println(name, style.Yellow.Regular("Run"), ":", style.Magenta.Regular(val.Run)) - if len(val.Params) > 0 { - fmt.Println(name, style.Yellow.Regular("Params"), ":", style.Magenta.Regular(val.Params)) + fmt.Println(name, style.Yellow.Regular("Fmt"), ":", style.Magenta.Regular(val.Cmds.Fmt)) + fmt.Println(name, style.Yellow.Regular("Generate"), ":", style.Magenta.Regular(val.Cmds.Generate)) + fmt.Println(name, style.Yellow.Regular("Test"), ":", style.Magenta.Regular(val.Cmds.Test)) + fmt.Println(name, style.Yellow.Regular("Install"), ":", style.Magenta.Regular(val.Cmds.Bin)) + fmt.Println(name, style.Yellow.Regular("Build"), ":", style.Magenta.Regular(val.Cmds.Build)) + fmt.Println(name, style.Yellow.Regular("Run"), ":", style.Magenta.Regular(val.Cmds.Run)) + if len(val.Args) > 0 { + fmt.Println(name, style.Yellow.Regular("Params"), ":", style.Magenta.Regular(val.Args)) } fmt.Println(name, style.Yellow.Regular("Watcher"), ":") fmt.Println(name, "\t", style.Yellow.Regular("Preview"), ":", style.Magenta.Regular(val.Watcher.Preview)) diff --git a/watcher/exec.go b/watcher/exec.go index 943f1ec..850f7b4 100644 --- a/watcher/exec.go +++ b/watcher/exec.go @@ -12,14 +12,13 @@ import ( "strings" "sync" "time" - "github.com/tockins/realize/style" ) // GoRun is an implementation of the bin execution func (p *Project) goRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) error { var build *exec.Cmd - var params []string + var args []string var path = "" isErrorText := func(string) bool { return false @@ -34,9 +33,9 @@ func (p *Project) goRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) return errRegexp.MatchString(t) } } - for _, param := range p.Params { - arr := strings.Fields(param) - params = append(params, arr...) + for _, arg := range p.Args { + arr := strings.Fields(arg) + args = append(args, arr...) } if _, err := os.Stat(filepath.Join(p.base, p.path)); err == nil { path = filepath.Join(p.base, p.path) @@ -46,12 +45,12 @@ func (p *Project) goRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) } if path != "" { - build = exec.Command(path, params...) + build = exec.Command(path, args...) } else { if _, err := os.Stat(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path))); err == nil { - build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path)), params...) + build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path)), args...) } else if _, err := os.Stat(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path)) + ".exe"); err == nil { - build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path))+".exe", params...) + build = exec.Command(filepath.Join(os.Getenv("GOBIN"), filepath.Base(p.path))+".exe", args...) } else { p.Buffer.StdLog = append(p.Buffer.StdLog, BufferOut{Time: time.Now(), Text: "Can't run a not compiled project"}) p.Fatal(err, "Can't run a not compiled project", ":") @@ -114,7 +113,12 @@ func (p *Project) goRun(channel chan bool, runner chan bool, wr *sync.WaitGroup) func (p *Project) goBuild() (string, error) { var out bytes.Buffer var stderr bytes.Buffer - build := exec.Command("go", "build") + args := []string{"build"} + for _, arg := range p.Cmds.Build.Args { + arr := strings.Fields(arg) + args = append(args, arr...) + } + build := exec.Command("go", args...) build.Dir = p.base build.Stdout = &out build.Stderr = &stderr @@ -132,7 +136,12 @@ func (p *Project) goInstall() (string, error) { if err != nil { return "", err } - build := exec.Command("go", "install") + args := []string{"install"} + for _, arg := range p.Cmds.Bin.Args { + arr := strings.Fields(arg) + args = append(args, arr...) + } + build := exec.Command("go", args...) build.Dir = p.base build.Stdout = &out build.Stderr = &stderr diff --git a/watcher/main.go b/watcher/main.go index de700ba..3474e26 100644 --- a/watcher/main.go +++ b/watcher/main.go @@ -1,11 +1,10 @@ package watcher import ( + "github.com/tockins/realize/settings" "log" "sync" "time" - - "github.com/tockins/realize/settings" ) var wg sync.WaitGroup @@ -21,8 +20,7 @@ type pollWatcher struct { } // Log struct -type logWriter struct { -} +type logWriter struct{} // Blueprint struct contains a projects list type Blueprint struct { @@ -33,24 +31,47 @@ type Blueprint struct { // Project defines the informations of a single project type Project struct { - settings.Settings `yaml:"-"` - LastChangedOn time.Time `yaml:"-" json:"-"` - base string - Name string `yaml:"name" json:"name"` - Path string `yaml:"path" json:"path"` - Fmt bool `yaml:"fmt" json:"fmt"` - Generate bool `yaml:"generate" json:"generate"` - Test bool `yaml:"test" json:"test"` - Bin bool `yaml:"bin" json:"bin"` - Build bool `yaml:"build" json:"build"` - Run bool `yaml:"run" json:"run"` - Params []string `yaml:"params,omitempty" json:"params,omitempty"` - Watcher Watcher `yaml:"watcher" json:"watcher"` - Streams Streams `yaml:"streams" json:"streams"` + settings.Settings `yaml:"-"` + LastChangedOn time.Time `yaml:"-" json:"-"` + base string + Name string `yaml:"name" json:"name"` + Path string `yaml:"path" json:"path"` + Cmds Cmds `yaml:"cmds" json:"cmds"` + Args []string `yaml:"args,omitempty" json:"args,omitempty"` + Watcher Watcher `yaml:"watcher" json:"watcher"` + Streams Streams `yaml:"streams" json:"streams"` + Buffer Buffer `yaml:"-" json:"buffer"` ErrorOutputPattern string `yaml:"errorOutputPattern" json:"errorOutputPattern"` - Buffer Buffer `yaml:"-" json:"buffer"` - parent *Blueprint - path string + parent *Blueprint + path string + tools tools +} + +type tools struct { + Fmt, Test, Generate, Vet tool +} + +type tool struct { + status *bool + cmd string + options []string + name string +} + +type Cmds struct { + Vet bool `yaml:"vet" json:"vet"` + Fmt bool `yaml:"fmt" json:"fmt"` + Test bool `yaml:"test" json:"test"` + Generate bool `yaml:"generate" json:"generate"` + Bin Cmd `yaml:"bin" json:"bin"` + Build Cmd `yaml:"build" json:"build"` + Run bool `yaml:"run" json:"run"` +} + +// Buildmode options +type Cmd struct { + Status bool `yaml:"status" json:"status"` + Args []string `yaml:"args,omitempty" json:"args,omitempty"` } // Watcher struct defines the livereload's logic diff --git a/watcher/watcher.go b/watcher/watcher.go index b7e16ba..1468d25 100644 --- a/watcher/watcher.go +++ b/watcher/watcher.go @@ -13,7 +13,7 @@ import ( "sync" "syscall" "time" - + "reflect" "github.com/fsnotify/fsnotify" "github.com/tockins/realize/style" ) @@ -67,7 +67,7 @@ func (p *Project) watchByPolling() { file := changed[:i] + ext path := filepath.Dir(changed[:i]) if changed[:i] != "" && inArray(ext, p.Watcher.Exts) { - if p.Run { + if p.Cmds.Run { close(channel) channel = make(chan bool) } @@ -78,9 +78,10 @@ func (p *Project) watchByPolling() { p.print("log", out, msg, "") p.cmd("change") - p.fmt(file) - p.test(path) - p.generate(path) + p.tool(file, p.tools.Fmt) + p.tool(file, p.tools.Vet) + p.tool(path, p.tools.Test) + p.tool(path, p.tools.Generate) go p.routines(channel, &wr) } return nil @@ -143,7 +144,7 @@ func (p *Project) watchByNotify() { file := event.Name[:i] + ext path := filepath.Dir(event.Name[:i]) if event.Name[:i] != "" && inArray(ext, p.Watcher.Exts) { - if p.Run { + if p.Cmds.Run { close(channel) channel = make(chan bool) } @@ -154,9 +155,10 @@ func (p *Project) watchByNotify() { p.print("log", out, msg, "") p.cmd("change") - p.fmt(file) - p.test(path) - p.generate(path) + p.tool(file, p.tools.Fmt) + p.tool(path, p.tools.Vet) + p.tool(path, p.tools.Test) + p.tool(path, p.tools.Generate) go p.routines(channel, &wr) } } @@ -186,11 +188,12 @@ func (p *Project) watch(watcher watcher) error { } if inArray(filepath.Ext(path), p.Watcher.Exts) { files++ - p.fmt(path) + p.tool(path, p.tools.Fmt) } else { folders++ - p.generate(path) - p.test(path) + p.tool(path, p.tools.Vet) + p.tool(path, p.tools.Test) + p.tool(path, p.tools.Generate) } } } @@ -222,7 +225,7 @@ func (p *Project) watch(watcher watcher) error { // Install calls an implementation of "go install" func (p *Project) install() error { - if p.Bin { + if p.Cmds.Bin.Status { start := time.Now() log.Println(p.pname(p.Name, 1), ":", "Installing..") stream, err := p.goInstall() @@ -242,7 +245,7 @@ func (p *Project) install() error { // Install calls an implementation of "go run" func (p *Project) run(channel chan bool, wr *sync.WaitGroup) { - if p.Run { + if p.Cmds.Run { start := time.Now() runner := make(chan bool, 1) log.Println(p.pname(p.Name, 1), ":", "Running..") @@ -261,7 +264,7 @@ func (p *Project) run(channel chan bool, wr *sync.WaitGroup) { // Build calls an implementation of the "go build" func (p *Project) build() error { - if p.Build { + if p.Cmds.Build.Status { start := time.Now() log.Println(p.pname(p.Name, 1), ":", "Building..") stream, err := p.goBuild() @@ -279,40 +282,20 @@ func (p *Project) build() error { return nil } -// Fmt calls an implementation of the "go fmt" -func (p *Project) fmt(path string) error { - if p.Fmt && strings.HasSuffix(path, ".go") { - if stream, err := p.goTools(p.base, "gofmt", "-s", "-w", "-e", path); err != nil { - msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Bold("Go Fmt"), style.Red.Regular("there are some errors in"), ":", style.Magenta.Bold(path)) - out = BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Fmt", Stream: stream} - p.print("error", out, msg, stream) - return err - } - } - return nil -} - -// Generate calls an implementation of the "go generate" -func (p *Project) generate(path string) error { - if p.Generate { - if stream, err := p.goTools(path, "go", "generate"); err != nil { - msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Bold("Go Generate"), style.Red.Regular("there are some errors in"), ":", style.Magenta.Bold(path)) - out = BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Generate", Stream: stream} - p.print("error", out, msg, stream) - return err - } - } - return nil -} - -// Test calls an implementation of the "go test" -func (p *Project) test(path string) error { - if p.Test { - if stream, err := p.goTools(path, "go", "test"); err != nil { - msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Bold("Go Test"), style.Red.Regular("there are some errors in "), ":", style.Magenta.Bold(path)) - out = BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: "Go Test", Stream: stream} - p.print("error", out, msg, stream) - return err +func (p *Project) tool(path string, tool tool) error { + if tool.status != nil { + v := reflect.ValueOf(tool.status).Elem() + if v.Interface().(bool) && (strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "")) { + if strings.HasSuffix(path, ".go"){ + tool.options = append(tool.options, path) + path = p.base + } + if stream, err := p.goTools(path, tool.cmd, tool.options...); err != nil { + msg = fmt.Sprintln(p.pname(p.Name, 2), ":", style.Red.Bold(tool.name), style.Red.Regular("there are some errors in"), ":", style.Magenta.Bold(path)) + out = BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: tool.name, Stream: stream} + p.print("error", out, msg, stream) + return err + } } } return nil