Don't depend on working directory in folders.FindDirWithLeaf (#54)

This is plumbing for allowing a configurable root that doesn't depend on
the working directory.
This commit is contained in:
Pieter Noordhuis 2022-09-14 15:08:55 +02:00 committed by GitHub
parent 14a45e701e
commit 281f25a627
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 75 additions and 18 deletions

View File

@ -2,30 +2,33 @@ package folders
import ( import (
"errors" "errors"
"fmt"
"os" "os"
"path" "path/filepath"
) )
func FindDirWithLeaf(leaf string) (string, error) { // FindDirWithLeaf returns the first directory that holds `leaf`,
dir, err := os.Getwd() // traversing up to the root of the filesystem, starting at `dir`.
if err != nil { func FindDirWithLeaf(dir string, leaf string) (string, error) {
return "", fmt.Errorf("cannot find $PWD: %s", err)
}
for { for {
_, err = os.Stat(fmt.Sprintf("%s/%s", dir, leaf)) _, err := os.Stat(filepath.Join(dir, leaf))
// No error means we found the leaf in dir.
if err == nil {
return dir, nil
}
// ErrNotExist means we continue traversal up the tree.
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
// TODO: test on windows next := filepath.Dir(dir)
next := path.Dir(dir) if dir == next {
if dir == next { // or stop at $HOME?.. // Return if we cannot continue traversal.
return "", fmt.Errorf("cannot find %s anywhere", leaf) return "", err
} }
dir = next dir = next
continue continue
} }
if err != nil {
return "", err return "", err
}
return dir, nil
} }
} }

38
folders/folders_test.go Normal file
View File

@ -0,0 +1,38 @@
package folders
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFindDirWithLeaf(t *testing.T) {
wd, err := os.Getwd()
require.NoError(t, err)
root := filepath.Join(wd, "..")
// Find from working directory should work.
{
out, err := FindDirWithLeaf(wd, ".git")
assert.NoError(t, err)
assert.Equal(t, out, root)
}
// Find from project root itself should work.
{
out, err := FindDirWithLeaf(root, ".git")
assert.NoError(t, err)
assert.Equal(t, out, root)
}
// Find for something that doesn't exist should work.
{
out, err := FindDirWithLeaf(root, "this-leaf-doesnt-exist-anywhere")
assert.ErrorIs(t, err, os.ErrNotExist)
assert.Equal(t, out, "")
}
}

View File

@ -3,6 +3,7 @@ package git
import ( import (
"fmt" "fmt"
"net/url" "net/url"
"os"
"path" "path"
"strings" "strings"
@ -12,7 +13,11 @@ import (
) )
func Root() (string, error) { func Root() (string, error) {
return folders.FindDirWithLeaf(".git") wd, err := os.Getwd()
if err != nil {
return "", err
}
return folders.FindDirWithLeaf(wd, ".git")
} }
// Origin finds the git repository the project is cloned from, so that // Origin finds the git repository the project is cloned from, so that

View File

@ -1,6 +1,7 @@
package project package project
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -104,5 +105,15 @@ func validateAndApplyProjectDefaults(prj Project) (Project, error) {
} }
func findProjectRoot() (string, error) { func findProjectRoot() (string, error) {
return folders.FindDirWithLeaf(ConfigFile) wd, err := os.Getwd()
if err != nil {
return "", err
}
dir, err := folders.FindDirWithLeaf(wd, ConfigFile)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return "", fmt.Errorf("cannot find %s anywhere", ConfigFile)
}
}
return dir, nil
} }