mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
one commit - added fileview backend changes
This commit is contained in:
parent
46b9c22f10
commit
8e907066ad
318
diff.txt
Normal file
318
diff.txt
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
diff --git a/src/app/workspace/cmdinput/textareainput.tsx b/src/app/workspace/cmdinput/textareainput.tsx
|
||||||
|
index c5461a90..0d43a66c 100644
|
||||||
|
--- a/src/app/workspace/cmdinput/textareainput.tsx
|
||||||
|
+++ b/src/app/workspace/cmdinput/textareainput.tsx
|
||||||
|
@@ -131,165 +131,177 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||||
|
this.checkHeight(false);
|
||||||
|
this.updateSP();
|
||||||
|
let keybindManager = GlobalModel.keybindManager;
|
||||||
|
- keybindManager.registerKeybinding("pane", "cmdinput", "any", (waveEvent) => {
|
||||||
|
- return mobx.action(() => {
|
||||||
|
- let inputRef = this.mainInputRef.current;
|
||||||
|
- if (util.isModKeyPress(waveEvent)) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
- let model = GlobalModel;
|
||||||
|
- let inputModel = model.inputModel;
|
||||||
|
- let ctrlMod = waveEvent.control || waveEvent.cmd || waveEvent.shift;
|
||||||
|
- let curLine = inputModel.getCurLine();
|
||||||
|
-
|
||||||
|
- let lastTab = this.lastTab;
|
||||||
|
- this.lastTab = keybindManager.checkKeyPressed(waveEvent, "cmdinput:autocomplete");
|
||||||
|
- let lastHist = this.lastHistoryUpDown;
|
||||||
|
- this.lastHistoryUpDown = false;
|
||||||
|
-
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:autocomplete")) {
|
||||||
|
- if (lastTab) {
|
||||||
|
- GlobalModel.submitCommand(
|
||||||
|
- "_compgen",
|
||||||
|
- null,
|
||||||
|
- [curLine],
|
||||||
|
- { comppos: String(curLine.length), compshow: "1", nohist: "1" },
|
||||||
|
- true
|
||||||
|
- );
|
||||||
|
- } else {
|
||||||
|
- GlobalModel.submitCommand(
|
||||||
|
- "_compgen",
|
||||||
|
- null,
|
||||||
|
- [curLine],
|
||||||
|
- { comppos: String(curLine.length), nohist: "1" },
|
||||||
|
- true
|
||||||
|
- );
|
||||||
|
+ if (GlobalModel.activeMainView.get() == "session") {
|
||||||
|
+ console.log("session");
|
||||||
|
+ keybindManager.registerKeybinding("pane", "cmdinput", "any", (waveEvent) => {
|
||||||
|
+ return mobx.action(() => {
|
||||||
|
+ let inputRef = this.mainInputRef.current;
|
||||||
|
+ if (util.isModKeyPress(waveEvent)) {
|
||||||
|
+ return false;
|
||||||
|
}
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "generic:confirm")) {
|
||||||
|
- if (!ctrlMod) {
|
||||||
|
- if (GlobalModel.inputModel.isEmpty()) {
|
||||||
|
- let activeWindow = GlobalModel.getScreenLinesForActiveScreen();
|
||||||
|
- let activeScreen = GlobalModel.getActiveScreen();
|
||||||
|
- if (activeScreen != null && activeWindow != null && activeWindow.lines.length > 0) {
|
||||||
|
- activeScreen.setSelectedLine(0);
|
||||||
|
- GlobalCommandRunner.screenSelectLine("E");
|
||||||
|
- }
|
||||||
|
+ let model = GlobalModel;
|
||||||
|
+ let inputModel = model.inputModel;
|
||||||
|
+ let ctrlMod = waveEvent.control || waveEvent.cmd || waveEvent.shift;
|
||||||
|
+ let curLine = inputModel.getCurLine();
|
||||||
|
+
|
||||||
|
+ let lastTab = this.lastTab;
|
||||||
|
+ this.lastTab = keybindManager.checkKeyPressed(waveEvent, "cmdinput:autocomplete");
|
||||||
|
+ let lastHist = this.lastHistoryUpDown;
|
||||||
|
+ this.lastHistoryUpDown = false;
|
||||||
|
+
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:autocomplete")) {
|
||||||
|
+ if (lastTab) {
|
||||||
|
+ GlobalModel.submitCommand(
|
||||||
|
+ "_compgen",
|
||||||
|
+ null,
|
||||||
|
+ [curLine],
|
||||||
|
+ { comppos: String(curLine.length), compshow: "1", nohist: "1" },
|
||||||
|
+ true
|
||||||
|
+ );
|
||||||
|
} else {
|
||||||
|
- setTimeout(() => GlobalModel.inputModel.uiSubmitCommand(), 0);
|
||||||
|
+ GlobalModel.submitCommand(
|
||||||
|
+ "_compgen",
|
||||||
|
+ null,
|
||||||
|
+ [curLine],
|
||||||
|
+ { comppos: String(curLine.length), nohist: "1" },
|
||||||
|
+ true
|
||||||
|
+ );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
- inputRef.setRangeText("\n", inputRef.selectionStart, inputRef.selectionEnd, "end");
|
||||||
|
- GlobalModel.inputModel.setCurLine(inputRef.value);
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "generic:cancel")) {
|
||||||
|
- let inputModel = GlobalModel.inputModel;
|
||||||
|
- inputModel.toggleInfoMsg();
|
||||||
|
- console.log("hello?", inputModel.inputMode.get());
|
||||||
|
- if (inputModel.inputMode.get() != null) {
|
||||||
|
- inputModel.resetInputMode();
|
||||||
|
- console.log("hello? 2");
|
||||||
|
- }
|
||||||
|
- console.log("hello 3?");
|
||||||
|
- inputModel.closeAIAssistantChat(true);
|
||||||
|
- console.log("hello 4?");
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:expandInput")) {
|
||||||
|
- let inputModel = GlobalModel.inputModel;
|
||||||
|
- inputModel.toggleExpandInput();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:clearInput")) {
|
||||||
|
- inputModel.resetInput();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:cutLineLeftOfCursor")) {
|
||||||
|
- this.controlU();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:previousHistoryItem")) {
|
||||||
|
- this.controlP();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:nextHistoryItem")) {
|
||||||
|
- this.controlN();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:cutWordLeftOfCursor")) {
|
||||||
|
- this.controlW();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:paste")) {
|
||||||
|
- this.controlY();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:openHistory")) {
|
||||||
|
- inputModel.openHistory();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeysPressed(waveEvent, ["generic:selectAbove", "generic:selectBelow"])) {
|
||||||
|
- if (!inputModel.isHistoryLoaded()) {
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "generic:selectAbove")) {
|
||||||
|
- this.lastHistoryUpDown = true;
|
||||||
|
- inputModel.loadHistory(false, 1, "screen");
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "generic:confirm")) {
|
||||||
|
+ if (!ctrlMod) {
|
||||||
|
+ if (GlobalModel.inputModel.isEmpty()) {
|
||||||
|
+ let activeWindow = GlobalModel.getScreenLinesForActiveScreen();
|
||||||
|
+ let activeScreen = GlobalModel.getActiveScreen();
|
||||||
|
+ if (activeScreen != null && activeWindow != null && activeWindow.lines.length > 0) {
|
||||||
|
+ activeScreen.setSelectedLine(0);
|
||||||
|
+ GlobalCommandRunner.screenSelectLine("E");
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ setTimeout(() => GlobalModel.inputModel.uiSubmitCommand(), 0);
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
}
|
||||||
|
+ inputRef.setRangeText("\n", inputRef.selectionStart, inputRef.selectionEnd, "end");
|
||||||
|
+ GlobalModel.inputModel.setCurLine(inputRef.value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
- // invisible history movement
|
||||||
|
- let linePos = this.getLinePos(inputRef);
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "generic:selectAbove")) {
|
||||||
|
- if (!lastHist && linePos.linePos > 1) {
|
||||||
|
- // regular arrow
|
||||||
|
- return false;
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "generic:cancel")) {
|
||||||
|
+ let inputModel = GlobalModel.inputModel;
|
||||||
|
+ inputModel.toggleInfoMsg();
|
||||||
|
+ if (inputModel.inputMode.get() != null) {
|
||||||
|
+ inputModel.resetInputMode();
|
||||||
|
}
|
||||||
|
- inputModel.moveHistorySelection(1);
|
||||||
|
- this.lastHistoryUpDown = true;
|
||||||
|
+ inputModel.closeAIAssistantChat(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "generic:selectBelow")) {
|
||||||
|
- if (!lastHist && linePos.linePos < linePos.numLines) {
|
||||||
|
- // regular arrow
|
||||||
|
- return false;
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:expandInput")) {
|
||||||
|
+ let inputModel = GlobalModel.inputModel;
|
||||||
|
+ inputModel.toggleExpandInput();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:clearInput")) {
|
||||||
|
+ inputModel.resetInput();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:cutLineLeftOfCursor")) {
|
||||||
|
+ this.controlU();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:previousHistoryItem")) {
|
||||||
|
+ this.controlP();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:nextHistoryItem")) {
|
||||||
|
+ this.controlN();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:cutWordLeftOfCursor")) {
|
||||||
|
+ this.controlW();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:paste")) {
|
||||||
|
+ this.controlY();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:openHistory")) {
|
||||||
|
+ inputModel.openHistory();
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeysPressed(waveEvent, ["generic:selectAbove", "generic:selectBelow"])) {
|
||||||
|
+ if (!inputModel.isHistoryLoaded()) {
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "generic:selectAbove")) {
|
||||||
|
+ this.lastHistoryUpDown = true;
|
||||||
|
+ inputModel.loadHistory(false, 1, "screen");
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ // invisible history movement
|
||||||
|
+ let linePos = this.getLinePos(inputRef);
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "generic:selectAbove")) {
|
||||||
|
+ if (!lastHist && linePos.linePos > 1) {
|
||||||
|
+ // regular arrow
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ inputModel.moveHistorySelection(1);
|
||||||
|
+ this.lastHistoryUpDown = true;
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "generic:selectBelow")) {
|
||||||
|
+ if (!lastHist && linePos.linePos < linePos.numLines) {
|
||||||
|
+ // regular arrow
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ inputModel.moveHistorySelection(-1);
|
||||||
|
+ this.lastHistoryUpDown = true;
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (
|
||||||
|
+ keybindManager.checkKeysPressed(waveEvent, [
|
||||||
|
+ "generic:selectPageAbove",
|
||||||
|
+ "generic:selectPageBelow",
|
||||||
|
+ ])
|
||||||
|
+ ) {
|
||||||
|
+ let infoScroll = inputModel.hasScrollingInfoMsg();
|
||||||
|
+ if (infoScroll) {
|
||||||
|
+ let div = document.querySelector(".cmd-input-info");
|
||||||
|
+ let amt = pageSize(div);
|
||||||
|
+ scrollDiv(
|
||||||
|
+ div,
|
||||||
|
+ keybindManager.checkKeyPressed(waveEvent, "generic:selectPageAbove") ? -amt : amt
|
||||||
|
+ );
|
||||||
|
}
|
||||||
|
- inputModel.moveHistorySelection(-1);
|
||||||
|
- this.lastHistoryUpDown = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
- }
|
||||||
|
- if (
|
||||||
|
- keybindManager.checkKeysPressed(waveEvent, ["generic:selectPageAbove", "generic:selectPageBelow"])
|
||||||
|
- ) {
|
||||||
|
- let infoScroll = inputModel.hasScrollingInfoMsg();
|
||||||
|
- if (infoScroll) {
|
||||||
|
- let div = document.querySelector(".cmd-input-info");
|
||||||
|
- let amt = pageSize(div);
|
||||||
|
- scrollDiv(
|
||||||
|
- div,
|
||||||
|
- keybindManager.checkKeyPressed(waveEvent, "generic:selectPageAbove") ? -amt : amt
|
||||||
|
- );
|
||||||
|
+ if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:openAIChat")) {
|
||||||
|
+ inputModel.openAIAssistantChat();
|
||||||
|
+ return true;
|
||||||
|
}
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- if (keybindManager.checkKeyPressed(waveEvent, "cmdinput:openAIChat")) {
|
||||||
|
- inputModel.openAIAssistantChat();
|
||||||
|
- return true;
|
||||||
|
- }
|
||||||
|
- // console.log(e.code, e.keyCode, e.key, event.which, ctrlMod, e);
|
||||||
|
- return false;
|
||||||
|
- })();
|
||||||
|
- });
|
||||||
|
+ // console.log(e.code, e.keyCode, e.key, event.which, ctrlMod, e);
|
||||||
|
+ return false;
|
||||||
|
+ })();
|
||||||
|
+ });
|
||||||
|
+ } else {
|
||||||
|
+ console.log("not session");
|
||||||
|
+ keybindManager.unregisterDomain("cmdinput");
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount(): void {
|
||||||
|
+ console.log("component unmounted??");
|
||||||
|
let keybindManager = GlobalModel.keybindManager;
|
||||||
|
keybindManager.unregisterDomain("cmdinput");
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
+ console.log("component update");
|
||||||
|
+ if (GlobalModel.activeMainView.get() != "session") {
|
||||||
|
+ console.log("unregistering");
|
||||||
|
+ let keybindManager = GlobalModel.keybindManager;
|
||||||
|
+ keybindManager.unregisterDomain("cmdinput");
|
||||||
|
+ }
|
||||||
|
let activeScreen = GlobalModel.getActiveScreen();
|
||||||
|
if (activeScreen != null) {
|
||||||
|
let focusType = activeScreen.focusType.get();
|
4
prettify.sh
Executable file
4
prettify.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
dirs=$(git diff main --name-only --diff-filter d | grep -e '\.[tj]sx\?$' | xargs)
|
||||||
|
echo dirs: $dirs
|
||||||
|
node_modules/prettier/bin-prettier.js --write $dirs
|
||||||
|
|
5
prettifyAndPush.sh
Executable file
5
prettifyAndPush.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
dirs=$(git diff main --name-only --diff-filter d | grep -e '\.[tj]sx\?$' | xargs)
|
||||||
|
node_modules/prettier/bin-prettier.js --write $dirs
|
||||||
|
git add $dirs
|
||||||
|
git commit --amend
|
||||||
|
git push
|
@ -64,6 +64,8 @@ const (
|
|||||||
FileStatPacketStr = "filestat"
|
FileStatPacketStr = "filestat"
|
||||||
LogPacketStr = "log" // logging packet (sent from waveshell back to server)
|
LogPacketStr = "log" // logging packet (sent from waveshell back to server)
|
||||||
ShellStatePacketStr = "shellstate"
|
ShellStatePacketStr = "shellstate"
|
||||||
|
ListDirPacketStr = "listdir"
|
||||||
|
SearchDirPacketStr = "searchdir"
|
||||||
RpcInputPacketStr = "rpcinput" // rpc-followup
|
RpcInputPacketStr = "rpcinput" // rpc-followup
|
||||||
SudoRequestPacketStr = "sudorequest"
|
SudoRequestPacketStr = "sudorequest"
|
||||||
SudoResponsePacketStr = "sudoresponse"
|
SudoResponsePacketStr = "sudoresponse"
|
||||||
@ -120,6 +122,8 @@ func init() {
|
|||||||
TypeStrToFactory[WriteFileDonePacketStr] = reflect.TypeOf(WriteFileDonePacketType{})
|
TypeStrToFactory[WriteFileDonePacketStr] = reflect.TypeOf(WriteFileDonePacketType{})
|
||||||
TypeStrToFactory[LogPacketStr] = reflect.TypeOf(LogPacketType{})
|
TypeStrToFactory[LogPacketStr] = reflect.TypeOf(LogPacketType{})
|
||||||
TypeStrToFactory[ShellStatePacketStr] = reflect.TypeOf(ShellStatePacketType{})
|
TypeStrToFactory[ShellStatePacketStr] = reflect.TypeOf(ShellStatePacketType{})
|
||||||
|
TypeStrToFactory[ListDirPacketStr] = reflect.TypeOf(ListDirPacketType{})
|
||||||
|
TypeStrToFactory[SearchDirPacketStr] = reflect.TypeOf(SearchDirPacketType{})
|
||||||
TypeStrToFactory[FileStatPacketStr] = reflect.TypeOf(FileStatPacketType{})
|
TypeStrToFactory[FileStatPacketStr] = reflect.TypeOf(FileStatPacketType{})
|
||||||
TypeStrToFactory[RpcInputPacketStr] = reflect.TypeOf(RpcInputPacketType{})
|
TypeStrToFactory[RpcInputPacketStr] = reflect.TypeOf(RpcInputPacketType{})
|
||||||
TypeStrToFactory[SudoRequestPacketStr] = reflect.TypeOf(SudoRequestPacketType{})
|
TypeStrToFactory[SudoRequestPacketStr] = reflect.TypeOf(SudoRequestPacketType{})
|
||||||
@ -133,6 +137,8 @@ func init() {
|
|||||||
var _ RpcPacketType = (*ReInitPacketType)(nil)
|
var _ RpcPacketType = (*ReInitPacketType)(nil)
|
||||||
var _ RpcPacketType = (*StreamFilePacketType)(nil)
|
var _ RpcPacketType = (*StreamFilePacketType)(nil)
|
||||||
var _ RpcPacketType = (*WriteFilePacketType)(nil)
|
var _ RpcPacketType = (*WriteFilePacketType)(nil)
|
||||||
|
var _ RpcPacketType = (*ListDirPacketType)(nil)
|
||||||
|
var _ RpcPacketType = (*SearchDirPacketType)(nil)
|
||||||
|
|
||||||
var _ RpcResponsePacketType = (*CmdStartPacketType)(nil)
|
var _ RpcResponsePacketType = (*CmdStartPacketType)(nil)
|
||||||
var _ RpcResponsePacketType = (*ResponsePacketType)(nil)
|
var _ RpcResponsePacketType = (*ResponsePacketType)(nil)
|
||||||
@ -449,8 +455,12 @@ func MakeFileStatPacketType() *FileStatPacketType {
|
|||||||
return &FileStatPacketType{Type: FileStatPacketStr}
|
return &FileStatPacketType{Type: FileStatPacketStr}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeFileStatPacketFromFileInfo(finfo fs.FileInfo, err string, done bool) *FileStatPacketType {
|
func MakeFileStatPacketFromFileInfo(listDirPk *ListDirPacketType, finfo fs.FileInfo, err string, done bool) *FileStatPacketType {
|
||||||
resp := MakeFileStatPacketType()
|
resp := MakeFileStatPacketType()
|
||||||
|
if listDirPk != nil {
|
||||||
|
resp.RespId = listDirPk.ReqId
|
||||||
|
resp.Path = listDirPk.Path
|
||||||
|
}
|
||||||
resp.Error = err
|
resp.Error = err
|
||||||
resp.Done = done
|
resp.Done = done
|
||||||
|
|
||||||
@ -464,6 +474,50 @@ func MakeFileStatPacketFromFileInfo(finfo fs.FileInfo, err string, done bool) *F
|
|||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ListDirPacketType struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
ReqId string `json:"reqid"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ListDirPacketType) GetType() string {
|
||||||
|
return ListDirPacketStr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ListDirPacketType) GetReqId() string {
|
||||||
|
return p.ReqId
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeListDirPacket() *ListDirPacketType {
|
||||||
|
return &ListDirPacketType{Type: ListDirPacketStr}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchDirPacketType struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
ReqId string `json:"reqid"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
SearchQuery string `json:"searchquery"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SearchDirPacketType) GetType() string {
|
||||||
|
return SearchDirPacketStr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SearchDirPacketType) GetReqId() string {
|
||||||
|
return p.ReqId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SearchDirPacketType) ConvertToListDir() *ListDirPacketType {
|
||||||
|
rtn := MakeListDirPacket()
|
||||||
|
rtn.ReqId = p.ReqId
|
||||||
|
rtn.Path = p.Path
|
||||||
|
return rtn
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeSearchDirPacket() *SearchDirPacketType {
|
||||||
|
return &SearchDirPacketType{Type: SearchDirPacketStr}
|
||||||
|
}
|
||||||
|
|
||||||
type StreamFilePacketType struct {
|
type StreamFilePacketType struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
ReqId string `json:"reqid"`
|
ReqId string `json:"reqid"`
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -660,6 +661,97 @@ func (m *MServer) streamFile(pk *packet.StreamFilePacketType) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MServer) writeListDirErrPacket(err error, reqId string) {
|
||||||
|
resp := packet.MakeFileStatPacketType()
|
||||||
|
resp.RespId = reqId
|
||||||
|
resp.Error = fmt.Sprintf("Error in list dir: %v", err)
|
||||||
|
resp.Done = true
|
||||||
|
m.Sender.SendPacket(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MServer) ListDir(listDirPk *packet.ListDirPacketType) {
|
||||||
|
dirEntries, err := os.ReadDir(listDirPk.Path)
|
||||||
|
var readDirError string = ""
|
||||||
|
if err != nil {
|
||||||
|
readDirError = fmt.Sprintf("error in list dir: %v", err)
|
||||||
|
}
|
||||||
|
curDirStat, err := os.Stat(listDirPk.Path)
|
||||||
|
if err != nil {
|
||||||
|
m.writeListDirErrPacket(err, listDirPk.ReqId)
|
||||||
|
}
|
||||||
|
resp := packet.MakeFileStatPacketFromFileInfo(listDirPk, curDirStat, readDirError, false)
|
||||||
|
resp.Name = "."
|
||||||
|
m.Sender.SendPacket(resp)
|
||||||
|
curDirStat, err = os.Stat(filepath.Join(listDirPk.Path, ".."))
|
||||||
|
if err != nil {
|
||||||
|
m.writeListDirErrPacket(err, listDirPk.ReqId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp = packet.MakeFileStatPacketFromFileInfo(listDirPk, curDirStat, readDirError, len(dirEntries) == 0)
|
||||||
|
resp.Name = ".."
|
||||||
|
m.Sender.SendPacket(resp)
|
||||||
|
|
||||||
|
for index := 0; index < len(dirEntries); index++ {
|
||||||
|
dirEntry := dirEntries[index]
|
||||||
|
dirEntryFileInfo, err := dirEntry.Info()
|
||||||
|
if err != nil {
|
||||||
|
m.writeListDirErrPacket(err, listDirPk.ReqId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
done := index == len(dirEntries)-1
|
||||||
|
resp = packet.MakeFileStatPacketFromFileInfo(listDirPk, dirEntryFileInfo, readDirError, done)
|
||||||
|
m.Sender.SendPacket(resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MServer) SearchDir(searchDirPk *packet.SearchDirPacketType) {
|
||||||
|
searchEmpty := true
|
||||||
|
foundRoot := false
|
||||||
|
err := filepath.WalkDir(searchDirPk.Path, func(path string, dirEntry fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
errString := fmt.Sprintf("%v", err)
|
||||||
|
if strings.Contains(errString, "operation not permitted") {
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileName := filepath.Base(path)
|
||||||
|
match, err := regexp.MatchString(searchDirPk.SearchQuery, fileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if match {
|
||||||
|
base.Logf("matched file: %v %v", path, searchDirPk.SearchQuery)
|
||||||
|
// special case where walkdir includes the current path, which messes up the stat pk
|
||||||
|
rootName := filepath.Base(searchDirPk.Path)
|
||||||
|
if !foundRoot && fileName == rootName {
|
||||||
|
foundRoot = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
dirEntryFileInfo, err := dirEntry.Info()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
searchEmpty = false
|
||||||
|
resp := packet.MakeFileStatPacketFromFileInfo(searchDirPk.ConvertToListDir(), dirEntryFileInfo, "", false)
|
||||||
|
m.Sender.SendPacket(resp)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
m.writeListDirErrPacket(err, searchDirPk.ReqId)
|
||||||
|
} else {
|
||||||
|
searchError := ""
|
||||||
|
if searchEmpty {
|
||||||
|
searchError = "none"
|
||||||
|
}
|
||||||
|
resp := packet.MakeFileStatPacketType()
|
||||||
|
resp.Error = searchError
|
||||||
|
resp.Done = true
|
||||||
|
m.Sender.SendPacket(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func int64Min(v1 int64, v2 int64) int64 {
|
func int64Min(v1 int64, v2 int64) int64 {
|
||||||
if v1 < v2 {
|
if v1 < v2 {
|
||||||
return v1
|
return v1
|
||||||
@ -703,6 +795,14 @@ func (m *MServer) ProcessRpcPacket(pk packet.RpcPacketType) {
|
|||||||
go m.writeFile(writePk, wfc)
|
go m.writeFile(writePk, wfc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if listDirPk, ok := pk.(*packet.ListDirPacketType); ok {
|
||||||
|
go m.ListDir(listDirPk)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if searchDirPk, ok := pk.(*packet.SearchDirPacketType); ok {
|
||||||
|
go m.SearchDir(searchDirPk)
|
||||||
|
return
|
||||||
|
}
|
||||||
m.Sender.SendErrorResponse(reqId, fmt.Errorf("invalid rpc type '%s'", pk.GetType()))
|
m.Sender.SendErrorResponse(reqId, fmt.Errorf("invalid rpc type '%s'", pk.GetType()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,7 +1033,7 @@ func configDirHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
var files []*packet.FileStatPacketType
|
var files []*packet.FileStatPacketType
|
||||||
for index := 0; index < len(entries); index++ {
|
for index := 0; index < len(entries); index++ {
|
||||||
curEntry := entries[index]
|
curEntry := entries[index]
|
||||||
curFile := packet.MakeFileStatPacketFromFileInfo(curEntry, "", false)
|
curFile := packet.MakeFileStatPacketFromFileInfo(nil, curEntry, "", false)
|
||||||
files = append(files, curFile)
|
files = append(files, curFile)
|
||||||
}
|
}
|
||||||
dirListJson, err := json.Marshal(files)
|
dirListJson, err := json.Marshal(files)
|
||||||
|
@ -279,6 +279,7 @@ func init() {
|
|||||||
registerCmdFn("set", SetCommand)
|
registerCmdFn("set", SetCommand)
|
||||||
|
|
||||||
registerCmdFn("view:stat", ViewStatCommand)
|
registerCmdFn("view:stat", ViewStatCommand)
|
||||||
|
registerCmdFn("view:dir", ViewDirCommand)
|
||||||
registerCmdFn("view:test", ViewTestCommand)
|
registerCmdFn("view:test", ViewTestCommand)
|
||||||
|
|
||||||
registerCmdFn("edit:test", EditTestCommand)
|
registerCmdFn("edit:test", EditTestCommand)
|
||||||
@ -287,6 +288,8 @@ func init() {
|
|||||||
registerCmdFn("codeedit", CodeEditCommand)
|
registerCmdFn("codeedit", CodeEditCommand)
|
||||||
registerCmdFn("codeview", CodeEditCommand)
|
registerCmdFn("codeview", CodeEditCommand)
|
||||||
|
|
||||||
|
registerCmdFn("searchdir", SearchDirCommand)
|
||||||
|
|
||||||
registerCmdFn("imageview", ImageViewCommand)
|
registerCmdFn("imageview", ImageViewCommand)
|
||||||
registerCmdFn("mdview", MarkdownViewCommand)
|
registerCmdFn("mdview", MarkdownViewCommand)
|
||||||
registerCmdFn("markdownview", MarkdownViewCommand)
|
registerCmdFn("markdownview", MarkdownViewCommand)
|
||||||
@ -1323,6 +1326,15 @@ func doCopyLocalFileToRemote(ctx context.Context, cmd *sstore.CmdType, remoteWsh
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer localFile.Close()
|
defer localFile.Close()
|
||||||
|
fileStat, err := localFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
writeStringToPty(ctx, cmd, fmt.Sprintf("error: could not get file stat: %v", err), &outputPos)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fileStat.IsDir() {
|
||||||
|
writeStringToPty(ctx, cmd, "Cant copy a directory, try zipping it up first", &outputPos)
|
||||||
|
return
|
||||||
|
}
|
||||||
writePk := packet.MakeWriteFilePacket()
|
writePk := packet.MakeWriteFilePacket()
|
||||||
writePk.ReqId = uuid.New().String()
|
writePk.ReqId = uuid.New().String()
|
||||||
writePk.Path = destPath
|
writePk.Path = destPath
|
||||||
@ -1337,11 +1349,6 @@ func doCopyLocalFileToRemote(ctx context.Context, cmd *sstore.CmdType, remoteWsh
|
|||||||
writeStringToPty(ctx, cmd, fmt.Sprintf("Write ready packet error: %v\r\n", err), &outputPos)
|
writeStringToPty(ctx, cmd, fmt.Sprintf("Write ready packet error: %v\r\n", err), &outputPos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fileStat, err := localFile.Stat()
|
|
||||||
if err != nil {
|
|
||||||
writeStringToPty(ctx, cmd, fmt.Sprintf("error: could not get file stat: %v", err), &outputPos)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fileSizeBytes := fileStat.Size()
|
fileSizeBytes := fileStat.Size()
|
||||||
bytesWritten := int64(0)
|
bytesWritten := int64(0)
|
||||||
lastFileTransferPercentage := float64(0)
|
lastFileTransferPercentage := float64(0)
|
||||||
@ -1434,6 +1441,10 @@ func doCopyRemoteFileToRemote(ctx context.Context, cmd *sstore.CmdType, sourceWs
|
|||||||
writeStringToPty(ctx, cmd, fmt.Sprintf("Response packet has error: %v\r\n", err), &outputPos)
|
writeStringToPty(ctx, cmd, fmt.Sprintf("Response packet has error: %v\r\n", err), &outputPos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if resp.Info.IsDir {
|
||||||
|
writeStringToPty(ctx, cmd, "Cant copy a directory, try zipping it up first", &outputPos)
|
||||||
|
return
|
||||||
|
}
|
||||||
fileSizeBytes := resp.Info.Size
|
fileSizeBytes := resp.Info.Size
|
||||||
if fileSizeBytes == 0 {
|
if fileSizeBytes == 0 {
|
||||||
writeStringToPty(ctx, cmd, "Source file does not exist or is empty - exiting\r\n", &outputPos)
|
writeStringToPty(ctx, cmd, "Source file does not exist or is empty - exiting\r\n", &outputPos)
|
||||||
@ -1525,6 +1536,10 @@ func doCopyLocalFileToLocal(ctx context.Context, cmd *sstore.CmdType, sourcePath
|
|||||||
writeStringToPty(ctx, cmd, fmt.Sprintf("error getting filestat %v", err), &outputPos)
|
writeStringToPty(ctx, cmd, fmt.Sprintf("error getting filestat %v", err), &outputPos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if sourceFileStat.IsDir() {
|
||||||
|
writeStringToPty(ctx, cmd, "Cant copy a directory, try zipping it up first", &outputPos)
|
||||||
|
return
|
||||||
|
}
|
||||||
fileSizeBytes := sourceFileStat.Size()
|
fileSizeBytes := sourceFileStat.Size()
|
||||||
writeStringToPty(ctx, cmd, fmt.Sprintf("Source File Size: %v\r\n", prettyPrintByteSize(fileSizeBytes)), &outputPos)
|
writeStringToPty(ctx, cmd, fmt.Sprintf("Source File Size: %v\r\n", prettyPrintByteSize(fileSizeBytes)), &outputPos)
|
||||||
destFile, err := os.Create(destPath)
|
destFile, err := os.Create(destPath)
|
||||||
@ -1571,6 +1586,10 @@ func doCopyRemoteFileToLocal(ctx context.Context, cmd *sstore.CmdType, remoteWsh
|
|||||||
writeStringToPty(ctx, cmd, fmt.Sprintf("Response packet has error: %v\r\n", err), &outputPos)
|
writeStringToPty(ctx, cmd, fmt.Sprintf("Response packet has error: %v\r\n", err), &outputPos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if resp.Info.IsDir {
|
||||||
|
writeStringToPty(ctx, cmd, "Cant copy a directory, try zipping it up first", &outputPos)
|
||||||
|
return
|
||||||
|
}
|
||||||
fileSizeBytes := resp.Info.Size
|
fileSizeBytes := resp.Info.Size
|
||||||
if fileSizeBytes == 0 {
|
if fileSizeBytes == 0 {
|
||||||
writeStringToPty(ctx, cmd, "Source file doesn't exist or file is empty - exiting\r\n", &outputPos)
|
writeStringToPty(ctx, cmd, "Source file doesn't exist or file is empty - exiting\r\n", &outputPos)
|
||||||
@ -1610,6 +1629,7 @@ func doCopyRemoteFileToLocal(ctx context.Context, cmd *sstore.CmdType, remoteWsh
|
|||||||
fileTransferPercentage = float64(bytesWritten) / float64(fileSizeBytes)
|
fileTransferPercentage = float64(bytesWritten) / float64(fileSizeBytes)
|
||||||
|
|
||||||
if fileTransferPercentage-lastFileTransferPercentage > float64(0.05) {
|
if fileTransferPercentage-lastFileTransferPercentage > float64(0.05) {
|
||||||
|
log.Printf("updating percentage\n")
|
||||||
writeStringToPty(ctx, cmd, "-", &outputPos)
|
writeStringToPty(ctx, cmd, "-", &outputPos)
|
||||||
lastFileTransferPercentage = fileTransferPercentage
|
lastFileTransferPercentage = fileTransferPercentage
|
||||||
}
|
}
|
||||||
@ -1647,6 +1667,15 @@ func parseCopyFileParam(info string) (remote string, path string, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fileIsDir(ctx context.Context, ids resolvedIds, remote *ResolvedRemote, filePath string) bool {
|
||||||
|
fileStat, err := getSingleFileStat(ctx, ids, remote, filePath)
|
||||||
|
log.Printf("file is dir: %v", err)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return fileStat.IsDir
|
||||||
|
}
|
||||||
|
|
||||||
func CopyFileCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
func CopyFileCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||||
if len(pk.Args) == 0 {
|
if len(pk.Args) == 0 {
|
||||||
return nil, fmt.Errorf("usage: /copyfile [file to copy] local=[path to copy to on local]")
|
return nil, fmt.Errorf("usage: /copyfile [file to copy] local=[path to copy to on local]")
|
||||||
@ -1716,9 +1745,10 @@ func CopyFileCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scb
|
|||||||
sourceFullPath = filepath.Join(sourceCwd, sourcePathWithHome)
|
sourceFullPath = filepath.Join(sourceCwd, sourcePathWithHome)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if destPath[len(destPath)-1:] == "/" {
|
if destPath[len(destPath)-1:] == "/" || fileIsDir(ctx, ids, destRemoteId, destPath) {
|
||||||
sourceFileName := filepath.Base(sourceFullPath)
|
sourceFileName := filepath.Base(sourceFullPath)
|
||||||
destPath = filepath.Join(destPath, sourceFileName)
|
destPath = filepath.Join(destPath, sourceFileName)
|
||||||
|
log.Printf("destPath: %v", destPath)
|
||||||
}
|
}
|
||||||
destWsh := destRemoteId.Waveshell
|
destWsh := destRemoteId.Waveshell
|
||||||
if destWsh == nil {
|
if destWsh == nil {
|
||||||
@ -1746,15 +1776,15 @@ func CopyFileCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scb
|
|||||||
cmd, err := makeDynCmd(ctx, "copy file", ids, pk.GetRawStr(), *pkTermOpts, nil)
|
cmd, err := makeDynCmd(ctx, "copy file", ids, pk.GetRawStr(), *pkTermOpts, nil)
|
||||||
writeStringToPty(ctx, cmd, outputStr, &outputPos)
|
writeStringToPty(ctx, cmd, outputStr, &outputPos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO tricky error since the command was a success, but we can't show the output
|
return nil, fmt.Errorf("cannot make termopts: %w", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
update, err := addLineForCmd(ctx, "/copy file", false, ids, cmd, "", nil)
|
pkTermOpts := convertTermOpts(termOpts)
|
||||||
|
cmd, err := makeDynCmd(ctx, "copy file", ids, pk.GetRawStr(), *pkTermOpts, nil)
|
||||||
|
writeStringToPty(ctx, cmd, outputStr, &outputPos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO tricky error since the command was a success, but we can't show the output
|
// TODO tricky error since the command was a success, but we can't show the output
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
update.AddUpdate(sstore.InteractiveUpdate(pk.Interactive))
|
|
||||||
if destRemote != ConnectedRemote && destRemoteId != nil && !destRemoteId.RState.IsConnected() {
|
if destRemote != ConnectedRemote && destRemoteId != nil && !destRemoteId.RState.IsConnected() {
|
||||||
writeStringToPty(ctx, cmd, fmt.Sprintf("Attempting to autoconnect to remote %v\r\n", destRemote), &outputPos)
|
writeStringToPty(ctx, cmd, fmt.Sprintf("Attempting to autoconnect to remote %v\r\n", destRemote), &outputPos)
|
||||||
err = destRemoteId.Waveshell.TryAutoConnect()
|
err = destRemoteId.Waveshell.TryAutoConnect()
|
||||||
@ -1773,8 +1803,7 @@ func CopyFileCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scb
|
|||||||
writeStringToPty(ctx, cmd, "Auto connect successful\r\n", &outputPos)
|
writeStringToPty(ctx, cmd, "Auto connect successful\r\n", &outputPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scbus.MainUpdateBus.DoScreenUpdate(cmd.ScreenId, update)
|
update := scbus.MakeUpdatePacket()
|
||||||
update = scbus.MakeUpdatePacket()
|
|
||||||
if destRemote == LocalRemote && sourceRemote == LocalRemote {
|
if destRemote == LocalRemote && sourceRemote == LocalRemote {
|
||||||
go doCopyLocalFileToLocal(context.Background(), cmd, sourceFullPath, destFullPath, outputPos)
|
go doCopyLocalFileToLocal(context.Background(), cmd, sourceFullPath, destFullPath, outputPos)
|
||||||
} else if destRemote == LocalRemote && sourceRemote != LocalRemote {
|
} else if destRemote == LocalRemote && sourceRemote != LocalRemote {
|
||||||
@ -5039,6 +5068,10 @@ func SetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.Up
|
|||||||
func makeStreamFilePk(ids resolvedIds, pk *scpacket.FeCommandPacketType) (*packet.StreamFilePacketType, error) {
|
func makeStreamFilePk(ids resolvedIds, pk *scpacket.FeCommandPacketType) (*packet.StreamFilePacketType, error) {
|
||||||
cwd := ids.Remote.FeState["cwd"]
|
cwd := ids.Remote.FeState["cwd"]
|
||||||
fileArg := pk.Args[0]
|
fileArg := pk.Args[0]
|
||||||
|
return makeStreamFilePkFromParams(cwd, fileArg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeStreamFilePkFromParams(cwd string, fileArg string) (*packet.StreamFilePacketType, error) {
|
||||||
if fileArg == "" {
|
if fileArg == "" {
|
||||||
return nil, fmt.Errorf("/view:stat file argument must be set (cannot be empty)")
|
return nil, fmt.Errorf("/view:stat file argument must be set (cannot be empty)")
|
||||||
}
|
}
|
||||||
@ -5050,6 +5083,7 @@ func makeStreamFilePk(ids resolvedIds, pk *scpacket.FeCommandPacketType) (*packe
|
|||||||
streamPk.Path = filepath.Join(cwd, fileArg)
|
streamPk.Path = filepath.Join(cwd, fileArg)
|
||||||
}
|
}
|
||||||
return streamPk, nil
|
return streamPk, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ViewStatCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
func ViewStatCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||||
@ -5060,42 +5094,18 @@ func ViewStatCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scb
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
streamPk, err := makeStreamFilePk(ids, pk)
|
fileArg := pk.Args[0]
|
||||||
|
statPk, streamPk, err := getFileStat(ctx, ids, fileArg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
streamPk.StatOnly = true
|
|
||||||
wsh := ids.Remote.Waveshell
|
|
||||||
iter, err := wsh.StreamFile(ctx, streamPk)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("/view:stat error: %v", err)
|
|
||||||
}
|
|
||||||
defer iter.Close()
|
|
||||||
respIf, err := iter.Next(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("/view:stat error getting response: %v", err)
|
|
||||||
}
|
|
||||||
resp, ok := respIf.(*packet.StreamFileResponseType)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("/view:stat error, bad response packet type: %T", respIf)
|
|
||||||
}
|
|
||||||
if resp.Error != "" {
|
|
||||||
return nil, fmt.Errorf("/view:stat error: %s", resp.Error)
|
|
||||||
}
|
|
||||||
if resp.Info == nil {
|
|
||||||
return nil, fmt.Errorf("/view:stat error, no file info")
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "path", resp.Info.Name))
|
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "path", statPk.Name))
|
||||||
buf.WriteString(fmt.Sprintf(" %-15s %d\n", "size", resp.Info.Size))
|
buf.WriteString(fmt.Sprintf(" %-15s %d\n", "size", statPk.Size))
|
||||||
modTs := time.UnixMilli(resp.Info.ModTs)
|
modTs := statPk.ModTs
|
||||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "modts", modTs.Format(TsFormatStr)))
|
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "modts", modTs.Format(TsFormatStr)))
|
||||||
buf.WriteString(fmt.Sprintf(" %-15s %v\n", "isdir", resp.Info.IsDir))
|
buf.WriteString(fmt.Sprintf(" %-15s %v\n", "isdir", statPk.IsDir))
|
||||||
modeStr := fs.FileMode(resp.Info.Perm).String()
|
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "perms", statPk.ModeStr))
|
||||||
if len(modeStr) > 9 {
|
|
||||||
modeStr = modeStr[len(modeStr)-9:]
|
|
||||||
}
|
|
||||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "perms", modeStr))
|
|
||||||
update := scbus.MakeUpdatePacket()
|
update := scbus.MakeUpdatePacket()
|
||||||
update.AddUpdate(sstore.InfoMsgType{
|
update.AddUpdate(sstore.InfoMsgType{
|
||||||
InfoTitle: fmt.Sprintf("view stat %q", streamPk.Path),
|
InfoTitle: fmt.Sprintf("view stat %q", streamPk.Path),
|
||||||
@ -5104,6 +5114,62 @@ func ViewStatCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scb
|
|||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSingleFileStat(ctx context.Context, ids resolvedIds, remote *ResolvedRemote, fileArg string) (*packet.FileStatPacketType, error) {
|
||||||
|
if remote.RemoteCopy.IsLocal() {
|
||||||
|
fileStat, err := os.Stat(fileArg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
statPk := packet.MakeFileStatPacketFromFileInfo(nil, fileStat, "", true)
|
||||||
|
return statPk, nil
|
||||||
|
} else {
|
||||||
|
statPk, _, err := getFileStat(ctx, ids, fileArg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return statPk, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFileStat(ctx context.Context, ids resolvedIds, fileArg string) (*packet.FileStatPacketType, *packet.StreamFilePacketType, error) {
|
||||||
|
streamPk, err := makeStreamFilePkFromParams(ids.Remote.FeState["cwd"], fileArg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
streamPk.StatOnly = true
|
||||||
|
wsh := ids.Remote.Waveshell
|
||||||
|
iter, err := wsh.StreamFile(ctx, streamPk)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("/view:stat error: %v", err)
|
||||||
|
}
|
||||||
|
defer iter.Close()
|
||||||
|
respIf, err := iter.Next(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("/view:stat error getting response: %v", err)
|
||||||
|
}
|
||||||
|
resp, ok := respIf.(*packet.StreamFileResponseType)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, fmt.Errorf("/view:stat error, bad response packet type: %T", respIf)
|
||||||
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
return nil, nil, fmt.Errorf("/view:stat error: %s", resp.Error)
|
||||||
|
}
|
||||||
|
if resp.Info == nil {
|
||||||
|
return nil, nil, fmt.Errorf("/view:stat error, no file info")
|
||||||
|
}
|
||||||
|
statPk := packet.MakeFileStatPacketType()
|
||||||
|
statPk.Name = resp.Info.Name
|
||||||
|
statPk.Size = resp.Info.Size
|
||||||
|
statPk.ModTs = time.UnixMilli(resp.Info.ModTs)
|
||||||
|
statPk.IsDir = resp.Info.IsDir
|
||||||
|
statPk.Perm = resp.Info.Perm
|
||||||
|
statPk.ModeStr = fs.FileMode(statPk.Perm).String()
|
||||||
|
if len(statPk.ModeStr) > 9 {
|
||||||
|
statPk.ModeStr = statPk.ModeStr[len(statPk.ModeStr)-9:]
|
||||||
|
}
|
||||||
|
return statPk, streamPk, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ViewTestCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
func ViewTestCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||||
if len(pk.Args) == 0 {
|
if len(pk.Args) == 0 {
|
||||||
return nil, fmt.Errorf("/view:test requires an argument (file name)")
|
return nil, fmt.Errorf("/view:test requires an argument (file name)")
|
||||||
@ -5388,6 +5454,209 @@ func MarkdownViewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
|||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StatDir(ctx context.Context, ids resolvedIds, path string, fileCallback func(pk *packet.FileStatPacketType, done bool, err error)) {
|
||||||
|
statPk, _, err := getFileStat(ctx, ids, path)
|
||||||
|
log.Printf("statPk: %\n", statPk)
|
||||||
|
if err != nil {
|
||||||
|
fileCallback(nil, true, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !statPk.IsDir {
|
||||||
|
fileCallback(statPk, true, nil)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
cwd := ids.Remote.FeState["cwd"]
|
||||||
|
listDirPk := packet.MakeListDirPacket()
|
||||||
|
listDirPk.ReqId = uuid.New().String()
|
||||||
|
if filepath.IsAbs(path) {
|
||||||
|
listDirPk.Path = path
|
||||||
|
} else {
|
||||||
|
listDirPk.Path = filepath.Join(cwd, path)
|
||||||
|
}
|
||||||
|
msh := ids.Remote.Waveshell
|
||||||
|
listDirIter, err := msh.ListDir(ctx, listDirPk)
|
||||||
|
if err != nil {
|
||||||
|
fileCallback(nil, true, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer listDirIter.Close()
|
||||||
|
for {
|
||||||
|
respIf, err := listDirIter.Next(ctx)
|
||||||
|
if err != nil {
|
||||||
|
fileCallback(nil, true, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, ok := respIf.(*packet.FileStatPacketType)
|
||||||
|
if !ok || resp == nil {
|
||||||
|
fileCallback(nil, true, fmt.Errorf("error unmarshalling file stat response type %v %v", resp, respIf))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
err = fmt.Errorf(resp.Error)
|
||||||
|
} else {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
fileCallback(resp, resp.Done, err)
|
||||||
|
if resp.Done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SearchDir(ctx context.Context, ids resolvedIds, path string, searchQuery string, fileCallback func(pk *packet.FileStatPacketType, done bool, err error)) {
|
||||||
|
log.Printf("running searchdir %v %v \n", path, searchQuery)
|
||||||
|
statPk, _, err := getFileStat(ctx, ids, path)
|
||||||
|
if err != nil {
|
||||||
|
fileCallback(nil, true, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !statPk.IsDir {
|
||||||
|
match, err := regexp.MatchString(searchQuery, statPk.Name)
|
||||||
|
if err != nil {
|
||||||
|
fileCallback(nil, true, err)
|
||||||
|
}
|
||||||
|
if match {
|
||||||
|
fileCallback(statPk, true, nil)
|
||||||
|
} else {
|
||||||
|
fileCallback(nil, true, nil)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cwd := ids.Remote.FeState["cwd"]
|
||||||
|
searchDirPk := packet.MakeSearchDirPacket()
|
||||||
|
searchDirPk.ReqId = uuid.New().String()
|
||||||
|
if filepath.IsAbs(path) {
|
||||||
|
searchDirPk.Path = path
|
||||||
|
} else {
|
||||||
|
searchDirPk.Path = filepath.Join(cwd, path)
|
||||||
|
}
|
||||||
|
searchDirPk.SearchQuery = searchQuery
|
||||||
|
msh := ids.Remote.Waveshell
|
||||||
|
searchDirIter, err := msh.SearchDir(ctx, searchDirPk)
|
||||||
|
if err != nil {
|
||||||
|
fileCallback(nil, true, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer searchDirIter.Close()
|
||||||
|
for {
|
||||||
|
respIf, err := searchDirIter.Next(ctx)
|
||||||
|
log.Printf("got next\n")
|
||||||
|
if err != nil {
|
||||||
|
fileCallback(nil, true, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, ok := respIf.(*packet.FileStatPacketType)
|
||||||
|
if !ok || resp == nil {
|
||||||
|
fileCallback(nil, true, fmt.Errorf("error unmarshalling file stat response type %v %v", resp, respIf))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("resp: %v\n", resp)
|
||||||
|
if resp.Error == "none" {
|
||||||
|
fileCallback(nil, true, nil)
|
||||||
|
return
|
||||||
|
} else if resp.Error != "" {
|
||||||
|
err = fmt.Errorf(resp.Error)
|
||||||
|
} else {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
if resp.Done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileCallback(resp, resp.Done, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SearchDirCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||||
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_RemoteConnected)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
path := ids.Remote.FeState["cwd"]
|
||||||
|
if len(pk.Args) > 0 {
|
||||||
|
path = pk.Args[0]
|
||||||
|
}
|
||||||
|
var searchQuery string
|
||||||
|
if len(pk.Args) > 1 {
|
||||||
|
searchQuery = pk.Args[1]
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("no search query specified - usage /searchdir [path] [query]")
|
||||||
|
}
|
||||||
|
lineId := pk.Kwargs["lineid"]
|
||||||
|
screenId := pk.Kwargs["screenid"]
|
||||||
|
cmd, err := sstore.GetCmdByScreenId(ctx, screenId, lineId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outputPty := resolveBool(pk.Kwargs["outputpty"], false)
|
||||||
|
if outputPty {
|
||||||
|
ids.Remote.Waveshell.ResetDataPos(base.MakeCommandKey(screenId, lineId))
|
||||||
|
err = sstore.ClearCmdPtyFile(ctx, screenId, lineId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error clearing existing pty file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
var outputPos int64
|
||||||
|
searchCtx := context.Background()
|
||||||
|
SearchDir(searchCtx, ids, path, searchQuery, func(statPk *packet.FileStatPacketType, done bool, err error) {
|
||||||
|
log.Printf("got callback\n")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("got error: %v\n", err)
|
||||||
|
} else {
|
||||||
|
err = writePacketToPty(searchCtx, cmd, statPk, &outputPos)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("err writing packet to pty: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
update := scbus.MakeUpdatePacket()
|
||||||
|
return update, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ViewDirCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||||
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_RemoteConnected)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
path := ids.Remote.FeState["cwd"]
|
||||||
|
if len(pk.Args) > 0 {
|
||||||
|
path = pk.Args[0]
|
||||||
|
}
|
||||||
|
lineId := pk.Kwargs["lineid"]
|
||||||
|
screenId := pk.Kwargs["screenid"]
|
||||||
|
cmd, err := sstore.GetCmdByScreenId(ctx, screenId, lineId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outputPty := resolveBool(pk.Kwargs["outputpty"], false)
|
||||||
|
if outputPty {
|
||||||
|
ids.Remote.Waveshell.ResetDataPos(base.MakeCommandKey(screenId, lineId))
|
||||||
|
err = sstore.ClearCmdPtyFile(ctx, screenId, lineId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error clearing existing pty file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
var outputPos int64
|
||||||
|
statCtx := context.Background()
|
||||||
|
StatDir(statCtx, ids, path, func(statPk *packet.FileStatPacketType, done bool, err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("got error: %v\n", err)
|
||||||
|
} else {
|
||||||
|
err = writePacketToPty(statCtx, cmd, statPk, &outputPos)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("err writing packet to pty: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
update := scbus.MakeUpdatePacket()
|
||||||
|
return update, nil
|
||||||
|
}
|
||||||
|
|
||||||
func EditTestCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
func EditTestCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||||
if len(pk.Args) == 0 {
|
if len(pk.Args) == 0 {
|
||||||
return nil, fmt.Errorf("/edit:test requires an argument (file name)")
|
return nil, fmt.Errorf("/edit:test requires an argument (file name)")
|
||||||
@ -5982,6 +6251,52 @@ func ClientSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sc
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error updating client ai base url: %v", err)
|
return nil, fmt.Errorf("error updating client ai base url: %v", err)
|
||||||
}
|
}
|
||||||
|
feOpts := clientData.FeOpts
|
||||||
|
feOpts.SudoPwStore = strings.ToLower(sudoPwStoreStr)
|
||||||
|
err = sstore.UpdateClientFeOpts(ctx, feOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error updating client feopts: %v", err)
|
||||||
|
}
|
||||||
|
// clear all sudo pw if turning off
|
||||||
|
if feOpts.SudoPwStore == "off" {
|
||||||
|
for _, proc := range remote.GetRemoteMap() {
|
||||||
|
proc.ClearCachedSudoPw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
varsUpdated = append(varsUpdated, "sudopwstore")
|
||||||
|
}
|
||||||
|
if sudoPwTimeoutStr, found := pk.Kwargs["sudopwtimeout"]; found {
|
||||||
|
oldPwTimeout := clientData.FeOpts.SudoPwTimeoutMs / 1000 / 60 // ms to minutes
|
||||||
|
if oldPwTimeout == 0 {
|
||||||
|
oldPwTimeout = sstore.DefaultSudoTimeout
|
||||||
|
}
|
||||||
|
newSudoPwTimeout, err := resolveNonNegInt(sudoPwTimeoutStr, sstore.DefaultSudoTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid sudo pw timeout, must be a number greater than 0: %v", err)
|
||||||
|
}
|
||||||
|
if newSudoPwTimeout == 0 {
|
||||||
|
return nil, fmt.Errorf("invalid sudo pw timeout, must be a number greater than 0")
|
||||||
|
}
|
||||||
|
feOpts := clientData.FeOpts
|
||||||
|
feOpts.SudoPwTimeoutMs = newSudoPwTimeout * 60 * 1000 // minutes to ms
|
||||||
|
err = sstore.UpdateClientFeOpts(ctx, feOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error updating client feopts: %v", err)
|
||||||
|
}
|
||||||
|
for _, proc := range remote.GetRemoteMap() {
|
||||||
|
proc.ChangeSudoTimeout(int64(newSudoPwTimeout - oldPwTimeout))
|
||||||
|
}
|
||||||
|
varsUpdated = append(varsUpdated, "sudopwtimeout")
|
||||||
|
}
|
||||||
|
if sudoPwClearOnSleepStr, found := pk.Kwargs["sudopwclearonsleep"]; found {
|
||||||
|
newSudoPwClearOnSleep := resolveBool(sudoPwClearOnSleepStr, true)
|
||||||
|
feOpts := clientData.FeOpts
|
||||||
|
feOpts.NoSudoPwClearOnSleep = !newSudoPwClearOnSleep
|
||||||
|
err = sstore.UpdateClientFeOpts(ctx, feOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error updating client feopts: %v", err)
|
||||||
|
}
|
||||||
|
varsUpdated = append(varsUpdated, "sudopwclearonsleep")
|
||||||
}
|
}
|
||||||
if aiTimeoutStr, found := CheckOptionAlias(pk.Kwargs, "openaitimeout", "aitimeout"); found {
|
if aiTimeoutStr, found := CheckOptionAlias(pk.Kwargs, "openaitimeout", "aitimeout"); found {
|
||||||
aiTimeout, err := strconv.ParseFloat(aiTimeoutStr, 64)
|
aiTimeout, err := strconv.ParseFloat(aiTimeoutStr, 64)
|
||||||
|
@ -1522,6 +1522,18 @@ func (wsh *WaveshellProc) StreamFile(ctx context.Context, streamPk *packet.Strea
|
|||||||
return wsh.PacketRpcIter(ctx, streamPk)
|
return wsh.PacketRpcIter(ctx, streamPk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msh *WaveshellProc) ListDir(ctx context.Context, listDirPk *packet.ListDirPacketType) (*packet.RpcResponseIter, error) {
|
||||||
|
return msh.PacketRpcIter(ctx, listDirPk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msh *WaveshellProc) SearchDir(ctx context.Context, searchDirPk *packet.SearchDirPacketType) (*packet.RpcResponseIter, error) {
|
||||||
|
return msh.PacketRpcIter(ctx, searchDirPk)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wsh *WaveshellProc) StreamFile(ctx context.Context, streamPk *packet.StreamFilePacketType) (*packet.RpcResponseIter, error) {
|
||||||
|
return wsh.PacketRpcIter(ctx, streamPk)
|
||||||
|
}
|
||||||
|
|
||||||
func addScVarsToState(state *packet.ShellState) *packet.ShellState {
|
func addScVarsToState(state *packet.ShellState) *packet.ShellState {
|
||||||
if state == nil {
|
if state == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -2210,6 +2222,7 @@ func (wsh *WaveshellProc) PacketRpcIter(ctx context.Context, pk packet.RpcPacket
|
|||||||
if pk == nil {
|
if pk == nil {
|
||||||
return nil, fmt.Errorf("PacketRpc passed nil packet")
|
return nil, fmt.Errorf("PacketRpc passed nil packet")
|
||||||
}
|
}
|
||||||
|
log.Printf("sending packet: %v", pk)
|
||||||
reqId := pk.GetReqId()
|
reqId := pk.GetReqId()
|
||||||
wsh.ServerProc.Output.RegisterRpcSz(reqId, RpcIterChannelSize)
|
wsh.ServerProc.Output.RegisterRpcSz(reqId, RpcIterChannelSize)
|
||||||
err := wsh.ServerProc.Input.SendPacketCtx(ctx, pk)
|
err := wsh.ServerProc.Input.SendPacketCtx(ctx, pk)
|
||||||
|
Loading…
Reference in New Issue
Block a user