From e742d83fa0d896b1311c987dfe1dd86d2bb5a318 Mon Sep 17 00:00:00 2001 From: TangoEnSkai <21152231+TangoEnSkai@users.noreply.github.com> Date: Sat, 22 Aug 2026 12:53:28 +0900 Subject: [PATCH] libs/fileset: cover leading-slash anchoring in glob patterns NewGlobSet compiles include patterns with go-gitignore, so a leading slash anchors the pattern to the fileset root while a bare name matches at any depth. Nothing tested that distinction, even though sync.include depends on it to select a top-level directory without also matching same-named directories nested deeper. Add a test that pins both halves: "/dir/" selects only the root directory, "dir/" selects the nested one as well. --- libs/fileset/glob_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/libs/fileset/glob_test.go b/libs/fileset/glob_test.go index 40388996447..365b96f55d5 100644 --- a/libs/fileset/glob_test.go +++ b/libs/fileset/glob_test.go @@ -2,7 +2,9 @@ package fileset import ( "io/fs" + "os" "path" + "path/filepath" "slices" "strings" "testing" @@ -132,3 +134,32 @@ func TestGlobFilesetDoubleQuotesWithFilePatterns(t *testing.T) { require.NoError(t, err) require.ElementsMatch(t, entries, collectRelativePaths(files)) } + +// A pattern with a leading slash is anchored to the fileset root, the same way +// git treats it in .gitignore. Without the slash the pattern matches a directory +// of that name at any depth. sync.include relies on this to select, say, a +// top-level "resources" directory without also picking up "vendor/resources". +func TestGlobFilesetLeadingSlashAnchorsToRoot(t *testing.T) { + tmpDir := t.TempDir() + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "dir"), 0o755)) + require.NoError(t, os.MkdirAll(filepath.Join(tmpDir, "nested", "dir"), 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "dir", "a.txt"), []byte("a"), 0o644)) + require.NoError(t, os.WriteFile(filepath.Join(tmpDir, "nested", "dir", "b.txt"), []byte("b"), 0o644)) + + root := vfs.MustNew(tmpDir) + + g, err := NewGlobSet(root, []string{"/dir/"}) + require.NoError(t, err) + files, err := g.Files() + require.NoError(t, err) + require.ElementsMatch(t, []string{filepath.Join("dir", "a.txt")}, collectRelativePaths(files)) + + g, err = NewGlobSet(root, []string{"dir/"}) + require.NoError(t, err) + files, err = g.Files() + require.NoError(t, err) + require.ElementsMatch(t, []string{ + filepath.Join("dir", "a.txt"), + filepath.Join("nested", "dir", "b.txt"), + }, collectRelativePaths(files)) +}