diff options
Diffstat (limited to 'internal/engine/engine.go')
| -rw-r--r-- | internal/engine/engine.go | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/internal/engine/engine.go b/internal/engine/engine.go index 0c3186d..61c310e 100644 --- a/internal/engine/engine.go +++ b/internal/engine/engine.go @@ -159,7 +159,7 @@ func LoadWith(mainFile string, overrides map[string][]byte, names ...string) (*E } } dir.ContentKeywords = contentKeywords(dir.Rules, dir.Excludes) - dir.DupScopes = dupScopes(dir.Rules) + dir.DupScopes = dupScopes(dir.Rules, dir.Excludes) dirs = append(dirs, dir) } @@ -267,16 +267,24 @@ func contentKeywords(rules []*Rule, excludes []*Exclude) []cond.Keyword { return out } -// dupScopes returns the distinct Cond.DupDirs lists of rules, in first-seen -// order. Lists are compared as written, with their length in the key so -// (duplicate) and (duplicate "") stay apart; two spellings of one directory -// stay two entries, which costs a second lookup but never a wrong answer, -// since facts.Duplicate resolves and shares the index itself. -func dupScopes(rules []*Rule) [][]string { +// dupScopes returns the distinct Cond.DupDirs lists a directory uses, in +// first-seen order, from its rules and its excludes alike. Lists are +// compared as written, with their length in the key so (duplicate) and +// (duplicate "") stay apart; two spellings of one directory stay two +// entries, which costs a second lookup but never a wrong answer, since +// facts.Duplicate resolves and shares the index itself. +// +// The excludes count because the protection these scopes drive - no rule +// deletes a file krino has found to be a duplicate - is about what krino +// knows, not about which form taught it. A directory whose only duplicate +// test sat in an (exclude ...) had no scopes at all, so a later rule could +// permanently delete every copy of a file krino had just called a +// duplicate. +func dupScopes(rules []*Rule, excludes []*Exclude) [][]string { var out [][]string seen := map[string]bool{} - for _, r := range rules { - for _, dirs := range r.Cond.DupDirs { + add := func(lists [][]string) { + for _, dirs := range lists { key := fmt.Sprintf("%d\x00%s", len(dirs), strings.Join(dirs, "\x00")) if seen[key] { continue @@ -285,6 +293,12 @@ func dupScopes(rules []*Rule) [][]string { out = append(out, dirs) } } + for _, r := range rules { + add(r.Cond.DupDirs) + } + for _, x := range excludes { + add(x.Cond.DupDirs) + } return out } |
