diff --git a/CHANGELOG.md b/CHANGELOG.md index 803dfd18..1e606311 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +- Improve performance of `--list` and `--summary` by skipping running shell + variables for these flags + ([#332](https://github.com/go-task/task/issues/332)). - Fixed a bug where an environment in a Taskfile was not always overridable by the system environment ([#425](https://github.com/go-task/task/issues/425)). diff --git a/help.go b/help.go index af12ddcb..256b13c8 100644 --- a/help.go +++ b/help.go @@ -30,7 +30,7 @@ func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) { tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks)) for _, task := range e.Taskfile.Tasks { if task.Desc != "" { - compiledTask, err := e.CompiledTask(taskfile.Call{Task: task.Task}) + compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task}) if err == nil { task = compiledTask } diff --git a/internal/compiler/compiler.go b/internal/compiler/compiler.go index 16c13886..b4305800 100644 --- a/internal/compiler/compiler.go +++ b/internal/compiler/compiler.go @@ -8,6 +8,7 @@ import ( // E.g. variable merger, template processing, etc. type Compiler interface { GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) + FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) HandleDynamicVar(v taskfile.Var, dir string) (string, error) ResetCache() } diff --git a/internal/compiler/v2/compiler_v2.go b/internal/compiler/v2/compiler_v2.go index 18c59d0f..d011a7ce 100644 --- a/internal/compiler/v2/compiler_v2.go +++ b/internal/compiler/v2/compiler_v2.go @@ -30,6 +30,11 @@ type CompilerV2 struct { muDynamicCache sync.Mutex } +// FastGetVariables is a no-op on v2 +func (c *CompilerV2) FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) { + return c.GetVariables(t, call) +} + // GetVariables returns fully resolved variables following the priority order: // 1. Task variables // 2. Call variables diff --git a/internal/compiler/v3/compiler_v3.go b/internal/compiler/v3/compiler_v3.go index 308171d4..41baab59 100644 --- a/internal/compiler/v3/compiler_v3.go +++ b/internal/compiler/v3/compiler_v3.go @@ -30,6 +30,14 @@ type CompilerV3 struct { } func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) { + return c.getVariables(t, call, true) +} + +func (c *CompilerV3) FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) { + return c.getVariables(t, call, false) +} + +func (c *CompilerV3) getVariables(t *taskfile.Task, call taskfile.Call, evaluateShVars bool) (*taskfile.Vars, error) { result := compiler.GetEnviron() result.Set("TASK", taskfile.Var{Static: t.Task}) @@ -37,6 +45,11 @@ func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfi return func(k string, v taskfile.Var) error { tr := templater.Templater{Vars: result, RemoveNoValue: true} + if !evaluateShVars { + result.Set(k, taskfile.Var{Static: tr.Replace(v.Static)}) + return nil + } + v = taskfile.Var{ Static: tr.Replace(v.Static), Sh: tr.Replace(v.Sh), diff --git a/task.go b/task.go index fbefd531..5fb70f9a 100644 --- a/task.go +++ b/task.go @@ -71,7 +71,7 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error { if e.Summary { for i, c := range calls { - compiledTask, err := e.CompiledTask(c) + compiledTask, err := e.FastCompiledTask(c) if err != nil { return nil } diff --git a/variables.go b/variables.go index a6929cfd..8c13154e 100644 --- a/variables.go +++ b/variables.go @@ -13,12 +13,27 @@ import ( // CompiledTask returns a copy of a task, but replacing variables in almost all // properties using the Go template package. func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) { + return e.compiledTask(call, true) +} + +// FastCompiledTask is like CompiledTask, but it skippes dynamic variables. +func (e *Executor) FastCompiledTask(call taskfile.Call) (*taskfile.Task, error) { + return e.compiledTask(call, false) +} + +func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskfile.Task, error) { origTask, ok := e.Taskfile.Tasks[call.Task] if !ok { return nil, &taskNotFoundError{call.Task} } - vars, err := e.Compiler.GetVariables(origTask, call) + var vars *taskfile.Vars + var err error + if evaluateShVars { + vars, err = e.Compiler.GetVariables(origTask, call) + } else { + vars, err = e.Compiler.FastGetVariables(origTask, call) + } if err != nil { return nil, err } @@ -59,16 +74,18 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) { new.Env = &taskfile.Vars{} new.Env.Merge(r.ReplaceVars(e.Taskfile.Env)) new.Env.Merge(r.ReplaceVars(origTask.Env)) - err = new.Env.Range(func(k string, v taskfile.Var) error { - static, err := e.Compiler.HandleDynamicVar(v, new.Dir) + if evaluateShVars { + err = new.Env.Range(func(k string, v taskfile.Var) error { + static, err := e.Compiler.HandleDynamicVar(v, new.Dir) + if err != nil { + return err + } + new.Env.Set(k, taskfile.Var{Static: static}) + return nil + }) if err != nil { - return err + return nil, err } - new.Env.Set(k, taskfile.Var{Static: static}) - return nil - }) - if err != nil { - return nil, err } if len(origTask.Cmds) > 0 {