diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-14 14:08:36 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-14 14:08:36 +0200 |
| commit | 1d3f2d1e4c59867024470d3444e12698b7ebb22e (patch) | |
| tree | 4fa14f455c72f9b206a680dcc1b0f4c1f3708158 /internal/engine/match.go | |
| parent | 07c24054cab965800983ef40f53a05c2db131ede (diff) | |
| download | krino-1d3f2d1e4c59867024470d3444e12698b7ebb22e.tar.gz krino-1d3f2d1e4c59867024470d3444e12698b7ebb22e.zip | |
0.0.4: max-size, exclude forms, --min-agev0.0.4
Diffstat (limited to 'internal/engine/match.go')
| -rw-r--r-- | internal/engine/match.go | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/internal/engine/match.go b/internal/engine/match.go index ffee7f0..8daea9d 100644 --- a/internal/engine/match.go +++ b/internal/engine/match.go @@ -34,6 +34,10 @@ type FileMatch struct { Rules []RuleMatch // matching rules in order, ending at the first with (stop) Warnings []string // "<rule>: <warning>", e.g. "acme: content unreadable: needs pdftotext, not installed" + // Excluded is the (exclude ...) form that set this file aside before any + // rule ran, as written; "" when none did. An excluded file has no Rules. + Excluded string + // NoDelete is non-empty when no delete step may run for this file (spec // ยง5.5 rule 2), and says why: the file is a duplicate under a scope its // directory's rules use, or that check failed. Only set for a file some @@ -92,7 +96,7 @@ func (e *Engine) Match(ctx context.Context, d *Dir) (*Result, error) { var matched, unmatched []FileMatch for _, fm := range fileMatches { - if len(fm.Rules) > 0 { + if len(fm.Rules) > 0 || fm.Excluded != "" { matched = append(matched, fm) } else { unmatched = append(unmatched, fm) @@ -119,6 +123,16 @@ func (e *Engine) Match(ctx context.Context, d *Dir) (*Result, error) { func evalFile(run *matchRun, file scan.File) FileMatch { f := newFacts(run, file) fm := FileMatch{File: file} + for _, x := range run.d.Excludes { + res := x.Cond.Eval(f) + for _, w := range res.Warnings { + fm.Warnings = append(fm.Warnings, "exclude: "+w) + } + if res.Match { + fm.Excluded = x.Text + return fm + } + } for _, r := range run.d.Rules { res := r.Cond.Eval(f) for _, w := range res.Warnings { @@ -180,12 +194,21 @@ type RuleTrace struct { Stopped string // "stopped by rule acme" when an earlier (stop) ended the search } +// ExcludeTrace is one (exclude ...) form's outcome in an Explain call. +type ExcludeTrace struct { + Text string + Match bool + Trace *cond.Trace +} + // Explanation is why (or why not) krino would act on one file. type Explanation struct { - Dir *Dir - File scan.File - Skip string // why krino would not look at this file at all; "" when it would - Rules []RuleTrace + Dir *Dir + File scan.File + Skip string // why krino would not look at this file at all; "" when it would + Excludes []ExcludeTrace + Excluded string // the first exclude that matches, which sets the file aside; "" when none does + Rules []RuleTrace } // Explain reports, for one file, whether krino's ordinary scan would ever @@ -235,6 +258,16 @@ func (e *Engine) Explain(ctx context.Context, path string) (*Explanation, error) run := newMatchRun(e, d, ctx, now, e.filesForExplain(d, sf, excl, now)) f := newFacts(run, sf) + var excludes []ExcludeTrace + excluded := "" + for _, x := range d.Excludes { + trace := x.Cond.Explain(f) + excludes = append(excludes, ExcludeTrace{Text: x.Text, Match: trace.Value, Trace: trace}) + if trace.Value && excluded == "" { + excluded = x.Text + } + } + var rules []RuleTrace stoppedBy := "" for _, r := range d.Rules { @@ -253,7 +286,7 @@ func (e *Engine) Explain(ctx context.Context, path string) (*Explanation, error) } } - return &Explanation{Dir: d, File: sf, Skip: skip, Rules: rules}, nil + return &Explanation{Dir: d, File: sf, Skip: skip, Excludes: excludes, Excluded: excluded, Rules: rules}, nil } // filesForExplain returns the file set Explain's duplicate checks run @@ -285,6 +318,7 @@ func walkOptions(d *Dir, excl []string, now time.Time) scan.Options { Exclude: excl, Busy: d.Settings.Busy, MinAge: d.Settings.MinAge, + MaxSize: d.Settings.MaxSize, Now: now, } } @@ -328,6 +362,9 @@ func explainSkip(d *Dir, sf scan.File, excl []string, now time.Time) string { if now.Sub(sf.ModTime) < d.Settings.MinAge { return "too new" } + if d.Settings.MaxSize > 0 && sf.Size > d.Settings.MaxSize { + return "too big" + } return "" } |
