diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 83eee38..2e420e9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -11,7 +11,7 @@ permissions: jobs: test: name: Test - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: # Fail fast is disabled because there are Go version specific features and tests diff --git a/example_unix_test.go b/example_unix_test.go new file mode 100644 index 0000000..e5c08db --- /dev/null +++ b/example_unix_test.go @@ -0,0 +1,32 @@ +//go:build !windows && !plan9 + +package locafero + +import ( + "fmt" + + "github.com/spf13/afero" +) + +func ExampleFinder_Find() { + fsys := afero.NewBasePathFs(afero.NewOsFs(), "testdata") + + finder := Finder{ + Paths: []string{ + "/home/user", + "/etc", + }, + Names: []string{"config.*"}, + Type: FileTypeFile, + } + + results, err := finder.Find(fsys) + if err != nil { + panic(err) + } + + fmt.Println("On Unix:", results) + + // Output: + // On Unix: [/home/user/config.yaml /etc/config.yaml] +} diff --git a/example_windows_test.go b/example_windows_test.go new file mode 100644 index 0000000..713701a --- /dev/null +++ b/example_windows_test.go @@ -0,0 +1,34 @@ +//go:build windows + +package locafero + +import ( + "fmt" + + "github.com/spf13/afero" +) + +func ExampleFinder_Find() { + // Use relative paths for Windows, because we do not know the absolute path. + // fsys := afero.NewBasePathFs(afero.NewOsFs(), "testdata") + fsys := afero.NewOsFs() + + finder := Finder{ + Paths: []string{ + "testdata\\home\\user", + "testdata\\etc", + }, + Names: []string{"config.*"}, + Type: FileTypeFile, + } + + results, err := finder.Find(fsys) + if err != nil { + panic(err) + } + + fmt.Println("On Windows:", results) + + // Output: + // On Windows: [testdata\home\user\config.yaml testdata\etc\config.yaml] +} diff --git a/finder.go b/finder.go index 1c1468a..ef8d547 100644 --- a/finder.go +++ b/finder.go @@ -63,7 +63,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) { // pool.Go(func() ([]string, error) { // // If the name contains any glob character, perform a glob match - // if strings.ContainsAny(searchName, "*?[]\\^") { + // if strings.ContainsAny(searchName, globMatch) { // return globWalkSearch(fsys, searchPath, searchName, f.Type) // } // @@ -79,7 +79,7 @@ func (f Finder) Find(fsys afero.Fs) ([]string, error) { allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) { // If the name contains any glob character, perform a glob match - if strings.ContainsAny(item.name, "*?[]\\^") { + if strings.ContainsAny(item.name, globMatch) { return globWalkSearch(fsys, item.path, item.name, f.Type) } diff --git a/finder_test.go b/finder_test.go index dc6c924..35e2095 100644 --- a/finder_test.go +++ b/finder_test.go @@ -1,8 +1,8 @@ package locafero import ( - "fmt" - "path" + "path/filepath" + "runtime" "testing" "github.com/spf13/afero" @@ -10,26 +10,48 @@ import ( "github.com/stretchr/testify/require" ) -func Example() { - fsys := afero.NewBasePathFs(afero.NewOsFs(), "testdata") +func toAbsOsPath(s string) string { + if runtime.GOOS == "windows" { + return filepath.Join("C:", s) + } - finder := Finder{ - Paths: []string{ - "/home/user", - "/etc", - }, - Names: []string{"config.*"}, - Type: FileTypeFile, + return s +} + +func eachToAbsOsPath(paths []string) []string { + if paths == nil { + return nil } - results, err := finder.Find(fsys) - if err != nil { - panic(err) + newPaths := make([]string, len(paths)) + + for i, p := range paths { + newPaths[i] = toAbsOsPath(p) + } + + return newPaths +} + +func toOsPath(s string) string { + if runtime.GOOS == "windows" { + return filepath.Clean(s) } - fmt.Print(results) + return s +} + +func eachToOsPath(paths []string) []string { + if paths == nil { + return nil + } - // Output: [/home/user/config.yaml /etc/config.yaml] + newPaths := make([]string, len(paths)) + + for i, p := range paths { + newPaths[i] = toOsPath(p) + } + + return newPaths } func TestFinder_Find(t *testing.T) { @@ -50,12 +72,12 @@ func TestFinder_Find(t *testing.T) { } for _, file := range files { - dir := path.Dir(file) + dir := filepath.Dir(toAbsOsPath(file)) err := fsys.MkdirAll(dir, 0o777) require.NoError(t, err) - _, err = fsys.Create(file) + _, err = fsys.Create(toAbsOsPath(file)) require.NoError(t, err) } @@ -257,10 +279,12 @@ func TestFinder_Find(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { + tt.finder.Paths = eachToAbsOsPath(tt.finder.Paths) + results, err := tt.finder.Find(fsys) require.NoError(t, err) - assert.Equal(t, tt.results, results) + assert.Equal(t, eachToAbsOsPath(tt.results), results) }) } } @@ -285,5 +309,37 @@ func TestFinder_Find_RelativePaths(t *testing.T) { "testdata/etc/config.yaml", } + assert.Equal(t, eachToOsPath(expected), results) +} + +func TestFinder_Find_AbsolutePaths(t *testing.T) { + abs := func(t *testing.T, s string) string { + t.Helper() + + a, err := filepath.Abs(s) + require.NoError(t, err) + + return a + } + + fsys := afero.NewOsFs() + + finder := Finder{ + Paths: []string{ + abs(t, "testdata/home/user"), + abs(t, "testdata/etc"), + }, + Names: []string{"config.*"}, + Type: FileTypeFile, + } + + results, err := finder.Find(fsys) + require.NoError(t, err) + + expected := []string{ + abs(t, "testdata/home/user/config.yaml"), + abs(t, "testdata/etc/config.yaml"), + } + assert.Equal(t, expected, results) } diff --git a/glob.go b/glob.go new file mode 100644 index 0000000..00f833e --- /dev/null +++ b/glob.go @@ -0,0 +1,5 @@ +//go:build !windows + +package locafero + +const globMatch = "*?[]\\^" diff --git a/glob_windows.go b/glob_windows.go new file mode 100644 index 0000000..7aec2b2 --- /dev/null +++ b/glob_windows.go @@ -0,0 +1,8 @@ +//go:build windows + +package locafero + +// See [filepath.Match]: +// +// On Windows, escaping is disabled. Instead, '\\' is treated as path separator. +const globMatch = "*?[]^"