pkg/gitinterface: open go-git with DetectDotGit:false

GetGoGitRepository was passing DetectDotGit:true to PlainOpenWithOptions
on a path that is already the resolved git directory (set from
'git rev-parse --git-dir' in LoadRepository). With detect on, go-git
looks for a .git entry inside that path; a bare repository has none, so
it returns ErrRepositoryNotExists and every caller (verifyCommitSignature,
tag verification) fails on bare repos.

DetectDotGit:false treats the path as the git dir directly and opens
both bare and working-tree layouts.

Adds tests covering GetGoGitRepository on bare repos including the
forge-conventional <name>.git layout.

Signed-off-by: Andrew Nesbitt <andrewnez@gmail.com>
This commit is contained in:
Andrew Nesbitt 2026-06-16 09:49:47 +01:00
parent a3caad7165
commit bf84dfd79a
No known key found for this signature in database
GPG key ID: 4B082F67059F4038
2 changed files with 35 additions and 1 deletions

View file

@ -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.

View file

@ -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 <name>.git.
dir := filepath.Join(t.TempDir(), "demo.git")
repo := CreateTestGitRepository(t, dir, true)
_, err := repo.GetGoGitRepository()
require.NoError(t, err)
})
}