aboutsummaryrefslogtreecommitdiffstats
path: root/gitignore_test.go
diff options
context:
space:
mode:
authorBernhard Guillon <Bernhard.Guillon@begu.org>2026-07-06 21:21:53 +0200
committerBernhard Guillon <Bernhard.Guillon@begu.org>2026-07-06 21:21:53 +0200
commit7512c95fa3f4b4e4ccdf452024f314a9a3c3b60f (patch)
treec38cfa736d70a2e2c5d1aae044f2c13ef96ae9fa /gitignore_test.go
parentb505ac2fe010fcc24b774c313d33dc099214e8ed (diff)
downloadsourcewatch-7512c95fa3f4b4e4ccdf452024f314a9a3c3b60f.tar.gz
sourcewatch-7512c95fa3f4b4e4ccdf452024f314a9a3c3b60f.zip
Add sync and gitignore tests, fix loadGitignore bug
- Added gitignore_test.go: comprehensive tests for go-gitignore patterns - Verified: *, **, [], negation, anchored patterns, comments - Documented limitation: ? wildcard not supported by go-gitignore - Added sync_test.go: integration tests for initial sync - Tests: basic files, gitignore excludes, negation, double-star, directory patterns, symlinks, permissions, dry-run, .git skip, nested gitignore, complex combined patterns - Fixed gitignore.go: use CompileIgnoreFile instead of passing entire file content as single string to CompileIgnoreLines
Diffstat (limited to 'gitignore_test.go')
-rw-r--r--gitignore_test.go220
1 files changed, 220 insertions, 0 deletions
diff --git a/gitignore_test.go b/gitignore_test.go
new file mode 100644
index 0000000..db9f25b
--- /dev/null
+++ b/gitignore_test.go
@@ -0,0 +1,220 @@
+package main
+
+import (
+ "testing"
+
+ ignore "github.com/sabhiram/go-gitignore"
+)
+
+func TestGitignore_SimplePatterns(t *testing.T) {
+ tests := []struct {
+ name string
+ patterns []string
+ path string
+ expected bool
+ }{
+ {"exact file", []string{"foo.txt"}, "foo.txt", true},
+ {"exact file no match", []string{"foo.txt"}, "bar.txt", false},
+ {"wildcard extension", []string{"*.log"}, "debug.log", true},
+ {"wildcard no match", []string{"*.log"}, "debug.txt", false},
+ {"directory pattern with content", []string{"build/"}, "build/output.o", true},
+ {"leading slash anchored", []string{"/foo"}, "foo", true},
+ {"leading slash anchored no match", []string{"/foo"}, "bar/foo", false},
+ {"comment line ignored", []string{"# this is a comment"}, "foo", false},
+ {"empty line ignored", []string{""}, "foo", false},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gi := ignore.CompileIgnoreLines(tt.patterns...)
+ result := gi.MatchesPath(tt.path)
+ if result != tt.expected {
+ t.Errorf("MatchesPath(%q) = %v, want %v", tt.path, result, tt.expected)
+ }
+ })
+ }
+}
+
+func TestGitignore_Negation(t *testing.T) {
+ gi := ignore.CompileIgnoreLines("*.log", "!important.log")
+
+ tests := []struct {
+ path string
+ expected bool
+ }{
+ {"debug.log", true},
+ {"important.log", false},
+ {"test.log", true},
+ {"readme.txt", false},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.path, func(t *testing.T) {
+ result := gi.MatchesPath(tt.path)
+ if result != tt.expected {
+ t.Errorf("MatchesPath(%q) = %v, want %v", tt.path, result, tt.expected)
+ }
+ })
+ }
+}
+
+func TestGitignore_DoubleStar(t *testing.T) {
+ tests := []struct {
+ name string
+ patterns []string
+ path string
+ expected bool
+ }{
+ {"double star prefix", []string{"**/temp"}, "temp", true},
+ {"double star prefix nested", []string{"**/temp"}, "foo/temp", true},
+ {"double star prefix deep nested", []string{"**/temp"}, "foo/bar/baz/temp", true},
+ {"double star suffix", []string{"temp/**"}, "temp/file.txt", true},
+ {"double star suffix deep", []string{"temp/**"}, "temp/sub/file.txt", true},
+ {"double star middle", []string{"foo/**/bar"}, "foo/bar", true},
+ {"double star middle nested", []string{"foo/**/bar"}, "foo/x/y/bar", true},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gi := ignore.CompileIgnoreLines(tt.patterns...)
+ result := gi.MatchesPath(tt.path)
+ if result != tt.expected {
+ t.Errorf("MatchesPath(%q) = %v, want %v", tt.path, result, tt.expected)
+ }
+ })
+ }
+}
+
+func TestGitignore_QuestionMark(t *testing.T) {
+ // NOTE: go-gitignore does not support ? wildcard
+ // This test documents the limitation
+ gi := ignore.CompileIgnoreLines("?.txt")
+
+ result := gi.MatchesPath("a.txt")
+ if result {
+ t.Log("go-gitignore now supports ? wildcard - update docs")
+ } else {
+ t.Log("go-gitignore does NOT support ? wildcard - known limitation")
+ }
+}
+
+func TestGitignore_BracketRange(t *testing.T) {
+ gi := ignore.CompileIgnoreLines("[abc].txt")
+
+ tests := []struct {
+ path string
+ expected bool
+ }{
+ {"a.txt", true},
+ {"b.txt", true},
+ {"c.txt", true},
+ {"d.txt", false},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.path, func(t *testing.T) {
+ result := gi.MatchesPath(tt.path)
+ if result != tt.expected {
+ t.Errorf("MatchesPath(%q) = %v, want %v", tt.path, result, tt.expected)
+ }
+ })
+ }
+}
+
+func TestGitignore_NestedGitignore(t *testing.T) {
+ rules := map[string][]string{
+ ".gitignore": {"*.log"},
+ "subdir/.gitignore": {"*.tmp"},
+ "subdir/deep/.gitignore": {"*.bak"},
+ }
+
+ gi := ignore.CompileIgnoreLines(rules[".gitignore"]...)
+
+ tests := []struct {
+ name string
+ path string
+ expected bool
+ }{
+ {"root log", "debug.log", true},
+ {"root txt", "readme.txt", false},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := gi.MatchesPath(tt.path)
+ if result != tt.expected {
+ t.Errorf("MatchesPath(%q) = %v, want %v", tt.path, result, tt.expected)
+ }
+ })
+ }
+
+ // Nested gitignore needs separate handling per directory
+ subGi := ignore.CompileIgnoreLines(rules["subdir/.gitignore"]...)
+ if subGi.MatchesPath("file.tmp") != true {
+ t.Error("subdir gitignore should match *.tmp")
+ }
+}
+
+func TestGitignore_CombinedPatterns(t *testing.T) {
+ gi := ignore.CompileIgnoreLines(
+ "*.o",
+ "*.a",
+ "build/",
+ "!lib/special.o",
+ )
+
+ tests := []struct {
+ path string
+ expected bool
+ }{
+ {"foo.o", true},
+ {"lib.a", true},
+ {"build/output.o", true},
+ {"lib/special.o", false},
+ {"src/main.c", false},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.path, func(t *testing.T) {
+ result := gi.MatchesPath(tt.path)
+ if result != tt.expected {
+ t.Errorf("MatchesPath(%q) = %v, want %v", tt.path, result, tt.expected)
+ }
+ })
+ }
+}
+
+func TestGitignore_HashInFilename(t *testing.T) {
+ gi := ignore.CompileIgnoreLines("*.txt")
+
+ tests := []struct {
+ path string
+ expected bool
+ }{
+ {"file#1.txt", true},
+ {"file#2.txt", true},
+ {"readme.md", false},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.path, func(t *testing.T) {
+ result := gi.MatchesPath(tt.path)
+ if result != tt.expected {
+ t.Errorf("MatchesPath(%q) = %v, want %v", tt.path, result, tt.expected)
+ }
+ })
+ }
+}
+
+func TestGitignore_TrailingSpace(t *testing.T) {
+ // NOTE: go-gitignore does not handle trailing spaces in patterns
+ // This test documents the limitation
+ gi := ignore.CompileIgnoreLines("foo.txt ")
+
+ result := gi.MatchesPath("foo.txt")
+ if result {
+ t.Log("go-gitignore handles trailing spaces correctly")
+ } else {
+ t.Log("go-gitignore does NOT handle trailing spaces - known limitation")
+ }
+}