aboutsummaryrefslogtreecommitdiff
path: root/gui/internal/model/plan.go
diff options
context:
space:
mode:
Diffstat (limited to 'gui/internal/model/plan.go')
-rw-r--r--gui/internal/model/plan.go25
1 files changed, 25 insertions, 0 deletions
diff --git a/gui/internal/model/plan.go b/gui/internal/model/plan.go
index ccbf17b..c3e9654 100644
--- a/gui/internal/model/plan.go
+++ b/gui/internal/model/plan.go
@@ -7,6 +7,7 @@ package model
import (
"context"
+ "errors"
"fmt"
"sort"
"time"
@@ -50,8 +51,24 @@ type PlanTab struct {
sess *engine.Session
dp *engine.DirPlan
lock *lock.Lock
+
+ // applying is set while Apply is in flight. Close must refuse then:
+ // releasing the lock and closing the log under a running apply moves
+ // files the log never records, so undo cannot see them, and unlocks a
+ // directory krino is still working in. The window can reach Close from
+ // several places while an apply runs - saving rules or settings, adding
+ // a directory, closing the window - so the refusal lives here rather
+ // than in whichever of them remembers.
+ applying bool
+
+ // testBeforeApply, when set, is called just before the engine's Apply
+ // begins, so a test can act while the apply is in flight.
+ testBeforeApply func()
}
+// ErrApplying is returned by Close while an apply is still running.
+var ErrApplying = errors.New("krino is still applying this plan")
+
// Counts is the plan's summary line.
type Counts struct {
Scanned, Acting, Excluded, Skipped, Unmatched, Warned int
@@ -95,6 +112,9 @@ func (t *PlanTab) Run() string { return t.sess.Run() }
// Close releases the directory's lock and ends the run, which Apply also
// does once the plan is history. Closing twice is not an error.
func (t *PlanTab) Close() error {
+ if t.applying {
+ return ErrApplying
+ }
if t.lock == nil {
return nil
}
@@ -303,7 +323,12 @@ func (t *PlanTab) Apply(ctx context.Context) (*engine.ApplyResult, error) {
approved[r.Rel] = true
}
}
+ t.applying = true
+ if t.testBeforeApply != nil {
+ t.testBeforeApply()
+ }
res, err := t.sess.Apply(ctx, t.dp, approved)
+ t.applying = false
t.Applied = true
// An applied plan is history: the run is over and the directory free
// again, without closing the window (GUI design ยง3).