fix: don't load non-git repos

Ayman Bagabas created

Fixes: https://github.com/charmbracelet/soft-serve/issues/108

Change summary

git/errors.go       |  2 ++
git/repo.go         | 22 +++++++++++++++++++++-
internal/git/git.go | 10 +++++++---
3 files changed, 30 insertions(+), 4 deletions(-)

Detailed changes

git/errors.go 🔗

@@ -15,4 +15,6 @@ var (
 	ErrReferenceNotFound = errors.New("reference not found")
 	// ErrRevisionNotExist is returned when a revision is not found.
 	ErrRevisionNotExist = git.ErrRevisionNotExist
+	// ErrNotAGitRepository is returned when the given path is not a Git repository.
+	ErrNotAGitRepository = errors.New("not a git repository")
 )

git/repo.go 🔗

@@ -18,7 +18,8 @@ var (
 // Repository is a wrapper around git.Repository with helper methods.
 type Repository struct {
 	*git.Repository
-	Path string
+	Path   string
+	IsBare bool
 }
 
 // Clone clones a repository.
@@ -35,15 +36,34 @@ func Init(path string, bare bool) (*Repository, error) {
 	return Open(path)
 }
 
+func isInsideWorkTree(r *git.Repository) bool {
+	out, err := r.RevParse("--is-inside-work-tree")
+	return err == nil && out == "true"
+}
+
+func isInsideGitDir(r *git.Repository) bool {
+	out, err := r.RevParse("--is-inside-git-dir")
+	return err == nil && out == "true"
+}
+
+func gitDir(r *git.Repository) (string, error) {
+	return r.RevParse("--git-dir")
+}
+
 // Open opens a git repository at the given path.
 func Open(path string) (*Repository, error) {
 	repo, err := git.Open(path)
 	if err != nil {
 		return nil, err
 	}
+	gp, err := gitDir(repo)
+	if err != nil || (gp != "." && gp != ".git") {
+		return nil, ErrNotAGitRepository
+	}
 	return &Repository{
 		Repository: repo,
 		Path:       path,
+		IsBare:     gp == ".",
 	}, nil
 }
 

internal/git/git.go 🔗

@@ -26,8 +26,8 @@ type Repo struct {
 	patchCache *lru.Cache
 }
 
-// Open opens a Git repository.
-func (rs *RepoSource) Open(path string) (*Repo, error) {
+// open opens a Git repository.
+func (rs *RepoSource) open(path string) (*Repo, error) {
 	rg, err := git.Open(path)
 	if err != nil {
 		return nil, err
@@ -199,8 +199,9 @@ func (rs *RepoSource) LoadRepo(name string) error {
 	rs.mtx.Lock()
 	defer rs.mtx.Unlock()
 	rp := filepath.Join(rs.Path, name)
-	r, err := rs.Open(rp)
+	r, err := rs.open(rp)
 	if err != nil {
+		log.Printf("error opening repository %s: %s", name, err)
 		return err
 	}
 	rs.repos[name] = r
@@ -215,6 +216,9 @@ func (rs *RepoSource) LoadRepos() error {
 	}
 	for _, de := range rd {
 		err = rs.LoadRepo(de.Name())
+		if err == git.ErrNotAGitRepository {
+			continue
+		}
 		if err != nil {
 			return err
 		}