mirror of
https://github.com/go-task/task.git
synced 2025-12-16 11:47:44 +01:00
refactor(interactive): simplify prompting functions and naming
This commit is contained in:
@@ -70,7 +70,7 @@ type (
|
||||
fuzzyModel *fuzzy.Model
|
||||
fuzzyModelOnce sync.Once
|
||||
|
||||
promptedVars *ast.Vars // vars collected via interactive prompts
|
||||
promptedVars *ast.Vars // vars collected via interactive prompts
|
||||
concurrencySemaphore chan struct{}
|
||||
taskCallCount map[string]*int32
|
||||
mkdirMutexMap map[string]*sync.Mutex
|
||||
|
||||
59
requires.go
59
requires.go
@@ -9,7 +9,20 @@ import (
|
||||
"github.com/go-task/task/v3/taskfile/ast"
|
||||
)
|
||||
|
||||
func (e *Executor) collectAllRequiredVars(calls []*Call) ([]*ast.VarsWithValidation, error) {
|
||||
// promptDepsVars traverses the dependency tree, collects all missing required
|
||||
// variables, and prompts for them upfront. This is used for deps which execute
|
||||
// in parallel, so all prompts must happen before execution to avoid interleaving.
|
||||
// Prompted values are stored in e.promptedVars for injection into task calls.
|
||||
func (e *Executor) promptDepsVars(calls []*Call) error {
|
||||
if !e.Interactive {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !e.AssumeTerm && !term.IsTerminal() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Collect all missing vars from the dependency tree
|
||||
visited := make(map[string]bool)
|
||||
varsMap := make(map[string]*ast.VarsWithValidation)
|
||||
|
||||
@@ -52,36 +65,24 @@ func (e *Executor) collectAllRequiredVars(calls []*Call) ([]*ast.VarsWithValidat
|
||||
|
||||
for _, call := range calls {
|
||||
if err := collect(call); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
result := make([]*ast.VarsWithValidation, 0, len(varsMap))
|
||||
for _, v := range varsMap {
|
||||
result = append(result, v)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (e *Executor) promptForAllVars(vars []*ast.VarsWithValidation) (*ast.Vars, error) {
|
||||
if len(vars) == 0 || !e.Interactive {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if !e.AssumeTerm && !term.IsTerminal() {
|
||||
return nil, nil
|
||||
if len(varsMap) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Prompt for all collected vars
|
||||
prompter := &prompt.Prompter{
|
||||
Stdin: e.Stdin,
|
||||
Stdout: e.Stdout,
|
||||
Stderr: e.Stderr,
|
||||
}
|
||||
|
||||
result := ast.NewVars()
|
||||
e.promptedVars = ast.NewVars()
|
||||
|
||||
for _, v := range vars {
|
||||
for _, v := range varsMap {
|
||||
var value string
|
||||
var err error
|
||||
|
||||
@@ -93,21 +94,21 @@ func (e *Executor) promptForAllVars(vars []*ast.VarsWithValidation) (*ast.Vars,
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, prompt.ErrCancelled) {
|
||||
return nil, &errors.TaskCancelledByUserError{TaskName: "interactive prompt"}
|
||||
return &errors.TaskCancelledByUserError{TaskName: "interactive prompt"}
|
||||
}
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
result.Set(v.Name, ast.Var{Value: value})
|
||||
e.promptedVars.Set(v.Name, ast.Var{Value: value})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// promptForMissingVars prompts for any required vars that are missing from the task.
|
||||
// It updates call.Vars with the prompted values and stores them in e.promptedVars for reuse.
|
||||
// promptTaskVars prompts for any missing required vars from a single task.
|
||||
// Used for sequential task calls (cmds) where we can prompt just-in-time.
|
||||
// Returns true if any vars were prompted (caller should recompile the task).
|
||||
func (e *Executor) promptForMissingVars(t *ast.Task, call *Call) (bool, error) {
|
||||
func (e *Executor) promptTaskVars(t *ast.Task, call *Call) (bool, error) {
|
||||
if !e.Interactive || t.Requires == nil || len(t.Requires.Vars) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
@@ -120,7 +121,7 @@ func (e *Executor) promptForMissingVars(t *ast.Task, call *Call) (bool, error) {
|
||||
var missing []*ast.VarsWithValidation
|
||||
for _, v := range t.Requires.Vars {
|
||||
if _, ok := t.Vars.Get(v.Name); !ok {
|
||||
// Also check if we already prompted for this var
|
||||
// Skip if already prompted
|
||||
if e.promptedVars != nil {
|
||||
if _, ok := e.promptedVars.Get(v.Name); ok {
|
||||
continue
|
||||
@@ -157,13 +158,13 @@ func (e *Executor) promptForMissingVars(t *ast.Task, call *Call) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Add to call.Vars so it's available for recompilation
|
||||
// Add to call.Vars for recompilation
|
||||
if call.Vars == nil {
|
||||
call.Vars = ast.NewVars()
|
||||
}
|
||||
call.Vars.Set(v.Name, ast.Var{Value: value})
|
||||
|
||||
// Store in promptedVars for reuse by other tasks
|
||||
// Cache for reuse by other tasks
|
||||
if e.promptedVars == nil {
|
||||
e.promptedVars = ast.NewVars()
|
||||
}
|
||||
|
||||
13
task.go
13
task.go
@@ -73,15 +73,8 @@ func (e *Executor) Run(ctx context.Context, calls ...*Call) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Collect all required vars upfront and prompt for them all at once
|
||||
requiredVars, err := e.collectAllRequiredVars(calls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prompt for all missing vars and store on executor
|
||||
e.promptedVars, err = e.promptForAllVars(requiredVars)
|
||||
if err != nil {
|
||||
// Prompt for all required vars from deps upfront (parallel execution)
|
||||
if err := e.promptDepsVars(calls); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -155,7 +148,7 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error {
|
||||
}
|
||||
|
||||
// Prompt for missing required vars (just-in-time for sequential task calls)
|
||||
prompted, err := e.promptForMissingVars(t, call)
|
||||
prompted, err := e.promptTaskVars(t, call)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user