diff --git a/go.mod b/go.mod index 744fcaa09b5ad465d954689291d0a8a4316ca661..28022cdaba2d71dd61c874716f6d978edb0f1d26 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/facebookgo/structtag v0.0.0-20150214074306-217e25fb9691 // indirect github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect github.com/fatih/color v1.13.0 + github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/go-git/go-git/v5 v5.4.2 // indirect github.com/go-playground/validator/v10 v10.9.0 github.com/go-redis/redis/v8 v8.11.3 diff --git a/go.sum b/go.sum index 5ae5a0ba024f2fc2b3cbb89a11b9dd523b428234..0a7c02bf268addeae3c587c416031e3338a0da03 100644 --- a/go.sum +++ b/go.sum @@ -215,6 +215,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/gavv/httpexpect/v2 v2.3.1 h1:sGLlKMn8AuHS9ztK9Sb7AJ7OxIL8v2PcLdyxfKt1Fo4= github.com/gavv/httpexpect/v2 v2.3.1/go.mod h1:yOE8m/aqFYQDNrgprMeXgq4YynfN9h1NgcE1+1suV64= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -1012,6 +1014,8 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/internal/pkg/consts/enum.go b/internal/pkg/consts/enum.go index 086da48940633f0e9d525440110e21e520fb2150..e9faedc2933e4898edfb647188d1fdaec3cad26e 100644 --- a/internal/pkg/consts/enum.go +++ b/internal/pkg/consts/enum.go @@ -62,6 +62,8 @@ const ( ExecTask ExecCmd = "execTask" ExecUnit ExecCmd = "execUnit" + + Watch ExecCmd = "watch" ) func (e ExecCmd) String() string { diff --git a/internal/pkg/helper/watch/status.go b/internal/pkg/helper/watch/status.go new file mode 100644 index 0000000000000000000000000000000000000000..873769e6f6d0bb6f0bb3b66609f144d16400a51d --- /dev/null +++ b/internal/pkg/helper/watch/status.go @@ -0,0 +1,27 @@ +package watchHelper + +import ( + "sync" +) + +const ( + KeyWatching = "watching_" +) + +var ( + SyncWatchMap sync.Map +) + +func SetWatching(path string, val bool) { + SyncWatchMap.Store(KeyWatching+path, val) +} + +func GetWatching(path string) (val bool) { + inf, ok := SyncWatchMap.Load(KeyWatching + path) + + if ok { + val = inf.(bool) + } + + return +} diff --git a/internal/pkg/helper/watch/watch.go b/internal/pkg/helper/watch/watch.go new file mode 100644 index 0000000000000000000000000000000000000000..5dff72d050746455474c3ab015084a3ead7c7a6a --- /dev/null +++ b/internal/pkg/helper/watch/watch.go @@ -0,0 +1,58 @@ +package watchHelper + +import ( + "encoding/json" + + commDomain "github.com/easysoft/zentaoatf/internal/pkg/domain" + websocketHelper "github.com/easysoft/zentaoatf/internal/pkg/helper/websocket" + serverDomain "github.com/easysoft/zentaoatf/internal/server/modules/v1/domain" + "github.com/fsnotify/fsnotify" + "github.com/kataras/iris/v12/websocket" +) + +func WatchFromReq(testSets []serverDomain.TestSet, wsMsg *websocket.Message) { + paths := []string{} + for _, testSet := range testSets { + paths = append(paths, testSet.WorkspacePath) + } + Watch(paths, wsMsg) +} + +func Watch(files []string, wsMsg *websocket.Message) { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return + } + defer watcher.Close() + + done := make(chan bool) + go func() { + defer close(done) + + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + if "REMOVE" == event.Op.String() || "CREATE" == event.Op.String() { + bytes, _ := json.Marshal(commDomain.WsResp{Category: "watch"}) + mqData := commDomain.MqMsg{Namespace: wsMsg.Namespace, Room: wsMsg.Room, Event: wsMsg.Event, Content: string(bytes)} + websocketHelper.PubMsg(mqData) + } + case _, ok := <-watcher.Errors: + if !ok { + return + } + } + } + }() + + for _, file := range files { + if GetWatching(file) { + continue + } + watcher.Add(file) + } + <-done +} diff --git a/internal/server/modules/v1/controller/websocket.go b/internal/server/modules/v1/controller/websocket.go index 857d979d511cf4fb35a28d31302bd77447f14aa9..2eb40859abe52f609fc92e8cd230e0221b4929ff 100644 --- a/internal/server/modules/v1/controller/websocket.go +++ b/internal/server/modules/v1/controller/websocket.go @@ -3,12 +3,14 @@ package controller import ( "encoding/json" "fmt" + commConsts "github.com/easysoft/zentaoatf/internal/pkg/consts" commDomain "github.com/easysoft/zentaoatf/internal/pkg/domain" execHelper "github.com/easysoft/zentaoatf/internal/pkg/helper/exec" + watchHelper "github.com/easysoft/zentaoatf/internal/pkg/helper/watch" websocketHelper "github.com/easysoft/zentaoatf/internal/pkg/helper/websocket" - "github.com/easysoft/zentaoatf/internal/server/config" - "github.com/easysoft/zentaoatf/internal/server/modules/v1/domain" + serverConfig "github.com/easysoft/zentaoatf/internal/server/config" + serverDomain "github.com/easysoft/zentaoatf/internal/server/modules/v1/domain" "github.com/easysoft/zentaoatf/internal/server/modules/v1/service" i118Utils "github.com/easysoft/zentaoatf/pkg/lib/i118" logUtils "github.com/easysoft/zentaoatf/pkg/lib/log" @@ -81,6 +83,11 @@ func (c *WebSocketCtrl) OnChat(wsMsg websocket.Message) (err error) { return } + if act == commConsts.Watch { + watchHelper.WatchFromReq(req.TestSets, &wsMsg) + return + } + if act == commConsts.ExecStop { if ch != nil { if !execHelper.GetRunning() { diff --git a/ui/src/views/exec/LogList.vue b/ui/src/views/exec/LogList.vue index 1589888145ec5f5cc17d5cc6623b80d2cf9ecb12..956ba5a075b06c83ac1b42cc4c02dc99a7aecc5c 100644 --- a/ui/src/views/exec/LogList.vue +++ b/ui/src/views/exec/LogList.vue @@ -106,7 +106,9 @@ const onWebsocketMsgEvent = (data: any) => { console.log('WebsocketMsgEvent in ExecLog', data.msg) let item = JSON.parse(data.msg) as WsMsg - + if(item.category == 'watch'){ + return; + } if ('isRunning' in wsMsg) { console.log('change isRunning to ', item.isRunning) store.dispatch('Exec/setRunning', item.isRunning) diff --git a/ui/src/views/script/WorkDir.vue b/ui/src/views/script/WorkDir.vue index 212301013de4d5e5399d25dd508944cecaaa3346..522a6a269108c7370f38325c7c131fd0e3307af0 100644 --- a/ui/src/views/script/WorkDir.vue +++ b/ui/src/views/script/WorkDir.vue @@ -53,7 +53,7 @@ import { WorkspaceData } from "@/store/workspace"; import {getContextMenuStyle, resizeWidth} from "@/utils/dom"; import Tree from "@/components/Tree.vue"; import notification from "@/utils/notification"; -import { computed, defineExpose, onMounted, onUnmounted, ref, watch } from "vue"; +import { computed, defineExpose, onMounted, onUnmounted, ref, watch, onBeforeUnmount } from "vue"; import Button from '@/components/Button.vue'; import TreeContextMenu from './TreeContextMenu.vue'; import FormSyncFromZentao from "./FormSyncFromZentao.vue"; @@ -107,8 +107,23 @@ onMounted(() => { setTimeout(() => { resizeWidth('main', 'left', 'splitter-h', 'right', 380, 800) }, 600) + bus.on(settings.eventWebSocketMsg, onWebsocketMsgEvent); }) +onBeforeUnmount( () => { + console.log('onBeforeUnmount') + bus.off(settings.eventWebSocketMsg, onWebsocketMsgEvent); +}) + +const onWebsocketMsgEvent = (data: any) => { + console.log('WebsocketMsgEvent in WatchFile', data.msg) + + let item = JSON.parse(data.msg) + if(item.category == 'watch'){ + loadScripts() + } +} + const onToolbarClicked = (e) => { const node = e.node == undefined ? treeDataMap.value[''] : treeDataMap.value[e.node.id] store.dispatch('Script/changeWorkspace', diff --git a/ui/src/views/script/store.ts b/ui/src/views/script/store.ts index 8164e6384b9841725a0363cebbdb97ece2474e2b..1b2ed26649092e42a310d62dce5889717d042f41 100644 --- a/ui/src/views/script/store.ts +++ b/ui/src/views/script/store.ts @@ -1,6 +1,8 @@ import { Mutation, Action } from 'vuex'; import { StoreModuleType } from "@/utils/store"; import { ResponseData } from '@/utils/request'; +import {WebSocket} from "@/services/websocket"; +import settings from "@/config/settings"; import { list, @@ -105,7 +107,13 @@ const StoreModel: ModuleType = { data.id = data.path; data.children = scriptTreeAddAttr(data.children ? data.children : []); commit('setList', [data]); - + if(data.children != undefined){ + const watchPaths = [] as any; + data.children.forEach(element => { + watchPaths.push({WorkspacePath: element.path}) + }); + WebSocket.sentMsg(settings.webSocketRoom, JSON.stringify({act: 'watch',testSets:watchPaths})) + } commit('setQueryParams', playload); return true; },