From c66a842ce4679a3ffa5504dad39b1402bea75e9f Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 14 Sep 2026 23:07:57 +0200 Subject: plan 10 re-check: cut run column, damaged undo run, emptied directory cleanup, text turning binary, explain flags, interrupt docs --- internal/journal/read.go | 6 ++++-- internal/journal/read_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'internal/journal') diff --git a/internal/journal/read.go b/internal/journal/read.go index 48cd6b0..9099c0d 100644 --- a/internal/journal/read.go +++ b/internal/journal/read.go @@ -172,10 +172,12 @@ func Entries(path, runID string) ([]Entry, error) { // runFieldOf best-effort extracts a line's Run column even when the line // otherwise fails to parse, so Entries can tell whether an unparsable line -// belonged to the run it was asked for. +// belonged to the run it was asked for. The column counts only when a tab +// ends it: a line cut inside it holds a prefix of some run's ID, which names +// no run (plan 10 re-check R2). func runFieldOf(line string) (string, bool) { f := strings.SplitN(line, "\t", 3) - if len(f) < 2 { + if len(f) < 3 { return "", false } return unescape(f[1]), true diff --git a/internal/journal/read_test.go b/internal/journal/read_test.go index fb6f77f..676b2bd 100644 --- a/internal/journal/read_test.go +++ b/internal/journal/read_test.go @@ -702,3 +702,32 @@ func TestReversedStepsCountsEveryUndoOfARun(t *testing.T) { } } } + +// TestEntriesRefusesALineCutInsideItsRunColumn: a crash that cuts the last +// line inside its run column leaves a prefix of some run's ID - it cannot +// be called another run's line, so inside this run's window it refuses the +// run (plan 10 re-check R2). +func TestEntriesRefusesALineCutInsideItsRunColumn(t *testing.T) { + path := filepath.Join(t.TempDir(), "krino.log") + w, _ := Open(path) + at := time.Date(2026, 9, 11, 10, 2, 3, 0, time.UTC) + run := "20260911T100203-ab12" + for _, e := range []Entry{ + {Time: at, Run: run, Action: "run-start", Status: "ok"}, + {Time: at, Run: run, Dir: "dl", File: "x.pdf", Step: 1, Action: "copy", Status: "ok", Src: "/a/x.pdf", Dst: "/b/x.pdf"}, + } { + if err := w.Append(e); err != nil { + t.Fatal(err) + } + } + w.Close() + f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0) + if err != nil { + t.Fatal(err) + } + f.WriteString("2026-09-11T10:02:04Z\t20260911T10") + f.Close() + if got, err := Entries(path, run); err == nil { + t.Errorf("Entries = %+v, no error; a line cut inside its run column must refuse the run", got) + } +} -- cgit v1.3