Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change save order status upToDate #1507

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/fingerprint/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type StatusCheckable interface {
// SourcesCheckable defines any type that can check if the sources of a task are up-to-date.
type SourcesCheckable interface {
IsUpToDate(t *ast.Task) (bool, error)
Update(t *ast.Task) error
Value(t *ast.Task) (any, error)
OnError(t *ast.Task) error
Kind() string
Expand Down
23 changes: 16 additions & 7 deletions internal/fingerprint/sources_checksum.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,6 @@ func (checker *ChecksumChecker) IsUpToDate(t *ast.Task) (bool, error) {
return false, nil
}

if !checker.dry && oldHash != newHash {
_ = os.MkdirAll(filepathext.SmartJoin(checker.tempDir, "checksum"), 0o755)
if err = os.WriteFile(checksumFile, []byte(newHash+"\n"), 0o644); err != nil {
return false, err
}
}

if len(t.Generates) > 0 {
// For each specified 'generates' field, check whether the files actually exist
for _, g := range t.Generates {
Expand All @@ -72,6 +65,22 @@ func (checker *ChecksumChecker) IsUpToDate(t *ast.Task) (bool, error) {
return oldHash == newHash, nil
}

func (checker *ChecksumChecker) Update(t *ast.Task) error {
if !checker.dry {
if len(t.Sources) == 0 {
return nil
}
checksumFile := checker.checksumFilePath(t)
newHash, err := checker.checksum(t)
if err != nil {
return nil
}
_ = os.MkdirAll(filepathext.SmartJoin(checker.tempDir, "checksum"), 0o755)
return os.WriteFile(checksumFile, []byte(newHash+"\n"), 0o644)
}
return nil
}

func (checker *ChecksumChecker) Value(t *ast.Task) (any, error) {
return checker.checksum(t)
}
Expand Down
4 changes: 4 additions & 0 deletions internal/fingerprint/sources_none.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ func (NoneChecker) IsUpToDate(t *ast.Task) (bool, error) {
return false, nil
}

func (NoneChecker) Update(t *ast.Task) error {
return nil
}

func (NoneChecker) Value(t *ast.Task) (any, error) {
return "", nil
}
Expand Down
50 changes: 30 additions & 20 deletions internal/fingerprint/sources_timestamp.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,7 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) {
_, err = os.Stat(timestampFile)
if err == nil {
generates = append(generates, timestampFile)
} else {
// Create the timestamp file for the next execution when the file does not exist.
if !checker.dry {
if err := os.MkdirAll(filepath.Dir(timestampFile), 0o755); err != nil {
return false, err
}
f, err := os.Create(timestampFile)
if err != nil {
return false, err
}
f.Close()
}
}

taskTime := time.Now()

// Compare the time of the generates and sources. If the generates are old, the task will be executed.

// Get the max time of the generates.
Expand All @@ -74,14 +59,39 @@ func (checker *TimestampChecker) IsUpToDate(t *ast.Task) (bool, error) {
return false, nil
}

// Modify the metadata of the file to the the current time.
return !shouldUpdate, nil
}

func (checker *TimestampChecker) Update(t *ast.Task) error {
if !checker.dry {
if err := os.Chtimes(timestampFile, taskTime, taskTime); err != nil {
return false, err
generates, err := Globs(t.Dir, t.Generates)
if err != nil {
return nil
}
if len(generates) == 0 {
return nil
}
}

return !shouldUpdate, nil
timestampFile := checker.timestampFilePath(t)
_, err = os.Stat(timestampFile)
if err == nil {
// Modify the metadata of the file to the the current time.
taskTime := time.Now()
return os.Chtimes(timestampFile, taskTime, taskTime)
}

// Compare the time of the generates and sources. If the generates are old, the task will be executed.
err = os.MkdirAll(filepath.Dir(timestampFile), 0o755)
if err != nil {
return err
}
f, err := os.Create(timestampFile)
if err != nil {
return err
}
return f.Close()
}
return nil
}

func (checker *TimestampChecker) Kind() string {
Expand Down
36 changes: 31 additions & 5 deletions internal/fingerprint/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,11 @@ func WithSourcesChecker(checker SourcesCheckable) CheckerOption {
}
}

func IsTaskUpToDate(
func getConfig(
ctx context.Context,
t *ast.Task,
opts ...CheckerOption,
) (bool, error) {
var statusUpToDate bool
var sourcesUpToDate bool
) (*CheckerConfig, error) {
var err error

// Default config
Expand All @@ -88,13 +86,29 @@ func IsTaskUpToDate(
if config.sourcesChecker == nil {
config.sourcesChecker, err = NewSourcesChecker(config.method, config.tempDir, config.dry)
if err != nil {
return false, err
return nil, err
}
}
return config, nil
}

func IsTaskUpToDate(
ctx context.Context,
t *ast.Task,
opts ...CheckerOption,
) (bool, error) {
var statusUpToDate bool
var sourcesUpToDate bool
var err error

statusIsSet := len(t.Status) != 0
sourcesIsSet := len(t.Sources) != 0

config, err := getConfig(ctx, t, opts...)
if err != nil {
return false, err
}

// If status is set, check if it is up-to-date
if statusIsSet {
statusUpToDate, err = config.statusChecker.IsUpToDate(ctx, t)
Expand Down Expand Up @@ -130,3 +144,15 @@ func IsTaskUpToDate(
// i.e. it is never considered "up-to-date"
return false, nil
}

func UpdateTask(
ctx context.Context,
t *ast.Task,
opts ...CheckerOption,
) error {
config, err := getConfig(ctx, t, opts...)
if err != nil {
return err
}
return config.sourcesChecker.Update(t)
}
4 changes: 4 additions & 0 deletions internal/mocks/sources_checkable.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion task.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ func (e *Executor) RunTask(ctx context.Context, call ast.Call) error {
}

skipFingerprinting := e.ForceAll || (!call.Indirect && e.Force)
var method string
if !skipFingerprinting {
if err := ctx.Err(); err != nil {
return err
Expand All @@ -215,7 +216,7 @@ func (e *Executor) RunTask(ctx context.Context, call ast.Call) error {
}

// Get the fingerprinting method to use
method := e.Taskfile.Method
method = e.Taskfile.Method
if t.Method != "" {
method = t.Method
}
Expand Down Expand Up @@ -265,6 +266,17 @@ func (e *Executor) RunTask(ctx context.Context, call ast.Call) error {
return &errors.TaskRunError{TaskName: t.Task, Err: err}
}
}
if !skipFingerprinting {
err := fingerprint.UpdateTask(ctx, t,
fingerprint.WithMethod(method),
fingerprint.WithTempDir(e.TempDir),
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
})
Expand Down
4 changes: 0 additions & 4 deletions task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,6 @@ func TestStatus(t *testing.T) {
assert.Equal(t, "task: [gen-foo] touch foo.txt", strings.TrimSpace(buff.String()))
buff.Reset()

// sources: not up-to-date
require.NoError(t, e.Run(context.Background(), ast.Call{Task: "gen-bar"}))
assert.Equal(t, "task: [gen-bar] touch bar.txt", strings.TrimSpace(buff.String()))
buff.Reset()
// all: up-to-date
require.NoError(t, e.Run(context.Background(), ast.Call{Task: "gen-bar"}))
assert.Equal(t, `task: Task "gen-bar" is up to date`, strings.TrimSpace(buff.String()))
Expand Down
Loading