1
0
mirror of https://github.com/go-task/task.git synced 2025-04-18 12:04:04 +03:00

feat: support for loops with generates (#2151)

This commit is contained in:
Artem Sedykh 2025-04-06 01:55:43 +03:00 committed by GitHub
parent a9de239e38
commit 6f0f38b8d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 113 additions and 3 deletions

View File

@ -759,6 +759,8 @@ func TestForCmds(t *testing.T) {
},
{name: "loop-sources"},
{name: "loop-sources-glob"},
{name: "loop-generates"},
{name: "loop-generates-glob"},
{name: "loop-vars"},
{name: "loop-vars-sh"},
{name: "loop-task"},
@ -800,6 +802,8 @@ func TestForDeps(t *testing.T) {
},
{name: "loop-sources"},
{name: "loop-sources-glob"},
{name: "loop-generates"},
{name: "loop-generates-glob"},
{name: "loop-vars"},
{name: "loop-vars-sh"},
{name: "loop-task"},

View File

@ -57,6 +57,23 @@ tasks:
- for: sources
cmd: cat "{{.ITEM}}"
# Loop over the task's generates
loop-generates:
generates:
- foo.txt
- bar.txt
cmds:
- for: generates
cmd: cat "{{.ITEM}}"
# Loop over the task's generates when globbed
loop-generates-glob:
generates:
- "*.txt"
cmds:
- for: generates
cmd: cat "{{.ITEM}}"
# Loop over the contents of a variable
loop-vars:
vars:

View File

@ -0,0 +1,2 @@
bar
foo

View File

@ -0,0 +1,2 @@
bar
foo

View File

@ -69,6 +69,27 @@ tasks:
vars:
FILE: "{{.ITEM}}"
# Loop over the task's generates
loop-generates:
generates:
- foo.txt
- bar.txt
deps:
- for: generates
task: cat
vars:
FILE: "{{.ITEM}}"
# Loop over the task's generates when globbed
loop-generates-glob:
generates:
- "*.txt"
deps:
- for: generates
task: cat
vars:
FILE: "{{.ITEM}}"
# Loop over the contents of a variable
loop-vars:
vars:

View File

@ -0,0 +1,2 @@
bar
foo

View File

@ -0,0 +1,2 @@
bar
foo

View File

@ -153,7 +153,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err
continue
}
if cmd.For != nil {
list, keys, err := itemsFromFor(cmd.For, new.Dir, new.Sources, vars, origTask.Location, cache)
list, keys, err := itemsFromFor(cmd.For, new.Dir, new.Sources, new.Generates, vars, origTask.Location, cache)
if err != nil {
return nil, err
}
@ -200,7 +200,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err
continue
}
if dep.For != nil {
list, keys, err := itemsFromFor(dep.For, new.Dir, new.Sources, vars, origTask.Location, cache)
list, keys, err := itemsFromFor(dep.For, new.Dir, new.Sources, new.Generates, vars, origTask.Location, cache)
if err != nil {
return nil, err
}
@ -270,6 +270,7 @@ func itemsFromFor(
f *ast.For,
dir string,
sources []*ast.Glob,
generates []*ast.Glob,
vars *ast.Vars,
location *ast.Location,
cache *templater.Cache,
@ -304,6 +305,20 @@ func itemsFromFor(
}
values = asAnySlice(glist)
}
// Get the list from the task generates
if f.From == "generates" {
glist, err := fingerprint.Globs(dir, generates)
if err != nil {
return nil, nil, err
}
// Make the paths relative to the task dir
for i, v := range glist {
if glist[i], err = filepath.Rel(dir, v); err != nil {
return nil, nil, err
}
}
values = asAnySlice(glist)
}
// Get the list from a variable and split it up
if f.Var != "" {
if vars != nil {

View File

@ -199,6 +199,9 @@ it is defined as a string, you can give it any of the following values:
- `sources` - Will run the command for each source file defined on the task.
(Glob patterns will be resolved, so `*.go` will run for every Go file that
matches).
- `generates` - Will run the command for each file defined in the task's generates
list. (Glob patterns will be resolved, so `*.txt` will run for every text file
that matches).
If it is defined as a list of strings, the command will be run for each value.

View File

@ -1483,6 +1483,48 @@ tasks:
cmd: cat {{joinPath .MY_DIR .ITEM}}
```
### Looping over your task's generates
Similar to sources, you can also loop over the generates of your task:
```yaml
version: '3'
tasks:
default:
generates:
- foo.txt
- bar.txt
cmds:
- for: generates
cmd: cat {{ .ITEM }}
```
This will also work if you use globbing syntax in your generates. For example, if
you specify a generate for `*.txt`, the loop will iterate over all files that
match that glob.
Generate paths will always be returned as paths relative to the task directory. If
you need to convert this to an absolute path, you can use the built-in
`joinPath` function. There are some [special variables](/reference/templating/#special-variables)
that you may find useful for this.
```yaml
version: '3'
tasks:
default:
vars:
MY_DIR: /path/to/dir
dir: '{{.MY_DIR}}'
generates:
- foo.txt
- bar.txt
cmds:
- for: generates
cmd: cat {{joinPath .MY_DIR .ITEM}}
```
### Looping over variables
To loop over the contents of a variable, you simply need to specify the variable

View File

@ -475,7 +475,7 @@
"for_attribute": {
"description": "The task attribute to iterate over",
"type": "string",
"enum": ["sources"]
"enum": ["sources", "generates"]
},
"for_var": {
"description": "Which variables to iterate over. The variable will be split using any whitespace character by default. This can be changed by using the `split` attribute.",