mirror of
https://github.com/go-task/task.git
synced 2025-12-17 04:07:44 +01:00
refactor(interactive): simplify prompting functions and naming
This commit is contained in:
@@ -70,7 +70,7 @@ type (
|
|||||||
fuzzyModel *fuzzy.Model
|
fuzzyModel *fuzzy.Model
|
||||||
fuzzyModelOnce sync.Once
|
fuzzyModelOnce sync.Once
|
||||||
|
|
||||||
promptedVars *ast.Vars // vars collected via interactive prompts
|
promptedVars *ast.Vars // vars collected via interactive prompts
|
||||||
concurrencySemaphore chan struct{}
|
concurrencySemaphore chan struct{}
|
||||||
taskCallCount map[string]*int32
|
taskCallCount map[string]*int32
|
||||||
mkdirMutexMap map[string]*sync.Mutex
|
mkdirMutexMap map[string]*sync.Mutex
|
||||||
|
|||||||
59
requires.go
59
requires.go
@@ -9,7 +9,20 @@ import (
|
|||||||
"github.com/go-task/task/v3/taskfile/ast"
|
"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)
|
visited := make(map[string]bool)
|
||||||
varsMap := make(map[string]*ast.VarsWithValidation)
|
varsMap := make(map[string]*ast.VarsWithValidation)
|
||||||
|
|
||||||
@@ -52,36 +65,24 @@ func (e *Executor) collectAllRequiredVars(calls []*Call) ([]*ast.VarsWithValidat
|
|||||||
|
|
||||||
for _, call := range calls {
|
for _, call := range calls {
|
||||||
if err := collect(call); err != nil {
|
if err := collect(call); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]*ast.VarsWithValidation, 0, len(varsMap))
|
if len(varsMap) == 0 {
|
||||||
for _, v := range varsMap {
|
return nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prompt for all collected vars
|
||||||
prompter := &prompt.Prompter{
|
prompter := &prompt.Prompter{
|
||||||
Stdin: e.Stdin,
|
Stdin: e.Stdin,
|
||||||
Stdout: e.Stdout,
|
Stdout: e.Stdout,
|
||||||
Stderr: e.Stderr,
|
Stderr: e.Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
result := ast.NewVars()
|
e.promptedVars = ast.NewVars()
|
||||||
|
|
||||||
for _, v := range vars {
|
for _, v := range varsMap {
|
||||||
var value string
|
var value string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -93,21 +94,21 @@ func (e *Executor) promptForAllVars(vars []*ast.VarsWithValidation) (*ast.Vars,
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, prompt.ErrCancelled) {
|
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.
|
// promptTaskVars prompts for any missing required vars from a single task.
|
||||||
// It updates call.Vars with the prompted values and stores them in e.promptedVars for reuse.
|
// 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).
|
// 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 {
|
if !e.Interactive || t.Requires == nil || len(t.Requires.Vars) == 0 {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@@ -120,7 +121,7 @@ func (e *Executor) promptForMissingVars(t *ast.Task, call *Call) (bool, error) {
|
|||||||
var missing []*ast.VarsWithValidation
|
var missing []*ast.VarsWithValidation
|
||||||
for _, v := range t.Requires.Vars {
|
for _, v := range t.Requires.Vars {
|
||||||
if _, ok := t.Vars.Get(v.Name); !ok {
|
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 e.promptedVars != nil {
|
||||||
if _, ok := e.promptedVars.Get(v.Name); ok {
|
if _, ok := e.promptedVars.Get(v.Name); ok {
|
||||||
continue
|
continue
|
||||||
@@ -157,13 +158,13 @@ func (e *Executor) promptForMissingVars(t *ast.Task, call *Call) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to call.Vars so it's available for recompilation
|
// Add to call.Vars for recompilation
|
||||||
if call.Vars == nil {
|
if call.Vars == nil {
|
||||||
call.Vars = ast.NewVars()
|
call.Vars = ast.NewVars()
|
||||||
}
|
}
|
||||||
call.Vars.Set(v.Name, ast.Var{Value: value})
|
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 {
|
if e.promptedVars == nil {
|
||||||
e.promptedVars = ast.NewVars()
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect all required vars upfront and prompt for them all at once
|
// Prompt for all required vars from deps upfront (parallel execution)
|
||||||
requiredVars, err := e.collectAllRequiredVars(calls)
|
if err := e.promptDepsVars(calls); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prompt for all missing vars and store on executor
|
|
||||||
e.promptedVars, err = e.promptForAllVars(requiredVars)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
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)
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user