From a018c297d9e725c2e8936ffe67a9d18d7ccf86e7 Mon Sep 17 00:00:00 2001 From: Brian McGee Date: Tue, 9 Jul 2024 13:36:26 +0100 Subject: [PATCH] fix: relative path resolution in filesystem walker Signed-off-by: Brian McGee --- walk/filesystem.go | 6 +-- walk/filesystem_test.go | 95 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 walk/filesystem_test.go diff --git a/walk/filesystem.go b/walk/filesystem.go index 18cc3dfc..c14fc451 100644 --- a/walk/filesystem.go +++ b/walk/filesystem.go @@ -20,11 +20,11 @@ func (f filesystemWalker) Walk(_ context.Context, fn WalkFunc) error { relPathOffset := len(f.root) + 1 relPathFn := func(path string) (string, error) { - // quick optimisation for the majority of use cases - // todo check that root is a prefix in path? - if len(path) >= relPathOffset { + // quick optimization for the majority of use cases + if len(path) >= relPathOffset && path[:len(f.root)] == f.root { return path[relPathOffset:], nil } + // fallback to proper relative path resolution return filepath.Rel(f.root, path) } diff --git a/walk/filesystem_test.go b/walk/filesystem_test.go new file mode 100644 index 00000000..202f0595 --- /dev/null +++ b/walk/filesystem_test.go @@ -0,0 +1,95 @@ +package walk + +import ( + "context" + "os" + "testing" + + "git.numtide.com/numtide/treefmt/test" + "github.com/stretchr/testify/require" +) + +var examplesPaths = []string{ + ".", + "elm", + "elm/elm.json", + "elm/src", + "elm/src/Main.elm", + "go", + "go/go.mod", + "go/main.go", + "haskell", + "haskell/CHANGELOG.md", + "haskell/Foo.hs", + "haskell/Main.hs", + "haskell/Nested", + "haskell/Nested/Foo.hs", + "haskell/Setup.hs", + "haskell/haskell.cabal", + "haskell/treefmt.toml", + "haskell-frontend", + "haskell-frontend/CHANGELOG.md", + "haskell-frontend/Main.hs", + "haskell-frontend/Setup.hs", + "haskell-frontend/haskell-frontend.cabal", + "html", + "html/index.html", + "html/scripts", + "html/scripts/.gitkeep", + "javascript", + "javascript/source", + "javascript/source/hello.js", + "nix", + "nix/sources.nix", + "nixpkgs.toml", + "python", + "python/main.py", + "python/requirements.txt", + "python/virtualenv_proxy.py", + "ruby", + "ruby/bundler.rb", + "rust", + "rust/Cargo.toml", + "rust/src", + "rust/src/main.rs", + "shell", + "shell/foo.sh", + "terraform", + "terraform/main.tf", + "terraform/two.tf", + "touch.toml", + "treefmt.toml", + "yaml", + "yaml/test.yaml", +} + +func TestFilesystemWalker_Walk(t *testing.T) { + tempDir := test.TempExamples(t) + + paths := make(chan string, 1) + go func() { + paths <- tempDir + close(paths) + }() + + as := require.New(t) + + walker, err := NewFilesystem(tempDir, paths) + as.NoError(err) + + idx := 0 + err = walker.Walk(context.Background(), func(file *File, err error) error { + as.Equal(examplesPaths[idx], file.RelPath) + idx += 1 + return nil + }) + as.NoError(err) + + // capture current cwd, so we can replace it after the test is finished + cwd, err := os.Getwd() + as.NoError(err) + t.Cleanup(func() { + // return to the previous working directory + as.NoError(os.Chdir(cwd)) + }) +}