#119 fixed workflow

This commit is contained in:
asoseil 2017-11-14 16:12:37 +01:00
parent f3fc262994
commit 331b181b69
3 changed files with 96 additions and 75 deletions

6
cmd.go
View File

@ -9,9 +9,9 @@ import (
// Tool options customizable, should be moved in Cmd // Tool options customizable, should be moved in Cmd
type tool struct { type tool struct {
name, err string name, err, out string
cmd, options []string cmd, options []string
dir, status bool dir, status bool
} }
// Cmds list of go commands // Cmds list of go commands

View File

@ -39,6 +39,7 @@ func (p *Project) goCompile(stop <-chan bool, method []string, args []string) (s
if err != nil { if err != nil {
return stderr.String(), err return stderr.String(), err
} }
return "", nil
} }
return "", nil return "", nil
} }
@ -213,6 +214,8 @@ func (p *Project) goTool(wg *sync.WaitGroup, stop <-chan bool, result chan<- too
tool.err = stderr.String() + out.String() tool.err = stderr.String() + out.String()
// send command result // send command result
result <- tool result <- tool
} else {
tool.out = out.String()
} }
return return
} }

View File

@ -118,16 +118,27 @@ L:
select { select {
case event := <-p.watcher.Events(): case event := <-p.watcher.Events():
if time.Now().Truncate(time.Second).After(p.lastTime) || event.Name != p.lastFile { if time.Now().Truncate(time.Second).After(p.lastTime) || event.Name != p.lastFile {
// event time
eventTime := time.Now()
// file extension
ext := ext(event.Name)
if ext == "" {
ext = "DIR"
}
// change message
msg = fmt.Sprintln(p.pname(p.Name, 4), ":", magenta.bold(strings.ToUpper(ext)), "changed", magenta.bold(event.Name))
out = BufferOut{Time: time.Now(), Text: ext + " changed " + event.Name}
// switch event type
switch event.Op { switch event.Op {
case fsnotify.Chmod: case fsnotify.Chmod:
case fsnotify.Remove: case fsnotify.Remove:
ext := ext(event.Name) p.watcher.Remove(event.Name)
if !strings.Contains(ext, "_") && !strings.Contains(ext, ".") && array(ext, p.Watcher.Exts) { if !strings.Contains(ext, "_") && !strings.Contains(ext, ".") && array(ext, p.Watcher.Exts) {
close(stop) close(stop)
stop = make(chan bool) stop = make(chan bool)
p.changed(event, stop) // stop p.stamp("log", out, msg, "")
go p.routines(stop, p.watcher, "")
} }
p.watcher.Remove(event.Name)
default: default:
file, err := os.Stat(event.Name) file, err := os.Stat(event.Name)
if err != nil { if err != nil {
@ -136,15 +147,20 @@ L:
if file.IsDir() { if file.IsDir() {
filepath.Walk(event.Name, p.walk) filepath.Walk(event.Name, p.walk)
} else if file.Size() > 0 { } else if file.Size() > 0 {
// used only for test and debug
if p.parent.Settings.Recovery { if p.parent.Settings.Recovery {
log.Println(event) log.Println(event)
} }
ext := ext(event.Name)
if !strings.Contains(ext, "_") && !strings.Contains(ext, ".") && array(ext, p.Watcher.Exts) { if !strings.Contains(ext, "_") && !strings.Contains(ext, ".") && array(ext, p.Watcher.Exts) {
// change watched // change watched
close(stop) // check if a file is still writing #119
stop = make(chan bool) if event.Op != fsnotify.Write || eventTime.Truncate(time.Millisecond).After(file.ModTime().Truncate(time.Millisecond)) {
p.changed(event, stop) close(stop)
stop = make(chan bool)
// stop and start again
p.stamp("log", out, msg, "")
go p.routines(stop, p.watcher, event.Name)
}
} }
p.lastTime = time.Now().Truncate(time.Second) p.lastTime = time.Now().Truncate(time.Second)
p.lastFile = event.Name p.lastFile = event.Name
@ -189,24 +205,12 @@ func (p *Project) config(r *realize) {
if len(p.Cmds.Fmt.Args) == 0 { if len(p.Cmds.Fmt.Args) == 0 {
p.Cmds.Fmt.Args = []string{"-s", "-w", "-e", "./"} p.Cmds.Fmt.Args = []string{"-s", "-w", "-e", "./"}
} }
p.tools = append(p.tools, tool{
status: p.Cmds.Fix.Status,
cmd: replace([]string{"go fix"}, p.Cmds.Fix.Method),
options: split([]string{}, p.Cmds.Fix.Args),
name: "Fix",
})
p.tools = append(p.tools, tool{ p.tools = append(p.tools, tool{
status: p.Cmds.Clean.Status, status: p.Cmds.Clean.Status,
cmd: replace([]string{"go clean"}, p.Cmds.Clean.Method), cmd: replace([]string{"go clean"}, p.Cmds.Clean.Method),
options: split([]string{}, p.Cmds.Clean.Args), options: split([]string{}, p.Cmds.Clean.Args),
name: "Clean", name: "Clean",
}) })
p.tools = append(p.tools, tool{
status: p.Cmds.Fmt.Status,
cmd: replace([]string{"gofmt"}, p.Cmds.Fmt.Method),
options: split([]string{}, p.Cmds.Fmt.Args),
name: "Fmt",
})
p.tools = append(p.tools, tool{ p.tools = append(p.tools, tool{
status: p.Cmds.Generate.Status, status: p.Cmds.Generate.Status,
cmd: replace([]string{"go", "generate"}, p.Cmds.Generate.Method), cmd: replace([]string{"go", "generate"}, p.Cmds.Generate.Method),
@ -215,11 +219,16 @@ func (p *Project) config(r *realize) {
dir: true, dir: true,
}) })
p.tools = append(p.tools, tool{ p.tools = append(p.tools, tool{
status: p.Cmds.Test.Status, status: p.Cmds.Fix.Status,
cmd: replace([]string{"go", "test"}, p.Cmds.Test.Method), cmd: replace([]string{"go fix"}, p.Cmds.Fix.Method),
options: split([]string{}, p.Cmds.Test.Args), options: split([]string{}, p.Cmds.Fix.Args),
name: "Test", name: "Fix",
dir: true, })
p.tools = append(p.tools, tool{
status: p.Cmds.Fmt.Status,
cmd: replace([]string{"gofmt"}, p.Cmds.Fmt.Method),
options: split([]string{}, p.Cmds.Fmt.Args),
name: "Fmt",
}) })
p.tools = append(p.tools, tool{ p.tools = append(p.tools, tool{
status: p.Cmds.Vet.Status, status: p.Cmds.Vet.Status,
@ -228,6 +237,13 @@ func (p *Project) config(r *realize) {
name: "Vet", name: "Vet",
dir: true, dir: true,
}) })
p.tools = append(p.tools, tool{
status: p.Cmds.Test.Status,
cmd: replace([]string{"go", "test"}, p.Cmds.Test.Method),
options: split([]string{}, p.Cmds.Test.Args),
name: "Test",
dir: true,
})
p.Cmds.Install = Cmd{ p.Cmds.Install = Cmd{
Status: p.Cmds.Install.Status, Status: p.Cmds.Install.Status,
Args: append([]string{}, p.Cmds.Install.Args...), Args: append([]string{}, p.Cmds.Install.Args...),
@ -291,10 +307,11 @@ func (p *Project) cmd(stop <-chan bool, flag string, global bool) {
// Compile is used for run and display the result of a compiling // Compile is used for run and display the result of a compiling
func (p *Project) compile(stop <-chan bool, cmd Cmd) error { func (p *Project) compile(stop <-chan bool, cmd Cmd) error {
if cmd.Status { if cmd.Status {
start := time.Now() var start time.Time
channel := make(chan Result) channel := make(chan Result)
go func() { go func() {
log.Println(p.pname(p.Name, 1), ":", cmd.startTxt) log.Println(p.pname(p.Name, 1), ":", cmd.startTxt)
start = time.Now()
stream, err := p.goCompile(stop, cmd.method, cmd.Args) stream, err := p.goCompile(stop, cmd.method, cmd.Args)
if stream != msgStop { if stream != msgStop {
channel <- Result{stream, err} channel <- Result{stream, err}
@ -352,7 +369,7 @@ func (p *Project) tool(stop <-chan bool, path string) error {
// no need a sequence, these commands can be asynchronous // no need a sequence, these commands can be asynchronous
if element.status { if element.status {
wg.Add(1) wg.Add(1)
go p.goTool(&wg, stop, result, path, element) p.goTool(&wg, stop, result, path, element)
} }
} }
wg.Wait() wg.Wait()
@ -362,9 +379,15 @@ func (p *Project) tool(stop <-chan bool, path string) error {
for { for {
select { select {
case tool := <-result: case tool := <-result:
msg = fmt.Sprintln(p.pname(p.Name, 2), ":", red.bold(tool.name), red.regular("there are some errors in"), ":", magenta.bold(path)) if tool.err != "" {
buff := BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: tool.name, Stream: tool.err} msg = fmt.Sprintln(p.pname(p.Name, 2), ":", red.bold(tool.name), red.regular("there are some errors in"), ":", magenta.bold(path))
p.stamp("error", buff, msg, tool.err) buff := BufferOut{Time: time.Now(), Text: "there are some errors in", Path: path, Type: tool.name, Stream: tool.err}
p.stamp("error", buff, msg, tool.err)
} else if tool.out != "" {
msg = fmt.Sprintln(p.pname(p.Name, 3), ":", red.bold(tool.name), red.regular("outputs"), ":", blue.bold(path))
buff := BufferOut{Time: time.Now(), Text: "outputs", Path: path, Type: tool.name, Stream: tool.out}
p.stamp("out", buff, msg, tool.out)
}
case <-done: case <-done:
break loop break loop
case <-stop: case <-stop:
@ -375,19 +398,6 @@ func (p *Project) tool(stop <-chan bool, path string) error {
return nil return nil
} }
// Changed detect a file/directory change
func (p *Project) changed(event fsnotify.Event, stop chan bool) {
e := ext(event.Name)
if e == "" {
e = "DIR"
}
msg = fmt.Sprintln(p.pname(p.Name, 4), ":", magenta.bold(strings.ToUpper(e)), "changed", magenta.bold(event.Name))
out = BufferOut{Time: time.Now(), Text: ext(event.Name) + " changed " + event.Name}
p.stamp("log", out, msg, "")
//stop running process
go p.routines(stop, p.watcher, event.Name)
}
// Watch the files tree of a project // Watch the files tree of a project
func (p *Project) walk(path string, info os.FileInfo, err error) error { func (p *Project) walk(path string, info os.FileInfo, err error) error {
for _, v := range p.Watcher.Ignore { for _, v := range p.Watcher.Ignore {
@ -476,45 +486,53 @@ func (p *Project) routines(stop <-chan bool, watcher FileWatcher, path string) {
} }
} }
}() }()
if !done { if done {
// before command return
p.cmd(stop, "before", false)
} }
if !done { // before command
// Go supported tools p.cmd(stop, "before", false)
p.tool(stop, path) if done {
// Prevent fake events on polling startup return
p.init = true
} }
// Go supported tools
p.tool(stop, path)
// Prevent fake events on polling startup
p.init = true
// prevent errors using realize without config with only run flag // prevent errors using realize without config with only run flag
if p.Cmds.Run && !p.Cmds.Install.Status && !p.Cmds.Build.Status { if p.Cmds.Run && !p.Cmds.Install.Status && !p.Cmds.Build.Status {
p.Cmds.Install.Status = true p.Cmds.Install.Status = true
} }
if !done { if done {
install = p.compile(stop, p.Cmds.Install) return
} }
if !done { install = p.compile(stop, p.Cmds.Install)
build = p.compile(stop, p.Cmds.Build) if done {
return
} }
if !done && (install == nil && build == nil) { build = p.compile(stop, p.Cmds.Build)
if p.Cmds.Run { if done {
start := time.Now() return
runner := make(chan bool, 1) }
go func() { if install == nil && build == nil && p.Cmds.Run {
log.Println(p.pname(p.Name, 1), ":", "Running..") var start time.Time
p.goRun(stop, runner) runner := make(chan bool, 1)
}() go func() {
select { log.Println(p.pname(p.Name, 1), ":", "Running..")
case <-runner: start = time.Now()
msg = fmt.Sprintln(p.pname(p.Name, 5), ":", green.regular("Started"), "in", magenta.regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s")) p.goRun(stop, runner)
out = BufferOut{Time: time.Now(), Text: "Started in " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"} }()
p.stamp("log", out, msg, "") select {
case <-stop: case <-runner:
return msg = fmt.Sprintln(p.pname(p.Name, 5), ":", green.regular("Started"), "in", magenta.regular(big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3), " s"))
} out = BufferOut{Time: time.Now(), Text: "Started in " + big.NewFloat(float64(time.Since(start).Seconds())).Text('f', 3) + " s"}
p.stamp("log", out, msg, "")
case <-stop:
return
} }
} }
if !done { if done {
p.cmd(stop, "after", false) return
} }
p.cmd(stop, "after", false)
} }