1
0
mirror of https://github.com/go-task/task.git synced 2025-08-10 22:42:19 +02:00

Merge remote-tracking branch 'upstream/v3' into report-timestamp-to-status

* upstream/v3:
  v3.0.0-preview1
  Update v3 changelog
  Only have colored output on v3
  Add --color=false flag to disable colored output
  Update documentation about sprig
  Update CHANGELOG
  Migrate from sprig to slim-sprig
  Fix build after merging master
  Use colors for some output messages
This commit is contained in:
Stephen Prater
2019-08-25 10:33:13 -07:00
18 changed files with 121 additions and 83 deletions

View File

@@ -1,5 +1,15 @@
# Changelog # Changelog
## v3.0.0 - Preview 1
- We're now using [slim-sprig](https://github.com/go-task/slim-sprig) instead of
[sprig](https://github.com/Masterminds/sprig), which allowed a file size
reduction of about 22%
([#219](https://github.com/go-task/task/pull/219)).
- We now use some colors on Task output to better distinguish message types -
commands are green, errors are red, etc
([#207](https://github.com/go-task/task/pull/207)).
## Unreleased ## Unreleased
- Fixed panic bug when assigning a global variable - Fixed panic bug when assigning a global variable

View File

@@ -1,4 +1,4 @@
version: '2' version: '3'
includes: includes:
docs: ./docs docs: ./docs

View File

@@ -10,6 +10,7 @@ import (
"github.com/go-task/task/v2" "github.com/go-task/task/v2"
"github.com/go-task/task/v2/internal/args" "github.com/go-task/task/v2/internal/args"
"github.com/go-task/task/v2/internal/logger"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@@ -61,6 +62,7 @@ func main() {
dir string dir string
entrypoint string entrypoint string
output string output string
color bool
) )
pflag.BoolVar(&versionFlag, "version", false, "show Task version") pflag.BoolVar(&versionFlag, "version", false, "show Task version")
@@ -76,6 +78,7 @@ func main() {
pflag.StringVarP(&dir, "dir", "d", "", "sets directory of execution") pflag.StringVarP(&dir, "dir", "d", "", "sets directory of execution")
pflag.StringVarP(&entrypoint, "taskfile", "t", "", `choose which Taskfile to run. Defaults to "Taskfile.yml"`) pflag.StringVarP(&entrypoint, "taskfile", "t", "", `choose which Taskfile to run. Defaults to "Taskfile.yml"`)
pflag.StringVarP(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]") pflag.StringVarP(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]")
pflag.BoolVarP(&color, "color", "c", true, "colored output")
pflag.Parse() pflag.Parse()
if versionFlag { if versionFlag {
@@ -114,6 +117,7 @@ func main() {
Dry: dry, Dry: dry,
Entrypoint: entrypoint, Entrypoint: entrypoint,
Summary: summary, Summary: summary,
Color: color,
Stdin: os.Stdin, Stdin: os.Stdin,
Stdout: os.Stdout, Stdout: os.Stdout,
@@ -132,7 +136,7 @@ func main() {
arguments := pflag.Args() arguments := pflag.Args()
if len(arguments) == 0 { if len(arguments) == 0 {
log.Println("task: No argument given, trying default task") e.Logger.Errf(logger.Yellow, "task: No argument given, trying default task")
arguments = []string{"default"} arguments = []string{"default"}
} }
@@ -154,7 +158,8 @@ func main() {
} }
if err := e.Run(ctx, calls...); err != nil { if err := e.Run(ctx, calls...); err != nil {
log.Fatal(err) e.Logger.Errf(logger.Red, "%v", err)
os.Exit(1)
} }
} }

View File

@@ -1,4 +1,4 @@
version: '2' version: '3'
tasks: tasks:
install: install:

View File

@@ -532,7 +532,7 @@ This works for all types of variables.
Task parse commands as [Go's template engine][gotemplate] before executing Task parse commands as [Go's template engine][gotemplate] before executing
them. Variables are accessible through dot syntax (`.VARNAME`). them. Variables are accessible through dot syntax (`.VARNAME`).
All functions by the Go's [sprig lib](http://masterminds.github.io/sprig/) All functions by the Go's [slim-sprig lib](https://go-task.github.io/slim-sprig/)
are available. The following example gets the current date in a given format: are available. The following example gets the current date in a given format:
```yaml ```yaml

15
go.mod
View File

@@ -1,21 +1,18 @@
module github.com/go-task/task/v2 module github.com/go-task/task/v2
require ( require (
github.com/Masterminds/semver v1.4.2 // indirect github.com/fatih/color v1.7.0
github.com/Masterminds/sprig v2.16.0+incompatible github.com/go-task/slim-sprig v0.0.0-20190623010546-24867827a98b
github.com/aokoli/goutils v1.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.0.0 // indirect
github.com/huandu/xstrings v1.1.0 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/kr/pretty v0.1.0 // indirect github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-zglob v0.0.1 github.com/mattn/go-zglob v0.0.1
github.com/mitchellh/go-homedir v1.0.0 github.com/mitchellh/go-homedir v1.0.0
github.com/radovskyb/watcher v1.0.5 github.com/radovskyb/watcher v1.0.5
github.com/spf13/pflag v1.0.3 github.com/spf13/pflag v1.0.3
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
golang.org/x/sync v0.0.0-20190423024810-112230192c58 golang.org/x/crypto v0.0.0-20180830192347-182538f80094 // indirect
golang.org/x/tools/gopls v0.1.3 // indirect golang.org/x/net v0.0.0-20180826012351-8a410e7b638d // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
gopkg.in/yaml.v2 v2.2.1 gopkg.in/yaml.v2 v2.2.1
mvdan.cc/sh v2.6.4+incompatible mvdan.cc/sh v2.6.4+incompatible
) )

34
go.sum
View File

@@ -1,23 +1,19 @@
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/sprig v2.16.0+incompatible h1:QZbMUPxRQ50EKAq3LFMnxddMu88/EUUG3qmxwtDmPsY=
github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/aokoli/goutils v1.0.1 h1:7fpzNGoJ3VA8qcrm++XEE1QUe0mIwNeLa02Nwq7RDkg=
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/huandu/xstrings v1.1.0 h1:9oZY6Z/H3A1gytJxzuicbmV5QoR8M1TAPcn9WTg7vqg= github.com/go-task/slim-sprig v0.0.0-20190623010546-24867827a98b h1:z6iCP1USASmEZtKTzynd/rP4vOtBLlsD3v24wItbJIs=
github.com/huandu/xstrings v1.1.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= github.com/go-task/slim-sprig v0.0.0-20190623010546-24867827a98b/go.mod h1:XLIiFDBy2M8pA/fEL5rx9xr2EAzrDEO0S5brm5iekOE=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY= github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
@@ -29,6 +25,7 @@ github.com/radovskyb/watcher v1.0.5/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v0.0.0-20180319223459-c679ae2cc0cb/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20180830192347-182538f80094 h1:rVTAlhYa4+lCfNxmAIEOGQRoD23UqP72M3+rSWVGDTg= golang.org/x/crypto v0.0.0-20180830192347-182538f80094 h1:rVTAlhYa4+lCfNxmAIEOGQRoD23UqP72M3+rSWVGDTg=
@@ -40,17 +37,8 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789 h1:T8D7l6WB3tLu+VpKvw06ieD/OhBi1XpJmG1U/FtttZg=
golang.org/x/sys v0.0.0-20180831094639-fa5fdf94c789/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190710153321-831012c29e42 h1:4IOeC7p+OItq3+O5BWkcmVu2uBe3jekXau5S4QZX9DU=
golang.org/x/tools v0.0.0-20190710153321-831012c29e42/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools/gopls v0.1.3 h1:CB5ECiPysqZrwxcyRjN+exyZpY0gODTZvNiqQi3lpeo=
golang.org/x/tools/gopls v0.1.3/go.mod h1:vrCQzOKxvuiZLjCKSmbbov04oeBQQOb4VQqwYK2PWIY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=

View File

@@ -5,6 +5,7 @@ import (
"sort" "sort"
"text/tabwriter" "text/tabwriter"
"github.com/go-task/task/v2/internal/logger"
"github.com/go-task/task/v2/internal/taskfile" "github.com/go-task/task/v2/internal/taskfile"
) )
@@ -12,10 +13,10 @@ import (
func (e *Executor) PrintTasksHelp() { func (e *Executor) PrintTasksHelp() {
tasks := e.tasksWithDesc() tasks := e.tasksWithDesc()
if len(tasks) == 0 { if len(tasks) == 0 {
e.Logger.Outf("task: No tasks with description available") e.Logger.Outf(logger.Yellow, "task: No tasks with description available")
return return
} }
e.Logger.Outf("task: Available tasks for this project:") e.Logger.Outf(logger.Default, "task: Available tasks for this project:")
// Format in tab-separated columns with a tab stop of 8. // Format in tab-separated columns with a tab stop of 8.
w := tabwriter.NewWriter(e.Stdout, 0, 8, 0, '\t', 0) w := tabwriter.NewWriter(e.Stdout, 0, 8, 0, '\t', 0)

View File

@@ -131,7 +131,7 @@ func (c *CompilerV1) HandleDynamicVar(v taskfile.Var) (string, error) {
result := strings.TrimSuffix(stdout.String(), "\n") result := strings.TrimSuffix(stdout.String(), "\n")
c.dynamicCache[v.Sh] = result c.dynamicCache[v.Sh] = result
c.Logger.VerboseErrf(`task: dynamic variable: '%s' result: '%s'`, v.Sh, result) c.Logger.VerboseErrf(logger.Magenta, `task: dynamic variable: '%s' result: '%s'`, v.Sh, result)
return result, nil return result, nil
} }

View File

@@ -103,7 +103,7 @@ func (c *CompilerV2) HandleDynamicVar(v taskfile.Var) (string, error) {
result := strings.TrimSuffix(stdout.String(), "\n") result := strings.TrimSuffix(stdout.String(), "\n")
c.dynamicCache[v.Sh] = result c.dynamicCache[v.Sh] = result
c.Logger.VerboseErrf(`task: dynamic variable: '%s' result: '%s'`, v.Sh, result) c.Logger.VerboseErrf(logger.Magenta, `task: dynamic variable: '%s' result: '%s'`, v.Sh, result)
return result, nil return result, nil
} }

View File

@@ -1,38 +1,65 @@
package logger package logger
import ( import (
"fmt"
"io" "io"
"github.com/fatih/color"
) )
type PrintFunc func(io.Writer, string, ...interface{})
var (
Default PrintFunc = color.New(color.Reset).FprintfFunc()
Bold PrintFunc = color.New(color.Bold).FprintfFunc()
Blue PrintFunc = color.New(color.FgBlue, color.Bold).FprintfFunc()
Green PrintFunc = color.New(color.FgGreen, color.Bold).FprintfFunc()
Cyan PrintFunc = color.New(color.FgCyan, color.Bold).FprintfFunc()
Yellow PrintFunc = color.New(color.FgYellow, color.Bold).FprintfFunc()
Magenta PrintFunc = color.New(color.FgMagenta, color.Bold).FprintfFunc()
Red PrintFunc = color.New(color.FgRed, color.Bold).FprintfFunc()
)
// Logger is just a wrapper that prints stuff to STDOUT or STDERR,
// with optional color.
type Logger struct { type Logger struct {
Stdout io.Writer Stdout io.Writer
Stderr io.Writer Stderr io.Writer
Verbose bool Verbose bool
Color bool
} }
func (l *Logger) Outf(s string, args ...interface{}) { // Outf prints stuff to STDOUT.
func (l *Logger) Outf(print PrintFunc, s string, args ...interface{}) {
if len(args) == 0 { if len(args) == 0 {
s, args = "%s", []interface{}{s} s, args = "%s", []interface{}{s}
} }
fmt.Fprintf(l.Stdout, s+"\n", args...) if !l.Color {
print = Default
}
print(l.Stdout, s+"\n", args...)
} }
func (l *Logger) VerboseOutf(s string, args ...interface{}) { // VerboseOutf prints stuff to STDOUT if verbose mode is enabled.
func (l *Logger) VerboseOutf(print PrintFunc, s string, args ...interface{}) {
if l.Verbose { if l.Verbose {
l.Outf(s, args...) l.Outf(print, s, args...)
} }
} }
func (l *Logger) Errf(s string, args ...interface{}) { // Errf prints stuff to STDERR.
func (l *Logger) Errf(print PrintFunc, s string, args ...interface{}) {
if len(args) == 0 { if len(args) == 0 {
s, args = "%s", []interface{}{s} s, args = "%s", []interface{}{s}
} }
fmt.Fprintf(l.Stderr, s+"\n", args...) if !l.Color {
print = Default
}
print(l.Stderr, s+"\n", args...)
} }
func (l *Logger) VerboseErrf(s string, args ...interface{}) { // VerboseErrf prints stuff to STDERR if verbose mode is enabled.
func (l *Logger) VerboseErrf(print PrintFunc, s string, args ...interface{}) {
if l.Verbose { if l.Verbose {
l.Errf(s, args...) l.Errf(print, s, args...)
} }
} }

View File

@@ -20,8 +20,8 @@ func printSpaceBetweenSummaries(l *logger.Logger, i int) {
return return
} }
l.Outf("") l.Outf(logger.Default, "")
l.Outf("") l.Outf(logger.Default, "")
} }
func PrintTask(l *logger.Logger, t *taskfile.Task) { func PrintTask(l *logger.Logger, t *taskfile.Task) {
@@ -50,14 +50,14 @@ func printTaskSummary(l *logger.Logger, t *taskfile.Task) {
for i, line := range lines { for i, line := range lines {
notLastLine := i+1 < len(lines) notLastLine := i+1 < len(lines)
if notLastLine || line != "" { if notLastLine || line != "" {
l.Outf(line) l.Outf(logger.Default, line)
} }
} }
} }
func printTaskName(l *logger.Logger, t *taskfile.Task) { func printTaskName(l *logger.Logger, t *taskfile.Task) {
l.Outf("task: %s", t.Task) l.Outf(logger.Default, "task: %s", t.Task)
l.Outf("") l.Outf(logger.Default, "")
} }
func hasDescription(t *taskfile.Task) bool { func hasDescription(t *taskfile.Task) bool {
@@ -65,11 +65,11 @@ func hasDescription(t *taskfile.Task) bool {
} }
func printTaskDescription(l *logger.Logger, t *taskfile.Task) { func printTaskDescription(l *logger.Logger, t *taskfile.Task) {
l.Outf(t.Desc) l.Outf(logger.Default, t.Desc)
} }
func printNoDescriptionOrSummary(l *logger.Logger) { func printNoDescriptionOrSummary(l *logger.Logger) {
l.Outf("(task does not have description or summary)") l.Outf(logger.Default, "(task does not have description or summary)")
} }
func printTaskDependencies(l *logger.Logger, t *taskfile.Task) { func printTaskDependencies(l *logger.Logger, t *taskfile.Task) {
@@ -77,11 +77,11 @@ func printTaskDependencies(l *logger.Logger, t *taskfile.Task) {
return return
} }
l.Outf("") l.Outf(logger.Default, "")
l.Outf("dependencies:") l.Outf(logger.Default, "dependencies:")
for _, d := range t.Deps { for _, d := range t.Deps {
l.Outf(" - %s", d.Task) l.Outf(logger.Default, " - %s", d.Task)
} }
} }
@@ -90,14 +90,14 @@ func printTaskCommands(l *logger.Logger, t *taskfile.Task) {
return return
} }
l.Outf("") l.Outf(logger.Default, "")
l.Outf("commands:") l.Outf(logger.Default, "commands:")
for _, c := range t.Cmds { for _, c := range t.Cmds {
isCommand := c.Cmd != "" isCommand := c.Cmd != ""
if isCommand { if isCommand {
l.Outf(" - %s", c.Cmd) l.Outf(logger.Default, " - %s", c.Cmd)
} else { } else {
l.Outf(" - Task: %s", c.Task) l.Outf(logger.Default, " - Task: %s", c.Task)
} }
} }
} }

View File

@@ -6,7 +6,7 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/Masterminds/sprig" "github.com/go-task/slim-sprig"
) )
var ( var (

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"github.com/go-task/task/v2/internal/execext" "github.com/go-task/task/v2/internal/execext"
"github.com/go-task/task/v2/internal/logger"
"github.com/go-task/task/v2/internal/taskfile" "github.com/go-task/task/v2/internal/taskfile"
) )
@@ -22,7 +23,7 @@ func (e *Executor) areTaskPreconditionsMet(ctx context.Context, t *taskfile.Task
}) })
if err != nil { if err != nil {
e.Logger.Errf("task: %s", p.Msg) e.Logger.Errf(logger.Magenta, "task: %s", p.Msg)
return false, ErrPreconditionFailed return false, ErrPreconditionFailed
} }
} }

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"github.com/go-task/task/v2/internal/execext" "github.com/go-task/task/v2/internal/execext"
"github.com/go-task/task/v2/internal/logger"
"github.com/go-task/task/v2/internal/status" "github.com/go-task/task/v2/internal/status"
"github.com/go-task/task/v2/internal/taskfile" "github.com/go-task/task/v2/internal/taskfile"
) )
@@ -78,10 +79,10 @@ func (e *Executor) isTaskUpToDateStatus(ctx context.Context, t *taskfile.Task) (
Env: getEnviron(t), Env: getEnviron(t),
}) })
if err != nil { if err != nil {
e.Logger.VerboseOutf("task: status command %s exited non-zero: %s", s, err) e.Logger.VerboseOutf(logger.Yellow, "task: status command %s exited non-zero: %s", s, err)
return false, nil return false, nil
} }
e.Logger.VerboseOutf("task: status command %s exited zero", s) e.Logger.VerboseOutf(logger.Yellow, "task: status command %s exited zero", s)
} }
return true, nil return true, nil
} }

23
task.go
View File

@@ -41,6 +41,7 @@ type Executor struct {
Silent bool Silent bool
Dry bool Dry bool
Summary bool Summary bool
Color bool
Stdin io.Reader Stdin io.Reader
Stdout io.Writer Stdout io.Writer
@@ -114,6 +115,7 @@ func (e *Executor) Setup() error {
Stdout: e.Stdout, Stdout: e.Stdout,
Stderr: e.Stderr, Stderr: e.Stderr,
Verbose: e.Verbose, Verbose: e.Verbose,
Color: e.Color,
} }
v, err := strconv.ParseFloat(e.Taskfile.Version, 64) v, err := strconv.ParseFloat(e.Taskfile.Version, 64)
@@ -128,8 +130,13 @@ func (e *Executor) Setup() error {
if v < 1 { if v < 1 {
return fmt.Errorf(`task: Taskfile version should be greater or equal to v1`) return fmt.Errorf(`task: Taskfile version should be greater or equal to v1`)
} }
if v > 2.6 { if v > 3.0 {
return fmt.Errorf(`task: Taskfile versions greater than v2.6 not implemented in the version of Task`) return fmt.Errorf(`task: Taskfile versions greater than v3.0 not implemented in the version of Task`)
}
// Color available only on v3
if v < 3 {
e.Logger.Color = false
} }
if v < 2 { if v < 2 {
@@ -228,24 +235,24 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
if upToDate && preCondMet { if upToDate && preCondMet {
if !e.Silent { if !e.Silent {
e.Logger.Errf(`task: Task "%s" is up to date`, t.Task) e.Logger.Errf(logger.Magenta, `task: Task "%s" is up to date`, t.Task)
} }
return nil return nil
} }
} }
if err := e.mkdir(t); err != nil { if err := e.mkdir(t); err != nil {
e.Logger.Errf("task: cannot make directory %q: %v", t.Dir, err) e.Logger.Errf(logger.Red, "task: cannot make directory %q: %v", t.Dir, err)
} }
for i := range t.Cmds { for i := range t.Cmds {
if err := e.runCommand(ctx, t, call, i); err != nil { if err := e.runCommand(ctx, t, call, i); err != nil {
if err2 := e.statusOnError(t); err2 != nil { if err2 := e.statusOnError(t); err2 != nil {
e.Logger.VerboseErrf("task: error cleaning status on error: %v", err2) e.Logger.VerboseErrf(logger.Yellow, "task: error cleaning status on error: %v", err2)
} }
if execext.IsExitError(err) && t.IgnoreError { if execext.IsExitError(err) && t.IgnoreError {
e.Logger.VerboseErrf("task: task error ignored: %v", err) e.Logger.VerboseErrf(logger.Yellow, "task: task error ignored: %v", err)
continue continue
} }
@@ -302,7 +309,7 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
return nil return nil
case cmd.Cmd != "": case cmd.Cmd != "":
if e.Verbose || (!cmd.Silent && !t.Silent && !e.Silent) { if e.Verbose || (!cmd.Silent && !t.Silent && !e.Silent) {
e.Logger.Errf(cmd.Cmd) e.Logger.Errf(logger.Green, "task: %s", cmd.Cmd)
} }
if e.Dry { if e.Dry {
@@ -333,7 +340,7 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
Stderr: stdErr, Stderr: stdErr,
}) })
if execext.IsExitError(err) && cmd.IgnoreError { if execext.IsExitError(err) && cmd.IgnoreError {
e.Logger.VerboseErrf("task: command error ignored: %v", err) e.Logger.VerboseErrf(logger.Yellow, "task: command error ignored: %v", err)
return nil return nil
} }
return err return err

View File

@@ -532,7 +532,7 @@ func TestDry(t *testing.T) {
assert.NoError(t, e.Setup()) assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"})) assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"}))
assert.Equal(t, "touch file.txt", strings.TrimSpace(buff.String())) assert.Equal(t, "task: touch file.txt", strings.TrimSpace(buff.String()))
if _, err := os.Stat(file); err == nil { if _, err := os.Stat(file); err == nil {
t.Errorf("File should not exist %s", file) t.Errorf("File should not exist %s", file)
} }

View File

@@ -8,6 +8,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/go-task/task/v2/internal/logger"
"github.com/go-task/task/v2/internal/taskfile" "github.com/go-task/task/v2/internal/taskfile"
"github.com/mattn/go-zglob" "github.com/mattn/go-zglob"
"github.com/radovskyb/watcher" "github.com/radovskyb/watcher"
@@ -24,14 +25,14 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
for i, c := range calls { for i, c := range calls {
tasks[i] = c.Task tasks[i] = c.Task
} }
e.Logger.Errf("task: Started watching for tasks: %s", strings.Join(tasks, ", ")) e.Logger.Errf(logger.Green, "task: Started watching for tasks: %s", strings.Join(tasks, ", "))
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
for _, c := range calls { for _, c := range calls {
c := c c := c
go func() { go func() {
if err := e.RunTask(ctx, c); err != nil && !isContextError(err) { if err := e.RunTask(ctx, c); err != nil && !isContextError(err) {
e.Logger.Errf("%v", err) e.Logger.Errf(logger.Red, "%v", err)
} }
}() }()
} }
@@ -49,7 +50,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
for { for {
select { select {
case event := <-w.Event: case event := <-w.Event:
e.Logger.VerboseErrf("task: received watch event: %v", event) e.Logger.VerboseErrf(logger.Magenta, "task: received watch event: %v", event)
cancel() cancel()
ctx, cancel = context.WithCancel(context.Background()) ctx, cancel = context.WithCancel(context.Background())
@@ -57,7 +58,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
c := c c := c
go func() { go func() {
if err := e.RunTask(ctx, c); err != nil && !isContextError(err) { if err := e.RunTask(ctx, c); err != nil && !isContextError(err) {
e.Logger.Errf("%v", err) e.Logger.Errf(logger.Red, "%v", err)
} }
}() }()
} }
@@ -68,7 +69,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
w.TriggerEvent(watcher.Remove, nil) w.TriggerEvent(watcher.Remove, nil)
}() }()
default: default:
e.Logger.Errf("%v", err) e.Logger.Errf(logger.Red, "%v", err)
} }
case <-w.Closed: case <-w.Closed:
cancel() cancel()
@@ -81,7 +82,7 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
// re-register each second because we can have new files // re-register each second because we can have new files
for { for {
if err := e.registerWatchedFiles(w, calls...); err != nil { if err := e.registerWatchedFiles(w, calls...); err != nil {
e.Logger.Errf("%v", err) e.Logger.Errf(logger.Red, "%v", err)
} }
time.Sleep(time.Second) time.Sleep(time.Second)
} }