From 07ce3572a0f00f588ad40c239d668009d72f6094 Mon Sep 17 00:00:00 2001 From: Simon Frei Date: Tue, 7 Apr 2020 10:23:38 +0200 Subject: [PATCH] lib/ignore: Only skip for toplevel includes (fixes #6487) (#6508) --- lib/ignore/ignore.go | 11 +++----- lib/ignore/ignore_test.go | 19 +++++++++++--- lib/scanner/walk_test.go | 54 +++++++++++++++++++++++++++++++++------ 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/lib/ignore/ignore.go b/lib/ignore/ignore.go index 8080f0eb6..c19584482 100644 --- a/lib/ignore/ignore.go +++ b/lib/ignore/ignore.go @@ -67,16 +67,11 @@ func (p Pattern) allowsSkippingIgnoredDirs() bool { if p.pattern[0] != '/' { return false } - // Double asterisk everywhere in the path except at the end is bad - if strings.Contains(strings.TrimSuffix(p.pattern, "**"), "**") { + if strings.Contains(p.pattern[1:], "/") { return false } - // Any wildcards anywhere except for the last path component are bad - lastSep := strings.LastIndex(p.pattern, "/") - if lastSep == -1 { - return true - } - return p.pattern[:lastSep] == glob.QuoteMeta(p.pattern[:lastSep]) + // Double asterisk everywhere in the path except at the end is bad + return !strings.Contains(strings.TrimSuffix(p.pattern, "**"), "**") } type Result uint8 diff --git a/lib/ignore/ignore_test.go b/lib/ignore/ignore_test.go index 1de1e305d..4e743cafb 100644 --- a/lib/ignore/ignore_test.go +++ b/lib/ignore/ignore_test.go @@ -1110,10 +1110,10 @@ func TestSkipIgnoredDirs(t *testing.T) { {`!/t*t`, true}, {`!/t?t`, true}, {`!/**`, true}, - {`!/parent/test`, true}, - {`!/parent/t[eih]t`, true}, - {`!/parent/t*t`, true}, - {`!/parent/t?t`, true}, + {`!/parent/test`, false}, + {`!/parent/t[eih]t`, false}, + {`!/parent/t*t`, false}, + {`!/parent/t?t`, false}, {`!/**.mp3`, false}, {`!/pa*nt/test`, false}, {`!/pa[sdf]nt/t[eih]t`, false}, @@ -1150,6 +1150,17 @@ func TestSkipIgnoredDirs(t *testing.T) { if !pats.SkipIgnoredDirs() { t.Error("SkipIgnoredDirs should be true") } + + stignore = ` + !/foo/ign* + * + ` + if err := pats.Parse(bytes.NewBufferString(stignore), ".stignore"); err != nil { + t.Fatal(err) + } + if pats.SkipIgnoredDirs() { + t.Error("SkipIgnoredDirs should be false") + } } func TestEmptyPatterns(t *testing.T) { diff --git a/lib/scanner/walk_test.go b/lib/scanner/walk_test.go index e1b6ac445..b6af968de 100644 --- a/lib/scanner/walk_test.go +++ b/lib/scanner/walk_test.go @@ -767,16 +767,10 @@ func TestNotExistingError(t *testing.T) { } func TestSkipIgnoredDirs(t *testing.T) { - tmp, err := ioutil.TempDir("", "") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmp) - - fss := fs.NewFilesystem(fs.FilesystemTypeBasic, tmp) + fss := fs.NewFilesystem(fs.FilesystemTypeFake, "") name := "foo/ignored" - err = fss.MkdirAll(name, 0777) + err := fss.MkdirAll(name, 0777) if err != nil { t.Fatal(err) } @@ -811,6 +805,50 @@ func TestSkipIgnoredDirs(t *testing.T) { } } +// https://github.com/syncthing/syncthing/issues/6487 +func TestIncludedSubdir(t *testing.T) { + fss := fs.NewFilesystem(fs.FilesystemTypeFake, "") + + name := filepath.Clean("foo/bar/included") + err := fss.MkdirAll(name, 0777) + if err != nil { + t.Fatal(err) + } + + pats := ignore.New(fss, ignore.WithCache(true)) + + stignore := ` + !/foo/bar + * + ` + if err := pats.Parse(bytes.NewBufferString(stignore), ".stignore"); err != nil { + t.Fatal(err) + } + + fchan := Walk(context.TODO(), Config{ + CurrentFiler: make(fakeCurrentFiler), + Filesystem: fss, + Matcher: pats, + }) + + found := false + for f := range fchan { + if f.Err != nil { + t.Fatalf("Error while scanning %v: %v", f.Err, f.Path) + } + if f.File.IsIgnored() { + t.Error("File is ignored:", f.File.Name) + } + if f.File.Name == name { + found = true + } + } + + if !found { + t.Errorf("File not present in scan results") + } +} + // Verify returns nil or an error describing the mismatch between the block // list and actual reader contents func verify(r io.Reader, blocksize int, blocks []protocol.BlockInfo) error {