Skip to content

Commit 3b0baf4

Browse files
committed
Hotreload
Hotreload1
1 parent 22b0f33 commit 3b0baf4

File tree

3 files changed

+248
-0
lines changed

3 files changed

+248
-0
lines changed

server/cmd/gva/run.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package gva
17+
18+
import (
19+
"github.com/spf13/cobra"
20+
)
21+
22+
// runCmd represents the run command
23+
var runCmd = &cobra.Command{
24+
Use: "run",
25+
Short: "running go codes with hot-compiled-like feature",
26+
Long: `
27+
The "run" command is used for running go codes with hot-compiled-like feature,
28+
which compiles and runs the go codes asynchronously when codes change.
29+
`,
30+
Run: func(cmd *cobra.Command, args []string) {
31+
// todo 未实现
32+
},
33+
}
34+
35+
func init() {
36+
rootCmd.AddCommand(runCmd)
37+
38+
// Here you will define your flags and configuration settings.
39+
40+
// Cobra supports Persistent Flags which will work for this command
41+
// and all subcommands, e.g.:
42+
// runCmd.PersistentFlags().String("foo", "", "A help for foo")
43+
44+
// Cobra supports local flags which will only run when this command
45+
// is called directly, e.g.:
46+
// runCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
47+
}

server/utils/cmd_Task.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package utils
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
"strings"
7+
"sync"
8+
)
9+
10+
type RunTask interface {
11+
AddTask()
12+
RunTask()
13+
}
14+
15+
// T: Task任务
16+
type T struct {
17+
sync.Mutex
18+
19+
// ch: 获取时间channel
20+
ch chan struct{}
21+
22+
// 记录pid 用于kill
23+
pid int
24+
25+
// 执行shell命令
26+
exec.Cmd
27+
}
28+
29+
// NewT: 实例化方法
30+
func NewT(path string, args []string, environment ...[]string) *T {
31+
env := os.Environ()
32+
if len(environment) > 0 {
33+
for k, v := range environment[0] {
34+
env[k] = v
35+
}
36+
}
37+
t := &T{
38+
Mutex: sync.Mutex{},
39+
ch: make(chan struct{}),
40+
Cmd: exec.Cmd{
41+
Path: path,
42+
Args: []string{path},
43+
Env: env,
44+
Stdin: os.Stdin,
45+
Stdout: os.Stdout,
46+
Stderr: os.Stderr,
47+
ExtraFiles: make([]*os.File, 0),
48+
},
49+
pid: os.Getpid(),
50+
}
51+
t.Dir, _ = os.Getwd()
52+
if len(args) > 0 {
53+
// Exclude of current binary path.
54+
start := 0
55+
if strings.EqualFold(path, args[0]) {
56+
start = 1
57+
}
58+
t.Args = append(t.Args, args[start:]...)
59+
}
60+
return t
61+
}
62+
63+
func (t *T) AddTask() {
64+
t.Lock()
65+
defer t.Unlock()
66+
if len(t.ch) == 1 {
67+
// 代表已经有任务了
68+
// 直接丢弃这次任务
69+
return
70+
}
71+
t.ch <- struct{}{}
72+
}
73+
74+
func (t *T) RunTask() {
75+
for {
76+
_, ok := <-t.ch
77+
if !ok {
78+
return
79+
}
80+
// todo 执行任务
81+
82+
}
83+
}

server/utils/cmd_monitor.go

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

0 commit comments

Comments
 (0)