refactor(interactive): remove sync writer now that prompts are upfront

This commit is contained in:
Valentin Maerten
2025-12-14 16:14:52 +01:00
parent bd166ff271
commit feb97c061c
5 changed files with 5 additions and 63 deletions

View File

@@ -54,11 +54,9 @@ type (
Failfast bool
// I/O
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
rawStdout io.Writer // unwrapped stdout for prompts
rawStderr io.Writer // unwrapped stderr for prompts
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
// Internal
Taskfile *ast.Taskfile
@@ -73,7 +71,6 @@ type (
fuzzyModel *fuzzy.Model
fuzzyModelOnce sync.Once
promptMutex sync.Mutex
promptedVars *ast.Vars // vars collected via interactive prompts
concurrencySemaphore chan struct{}
taskCallCount map[string]*int32

View File

@@ -1,28 +0,0 @@
package output
import (
"io"
"sync"
)
// SyncWriter wraps an io.Writer with a mutex to synchronize writes.
// This is used to prevent output from interleaving with interactive prompts.
type SyncWriter struct {
w io.Writer
mu *sync.Mutex
}
// NewSyncWriter creates a new SyncWriter that uses the provided mutex.
func NewSyncWriter(w io.Writer, mu *sync.Mutex) *SyncWriter {
return &SyncWriter{
w: w,
mu: mu,
}
}
// Write implements io.Writer with synchronized access.
func (sw *SyncWriter) Write(p []byte) (n int, err error) {
sw.mu.Lock()
defer sw.mu.Unlock()
return sw.w.Write(p)
}

View File

@@ -3,7 +3,6 @@ package prompt
import (
"fmt"
"io"
"os"
"strings"
"github.com/charmbracelet/bubbles/textinput"
@@ -31,15 +30,6 @@ type Prompter struct {
Stderr io.Writer
}
// New creates a new Prompter with default stdin/stdout/stderr
func New() *Prompter {
return &Prompter{
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
}
}
// Text prompts the user for a text value
func (p *Prompter) Text(varName string) (string, error) {
m := newTextModel(varName)

View File

@@ -91,15 +91,10 @@ func (e *Executor) promptForAllVars(vars []*ast.VarsWithValidation) (*ast.Vars,
return nil, nil
}
// Lock to prevent any output during prompting
e.promptMutex.Lock()
defer e.promptMutex.Unlock()
// Use raw stderr for prompts to avoid deadlock with SyncWriter
prompter := &prompt.Prompter{
Stdin: e.Stdin,
Stdout: e.rawStdout,
Stderr: e.rawStderr,
Stdout: e.Stdout,
Stderr: e.Stderr,
}
result := ast.NewVars()

View File

@@ -19,7 +19,6 @@ import (
"github.com/go-task/task/v3/internal/fsext"
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/internal/output"
"github.com/go-task/task/v3/internal/term"
"github.com/go-task/task/v3/internal/version"
"github.com/go-task/task/v3/taskfile"
"github.com/go-task/task/v3/taskfile/ast"
@@ -180,17 +179,6 @@ func (e *Executor) setupStdFiles() {
if e.Stderr == nil {
e.Stderr = os.Stderr
}
// Keep raw references for interactive prompts
e.rawStdout = e.Stdout
e.rawStderr = e.Stderr
// Wrap with synchronized writers when interactive mode is enabled AND we have a TTY
// to prevent output from interleaving with prompts
if e.Interactive && !e.NoTTY && (e.AssumeTerm || term.IsTerminal()) {
e.Stdout = output.NewSyncWriter(e.Stdout, &e.promptMutex)
e.Stderr = output.NewSyncWriter(e.Stderr, &e.promptMutex)
}
}
func (e *Executor) setupLogger() {