diff --git a/glob.go b/glob.go index d2df9b7..fee0751 100644 --- a/glob.go +++ b/glob.go @@ -124,6 +124,14 @@ func Glob(pattern string, opts ...OptFunc) ([]string, error) { // nolint:funlen, return nil, fmt.Errorf("cannot determine static prefix: %w", err) } + // Check if the file is valid symlink without following it + // It works only for valid absolut or relative file paths, in other words, will fail for WithFs() option + if patternInfo, err := os.Lstat(pattern); err == nil { // nolint:govet + if patternInfo.Mode()&os.ModeSymlink == os.ModeSymlink { + return cleanFilepaths([]string{pattern}, options.prefix), nil + } + } + prefixInfo, err := fs.Stat(options.fs, prefix) if errors.Is(err, fs.ErrNotExist) { if !ContainsMatchers(pattern) { diff --git a/glob_test.go b/glob_test.go index 9831f2a..188fc3c 100644 --- a/glob_test.go +++ b/glob_test.go @@ -450,6 +450,32 @@ func TestGlob(t *testing.T) { // nolint:funlen "a/b/4.txt", }, matches) }) + + t.Run("symlinks", func(t *testing.T) { + t.Parallel() + var fsPath string + if testFS, ok := testFs(t, []string{"./a/file"}, nil).(testfs.FS); ok { + fsPath = testFS.Path() + } + + workingSymlink := filepath.Join(fsPath, "b") + brokenSymlink := filepath.Join(fsPath, "c") + err := os.Symlink("a", workingSymlink) + require.NoError(t, err) + err = os.Symlink("non-existent", brokenSymlink) + require.NoError(t, err) + + matches, err := Glob(workingSymlink) + require.NoError(t, err) + require.Equal(t, []string{ + workingSymlink, + }, matches) + matches, err = Glob(brokenSymlink) + require.NoError(t, err) + require.Equal(t, []string{ + brokenSymlink, + }, matches) + }) } func TestQuoteMeta(t *testing.T) {