增加 1.0版本
This commit is contained in:
commit
c03372f76e
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.idea/*
|
||||
fileboy
|
||||
fileboy.exe
|
||||
filegirl.yaml
|
8
build-darwin.bat
Normal file
8
build-darwin.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@echo off
|
||||
echo build start...
|
||||
SET CGO_ENABLED=0
|
||||
SET GOOS=darwin
|
||||
SET GOARCH=amd64
|
||||
go build -ldflags "-s -w"
|
||||
echo build success
|
||||
pause
|
8
build-linux.bat
Normal file
8
build-linux.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@echo off
|
||||
echo build start...
|
||||
SET CGO_ENABLED=0
|
||||
SET GOOS=linux
|
||||
SET GOARCH=amd64
|
||||
go build -ldflags "-s -w"
|
||||
echo build success
|
||||
pause
|
8
build-windows.bat
Normal file
8
build-windows.bat
Normal file
@ -0,0 +1,8 @@
|
||||
@echo off
|
||||
echo build start...
|
||||
SET CGO_ENABLED=0
|
||||
SET GOOS=windows
|
||||
SET GOARCH=amd64
|
||||
go build -ldflags "-s -w"
|
||||
echo build success
|
||||
pause
|
240
fileboy.go
Normal file
240
fileboy.go
Normal file
@ -0,0 +1,240 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"gopkg.in/fsnotify/fsnotify.v1"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Version = 1
|
||||
)
|
||||
|
||||
var (
|
||||
projectFolder string = "."
|
||||
|
||||
cfg *FileGirl
|
||||
|
||||
watcher *fsnotify.Watcher
|
||||
|
||||
cmd *exec.Cmd
|
||||
|
||||
runLock sync.Mutex
|
||||
)
|
||||
|
||||
type wDirState struct {
|
||||
Name string
|
||||
Recursive bool
|
||||
}
|
||||
|
||||
func parseConfig() {
|
||||
cfg = new(FileGirl)
|
||||
fc, err := ioutil.ReadFile(projectFolder + "/filegirl.yaml")
|
||||
if err != nil {
|
||||
log.Panicln("read filegirl.yaml file err: ", err)
|
||||
}
|
||||
err = yaml.Unmarshal(fc, cfg)
|
||||
if err != nil {
|
||||
log.Panicln("parsed filegirl.yaml failed: ", err)
|
||||
}
|
||||
if cfg.Core.Version > Version {
|
||||
log.Panicln("current fileboy support max version : ", Version)
|
||||
}
|
||||
log.Println(cfg)
|
||||
}
|
||||
|
||||
func eventDispatcher(event fsnotify.Event) {
|
||||
ext := path.Ext(event.Name)
|
||||
if len(cfg.Monitor.Types) > 0 &&
|
||||
cfg.Monitor.Types[0] != ".*" &&
|
||||
!inStringArray(ext, cfg.Monitor.Types) {
|
||||
//log.Println(ext, cfg.Monitor.Types, inStringArray(ext, cfg.Monitor.Types))
|
||||
return
|
||||
}
|
||||
switch event.Op {
|
||||
case fsnotify.Create:
|
||||
case fsnotify.Write:
|
||||
log.Println("event write : ", event.Name)
|
||||
if cmd != nil {
|
||||
err := cmd.Process.Kill()
|
||||
if err != nil {
|
||||
log.Println("err: ", err)
|
||||
}
|
||||
log.Println("stop old process ")
|
||||
}
|
||||
go run()
|
||||
case fsnotify.Remove:
|
||||
case fsnotify.Rename:
|
||||
}
|
||||
}
|
||||
|
||||
func run() {
|
||||
runLock.Lock()
|
||||
defer runLock.Unlock()
|
||||
for i := 0; i < len(cfg.Command.Exec); i++ {
|
||||
carr := cmdParse2Array(cfg.Command.Exec[i])
|
||||
cmd = exec.Command(carr[0], carr[1:]...)
|
||||
//cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: syscall.CREATE_UNICODE_ENVIRONMENT}
|
||||
cmd.Stdin = os.Stdin
|
||||
//cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
log.Println("error=>", err.Error())
|
||||
return
|
||||
}
|
||||
cmd.Start()
|
||||
reader := bufio.NewReader(stdout)
|
||||
for {
|
||||
line, err2 := reader.ReadString('\n')
|
||||
if err2 != nil || io.EOF == err2 {
|
||||
break
|
||||
}
|
||||
log.Print(line)
|
||||
}
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
log.Println("cmd wait err ", err)
|
||||
break
|
||||
}
|
||||
err = cmd.Process.Kill()
|
||||
if err != nil {
|
||||
log.Println("cmd cannot kill ", err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("end ")
|
||||
}
|
||||
|
||||
func addWatcher() {
|
||||
dirs := make([]string, 0)
|
||||
for i := 0; i < len(cfg.Monitor.IncludeDirs); i++ {
|
||||
darr := dirParse2Array(cfg.Monitor.IncludeDirs[i])
|
||||
if len(darr) < 1 || len(darr) > 2 {
|
||||
log.Fatalln("filegirl section monitor dirs is error. ", cfg.Monitor.IncludeDirs[i])
|
||||
}
|
||||
if darr[0] == "." {
|
||||
if len(darr) == 2 && darr[1] == "*" {
|
||||
dirs = make([]string, 0)
|
||||
dirs = append(dirs, ".")
|
||||
listFile(projectFolder, func(d string) {
|
||||
dirs = arrayUniqueAdd(dirs, d)
|
||||
})
|
||||
} else {
|
||||
dirs = arrayUniqueAdd(dirs, projectFolder)
|
||||
}
|
||||
break
|
||||
} else {
|
||||
if len(darr) == 2 && darr[1] == "*" {
|
||||
listFile(projectFolder+"/"+darr[0], func(d string) {
|
||||
dirs = arrayUniqueAdd(dirs, d)
|
||||
})
|
||||
} else {
|
||||
dirs = arrayUniqueAdd(dirs, projectFolder+"/"+darr[0])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
for i := 0; i < len(cfg.Monitor.ExceptDirs); i++ {
|
||||
p := projectFolder + "/" + cfg.Monitor.ExceptDirs[i]
|
||||
dirs = arrayRemoveElement(dirs, p)
|
||||
listFile(p, func(d string) {
|
||||
dirs = arrayRemoveElement(dirs, d)
|
||||
})
|
||||
}
|
||||
for _, dir := range dirs {
|
||||
log.Println("watcher add -> ", dir)
|
||||
err := watcher.Add(dir)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
log.Println("fileboy is ready.")
|
||||
}
|
||||
|
||||
func initWatcher() {
|
||||
parseConfig()
|
||||
var err error
|
||||
watcher, err = fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
defer watcher.Close()
|
||||
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
eventDispatcher(event)
|
||||
case err, ok := <-watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Println("error:", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
addWatcher()
|
||||
<-done
|
||||
}
|
||||
|
||||
func parseArgs() {
|
||||
l := len(os.Args)
|
||||
if l == 1 {
|
||||
initWatcher()
|
||||
return
|
||||
}
|
||||
if l == 2 {
|
||||
c := os.Args[1]
|
||||
switch c {
|
||||
case "init":
|
||||
err := ioutil.WriteFile(projectFolder+"/filegirl.yaml", []byte(exampleFileGirl), 0644)
|
||||
if err != nil {
|
||||
log.Println("error create filegirl.yaml config! ", err)
|
||||
return
|
||||
}
|
||||
log.Println("create filegirl.yaml ok")
|
||||
return
|
||||
case "exec":
|
||||
parseConfig()
|
||||
run()
|
||||
return
|
||||
default:
|
||||
fmt.Print(helpStr)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func show() {
|
||||
fmt.Print(logo)
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
fmt.Println(englishSay[rand.Intn(len(englishSay))], "\r\n")
|
||||
fmt.Println("Version: ", Version, " Author: deng@yoytang.com")
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetPrefix("[FileBoy]: ")
|
||||
log.SetFlags(2)
|
||||
show()
|
||||
var err error
|
||||
projectFolder, err = os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
parseArgs()
|
||||
}
|
17
filegirl.go
Normal file
17
filegirl.go
Normal file
@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
type FileGirl struct {
|
||||
Core struct {
|
||||
Version int `yaml:"version"`
|
||||
}
|
||||
Monitor struct {
|
||||
Types []string `yaml:"types"`
|
||||
IncludeDirs []string `yaml:"includeDirs"`
|
||||
ExceptDirs []string `yaml:"exceptDirs"`
|
||||
}
|
||||
Command struct {
|
||||
//BeforeExec string `yaml:"beforeExec"`
|
||||
Exec []string `yaml:"exec"`
|
||||
//AfterExec string `yaml:"afterExec"`
|
||||
}
|
||||
}
|
72
raw.go
Normal file
72
raw.go
Normal file
@ -0,0 +1,72 @@
|
||||
package main
|
||||
|
||||
var exampleFileGirl string = `# 主配置
|
||||
core:
|
||||
# 配置版本号
|
||||
version: 1
|
||||
|
||||
# 监控配置
|
||||
monitor:
|
||||
# 要监听的目录
|
||||
# test1 监听当前目录下 test1 目录
|
||||
# test1/test2 监听当前目录下 test1/test2 目录
|
||||
# test1,* 监听当前目录下 test1 目录及其所有子目录(递归)
|
||||
# .,* 监听当前目录及其所有子目录(递归)
|
||||
includeDirs:
|
||||
- .,*
|
||||
|
||||
# 不监听的目录
|
||||
# .idea 忽略.idea目录及其所有子目录的监听
|
||||
exceptDirs:
|
||||
- .idea
|
||||
- .git
|
||||
- .vscode
|
||||
|
||||
# 监听文件的格式,此类文件更改会执行 commend 中的命令
|
||||
# .go 后缀为 .go 的文件更改,会执行 commend 中的命令
|
||||
# .* 所有的文件更改都会执行 commend 中的命令
|
||||
types:
|
||||
- .go
|
||||
|
||||
# 命令
|
||||
command:
|
||||
# 监听的文件有更改会执行的命令
|
||||
# 可以有多条命令,会依次执行
|
||||
# 如有多条命令,每条命令都会等待上一条命令执行完毕后才会执行
|
||||
# 如遇交互式命令,允许外部获取输入
|
||||
exec:
|
||||
- go version
|
||||
- go env
|
||||
`
|
||||
|
||||
var helpStr = `fileboy [option]
|
||||
Usage of fileboy:
|
||||
无参数
|
||||
读取当前目录下的 filegirl.yaml 配置,开始监听并工作
|
||||
init
|
||||
初始化 fileboy, 在当前目录生成 filegirl.yaml 配置文件
|
||||
exec
|
||||
尝试运行定义的 commend 命令
|
||||
`
|
||||
|
||||
var englishSay = []string{
|
||||
` Have you, the darkness is no darkness.`,
|
||||
` Why do the good girls always love bad boys?`,
|
||||
` If love is not madness.`,
|
||||
` This world is so lonely without you.`,
|
||||
` You lie. Silence in front of me.`,
|
||||
` I need him like I need the air to breathe.`,
|
||||
` Happiness is when the desolated soul meets love.`,
|
||||
` What I can lose, but do not want to lose you.`,
|
||||
` The same words, both miss, is also missed.`,
|
||||
` Each bathed in the love of the people is a poet.`,
|
||||
}
|
||||
|
||||
var logo = `
|
||||
_______ _____ _ _______ ______ _____ _ _
|
||||
(_______|_____) | (_______|____ \ / ___ \| | | |
|
||||
_____ _ | | _____ ____) ) | | | |___| |
|
||||
| ___) | | | | | ___) | __ (| | | |\_____/
|
||||
| | _| |_| |_____| |_____| |__) ) |___| | ___
|
||||
|_| (_____)_______)_______)______/ \_____/ (___)
|
||||
`
|
66
util.go
Normal file
66
util.go
Normal file
@ -0,0 +1,66 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func inStringArray(value string, arr []string) bool {
|
||||
for _, v := range arr {
|
||||
if value == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func cmdParse2Array(s string) []string {
|
||||
a := strings.Split(s, " ")
|
||||
r := make([]string, 0)
|
||||
for i := 0; i < len(a); i++ {
|
||||
if ss := strings.Trim(a[i], " "); ss != "" {
|
||||
r = append(r, ss)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func dirParse2Array(s string) []string {
|
||||
a := strings.Split(s, ",")
|
||||
r := make([]string, 0)
|
||||
for i := 0; i < len(a); i++ {
|
||||
if ss := strings.Trim(a[i], " "); ss != "" {
|
||||
r = append(r, ss)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func listFile(folder string, fun func(string)) {
|
||||
files, _ := ioutil.ReadDir(folder)
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
d := folder + "/" + file.Name()
|
||||
fun(d)
|
||||
listFile(d, fun)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func arrayUniqueAdd(a []string, add string) []string {
|
||||
if inStringArray(add, a) {
|
||||
return a
|
||||
}
|
||||
return append(a, add)
|
||||
}
|
||||
|
||||
func arrayRemoveElement(a []string, r string) []string {
|
||||
i := 0
|
||||
for k, v := range a {
|
||||
if v == r {
|
||||
i = k
|
||||
break
|
||||
}
|
||||
}
|
||||
return append(a[:i], a[i+1:]...)
|
||||
}
|
Loading…
Reference in New Issue
Block a user