Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

152 lines
3.7 KiB
Go

package excludes
import (
"testing"
)
func TestMatcher_Nil(t *testing.T) {
var m *Matcher
if m.MatchRel("anything") {
t.Fatal("nil matcher should never match")
}
}
func TestMatcher_Builtin(t *testing.T) {
m := New(Builtin)
cases := []struct {
path string
want bool
}{
{".git/HEAD", true},
{"pkg/.git/HEAD", true},
{"src/node_modules/foo/index.js", true},
{"vendor/lib/x.go", true},
{"pkg/foo.go", false},
{"README.md", false},
{"tmp.tmp", true},
{"deep/nested/file.swp", true},
{".Makefile.swpx", true},
{"src/.foo.swo", true},
{"src/.foo.swn", true},
{"backup~", true},
}
for _, tc := range cases {
if got := m.MatchRel(tc.path); got != tc.want {
t.Errorf("MatchRel(%q) = %v, want %v", tc.path, got, tc.want)
}
}
}
func TestMatcher_Negation(t *testing.T) {
// Exclude all of dist, except dist/keep
m := New([]string{"dist/", "!dist/keep/**"})
if !m.MatchRel("dist/junk.txt") {
t.Error("dist/junk.txt should be excluded")
}
if m.MatchRel("dist/keep/foo.txt") {
t.Error("dist/keep/foo.txt should be re-included")
}
}
func TestMatcher_HasNegatedDescendant(t *testing.T) {
cases := []struct {
name string
patterns []string
relDir string
want bool
}{
{
// Issue #113: a blanket "dir/*" makes go-gitignore report the
// parent directory itself as excluded; the re-include lives
// beneath it, so the parent must keep being descended.
name: "blanket plus reinclude under parent",
patterns: []string{"wp-content/plugins/*", "!wp-content/plugins/foo/"},
relDir: "wp-content/plugins",
want: true,
},
{
name: "sibling without reinclude is prunable",
patterns: []string{"wp-content/plugins/*", "!wp-content/plugins/foo/"},
relDir: "wp-content/plugins/other",
want: false,
},
{
name: "unrelated dir is prunable",
patterns: []string{"wp-content/plugins/*", "!wp-content/plugins/foo/"},
relDir: "node_modules",
want: false,
},
{
name: "reinclude two levels down keeps grandparent",
patterns: []string{"a/*", "!a/b/c/"},
relDir: "a",
want: true,
},
{
name: "reinclude two levels down keeps parent",
patterns: []string{"a/*", "!a/b/c/"},
relDir: "a/b",
want: true,
},
{
name: "reinclude two levels down prunes uninvolved sibling",
patterns: []string{"a/*", "!a/b/c/", "!a/x"},
relDir: "a/y",
want: false,
},
{
name: "unanchored basename negation keeps every dir",
patterns: []string{"build/", "!keep.txt"},
relDir: "build",
want: true,
},
{
name: "wildcard-leading negation keeps every dir",
patterns: []string{"build/", "!**/keep/"},
relDir: "build",
want: true,
},
{
name: "no negations never keeps",
patterns: []string{"build/", "dist/"},
relDir: "build",
want: false,
},
{
name: "trailing-slash relDir is tolerated",
patterns: []string{"a/*", "!a/b/c/"},
relDir: "a/b/",
want: true,
},
{
name: "leading-dot-slash relDir is tolerated",
patterns: []string{"a/*", "!a/b/c/"},
relDir: "./a",
want: true,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
m := New(tc.patterns)
if got := m.HasNegatedDescendant(tc.relDir); got != tc.want {
t.Errorf("HasNegatedDescendant(%q) = %v, want %v", tc.relDir, got, tc.want)
}
})
}
}
func TestMatcher_HasNegatedDescendant_Nil(t *testing.T) {
var m *Matcher
if m.HasNegatedDescendant("anything") {
t.Fatal("nil matcher should report no negated descendants")
}
}
func TestMatcher_CommentsAndEmpty(t *testing.T) {
m := New([]string{"", "# comment", "foo/"})
pats := m.Patterns()
if len(pats) != 1 || pats[0] != "foo/" {
t.Errorf("expected [foo/], got %v", pats)
}
}