mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
reinit updates (#500)
* working on re-init when you create a tab. some refactoring of existing reinit to make the messaging clearer. auto-connect, etc. * working to remove the 'default' shell states out of MShellProc. each tab should have its own state that gets set on open. * refactor newtab settings into individual components (and move to a new file) * more refactoring of tab settings -- use same control in settings and newtab * have screensettings use the same newtab settings components * use same conn dropdown, fix classes, update some of the confirm messages to be less confusing (replace screen with tab) * force a cr on a new tab to initialize state in a new line. poc right now, need to add to new workspace workflow as well * small fixups * remove nohist from GetRawStr, make const * update hover behavior for tabs * fix interaction between change remote dropdown, cmdinput, error handling, and selecting a remote * only switch screen remote if the activemainview is session (new remote flow). don't switch it if we're on the connections page which is confusing. also make it interactive * fix wording on tos modal * allow empty workspaces. also allow the last workspace to be deleted. (prep for new startup sequence where we initialize the first session after tos modal) * add some dead code that might come in use later (when we change how we show connection in cmdinput) * working a cople different angles. new settings tab-pulldown (likely orphaned). and then allowing null activeScreen and null activeSession in workspaceview (show appropriate messages, and give buttons to create new tabs/workspaces). prep for new startup flow * don't call initActiveShells anymore. also call ensureWorkspace() on TOS close * trying to use new pulldown screen settings * experiment with an escape keybinding * working on tab settings close triggers * close tab settings on tab switch * small updates to tos popup, reorder, update button text/size, small wording updates * when deleting a screen, send SIGHUP to all running commands * not sure how this happened, lineid should not be passed to setLineFocus * remove context timeouts for ReInit (it is now interactive, so it gets canceled like a normal command -- via ^C, and should not timeout on its own) * deal with screen/session tombstones updates (ignore to quite warning) * remove defaultfestate from remote * fix issue with removing default ris * remove dead code * open the settings pulldown for new screens * update prompt to show when the shell is still initializing (or if it failed) * switch buttons to use wave button class, update messages, and add warning for no shell state * all an override of rptr for dyncmds. needed for the 'connect' command (we need to set the rptr to the *new* connection rather than the old one) * remove old commented out code
This commit is contained in:
@@ -978,11 +978,6 @@ func main() {
|
||||
log.Printf("[error] ensuring local remote: %v\n", err)
|
||||
return
|
||||
}
|
||||
err = sstore.EnsureOneSession(context.Background())
|
||||
if err != nil {
|
||||
log.Printf("[error] ensuring default session: %v\n", err)
|
||||
return
|
||||
}
|
||||
err = remote.LoadRemotes(context.Background())
|
||||
if err != nil {
|
||||
log.Printf("[error] loading remotes: %v\n", err)
|
||||
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/base"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/server"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/shellapi"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/shellenv"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/shellutil"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/shexec"
|
||||
@@ -96,6 +95,7 @@ const (
|
||||
KwArgTemplate = "template"
|
||||
KwArgLang = "lang"
|
||||
KwArgMinimap = "minimap"
|
||||
KwArgNoHist = "nohist"
|
||||
)
|
||||
|
||||
var ColorNames = []string{"yellow", "blue", "pink", "mint", "cyan", "violet", "orange", "green", "red", "white"}
|
||||
@@ -190,6 +190,7 @@ func init() {
|
||||
registerCmdFn("session:showall", SessionShowAllCommand)
|
||||
registerCmdFn("session:show", SessionShowCommand)
|
||||
registerCmdFn("session:openshared", SessionOpenSharedCommand)
|
||||
registerCmdFn("session:ensureone", SessionEnsureOneCommand)
|
||||
|
||||
registerCmdFn("screen", ScreenCommand)
|
||||
registerCmdFn("screen:archive", ScreenArchiveCommand)
|
||||
@@ -364,6 +365,20 @@ func resolveCommaSepListToMap(arg string) map[string]bool {
|
||||
return rtn
|
||||
}
|
||||
|
||||
func resolveShellType(shellArg string, defaultShell string) (string, error) {
|
||||
if shellArg == "" {
|
||||
if defaultShell == "" {
|
||||
shellArg = packet.ShellType_bash
|
||||
} else {
|
||||
shellArg = defaultShell
|
||||
}
|
||||
}
|
||||
if shellArg != packet.ShellType_bash && shellArg != packet.ShellType_zsh {
|
||||
return "", fmt.Errorf("invalid shell type %q", shellArg)
|
||||
}
|
||||
return shellArg, nil
|
||||
}
|
||||
|
||||
func resolveBool(arg string, def bool) bool {
|
||||
if arg == "" {
|
||||
return def
|
||||
@@ -723,7 +738,7 @@ func EvalCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.U
|
||||
} else {
|
||||
return nil, fmt.Errorf("error in Eval Meta Command: %w", rtnErr)
|
||||
}
|
||||
if !resolveBool(pk.Kwargs["nohist"], false) {
|
||||
if !resolveBool(pk.Kwargs[KwArgNoHist], false) {
|
||||
// TODO should this be "pk" or "newPk" (2nd arg)
|
||||
err := addToHistory(ctx, pk, historyContext, (newPk.MetaCmd != "run"), (rtnErr != nil))
|
||||
if err != nil {
|
||||
@@ -816,6 +831,14 @@ func ScreenDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
if screenId == "" {
|
||||
return nil, fmt.Errorf("/screen:delete no active screen or screen arg passed")
|
||||
}
|
||||
runningCmds, err := sstore.GetRunningScreenCmds(ctx, screenId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/screen:delete cannot get running cmds: %v", err)
|
||||
}
|
||||
for _, runningCmd := range runningCmds {
|
||||
// send SIGHUP to all running commands in this screen
|
||||
remote.SendSignalToCmd(ctx, runningCmd, "SIGHUP")
|
||||
}
|
||||
update, err := sstore.DeleteScreen(ctx, screenId, false, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -826,7 +849,7 @@ func ScreenDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
func ScreenOpenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||
ids, err := resolveUiIds(ctx, pk, R_Session)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/screen:open cannot open screen: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
activate := resolveBool(pk.Kwargs["activate"], true)
|
||||
newName := pk.Kwargs["name"]
|
||||
@@ -836,13 +859,37 @@ func ScreenOpenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
update, err := sstore.InsertScreen(ctx, ids.SessionId, newName, sstore.ScreenCreateOpts{}, activate)
|
||||
sco := sstore.ScreenCreateOpts{RtnScreenId: new(string)}
|
||||
update, err := sstore.InsertScreen(ctx, ids.SessionId, newName, sco, activate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sco.RtnScreenId == nil {
|
||||
return nil, fmt.Errorf("error creating tab, no tab id returned")
|
||||
}
|
||||
uiContextCopy := *pk.UIContext
|
||||
uiContextCopy.ScreenId = *sco.RtnScreenId
|
||||
crUpdate, err := doNewTabConnectLocal(ctx, *sco.RtnScreenId, &uiContextCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update.Merge(crUpdate)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func doNewTabConnectLocal(ctx context.Context, screenId string, uiContext *scpacket.UIContextType) (scbus.UpdatePacket, error) {
|
||||
crPk := scpacket.MakeFeCommandPacket()
|
||||
crPk.MetaCmd = "connect"
|
||||
crPk.Args = []string{"local"}
|
||||
crPk.RawStr = "/connect local"
|
||||
crPk.UIContext = uiContext
|
||||
crUpdate, err := CrCommand(ctx, crPk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating tab, cannot connect to remote: %w", err)
|
||||
}
|
||||
return crUpdate, nil
|
||||
}
|
||||
|
||||
func ScreenReorderCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||
// Resolve the UI IDs for the session and screen
|
||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen)
|
||||
@@ -1666,7 +1713,7 @@ func CopyFileCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scb
|
||||
return nil, fmt.Errorf("cannot make termopts: %w", err)
|
||||
}
|
||||
pkTermOpts := convertTermOpts(termOpts)
|
||||
cmd, err := makeDynCmd(ctx, "copy file", ids, pk.GetRawStr(), *pkTermOpts)
|
||||
cmd, err := makeDynCmd(ctx, "copy file", ids, pk.GetRawStr(), *pkTermOpts, nil)
|
||||
writeStringToPty(ctx, cmd, outputStr, &outputPos)
|
||||
if err != nil {
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
@@ -2462,10 +2509,16 @@ func crShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType, ids re
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get remote instances: %w", err)
|
||||
}
|
||||
rmap := remote.GetRemoteMap()
|
||||
if len(riArr) == 0 {
|
||||
update := scbus.MakeUpdatePacket()
|
||||
update.AddUpdate(sstore.InfoMsgType{
|
||||
InfoMsg: "this tab has no shell states",
|
||||
})
|
||||
return update, nil
|
||||
}
|
||||
for _, ri := range riArr {
|
||||
rptr := sstore.RemotePtrType{RemoteId: ri.RemoteId, Name: ri.Name}
|
||||
msh := rmap[ri.RemoteId]
|
||||
msh := remote.GetRemoteById(ri.RemoteId)
|
||||
if msh == nil {
|
||||
continue
|
||||
}
|
||||
@@ -2477,28 +2530,9 @@ func crShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType, ids re
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("%-30s %-50s\n", displayName, cwdStr))
|
||||
}
|
||||
riBaseMap := make(map[string]bool)
|
||||
for _, ri := range riArr {
|
||||
if ri.Name == "" {
|
||||
riBaseMap[ri.RemoteId] = true
|
||||
}
|
||||
}
|
||||
for remoteId, msh := range rmap {
|
||||
if riBaseMap[remoteId] {
|
||||
continue
|
||||
}
|
||||
feState := msh.GetDefaultFeState(msh.GetShellPref())
|
||||
if feState == nil {
|
||||
continue
|
||||
}
|
||||
cwdStr := "-"
|
||||
if feState["cwd"] != "" {
|
||||
cwdStr = feState["cwd"]
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf("%-30s %-50s (default)\n", msh.GetDisplayName(), cwdStr))
|
||||
}
|
||||
update := scbus.MakeUpdatePacket()
|
||||
update.AddUpdate(sstore.InfoMsgType{
|
||||
InfoTitle: "shell states for tab",
|
||||
InfoLines: splitLinesForInfo(buf.String()),
|
||||
})
|
||||
return update, nil
|
||||
@@ -2854,7 +2888,7 @@ func OpenAICommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus
|
||||
return nil, fmt.Errorf("openai error, invalid 'pterm' value %q: %v", ptermVal, err)
|
||||
}
|
||||
termOpts := convertTermOpts(pkTermOpts)
|
||||
cmd, err := makeDynCmd(ctx, GetCmdStr(pk), ids, pk.GetRawStr(), *termOpts)
|
||||
cmd, err := makeDynCmd(ctx, GetCmdStr(pk), ids, pk.GetRawStr(), *termOpts, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("openai error, cannot make dyn cmd")
|
||||
}
|
||||
@@ -2936,50 +2970,104 @@ func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.Upd
|
||||
if rstate.Archived {
|
||||
return nil, fmt.Errorf("/%s error: remote %q cannot switch to archived remote", GetCmdStr(pk), newRemote)
|
||||
}
|
||||
newMsh := remote.GetRemoteById(rptr.RemoteId)
|
||||
if newMsh == nil {
|
||||
return nil, fmt.Errorf("/%s error: remote %q not found (msh)", GetCmdStr(pk), newRemote)
|
||||
}
|
||||
if !newMsh.IsConnected() {
|
||||
err := newMsh.TryAutoConnect()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%q is disconnected, auto-connect failed: %w", rstate.GetBaseDisplayName(), err)
|
||||
}
|
||||
if !newMsh.IsConnected() {
|
||||
if newMsh.GetRemoteCopy().ConnectMode == sstore.ConnectModeManual {
|
||||
return nil, fmt.Errorf("%q is disconnected (must manually connect)", rstate.GetBaseDisplayName())
|
||||
}
|
||||
return nil, fmt.Errorf("%q is disconnected", rstate.GetBaseDisplayName())
|
||||
}
|
||||
}
|
||||
err = sstore.UpdateCurRemote(ctx, ids.ScreenId, *rptr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/%s error: cannot update curremote: %w", GetCmdStr(pk), err)
|
||||
}
|
||||
noHist := resolveBool(pk.Kwargs["nohist"], false)
|
||||
if noHist {
|
||||
screen, err := sstore.GetScreenById(ctx, ids.ScreenId)
|
||||
ri, err := sstore.GetRemoteStatePtr(ctx, ids.SessionId, ids.ScreenId, *rptr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/%s error looking up connection state: %w", GetCmdStr(pk), err)
|
||||
}
|
||||
if ri == nil {
|
||||
// ok, if ri is nil we need to do a reinit
|
||||
verbose := resolveBool(pk.Kwargs["verbose"], false)
|
||||
shellType, err := resolveShellType(pk.Kwargs["shell"], rstate.DefaultShellType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/%s error: cannot resolve screen for update: %w", GetCmdStr(pk), err)
|
||||
return nil, err
|
||||
}
|
||||
update := scbus.MakeUpdatePacket()
|
||||
update.AddUpdate(*screen, sstore.InteractiveUpdate(pk.Interactive))
|
||||
termOpts, err := GetUITermOpts(pk.UIContext.WinSize, DefaultPTERM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot make termopts: %w", err)
|
||||
}
|
||||
pkTermOpts := convertTermOpts(termOpts)
|
||||
cmd, err := makeDynCmd(ctx, "connect", ids, pk.GetRawStr(), *pkTermOpts, &makeDynCmdOpts{OverrideRPtr: rptr})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update, err := addLineForCmd(ctx, "connect", true, ids, cmd, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts := connectOptsType{
|
||||
Verbose: verbose,
|
||||
ShellType: shellType,
|
||||
SessionId: ids.SessionId,
|
||||
ScreenId: ids.ScreenId,
|
||||
RPtr: *rptr,
|
||||
}
|
||||
go doAsyncResetCommand(newMsh, opts, cmd)
|
||||
return update, nil
|
||||
} else {
|
||||
outputStr := fmt.Sprintf("reconnected to %s", GetFullRemoteDisplayName(rptr, rstate))
|
||||
cmd, err := makeStaticCmd(ctx, GetCmdStr(pk), 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, "/"+GetCmdStr(pk), false, ids, cmd, "", nil)
|
||||
if err != nil {
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.AddUpdate(sstore.InteractiveUpdate(pk.Interactive))
|
||||
return update, nil
|
||||
}
|
||||
outputStr := fmt.Sprintf("connected to %s", GetFullRemoteDisplayName(rptr, rstate))
|
||||
cmd, err := makeStaticCmd(ctx, GetCmdStr(pk), 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, "/"+GetCmdStr(pk), false, ids, cmd, "", nil)
|
||||
if err != nil {
|
||||
// TODO tricky error since the command was a success, but we can't show the output
|
||||
return nil, err
|
||||
}
|
||||
update.AddUpdate(sstore.InteractiveUpdate(pk.Interactive))
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func makeDynCmd(ctx context.Context, metaCmd string, ids resolvedIds, cmdStr string, termOpts sstore.TermOpts) (*sstore.CmdType, error) {
|
||||
type makeDynCmdOpts struct {
|
||||
OverrideRPtr *sstore.RemotePtrType
|
||||
}
|
||||
|
||||
func makeDynCmd(ctx context.Context, metaCmd string, ids resolvedIds, cmdStr string, termOpts sstore.TermOpts, opts *makeDynCmdOpts) (*sstore.CmdType, error) {
|
||||
var rptr scpacket.RemotePtrType
|
||||
if opts != nil && opts.OverrideRPtr != nil {
|
||||
rptr = *opts.OverrideRPtr
|
||||
} else if ids.Remote != nil {
|
||||
rptr = ids.Remote.RemotePtr
|
||||
} else {
|
||||
local := remote.GetLocalRemote()
|
||||
rptr = scpacket.RemotePtrType{RemoteId: local.RemoteId}
|
||||
}
|
||||
cmd := &sstore.CmdType{
|
||||
ScreenId: ids.ScreenId,
|
||||
LineId: scbase.GenWaveUUID(),
|
||||
CmdStr: cmdStr,
|
||||
RawCmdStr: cmdStr,
|
||||
Remote: ids.Remote.RemotePtr,
|
||||
Remote: rptr,
|
||||
TermOpts: termOpts,
|
||||
Status: sstore.CmdStatusRunning,
|
||||
RunOut: nil,
|
||||
}
|
||||
if ids.Remote.StatePtr != nil {
|
||||
if ids.Remote != nil && ids.Remote.StatePtr != nil {
|
||||
cmd.StatePtr = *ids.Remote.StatePtr
|
||||
}
|
||||
if ids.Remote.FeState != nil {
|
||||
if ids.Remote != nil && ids.Remote.FeState != nil {
|
||||
cmd.FeState = ids.Remote.FeState
|
||||
}
|
||||
err := sstore.CreateCmdPtyFile(ctx, cmd.ScreenId, cmd.LineId, cmd.TermOpts.MaxPtySize)
|
||||
@@ -3369,13 +3457,32 @@ func SessionOpenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
update, err := sstore.InsertSessionWithName(ctx, newName, activate)
|
||||
update, newSessionId, newScreenId, err := sstore.InsertSessionWithName(ctx, newName, activate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uiContextCopy := *pk.UIContext
|
||||
uiContextCopy.SessionId = newSessionId
|
||||
uiContextCopy.ScreenId = newScreenId
|
||||
crUpdate, err := doNewTabConnectLocal(ctx, newScreenId, &uiContextCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update.Merge(crUpdate)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func SessionEnsureOneCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scbus.UpdatePacket, error) {
|
||||
numSessions, err := sstore.GetSessionCount(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get number of sessions: %v", err)
|
||||
}
|
||||
if numSessions > 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return SessionOpenCommand(ctx, pk)
|
||||
}
|
||||
|
||||
func makeExternLink(urlStr string) string {
|
||||
return fmt.Sprintf(`https://extern?%s`, url.QueryEscape(urlStr))
|
||||
}
|
||||
@@ -3471,7 +3578,7 @@ func ScreenShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
if screen == nil {
|
||||
return nil, fmt.Errorf("screen not found")
|
||||
}
|
||||
statePtr, err := remote.ResolveCurrentScreenStatePtr(ctx, ids.SessionId, ids.ScreenId, ids.Remote.RemotePtr)
|
||||
statePtr, err := sstore.GetRemoteStatePtr(ctx, ids.SessionId, ids.ScreenId, ids.Remote.RemotePtr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot resolve current screen stateptr: %v", err)
|
||||
}
|
||||
@@ -3483,8 +3590,10 @@ func ScreenShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "tabicon", screen.ScreenOpts.TabIcon))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %d\n", "selectedline", screen.SelectedLine))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "curremote", GetFullRemoteDisplayName(&screen.CurRemote, &ids.Remote.RState)))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "stateptr-base", statePtr.BaseHash))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %v\n", "stateptr-diff", statePtr.DiffHashArr))
|
||||
if statePtr != nil {
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "stateptr-base", statePtr.BaseHash))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %v\n", "stateptr-diff", statePtr.DiffHashArr))
|
||||
}
|
||||
update := scbus.MakeUpdatePacket()
|
||||
update.AddUpdate(sstore.InfoMsgType{
|
||||
InfoTitle: "screen info",
|
||||
@@ -3682,21 +3791,17 @@ func RemoteResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
if !ids.Remote.MShell.IsConnected() {
|
||||
return nil, fmt.Errorf("cannot reinit, remote is not connected")
|
||||
}
|
||||
shellType := ids.Remote.ShellType
|
||||
if pk.Kwargs["shell"] != "" {
|
||||
shellArg := pk.Kwargs["shell"]
|
||||
if shellArg != packet.ShellType_bash && shellArg != packet.ShellType_zsh {
|
||||
return nil, fmt.Errorf("/reset invalid shell type %q", shellArg)
|
||||
}
|
||||
shellType = shellArg
|
||||
}
|
||||
verbose := resolveBool(pk.Kwargs["verbose"], false)
|
||||
shellType, err := resolveShellType(pk.Kwargs["shell"], ids.Remote.ShellType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
termOpts, err := GetUITermOpts(pk.UIContext.WinSize, DefaultPTERM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot make termopts: %w", err)
|
||||
}
|
||||
pkTermOpts := convertTermOpts(termOpts)
|
||||
cmd, err := makeDynCmd(ctx, "reset", ids, pk.GetRawStr(), *pkTermOpts)
|
||||
cmd, err := makeDynCmd(ctx, "reset", ids, pk.GetRawStr(), *pkTermOpts, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -3704,12 +3809,28 @@ func RemoteResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
go doResetCommand(ids, shellType, cmd, verbose)
|
||||
opts := connectOptsType{
|
||||
Verbose: verbose,
|
||||
ShellType: shellType,
|
||||
SessionId: ids.SessionId,
|
||||
ScreenId: ids.ScreenId,
|
||||
RPtr: ids.Remote.RemotePtr,
|
||||
}
|
||||
go doAsyncResetCommand(ids.Remote.MShell, opts, cmd)
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func doResetCommand(ids resolvedIds, shellType string, cmd *sstore.CmdType, verbose bool) {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), shellapi.ReInitTimeout)
|
||||
type connectOptsType struct {
|
||||
ShellType string // shell type to connect with
|
||||
Verbose bool // extra output (show state changes, sizes, etc.)
|
||||
SessionId string
|
||||
ScreenId string
|
||||
RPtr sstore.RemotePtrType
|
||||
}
|
||||
|
||||
// this does the asynchroneous part of the connection reset
|
||||
func doAsyncResetCommand(msh *remote.MShellProc, opts connectOptsType, cmd *sstore.CmdType) {
|
||||
ctx, cancelFn := context.WithCancel(context.Background())
|
||||
defer cancelFn()
|
||||
startTime := time.Now()
|
||||
var outputPos int64
|
||||
@@ -3725,28 +3846,30 @@ func doResetCommand(ids resolvedIds, shellType string, cmd *sstore.CmdType, verb
|
||||
dataFn := func(data []byte) {
|
||||
writeStringToPty(ctx, cmd, string(data), &outputPos)
|
||||
}
|
||||
origStatePtr := ids.Remote.MShell.GetDefaultStatePtr(shellType)
|
||||
ssPk, err := ids.Remote.MShell.ReInit(ctx, base.MakeCommandKey(cmd.ScreenId, cmd.LineId), shellType, dataFn, verbose)
|
||||
origStatePtr, _ := sstore.GetRemoteStatePtr(ctx, opts.SessionId, opts.ScreenId, opts.RPtr)
|
||||
ssPk, err := msh.ReInit(ctx, base.MakeCommandKey(cmd.ScreenId, cmd.LineId), opts.ShellType, dataFn, opts.Verbose)
|
||||
if err != nil {
|
||||
rtnErr = err
|
||||
return
|
||||
}
|
||||
if ssPk == nil || ssPk.State == nil {
|
||||
rtnErr = fmt.Errorf("invalid initpk received from remote (no remote state)")
|
||||
rtnErr = fmt.Errorf("no state received from connection (nil)")
|
||||
return
|
||||
}
|
||||
feState := sstore.FeStateFromShellState(ssPk.State)
|
||||
remoteInst, err := sstore.UpdateRemoteState(ctx, ids.SessionId, ids.ScreenId, ids.Remote.RemotePtr, feState, ssPk.State, nil)
|
||||
remoteInst, err := sstore.UpdateRemoteState(ctx, opts.SessionId, opts.ScreenId, opts.RPtr, feState, ssPk.State, nil)
|
||||
if err != nil {
|
||||
rtnErr = err
|
||||
return
|
||||
}
|
||||
newStatePtr := ids.Remote.MShell.GetDefaultStatePtr(shellType)
|
||||
if verbose && origStatePtr != nil && newStatePtr != nil {
|
||||
newStatePtr := sstore.ShellStatePtr{
|
||||
BaseHash: ssPk.State.GetHashVal(false),
|
||||
}
|
||||
if opts.Verbose && origStatePtr != nil {
|
||||
statePtrDiff := fmt.Sprintf("oldstate: %v, newstate: %v\r\n", origStatePtr.BaseHash, newStatePtr.BaseHash)
|
||||
writeStringToPty(ctx, cmd, statePtrDiff, &outputPos)
|
||||
origFullState, _ := sstore.GetFullState(ctx, *origStatePtr)
|
||||
newFullState, _ := sstore.GetFullState(ctx, *newStatePtr)
|
||||
newFullState, _ := sstore.GetFullState(ctx, newStatePtr)
|
||||
if origFullState != nil && newFullState != nil {
|
||||
var diffBuf bytes.Buffer
|
||||
rtnstate.DisplayStateUpdateDiff(&diffBuf, *origFullState, *newFullState)
|
||||
@@ -3756,7 +3879,7 @@ func doResetCommand(ids resolvedIds, shellType string, cmd *sstore.CmdType, verb
|
||||
}
|
||||
}
|
||||
update := scbus.MakeUpdatePacket()
|
||||
update.AddUpdate(sstore.MakeSessionUpdateForRemote(ids.SessionId, remoteInst))
|
||||
update.AddUpdate(sstore.MakeSessionUpdateForRemote(opts.SessionId, remoteInst))
|
||||
scbus.MainUpdateBus.DoUpdate(update)
|
||||
}
|
||||
|
||||
@@ -3765,10 +3888,13 @@ func ResetCwdCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (scb
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
statePtr, err := remote.ResolveCurrentScreenStatePtr(ctx, ids.SessionId, ids.ScreenId, ids.Remote.RemotePtr)
|
||||
statePtr, err := sstore.GetRemoteStatePtr(ctx, ids.SessionId, ids.ScreenId, ids.Remote.RemotePtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if statePtr == nil {
|
||||
return nil, fmt.Errorf("no shell state found, cannot reset cwd (run /reset)")
|
||||
}
|
||||
stateDiff, err := sstore.GetCurStateDiffFromPtr(ctx, statePtr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -41,7 +41,7 @@ type ResolvedRemote struct {
|
||||
MShell *remote.MShellProc
|
||||
RState remote.RemoteRuntimeState
|
||||
RemoteCopy *sstore.RemoteType
|
||||
ShellType string
|
||||
ShellType string // default remote shell preference
|
||||
StatePtr *sstore.ShellStatePtr
|
||||
FeState map[string]string
|
||||
}
|
||||
@@ -488,8 +488,8 @@ func ResolveRemoteFromPtr(ctx context.Context, rptr *sstore.RemotePtrType, sessi
|
||||
} else {
|
||||
if ri == nil {
|
||||
rtn.ShellType = msh.GetShellPref()
|
||||
rtn.StatePtr = msh.GetDefaultStatePtr(rtn.ShellType)
|
||||
rtn.FeState = msh.GetDefaultFeState(rtn.ShellType)
|
||||
rtn.StatePtr = nil
|
||||
rtn.FeState = nil
|
||||
} else {
|
||||
rtn.StatePtr = &sstore.ShellStatePtr{BaseHash: ri.StateBaseHash, DiffHashArr: ri.StateDiffHashArr}
|
||||
rtn.FeState = ri.FeState
|
||||
|
||||
@@ -314,7 +314,7 @@ func IsReturnStateCommand(cmdStr string) bool {
|
||||
func EvalBracketArgs(origCmdStr string) (map[string]string, string, error) {
|
||||
rtn := make(map[string]string)
|
||||
if strings.HasPrefix(origCmdStr, " ") {
|
||||
rtn["nohist"] = "1"
|
||||
rtn[KwArgNoHist] = "1"
|
||||
}
|
||||
cmdStr := strings.TrimSpace(origCmdStr)
|
||||
if !strings.HasPrefix(cmdStr, "[") {
|
||||
|
||||
@@ -214,38 +214,6 @@ func (msh *MShellProc) GetStatus() string {
|
||||
return msh.Status
|
||||
}
|
||||
|
||||
func (msh *MShellProc) GetDefaultState(shellType string) *packet.ShellState {
|
||||
_, state := msh.StateMap.GetCurrentState(shellType)
|
||||
return state
|
||||
}
|
||||
|
||||
func (msh *MShellProc) EnsureShellType(ctx context.Context, shellType string) error {
|
||||
if msh.StateMap.HasShell(shellType) {
|
||||
return nil
|
||||
}
|
||||
// try to reinit the shell
|
||||
_, err := msh.ReInit(ctx, base.CommandKey(""), shellType, nil, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error trying to initialize shell %q: %v", shellType, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msh *MShellProc) GetDefaultStatePtr(shellType string) *sstore.ShellStatePtr {
|
||||
msh.Lock.Lock()
|
||||
defer msh.Lock.Unlock()
|
||||
hash, _ := msh.StateMap.GetCurrentState(shellType)
|
||||
if hash == "" {
|
||||
return nil
|
||||
}
|
||||
return &sstore.ShellStatePtr{BaseHash: hash}
|
||||
}
|
||||
|
||||
func (msh *MShellProc) GetDefaultFeState(shellType string) map[string]string {
|
||||
state := msh.GetDefaultState(shellType)
|
||||
return sstore.FeStateFromShellState(state)
|
||||
}
|
||||
|
||||
func (msh *MShellProc) GetRemoteId() string {
|
||||
msh.Lock.Lock()
|
||||
defer msh.Lock.Unlock()
|
||||
@@ -489,6 +457,26 @@ func ResolveRemoteRef(remoteRef string) *RemoteRuntimeState {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SendSignalToCmd(ctx context.Context, cmd *sstore.CmdType, sig string) error {
|
||||
msh := GetRemoteById(cmd.Remote.RemoteId)
|
||||
if msh == nil {
|
||||
return fmt.Errorf("no connection found")
|
||||
}
|
||||
if !msh.IsConnected() {
|
||||
return fmt.Errorf("not connected")
|
||||
}
|
||||
cmdCk := base.MakeCommandKey(cmd.ScreenId, cmd.LineId)
|
||||
if !msh.IsCmdRunning(cmdCk) {
|
||||
// this could also return nil (depends on use case)
|
||||
// settled on coded error so we can check for this error
|
||||
return base.CodedErrorf(packet.EC_CmdNotRunning, "cmd not running")
|
||||
}
|
||||
sigPk := packet.MakeSpecialInputPacket()
|
||||
sigPk.CK = cmdCk
|
||||
sigPk.SigName = sig
|
||||
return msh.ServerProc.Input.SendPacket(sigPk)
|
||||
}
|
||||
|
||||
func unquoteDQBashString(str string) (string, bool) {
|
||||
if len(str) < 2 {
|
||||
return str, false
|
||||
@@ -588,6 +576,7 @@ func (msh *MShellProc) GetRemoteRuntimeState() RemoteRuntimeState {
|
||||
InstallStatus: msh.InstallStatus,
|
||||
NeedsMShellUpgrade: msh.NeedsMShellUpgrade,
|
||||
Local: msh.Remote.Local,
|
||||
IsSudo: msh.Remote.IsSudo(),
|
||||
NoInitPk: msh.ErrNoInitPk,
|
||||
AuthType: sstore.RemoteAuthTypeNone,
|
||||
ShellPref: msh.Remote.ShellPref,
|
||||
@@ -661,11 +650,6 @@ func (msh *MShellProc) GetRemoteRuntimeState() RemoteRuntimeState {
|
||||
vars["besthost"] = vars["remotehost"]
|
||||
vars["bestshorthost"] = vars["remoteshorthost"]
|
||||
}
|
||||
_, curState := msh.StateMap.GetCurrentState(shellPref)
|
||||
if curState != nil {
|
||||
state.DefaultFeState = sstore.FeStateFromShellState(curState)
|
||||
vars["cwd"] = curState.Cwd
|
||||
}
|
||||
if msh.Remote.Local && msh.Remote.IsSudo() {
|
||||
vars["bestuser"] = "sudo"
|
||||
} else if msh.Remote.IsSudo() {
|
||||
@@ -687,7 +671,6 @@ func (msh *MShellProc) GetRemoteRuntimeState() RemoteRuntimeState {
|
||||
varsCopy[key] = value
|
||||
}
|
||||
state.RemoteVars = varsCopy
|
||||
state.ActiveShells = msh.StateMap.GetShells()
|
||||
return state
|
||||
}
|
||||
|
||||
@@ -932,9 +915,9 @@ func (msh *MShellProc) writeToPtyBuffer_nolock(strFmt string, args ...interface{
|
||||
realStr = realStr + "\r\n"
|
||||
}
|
||||
if strings.HasPrefix(realStr, "*") {
|
||||
realStr = "\033[0m\033[31mprompt>\033[0m " + realStr[1:]
|
||||
realStr = "\033[0m\033[31mwave>\033[0m " + realStr[1:]
|
||||
} else {
|
||||
realStr = "\033[0m\033[32mprompt>\033[0m " + realStr
|
||||
realStr = "\033[0m\033[32mwave>\033[0m " + realStr
|
||||
}
|
||||
barr := msh.PtyBuffer.Bytes()
|
||||
if len(barr) > 0 && barr[len(barr)-1] != '\n' {
|
||||
@@ -1509,18 +1492,18 @@ func (msh *MShellProc) ReInit(ctx context.Context, ck base.CommandKey, shellType
|
||||
}
|
||||
|
||||
func makeShellInitOutputMsg(verbose bool, state *packet.ShellState, stats *packet.ShellStateStats, dur time.Duration, ptyMsg bool) string {
|
||||
waveStr := fmt.Sprintf("%swave>%s", utilfn.AnsiGreenColor(), utilfn.AnsiResetColor())
|
||||
if !verbose || ptyMsg {
|
||||
if ptyMsg {
|
||||
return fmt.Sprintf("initialized state shell:%s statehash:%s %dms\n", state.GetShellType(), state.GetHashVal(false), dur.Milliseconds())
|
||||
} else {
|
||||
return fmt.Sprintf("initialized connection state (shell:%s)\r\n", state.GetShellType())
|
||||
return fmt.Sprintf("%s initialized connection state (shell:%s)\r\n", waveStr, state.GetShellType())
|
||||
}
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("-----\r\n")
|
||||
buf.WriteString(fmt.Sprintf("initialized connection shell:%s statehash:%s %dms\r\n", state.GetShellType(), state.GetHashVal(false), dur.Milliseconds()))
|
||||
buf.WriteString(fmt.Sprintf("%s initialized connection shell:%s statehash:%s %dms\r\n", waveStr, state.GetShellType(), state.GetHashVal(false), dur.Milliseconds()))
|
||||
if stats != nil {
|
||||
buf.WriteString(fmt.Sprintf(" outsize:%s size:%s env:%d, vars:%d, aliases:%d, funcs:%d\r\n", scbase.NumFormatDec(stats.OutputSize), scbase.NumFormatDec(stats.StateSize), stats.EnvCount, stats.VarCount, stats.AliasCount, stats.FuncCount))
|
||||
buf.WriteString(fmt.Sprintf("%s outsize:%s size:%s env:%d, vars:%d, aliases:%d, funcs:%d\r\n", waveStr, scbase.NumFormatDec(stats.OutputSize), scbase.NumFormatDec(stats.StateSize), stats.EnvCount, stats.VarCount, stats.AliasCount, stats.FuncCount))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
@@ -1762,7 +1745,7 @@ func (msh *MShellProc) Launch(interactive bool) {
|
||||
msh.WriteToPtyBuffer("*disconnected exitcode=%d\n", exitCode)
|
||||
}()
|
||||
go msh.ProcessPackets()
|
||||
msh.initActiveShells()
|
||||
// msh.initActiveShells()
|
||||
go msh.NotifyRemoteUpdate()
|
||||
}
|
||||
|
||||
@@ -1780,7 +1763,7 @@ func (msh *MShellProc) initActiveShells() {
|
||||
wg.Add(1)
|
||||
go func(shellType string) {
|
||||
defer wg.Done()
|
||||
reinitCtx, cancelFn := context.WithTimeout(context.Background(), shellapi.ReInitTimeout)
|
||||
reinitCtx, cancelFn := context.WithTimeout(context.Background(), 12*time.Second)
|
||||
defer cancelFn()
|
||||
_, err = msh.ReInit(reinitCtx, base.CommandKey(""), shellType, nil, false)
|
||||
if err != nil {
|
||||
@@ -1894,25 +1877,6 @@ func (msh *MShellProc) removePendingStateCmd(screenId string, rptr sstore.Remote
|
||||
}
|
||||
}
|
||||
|
||||
func ResolveCurrentScreenStatePtr(ctx context.Context, sessionId string, screenId string, remotePtr sstore.RemotePtrType) (*sstore.ShellStatePtr, error) {
|
||||
statePtr, err := sstore.GetRemoteStatePtr(ctx, sessionId, screenId, remotePtr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get current connection stateptr: %w", err)
|
||||
}
|
||||
if statePtr == nil {
|
||||
msh := GetRemoteById(remotePtr.RemoteId)
|
||||
err := msh.EnsureShellType(ctx, msh.GetShellPref()) // make sure shellType is initialized
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
statePtr = msh.GetDefaultStatePtr(msh.GetShellPref())
|
||||
if statePtr == nil {
|
||||
return nil, fmt.Errorf("no valid default connection stateptr")
|
||||
}
|
||||
}
|
||||
return statePtr, nil
|
||||
}
|
||||
|
||||
type RunCommandOpts struct {
|
||||
SessionId string
|
||||
ScreenId string
|
||||
@@ -1990,10 +1954,13 @@ func RunCommand(ctx context.Context, rcOpts RunCommandOpts, runPacket *packet.Ru
|
||||
statePtr = rcOpts.StatePtr
|
||||
} else {
|
||||
var err error
|
||||
statePtr, err = ResolveCurrentScreenStatePtr(ctx, sessionId, screenId, remotePtr)
|
||||
statePtr, err = sstore.GetRemoteStatePtr(ctx, sessionId, screenId, remotePtr)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("cannot run command: %w", err)
|
||||
}
|
||||
if statePtr == nil {
|
||||
return nil, nil, fmt.Errorf("cannot run command: no valid shell state found")
|
||||
}
|
||||
}
|
||||
currentState, err := sstore.GetFullState(ctx, *statePtr)
|
||||
if err != nil || currentState == nil {
|
||||
@@ -2002,10 +1969,6 @@ func RunCommand(ctx context.Context, rcOpts RunCommandOpts, runPacket *packet.Ru
|
||||
runPacket.State = addScVarsToState(currentState)
|
||||
runPacket.StateComplete = true
|
||||
runPacket.ShellType = currentState.GetShellType()
|
||||
err = msh.EnsureShellType(ctx, runPacket.ShellType) // make sure shellType is initialized
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// start cmdwait. must be started before sending the run packet
|
||||
// this ensures that we don't process output, or cmddone packets until we set up the line, cmd, and ptyout file
|
||||
@@ -2144,7 +2107,7 @@ func (msh *MShellProc) HandleFeInput(inputPk *scpacket.FeInputPacketType) error
|
||||
msh.Lock.Unlock()
|
||||
if sink == nil {
|
||||
// no sink and no running command
|
||||
return fmt.Errorf("cannot send input, cmd is not running")
|
||||
return fmt.Errorf("cannot send input, cmd is not running (%s)", inputPk.CK)
|
||||
}
|
||||
return sink.HandleInput(inputPk)
|
||||
}
|
||||
@@ -2461,7 +2424,7 @@ func (msh *MShellProc) processSinglePacket(pk packet.PacketType) {
|
||||
msh.WriteToPtyBuffer("stderr> [remote %s] %s\n", msh.GetRemoteName(), rawPk.Data)
|
||||
return
|
||||
}
|
||||
msh.WriteToPtyBuffer("MSH> [remote %s] unhandled packet %s\n", msh.GetRemoteName(), packet.AsString(pk))
|
||||
msh.WriteToPtyBuffer("*[remote %s] unhandled packet %s\n", msh.GetRemoteName(), packet.AsString(pk))
|
||||
}
|
||||
|
||||
func (msh *MShellProc) ProcessPackets() {
|
||||
|
||||
@@ -5,6 +5,7 @@ package scbus
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
||||
@@ -96,6 +97,16 @@ func (upk *ModelUpdatePacketType) AddUpdate(items ...ModelUpdateItem) {
|
||||
*(upk.Data) = append(*(upk.Data), items...)
|
||||
}
|
||||
|
||||
// adds the items from p2 to the update (p2 must be ModelUpdatePacketType)
|
||||
func (upk *ModelUpdatePacketType) Merge(p2Arg UpdatePacket) error {
|
||||
p2, ok := p2Arg.(*ModelUpdatePacketType)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot merge ModelUpdatePacketType with %T", p2Arg)
|
||||
}
|
||||
*(upk.Data) = append(*(upk.Data), *(p2.Data)...)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a new model update packet
|
||||
func MakeUpdatePacket() *ModelUpdatePacketType {
|
||||
return &ModelUpdatePacketType{
|
||||
|
||||
@@ -106,6 +106,9 @@ func (pk *FeCommandPacketType) GetRawStr() string {
|
||||
}
|
||||
var args []string
|
||||
for k, v := range pk.Kwargs {
|
||||
if k == "nohist" {
|
||||
continue
|
||||
}
|
||||
argStr := fmt.Sprintf("%s=%s", shellescape.Quote(k), shellescape.Quote(v))
|
||||
args = append(args, argStr)
|
||||
}
|
||||
|
||||
@@ -386,9 +386,9 @@ func GetSessionByName(ctx context.Context, name string) (*SessionType, error) {
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// returns sessionId
|
||||
// returns (update, newSessionId, newScreenId, error)
|
||||
// if sessionName == "", it will be generated
|
||||
func InsertSessionWithName(ctx context.Context, sessionName string, activate bool) (*scbus.ModelUpdatePacketType, error) {
|
||||
func InsertSessionWithName(ctx context.Context, sessionName string, activate bool) (*scbus.ModelUpdatePacketType, string, string, error) {
|
||||
var newScreen *ScreenType
|
||||
newSessionId := scbase.GenWaveUUID()
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
@@ -414,11 +414,11 @@ func InsertSessionWithName(ctx context.Context, sessionName string, activate boo
|
||||
return nil
|
||||
})
|
||||
if txErr != nil {
|
||||
return nil, txErr
|
||||
return nil, "", "", txErr
|
||||
}
|
||||
session, err := GetSessionById(ctx, newSessionId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, "", "", err
|
||||
}
|
||||
update := scbus.MakeUpdatePacket()
|
||||
update.AddUpdate(*session)
|
||||
@@ -426,7 +426,7 @@ func InsertSessionWithName(ctx context.Context, sessionName string, activate boo
|
||||
if activate {
|
||||
update.AddUpdate(ActiveSessionIdUpdate(newSessionId))
|
||||
}
|
||||
return update, nil
|
||||
return update, newSessionId, newScreen.ScreenId, nil
|
||||
}
|
||||
|
||||
func SetActiveSessionId(ctx context.Context, sessionId string) error {
|
||||
@@ -569,6 +569,9 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
|
||||
query = `UPDATE session SET activescreenid = ? WHERE sessionid = ?`
|
||||
tx.Exec(query, newScreenId, sessionId)
|
||||
}
|
||||
if opts.RtnScreenId != nil {
|
||||
*opts.RtnScreenId = newScreenId
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if txErr != nil {
|
||||
@@ -1044,11 +1047,6 @@ func DeleteScreen(ctx context.Context, screenId string, sessionDel bool, update
|
||||
if sessionId == "" {
|
||||
return fmt.Errorf("cannot delete screen (no sessionid)")
|
||||
}
|
||||
query = `SELECT count(*) FROM screen WHERE sessionid = ? AND NOT archived`
|
||||
numScreens := tx.GetInt(query, sessionId)
|
||||
if numScreens <= 1 {
|
||||
return fmt.Errorf("cannot delete the last screen in a session")
|
||||
}
|
||||
isActive = tx.Exists(`SELECT sessionid FROM session WHERE sessionid = ? AND activescreenid = ?`, sessionId, screenId)
|
||||
if isActive {
|
||||
screenIds := tx.SelectStrings(`SELECT screenid FROM screen WHERE sessionid = ? AND NOT archived ORDER BY screenidx`, sessionId)
|
||||
|
||||
@@ -375,6 +375,7 @@ type ScreenCreateOpts struct {
|
||||
CopyRemote bool
|
||||
CopyCwd bool
|
||||
CopyEnv bool
|
||||
RtnScreenId *string
|
||||
}
|
||||
|
||||
func (sco ScreenCreateOpts) HasCopy() bool {
|
||||
@@ -760,7 +761,6 @@ type RemoteRuntimeState struct {
|
||||
RemoteAlias string `json:"remotealias,omitempty"`
|
||||
RemoteCanonicalName string `json:"remotecanonicalname"`
|
||||
RemoteVars map[string]string `json:"remotevars"`
|
||||
DefaultFeState map[string]string `json:"defaultfestate"`
|
||||
Status string `json:"status"`
|
||||
ConnectTimeout int `json:"connecttimeout,omitempty"`
|
||||
CountdownActive bool `json:"countdownactive"`
|
||||
@@ -779,9 +779,9 @@ type RemoteRuntimeState struct {
|
||||
MShellVersion string `json:"mshellversion"`
|
||||
WaitingForPassword bool `json:"waitingforpassword,omitempty"`
|
||||
Local bool `json:"local,omitempty"`
|
||||
IsSudo bool `json:"issudo,omitempty"`
|
||||
RemoteOpts *RemoteOptsType `json:"remoteopts,omitempty"`
|
||||
CanComplete bool `json:"cancomplete,omitempty"`
|
||||
ActiveShells []string `json:"activeshells,omitempty"`
|
||||
ShellPref string `json:"shellpref,omitempty"`
|
||||
DefaultShellType string `json:"defaultshelltype,omitempty"`
|
||||
}
|
||||
@@ -1127,21 +1127,6 @@ func EnsureLocalRemote(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func EnsureOneSession(ctx context.Context) error {
|
||||
numSessions, err := GetSessionCount(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if numSessions > 0 {
|
||||
return nil
|
||||
}
|
||||
_, err = InsertSessionWithName(ctx, DefaultSessionName, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createClientData(tx *TxWrap) error {
|
||||
curve := elliptic.P384()
|
||||
pkey, err := ecdsa.GenerateKey(curve, rand.Reader)
|
||||
|
||||
Reference in New Issue
Block a user