1
0
mirror of https://github.com/go-task/task.git synced 2025-04-11 11:41:56 +02:00

Export Time Struct to Template

This commit is contained in:
Stephen Prater 2019-08-25 13:16:59 -07:00
parent cb6fe4bb59
commit a1aec8178a
11 changed files with 40 additions and 26 deletions

View File

@ -356,6 +356,11 @@ Two special variables `{{.CHECKSUM}}` and `{{.TIMESTAMP}}` are available
for interpolation within `status` commands, depending on the method assigned
to fingerprint the sources. Only `source` globs are fingerprinted.
Note that the `{{.TIMESTAMP}}` variable is a "live" Go time struct, and can be
formatted using any of the methods that `Time` responds to.
See [the Go Time documentation](https://golang.org/pkg/time/) for more information.
You can use `--force` or `-f` if you want to force a task to run even when
up-to-date.

View File

@ -74,7 +74,7 @@ func (c *Checksum) checksum(files ...string) (string, error) {
}
// Value implements the Checker Interface
func (c *Checksum) Value() (string, error) {
func (c *Checksum) Value() (interface{}, error) {
return c.checksum()
}

View File

@ -9,7 +9,7 @@ func (None) IsUpToDate() (bool, error) {
}
// Value implements the Checker interface
func (None) Value() (string, error) {
func (None) Value() (interface{}, error) {
return "", nil
}

View File

@ -9,7 +9,7 @@ var (
// Checker is an interface that checks if the status is up-to-date
type Checker interface {
IsUpToDate() (bool, error)
Value() (string, error)
Value() (interface{}, error)
OnError() error
Kind() string
}

View File

@ -1,7 +1,6 @@
package status
import (
"fmt"
"os"
"time"
)
@ -47,22 +46,22 @@ func (t *Timestamp) Kind() string {
}
// Value implements the Checker Interface
func (t *Timestamp) Value() (string, error) {
func (t *Timestamp) Value() (interface{}, error) {
sources, err := glob(t.Dir, t.Sources)
if err != nil {
return "<no value>", err
return time.Now(), err
}
sourcesMaxTime, err := getMaxTime(sources...)
if err != nil {
return "<no value>", err
return time.Now(), err
}
if sourcesMaxTime.IsZero() {
return "0", nil
return time.Unix(0, 0), nil
}
return fmt.Sprintf("%d", sourcesMaxTime.Unix()), nil
return sourcesMaxTime, nil
}
func getMinTime(files ...string) (time.Time, error) {

View File

@ -13,17 +13,22 @@ var (
// Vars is a string[string] variables map.
type Vars map[string]Var
// ToStringMap converts Vars to a string map containing only the static
// ToCacheMap converts Vars to a map containing only the static
// variables
func (vs Vars) ToStringMap() (m map[string]string) {
m = make(map[string]string, len(vs))
func (vs Vars) ToCacheMap() (m map[string](interface{})) {
m = make(map[string](interface{}), len(vs))
for k, v := range vs {
if v.Sh != "" {
// Dynamic variable is not yet resolved; trigger
// <no value> to be used in templates.
continue
}
m[k] = v.Static
if v.Live != nil {
m[k] = v.Live
} else {
m[k] = v.Static
}
}
return
}
@ -31,6 +36,7 @@ func (vs Vars) ToStringMap() (m map[string]string) {
// Var represents either a static or dynamic variable.
type Var struct {
Static string
Live interface{}
Sh string
}

View File

@ -14,12 +14,12 @@ import (
type Templater struct {
Vars taskfile.Vars
strMap map[string]string
err error
cacheMap map[string](interface{})
err error
}
func (r *Templater) RefreshStringMap() {
r.strMap = r.Vars.ToStringMap()
func (r *Templater) RefreshCacheMap() {
r.cacheMap = r.Vars.ToCacheMap()
}
func (r *Templater) Replace(str string) string {
@ -33,12 +33,12 @@ func (r *Templater) Replace(str string) string {
return ""
}
if r.strMap == nil {
r.strMap = r.Vars.ToStringMap()
if r.cacheMap == nil {
r.cacheMap = r.Vars.ToCacheMap()
}
var b bytes.Buffer
if err = templ.Execute(&b, r.strMap); err != nil {
if err = templ.Execute(&b, r.cacheMap); err != nil {
r.err = err
return ""
}
@ -66,6 +66,7 @@ func (r *Templater) ReplaceVars(vars taskfile.Vars) taskfile.Vars {
for k, v := range vars {
new[k] = taskfile.Var{
Static: r.Replace(v.Static),
Live: v.Live,
Sh: r.Replace(v.Sh),
}
}

View File

@ -355,7 +355,7 @@ func getEnviron(t *taskfile.Task) []string {
}
environ := os.Environ()
for k, v := range t.Env.ToStringMap() {
for k, v := range t.Env.ToCacheMap() {
environ = append(environ, fmt.Sprintf("%s=%s", k, v))
}
return environ

View File

@ -423,8 +423,10 @@ func TestStatusChecksum(t *testing.T) {
buff.Reset()
inf, _ := os.Stat(filepath.Join(dir, "source.txt"))
ts := fmt.Sprintf("%d", inf.ModTime().Unix())
tf := fmt.Sprintf("%s", inf.ModTime())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build-with-timestamp"}))
assert.Contains(t, buff.String(), ts)
assert.Contains(t, buff.String(), tf)
}
func TestInit(t *testing.T) {

View File

@ -19,4 +19,5 @@ build-with-timestamp:
sources:
- ./source.txt
status:
- echo "{{.TIMESTAMP}}"
- echo '{{.TIMESTAMP.Unix }}'
- echo '{{.TIMESTAMP}}'

View File

@ -106,10 +106,10 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
return nil, err
}
vars[strings.ToUpper(checker.Kind())] = taskfile.Var{Static: value}
// Adding new static variables, requires us to refresh the templaters
// cache of the the static values
r.RefreshStringMap()
vars[strings.ToUpper(checker.Kind())] = taskfile.Var{Live: value}
// Adding new variables, requires us to refresh the templaters
// cache of the the values manually
r.RefreshCacheMap()
new.Status = r.ReplaceSlice(origTask.Status)
}