From 108517bd086edc56b2a33134cb57436c2eaba948 Mon Sep 17 00:00:00 2001 From: sawka Date: Tue, 31 Jan 2023 17:56:56 -0800 Subject: [PATCH] add /screen:reset to remove all remote instances for screen --- pkg/cmdrunner/cmdrunner.go | 56 +++++++++++++++++++++++++++++++++++--- pkg/sstore/dbops.go | 25 +++++++++++++++-- pkg/sstore/updatebus.go | 2 +- 3 files changed, 76 insertions(+), 7 deletions(-) diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index 8412aa8e..d40c84ed 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -134,6 +134,7 @@ func init() { registerCmdAlias("screen:new", ScreenOpenCommand) registerCmdFn("screen:set", ScreenSetCommand) registerCmdFn("screen:showall", ScreenShowAllCommand) + registerCmdFn("screen:reset", ScreenResetCommand) registerCmdAlias("remote", RemoteCommand) registerCmdFn("remote:show", RemoteShowCommand) @@ -145,6 +146,7 @@ func init() { registerCmdFn("remote:connect", RemoteConnectCommand) registerCmdFn("remote:install", RemoteInstallCommand) registerCmdFn("remote:installcancel", RemoteInstallCancelCommand) + registerCmdFn("remote:reset", RemoteResetCommand) registerCmdFn("sw:set", SwSetCommand) registerCmdFn("sw:resize", SwResizeCommand) @@ -1004,6 +1006,52 @@ func ScreenShowAllCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) }, nil } +func ScreenResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { + ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen) + if err != nil { + return nil, err + } + screen, err := sstore.GetScreenById(ctx, ids.SessionId, ids.ScreenId) + if err != nil { + return nil, fmt.Errorf("error retrieving screen: %v", err) + } + localRemote := remote.GetLocalRemote() + if localRemote == nil { + return nil, fmt.Errorf("error getting local remote (not found)") + } + rptr := sstore.RemotePtrType{RemoteId: localRemote.RemoteId} + var windows []*sstore.WindowType + sessionUpdate := &sstore.SessionType{SessionId: ids.SessionId} + for _, sw := range screen.Windows { + ris, err := sstore.WindowReset(ctx, ids.SessionId, sw.WindowId) + if err != nil { + return nil, fmt.Errorf("error resetting screen window: %v", err) + } + sessionUpdate.Remotes = append(sessionUpdate.Remotes, ris...) + err = sstore.UpdateCurRemote(ctx, ids.SessionId, sw.WindowId, rptr) + if err != nil { + return nil, fmt.Errorf("cannot reset window remote back to local: %w", err) + } + winUpdate := &sstore.WindowType{SessionId: ids.SessionId, WindowId: sw.WindowId, CurRemote: rptr} + windows = append(windows, winUpdate) + } + outputStr := "reset screen state (all remote state reset)" + cmd, err := makeStaticCmd(ctx, "screen:reset", ids, pk.GetRawStr(), []byte(outputStr)) + if err != nil { + // TODO tricky error since the command was a success, but we can't show the output + return nil, err + } + update, err := addLineForCmd(ctx, "/screen:reset", false, ids, cmd) + if err != nil { + // TODO tricky error since the command was a success, but we can't show the output + return nil, err + } + update.Interactive = pk.Interactive + update.Windows = windows + update.Sessions = []*sstore.SessionType{sessionUpdate} + return update, nil +} + func RemoteArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote) if err != nil { @@ -1016,11 +1064,11 @@ func RemoteArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) update := sstore.InfoMsgUpdate("remote [%s] archived", ids.Remote.DisplayName) localRemote := remote.GetLocalRemote() if localRemote != nil { - update.Window = &sstore.WindowType{ + update.Windows = []*sstore.WindowType{&sstore.WindowType{ SessionId: ids.SessionId, WindowId: ids.WindowId, CurRemote: sstore.RemotePtrType{RemoteId: localRemote.GetRemoteId()}, - } + }} } return update, nil } @@ -1102,11 +1150,11 @@ func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.Up return nil, fmt.Errorf("/cr error: cannot update curremote: %w", err) } update := sstore.ModelUpdate{ - Window: &sstore.WindowType{ + Windows: []*sstore.WindowType{&sstore.WindowType{ SessionId: ids.SessionId, WindowId: ids.WindowId, CurRemote: *rptr, - }, + }}, Info: &sstore.InfoMsgType{ InfoMsg: fmt.Sprintf("current remote = %q", remoteName), TimeoutMs: 2000, diff --git a/pkg/sstore/dbops.go b/pkg/sstore/dbops.go index 1a1b52e5..bd09ff2c 100644 --- a/pkg/sstore/dbops.go +++ b/pkg/sstore/dbops.go @@ -1252,7 +1252,7 @@ func ArchiveWindowLines(ctx context.Context, sessionId string, windowId string) if err != nil { return nil, err } - return &ModelUpdate{Window: win}, nil + return &ModelUpdate{Windows: []*WindowType{win}}, nil } func PurgeWindowLines(ctx context.Context, sessionId string, windowId string) (*ModelUpdate, error) { @@ -1289,7 +1289,7 @@ func PurgeWindowLines(ctx context.Context, sessionId string, windowId string) (* } win.Lines = append(win.Lines, line) } - return &ModelUpdate{Window: win}, nil + return &ModelUpdate{Windows: []*WindowType{win}}, nil } func GetRunningWindowCmds(ctx context.Context, sessionId string, windowId string) ([]*CmdType, error) { @@ -1317,6 +1317,27 @@ func UpdateCmdTermOpts(ctx context.Context, sessionId string, cmdId string, term return txErr } +// returns riids of deleted RIs +func WindowReset(ctx context.Context, sessionId string, windowId string) ([]*RemoteInstance, error) { + var delRis []*RemoteInstance + txErr := WithTx(ctx, func(tx *TxWrap) error { + query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?` + if !tx.Exists(query, sessionId, windowId) { + return fmt.Errorf("window does not exist") + } + query = `SELECT riid FROM remote_instance WHERE sessionid = ? AND windowid = ?` + riids := tx.SelectStrings(query, sessionId, windowId) + for _, riid := range riids { + ri := &RemoteInstance{SessionId: sessionId, WindowId: windowId, RIId: riid, Remove: true} + delRis = append(delRis, ri) + } + query = `DELETE FROM remote_instance WHERE sessionid = ? AND windowid = ?` + tx.ExecWrap(query, sessionId, windowId) + return nil + }) + return delRis, txErr +} + func DeleteSession(ctx context.Context, sessionId string) (UpdatePacket, error) { var newActiveSessionId string txErr := WithTx(ctx, func(tx *TxWrap) error { diff --git a/pkg/sstore/updatebus.go b/pkg/sstore/updatebus.go index 4c5ba2aa..84cbb302 100644 --- a/pkg/sstore/updatebus.go +++ b/pkg/sstore/updatebus.go @@ -32,7 +32,7 @@ func (PtyDataUpdate) UpdateType() string { type ModelUpdate struct { Sessions []*SessionType `json:"sessions,omitempty"` ActiveSessionId string `json:"activesessionid,omitempty"` - Window *WindowType `json:"window,omitempty"` + Windows []*WindowType `json:"windows,omitempty"` ScreenWindows []*ScreenWindowType `json:"screenwindows,omitempty"` Line *LineType `json:"line,omitempty"` Cmd *CmdType `json:"cmd,omitempty"`