@@ -24,6 +24,12 @@ import (
24
24
"cdr.dev/coder-cli/pkg/clog"
25
25
)
26
26
27
+ var (
28
+ showInteractiveOutput = terminal .IsTerminal (int (os .Stdout .Fd ()))
29
+ outputFd = os .Stdout .Fd ()
30
+ inputFd = os .Stdin .Fd ()
31
+ )
32
+
27
33
func getEnvsForCompletion (user string ) func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
28
34
return func (cmd * cobra.Command , args []string , toComplete string ) ([]string , cobra.ShellCompDirective ) {
29
35
ctx := cmd .Context ()
@@ -146,15 +152,14 @@ func shell(cmd *cobra.Command, cmdArgs []string) error {
146
152
}
147
153
148
154
// TODO: Verify this is the correct behavior
149
- isInteractive := terminal .IsTerminal (int (os .Stdout .Fd ()))
150
- if isInteractive { // checkAndRebuildEnvironment requires an interactive shell
155
+ if showInteractiveOutput { // checkAndRebuildEnvironment requires an interactive shell
151
156
// Checks & Rebuilds the environment if needed.
152
157
if err := checkAndRebuildEnvironment (ctx , client , env ); err != nil {
153
158
return err
154
159
}
155
160
}
156
161
157
- if err := runCommand (ctx , client , env , command , args ); err != nil {
162
+ if err := runCommand (cmd , client , env , command , args ); err != nil {
158
163
if exitErr , ok := err .(wsep.ExitError ); ok {
159
164
os .Exit (exitErr .Code )
160
165
}
@@ -309,26 +314,23 @@ func sendResizeEvents(ctx context.Context, termFD uintptr, process wsep.Process)
309
314
}
310
315
}
311
316
312
- func runCommand (ctx context.Context , client coder.Client , env * coder.Environment , command string , args []string ) error {
313
- termFD := os .Stdout .Fd ()
314
-
315
- isInteractive := terminal .IsTerminal (int (termFD ))
316
- if isInteractive {
317
+ func runCommand (cmd * cobra.Command , client coder.Client , env * coder.Environment , command string , args []string ) error {
318
+ if showInteractiveOutput {
317
319
// If the client has a tty, take over it by setting the raw mode.
318
320
// This allows for all input to be directly forwarded to the remote process,
319
321
// otherwise, the local terminal would buffer input, interpret special keys, etc.
320
- stdinState , err := xterminal .MakeRaw (os . Stdin . Fd () )
322
+ stdinState , err := xterminal .MakeRaw (inputFd )
321
323
if err != nil {
322
324
return err
323
325
}
324
326
defer func () {
325
327
// Best effort. If this fails it will result in a broken terminal,
326
328
// but there is nothing we can do about it.
327
- _ = xterminal .Restore (os . Stdin . Fd () , stdinState )
329
+ _ = xterminal .Restore (inputFd , stdinState )
328
330
}()
329
331
}
330
332
331
- ctx , cancel := context .WithCancel (ctx )
333
+ ctx , cancel := context .WithCancel (cmd . Context () )
332
334
defer cancel ()
333
335
334
336
conn , err := coderutil .DialEnvWsep (ctx , client , env )
@@ -338,7 +340,7 @@ func runCommand(ctx context.Context, client coder.Client, env *coder.Environment
338
340
go heartbeat (ctx , conn , 15 * time .Second )
339
341
340
342
var cmdEnv []string
341
- if isInteractive {
343
+ if showInteractiveOutput {
342
344
term := os .Getenv ("TERM" )
343
345
if term == "" {
344
346
term = "xterm"
@@ -350,7 +352,7 @@ func runCommand(ctx context.Context, client coder.Client, env *coder.Environment
350
352
process , err := execer .Start (ctx , wsep.Command {
351
353
Command : command ,
352
354
Args : args ,
353
- TTY : isInteractive ,
355
+ TTY : showInteractiveOutput ,
354
356
Stdin : true ,
355
357
Env : cmdEnv ,
356
358
})
@@ -363,8 +365,8 @@ func runCommand(ctx context.Context, client coder.Client, env *coder.Environment
363
365
}
364
366
365
367
// Now that the remote process successfully started, if we have a tty, start the resize event watcher.
366
- if isInteractive {
367
- go sendResizeEvents (ctx , termFD , process )
368
+ if showInteractiveOutput {
369
+ go sendResizeEvents (ctx , outputFd , process )
368
370
}
369
371
370
372
go func () {
@@ -373,17 +375,17 @@ func runCommand(ctx context.Context, client coder.Client, env *coder.Environment
373
375
374
376
ap := activity .NewPusher (client , env .ID , sshActivityName )
375
377
wr := ap .Writer (stdin )
376
- if _ , err := io .Copy (wr , os . Stdin ); err != nil {
378
+ if _ , err := io .Copy (wr , cmd . InOrStdin () ); err != nil {
377
379
cancel ()
378
380
}
379
381
}()
380
382
go func () {
381
- if _ , err := io .Copy (os . Stdout , process .Stdout ()); err != nil {
383
+ if _ , err := io .Copy (cmd . OutOrStdout () , process .Stdout ()); err != nil {
382
384
cancel ()
383
385
}
384
386
}()
385
387
go func () {
386
- if _ , err := io .Copy (os . Stderr , process .Stderr ()); err != nil {
388
+ if _ , err := io .Copy (cmd . ErrOrStderr () , process .Stderr ()); err != nil {
387
389
cancel ()
388
390
}
389
391
}()
0 commit comments