Browse Source

Hotreload

Hotreload1
main
songzhibin97 4 years ago
parent
commit
3b0baf4e7e
  1. 47
      server/cmd/gva/run.go
  2. 83
      server/utils/cmd_Task.go
  3. 118
      server/utils/cmd_monitor.go

47
server/cmd/gva/run.go

@ -0,0 +1,47 @@
/*
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
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 gva
import (
"github.com/spf13/cobra"
)
// runCmd represents the run command
var runCmd = &cobra.Command{
Use: "run",
Short: "running go codes with hot-compiled-like feature",
Long: `
The "run" command is used for running go codes with hot-compiled-like feature,
which compiles and runs the go codes asynchronously when codes change.
`,
Run: func(cmd *cobra.Command, args []string) {
// todo 未实现
},
}
func init() {
rootCmd.AddCommand(runCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// runCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// runCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

83
server/utils/cmd_Task.go

@ -0,0 +1,83 @@
package utils
import (
"os"
"os/exec"
"strings"
"sync"
)
type RunTask interface {
AddTask()
RunTask()
}
// T: Task任务
type T struct {
sync.Mutex
// ch: 获取时间channel
ch chan struct{}
// 记录pid 用于kill
pid int
// 执行shell命令
exec.Cmd
}
// NewT: 实例化方法
func NewT(path string, args []string, environment ...[]string) *T {
env := os.Environ()
if len(environment) > 0 {
for k, v := range environment[0] {
env[k] = v
}
}
t := &T{
Mutex: sync.Mutex{},
ch: make(chan struct{}),
Cmd: exec.Cmd{
Path: path,
Args: []string{path},
Env: env,
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
ExtraFiles: make([]*os.File, 0),
},
pid: os.Getpid(),
}
t.Dir, _ = os.Getwd()
if len(args) > 0 {
// Exclude of current binary path.
start := 0
if strings.EqualFold(path, args[0]) {
start = 1
}
t.Args = append(t.Args, args[start:]...)
}
return t
}
func (t *T) AddTask() {
t.Lock()
defer t.Unlock()
if len(t.ch) == 1 {
// 代表已经有任务了
// 直接丢弃这次任务
return
}
t.ch <- struct{}{}
}
func (t *T) RunTask() {
for {
_, ok := <-t.ch
if !ok {
return
}
// todo 执行任务
}
}

118
server/utils/cmd_monitor.go

@ -0,0 +1,118 @@
package utils
import (
"errors"
"fmt"
"github.com/fsnotify/fsnotify"
"io/ioutil"
"os"
"path/filepath"
)
// Watch: 监控对象
type Watch struct {
*fsnotify.Watcher
}
func NewWatch() *Watch {
obj, _ := fsnotify.NewWatcher()
return &Watch{obj}
}
// Watch: 监控对象
func (w *Watch) Watch(path string) error {
// 先转化为绝对路径
path, err := filepath.Abs(path)
if err != nil {
return err
}
// 判断是单个文件还是目录文件
fileInfo, err := os.Stat(path)
if err != nil {
return err
}
// 判断是否是目录 添加监控
if fileInfo.IsDir() {
// dir
err = w.watchDir(path)
} else {
err = w.watchFile(path)
}
if err != nil {
return err
}
c := make(chan error)
// 启动监控
go func() {
for {
select {
case even, ok := <-w.Events:
if !ok {
// close
fmt.Println("Errors close")
c <- errors.New("errors close")
return
}
// 判断时间
fmt.Println("even", even)
switch {
// todo 待处理
case even.Op&fsnotify.Create == fsnotify.Create:
//这里获取新创建文件的信息,如果是目录,则加入监控中
fmt.Println("创建文件 : ", even.Name)
_ = w.Add(even.Name)
case even.Op&fsnotify.Write == fsnotify.Write:
fmt.Println("修改 : ", even.Name)
case even.Op&fsnotify.Remove == fsnotify.Remove:
fmt.Println("删除 : ", even.Name)
_ = w.Remove(even.Name)
case even.Op&fsnotify.Rename == fsnotify.Rename:
fmt.Println("重命名 : ", even.Name)
_ = w.Remove(even.Name)
}
case err = <-w.Errors:
c <- err
return
}
}
}()
return <-c
}
// watchDir: 处理监控目录
func (w *Watch) watchDir(path string) error {
// 先将自己添加到监控
err := w.Add(path)
if err != nil {
return err
}
fileSlice, err := ioutil.ReadDir(path)
if err != nil {
return err
}
for _, f := range fileSlice {
fPath := filepath.Join(path, f.Name())
if !f.IsDir() {
// todo 这里加一些条件筛选添加监控的内容
err = w.watchFile(fPath)
if err != nil {
return err
}
} else {
err := w.watchDir(fPath)
if err != nil {
return err
}
}
}
return err
}
// watchDir: 处理监控单文件
func (w *Watch) watchFile(path string) error {
return w.Add(path)
}
Loading…
Cancel
Save