b8622ddd60a831ec5e82333e8c47f4706d65253e / cmd/simplegit/main_test.go · 4521 bytes · raw
package main
import (
"database/sql"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"git.josie-c.com/josie/simplegit/internal/db"
"git.josie-c.com/josie/simplegit/internal/git"
)
func runGit(t *testing.T, dir string, args ...string) {
t.Helper()
cmd := exec.Command("git", args...)
cmd.Dir = dir
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("git %v: %v: %s", args, err, out)
}
}
func hashObject(t *testing.T, repoPath, content string) string {
t.Helper()
cmd := exec.Command("git", "hash-object", "-w", "--stdin")
cmd.Dir = repoPath
cmd.Stdin = strings.NewReader(content)
out, err := cmd.Output()
if err != nil {
t.Fatalf("hash-object: %v", err)
}
return strings.TrimSpace(string(out))
}
// commitToBranch writes a one-file commit and points branch at it.
func commitToBranch(t *testing.T, repoPath, branch string) string {
t.Helper()
blob := hashObject(t, repoPath, "hello\n")
treeCmd := exec.Command("git", "mktree")
treeCmd.Dir = repoPath
treeCmd.Stdin = strings.NewReader("100644 blob " + blob + "\tfile\n")
treeOut, err := treeCmd.Output()
if err != nil {
t.Fatalf("mktree: %v", err)
}
commitCmd := exec.Command("git", "commit-tree", strings.TrimSpace(string(treeOut)), "-m", "seed")
commitCmd.Dir = repoPath
commitCmd.Env = append(os.Environ(),
"GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@t",
"GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@t")
commitOut, err := commitCmd.Output()
if err != nil {
t.Fatalf("commit-tree: %v", err)
}
sha := strings.TrimSpace(string(commitOut))
runGit(t, repoPath, "update-ref", "refs/heads/"+branch, sha)
return sha
}
func newHookFixture(t *testing.T) (string, *sql.DB) {
t.Helper()
dataDir := t.TempDir()
repoPath := filepath.Join(dataDir, "repos", "josie", "demo.git")
if err := os.MkdirAll(filepath.Dir(repoPath), 0o755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if err := git.InitBare(repoPath, "main"); err != nil {
t.Fatalf("InitBare: %v", err)
}
database, err := db.Open(filepath.Join(dataDir, "simplegit.db"))
if err != nil {
t.Fatalf("db.Open: %v", err)
}
t.Cleanup(func() { database.Close() })
ownerID, err := db.CreateUser(database, "josie", "hash")
if err != nil {
t.Fatalf("CreateUser: %v", err)
}
if _, err := db.CreateRepo(database, ownerID, "demo", "", "private"); err != nil {
t.Fatalf("CreateRepo: %v", err)
}
return repoPath, database
}
func runHookWithStdin(t *testing.T, repoPath, stdin string) error {
t.Helper()
r, w, err := os.Pipe()
if err != nil {
t.Fatalf("pipe: %v", err)
}
old := os.Stdin
os.Stdin = r
defer func() {
os.Stdin = old
r.Close()
}()
go func() {
_, _ = io.WriteString(w, stdin)
w.Close()
}()
return runHook([]string{"--repo", repoPath})
}
func TestRunHookEstablishesDefaultBranch(t *testing.T) {
repoPath, database := newHookFixture(t)
sha := commitToBranch(t, repoPath, "master")
stdin := "0000000000000000000000000000000000000000 " + sha + " refs/heads/master\n"
if err := runHookWithStdin(t, repoPath, stdin); err != nil {
t.Fatalf("runHook: %v", err)
}
repo, err := db.GetRepoByName(database, "josie", "demo")
if err != nil {
t.Fatalf("GetRepoByName: %v", err)
}
if repo.DefaultBranch != "master" {
t.Errorf("DefaultBranch = %q, want master", repo.DefaultBranch)
}
if !repo.PushedAt.Valid {
t.Error("PushedAt is NULL, want a timestamp")
}
if branch, err := git.DefaultBranch(repoPath); err != nil || branch != "master" {
t.Errorf("HEAD branch = %q, %v; want master", branch, err)
}
}
func TestRunHookKeepsExistingDefaultBranch(t *testing.T) {
repoPath, database := newHookFixture(t)
sha := commitToBranch(t, repoPath, "main")
stdin := "0000000000000000000000000000000000000000 " + sha + " refs/heads/main\n"
if err := runHookWithStdin(t, repoPath, stdin); err != nil {
t.Fatalf("runHook: %v", err)
}
repo, err := db.GetRepoByName(database, "josie", "demo")
if err != nil {
t.Fatalf("GetRepoByName: %v", err)
}
if repo.DefaultBranch != "main" {
t.Errorf("DefaultBranch = %q, want unchanged main", repo.DefaultBranch)
}
}
func TestSplitRepoPath(t *testing.T) {
owner, name, dataDir, err := splitRepoPath("/srv/simplegit/data/repos/josie/demo.git")
if err != nil {
t.Fatalf("splitRepoPath: %v", err)
}
if owner != "josie" || name != "demo" || dataDir != "/srv/simplegit/data" {
t.Errorf("split = %q/%q in %q", owner, name, dataDir)
}
if _, _, _, err := splitRepoPath("/tmp/not-a-repo"); err == nil {
t.Error("splitRepoPath accepted a non-.git path")
}
}