Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ type (
executionHashes map[string]context.Context
executionHashesMutex sync.Mutex
watchedDirs *xsync.Map[string, bool]
taskMapCache map[string]map[string]any
taskMapCacheMutex sync.RWMutex
}
TempDir struct {
Remote string
Expand Down
23 changes: 23 additions & 0 deletions task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2652,6 +2652,29 @@ func TestWildcard(t *testing.T) {
}
}

func TestReferenceSelf(t *testing.T) {
t.Parallel()

const dir = "testdata/reference_self"

var buff bytes.Buffer
e := task.NewExecutor(
task.WithDir(dir),
task.WithStdout(&buff),
task.WithStderr(&buff),
task.WithForceAll(true),
)
require.NoError(t, e.Setup())
require.NoError(t, e.Run(t.Context(), &task.Call{Task: "default"}))

assert.Contains(t, buff.String(), `task: [check-sources-empty] echo []`)
assert.Contains(t, buff.String(), `[]`)
assert.Contains(t, buff.String(), `task: [check-generates] echo [a b *.txt]`)
assert.Contains(t, buff.String(), `[a b *.txt]`)
assert.Contains(t, buff.String(), `task: [check-generates-empty] echo []`)
assert.Contains(t, buff.String(), `[]`)
}

// enableExperimentForTest enables the experiment behind pointer e for the duration of test t and sub-tests,
// with the experiment being restored to its previous state when tests complete.
//
Expand Down
Empty file.
Empty file.
32 changes: 32 additions & 0 deletions testdata/reference_other_tasks/taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: '3'

method: none

tasks:

_ref:
sources: ["a", "b", "*.txt"]
generates: ["a", "b", "*.txt"]
cmd: ":"

_ref-empty:
cmd: ":"

check-sources:
cmd: echo {{ .TASKS._ref.sources }}

check-sources-empty:
cmd: echo {{ (index .TASKS "_ref-empty").sources }}

check-generates:
cmd: echo {{ .TASKS._ref.generates }}

check-generates-empty:
cmd: echo {{ (index .TASKS "_ref-empty").generates }}

default:
cmds:
- task: check-sources
- task: check-sources-empty
- task: check-generates
- task: check-generates-empty
Empty file added testdata/reference_self/1.txt
Empty file.
Empty file added testdata/reference_self/2.txt
Empty file.
26 changes: 26 additions & 0 deletions testdata/reference_self/taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3'

method: none

tasks:

check-sources:
sources: ["a", "b", "*.txt"]
cmd: echo {{ .TASKS.self.sources }}

check-sources-empty:
cmd: echo {{ .TASKS.self.sources }}

check-generates:
generates: ["a", "b", "*.txt"]
cmd: echo {{ .TASKS.self.generates }}

check-generates-empty:
cmd: echo {{ .TASKS.self.generates }}

default:
cmds:
- task: check-sources
- task: check-sources-empty
- task: check-generates
- task: check-generates-empty
51 changes: 51 additions & 0 deletions variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,51 @@ func (e *Executor) CompiledTaskForTaskList(call *Call) (*ast.Task, error) {
}, nil
}

func taskToMap(t *ast.Task) map[string]any {
result := make(map[string]any)

// Convert sources to a slice of strings
if len(t.Sources) > 0 {
sources := make([]string, 0, len(t.Sources))
for _, glob := range t.Sources {
sources = append(sources, glob.Glob)
}
result["sources"] = sources
} else {
result["sources"] = []string{}
}

// Convert generates to a slice of strings
if len(t.Generates) > 0 {
generates := make([]string, 0, len(t.Generates))
for _, glob := range t.Generates {
generates = append(generates, glob.Glob)
}
result["generates"] = generates
} else {
result["generates"] = []string{}
}

// Add other commonly used properties
result["task"] = t.Task
result["dir"] = t.Dir
result["label"] = t.Label
result["desc"] = t.Desc
result["method"] = t.Method
result["prefix"] = t.Prefix
result["run"] = t.Run
result["silent"] = t.Silent
result["interactive"] = t.Interactive
result["internal"] = t.Internal
result["ignore_error"] = t.IgnoreError
result["watch"] = t.Watch
result["failfast"] = t.Failfast
result["aliases"] = t.Aliases
result["dotenv"] = t.Dotenv

return result
}

func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, error) {
origTask, err := e.GetTask(call)
if err != nil {
Expand Down Expand Up @@ -141,6 +186,12 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err
new.Prefix = new.Task
}

// Add TASKS.self variable after basic properties are expanded
tasksMap := make(map[string]any)
tasksMap["self"] = taskToMap(&new)
vars.Set("TASKS", ast.Var{Value: tasksMap})
cache.ResetCache()

dotenvEnvs := ast.NewVars()
if len(new.Dotenv) > 0 {
for _, dotEnvPath := range new.Dotenv {
Expand Down