aboutsummaryrefslogtreecommitdiff
path: root/internal/engine/apply.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/engine/apply.go')
-rw-r--r--internal/engine/apply.go40
1 files changed, 23 insertions, 17 deletions
diff --git a/internal/engine/apply.go b/internal/engine/apply.go
index 1e59aa1..e2d4db8 100644
--- a/internal/engine/apply.go
+++ b/internal/engine/apply.go
@@ -118,6 +118,11 @@ func (e *Engine) applyFile(ctx context.Context, dirName string, c plan.Chain, ap
return unloggedStep(rel, c.Steps[i], sr, err)
}
return nil
+ }, func(i int, step plan.Step, entry string) error {
+ // The displaced file is in the Trash from this moment, whatever
+ // becomes of the step that needed its name, so its line is written
+ // here rather than with the rest of the step.
+ return e.logDisplace(j, run, dirName, rel, i+1, step, entry)
})
if err != nil {
return FileResult{}, err
@@ -125,6 +130,24 @@ func (e *Engine) applyFile(ctx context.Context, dirName string, c plan.Chain, ap
return FileResult{File: c.File, Steps: results}, nil
}
+// logDisplace writes the line for a file trashed to make room, as soon as
+// it has reached the Trash. It is its own action with its own line (spec
+// §9), independent of whether the step that needed the name then succeeds.
+func (e *Engine) logDisplace(j *journal.Writer, run, dirName, rel string, stepNum int, step plan.Step, entry string) error {
+ dst := filepath.Join(trash.Dir(), "files", entry)
+ size, mtime := statSizeModTime(dst)
+ return j.Append(journal.Entry{
+ Time: e.Now(), Run: run, Dir: dirName, File: rel, Step: stepNum,
+ Action: "displace", Status: "ok", Rule: step.Rule,
+ // Detail carries the trash entry name explicitly: Dst's shape
+ // (trash.Dir()/files/<entry>) is internal/apply's and this file's
+ // own convention, not a contract undo may quietly depend on.
+ // PlanUndo/ApplyUndo read the name from here, never by taking
+ // Dst's basename.
+ Src: step.Displaces, Dst: dst, Size: size, ModTime: mtime, Detail: entry,
+ })
+}
+
// unloggedStep is the error for a step whose log entry could not be
// written. A step that ran is named with where its file is now: undo
// cannot see it, so the user must be told where to look.
@@ -233,23 +256,6 @@ func actionName(k plan.Kind) string {
// step's planned destination (informational only — PlanUndo never reverses
// a non-"ok" entry) and Size/ModTime stay zero.
func (e *Engine) logStep(j *journal.Writer, run, dirName, rel string, stepNum int, step plan.Step, sr apply.StepResult) error {
- if sr.DisplacedEntry != "" {
- dst := filepath.Join(trash.Dir(), "files", sr.DisplacedEntry)
- size, mtime := statSizeModTime(dst)
- if err := j.Append(journal.Entry{
- Time: e.Now(), Run: run, Dir: dirName, File: rel, Step: stepNum,
- Action: "displace", Status: "ok", Rule: step.Rule,
- // Detail carries the trash entry name explicitly: Dst's shape
- // (trash.Dir()/files/<entry>) is internal/apply's and this
- // file's own convention, not a contract undo may quietly
- // depend on. PlanUndo/ApplyUndo read the name from here,
- // never by taking Dst's basename.
- Src: step.Displaces, Dst: dst, Size: size, ModTime: mtime, Detail: sr.DisplacedEntry,
- }); err != nil {
- return err
- }
- }
-
for _, dir := range sr.Made {
size, mtime := statSizeModTime(dir)
if err := j.Append(journal.Entry{