Skip to content

Commit aebd083

Browse files
committed
fix(templater): ref with for loops
1 parent 179bde1 commit aebd083

File tree

6 files changed

+70
-3
lines changed

6 files changed

+70
-3
lines changed

executor_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,8 @@ func TestForCmds(t *testing.T) {
813813
{name: "loop-generates-glob"},
814814
{name: "loop-vars"},
815815
{name: "loop-vars-sh"},
816+
{name: "loop-vars-ref"},
817+
{name: "loop-vars-ref-as"},
816818
{name: "loop-task"},
817819
{name: "loop-task-as"},
818820
{name: "loop-different-tasks"},

internal/templater/templater.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ func (r *Cache) Err() error {
3232
}
3333

3434
func ResolveRef(ref string, cache *Cache) any {
35+
return ResolveRefWithExtra(ref, cache, nil)
36+
}
37+
38+
// ResolveRefWithExtra resolves a ref string using the cache plus any
39+
// additional data (e.g. loop variables) provided in extra.
40+
func ResolveRefWithExtra(ref string, cache *Cache, extra map[string]any) any {
3541
// If there is already an error, do nothing
3642
if cache.err != nil {
3743
return nil
@@ -42,15 +48,21 @@ func ResolveRef(ref string, cache *Cache) any {
4248
cache.cacheMap = cache.Vars.ToCacheMap()
4349
}
4450

51+
data := cache.cacheMap
52+
if len(extra) > 0 {
53+
data = maps.Clone(cache.cacheMap)
54+
maps.Copy(data, extra)
55+
}
56+
4557
if ref == "." {
46-
return cache.cacheMap
58+
return data
4759
}
4860
t, err := template.New("resolver").Funcs(templateFuncs).Parse(fmt.Sprintf("{{%s}}", ref))
4961
if err != nil {
5062
cache.err = err
5163
return nil
5264
}
53-
val, err := t.Resolve(cache.cacheMap)
65+
val, err := t.Resolve(data)
5466
if err != nil {
5567
cache.err = err
5668
return nil
@@ -121,7 +133,7 @@ func ReplaceVar(v ast.Var, cache *Cache) ast.Var {
121133

122134
func ReplaceVarWithExtra(v ast.Var, cache *Cache, extra map[string]any) ast.Var {
123135
if v.Ref != "" {
124-
return ast.Var{Value: ResolveRef(v.Ref, cache)}
136+
return ast.Var{Value: ResolveRefWithExtra(v.Ref, cache, extra)}
125137
}
126138
return ast.Var{
127139
Value: ReplaceWithExtra(v.Value, cache, extra),
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package templater
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
8+
"github.com/go-task/task/v3/taskfile/ast"
9+
)
10+
11+
func TestReplaceVarWithExtra_ResolvesRefFromExtra(t *testing.T) {
12+
t.Parallel()
13+
14+
cache := Cache{Vars: ast.NewVars()}
15+
extra := map[string]any{"ITEM": "a"}
16+
17+
got := ReplaceVarWithExtra(ast.Var{Ref: ".ITEM"}, &cache, extra)
18+
19+
require.Equal(t, "a", got.Value)
20+
}

testdata/for/cmds/Taskfile.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,35 @@ tasks:
9494
var: FOO
9595
cmd: cat "{{.ITEM}}"
9696

97+
# Loop variable passed by ref should work (currently broken)
98+
loop-vars-ref:
99+
vars:
100+
FOO: "a b"
101+
cmds:
102+
- for:
103+
var: FOO
104+
task: process
105+
vars:
106+
THING:
107+
ref: .ITEM
108+
109+
# Loop variable with alias passed by ref
110+
loop-vars-ref-as:
111+
vars:
112+
FOO: "x y"
113+
cmds:
114+
- for:
115+
var: FOO
116+
as: VAL
117+
task: process
118+
vars:
119+
THING:
120+
ref: .VAL
121+
122+
process:
123+
internal: true
124+
cmd: echo "{{.THING}}"
125+
97126
# Loop over another task
98127
loop-task:
99128
vars:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
x
2+
y
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
a
2+
b

0 commit comments

Comments
 (0)