diff options
Diffstat (limited to 'internal/engine/match.go')
| -rw-r--r-- | internal/engine/match.go | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/internal/engine/match.go b/internal/engine/match.go index 67f0c06..591f686 100644 --- a/internal/engine/match.go +++ b/internal/engine/match.go @@ -228,10 +228,11 @@ func noDelete(f *facts, scopes [][]string) string { // RuleTrace is one rule's outcome in an Explain call. type RuleTrace struct { - Rule *Rule - Match bool - Trace *cond.Trace // nil when not evaluated - Stopped string // "stopped by rule acme" when an earlier (stop) ended the search + Rule *Rule + Match bool + Captures []string // of a matching rule, as its actions' {N} see them + Trace *cond.Trace // nil when not evaluated + Stopped string // "stopped by rule acme" when an earlier (stop) ended the search } // ExcludeTrace is one (exclude ...) form's outcome in an Explain call. @@ -250,6 +251,10 @@ type Explanation struct { Excluded string // the first exclude that matches, which sets the file aside; "" when none does Rules []RuleTrace NoDelete string // why a delete from the matching rules would be skipped (spec §5.5); "" when it would not + // Chain is what the matching rules would do to the file: the same steps + // the directory's plan builds for it, placeholders expanded and + // conflicts resolved (GUI design §1.3). + Chain []plan.Step } // Explain reports, for one file, whether krino's ordinary scan would ever @@ -333,11 +338,16 @@ func (e *Engine) Explain(ctx context.Context, path string) (*Explanation, error) continue } } + var caps []string if match { + // Eval, on the same memoised facts and before matched becomes + // true, is what gives the captures its actions would use. + res := r.Cond.Eval(f) + caps = res.Captures f.matched = true - matched = append(matched, RuleMatch{Rule: r}) + matched = append(matched, RuleMatch{Rule: r, Captures: caps, Reasons: res.Reasons}) } - rules = append(rules, RuleTrace{Rule: r, Match: match, Trace: trace}) + rules = append(rules, RuleTrace{Rule: r, Match: match, Captures: caps, Trace: trace}) if match && r.Conf.Stop { stoppedBy = r.Name } @@ -347,7 +357,15 @@ func (e *Engine) Explain(ctx context.Context, path string) (*Explanation, error) noDel = noDelete(f, d.DupScopes) } - return &Explanation{Dir: d, File: sf, Skip: skip, Excludes: excludes, Excluded: excluded, Rules: rules, NoDelete: noDel}, nil + var chain []plan.Step + if len(matched) > 0 { + in := []plan.Input{{File: sf, Rules: planRules(matched), NoDelete: noDel}} + if built := plan.Build(d.Root, in, now, plan.OS{}, plan.NewClaims()); len(built) == 1 { + chain = built[0].Steps + } + } + + return &Explanation{Dir: d, File: sf, Skip: skip, Excludes: excludes, Excluded: excluded, Rules: rules, NoDelete: noDel, Chain: chain}, nil } // excludesUseDuplicate reports whether any of d's excludes has a |
