2017-09-16 16:44:13 +02:00
|
|
|
package status
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/md5"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2017-09-30 19:40:11 +02:00
|
|
|
"regexp"
|
2017-09-16 16:44:13 +02:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Checksum validades if a task is up to date by calculating its source
|
|
|
|
// files checksum
|
|
|
|
type Checksum struct {
|
2022-07-08 19:40:10 +02:00
|
|
|
TempDir string
|
2021-01-07 16:36:09 +02:00
|
|
|
TaskDir string
|
2019-08-01 05:51:27 +02:00
|
|
|
Task string
|
|
|
|
Sources []string
|
|
|
|
Generates []string
|
|
|
|
Dry bool
|
2017-09-16 16:44:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// IsUpToDate implements the Checker interface
|
|
|
|
func (c *Checksum) IsUpToDate() (bool, error) {
|
2019-09-09 03:51:56 +02:00
|
|
|
if len(c.Sources) == 0 {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2017-10-01 20:05:09 +02:00
|
|
|
checksumFile := c.checksumFilePath()
|
2017-09-16 16:44:13 +02:00
|
|
|
|
2021-12-21 04:00:34 +02:00
|
|
|
data, _ := os.ReadFile(checksumFile)
|
2017-09-16 16:44:13 +02:00
|
|
|
oldMd5 := strings.TrimSpace(string(data))
|
|
|
|
|
2021-01-07 16:36:09 +02:00
|
|
|
sources, err := globs(c.TaskDir, c.Sources)
|
2017-09-16 16:44:13 +02:00
|
|
|
if err != nil {
|
2019-08-21 06:42:19 +02:00
|
|
|
return false, err
|
2019-08-01 05:51:27 +02:00
|
|
|
}
|
2019-08-21 06:42:19 +02:00
|
|
|
|
2017-09-16 16:44:13 +02:00
|
|
|
newMd5, err := c.checksum(sources...)
|
|
|
|
if err != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
2019-02-09 14:41:19 +02:00
|
|
|
if !c.Dry {
|
2022-07-08 19:40:10 +02:00
|
|
|
_ = os.MkdirAll(filepath.Join(c.TempDir, "checksum"), 0755)
|
2021-12-21 04:00:34 +02:00
|
|
|
if err = os.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
2019-02-09 14:41:19 +02:00
|
|
|
return false, err
|
|
|
|
}
|
2017-09-16 16:44:13 +02:00
|
|
|
}
|
2019-08-21 06:35:16 +02:00
|
|
|
|
2019-08-25 21:29:32 +02:00
|
|
|
if len(c.Generates) > 0 {
|
|
|
|
// For each specified 'generates' field, check whether the files actually exist
|
2019-08-21 06:35:16 +02:00
|
|
|
for _, g := range c.Generates {
|
2021-05-08 22:02:08 +02:00
|
|
|
generates, err := Glob(c.TaskDir, g)
|
2019-08-25 21:29:32 +02:00
|
|
|
if os.IsNotExist(err) {
|
2019-08-21 06:35:16 +02:00
|
|
|
return false, nil
|
|
|
|
}
|
2019-08-25 21:29:32 +02:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
2019-08-21 06:35:16 +02:00
|
|
|
if len(generates) == 0 {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-16 16:44:13 +02:00
|
|
|
return oldMd5 == newMd5, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Checksum) checksum(files ...string) (string, error) {
|
|
|
|
h := md5.New()
|
|
|
|
|
|
|
|
for _, f := range files {
|
2019-08-21 06:34:58 +02:00
|
|
|
// also sum the filename, so checksum changes for renaming a file
|
|
|
|
if _, err := io.Copy(h, strings.NewReader(filepath.Base(f))); err != nil {
|
2017-09-16 16:44:13 +02:00
|
|
|
return "", err
|
|
|
|
}
|
2019-08-21 06:34:58 +02:00
|
|
|
f, err := os.Open(f)
|
2017-09-19 19:03:24 +02:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2017-11-02 14:31:34 +02:00
|
|
|
if _, err = io.Copy(h, f); err != nil {
|
2017-09-16 16:44:13 +02:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf("%x", h.Sum(nil)), nil
|
|
|
|
}
|
|
|
|
|
2019-08-25 19:30:00 +02:00
|
|
|
// Value implements the Checker Interface
|
2019-08-25 22:16:59 +02:00
|
|
|
func (c *Checksum) Value() (interface{}, error) {
|
2019-06-11 20:49:37 +02:00
|
|
|
return c.checksum()
|
|
|
|
}
|
|
|
|
|
2017-10-01 20:05:09 +02:00
|
|
|
// OnError implements the Checker interface
|
|
|
|
func (c *Checksum) OnError() error {
|
2020-05-31 20:48:23 +02:00
|
|
|
if len(c.Sources) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
2017-10-01 20:05:09 +02:00
|
|
|
return os.Remove(c.checksumFilePath())
|
|
|
|
}
|
|
|
|
|
2019-08-25 19:30:00 +02:00
|
|
|
// Kind implements the Checker Interface
|
2019-09-14 22:54:41 +02:00
|
|
|
func (*Checksum) Kind() string {
|
2019-08-25 19:30:00 +02:00
|
|
|
return "checksum"
|
|
|
|
}
|
|
|
|
|
2017-10-01 20:05:09 +02:00
|
|
|
func (c *Checksum) checksumFilePath() string {
|
2022-07-08 19:40:10 +02:00
|
|
|
return filepath.Join(c.TempDir, "checksum", c.normalizeFilename(c.Task))
|
2017-10-01 20:05:09 +02:00
|
|
|
}
|
|
|
|
|
2017-09-30 19:40:11 +02:00
|
|
|
var checksumFilenameRegexp = regexp.MustCompile("[^A-z0-9]")
|
|
|
|
|
|
|
|
// replaces invalid caracters on filenames with "-"
|
|
|
|
func (*Checksum) normalizeFilename(f string) string {
|
|
|
|
return checksumFilenameRegexp.ReplaceAllString(f, "-")
|
|
|
|
}
|