Refuse an exclude pattern that does not compile when the config loads (closes #455)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
An exclude pattern that did not compile was skipped with a log warning during the backup, which then stored what it meant to leave out. Config.Validate now refuses such a pattern, global or per snapshot, naming the setting and quoting the pattern. The compile step moves to a new package, internal/exclude, which both the config and the scanner call. Model: opus-5-5
This commit was merged in pull request #456.
This commit is contained in:
1 parent
6a8bb2f389
commit
5ca0d46932
6 files changed
+294
-69
No files matched your search
@@ -0,0 +1,73 @@
|
||||
package exclude_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"sneak.berlin/go/vaultik/internal/exclude"
|
||||
)
|
||||
|
||||
// TestCompile checks the error, the anchoring and the globs that Compile
|
||||
// returns for one exclude pattern.
|
||||
func TestCompile(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
pattern string
|
||||
wantErr string
|
||||
wantAnchored bool
|
||||
// wantMatches lists paths that one of the globs must match. When
|
||||
// it is empty, Compile must return no globs.
|
||||
wantMatches []string
|
||||
}{
|
||||
{name: "does not compile", pattern: "build[",
|
||||
wantErr: `"build[" is not a valid exclude pattern`},
|
||||
{name: "empty", pattern: ""},
|
||||
{name: "leading slash anchors", pattern: "/build",
|
||||
wantAnchored: true, wantMatches: []string{"build"}},
|
||||
{name: "double star after the slash clears anchoring",
|
||||
pattern: "/**/build", wantMatches: []string{"build"}},
|
||||
{name: "double star in the middle", pattern: "a/**/*.log",
|
||||
wantMatches: []string{"a/x.log", "a/b/x.log"}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
globs, anchored, err := exclude.Compile(tt.pattern)
|
||||
if tt.wantErr == "" && err != nil {
|
||||
t.Fatalf("Compile(%q) error = %v, want none", tt.pattern, err)
|
||||
}
|
||||
|
||||
if tt.wantErr != "" &&
|
||||
(err == nil || !strings.HasPrefix(err.Error(), tt.wantErr)) {
|
||||
t.Fatalf("Compile(%q) error = %v, want one starting with %q",
|
||||
tt.pattern, err, tt.wantErr)
|
||||
}
|
||||
|
||||
if anchored != tt.wantAnchored {
|
||||
t.Errorf("Compile(%q) anchored = %t, want %t",
|
||||
tt.pattern, anchored, tt.wantAnchored)
|
||||
}
|
||||
|
||||
if len(tt.wantMatches) == 0 && len(globs) != 0 {
|
||||
t.Errorf("Compile(%q) returned %d globs, want none",
|
||||
tt.pattern, len(globs))
|
||||
}
|
||||
|
||||
for _, path := range tt.wantMatches {
|
||||
matched := slices.ContainsFunc(globs, func(g glob.Glob) bool {
|
||||
return g.Match(path)
|
||||
})
|
||||
if !matched {
|
||||
t.Errorf("Compile(%q) globs do not match %q",
|
||||
tt.pattern, path)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user