lib/ignore: Only handle lines prefixed with #include specially (fixes #4680)

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4684
LGTM: AudriusButkevicius, calmh
This commit is contained in:
Simon Frei 2018-01-17 16:56:53 +00:00 committed by Jakob Borg
parent e147db5233
commit a1761795fe
2 changed files with 39 additions and 15 deletions

View File

@ -304,7 +304,7 @@ func loadIgnoreFile(fs fs.Filesystem, file string, cd ChangeDetector) (fs.File,
return fd, info, err return fd, info, err
} }
func loadParseIncludeFile(filesystem fs.Filesystem, file string, cd ChangeDetector, linesSeen map[string]struct{}) ([]string, []Pattern, error) { func loadParseIncludeFile(filesystem fs.Filesystem, file string, cd ChangeDetector, linesSeen map[string]struct{}) ([]Pattern, error) {
// Allow escaping the folders filesystem. // Allow escaping the folders filesystem.
// TODO: Deprecate, somehow? // TODO: Deprecate, somehow?
if filesystem.Type() == fs.FilesystemTypeBasic { if filesystem.Type() == fs.FilesystemTypeBasic {
@ -317,18 +317,19 @@ func loadParseIncludeFile(filesystem fs.Filesystem, file string, cd ChangeDetect
} }
if cd.Seen(filesystem, file) { if cd.Seen(filesystem, file) {
return nil, nil, fmt.Errorf("multiple include of ignore file %q", file) return nil, fmt.Errorf("multiple include of ignore file %q", file)
} }
fd, info, err := loadIgnoreFile(filesystem, file, cd) fd, info, err := loadIgnoreFile(filesystem, file, cd)
if err != nil { if err != nil {
return nil, nil, err return nil, err
} }
defer fd.Close() defer fd.Close()
cd.Remember(filesystem, file, info.ModTime()) cd.Remember(filesystem, file, info.ModTime())
return parseIgnoreFile(filesystem, fd, file, cd, linesSeen) _, patterns, err := parseIgnoreFile(filesystem, fd, file, cd, linesSeen)
return patterns, err
} }
func parseIgnoreFile(fs fs.Filesystem, fd io.Reader, currentFile string, cd ChangeDetector, linesSeen map[string]struct{}) ([]string, []Pattern, error) { func parseIgnoreFile(fs fs.Filesystem, fd io.Reader, currentFile string, cd ChangeDetector, linesSeen map[string]struct{}) ([]string, []Pattern, error) {
@ -395,14 +396,6 @@ func parseIgnoreFile(fs fs.Filesystem, fd io.Reader, currentFile string, cd Chan
return fmt.Errorf("invalid pattern %q in ignore file (%v)", line, err) return fmt.Errorf("invalid pattern %q in ignore file (%v)", line, err)
} }
patterns = append(patterns, pattern) patterns = append(patterns, pattern)
} else if strings.HasPrefix(line, "#include ") {
includeRel := strings.TrimSpace(line[len("#include "):])
includeFile := filepath.Join(filepath.Dir(currentFile), includeRel)
_, includePatterns, err := loadParseIncludeFile(fs, includeFile, cd, linesSeen)
if err != nil {
return fmt.Errorf("include of %q: %v", includeRel, err)
}
patterns = append(patterns, includePatterns...)
} else { } else {
// Path name or pattern, add it so it matches files both in // Path name or pattern, add it so it matches files both in
// current directory and subdirs. // current directory and subdirs.
@ -441,8 +434,13 @@ func parseIgnoreFile(fs fs.Filesystem, fd io.Reader, currentFile string, cd Chan
line = filepath.ToSlash(line) line = filepath.ToSlash(line)
switch { switch {
case strings.HasPrefix(line, "#"): case strings.HasPrefix(line, "#include"):
err = addPattern(line) includeRel := strings.TrimSpace(line[len("#include "):])
includeFile := filepath.Join(filepath.Dir(currentFile), includeRel)
var includePatterns []Pattern
if includePatterns, err = loadParseIncludeFile(fs, includeFile, cd, linesSeen); err == nil {
patterns = append(patterns, includePatterns...)
}
case strings.HasSuffix(line, "/**"): case strings.HasSuffix(line, "/**"):
err = addPattern(line) err = addPattern(line)
case strings.HasSuffix(line, "/"): case strings.HasSuffix(line, "/"):

View File

@ -186,7 +186,6 @@ func TestBadPatterns(t *testing.T) {
"**/[", "**/[",
"#include nonexistent", "#include nonexistent",
"#include .stignore", "#include .stignore",
"!#include makesnosense",
} }
for _, pat := range badPatterns { for _, pat := range badPatterns {
@ -930,3 +929,30 @@ func TestDuplicateLines(t *testing.T) {
t.Fatalf("Parsed patterns differ when manually removing duplicate lines") t.Fatalf("Parsed patterns differ when manually removing duplicate lines")
} }
} }
func TestIssue4680(t *testing.T) {
stignore := `
#snapshot
`
testcases := []struct {
file string
matches bool
}{
{"#snapshot", true},
{"#snapshot/foo", true},
}
pats := New(fs.NewFilesystem(fs.FilesystemTypeBasic, "."), WithCache(true))
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
t.Fatal(err)
}
for _, tc := range testcases {
res := pats.Match(tc.file).IsIgnored()
if res != tc.matches {
t.Errorf("Matches(%q) == %v, expected %v", tc.file, res, tc.matches)
}
}
}