package status import ( "os" "time" ) // Timestamp checks if any source change compared with the generated files, // using file modifications timestamps. type Timestamp struct { Dir string Sources []string Generates []string } // IsUpToDate implements the Checker interface func (t *Timestamp) IsUpToDate() (bool, error) { if len(t.Sources) == 0 || len(t.Generates) == 0 { return false, nil } sources, err := globs(t.Dir, t.Sources) if err != nil { return false, nil } generates, err := globs(t.Dir, t.Generates) if err != nil { return false, nil } sourcesMaxTime, err := getMaxTime(sources...) if err != nil || sourcesMaxTime.IsZero() { return false, nil } generatesMinTime, err := getMinTime(generates...) if err != nil || generatesMinTime.IsZero() { return false, nil } return !generatesMinTime.Before(sourcesMaxTime), nil } func getMinTime(files ...string) (time.Time, error) { var t time.Time for _, f := range files { info, err := os.Stat(f) if err != nil { return time.Time{}, err } t = minTime(t, info.ModTime()) } return t, nil } func getMaxTime(files ...string) (time.Time, error) { var t time.Time for _, f := range files { info, err := os.Stat(f) if err != nil { return time.Time{}, err } t = maxTime(t, info.ModTime()) } return t, nil } 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 } // OnError implements the Checker interface func (*Timestamp) OnError() error { return nil }