diff --git a/realize.go b/realize.go index c683134..05a9006 100644 --- a/realize.go +++ b/realize.go @@ -8,21 +8,18 @@ import ( w "github.com/tockins/realize/watcher" "gopkg.in/urfave/cli.v2" "os" - "time" ) const ( name = "Realize" - version = "1.2.1" + version = "1.3" description = "A Go build system with file watchers, output streams and live reload. Run, build and watch file changes with custom paths" config = "realize.yaml" - streams = "streams.log" + outputs = "outputs.log" errs = "errors.log" logs = "logs.log" host = "localhost" port = 5001 - server = true - open = false ) var r realize @@ -45,23 +42,12 @@ func init() { Description: description, Sync: make(chan string), Settings: c.Settings{ - Config: c.Config{ - Flimit: 0, - Polling: false, - PollingInterval: time.Millisecond * 200, - }, Resources: c.Resources{ Config: config, - Streams: streams, + Outputs: outputs, Logs: logs, Errors: errs, }, - Server: c.Server{ - Enabled: server, - Open: open, - Host: host, - Port: port, - }, }, } r.Blueprint = w.Blueprint{ @@ -122,43 +108,32 @@ func main() { Usage: r.Description, Commands: []*cli.Command{ { - Name: "run", - Usage: "Build and watch file changes. Can be used even with a single project or without the config file", + Name: "run", + Aliases: []string{"r"}, + Usage: "Run a toolchain on a project. Can be personalized, used with a single project and without make a realize config file", Flags: []cli.Flag{ - &cli.StringFlag{Name: "path", Aliases: []string{"b"}, Value: "", Usage: "Project base path"}, - &cli.BoolFlag{Name: "build", Value: false, Usage: "Enables the build"}, - &cli.BoolFlag{Name: "no-run", Usage: "Disables the run"}, - &cli.BoolFlag{Name: "no-bin", Usage: "Disables the installation"}, - &cli.BoolFlag{Name: "no-fmt", Usage: "Disables the fmt (go fmt)"}, - &cli.BoolFlag{Name: "no-server", Usage: "Disables the web panel"}, - &cli.BoolFlag{Name: "no-config", Value: false, Usage: "Uses the config settings"}, - &cli.BoolFlag{Name: "open", Usage: "Automatically opens the web panel"}, - &cli.IntFlag{Name: "port", Usage: "Sets the web panel port"}, - &cli.BoolFlag{Name: "test", Value: false, Usage: "Enables the tests"}, + &cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: "", Usage: "Project base path"}, + &cli.IntFlag{Name: "flimit", Aliases: []string{"f"}, Usage: "Increase files limit"}, + &cli.BoolFlag{Name: "legacy", Aliases: []string{"l"}, Value: false, Usage: "Enable legacy watch"}, + &cli.IntFlag{Name: "legacy-delay", Aliases: []string{"ld"}, Usage: "Restarting delay for legacy watch"}, + &cli.BoolFlag{Name: "build", Aliases: []string{"b"}, Value: false, Usage: "Enable go build"}, + &cli.BoolFlag{Name: "test", Aliases: []string{"t"}, Value: false, Usage: "Enable go test"}, + &cli.BoolFlag{Name: "generate", Aliases: []string{"g"}, Value: false, Usage: "Enable go generate"}, + &cli.BoolFlag{Name: "preview", Aliases: []string{"prev"}, Value: false, Usage: "Print each watched file"}, + &cli.BoolFlag{Name: "no-run", Aliases: []string{"nr"}, Usage: "Disable go run"}, + &cli.BoolFlag{Name: "no-bin", Aliases: []string{"nb"}, Usage: "Disable go install"}, + &cli.BoolFlag{Name: "no-fmt", Aliases: []string{"nf"}, Usage: "Disable go fmt"}, + &cli.BoolFlag{Name: "no-config", Aliases: []string{"nc"}, Value: false, Usage: "Run ignoring an existing config file"}, + &cli.BoolFlag{Name: "no-server", Aliases: []string{"ns"}, Value: false, Usage: "Disable web panel"}, + &cli.BoolFlag{Name: "serv-open", Aliases: []string{"so"}, Value: false, Usage: "Open wen panel in a new browser tab"}, + &cli.IntFlag{Name: "serv-port", Aliases: []string{"sp"}, Value: port, Usage: "Server port number"}, + &cli.StringFlag{Name: "serv-host", Aliases: []string{"sh"}, Value: host, Usage: "Server host"}, }, Action: func(p *cli.Context) error { - if p.Bool("no-config") { - r.Settings = c.Settings{ - Config: c.Config{ - Flimit: 0, - }, - Resources: c.Resources{ - Config: config, - Streams: streams, - Logs: logs, - Errors: errs, - }, - Server: c.Server{ - Enabled: server, - Open: open, - Host: host, - Port: port, - }, - } - r.Blueprint.Projects = r.Blueprint.Projects[:0] - r.Blueprint.Add(p) - } else if len(r.Blueprint.Projects) <= 0 { - r.Blueprint.Add(p) + r.Settings.Init(p) + if r.Settings.Config.Create || len(r.Blueprint.Projects) <= 0 { + r.Blueprint.Projects = []w.Project{} + handle(r.Blueprint.Add(p)) } handle(r.Server.Start(p)) handle(r.Blueprint.Run()) @@ -170,23 +145,51 @@ func main() { }, }, { - Name: "add", + Name: "config", Category: "Configuration", - Aliases: []string{"a"}, - Usage: "Add another project", + Aliases: []string{"c"}, + Usage: "Create/Edit a realize config", Flags: []cli.Flag{ &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: r.Wdir(), Usage: "Project name"}, - &cli.StringFlag{Name: "path", Aliases: []string{"b"}, Value: "/", Usage: "Project base path"}, - &cli.BoolFlag{Name: "build", Value: false, Usage: "Enable the build"}, - &cli.BoolFlag{Name: "no-run", Usage: "Disables the run"}, - &cli.BoolFlag{Name: "no-bin", Usage: "Disables the installation"}, - &cli.BoolFlag{Name: "no-fmt", Usage: "Disables the fmt (go fmt)"}, - &cli.BoolFlag{Name: "test", Value: false, Usage: "Enables the tests"}, + &cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: "", Usage: "Project base path"}, + &cli.BoolFlag{Name: "build", Aliases: []string{"b"}, Value: false, Usage: "Enable go build"}, + &cli.BoolFlag{Name: "test", Aliases: []string{"t"}, Value: false, Usage: "Enable go test"}, + &cli.BoolFlag{Name: "generate", Aliases: []string{"g"}, Value: false, Usage: "Enable go generate"}, + &cli.BoolFlag{Name: "preview", Aliases: []string{"prev"}, Value: false, Usage: "Print each watched file"}, + &cli.BoolFlag{Name: "no-run", Aliases: []string{"nr"}, Usage: "Disable go run"}, + &cli.BoolFlag{Name: "no-bin", Aliases: []string{"nb"}, Usage: "Disable go install"}, + &cli.BoolFlag{Name: "no-fmt", Aliases: []string{"nf"}, Usage: "Disable go fmt"}, }, Action: func(p *cli.Context) (err error) { handle(r.Blueprint.Insert(p)) handle(r.Record(r)) - fmt.Println(r.Green.Bold("Your project was successfully added")) + fmt.Println(r.Green.Bold("Your project was successfully added.")) + return nil + }, + Before: func(c *cli.Context) error { + return before() + }, + }, + { + Name: "add", + Category: "Configuration", + Aliases: []string{"a"}, + Usage: "Add a new project to an existing realize config file", + Flags: []cli.Flag{ + &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: r.Wdir(), Usage: "Project name"}, + &cli.StringFlag{Name: "path", Aliases: []string{"p"}, Value: "", Usage: "Project base path"}, + &cli.BoolFlag{Name: "build", Aliases: []string{"b"}, Value: false, Usage: "Enable go build"}, + &cli.BoolFlag{Name: "test", Aliases: []string{"t"}, Value: false, Usage: "Enable go test"}, + &cli.BoolFlag{Name: "generate", Aliases: []string{"g"}, Value: false, Usage: "Enable go generate"}, + &cli.BoolFlag{Name: "preview", Aliases: []string{"prev"}, Value: false, Usage: "Print each watched file"}, + &cli.BoolFlag{Name: "no-run", Aliases: []string{"nr"}, Usage: "Disable go run"}, + &cli.BoolFlag{Name: "no-bin", Aliases: []string{"nb"}, Usage: "Disable go install"}, + &cli.BoolFlag{Name: "no-fmt", Aliases: []string{"nf"}, Usage: "Disable go fmt"}, + }, + Action: func(p *cli.Context) (err error) { + handle(r.Blueprint.Insert(p)) + handle(r.Record(r)) + fmt.Println(r.Green.Bold("Your project was successfully added.")) return nil }, Before: func(c *cli.Context) error { @@ -197,7 +200,7 @@ func main() { Name: "remove", Category: "Configuration", Aliases: []string{"r"}, - Usage: "Remove a project", + Usage: "Remove a project from a config file", Flags: []cli.Flag{ &cli.StringFlag{Name: "name", Aliases: []string{"n"}, Value: ""}, }, @@ -223,6 +226,20 @@ func main() { return before() }, }, + { + Name: "clean", + Category: "Configuration", + Aliases: []string{"c"}, + Usage: "Remove realize folder", + Action: func(p *cli.Context) error { + handle(r.Settings.Remove()) + fmt.Println(r.Green.Bold("Realize folder successfully removed.")) + return nil + }, + Before: func(c *cli.Context) error { + return before() + }, + }, }, } c.Run(os.Args) diff --git a/server/main.go b/server/main.go index 1c8476b..5e2106b 100644 --- a/server/main.go +++ b/server/main.go @@ -48,10 +48,7 @@ func render(c echo.Context, path string, mime int) error { // Start the web server func (s *Server) Start(p *cli.Context) (err error) { - if p.Int("port") != 0 { - s.Settings.Server.Port = p.Int("port") - } - if !p.Bool("no-server") && s.Enabled { + if s.Status { e := echo.New() e.Use(middleware.Gzip()) e.Use(middleware.Recover()) @@ -95,8 +92,6 @@ func (s *Server) Start(p *cli.Context) (err error) { return err } } - } else { - s.Server.Enabled = false } return nil } diff --git a/settings/settings.go b/settings/settings.go index f78c619..cf8b32e 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -1,6 +1,7 @@ package settings import ( + "gopkg.in/urfave/cli.v2" "gopkg.in/yaml.v2" "os" "time" @@ -9,30 +10,36 @@ import ( // Settings defines a group of general settings type Settings struct { Colors `yaml:"-"` + Config `yaml:",inline" json:"config"` Resources `yaml:"resources" json:"resources"` - Server `yaml:"server" json:"server"` - Config `yaml:"config" json:"config"` + Server `yaml:"server,omitempty" json:"server,omitempty"` } // Config defines structural options type Config struct { - Flimit uint64 `yaml:"flimit" json:"flimit"` - Polling bool `yaml:"polling" json:"polling"` - PollingInterval time.Duration `yaml:"polling_interval" json:"polling_interval"` + Create bool `yaml:"-" json:"-"` + Flimit uint64 `yaml:"flimit,omitempty" json:"flimit,omitempty"` + Legacy `yaml:"legacy,omitempty" json:"legacy,omitempty"` +} + +// Polling configuration +type Legacy struct { + Status bool `yaml:"status" json:"status"` + Interval time.Duration `yaml:"interval" json:"interval"` } // Server settings, used for the web panel type Server struct { - Enabled bool `yaml:"enable" json:"enable"` - Open bool `yaml:"open" json:"open"` - Host string `yaml:"host" json:"host"` - Port int `yaml:"port" json:"port"` + Status bool `yaml:"status" json:"status"` + Open bool `yaml:"open" json:"open"` + Host string `yaml:"host" json:"host"` + Port int `yaml:"port" json:"port"` } // Resources defines the files generated by realize type Resources struct { Config string `yaml:"-" json:"-"` - Streams string `yaml:"streams" json:"output"` + Outputs string `yaml:"outputs" json:"outputs"` Logs string `yaml:"logs" json:"log"` Errors string `yaml:"errors" json:"error"` } @@ -53,14 +60,43 @@ func (s *Settings) Read(out interface{}) error { // Record create and unmarshal the yaml config file func (s *Settings) Record(out interface{}) error { - y, err := yaml.Marshal(out) - if err != nil { - return err - } - if _, err := os.Stat(".realize/"); os.IsNotExist(err) { - if err = os.Mkdir(".realize/", 0770); err != nil { - return s.Write(s.Resources.Config, y) + if s.Config.Create { + y, err := yaml.Marshal(out) + if err != nil { + return err } + if _, err := os.Stat(".realize/"); os.IsNotExist(err) { + if err = os.Mkdir(".realize/", 0770); err != nil { + return s.Write(s.Resources.Config, y) + } + } + return s.Write(".realize/"+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/") + } + return nil +} + +// Init configuration for general settings +func (s *Settings) Init(p *cli.Context) { + s.Config = Config{ + Create: !p.Bool("no-config"), + Flimit: p.Uint64("flimit"), + Legacy: Legacy{ + Status: p.Bool("legacy"), + Interval: p.Duration("legacy-delay"), + }, + } + s.Server = Server{ + Status: !p.Bool("no-server"), + Open: p.Bool("serv-open"), + Host: p.String("serv-host"), + Port: p.Int("serv-port"), } - return s.Write(".realize/"+s.Resources.Config, y) } diff --git a/watcher/cmd.go b/watcher/cmd.go index 4aaa389..f998ba4 100644 --- a/watcher/cmd.go +++ b/watcher/cmd.go @@ -17,7 +17,7 @@ func (h *Blueprint) Run() error { for k := range h.Projects { h.Projects[k].parent = h h.Projects[k].path = h.Projects[k].Path - if h.Polling.Status { + if h.Legacy.Status { go h.Projects[k].watchByPolling() } else { go h.Projects[k].watchByNotify() @@ -32,27 +32,27 @@ func (h *Blueprint) Run() error { // Add a new project func (h *Blueprint) Add(p *cli.Context) error { project := Project{ - Name: h.name(p), - Path: strings.Replace(filepath.Clean(p.String("path")), "\\", "/", -1), - Build: p.Bool("build"), - Bin: !p.Bool("no-bin"), - Run: !p.Bool("no-run"), - Fmt: !p.Bool("no-fmt"), - Test: p.Bool("test"), - Params: argsParam(p), + Name: h.name(p), + Path: strings.Replace(filepath.Clean(p.String("path")), "\\", "/", -1), + 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), Watcher: Watcher{ Paths: []string{"/"}, Ignore: []string{"vendor"}, Exts: []string{".go"}, - Preview: false, + Preview: p.Bool("preview"), + Scripts: []Command{}, }, - Cli: Cli{ - Streams: true, - }, - File: File{ - Streams: false, - Logs: false, - Errors: false, + Streams: Streams{ + CliOut: true, + FileOut: false, + FileLog: false, + FileErr: false, }, } if _, err := duplicates(project, h.Projects); err != nil { @@ -97,18 +97,17 @@ func (h *Blueprint) List() error { for _, val := range h.Projects { fmt.Println(h.Blue.Bold("|"), h.Blue.Bold(strings.ToUpper(val.Name))) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Base Path"), ":", h.Magenta.Regular(val.Path)) - fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Run"), ":", h.Magenta.Regular(val.Run)) - fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Build"), ":", h.Magenta.Regular(val.Build)) - fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Install"), ":", h.Magenta.Regular(val.Bin)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Fmt"), ":", h.Magenta.Regular(val.Fmt)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Generate"), ":", h.Magenta.Regular(val.Generate)) fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Test"), ":", h.Magenta.Regular(val.Test)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Install"), ":", h.Magenta.Regular(val.Bin)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Build"), ":", h.Magenta.Regular(val.Build)) + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Run"), ":", h.Magenta.Regular(val.Run)) if len(val.Params) > 0 { fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Params"), ":", h.Magenta.Regular(val.Params)) } fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Watcher"), ":") - if len(val.Watcher.Commands) > 0 { - fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("After"), ":", h.Magenta.Regular(val.Watcher.Commands)) - } + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Preview"), ":", h.Magenta.Regular(val.Watcher.Preview)) if len(val.Watcher.Exts) > 0 { fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Extensions"), ":", h.Magenta.Regular(val.Watcher.Exts)) } @@ -118,13 +117,25 @@ func (h *Blueprint) List() error { if len(val.Watcher.Ignore) > 0 { fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Ignored paths"), ":", h.Magenta.Regular(val.Watcher.Ignore)) } - fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Files preview"), ":", h.Magenta.Regular(val.Watcher.Preview)) - fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Cli"), ":") - fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Streams"), ":", h.Magenta.Regular(val.Cli.Streams)) - fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("File"), ":") - fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Streams"), ":", h.Magenta.Regular(val.File.Streams)) - fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Logs"), ":", h.Magenta.Regular(val.File.Logs)) - fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Errors"), ":", h.Magenta.Regular(val.File.Errors)) + if len(val.Watcher.Scripts) > 0 { + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Scripts"), ":") + for _, v := range val.Watcher.Scripts { + if v.Command != "" { + fmt.Println(h.Magenta.Regular("|"), "\t\t\t", h.Magenta.Regular("-"), h.Yellow.Regular("Command"), ":", h.Magenta.Regular(v.Command)) + if v.Path != "" { + fmt.Println(h.Magenta.Regular("|"), "\t\t\t", h.Yellow.Regular("Path"), ":", h.Magenta.Regular(v.Path)) + } + if v.Type != "" { + fmt.Println(h.Magenta.Regular("|"), "\t\t\t", h.Yellow.Regular("Type"), ":", h.Magenta.Regular(v.Type)) + } + } + } + } + fmt.Println(h.Magenta.Regular("|"), "\t", h.Yellow.Regular("Streams"), ":") + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("Cli Out"), ":", h.Magenta.Regular(val.Streams.CliOut)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("File Out"), ":", h.Magenta.Regular(val.Streams.FileOut)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("File Log"), ":", h.Magenta.Regular(val.Streams.FileLog)) + fmt.Println(h.Magenta.Regular("|"), "\t\t", h.Yellow.Regular("File Err"), ":", h.Magenta.Regular(val.Streams.FileErr)) } return nil } diff --git a/watcher/exec.go b/watcher/exec.go index c0ce047..d197576 100644 --- a/watcher/exec.go +++ b/watcher/exec.go @@ -141,7 +141,7 @@ func (p *Project) goTools(dir string, name string, cmd ...string) (string, error return "", nil } -// Cmds exec a list of defined commands +// Exec an additional command from a defined path if specified func (p *Project) command(cmd Command) (errors string, logs string) { var stdout bytes.Buffer var stderr bytes.Buffer diff --git a/watcher/main.go b/watcher/main.go index 2c51ca4..c3a6f80 100644 --- a/watcher/main.go +++ b/watcher/main.go @@ -39,15 +39,14 @@ type Project struct { Name string `yaml:"name" json:"name"` Path string `yaml:"path" json:"path"` Fmt bool `yaml:"fmt" json:"fmt"` - Test bool `yaml:"test" json:"test"` 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"` - Cli Cli `yaml:"cli,omitempty" json:"cli,omitempty"` - File File `yaml:"file,omitempty" json:"file,omitempty"` + Streams Streams `yaml:"streams" json:"streams"` Buffer Buffer `yaml:"-" json:"buffer"` parent *Blueprint path string @@ -55,30 +54,26 @@ type Project struct { // Watcher struct defines the livereload's logic type Watcher struct { - Preview bool `yaml:"preview" json:"preview"` - Paths []string `yaml:"paths" json:"paths"` - Ignore []string `yaml:"ignore_paths" json:"ignore"` - Exts []string `yaml:"exts" json:"exts"` - Commands []Command `yaml:"commands,omitempty" json:"commands,omitempty"` + Preview bool `yaml:"preview" json:"preview"` + Paths []string `yaml:"paths" json:"paths"` + Ignore []string `yaml:"ignore_paths" json:"ignore"` + Exts []string `yaml:"exts" json:"exts"` + Scripts []Command `yaml:"scripts,omitempty" json:"scripts,omitempty"` } // Command options type Command struct { - Type string `yaml:"type,omitempty" json:"type,omitempty"` - Command string `yaml:"command,omitempty" json:"command,omitempty"` - Path string `yaml:"path,omitempty" json:"path,omitempty"` -} - -// Cli output status, enables or disables -type Cli struct { - Streams bool `yaml:"streams" json:"streams"` + Type string `yaml:"type" json:"type"` + Command string `yaml:"command" json:"command"` + Path string `yaml:"path" json:"path"` } // File determinates the status of each log files (streams, logs, errors) -type File struct { - Streams bool `yaml:"streams,omitempty" json:"streams,omitempty"` - Logs bool `yaml:"logs,omitempty" json:"logs,omitempty"` - Errors bool `yaml:"errors,omitempty" json:"errors,omitempty"` +type Streams struct { + CliOut bool `yaml:"cli_out" json:"cli_out"` + FileOut bool `yaml:"file_out" json:"file_out"` + FileLog bool `yaml:"file_log" json:"file_log"` + FileErr bool `yaml:"file_err" json:"file_err"` } // Buffer define an array buffer for each log files diff --git a/watcher/watcher.go b/watcher/watcher.go index 1441f7b..a9cc41e 100644 --- a/watcher/watcher.go +++ b/watcher/watcher.go @@ -43,7 +43,7 @@ func (p *Project) watchByPolling() { }() p.cmd("before") - p.Fatal(p.walks(watcher)) + p.Fatal(p.watch(watcher)) go p.routines(channel, &wr) p.LastChangedOn = time.Now().Truncate(time.Second) walk := func(changed string, info os.FileInfo, err error) error { @@ -64,16 +64,17 @@ func (p *Project) watchByPolling() { file := changed[:i] + ext path := filepath.Dir(changed[:i]) if changed[:i] != "" && inArray(ext, p.Watcher.Exts) { - p.LastChangedOn = time.Now().Truncate(time.Second) - msg = fmt.Sprintln(p.pname(p.Name, 4), ":", p.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), p.Magenta.Bold(file)) - out = BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file} - p.print("log", out, msg, "") - // stop and run again if p.Run { close(channel) channel = make(chan bool) } - // handle multiple errors, need a better way + p.LastChangedOn = time.Now().Truncate(time.Second) + // repeat the initial cycle + msg = fmt.Sprintln(p.pname(p.Name, 4), ":", p.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), p.Magenta.Bold(file)) + out = BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file} + p.print("log", out, msg, "") + + p.cmd("change") p.fmt(file) p.test(path) p.generate(path) @@ -98,7 +99,7 @@ func (p *Project) watchByPolling() { select { case <-exit: return - case <-time.After(p.parent.Polling.Interval / time.Duration(len(p.Watcher.Paths))): + case <-time.After(p.parent.Legacy.Interval / time.Duration(len(p.Watcher.Paths))): } } } @@ -118,7 +119,7 @@ func (p *Project) watchByNotify() { }() p.cmd("before") - p.Fatal(p.walks(watcher)) + p.Fatal(p.watch(watcher)) go p.routines(channel, &wr) p.LastChangedOn = time.Now().Truncate(time.Second) for { @@ -139,16 +140,17 @@ func (p *Project) watchByNotify() { file := event.Name[:i] + ext path := filepath.Dir(event.Name[:i]) if event.Name[:i] != "" && inArray(ext, p.Watcher.Exts) { - p.LastChangedOn = time.Now().Truncate(time.Second) - msg = fmt.Sprintln(p.pname(p.Name, 4), ":", p.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), p.Magenta.Bold(file)) - out = BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file} - p.print("log", out, msg, "") - // stop and run again if p.Run { close(channel) channel = make(chan bool) } - // handle multiple errors, need a better way + p.LastChangedOn = time.Now().Truncate(time.Second) + // repeat the initial cycle + msg = fmt.Sprintln(p.pname(p.Name, 4), ":", p.Magenta.Bold(strings.ToUpper(ext[1:])+" changed"), p.Magenta.Bold(file)) + out = BufferOut{Time: time.Now(), Text: strings.ToUpper(ext[1:]) + " changed " + file} + p.print("log", out, msg, "") + + p.cmd("change") p.fmt(file) p.test(path) p.generate(path) @@ -166,6 +168,55 @@ func (p *Project) watchByNotify() { } } +// Watch the files tree of a project +func (p *Project) watch(watcher watcher) error { + var files, folders int64 + wd, _ := os.Getwd() + walk := func(path string, info os.FileInfo, err error) error { + if !p.ignore(path) { + if (info.IsDir() && len(filepath.Ext(path)) == 0 && !strings.HasPrefix(path, ".")) && !strings.Contains(path, "/.") || (inArray(filepath.Ext(path), p.Watcher.Exts)) { + if p.Watcher.Preview { + log.Println(p.pname(p.Name, 1), ":", path) + } + if err = watcher.Add(path); err != nil { + return filepath.SkipDir + } + if inArray(filepath.Ext(path), p.Watcher.Exts) { + files++ + p.fmt(path) + } else { + folders++ + p.generate(path) + p.test(path) + } + } + } + return nil + } + if p.path == "." || p.path == "/" { + p.base = wd + p.path = p.Wdir() + } else if filepath.IsAbs(p.path) { + p.base = p.path + } else { + p.base = filepath.Join(wd, p.path) + } + for _, dir := range p.Watcher.Paths { + base := filepath.Join(p.base, dir) + if _, err := os.Stat(base); err == nil { + if err := filepath.Walk(base, walk); err != nil { + log.Println(p.Red.Bold(err.Error())) + } + } else { + return errors.New(base + " path doesn't exist") + } + } + msg = fmt.Sprintln(p.pname(p.Name, 1), ":", p.Blue.Bold("Watching"), p.Magenta.Bold(files), "file/s", p.Magenta.Bold(folders), "folder/s") + out = BufferOut{Time: time.Now(), Text: "Watching " + strconv.FormatInt(files, 10) + " files/s " + strconv.FormatInt(folders, 10) + " folder/s"} + p.print("log", out, msg, "") + return nil +} + // Install calls an implementation of "go install" func (p *Project) install() error { if p.Bin { @@ -266,7 +317,7 @@ func (p *Project) test(path string) error { // Cmd calls an wrapper for execute the commands after/before func (p *Project) cmd(flag string) { - for _, cmd := range p.Watcher.Commands { + for _, cmd := range p.Watcher.Scripts { if strings.ToLower(cmd.Type) == flag { errors, logs := p.command(cmd) msg = fmt.Sprintln(p.pname(p.Name, 5), ":", p.Green.Bold("Command"), p.Green.Bold("\"")+cmd.Command+p.Green.Bold("\"")) @@ -291,55 +342,6 @@ func (p *Project) cmd(flag string) { } } -// Walks the file tree of a project -func (p *Project) walks(watcher watcher) error { - var files, folders int64 - wd, _ := os.Getwd() - walk := func(path string, info os.FileInfo, err error) error { - if !p.ignore(path) { - if (info.IsDir() && len(filepath.Ext(path)) == 0 && !strings.HasPrefix(path, ".")) && !strings.Contains(path, "/.") || (inArray(filepath.Ext(path), p.Watcher.Exts)) { - if p.Watcher.Preview { - log.Println(p.pname(p.Name, 1), ":", path) - } - if err = watcher.Add(path); err != nil { - return filepath.SkipDir - } - if inArray(filepath.Ext(path), p.Watcher.Exts) { - files++ - p.fmt(path) - } else { - folders++ - p.generate(path) - p.test(path) - } - } - } - return nil - } - if p.path == "." || p.path == "/" { - p.base = wd - p.path = p.Wdir() - } else if filepath.IsAbs(p.path) { - p.base = p.path - } else { - p.base = filepath.Join(wd, p.path) - } - for _, dir := range p.Watcher.Paths { - base := filepath.Join(p.base, dir) - if _, err := os.Stat(base); err == nil { - if err := filepath.Walk(base, walk); err != nil { - log.Println(p.Red.Bold(err.Error())) - } - } else { - return errors.New(base + " path doesn't exist") - } - } - msg = fmt.Sprintln(p.pname(p.Name, 1), ":", p.Blue.Bold("Watching"), p.Magenta.Bold(files), "file/s", p.Magenta.Bold(folders), "folder/s") - out = BufferOut{Time: time.Now(), Text: "Watching " + strconv.FormatInt(files, 10) + " files/s " + strconv.FormatInt(folders, 10) + " folder/s"} - p.print("log", out, msg, "") - return nil -} - // Ignore and validate a path func (p *Project) ignore(str string) bool { for _, v := range p.Watcher.Ignore { @@ -388,20 +390,20 @@ func (p *Project) print(t string, o BufferOut, msg string, stream string) { switch t { case "out": p.Buffer.StdOut = append(p.Buffer.StdOut, o) - if p.File.Streams { - f := p.Create(p.base, p.parent.Resources.Streams) + if p.Streams.FileOut { + f := p.Create(p.base, p.parent.Resources.Outputs) t := time.Now() s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Text, "\r\n"} if _, err := f.WriteString(strings.Join(s, " ")); err != nil { p.Fatal(err, "") } } - if msg != "" && p.Cli.Streams { + if msg != "" && p.Streams.CliOut { log.Print(msg) } case "log": p.Buffer.StdLog = append(p.Buffer.StdLog, o) - if p.File.Logs { + if p.Streams.FileLog { f := p.Create(p.base, p.parent.Resources.Logs) t := time.Now() s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Text, "\r\n"} @@ -417,7 +419,7 @@ func (p *Project) print(t string, o BufferOut, msg string, stream string) { } case "error": p.Buffer.StdErr = append(p.Buffer.StdErr, o) - if p.File.Errors { + if p.Streams.FileErr { f := p.Create(p.base, p.parent.Resources.Errors) t := time.Now() s := []string{t.Format("2006-01-02 15:04:05"), strings.ToUpper(p.Name), ":", o.Type, o.Text, o.Path, "\r\n"}