Skip to content

Commit 148b090

Browse files
authored
fix: bug where non-nil, empty dynamic variables are returned as an empty interface (#1904)
1 parent 28a96d1 commit 148b090

File tree

3 files changed

+17
-12
lines changed

3 files changed

+17
-12
lines changed

internal/compiler/compiler.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ func (c *Compiler) getVariables(t *ast.Task, call *ast.Call, evaluateShVars bool
7474
if err := cache.Err(); err != nil {
7575
return err
7676
}
77-
// If the variable is not dynamic, we can set it and return
78-
if newVar.Value != nil || newVar.Sh == "" {
77+
// If the variable is already set, we can set it and return
78+
if newVar.Value != nil {
7979
result.Set(k, ast.Var{Value: newVar.Value})
8080
return nil
8181
}
@@ -136,10 +136,15 @@ func (c *Compiler) HandleDynamicVar(v ast.Var, dir string) (string, error) {
136136
c.muDynamicCache.Lock()
137137
defer c.muDynamicCache.Unlock()
138138

139+
// If the variable is not dynamic or it is empty, return an empty string
140+
if v.Sh == nil || *v.Sh == "" {
141+
return "", nil
142+
}
143+
139144
if c.dynamicCache == nil {
140145
c.dynamicCache = make(map[string]string, 30)
141146
}
142-
if result, ok := c.dynamicCache[v.Sh]; ok {
147+
if result, ok := c.dynamicCache[*v.Sh]; ok {
143148
return result, nil
144149
}
145150

@@ -150,7 +155,7 @@ func (c *Compiler) HandleDynamicVar(v ast.Var, dir string) (string, error) {
150155

151156
var stdout bytes.Buffer
152157
opts := &execext.RunCommandOptions{
153-
Command: v.Sh,
158+
Command: *v.Sh,
154159
Dir: dir,
155160
Stdout: &stdout,
156161
Stderr: c.Logger.Stderr,
@@ -164,7 +169,7 @@ func (c *Compiler) HandleDynamicVar(v ast.Var, dir string) (string, error) {
164169
result := strings.TrimSuffix(stdout.String(), "\r\n")
165170
result = strings.TrimSuffix(result, "\n")
166171

167-
c.dynamicCache[v.Sh] = result
172+
c.dynamicCache[*v.Sh] = result
168173
c.Logger.VerboseErrf(logger.Magenta, "task: dynamic variable: %q result: %q\n", v.Sh, result)
169174

170175
return result, nil

taskfile/ast/var.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type Vars struct {
2020
func (vs *Vars) ToCacheMap() (m map[string]any) {
2121
m = make(map[string]any, vs.Len())
2222
_ = vs.Range(func(k string, v Var) error {
23-
if v.Sh != "" {
23+
if v.Sh != nil && *v.Sh != "" {
2424
// Dynamic variable is not yet resolved; trigger
2525
// <no value> to be used in templates.
2626
return nil
@@ -81,7 +81,7 @@ func (vs *Vars) DeepCopy() *Vars {
8181
type Var struct {
8282
Value any
8383
Live any
84-
Sh string
84+
Sh *string
8585
Ref string
8686
Dir string
8787
}
@@ -98,7 +98,7 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error {
9898
// If the value is a string and it starts with $, then it's a shell command
9999
if str, ok := value.(string); ok {
100100
if str, ok = strings.CutPrefix(str, "$"); ok {
101-
v.Sh = str
101+
v.Sh = &str
102102
return nil
103103
}
104104
if str, ok = strings.CutPrefix(str, "#"); ok {
@@ -118,7 +118,7 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error {
118118
switch key {
119119
case "sh", "ref", "map":
120120
var m struct {
121-
Sh string
121+
Sh *string
122122
Ref string
123123
Map any
124124
}
@@ -150,7 +150,7 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error {
150150
switch key {
151151
case "sh", "ref":
152152
var m struct {
153-
Sh string
153+
Sh *string
154154
Ref string
155155
}
156156
if err := node.Decode(&m); err != nil {

variables.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func (e *Executor) compiledTask(call *ast.Call, evaluateShVars bool) (*ast.Task,
112112
if evaluateShVars {
113113
err = new.Env.Range(func(k string, v ast.Var) error {
114114
// If the variable is not dynamic, we can set it and return
115-
if v.Value != nil || v.Sh == "" {
115+
if v.Value != nil || v.Sh == nil {
116116
new.Env.Set(k, ast.Var{Value: v.Value})
117117
return nil
118118
}
@@ -301,7 +301,7 @@ func itemsFromFor(
301301
// If the variable is dynamic, then it hasn't been resolved yet
302302
// and we can't use it as a list. This happens when fast compiling a task
303303
// for use in --list or --list-all etc.
304-
if v.Value != nil && v.Sh == "" {
304+
if v.Value != nil && v.Sh == nil {
305305
switch value := v.Value.(type) {
306306
case string:
307307
if f.Split != "" {

0 commit comments

Comments
 (0)