11
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
package git_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"superwork-tui/internal/git"
|
||||
)
|
||||
|
||||
// initBareAndClone creates a bare origin repo and a local clone with one commit.
|
||||
func initBareAndClone(t *testing.T) (origin, clone string) {
|
||||
t.Helper()
|
||||
origin = t.TempDir()
|
||||
clone = t.TempDir()
|
||||
|
||||
run := func(dir string, args ...string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = dir
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("git %v: %v\n%s", args, err, out)
|
||||
}
|
||||
}
|
||||
|
||||
run(origin, "init", "--bare")
|
||||
|
||||
run(clone, "init")
|
||||
run(clone, "config", "user.email", "test@test.com")
|
||||
run(clone, "config", "user.name", "test")
|
||||
run(clone, "remote", "add", "origin", origin)
|
||||
|
||||
f := filepath.Join(clone, "README")
|
||||
if err := os.WriteFile(f, []byte("init"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
run(clone, "add", ".")
|
||||
run(clone, "commit", "-m", "init")
|
||||
run(clone, "push", "origin", "HEAD:refs/heads/main")
|
||||
run(clone, "push", "origin", "HEAD:refs/heads/build")
|
||||
|
||||
return origin, clone
|
||||
}
|
||||
|
||||
func TestCheckBranchSync_SameBranch_Unavailable(t *testing.T) {
|
||||
_, clone := initBareAndClone(t)
|
||||
status, err := git.CheckBranchSync(context.Background(), git.BranchSyncOpts{
|
||||
WorkspaceRoot: clone,
|
||||
DevBranch: "main",
|
||||
AutoBuildBranch: "main",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !status.Unavailable {
|
||||
t.Error("same branch should be Unavailable")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckBranchSync_NotGitRepo_Unavailable(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
status, err := git.CheckBranchSync(context.Background(), git.BranchSyncOpts{
|
||||
WorkspaceRoot: dir,
|
||||
DevBranch: "main",
|
||||
AutoBuildBranch: "build",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !status.Unavailable {
|
||||
t.Error("non-git-repo should be Unavailable")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckBranchSync_ZeroBehind(t *testing.T) {
|
||||
_, clone := initBareAndClone(t)
|
||||
status, err := git.CheckBranchSync(context.Background(), git.BranchSyncOpts{
|
||||
WorkspaceRoot: clone,
|
||||
DevBranch: "main",
|
||||
AutoBuildBranch: "build",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if status.Unavailable {
|
||||
t.Errorf("should be available, reason: %s", status.Reason)
|
||||
}
|
||||
if status.Behind != 0 {
|
||||
t.Errorf("Behind = %d, want 0 (branches are in sync)", status.Behind)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckBranchSync_NonZeroBehind(t *testing.T) {
|
||||
_, clone := initBareAndClone(t)
|
||||
run := func(args ...string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = clone
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("git %v: %v\n%s", args, err, out)
|
||||
}
|
||||
}
|
||||
// Advance main by two commits; build stays behind.
|
||||
for i := 0; i < 2; i++ {
|
||||
f := filepath.Join(clone, "f")
|
||||
if err := os.WriteFile(f, []byte{byte(i)}, 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
run("add", ".")
|
||||
run("commit", "-m", "advance")
|
||||
}
|
||||
run("push", "origin", "HEAD:refs/heads/main")
|
||||
|
||||
status, err := git.CheckBranchSync(context.Background(), git.BranchSyncOpts{
|
||||
WorkspaceRoot: clone,
|
||||
DevBranch: "main",
|
||||
AutoBuildBranch: "build",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if status.Unavailable {
|
||||
t.Fatalf("should be available, reason: %s", status.Reason)
|
||||
}
|
||||
if status.Behind != 2 {
|
||||
t.Errorf("Behind = %d, want 2", status.Behind)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunBranchSync_AdvancesAutoBuild(t *testing.T) {
|
||||
origin, clone := initBareAndClone(t)
|
||||
run := func(args ...string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = clone
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("git %v: %v\n%s", args, err, out)
|
||||
}
|
||||
}
|
||||
f := filepath.Join(clone, "f")
|
||||
if err := os.WriteFile(f, []byte("x"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
run("add", ".")
|
||||
run("commit", "-m", "advance")
|
||||
run("push", "origin", "HEAD:refs/heads/main")
|
||||
|
||||
revOf := func(ref string) string {
|
||||
t.Helper()
|
||||
cmd := exec.Command("git", "-C", origin, "rev-parse", ref)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("rev-parse %s: %v\n%s", ref, err, out)
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
if revOf("main") == revOf("build") {
|
||||
t.Fatal("precondition: build should be behind main")
|
||||
}
|
||||
|
||||
if err := git.RunBranchSync(context.Background(), git.BranchSyncOpts{
|
||||
WorkspaceRoot: clone,
|
||||
DevBranch: "main",
|
||||
AutoBuildBranch: "build",
|
||||
}); err != nil {
|
||||
t.Fatalf("RunBranchSync: %v", err)
|
||||
}
|
||||
|
||||
if revOf("main") != revOf("build") {
|
||||
t.Errorf("build should have advanced to main; main=%q build=%q", revOf("main"), revOf("build"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteLocalBranch_NonExistent_NoOp(t *testing.T) {
|
||||
root := initRepo(t)
|
||||
err := git.DeleteLocalBranch(context.Background(), root, "nonexistent-branch")
|
||||
if err != nil {
|
||||
t.Errorf("DeleteLocalBranch on nonexistent branch should be no-op, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteLocalBranch_Exists_Deletes(t *testing.T) {
|
||||
root := initRepo(t)
|
||||
run := func(args ...string) {
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = root
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("git %v: %v\n%s", args, err, out)
|
||||
}
|
||||
}
|
||||
run("branch", "temp-branch")
|
||||
err := git.DeleteLocalBranch(context.Background(), root, "temp-branch")
|
||||
if err != nil {
|
||||
t.Errorf("DeleteLocalBranch: %v", err)
|
||||
}
|
||||
// Verify branch is gone.
|
||||
cmd := exec.Command("git", "-C", root, "show-ref", "--verify", "refs/heads/temp-branch")
|
||||
if cmd.Run() == nil {
|
||||
t.Error("branch should have been deleted")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user