aboutsummaryrefslogtreecommitdiff
path: root/internal/engine/session.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-16 01:34:45 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-16 01:34:45 +0200
commitecfaeabf2a92e26c6a521d5fac404a0fff6263b6 (patch)
tree4147dd6809a45fe5b773447352354dbee2295900 /internal/engine/session.go
parentbe4b1275c76b9cad984dfafaa8023db94eb3eecf (diff)
downloadkrino-ecfaeabf2a92e26c6a521d5fac404a0fff6263b6.tar.gz
krino-ecfaeabf2a92e26c6a521d5fac404a0fff6263b6.zip
milestone 1 review: claims span the run, explain's chain is opt-in and its own, overrides keyed by clean path, splice and enum guards
Diffstat (limited to 'internal/engine/session.go')
-rw-r--r--internal/engine/session.go33
1 files changed, 21 insertions, 12 deletions
diff --git a/internal/engine/session.go b/internal/engine/session.go
index 33b6a76..d79c364 100644
--- a/internal/engine/session.go
+++ b/internal/engine/session.go
@@ -25,6 +25,7 @@ type Session struct {
j *journal.Writer
run string
claims *plan.Claims
+ landed []string // where this run's applied files ended up, in order
dry bool
}
@@ -90,26 +91,34 @@ func (s *Session) Plan(ctx context.Context, d *Dir) (*DirPlan, error) {
return s.e.Plan(ctx, d, s.claims)
}
-// Apply carries out the approved files of dp and logs the run's steps. A
-// real run applies each directory before the next is planned, so afterwards
-// the disk is the truth for the next one: only the paths this directory's
-// files ended up at stay claimed, which keeps a later (on-conflict
-// overwrite) from displacing this run's own result (spec §7.4). A dry
-// session keeps every claim, since it applies nothing.
+// Apply carries out the approved files of dp and logs the run's steps,
+// remembering where they ended up for FinishDirectory.
func (s *Session) Apply(ctx context.Context, dp *DirPlan, approved map[string]bool) (*ApplyResult, error) {
if err := s.OpenLog(); err != nil {
return nil, err
}
res, err := s.e.Apply(ctx, dp, approved, s.j, s.run)
- if !s.dry {
- s.claims = plan.NewClaims()
- for _, p := range landedAt(res) {
- s.claims.Claim(p)
- }
- }
+ s.landed = append(s.landed, landedAt(res)...)
return res, err
}
+// FinishDirectory ends one directory of a real run: the disk is now the
+// truth for the next one, so the claims start again from where this run's
+// files have actually ended up - every directory's, not just this one's
+// (spec §7.4, plan 13 review F3). A path this directory planned but did not
+// apply is free again; a path it did apply stays protected from a later
+// (on-conflict overwrite) for the rest of the run, even across a directory
+// that applies nothing. A dry run applies nothing and keeps every claim.
+func (s *Session) FinishDirectory() {
+ if s.dry {
+ return
+ }
+ s.claims = plan.NewClaims()
+ for _, p := range s.landed {
+ s.claims.Claim(p)
+ }
+}
+
// landedAt is where res's files ended up: each copy, and the last place a
// move or rename put a file - not a path it passed through and left, and
// nothing at all for a file deleted for good.