You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
2.6 KiB

  1. package utils
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/fsnotify/fsnotify"
  6. "io/ioutil"
  7. "os"
  8. "path/filepath"
  9. )
  10. // Watch: 监控对象
  11. type Watch struct {
  12. *fsnotify.Watcher
  13. }
  14. func NewWatch() *Watch {
  15. obj, _ := fsnotify.NewWatcher()
  16. return &Watch{obj}
  17. }
  18. // Watch: 监控对象
  19. func (w *Watch) Watch(path string, t *T) error {
  20. // 先转化为绝对路径
  21. path, err := filepath.Abs(path)
  22. if err != nil {
  23. return err
  24. }
  25. // 判断是单个文件还是目录文件
  26. fileInfo, err := os.Stat(path)
  27. if err != nil {
  28. return err
  29. }
  30. // 判断是否是目录 添加监控
  31. if fileInfo.IsDir() {
  32. // dir
  33. err = w.watchDir(path)
  34. } else {
  35. err = w.watchFile(path)
  36. }
  37. if err != nil {
  38. return err
  39. }
  40. c := make(chan error)
  41. // 启动监控
  42. go func() {
  43. for {
  44. select {
  45. case even, ok := <-w.Events:
  46. if !ok {
  47. // close
  48. fmt.Println("Errors close")
  49. c <- errors.New("errors close")
  50. return
  51. }
  52. // 判断事件
  53. switch {
  54. case even.Op&fsnotify.Create == fsnotify.Create:
  55. //这里获取新创建文件的信息,如果是目录,则加入监控中
  56. fmt.Println("创建文件 : ", even.Name)
  57. //t.AddTask()
  58. _ = w.Add(even.Name)
  59. case even.Op&fsnotify.Write == fsnotify.Write:
  60. fmt.Println("修改文件 : ", even.Name)
  61. w.addTask(t, even.Name)
  62. case even.Op&fsnotify.Remove == fsnotify.Remove || even.Op&fsnotify.Rename == fsnotify.Rename:
  63. fmt.Println("删除或重命名文件 : ", even.Name)
  64. _ = w.Remove(even.Name)
  65. w.addTask(t, even.Name)
  66. }
  67. case err = <-w.Errors:
  68. fmt.Println("even Error:", err)
  69. c <- err
  70. return
  71. }
  72. }
  73. }()
  74. return <-c
  75. }
  76. // watchDir: 处理监控目录
  77. func (w *Watch) watchDir(path string) error {
  78. // 先将自己添加到监控
  79. err := w.Add(path)
  80. if err != nil {
  81. return err
  82. }
  83. fileSlice, err := ioutil.ReadDir(path)
  84. if err != nil {
  85. return err
  86. }
  87. for _, f := range fileSlice {
  88. fPath := filepath.Join(path, f.Name())
  89. if !f.IsDir() {
  90. // 判断是否可监控的文件
  91. if chickPower(fPath) {
  92. err = w.watchFile(fPath)
  93. if err != nil {
  94. return err
  95. }
  96. }
  97. } else {
  98. err := w.watchDir(fPath)
  99. if err != nil {
  100. return err
  101. }
  102. }
  103. }
  104. return err
  105. }
  106. // watchDir: 处理监控单文件
  107. func (w *Watch) watchFile(path string) error {
  108. var err error
  109. if chickPower(path) {
  110. err = w.Add(path)
  111. }
  112. return err
  113. }
  114. // chickPower: 判断是否在可控范围内
  115. func chickPower(name string) bool {
  116. return filepath.Ext(name) == ".go" || filepath.Ext(name) == ".yaml"
  117. }
  118. // addTask: 偏函数 简化发送任务
  119. func (w *Watch) addTask(t *T, name string) {
  120. if chickPower(name) {
  121. t.AddTask()
  122. }
  123. }