Skip to content

Commit

Permalink
fix shuttle should search recursively for shuttle files (#209)
Browse files Browse the repository at this point in the history
The reason is that all the other commands support it, so we should register the commands if a shuttle file is available.

The change was made to search recursively until the path is empty. If a given path --project or -p is supplied, we won't do recursive checks.

Signed-off-by: Kasper J. Hermansen <[email protected]>
  • Loading branch information
kjuulh authored Jan 5, 2024
1 parent 5c0cc23 commit d82da95
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 10 deletions.
42 changes: 32 additions & 10 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package cmd

import (
stdcontext "context"
"errors"
"fmt"
"io"
"log"
"os"
"path"
"strings"

"github.com/spf13/cobra"

Expand Down Expand Up @@ -281,26 +281,48 @@ func getProjectContext(

// getRepositoryContext makes sure that we're in a repository context, this is useful to add extra commands, which are only useful when in a repository with a shuttle file
func getRepositoryContext(projectPath string) bool {

var fullProjectPath string
if path.IsAbs(projectPath) {
fullProjectPath = projectPath
if projectPath != "" && projectPath != "." {
return shuttleFileExists(projectPath, fileExists)
} else {
dir, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

fullProjectPath = path.Join(dir, projectPath)
fullProjectPath := path.Join(dir, projectPath)
exists := shuttleFileExistsRecursive(fullProjectPath, fileExists)
return exists
}
}

shuttleFile := path.Join(fullProjectPath, "shuttle.yaml")
type fileExistsFunc func(filePath string) bool

if _, err := os.Stat(shuttleFile); err != nil {
if errors.Is(err, os.ErrNotExist) {
return false
// shuttleFileExistsRecursive tries to find a shuttle file by going towards the root the path, it will check each folder towards the root.
func shuttleFileExistsRecursive(projectPath string, existsFunc fileExistsFunc) bool {
if strings.Contains(projectPath, "/") {
exists := shuttleFileExists(projectPath, existsFunc)
if exists {
return true
}

return shuttleFileExistsRecursive(path.Dir(projectPath), existsFunc)

}

return shuttleFileExists(projectPath, existsFunc)

}

// shuttleFileExists will check the given directory and return if a shuttle.yaml file is found
func shuttleFileExists(projectPath string, existsFunc fileExistsFunc) bool {
shuttleFile := path.Join(projectPath, "shuttle.yaml")
return existsFunc(shuttleFile)
}

func fileExists(filePath string) bool {
_, err := os.Stat(filePath)
if err != nil {
return false
}
return true
}
155 changes: 155 additions & 0 deletions cmd/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package cmd

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestShuttleFileExists(t *testing.T) {
t.Parallel()

t.Run("full path, with file", func(t *testing.T) {
actual := shuttleFileExists("/some/long/path", func(filePath string) bool {
switch filePath {
case "/some/long/path/shuttle.yaml":
return true
default:
pathNotExpected(t, filePath)
return false
}
})

assert.True(t, actual)
})

t.Run("full path, no file", func(t *testing.T) {
actual := shuttleFileExists("/some/long/path", func(filePath string) bool {
switch filePath {
case "/some/long/path/shuttle.yaml":
return false
default:
pathNotExpected(t, filePath)
return true
}
})

assert.False(t, actual)
})

t.Run("current path, with file", func(t *testing.T) {
actual := shuttleFileExists(".", func(filePath string) bool {
switch filePath {
case "shuttle.yaml":
return true
default:
pathNotExpected(t, filePath)
return false
}
})

assert.True(t, actual)
})

t.Run("current path, no file", func(t *testing.T) {
actual := shuttleFileExists(".", func(filePath string) bool {
switch filePath {
case "shuttle.yaml":
return false
default:
pathNotExpected(t, filePath)
return true
}
})

assert.False(t, actual)
})
}

func TestShuttleFileExistsRecursive(t *testing.T) {
t.Parallel()

t.Run("full path, file in given path", func(t *testing.T) {
actual := shuttleFileExistsRecursive("/some/long/path", func(filePath string) bool {
switch filePath {
case "/some/long/path/shuttle.yaml":
return true
default:
pathNotExpected(t, filePath)
return false
}
})

assert.True(t, actual)
})

t.Run("full path, file in sub directory", func(t *testing.T) {
actual := shuttleFileExistsRecursive("/some/long/path", func(filePath string) bool {
switch filePath {
case "/some/long/path/shuttle.yaml":
return false
case "/some/long/shuttle.yaml":
return true
default:
pathNotExpected(t, filePath)
return false
}
})

assert.True(t, actual)
})

t.Run("full path, file in root", func(t *testing.T) {
actual := shuttleFileExistsRecursive("/some/long/path", func(filePath string) bool {
switch filePath {
case "/some/long/path/shuttle.yaml":
return false
case "/some/long/shuttle.yaml":
return false
case "/some/shuttle.yaml":
return false
case "/shuttle.yaml":
return true
default:
pathNotExpected(t, filePath)
return false
}
})

assert.True(t, actual)
})

t.Run("empty path, file false", func(t *testing.T) {
actual := shuttleFileExistsRecursive("", func(filePath string) bool {
switch filePath {
case "shuttle.yaml":
return false
default:
pathNotExpected(t, filePath)
return false
}
})

assert.False(t, actual)
})

t.Run("current dir, file found", func(t *testing.T) {
actual := shuttleFileExistsRecursive(".", func(filePath string) bool {
switch filePath {
case "shuttle.yaml":
return true
default:
pathNotExpected(t, filePath)
return false
}
})

assert.True(t, actual)
})
}

func pathNotExpected(t *testing.T, filePath string) {
t.Helper()

assert.Fail(t, "path was not expected", "the path %s was not expected in matcher", filePath)
}

0 comments on commit d82da95

Please sign in to comment.