mirror of
				https://github.com/go-task/task.git
				synced 2025-10-30 23:58:01 +02:00 
			
		
		
		
	fix: bug where non-nil, empty dynamic variables are returned as an empty interface (#1904)
This commit is contained in:
		| @@ -74,8 +74,8 @@ func (c *Compiler) getVariables(t *ast.Task, call *ast.Call, evaluateShVars bool | ||||
| 			if err := cache.Err(); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			// If the variable is not dynamic, we can set it and return | ||||
| 			if newVar.Value != nil || newVar.Sh == "" { | ||||
| 			// If the variable is already set, we can set it and return | ||||
| 			if newVar.Value != nil { | ||||
| 				result.Set(k, ast.Var{Value: newVar.Value}) | ||||
| 				return nil | ||||
| 			} | ||||
| @@ -136,10 +136,15 @@ func (c *Compiler) HandleDynamicVar(v ast.Var, dir string) (string, error) { | ||||
| 	c.muDynamicCache.Lock() | ||||
| 	defer c.muDynamicCache.Unlock() | ||||
|  | ||||
| 	// If the variable is not dynamic or it is empty, return an empty string | ||||
| 	if v.Sh == nil || *v.Sh == "" { | ||||
| 		return "", nil | ||||
| 	} | ||||
|  | ||||
| 	if c.dynamicCache == nil { | ||||
| 		c.dynamicCache = make(map[string]string, 30) | ||||
| 	} | ||||
| 	if result, ok := c.dynamicCache[v.Sh]; ok { | ||||
| 	if result, ok := c.dynamicCache[*v.Sh]; ok { | ||||
| 		return result, nil | ||||
| 	} | ||||
|  | ||||
| @@ -150,7 +155,7 @@ func (c *Compiler) HandleDynamicVar(v ast.Var, dir string) (string, error) { | ||||
|  | ||||
| 	var stdout bytes.Buffer | ||||
| 	opts := &execext.RunCommandOptions{ | ||||
| 		Command: v.Sh, | ||||
| 		Command: *v.Sh, | ||||
| 		Dir:     dir, | ||||
| 		Stdout:  &stdout, | ||||
| 		Stderr:  c.Logger.Stderr, | ||||
| @@ -164,7 +169,7 @@ func (c *Compiler) HandleDynamicVar(v ast.Var, dir string) (string, error) { | ||||
| 	result := strings.TrimSuffix(stdout.String(), "\r\n") | ||||
| 	result = strings.TrimSuffix(result, "\n") | ||||
|  | ||||
| 	c.dynamicCache[v.Sh] = result | ||||
| 	c.dynamicCache[*v.Sh] = result | ||||
| 	c.Logger.VerboseErrf(logger.Magenta, "task: dynamic variable: %q result: %q\n", v.Sh, result) | ||||
|  | ||||
| 	return result, nil | ||||
|   | ||||
| @@ -20,7 +20,7 @@ type Vars struct { | ||||
| func (vs *Vars) ToCacheMap() (m map[string]any) { | ||||
| 	m = make(map[string]any, vs.Len()) | ||||
| 	_ = vs.Range(func(k string, v Var) error { | ||||
| 		if v.Sh != "" { | ||||
| 		if v.Sh != nil && *v.Sh != "" { | ||||
| 			// Dynamic variable is not yet resolved; trigger | ||||
| 			// <no value> to be used in templates. | ||||
| 			return nil | ||||
| @@ -81,7 +81,7 @@ func (vs *Vars) DeepCopy() *Vars { | ||||
| type Var struct { | ||||
| 	Value any | ||||
| 	Live  any | ||||
| 	Sh    string | ||||
| 	Sh    *string | ||||
| 	Ref   string | ||||
| 	Dir   string | ||||
| } | ||||
| @@ -98,7 +98,7 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error { | ||||
| 			// If the value is a string and it starts with $, then it's a shell command | ||||
| 			if str, ok := value.(string); ok { | ||||
| 				if str, ok = strings.CutPrefix(str, "$"); ok { | ||||
| 					v.Sh = str | ||||
| 					v.Sh = &str | ||||
| 					return nil | ||||
| 				} | ||||
| 				if str, ok = strings.CutPrefix(str, "#"); ok { | ||||
| @@ -118,7 +118,7 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error { | ||||
| 				switch key { | ||||
| 				case "sh", "ref", "map": | ||||
| 					var m struct { | ||||
| 						Sh  string | ||||
| 						Sh  *string | ||||
| 						Ref string | ||||
| 						Map any | ||||
| 					} | ||||
| @@ -150,7 +150,7 @@ func (v *Var) UnmarshalYAML(node *yaml.Node) error { | ||||
| 		switch key { | ||||
| 		case "sh", "ref": | ||||
| 			var m struct { | ||||
| 				Sh  string | ||||
| 				Sh  *string | ||||
| 				Ref string | ||||
| 			} | ||||
| 			if err := node.Decode(&m); err != nil { | ||||
|   | ||||
| @@ -112,7 +112,7 @@ func (e *Executor) compiledTask(call *ast.Call, evaluateShVars bool) (*ast.Task, | ||||
| 	if evaluateShVars { | ||||
| 		err = new.Env.Range(func(k string, v ast.Var) error { | ||||
| 			// If the variable is not dynamic, we can set it and return | ||||
| 			if v.Value != nil || v.Sh == "" { | ||||
| 			if v.Value != nil || v.Sh == nil { | ||||
| 				new.Env.Set(k, ast.Var{Value: v.Value}) | ||||
| 				return nil | ||||
| 			} | ||||
| @@ -301,7 +301,7 @@ func itemsFromFor( | ||||
| 			// If the variable is dynamic, then it hasn't been resolved yet | ||||
| 			// and we can't use it as a list. This happens when fast compiling a task | ||||
| 			// for use in --list or --list-all etc. | ||||
| 			if v.Value != nil && v.Sh == "" { | ||||
| 			if v.Value != nil && v.Sh == nil { | ||||
| 				switch value := v.Value.(type) { | ||||
| 				case string: | ||||
| 					if f.Split != "" { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user