Skip to content

Commit b708548

Browse files
committed
Includes: Support templating in included 'task.dir' field.
1 parent 91f9299 commit b708548

5 files changed

Lines changed: 66 additions & 29 deletions

File tree

compiler.go

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,6 @@ func (c *Compiler) getVariables(t *ast.Task, call *Call, evaluateShVars bool) (*
9191
}
9292
rangeFunc := getRangeFunc(c.Dir)
9393

94-
var taskRangeFunc func(k string, v ast.Var) error
95-
if t != nil {
96-
// NOTE(@andreynering): We're manually joining these paths here because
97-
// this is the raw task, not the compiled one.
98-
cache := &templater.Cache{Vars: result}
99-
dir := templater.Replace(t.Dir, cache)
100-
if err := cache.Err(); err != nil {
101-
return nil, err
102-
}
103-
dir = filepathext.SmartJoin(c.Dir, dir)
104-
taskRangeFunc = getRangeFunc(dir)
105-
}
106-
10794
for k, v := range c.TaskfileEnv.All() {
10895
if err := rangeFunc(k, v); err != nil {
10996
return nil, err
@@ -114,31 +101,54 @@ func (c *Compiler) getVariables(t *ast.Task, call *Call, evaluateShVars bool) (*
114101
return nil, err
115102
}
116103
}
104+
117105
if t != nil {
118106
for k, v := range t.IncludeVars.All() {
119107
if err := rangeFunc(k, v); err != nil {
120108
return nil, err
121109
}
122110
}
111+
112+
if !evaluateShVars {
113+
// Add includedTaskfile.Vars, and replace/overwrite taskfile.Vars,
114+
// _before_ calculating the t.Dir using the templater. Because
115+
// evaluateShVars is not set, the dir used when creating rangeFunc
116+
// will not be used (sh vars are evaluated on subsequent calls).
117+
for k, v := range t.IncludedTaskfileVars.All() {
118+
if err := rangeFunc(k, v); err != nil {
119+
return nil, err
120+
}
121+
}
122+
}
123+
124+
// Calculate the taskDir for evaluation of IncludeVars. If the original TaskDir
125+
// was saved to t.IncludeTaskDir then that path needs to be used.
126+
cache := &templater.Cache{Vars: result}
127+
t.Dir = templater.Replace(t.Dir, cache)
128+
if len(t.IncludeTaskDir) > 0 {
129+
// If the included TaskDir is absolute, then it will become
130+
// the TaskDir, otherwise join with the existing TaskDir.
131+
taskDir := templater.Replace(t.IncludeTaskDir, cache)
132+
t.Dir = filepathext.SmartJoin(t.Dir, taskDir)
133+
}
134+
taskRangeFunc := getRangeFunc(t.Dir)
135+
123136
for k, v := range t.IncludedTaskfileVars.All() {
124137
if err := taskRangeFunc(k, v); err != nil {
125138
return nil, err
126139
}
127140
}
128-
}
129-
130-
if t == nil || call == nil {
131-
return result, nil
132-
}
133-
134-
for k, v := range call.Vars.All() {
135-
if err := rangeFunc(k, v); err != nil {
136-
return nil, err
141+
if call != nil {
142+
for k, v := range call.Vars.All() {
143+
if err := rangeFunc(k, v); err != nil {
144+
return nil, err
145+
}
146+
}
137147
}
138-
}
139-
for k, v := range t.Vars.All() {
140-
if err := taskRangeFunc(k, v); err != nil {
141-
return nil, err
148+
for k, v := range t.Vars.All() {
149+
if err := taskRangeFunc(k, v); err != nil {
150+
return nil, err
151+
}
142152
}
143153
}
144154

internal/filepathext/filepathext.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import (
66
"strings"
77
)
88

9-
// SmartJoin joins two paths, but only if the second is not already an
10-
// absolute path.
9+
// SmartJoin joins two paths when the second path is not absolute, otherwise
10+
// it returns the second (absolute) path.
1111
func SmartJoin(a, b string) string {
1212
if IsAbs(b) {
1313
return b
@@ -28,6 +28,7 @@ func IsAbs(path string) bool {
2828
var knownAbsDirs = []string{
2929
".ROOT_DIR",
3030
".TASKFILE_DIR",
31+
".TASK_DIR",
3132
".USER_WORKING_DIR",
3233
}
3334

task_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,23 @@ func TestIncludedTaskfileVarMerging(t *testing.T) {
13331333
}
13341334
}
13351335

1336+
func TestIncludedDirWithTemplate(t *testing.T) {
1337+
t.Parallel()
1338+
1339+
const dir = "testdata/included_dir_with_template"
1340+
var buff bytes.Buffer
1341+
e := task.NewExecutor(
1342+
task.WithDir(dir),
1343+
task.WithStdout(&buff),
1344+
task.WithStderr(&buff),
1345+
task.WithSilent(true),
1346+
)
1347+
require.NoError(t, e.Setup())
1348+
err := e.Run(t.Context(), &task.Call{Task: "default"})
1349+
require.NoError(t, err)
1350+
assert.Contains(t, buff.String(), "Build WORKING_DIR: /tmp")
1351+
}
1352+
13361353
func TestInternalTask(t *testing.T) {
13371354
t.Parallel()
13381355

taskfile/ast/task.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type Task struct {
4545
Failfast bool
4646
// Populated during merging
4747
Namespace string `hash:"ignore"`
48+
IncludeTaskDir string
4849
IncludeVars *Vars
4950
IncludedTaskfileVars *Vars
5051

taskfile/ast/tasks.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,15 @@ func (t1 *Tasks) Merge(t2 *Tasks, include *Include, includedTaskfileVars *Vars)
171171
}
172172

173173
if include.AdvancedImport {
174-
task.Dir = filepathext.SmartJoin(include.Dir, task.Dir)
174+
if filepathext.IsAbs(task.Dir) {
175+
// TaskDir with (obvious) absolute path has priority.
176+
} else {
177+
// TaskDir will be either <IncludeDir> or <IncludeDir>/<TaskDir>, however
178+
// task.Dir may still compile to an absolute path. Set/save now and resolve
179+
// later in Compiler.getVariables.
180+
task.IncludeTaskDir = task.Dir
181+
task.Dir = include.Dir
182+
}
175183
if task.IncludeVars == nil {
176184
task.IncludeVars = NewVars()
177185
}

0 commit comments

Comments
 (0)