From 0cf1a553de559221284bf46c32013f7a1ac2e98e Mon Sep 17 00:00:00 2001 From: sun shengxiang Date: Sat, 6 Jul 2013 15:30:57 +0800 Subject: [PATCH] half work --- createapp.go | 1 + start.go | 24 +++++++---- util.go | 30 ++++++++++++++ watch.go | 113 +++++++++++++++++++++++++++++++++++---------------- 4 files changed, 125 insertions(+), 43 deletions(-) create mode 100644 util.go diff --git a/createapp.go b/createapp.go index 176cc19..7c2fce9 100644 --- a/createapp.go +++ b/createapp.go @@ -45,6 +45,7 @@ func createapp(cmd *Command, args []string) { } gopath := os.Getenv("GOPATH") + Debugf("gopath:%s", gopath) if gopath == "" { fmt.Println("you should set GOPATH in the env") os.Exit(2) diff --git a/start.go b/start.go index de09dfa..8eb4d42 100644 --- a/start.go +++ b/start.go @@ -4,6 +4,7 @@ import ( "fmt" "os" path "path/filepath" + "runtime" ) var cmdStart = &Command{ @@ -32,22 +33,31 @@ func init() { cmdStart.Run = startapp } +var appname string + func startapp(cmd *Command, args []string) { if len(args) != 1 { fmt.Println("error args") os.Exit(2) } crupath, _ := os.Getwd() + Debugf("current path:%s\n", crupath) + var paths []string paths = append(paths, path.Join(crupath, "controllers"), path.Join(crupath, "models")) NewWatcher(paths) - go Start(args[0]) + appname = args[0] + Autobuild() for { - select { - case <-restart: - go Start(args[0]) - case <-builderror: - fmt.Println("build error:", builderror) - } + runtime.Gosched() } + //go Start(args[0]) + //for { + // select { + // case <-restart: + // go Start(args[0]) + // case err := <-builderror: + // fmt.Println("build error:", err) + // } + //} } diff --git a/util.go b/util.go new file mode 100644 index 0000000..f8b7e13 --- /dev/null +++ b/util.go @@ -0,0 +1,30 @@ +package main + +import "fmt" +import "os" +import "runtime" +import "path/filepath" + +// Go is a basic promise implementation: it wraps calls a function in a goroutine +// and returns a channel which will later return the function's return value. +func Go(f func() error) chan error { + ch := make(chan error) + go func() { + ch <- f() + }() + return ch +} + +// if os.env DEBUG set, debug is on +func Debugf(format string, a ...interface{}) { + if os.Getenv("DEBUG") != "" { + _, file, line, ok := runtime.Caller(1) + if !ok { + file = "" + line = -1 + } else { + file = filepath.Base(file) + } + fmt.Fprintf(os.Stderr, fmt.Sprintf("[debug] %s:%d %s\n", file, line, format), a...) + } +} diff --git a/watch.go b/watch.go index 97a65f9..e21e27b 100644 --- a/watch.go +++ b/watch.go @@ -1,27 +1,33 @@ package main import ( - "bytes" "fmt" "github.com/howeyc/fsnotify" - "io" + //"io" "log" "os" "os/exec" "runtime" + "sync" + "time" ) var ( builderror chan string restart chan bool cmd *exec.Cmd + state sync.Mutex + running bool ) func init() { builderror = make(chan string) - restart = make(chan bool) + //restart = make(chan bool) + running = false } +var eventTime = make(map[string]time.Time) + func NewWatcher(paths []string) { watcher, err := fsnotify.NewWatcher() if err != nil { @@ -32,8 +38,21 @@ func NewWatcher(paths []string) { for { select { case e := <-watcher.Event: - fmt.Println(e) - go Autobuild() + + isbuild := true + if t, ok := eventTime[e.String()]; ok { + //Debugf("%s pk %s", t, time.Now()) + if t.Add(time.Millisecond * 500).After(time.Now()) { + isbuild = false + } + } + Debugf("isbuild:%v", isbuild) + eventTime[e.String()] = time.Now() + + if isbuild { + fmt.Println(e) + go Autobuild() + } case err := <-watcher.Error: log.Fatal("error:", err) } @@ -64,23 +83,18 @@ func Autobuild() { } }() - fmt.Println("Autobuild") + fmt.Println("autobuild") path, _ := os.Getwd() os.Chdir(path) bcmd := exec.Command("go", "build") - var out bytes.Buffer - var berr bytes.Buffer - bcmd.Stdout = &out - bcmd.Stderr = &berr + bcmd.Stdout = os.Stdout + bcmd.Stderr = os.Stderr err := bcmd.Run() if err != nil { - fmt.Println("run error", err) - } - if out.String() == "" { - Kill() - } else { - builderror <- berr.String() + builderror <- err.Error() + return } + Restart(appname) } func Kill() { @@ -90,31 +104,58 @@ func Kill() { } } +func Restart(appname string) { + Kill() + go Start() +} func Start(appname string) { fmt.Println("start", appname) + cmd = exec.Command(appname) - stdout, err := cmd.StdoutPipe() - if err != nil { - fmt.Println("stdout:", err) - } - stderr, err := cmd.StderrPipe() - if err != nil { - fmt.Println("stdin:", err) - } - r := io.MultiReader(stdout, stderr) - err = cmd.Start() - if err != nil { - fmt.Println("cmd start:", err) - } + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + ch := Go(func() error { + state.Lock() + defer state.Unlock() + running = true + return cmd.Run() + }) for { - buf := make([]byte, 1024) - count, err := r.Read(buf) - if err != nil || count == 0 { - fmt.Println("process exit") - restart <- true + select { + case err := <-ch: + fmt.Println("cmd start error: ", err) + state.Lock() + defer state.Unlock() + running = false return - } else { - fmt.Println("result:", string(buf)) + case <-time.After(2 * time.Second): } } + + //stdout, err := cmd.StdoutPipe() + + //if err != nil { + //fmt.Println("stdout:", err) + //} + //stderr, err := cmd.StderrPipe() + //if err != nil { + //fmt.Println("stdin:", err) + //} + //r := io.MultiReader(stdout, stderr) + //err = cmd.Start() + //if err != nil { + // fmt.Println("cmd start:", err) + //} + //for { + // buf := make([]byte, 1024) + // count, err := r.Read(buf) + // if err != nil || count == 0 { + // fmt.Println("process exit") + // restart <- true + // return + // } else { + // fmt.Println("result:", string(buf)) + // } + //} }