test: expand routing and compact coverage
This commit is contained in:
committed by
Steve Yegge
parent
cb280b0fad
commit
12b797781d
@@ -1,21 +1,20 @@
|
|||||||
package compact
|
package compact
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var gitExec = func(name string, args ...string) ([]byte, error) {
|
||||||
|
return exec.Command(name, args...).Output()
|
||||||
|
}
|
||||||
|
|
||||||
// GetCurrentCommitHash returns the current git HEAD commit hash.
|
// GetCurrentCommitHash returns the current git HEAD commit hash.
|
||||||
// Returns empty string if not in a git repository or if git command fails.
|
// Returns empty string if not in a git repository or if git command fails.
|
||||||
func GetCurrentCommitHash() string {
|
func GetCurrentCommitHash() string {
|
||||||
cmd := exec.Command("git", "rev-parse", "HEAD")
|
output, err := gitExec("git", "rev-parse", "HEAD")
|
||||||
var out bytes.Buffer
|
if err != nil {
|
||||||
cmd.Stdout = &out
|
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
return strings.TrimSpace(string(output))
|
||||||
return strings.TrimSpace(out.String())
|
|
||||||
}
|
}
|
||||||
|
|||||||
30
internal/compact/git_test.go
Normal file
30
internal/compact/git_test.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package compact
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetCurrentCommitHashSuccess(t *testing.T) {
|
||||||
|
orig := gitExec
|
||||||
|
gitExec = func(string, ...string) ([]byte, error) {
|
||||||
|
return []byte("abc123\n"), nil
|
||||||
|
}
|
||||||
|
t.Cleanup(func() { gitExec = orig })
|
||||||
|
|
||||||
|
if got := GetCurrentCommitHash(); got != "abc123" {
|
||||||
|
t.Fatalf("expected trimmed hash, got %q", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetCurrentCommitHashError(t *testing.T) {
|
||||||
|
orig := gitExec
|
||||||
|
gitExec = func(string, ...string) ([]byte, error) {
|
||||||
|
return nil, errors.New("boom")
|
||||||
|
}
|
||||||
|
t.Cleanup(func() { gitExec = orig })
|
||||||
|
|
||||||
|
if got := GetCurrentCommitHash(); got != "" {
|
||||||
|
t.Fatalf("expected empty string on error, got %q", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var gitCommandRunner = func(repoPath string, args ...string) ([]byte, error) {
|
||||||
|
cmd := exec.Command("git", args...)
|
||||||
|
if repoPath != "" {
|
||||||
|
cmd.Dir = repoPath
|
||||||
|
}
|
||||||
|
return cmd.Output()
|
||||||
|
}
|
||||||
|
|
||||||
// UserRole represents whether the user is a maintainer or contributor
|
// UserRole represents whether the user is a maintainer or contributor
|
||||||
type UserRole string
|
type UserRole string
|
||||||
|
|
||||||
@@ -22,11 +30,7 @@ const (
|
|||||||
// 3. Fall back to contributor if uncertain
|
// 3. Fall back to contributor if uncertain
|
||||||
func DetectUserRole(repoPath string) (UserRole, error) {
|
func DetectUserRole(repoPath string) (UserRole, error) {
|
||||||
// First check for explicit role in git config
|
// First check for explicit role in git config
|
||||||
cmd := exec.Command("git", "config", "--get", "beads.role")
|
output, err := gitCommandRunner(repoPath, "config", "--get", "beads.role")
|
||||||
if repoPath != "" {
|
|
||||||
cmd.Dir = repoPath
|
|
||||||
}
|
|
||||||
output, err := cmd.Output()
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
role := strings.TrimSpace(string(output))
|
role := strings.TrimSpace(string(output))
|
||||||
if role == string(Maintainer) {
|
if role == string(Maintainer) {
|
||||||
@@ -38,18 +42,10 @@ func DetectUserRole(repoPath string) (UserRole, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check push access by examining remote URL
|
// Check push access by examining remote URL
|
||||||
cmd = exec.Command("git", "remote", "get-url", "--push", "origin")
|
output, err = gitCommandRunner(repoPath, "remote", "get-url", "--push", "origin")
|
||||||
if repoPath != "" {
|
|
||||||
cmd.Dir = repoPath
|
|
||||||
}
|
|
||||||
output, err = cmd.Output()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Fallback to standard fetch URL if push URL fails (some git versions/configs)
|
// Fallback to standard fetch URL if push URL fails (some git versions/configs)
|
||||||
cmd = exec.Command("git", "remote", "get-url", "origin")
|
output, err = gitCommandRunner(repoPath, "remote", "get-url", "origin")
|
||||||
if repoPath != "" {
|
|
||||||
cmd.Dir = repoPath
|
|
||||||
}
|
|
||||||
output, err = cmd.Output()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// No remote or error - default to contributor
|
// No remote or error - default to contributor
|
||||||
return Contributor, nil
|
return Contributor, nil
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package routing
|
package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -142,3 +144,104 @@ func TestResolveToExternalRef(t *testing.T) {
|
|||||||
t.Errorf("ResolveToExternalRef() = %q, want empty string for nonexistent path", got)
|
t.Errorf("ResolveToExternalRef() = %q, want empty string for nonexistent path", got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type gitCall struct {
|
||||||
|
repo string
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type gitResponse struct {
|
||||||
|
expect gitCall
|
||||||
|
output string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
type gitStub struct {
|
||||||
|
t *testing.T
|
||||||
|
responses []gitResponse
|
||||||
|
idx int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *gitStub) run(repo string, args ...string) ([]byte, error) {
|
||||||
|
if s.idx >= len(s.responses) {
|
||||||
|
s.t.Fatalf("unexpected git call %v in repo %s", args, repo)
|
||||||
|
}
|
||||||
|
resp := s.responses[s.idx]
|
||||||
|
s.idx++
|
||||||
|
if resp.expect.repo != repo {
|
||||||
|
s.t.Fatalf("repo mismatch: got %q want %q", repo, resp.expect.repo)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(resp.expect.args, args) {
|
||||||
|
s.t.Fatalf("args mismatch: got %v want %v", args, resp.expect.args)
|
||||||
|
}
|
||||||
|
return []byte(resp.output), resp.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *gitStub) verify() {
|
||||||
|
if s.idx != len(s.responses) {
|
||||||
|
s.t.Fatalf("expected %d git calls, got %d", len(s.responses), s.idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDetectUserRole_ConfigOverrideMaintainer(t *testing.T) {
|
||||||
|
orig := gitCommandRunner
|
||||||
|
stub := &gitStub{t: t, responses: []gitResponse{
|
||||||
|
{expect: gitCall{"", []string{"config", "--get", "beads.role"}}, output: "maintainer\n"},
|
||||||
|
}}
|
||||||
|
gitCommandRunner = stub.run
|
||||||
|
t.Cleanup(func() {
|
||||||
|
gitCommandRunner = orig
|
||||||
|
stub.verify()
|
||||||
|
})
|
||||||
|
|
||||||
|
role, err := DetectUserRole("")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("DetectUserRole error = %v", err)
|
||||||
|
}
|
||||||
|
if role != Maintainer {
|
||||||
|
t.Fatalf("expected %s, got %s", Maintainer, role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDetectUserRole_PushURLMaintainer(t *testing.T) {
|
||||||
|
orig := gitCommandRunner
|
||||||
|
stub := &gitStub{t: t, responses: []gitResponse{
|
||||||
|
{expect: gitCall{"/repo", []string{"config", "--get", "beads.role"}}, output: "unknown"},
|
||||||
|
{expect: gitCall{"/repo", []string{"remote", "get-url", "--push", "origin"}}, output: "git@github.com:owner/repo.git"},
|
||||||
|
}}
|
||||||
|
gitCommandRunner = stub.run
|
||||||
|
t.Cleanup(func() {
|
||||||
|
gitCommandRunner = orig
|
||||||
|
stub.verify()
|
||||||
|
})
|
||||||
|
|
||||||
|
role, err := DetectUserRole("/repo")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("DetectUserRole error = %v", err)
|
||||||
|
}
|
||||||
|
if role != Maintainer {
|
||||||
|
t.Fatalf("expected %s, got %s", Maintainer, role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDetectUserRole_DefaultContributor(t *testing.T) {
|
||||||
|
orig := gitCommandRunner
|
||||||
|
stub := &gitStub{t: t, responses: []gitResponse{
|
||||||
|
{expect: gitCall{"", []string{"config", "--get", "beads.role"}}, err: errors.New("missing")},
|
||||||
|
{expect: gitCall{"", []string{"remote", "get-url", "--push", "origin"}}, err: errors.New("no push")},
|
||||||
|
{expect: gitCall{"", []string{"remote", "get-url", "origin"}}, output: "https://github.com/owner/repo.git"},
|
||||||
|
}}
|
||||||
|
gitCommandRunner = stub.run
|
||||||
|
t.Cleanup(func() {
|
||||||
|
gitCommandRunner = orig
|
||||||
|
stub.verify()
|
||||||
|
})
|
||||||
|
|
||||||
|
role, err := DetectUserRole("")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("DetectUserRole error = %v", err)
|
||||||
|
}
|
||||||
|
if role != Contributor {
|
||||||
|
t.Fatalf("expected %s, got %s", Contributor, role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user