Merge remote-tracking branch 'upstream/master'

master
jason-gao 2019-12-09 16:26:40 +08:00
commit 06fb9f6a97
9 changed files with 151 additions and 21 deletions

12
.gitpod.Dockerfile vendored Normal file
View File

@ -0,0 +1,12 @@
FROM gitpod/workspace-full
USER root
# Install custom tools, runtime, etc. using apt-get
# For example, the command below would install "bastet" - a command line tetris clone:
#
# RUN apt-get update \
# && apt-get install -y bastet \
# && apt-get clean && rm -rf /var/cache/apt/* && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/*
#
# More information: https://www.gitpod.io/docs/42_config_docker/

7
.gitpod.yml Normal file
View File

@ -0,0 +1,7 @@
image:
file: .gitpod.Dockerfile
# List the start up tasks. You can start them in parallel in multiple terminals. See https://www.gitpod.io/docs/44_config_start_tasks/
tasks:
- init: go get -d -v ./...
command: go build

15
.travis.yml Normal file
View File

@ -0,0 +1,15 @@
language: go
go:
- 1.13.x
- master
script:
- go build
- ./fileboy version
- ./fileboy help
- ./fileboy init
- cat filegirl.yaml
- ./fileboy exec

View File

@ -1,5 +1,7 @@
## 项目说明
[![Build Status](https://travis-ci.org/dengsgo/fileboy.svg?branch=master)](https://travis-ci.org/dengsgo/fileboy) [![Go Report Card](https://goreportcard.com/badge/github.com/dengsgo/fileboy)](https://goreportcard.com/report/github.com/dengsgo/fileboy)
fileboy文件变更监听通知系统使用 Go 编写。
适用于 Hot Reload 典型的如开发go项目无需每次手动执行 go build又比如前端 node 打包) 或者 系统监控的场景。
___

View File

@ -29,12 +29,21 @@ var (
watcher *fsnotify.Watcher
taskMan *TaskMan
ioeventMapStr = map[fsnotify.Op]string{
fsnotify.Write: "write",
fsnotify.Rename: "rename",
fsnotify.Remove: "remove",
fsnotify.Create: "create",
fsnotify.Chmod: "chmod",
}
)
type changedFile struct {
Name string
Changed int64
Ext string
Event string
}
func parseConfig() {
@ -56,6 +65,7 @@ func parseConfig() {
cfg.Monitor.TypesMap = map[string]bool{}
cfg.Monitor.IncludeDirsMap = map[string]bool{}
cfg.Monitor.ExceptDirsMap = map[string]bool{}
cfg.Monitor.IncludeDirsRec = map[string]bool{}
// convert to map
for _, v := range cfg.Monitor.Types {
cfg.Monitor.TypesMap[v] = true
@ -70,26 +80,23 @@ func eventDispatcher(event fsnotify.Event) {
!keyInMonitorTypesMap(ext, cfg) {
return
}
switch event.Op {
case
fsnotify.Write,
fsnotify.Rename:
log.Println("EVENT", event.Op.String(), ":", event.Name)
taskMan.Put(&changedFile{
Name: relativePath(projectFolder, event.Name),
Changed: time.Now().UnixNano(),
Ext: ext,
})
case fsnotify.Remove:
case fsnotify.Create:
op := ioeventMapStr[event.Op]
if len(cfg.Monitor.Events) != 0 && !inStrArray(op, cfg.Monitor.Events) {
return
}
log.Println("EVENT", event.Op.String(), ":", event.Name)
taskMan.Put(&changedFile{
Name: relativePath(projectFolder, event.Name),
Changed: time.Now().UnixNano(),
Ext: ext,
Event: op,
})
}
func addWatcher() {
log.Println("collecting directory information...")
dirsMap := map[string]bool{
projectFolder: true,
}
dirsMap := map[string]bool{}
for _, dir := range cfg.Monitor.IncludeDirs {
darr := dirParse2Array(dir)
if len(darr) < 1 || len(darr) > 2 {
@ -107,6 +114,7 @@ func addWatcher() {
listFile(projectFolder, func(d string) {
dirsMap[d] = true
})
cfg.Monitor.IncludeDirsRec[projectFolder] = true
break
} else {
dirsMap[projectFolder] = true
@ -118,6 +126,7 @@ func addWatcher() {
listFile(md, func(d string) {
dirsMap[d] = true
})
cfg.Monitor.IncludeDirsRec[md] = true
}
}
@ -136,7 +145,7 @@ func addWatcher() {
log.Println("watcher add -> ", dir)
err := watcher.Add(dir)
if err != nil {
logAndExit(err)
logAndExit(PreError, err)
}
}
log.Println("total monitored dirs: " + strconv.Itoa(len(dirsMap)))
@ -161,6 +170,9 @@ func initWatcher() {
if !ok {
return
}
// directory structure changes, dynamically add, delete and monitor according to rules
// TODO // this method cannot be triggered when the parent folder of the change folder is not monitored
go watchChangeHandler(event)
eventDispatcher(event)
case err, ok := <-watcher.Errors:
if !ok {
@ -173,6 +185,56 @@ func initWatcher() {
addWatcher()
}
func watchChangeHandler(event fsnotify.Event) {
if event.Op != fsnotify.Create && event.Op != fsnotify.Rename {
return
}
_, err := ioutil.ReadDir(event.Name)
if err != nil {
return
}
do := false
for rec := range cfg.Monitor.IncludeDirsRec {
if !strings.HasPrefix(event.Name, rec) {
continue
}
// check exceptDirs
has := false
for _, v := range cfg.Monitor.ExceptDirs {
if strings.HasPrefix(event.Name, projectFolder+"/"+v) {
has = true
}
}
if has {
continue
}
_ = watcher.Remove(event.Name)
err := watcher.Add(event.Name)
if err == nil {
do = true
log.Println("watcher add -> ", event.Name)
} else {
log.Println(PreWarn, "watcher add faild:", event.Name, err)
}
}
if do {
return
}
// check map
if _, ok := cfg.Monitor.DirsMap[event.Name]; ok {
_ = watcher.Remove(event.Name)
err := watcher.Add(event.Name)
if err == nil {
log.Println("watcher add -> ", event.Name)
} else {
log.Println(PreWarn, "watcher add faild:", event.Name, err)
}
}
}
func parseArgs() {
switch len(os.Args) {
case 1:
@ -219,6 +281,7 @@ func show() {
func main() {
log.SetPrefix("[FileBoy]: ")
log.SetFlags(2)
log.SetOutput(os.Stdout)
show()
var err error
projectFolder, err = os.Getwd()

View File

@ -8,11 +8,14 @@ type FileGirl struct {
Types []string `yaml:"types"`
IncludeDirs []string `yaml:"includeDirs"`
ExceptDirs []string `yaml:"exceptDirs"`
Events []string `yaml:"events"`
// convert to
TypesMap map[string]bool `yaml:"-"`
IncludeDirsMap map[string]bool `yaml:"-"`
ExceptDirsMap map[string]bool `yaml:"-"`
DirsMap map[string]bool `yaml:"-"`
IncludeDirsRec map[string]bool `yaml:"-"`
}
Command struct {
Exec []string `yaml:"exec"`

View File

@ -14,6 +14,7 @@ type postParams struct {
File string `json:"file"`
Changed int64 `json:"changed"`
Ext string `json:"ext"`
Event string `json:"event"`
}
type NetNotifier struct {
@ -42,6 +43,7 @@ func (n *NetNotifier) Put(cf *changedFile) {
File: cf.Name,
Changed: cf.Changed,
Ext: cf.Ext,
Event: cf.Event,
})
}

14
raw.go
View File

@ -32,6 +32,20 @@ monitor:
types:
- .go
# command
#
# write
# rename
# remove
# create
# chmod (unix)
events:
- write
- rename
- remove
- create
- chmod
#
command:
#

22
util.go
View File

@ -25,12 +25,15 @@ func cmdParse2Array(s string, cf *changedFile) []string {
}
func strParseRealStr(s string, cf *changedFile) string {
return strings.Replace(
strings.Replace(
strings.Replace(s, "{{file}}", cf.Name, -1),
"{{ext}}", cf.Ext, -1,
return strings.ReplaceAll(
strings.ReplaceAll(
strings.ReplaceAll(
strings.ReplaceAll(s, "{{file}}", cf.Name),
"{{ext}}", cf.Ext,
),
"{{changed}}", strconv.FormatInt(cf.Changed, 10),
),
"{{changed}}", strconv.FormatInt(cf.Changed, 10), -1,
"{{event}}", cf.Event,
)
}
@ -64,6 +67,15 @@ func relativePath(folder, p string) string {
return s
}
func inStrArray(s string, arr []string) bool {
for _, v := range arr {
if s == v {
return true
}
}
return false
}
func logAndExit(v ...interface{}) {
log.Println(v...)
os.Exit(0)