diff --git a/pkg/gitinterface/repository.go b/pkg/gitinterface/repository.go index ddd77f36..b0217b12 100644 --- a/pkg/gitinterface/repository.go +++ b/pkg/gitinterface/repository.go @@ -36,7 +36,11 @@ type Repository struct { // GetGoGitRepository returns the go-git representation of a repository. We use // this in certain signing and verifying workflows. func (r *Repository) GetGoGitRepository() (*git.Repository, error) { - return git.PlainOpenWithOptions(r.gitDirPath, &git.PlainOpenOptions{DetectDotGit: true}) + // gitDirPath is already the resolved git directory (set via + // `git rev-parse --git-dir` in LoadRepository), so DetectDotGit must be + // false: with it true, go-git looks for a .git entry inside this path, + // which a bare repository does not have, and returns ErrRepositoryNotExists. + return git.PlainOpenWithOptions(r.gitDirPath, &git.PlainOpenOptions{DetectDotGit: false}) } // GetGitDir returns the GIT_DIR path for the repository. diff --git a/pkg/gitinterface/repository_test.go b/pkg/gitinterface/repository_test.go index 974668f4..7f57edac 100644 --- a/pkg/gitinterface/repository_test.go +++ b/pkg/gitinterface/repository_test.go @@ -64,4 +64,34 @@ func TestRepository(t *testing.T) { _, err := LoadRepository(tmpDir) assert.ErrorContains(t, err, "unable to identify git directory for repository") }) + + t.Run("GetGoGitRepository", func(t *testing.T) { + for _, bare := range []bool{false, true} { + name := "worktree" + if bare { + name = "bare" + } + t.Run(name, func(t *testing.T) { + tmpDir := t.TempDir() + repo := CreateTestGitRepository(t, tmpDir, bare) + ggr, err := repo.GetGoGitRepository() + require.NoError(t, err, "GetGoGitRepository on %s repo", name) + _, err = ggr.Head() + // Empty repo: ErrReferenceNotFound is fine; what matters is the + // repo opened. Anything else (esp. ErrRepositoryNotExists) is a + // failure to open the storage. + if err != nil { + assert.ErrorContains(t, err, "reference not found") + } + }) + } + }) + + t.Run("GetGoGitRepository on .git-suffixed bare repo", func(t *testing.T) { + // Forge-style bare repos are conventionally named .git. + dir := filepath.Join(t.TempDir(), "demo.git") + repo := CreateTestGitRepository(t, dir, true) + _, err := repo.GetGoGitRepository() + require.NoError(t, err) + }) }