Files
kandev/apps/backend/internal/common/gitref/gitref_test.go
T
2026-06-29 14:17:14 +01:00

227 lines
7.9 KiB
Go

package gitref
import (
"os"
"path/filepath"
"testing"
)
// TestDefaultBranch_RejectsRelativePath — guardRepoPath refuses relative
// paths so callers can't sneak `repos/..` past the I/O boundary even if
// the upstream allowlist check is bypassed.
func TestDefaultBranch_RejectsRelativePath(t *testing.T) {
if _, err := DefaultBranch("repos/foo"); err == nil {
t.Fatal("expected error for relative path")
}
}
// TestDefaultBranch_RejectsTraversal — explicit guard against ".."
// segments in the RAW input. We must check before filepath.Clean: Clean
// resolves '..' away from absolute paths (`/allowed/../etc` → `/etc`) and
// would silently let a traversal attempt through.
func TestDefaultBranch_RejectsTraversal(t *testing.T) {
cases := []string{
"/tmp/../etc",
"/foo/bar/../../etc",
"/a/b/..",
}
for _, p := range cases {
if _, err := DefaultBranch(p); err == nil {
t.Errorf("expected error for path %q (contains '..')", p)
}
}
}
// TestDefaultBranch_RejectsEmpty — guardRepoPath errors on empty input
// rather than letting filepath.Join silently turn it into ".git".
func TestDefaultBranch_RejectsEmpty(t *testing.T) {
if _, err := DefaultBranch(""); err == nil {
t.Fatal("expected error for empty path")
}
}
// TestDefaultBranch_AcceptsAbsolutePathToValidRepo — sanity check that
// the guard doesn't reject legitimate absolute paths. We seed a minimal
// .git directory with a HEAD on main and assert the probe finds it.
func TestDefaultBranch_AcceptsAbsolutePathToValidRepo(t *testing.T) {
repoPath := t.TempDir()
if !filepath.IsAbs(repoPath) {
t.Fatalf("t.TempDir() returned non-absolute path: %q", repoPath)
}
gitDir := filepath.Join(repoPath, ".git")
if err := os.MkdirAll(gitDir, 0o755); err != nil {
t.Fatalf("mkdir git: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "HEAD"), []byte("ref: refs/heads/main\n"), 0o644); err != nil {
t.Fatalf("write HEAD: %v", err)
}
branch, err := DefaultBranch(repoPath)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Git branch names are case-sensitive — assert exact equality, not
// EqualFold. A function that returns "Main" or "MAIN" should fail.
if branch != "main" {
t.Fatalf("expected main, got %q", branch)
}
}
func TestDefaultBranch_PrefersMainWhenOriginHeadPointsAtMaster(t *testing.T) {
repoPath := t.TempDir()
gitDir := filepath.Join(repoPath, ".git")
if err := os.MkdirAll(filepath.Join(gitDir, "refs", "remotes", "origin"), 0o755); err != nil {
t.Fatalf("mkdir origin refs: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "HEAD"), []byte("ref: refs/heads/feature/x\n"), 0o644); err != nil {
t.Fatalf("write HEAD: %v", err)
}
if err := os.WriteFile(
filepath.Join(gitDir, "refs", "remotes", "origin", "HEAD"),
[]byte("ref: refs/remotes/origin/master\n"),
0o644,
); err != nil {
t.Fatalf("write origin HEAD: %v", err)
}
for _, branch := range []string{"main", "master"} {
refPath := filepath.Join(gitDir, "refs", "remotes", "origin", branch)
if err := os.WriteFile(refPath, []byte("0000000\n"), 0o644); err != nil {
t.Fatalf("write %s ref: %v", branch, err)
}
}
branch, err := DefaultBranch(repoPath)
if err != nil {
t.Fatalf("DefaultBranch error: %v", err)
}
if branch != "main" {
t.Fatalf("DefaultBranch = %q, want main", branch)
}
}
func TestDefaultBranch_PreservesNonMainOriginHeadWhenMainExists(t *testing.T) {
repoPath := t.TempDir()
gitDir := filepath.Join(repoPath, ".git")
if err := os.MkdirAll(filepath.Join(gitDir, "refs", "remotes", "origin"), 0o755); err != nil {
t.Fatalf("mkdir origin refs: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "HEAD"), []byte("ref: refs/heads/feature/x\n"), 0o644); err != nil {
t.Fatalf("write HEAD: %v", err)
}
if err := os.WriteFile(
filepath.Join(gitDir, "refs", "remotes", "origin", "HEAD"),
[]byte("ref: refs/remotes/origin/trunk\n"),
0o644,
); err != nil {
t.Fatalf("write origin HEAD: %v", err)
}
for _, branch := range []string{"main", "trunk"} {
refPath := filepath.Join(gitDir, "refs", "remotes", "origin", branch)
if err := os.WriteFile(refPath, []byte("0000000\n"), 0o644); err != nil {
t.Fatalf("write %s ref: %v", branch, err)
}
}
branch, err := DefaultBranch(repoPath)
if err != nil {
t.Fatalf("DefaultBranch error: %v", err)
}
if branch != "trunk" {
t.Fatalf("DefaultBranch = %q, want trunk", branch)
}
}
func TestDefaultBranch_LocalMainDoesNotOverrideOriginHeadMaster(t *testing.T) {
repoPath := t.TempDir()
gitDir := filepath.Join(repoPath, ".git")
if err := os.MkdirAll(filepath.Join(gitDir, "refs", "remotes", "origin"), 0o755); err != nil {
t.Fatalf("mkdir origin refs: %v", err)
}
if err := os.MkdirAll(filepath.Join(gitDir, "refs", "heads"), 0o755); err != nil {
t.Fatalf("mkdir local refs: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "HEAD"), []byte("ref: refs/heads/feature/x\n"), 0o644); err != nil {
t.Fatalf("write HEAD: %v", err)
}
if err := os.WriteFile(
filepath.Join(gitDir, "refs", "remotes", "origin", "HEAD"),
[]byte("ref: refs/remotes/origin/master\n"),
0o644,
); err != nil {
t.Fatalf("write origin HEAD: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "refs", "remotes", "origin", "master"), []byte("0000000\n"), 0o644); err != nil {
t.Fatalf("write origin master ref: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "refs", "heads", "main"), []byte("0000000\n"), 0o644); err != nil {
t.Fatalf("write local main ref: %v", err)
}
branch, err := DefaultBranch(repoPath)
if err != nil {
t.Fatalf("DefaultBranch error: %v", err)
}
if branch != "master" {
t.Fatalf("DefaultBranch = %q, want master", branch)
}
}
func TestDefaultBranch_RemoteMasterBeatsLocalMainWithoutOriginHead(t *testing.T) {
repoPath := t.TempDir()
gitDir := filepath.Join(repoPath, ".git")
if err := os.MkdirAll(filepath.Join(gitDir, "refs", "remotes", "origin"), 0o755); err != nil {
t.Fatalf("mkdir origin refs: %v", err)
}
if err := os.MkdirAll(filepath.Join(gitDir, "refs", "heads"), 0o755); err != nil {
t.Fatalf("mkdir local refs: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "HEAD"), []byte("ref: refs/heads/feature/x\n"), 0o644); err != nil {
t.Fatalf("write HEAD: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "refs", "remotes", "origin", "master"), []byte("0000000\n"), 0o644); err != nil {
t.Fatalf("write origin master ref: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "refs", "heads", "main"), []byte("0000000\n"), 0o644); err != nil {
t.Fatalf("write local main ref: %v", err)
}
branch, err := DefaultBranch(repoPath)
if err != nil {
t.Fatalf("DefaultBranch error: %v", err)
}
if branch != "master" {
t.Fatalf("DefaultBranch = %q, want master", branch)
}
}
func TestDefaultBranch_MainNamespaceDoesNotOverrideOriginHeadMaster(t *testing.T) {
repoPath := t.TempDir()
gitDir := filepath.Join(repoPath, ".git")
if err := os.MkdirAll(filepath.Join(gitDir, "refs", "remotes", "origin", "main"), 0o755); err != nil {
t.Fatalf("mkdir origin main namespace: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "HEAD"), []byte("ref: refs/heads/feature/x\n"), 0o644); err != nil {
t.Fatalf("write HEAD: %v", err)
}
if err := os.WriteFile(
filepath.Join(gitDir, "refs", "remotes", "origin", "HEAD"),
[]byte("ref: refs/remotes/origin/master\n"),
0o644,
); err != nil {
t.Fatalf("write origin HEAD: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "refs", "remotes", "origin", "main", "foo"), []byte("0000000\n"), 0o644); err != nil {
t.Fatalf("write origin main/foo ref: %v", err)
}
if err := os.WriteFile(filepath.Join(gitDir, "refs", "remotes", "origin", "master"), []byte("0000000\n"), 0o644); err != nil {
t.Fatalf("write origin master ref: %v", err)
}
branch, err := DefaultBranch(repoPath)
if err != nil {
t.Fatalf("DefaultBranch error: %v", err)
}
if branch != "master" {
t.Fatalf("DefaultBranch = %q, want master", branch)
}
}