@@ -236,41 +236,31 @@ func newUpCmd(opts *Options) *cobra.Command {
236236 }
237237 }
238238 if enableTmux && sshMode == "embedded" {
239- spinner := newTransientStatus (cmd .OutOrStdout (), "Checking tmux in dev container" )
240- if ! spinner .enabled {
241- ui .stepRun ("tmux" , "checking dev container" )
242- }
239+ ui .stepRun ("tmux" , "checking dev container" )
243240 status , installer , err := detectEmbeddedTmux (cmd .Context (), k , ns , pod )
244241 if err != nil {
245- spinner .stop ()
246242 ui .warnf ("failed to check tmux in dev container: %v" , err )
247243 } else if status == "install" {
248- if spinner .enabled {
249- spinner .update (fmt .Sprintf ("Installing tmux via %s" , installer ))
250- } else {
251- ui .stepRun ("tmux" , fmt .Sprintf ("installing via %s" , installer ))
252- }
253- installed , detail , err := installEmbeddedTmux (cmd .Context (), k , ns , pod , installer , func (phase string ) {
254- if spinner .enabled {
255- spinner .update (strings .TrimSpace (phase ))
256- return
257- }
244+ ui .stepRun ("tmux" , fmt .Sprintf ("installing via %s" , installer ))
245+ _ , detail , err := installEmbeddedTmux (cmd .Context (), k , ns , pod , installer , func (phase string ) {
258246 if strings .TrimSpace (phase ) != "" {
259247 ui .stepRun ("tmux" , phase )
260248 }
261249 })
262- spinner .stop ()
263250 if err != nil {
264- ui .warnf ("failed to install tmux in dev container: %v" , err )
265- } else if installed {
251+ if recoveredDetail , ok := embeddedTmuxDetailIfReady (cmd .Context (), k , ns , pod ); ok {
252+ ui .stepDone ("tmux" , recoveredDetail )
253+ } else {
254+ ui .warnf ("tmux not ready in dev container: %v" , err )
255+ }
256+ } else if strings .TrimSpace (detail ) != "" {
266257 ui .stepDone ("tmux" , detail )
267258 }
268259 } else {
269- spinner .stop ()
270260 _ , detail , err := interpretTmuxStatus (status , installer , "" )
271261 if err != nil {
272- ui .warnf ("failed to prepare tmux in dev container: %v" , err )
273- } else {
262+ ui .warnf ("tmux not ready in dev container: %v" , err )
263+ } else if strings . TrimSpace ( detail ) != "" {
274264 ui .stepDone ("tmux" , detail )
275265 }
276266 }
@@ -475,7 +465,15 @@ func installEmbeddedTmux(ctx context.Context, k devShellExecutor, namespace, pod
475465 }
476466 s , inst , rawLine := parseTmuxStatus (raw .String ())
477467 if s == "" {
478- return false , "" , fmt .Errorf ("unexpected tmux prepare result %q" , strings .TrimSpace (raw .String ()))
468+ detectStatus , detectInstaller , detectErr := detectEmbeddedTmux (ctx , k , namespace , pod )
469+ if detectErr == nil {
470+ return interpretTmuxStatus (detectStatus , detectInstaller , raw .String ())
471+ }
472+ trimmed := strings .TrimSpace (raw .String ())
473+ if trimmed == "" {
474+ return false , "" , fmt .Errorf ("unexpected tmux prepare result with no status marker; inspect %s in the dev container" , embeddedTmuxLogPath )
475+ }
476+ return false , "" , fmt .Errorf ("unexpected tmux prepare result %q; inspect %s in the dev container" , trimmed , embeddedTmuxLogPath )
479477 }
480478 inst = strings .TrimSpace (inst )
481479 return interpretTmuxStatus (s , inst , rawLine )
@@ -517,6 +515,18 @@ func parseTmuxStatus(raw string) (status, installer, line string) {
517515 return status , installer , line
518516}
519517
518+ func embeddedTmuxDetailIfReady (ctx context.Context , k devShellExecutor , namespace , pod string ) (string , bool ) {
519+ status , installer , err := detectEmbeddedTmux (ctx , k , namespace , pod )
520+ if err != nil {
521+ return "" , false
522+ }
523+ _ , detail , err := interpretTmuxStatus (status , installer , "" )
524+ if err != nil || strings .TrimSpace (detail ) == "" {
525+ return "" , false
526+ }
527+ return detail , true
528+ }
529+
520530func warnIfConfigNewerThanSession (opts * Options , k * kube.Client , namespace , sessionName , podName string , errOut io.Writer ) error {
521531 cfgPath , err := config .ResolvePath (opts .ConfigPath )
522532 if err != nil {
@@ -539,20 +549,45 @@ func warnIfConfigNewerThanSession(opts *Options, k *kube.Client, namespace, sess
539549}
540550
541551type upUI struct {
542- out io.Writer
543- errOut io.Writer
544- warnings []string
552+ out io.Writer
553+ errOut io.Writer
554+ warnings []string
555+ interactive bool
556+ activeStep string
557+ active * transientStatus
545558}
546559
547560func newUpUI (out , errOut io.Writer ) * upUI {
548- return & upUI {out : out , errOut : errOut }
561+ return & upUI {
562+ out : out ,
563+ errOut : errOut ,
564+ interactive : isTerminalWriter (out ),
565+ }
549566}
550567
551568func (u * upUI ) section (name string ) {
569+ u .stopActive ()
552570 fmt .Fprintf (u .out , "\n == %s ==\n " , name )
553571}
554572
555573func (u * upUI ) stepRun (step , detail string ) {
574+ if u .interactive {
575+ message := u .stepMessage (step , detail )
576+ if u .active != nil && u .active .enabled {
577+ if u .activeStep == step {
578+ u .active .update (message )
579+ return
580+ }
581+ u .stopActive ()
582+ }
583+ u .activeStep = step
584+ u .active = newTransientStatusWithMode (u .out , message , true )
585+ if u .active .enabled {
586+ return
587+ }
588+ u .active = nil
589+ u .activeStep = ""
590+ }
556591 if detail == "" {
557592 fmt .Fprintf (u .out , "… %s\n " , step )
558593 return
@@ -561,13 +596,31 @@ func (u *upUI) stepRun(step, detail string) {
561596}
562597
563598func (u * upUI ) stepDone (step , detail string ) {
599+ if u .activeStep == step {
600+ u .stopActive ()
601+ }
564602 if detail == "" {
565603 fmt .Fprintf (u .out , "✔ %s\n " , step )
566604 return
567605 }
568606 fmt .Fprintf (u .out , "✔ %s: %s\n " , step , detail )
569607}
570608
609+ func (u * upUI ) stepMessage (step , detail string ) string {
610+ if strings .TrimSpace (detail ) == "" {
611+ return step
612+ }
613+ return step + ": " + detail
614+ }
615+
616+ func (u * upUI ) stopActive () {
617+ if u .active != nil {
618+ u .active .stop ()
619+ u .active = nil
620+ }
621+ u .activeStep = ""
622+ }
623+
571624func (u * upUI ) warnf (format string , args ... any ) {
572625 msg := strings .TrimSpace (fmt .Sprintf (format , args ... ))
573626 if msg == "" {
@@ -577,6 +630,7 @@ func (u *upUI) warnf(format string, args ...any) {
577630}
578631
579632func (u * upUI ) printWarnings () {
633+ u .stopActive ()
580634 if len (u .warnings ) == 0 {
581635 return
582636 }
@@ -591,6 +645,7 @@ func (u *upUI) warnWriter() io.Writer {
591645}
592646
593647func (u * upUI ) printReadyCard (sessionName , namespace , pod , sshSummary , syncSummary string , ports []config.PortMapping , syncPairs []syncengine.Pair , syncModeSymbol string ) {
648+ u .stopActive ()
594649 fmt .Fprintln (u .out , "\n == Ready ==" )
595650 fmt .Fprintf (u .out , "session: %s\n " , sessionName )
596651 fmt .Fprintf (u .out , "namespace: %s\n " , namespace )
0 commit comments