diff --git a/internal/fingerprint/sources_checksum.go b/internal/fingerprint/sources_checksum.go index 16a98c1640..b2376e384c 100644 --- a/internal/fingerprint/sources_checksum.go +++ b/internal/fingerprint/sources_checksum.go @@ -15,7 +15,7 @@ import ( ) // ChecksumChecker validates if a task is up to date by calculating its source -// files checksum +// and destination (generates) files checksum type ChecksumChecker struct { tempDir string dry bool @@ -92,10 +92,15 @@ func (c *ChecksumChecker) checksum(t *ast.Task) (string, error) { if err != nil { return "", err } + generates, err := Globs(t.Dir, t.Generates) + if err != nil { + return "", err + } + files := append(sources, generates...) h := xxh3.New() buf := make([]byte, 128*1024) - for _, f := range sources { + for _, f := range files { // also sum the filename, so checksum changes for renaming a file if _, err := io.CopyBuffer(h, strings.NewReader(filepath.Base(f)), buf); err != nil { return "", err diff --git a/internal/fingerprint/task.go b/internal/fingerprint/task.go index 2b48e114c9..0377d999ed 100644 --- a/internal/fingerprint/task.go +++ b/internal/fingerprint/task.go @@ -130,3 +130,49 @@ func IsTaskUpToDate( // i.e. it is never considered "up-to-date" return false, nil } + +func FinalizeTask( + ctx context.Context, + t *ast.Task, + opts ...CheckerOption, +) error { + var err error + + // Default config + config := &CheckerConfig{ + method: "none", + tempDir: "", + dry: false, + logger: nil, + statusChecker: nil, + sourcesChecker: nil, + } + + // Apply functional options + for _, opt := range opts { + opt(config) + } + + // If no status checker was given, set up the default one + if config.statusChecker == nil { + config.statusChecker = NewStatusChecker(config.logger) + } + + // If no sources checker was given, set up the default one + if config.sourcesChecker == nil { + config.sourcesChecker, err = NewSourcesChecker(config.method, config.tempDir, config.dry) + if err != nil { + return err + } + } + + // If sources and generates are set, regenerate the checksum / timestamp file + if len(t.Sources) != 0 && len(t.Generates) != 0 { + _, err = config.sourcesChecker.IsUpToDate(t) + if err != nil { + return err + } + } + + return nil +} diff --git a/task.go b/task.go index 0b762c6140..31829d65e5 100644 --- a/task.go +++ b/task.go @@ -236,6 +236,26 @@ func (e *Executor) RunTask(ctx context.Context, call *Call) error { return &errors.TaskRunError{TaskName: t.Task, Err: err} } } + + if !skipFingerprinting { + // Get the fingerprinting method to use + method := e.Taskfile.Method + if t.Method != "" { + method = t.Method + } + + // Finalize the task fingerprinting + err := fingerprint.FinalizeTask(ctx, t, + fingerprint.WithMethod(method), + fingerprint.WithTempDir(e.TempDir.Fingerprint), + fingerprint.WithDry(e.Dry), + fingerprint.WithLogger(e.Logger), + ) + if err != nil { + return err + } + } + e.Logger.VerboseErrf(logger.Magenta, "task: %q finished\n", call.Task) return nil })