diff --git a/pkg/backend/display/jsonmessage.go b/pkg/backend/display/jsonmessage.go index 09f80480976b..d917edcdea51 100644 --- a/pkg/backend/display/jsonmessage.go +++ b/pkg/backend/display/jsonmessage.go @@ -23,7 +23,6 @@ import ( "os" "unicode/utf8" - gotty "github.com/ijc/Gotty" "golang.org/x/crypto/ssh/terminal" "github.com/pulumi/pulumi/pkg/v3/engine" @@ -147,10 +146,30 @@ type messageRenderer struct { printedProgressCache map[string]Progress } -func newMessageRenderer(stdout io.Writer, op string, opts Options) progressRenderer { +func newInteractiveMessageRenderer(stdout io.Writer, opts Options, + terminalWidth, terminalHeight int, termInfo termInfo) progressRenderer { + + progressOutput, closed := make(chan Progress), make(chan bool) + go func() { + ShowProgressOutput(progressOutput, stdout, termInfo) + close(closed) + }() + + return &messageRenderer{ + opts: opts, + isTerminal: true, + terminalWidth: terminalWidth, + terminalHeight: terminalHeight, + progressOutput: progressOutput, + closed: closed, + printedProgressCache: make(map[string]Progress), + } +} + +func newNonInteractiveRenderer(stdout io.Writer, op string, opts Options) progressRenderer { progressOutput, closed := make(chan Progress), make(chan bool) go func() { - ShowProgressOutput(progressOutput, stdout, false) + ShowProgressOutput(progressOutput, stdout, nil) close(closed) }() @@ -366,25 +385,11 @@ func (r *messageRenderer) updateTerminalDimensions() { // ShowProgressOutput displays a progress stream from `in` to `out`, `isTerminal` describes if // `out` is a terminal. If this is the case, it will print `\n` at the end of each line and move the // cursor while displaying. -func ShowProgressOutput(in <-chan Progress, out io.Writer, isTerminal bool) { +func ShowProgressOutput(in <-chan Progress, out io.Writer, info termInfo) { var ( ids = make(map[string]int) ) - var info termInfo - - if isTerminal { - term := os.Getenv("TERM") - if term == "" { - term = "vt102" - } - - var err error - if info, err = gotty.OpenTermInfo(term); err != nil { - info = &noTermInfo{} - } - } - for jm := range in { diff := 0 diff --git a/pkg/backend/display/progress.go b/pkg/backend/display/progress.go index c3f452e7cb9d..580025ddb614 100644 --- a/pkg/backend/display/progress.go +++ b/pkg/backend/display/progress.go @@ -234,10 +234,10 @@ func ShowProgressEvents(op string, action apitype.UpdateKind, stack tokens.Name, } isTerminal := true - renderer, err := newTreeRenderer(stdin, stdout, opts) + renderer, err := newInteractiveRenderer(stdin, stdout, opts) if err != nil { fmt.Println(err) - isTerminal, renderer = false, newMessageRenderer(stdout, op, opts) + isTerminal, renderer = false, newNonInteractiveRenderer(stdout, op, opts) } display := &ProgressDisplay{ @@ -360,7 +360,6 @@ func (display *ProgressDisplay) generateTreeNodes() []*treeNode { } func (display *ProgressDisplay) addIndentations(treeNodes []*treeNode, isRoot bool, indentation string) { - childIndentation := indentation + "│ " lastChildIndentation := indentation + " " diff --git a/pkg/backend/display/tree.go b/pkg/backend/display/tree.go index eb81b91fd02b..b78ca88272a4 100644 --- a/pkg/backend/display/tree.go +++ b/pkg/backend/display/tree.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "os" + "runtime" "strings" "sync" "time" @@ -67,7 +68,7 @@ type fileLike interface { Fd() uintptr } -func newTreeRenderer(in io.Reader, out io.Writer, opts Options) (progressRenderer, error) { +func newInteractiveRenderer(in io.Reader, out io.Writer, opts Options) (progressRenderer, error) { if !opts.IsInteractive { return nil, fmt.Errorf("the tree display can only be used in interactive mode") } @@ -78,11 +79,6 @@ func newTreeRenderer(in io.Reader, out io.Writer, opts Options) (progressRendere } outFD := int(outFile.Fd()) - inFile, err := cancelreader.NewReader(in) - if err != nil { - return nil, fmt.Errorf("preparing stdin: %w", err) - } - width, height, err := terminal.GetSize(outFD) if err != nil { return nil, fmt.Errorf("getting terminal dimensions: %w", err) @@ -100,6 +96,17 @@ func newTreeRenderer(in io.Reader, out io.Writer, opts Options) (progressRendere info = &noTermInfo{} } + // Something about the tree renderer--possibly the raw terminal--does not yet play well with Windows, so for now + // we fall back to the legacy renderer on that platform. + if runtime.GOOS == "windows" { + return newInteractiveMessageRenderer(out, opts, width, height, info), nil + } + + inFile, err := cancelreader.NewReader(in) + if err != nil { + return nil, fmt.Errorf("preparing stdin: %w", err) + } + state, err := terminal.MakeRaw(outFD) if err != nil { return nil, fmt.Errorf("enabling raw terminal: %w", err)