package task import ( "context" "os" "path/filepath" "time" "github.com/go-task/task/execext" "github.com/mattn/go-zglob" ) func (t *Task) isUpToDate(ctx context.Context) (bool, error) { if len(t.Status) > 0 { return t.isUpToDateStatus(ctx) } return t.isUpToDateTimestamp(ctx) } func (t *Task) isUpToDateStatus(ctx context.Context) (bool, error) { for _, s := range t.Status { err := execext.RunCommand(&execext.RunCommandOptions{ Context: ctx, Command: s, Dir: t.Dir, Env: t.getEnviron(), }) if err != nil { return false, nil } } return true, nil } func (t *Task) isUpToDateTimestamp(ctx context.Context) (bool, error) { if len(t.Sources) == 0 || len(t.Generates) == 0 { return false, nil } sourcesMaxTime, err := getPatternsMaxTime(t.Dir, t.Sources) if err != nil || sourcesMaxTime.IsZero() { return false, nil } generatesMinTime, err := getPatternsMinTime(t.Dir, t.Generates) if err != nil || generatesMinTime.IsZero() { return false, nil } return !generatesMinTime.Before(sourcesMaxTime), nil } func getPatternsMinTime(dir string, patterns []string) (m time.Time, err error) { for _, p := range patterns { if !filepath.IsAbs(p) { p = filepath.Join(dir, p) } mp, err := getPatternMinTime(p) if err != nil { return time.Time{}, err } m = minTime(m, mp) } return } func getPatternsMaxTime(dir string, patterns []string) (m time.Time, err error) { for _, p := range patterns { if !filepath.IsAbs(p) { p = filepath.Join(dir, p) } mp, err := getPatternMaxTime(p) if err != nil { return time.Time{}, err } m = maxTime(m, mp) } return } func getPatternMinTime(pattern string) (m time.Time, err error) { files, err := zglob.Glob(pattern) if err != nil { return time.Time{}, err } for _, f := range files { info, err := os.Stat(f) if err != nil { return time.Time{}, err } m = minTime(m, info.ModTime()) } return } func getPatternMaxTime(pattern string) (m time.Time, err error) { files, err := zglob.Glob(pattern) if err != nil { return time.Time{}, err } for _, f := range files { info, err := os.Stat(f) if err != nil { return time.Time{}, err } m = maxTime(m, info.ModTime()) } return } func minTime(a, b time.Time) time.Time { if !a.IsZero() && a.Before(b) { return a } return b } func maxTime(a, b time.Time) time.Time { if a.After(b) { return a } return b }