mirror of
				https://github.com/beego/bee.git
				synced 2025-10-31 17:33:26 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			188 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2013 bee authors
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License"): you may
 | |
| // not use this file except in compliance with the License. You may obtain
 | |
| // a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | |
| // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | |
| // License for the specific language governing permissions and limitations
 | |
| // under the License.
 | |
| 
 | |
| package main
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"log"
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"strings"
 | |
| 	"sync"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/Unknwon/com"
 | |
| 	"github.com/howeyc/fsnotify"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	cmd       *exec.Cmd
 | |
| 	state     sync.Mutex
 | |
| 	eventTime = make(map[string]int64)
 | |
| )
 | |
| 
 | |
| func NewWatcher(paths []string) {
 | |
| 	watcher, err := fsnotify.NewWatcher()
 | |
| 	if err != nil {
 | |
| 		com.ColorLog("[ERRO] Fail to create new Watcher[ %s ]\n", err)
 | |
| 		os.Exit(2)
 | |
| 	}
 | |
| 
 | |
| 	go func() {
 | |
| 		for {
 | |
| 			select {
 | |
| 			case e := <-watcher.Event:
 | |
| 				isbuild := true
 | |
| 
 | |
| 				// Skip TMP files for Sublime Text.
 | |
| 				if checkTMPFile(e.Name) {
 | |
| 					continue
 | |
| 				}
 | |
| 				if !checkIsGoFile(e.Name) {
 | |
| 					continue
 | |
| 				}
 | |
| 
 | |
| 				mt := getFileModTime(e.Name)
 | |
| 				if t := eventTime[e.Name]; mt == t {
 | |
| 					com.ColorLog("[SKIP] # %s #\n", e.String())
 | |
| 					isbuild = false
 | |
| 				}
 | |
| 
 | |
| 				eventTime[e.Name] = mt
 | |
| 
 | |
| 				if isbuild {
 | |
| 					com.ColorLog("[EVEN] %s\n", e)
 | |
| 					go Autobuild()
 | |
| 				}
 | |
| 			case err := <-watcher.Error:
 | |
| 				log.Fatal("error:", err)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		time.Sleep(500 * time.Millisecond)
 | |
| 	}()
 | |
| 
 | |
| 	com.ColorLog("[INFO] Initializing watcher...\n")
 | |
| 	for _, path := range paths {
 | |
| 		com.ColorLog("[TRAC] Directory( %s )\n", path)
 | |
| 		err = watcher.Watch(path)
 | |
| 		if err != nil {
 | |
| 			com.ColorLog("[ERRO] Fail to watch directory[ %s ]\n", err)
 | |
| 			os.Exit(2)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| // getFileModTime retuens unix timestamp of `os.File.ModTime` by given path.
 | |
| func getFileModTime(path string) int64 {
 | |
| 	path = strings.Replace(path, "\\", "/", -1)
 | |
| 	f, err := os.Open(path)
 | |
| 	if err != nil {
 | |
| 		com.ColorLog("[ERRO] Fail to open file[ %s ]\n", err)
 | |
| 		return time.Now().Unix()
 | |
| 	}
 | |
| 	defer f.Close()
 | |
| 
 | |
| 	fi, err := f.Stat()
 | |
| 	if err != nil {
 | |
| 		com.ColorLog("[ERRO] Fail to get file information[ %s ]\n", err)
 | |
| 		return time.Now().Unix()
 | |
| 	}
 | |
| 
 | |
| 	return fi.ModTime().Unix()
 | |
| }
 | |
| 
 | |
| func Autobuild() {
 | |
| 	state.Lock()
 | |
| 	defer state.Unlock()
 | |
| 
 | |
| 	com.ColorLog("[INFO] Start building...\n")
 | |
| 	path, _ := os.Getwd()
 | |
| 	os.Chdir(path)
 | |
| 
 | |
| 	var err error
 | |
| 	// For applications use full import path like "github.com/.../.."
 | |
| 	// are able to use "go install" to reduce build time.
 | |
| 	if conf.GoInstall {
 | |
| 		icmd := exec.Command("go", "install")
 | |
| 		icmd.Stdout = os.Stdout
 | |
| 		icmd.Stderr = os.Stderr
 | |
| 		err = icmd.Run()
 | |
| 	}
 | |
| 
 | |
| 	if err == nil {
 | |
| 		bcmd := exec.Command("go", "build")
 | |
| 		bcmd.Stdout = os.Stdout
 | |
| 		bcmd.Stderr = os.Stderr
 | |
| 		err = bcmd.Run()
 | |
| 	}
 | |
| 
 | |
| 	if err != nil {
 | |
| 		com.ColorLog("[ERRO] ============== Build failed ===================\n")
 | |
| 		return
 | |
| 	}
 | |
| 	com.ColorLog("[SUCC] Build was successful\n")
 | |
| 	Restart(appname)
 | |
| }
 | |
| 
 | |
| func Kill() {
 | |
| 	defer func() {
 | |
| 		if e := recover(); e != nil {
 | |
| 			fmt.Println("Kill -> ", e)
 | |
| 		}
 | |
| 	}()
 | |
| 	if cmd != nil {
 | |
| 		cmd.Process.Kill()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func Restart(appname string) {
 | |
| 	Debugf("kill running process")
 | |
| 	Kill()
 | |
| 	go Start(appname)
 | |
| }
 | |
| 
 | |
| func Start(appname string) {
 | |
| 	com.ColorLog("[INFO] Restarting %s ...\n", appname)
 | |
| 	if strings.Index(appname, "./") == -1 {
 | |
| 		appname = "./" + appname
 | |
| 	}
 | |
| 
 | |
| 	cmd = exec.Command(appname)
 | |
| 	cmd.Stdout = os.Stdout
 | |
| 	cmd.Stderr = os.Stderr
 | |
| 
 | |
| 	go cmd.Run()
 | |
| 	com.ColorLog("[INFO] %s is running...\n", appname)
 | |
| 	started <- true
 | |
| }
 | |
| 
 | |
| // checkTMPFile returns true if the event was for TMP files.
 | |
| func checkTMPFile(name string) bool {
 | |
| 	if strings.HasSuffix(strings.ToLower(name), ".tmp") {
 | |
| 		return true
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // checkIsGoFile returns true if the name HasSuffix ".go".
 | |
| func checkIsGoFile(name string) bool {
 | |
| 	if strings.HasSuffix(name, ".go") {
 | |
| 		return true
 | |
| 	}
 | |
| 	return false
 | |
| }
 | 
