mirror of
https://github.com/gabrie30/ghorg.git
synced 2026-01-21 16:21:43 +01:00
- Implement SyncDefaultBranch function with 4 safety checks - Add 8 git helper functions (GetRemoteURL, HasLocalChanges, etc.) - Add 640 lines of unit tests for git helpers (git_test.go) - Add 2074 lines of sync tests with 45+ scenarios (sync_test.go) - Integrate GHORG_SYNC_DEFAULT_BRANCH environment variable - Add 8 testing targets to Makefile - Update README.md with comprehensive sync feature documentation - Update sample-conf.yaml with detailed configuration comments - Add test coverage verification document Safety checks implemented: - Skips sync if uncommitted local changes - Skips sync if unpushed commits - Skips sync if commits not on default branch - Skips sync if default branch diverged from HEAD Test coverage: 51.6% overall, 76-100% on new functions
715 lines
19 KiB
Go
715 lines
19 KiB
Go
package git
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gabrie30/ghorg/scm"
|
|
)
|
|
|
|
// createTestGitRepo creates a test git repository with a single commit
|
|
func createTestGitRepo(t *testing.T) (string, func()) {
|
|
t.Helper()
|
|
|
|
tempDir, err := os.MkdirTemp("", "ghorg-git-test-")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp directory: %v", err)
|
|
}
|
|
|
|
cleanup := func() {
|
|
os.RemoveAll(tempDir)
|
|
}
|
|
|
|
// Initialize git repo
|
|
cmd := exec.Command("git", "init")
|
|
cmd.Dir = tempDir
|
|
if err := cmd.Run(); err != nil {
|
|
cleanup()
|
|
t.Fatalf("Failed to initialize git repo: %v", err)
|
|
}
|
|
|
|
// Configure git
|
|
cmd = exec.Command("git", "config", "user.email", "test@example.com")
|
|
cmd.Dir = tempDir
|
|
if err := cmd.Run(); err != nil {
|
|
cleanup()
|
|
t.Fatalf("Failed to configure git user.email: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "config", "user.name", "Test User")
|
|
cmd.Dir = tempDir
|
|
if err := cmd.Run(); err != nil {
|
|
cleanup()
|
|
t.Fatalf("Failed to configure git user.name: %v", err)
|
|
}
|
|
|
|
// Create initial commit
|
|
testFile := filepath.Join(tempDir, "test.txt")
|
|
if err := os.WriteFile(testFile, []byte("test content"), 0644); err != nil {
|
|
cleanup()
|
|
t.Fatalf("Failed to create test file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "add", "test.txt")
|
|
cmd.Dir = tempDir
|
|
if err := cmd.Run(); err != nil {
|
|
cleanup()
|
|
t.Fatalf("Failed to add file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "-c", "commit.gpgsign=false", "commit", "-m", "Initial commit")
|
|
cmd.Dir = tempDir
|
|
if err := cmd.Run(); err != nil {
|
|
cleanup()
|
|
t.Fatalf("Failed to create initial commit: %v", err)
|
|
}
|
|
|
|
// Rename to main branch
|
|
cmd = exec.Command("git", "branch", "-M", "main")
|
|
cmd.Dir = tempDir
|
|
if err := cmd.Run(); err != nil {
|
|
cleanup()
|
|
t.Fatalf("Failed to rename branch to main: %v", err)
|
|
}
|
|
|
|
return tempDir, cleanup
|
|
}
|
|
|
|
func TestGetRemoteURL(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
|
|
t.Run("No remote configured", func(t *testing.T) {
|
|
_, err := client.GetRemoteURL(repo, "origin")
|
|
if err == nil {
|
|
t.Error("Expected error when no remote is configured")
|
|
}
|
|
})
|
|
|
|
t.Run("Remote exists", func(t *testing.T) {
|
|
// Add a remote
|
|
expectedURL := "https://github.com/test/repo.git"
|
|
cmd := exec.Command("git", "remote", "add", "origin", expectedURL)
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add remote: %v", err)
|
|
}
|
|
|
|
url, err := client.GetRemoteURL(repo, "origin")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
|
|
// Git may return URL in different formats (https or ssh)
|
|
// Just verify we got a non-empty URL
|
|
if url == "" {
|
|
t.Error("Expected non-empty URL")
|
|
}
|
|
|
|
// Verify it contains the repo identifier
|
|
if !strings.Contains(url, "test/repo") && !strings.Contains(url, "test:repo") {
|
|
t.Errorf("Expected URL to contain 'test/repo' or 'test:repo', got '%s'", url)
|
|
}
|
|
})
|
|
|
|
t.Run("Non-existent remote", func(t *testing.T) {
|
|
_, err := client.GetRemoteURL(repo, "nonexistent")
|
|
if err == nil {
|
|
t.Error("Expected error for non-existent remote")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestHasLocalChanges(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
|
|
t.Run("Clean working directory", func(t *testing.T) {
|
|
hasChanges, err := client.HasLocalChanges(repo)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if hasChanges {
|
|
t.Error("Expected no local changes in clean working directory")
|
|
}
|
|
})
|
|
|
|
t.Run("Modified file", func(t *testing.T) {
|
|
// Modify file
|
|
testFile := filepath.Join(repoPath, "test.txt")
|
|
if err := os.WriteFile(testFile, []byte("modified content"), 0644); err != nil {
|
|
t.Fatalf("Failed to modify file: %v", err)
|
|
}
|
|
|
|
hasChanges, err := client.HasLocalChanges(repo)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if !hasChanges {
|
|
t.Error("Expected local changes after modifying file")
|
|
}
|
|
|
|
// Clean up
|
|
cmd := exec.Command("git", "checkout", "test.txt")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to restore file: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("Untracked file", func(t *testing.T) {
|
|
// Create untracked file
|
|
newFile := filepath.Join(repoPath, "untracked.txt")
|
|
if err := os.WriteFile(newFile, []byte("untracked"), 0644); err != nil {
|
|
t.Fatalf("Failed to create untracked file: %v", err)
|
|
}
|
|
|
|
hasChanges, err := client.HasLocalChanges(repo)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if !hasChanges {
|
|
t.Error("Expected local changes with untracked file")
|
|
}
|
|
|
|
// Clean up
|
|
os.Remove(newFile)
|
|
})
|
|
}
|
|
|
|
func TestHasUnpushedCommits(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
|
|
t.Run("No upstream configured", func(t *testing.T) {
|
|
_, err := client.HasUnpushedCommits(repo)
|
|
if err == nil {
|
|
t.Error("Expected error when no upstream is configured")
|
|
}
|
|
})
|
|
|
|
t.Run("With upstream and no unpushed commits", func(t *testing.T) {
|
|
// Create bare remote
|
|
bareDir, err := os.MkdirTemp("", "ghorg-bare-")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create bare directory: %v", err)
|
|
}
|
|
defer os.RemoveAll(bareDir)
|
|
|
|
cmd := exec.Command("git", "init", "--bare")
|
|
cmd.Dir = bareDir
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create bare repo: %v", err)
|
|
}
|
|
|
|
// Add remote and push
|
|
cmd = exec.Command("git", "remote", "add", "origin", bareDir)
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add remote: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "push", "-u", "origin", "main")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to push: %v", err)
|
|
}
|
|
|
|
hasUnpushed, err := client.HasUnpushedCommits(repo)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if hasUnpushed {
|
|
t.Error("Expected no unpushed commits after push")
|
|
}
|
|
})
|
|
|
|
t.Run("With unpushed commits", func(t *testing.T) {
|
|
// Create a new commit
|
|
newFile := filepath.Join(repoPath, "new.txt")
|
|
if err := os.WriteFile(newFile, []byte("new content"), 0644); err != nil {
|
|
t.Fatalf("Failed to create new file: %v", err)
|
|
}
|
|
|
|
cmd := exec.Command("git", "add", "new.txt")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "-c", "commit.gpgsign=false", "commit", "-m", "New commit")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create commit: %v", err)
|
|
}
|
|
|
|
hasUnpushed, err := client.HasUnpushedCommits(repo)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if !hasUnpushed {
|
|
t.Error("Expected unpushed commits after local commit")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestGetCurrentBranch(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
|
|
t.Run("Get main branch", func(t *testing.T) {
|
|
branch, err := client.GetCurrentBranch(repo)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if branch != "main" {
|
|
t.Errorf("Expected branch 'main', got '%s'", branch)
|
|
}
|
|
})
|
|
|
|
t.Run("Get feature branch", func(t *testing.T) {
|
|
// Create and checkout feature branch
|
|
cmd := exec.Command("git", "checkout", "-b", "feature")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create feature branch: %v", err)
|
|
}
|
|
|
|
branch, err := client.GetCurrentBranch(repo)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if branch != "feature" {
|
|
t.Errorf("Expected branch 'feature', got '%s'", branch)
|
|
}
|
|
|
|
// Switch back to main
|
|
cmd = exec.Command("git", "checkout", "main")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to checkout main: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestHasCommitsNotOnDefaultBranch(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
|
|
t.Run("Main branch has no extra commits", func(t *testing.T) {
|
|
hasCommits, err := client.HasCommitsNotOnDefaultBranch(repo, "main")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if hasCommits {
|
|
t.Error("Expected no commits not on default branch")
|
|
}
|
|
})
|
|
|
|
t.Run("Feature branch with commits", func(t *testing.T) {
|
|
// Create feature branch
|
|
cmd := exec.Command("git", "checkout", "-b", "feature")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create feature branch: %v", err)
|
|
}
|
|
|
|
// Add commit on feature branch
|
|
newFile := filepath.Join(repoPath, "feature.txt")
|
|
if err := os.WriteFile(newFile, []byte("feature content"), 0644); err != nil {
|
|
t.Fatalf("Failed to create feature file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "add", "feature.txt")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "-c", "commit.gpgsign=false", "commit", "-m", "Feature commit")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create commit: %v", err)
|
|
}
|
|
|
|
hasCommits, err := client.HasCommitsNotOnDefaultBranch(repo, "feature")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if !hasCommits {
|
|
t.Error("Expected commits not on default branch")
|
|
}
|
|
|
|
// Switch back to main
|
|
cmd = exec.Command("git", "checkout", "main")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to checkout main: %v", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestIsDefaultBranchBehindHead(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
|
|
t.Run("Default branch is current", func(t *testing.T) {
|
|
isBehind, err := client.IsDefaultBranchBehindHead(repo, "main")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if !isBehind {
|
|
t.Error("Expected default branch to be ancestor of itself (true)")
|
|
}
|
|
})
|
|
|
|
t.Run("Default branch behind feature branch", func(t *testing.T) {
|
|
// Create feature branch with commits
|
|
cmd := exec.Command("git", "checkout", "-b", "feature")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create feature branch: %v", err)
|
|
}
|
|
|
|
// Add commit
|
|
newFile := filepath.Join(repoPath, "feature.txt")
|
|
if err := os.WriteFile(newFile, []byte("feature content"), 0644); err != nil {
|
|
t.Fatalf("Failed to create feature file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "add", "feature.txt")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "-c", "commit.gpgsign=false", "commit", "-m", "Feature commit")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create commit: %v", err)
|
|
}
|
|
|
|
isBehind, err := client.IsDefaultBranchBehindHead(repo, "feature")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if !isBehind {
|
|
t.Error("Expected default branch to be behind feature branch")
|
|
}
|
|
|
|
// Switch back to main
|
|
cmd = exec.Command("git", "checkout", "main")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to checkout main: %v", err)
|
|
}
|
|
})
|
|
|
|
t.Run("Divergent branches", func(t *testing.T) {
|
|
// Create divergent branch
|
|
cmd := exec.Command("git", "checkout", "-b", "divergent")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create divergent branch: %v", err)
|
|
}
|
|
|
|
// Add commit on divergent
|
|
file1 := filepath.Join(repoPath, "divergent.txt")
|
|
if err := os.WriteFile(file1, []byte("divergent content"), 0644); err != nil {
|
|
t.Fatalf("Failed to create file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "add", "divergent.txt")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "-c", "commit.gpgsign=false", "commit", "-m", "Divergent commit")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create commit: %v", err)
|
|
}
|
|
|
|
// Switch to main and add different commit
|
|
cmd = exec.Command("git", "checkout", "main")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to checkout main: %v", err)
|
|
}
|
|
|
|
file2 := filepath.Join(repoPath, "main.txt")
|
|
if err := os.WriteFile(file2, []byte("main content"), 0644); err != nil {
|
|
t.Fatalf("Failed to create file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "add", "main.txt")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "-c", "commit.gpgsign=false", "commit", "-m", "Main commit")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create commit: %v", err)
|
|
}
|
|
|
|
isBehind, err := client.IsDefaultBranchBehindHead(repo, "divergent")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
if isBehind {
|
|
t.Error("Expected default branch NOT to be behind divergent branch")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestMergeIntoDefaultBranch(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
|
|
t.Run("Fast-forward merge", func(t *testing.T) {
|
|
// Create feature branch
|
|
cmd := exec.Command("git", "checkout", "-b", "feature")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create feature branch: %v", err)
|
|
}
|
|
|
|
// Add commit
|
|
newFile := filepath.Join(repoPath, "feature.txt")
|
|
if err := os.WriteFile(newFile, []byte("feature content"), 0644); err != nil {
|
|
t.Fatalf("Failed to create feature file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "add", "feature.txt")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "-c", "commit.gpgsign=false", "commit", "-m", "Feature commit")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create commit: %v", err)
|
|
}
|
|
|
|
// Merge into main
|
|
err := client.MergeIntoDefaultBranch(repo, "feature")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error during merge: %v", err)
|
|
}
|
|
|
|
// Verify we're on main
|
|
currentBranch, err := client.GetCurrentBranch(repo)
|
|
if err != nil {
|
|
t.Errorf("Failed to get current branch: %v", err)
|
|
}
|
|
if currentBranch != "main" {
|
|
t.Errorf("Expected to be on main branch, got '%s'", currentBranch)
|
|
}
|
|
|
|
// Verify file exists on main
|
|
if _, err := os.Stat(newFile); os.IsNotExist(err) {
|
|
t.Error("Expected merged file to exist on main branch")
|
|
}
|
|
})
|
|
|
|
t.Run("Merge non-existent branch fails", func(t *testing.T) {
|
|
err := client.MergeIntoDefaultBranch(repo, "nonexistent")
|
|
if err == nil {
|
|
t.Error("Expected error when merging non-existent branch")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestUpdateRef(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
|
|
t.Run("Update ref to HEAD", func(t *testing.T) {
|
|
// Create a new branch
|
|
cmd := exec.Command("git", "branch", "test-branch")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create test branch: %v", err)
|
|
}
|
|
|
|
// Add a commit on main
|
|
newFile := filepath.Join(repoPath, "update-ref.txt")
|
|
if err := os.WriteFile(newFile, []byte("content"), 0644); err != nil {
|
|
t.Fatalf("Failed to create file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "add", "update-ref.txt")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to add file: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "-c", "commit.gpgsign=false", "commit", "-m", "Update ref commit")
|
|
cmd.Dir = repoPath
|
|
if err := cmd.Run(); err != nil {
|
|
t.Fatalf("Failed to create commit: %v", err)
|
|
}
|
|
|
|
// Update test-branch ref to point to main
|
|
err := client.UpdateRef(repo, "refs/heads/test-branch", "refs/heads/main")
|
|
if err != nil {
|
|
t.Errorf("Unexpected error updating ref: %v", err)
|
|
}
|
|
|
|
// Verify test-branch now points to same commit as main
|
|
cmd = exec.Command("git", "rev-parse", "main")
|
|
cmd.Dir = repoPath
|
|
mainSHA, err := cmd.Output()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get main SHA: %v", err)
|
|
}
|
|
|
|
cmd = exec.Command("git", "rev-parse", "test-branch")
|
|
cmd.Dir = repoPath
|
|
testSHA, err := cmd.Output()
|
|
if err != nil {
|
|
t.Fatalf("Failed to get test-branch SHA: %v", err)
|
|
}
|
|
|
|
if string(mainSHA) != string(testSHA) {
|
|
t.Error("Expected test-branch to point to same commit as main after UpdateRef")
|
|
}
|
|
})
|
|
|
|
t.Run("Update ref with invalid commitRef fails", func(t *testing.T) {
|
|
err := client.UpdateRef(repo, "refs/heads/test", "nonexistent-ref")
|
|
if err == nil {
|
|
t.Error("Expected error when updating ref with invalid commitRef")
|
|
}
|
|
})
|
|
}
|
|
|
|
// TestErrorHandlingEdgeCases tests additional error handling scenarios
|
|
func TestErrorHandlingEdgeCases(t *testing.T) {
|
|
repoPath, cleanup := createTestGitRepo(t)
|
|
defer cleanup()
|
|
|
|
client := NewGit()
|
|
|
|
t.Run("GetRemoteURL with invalid repo path", func(t *testing.T) {
|
|
repo := scm.Repo{
|
|
HostPath: "/nonexistent/path",
|
|
CloneBranch: "main",
|
|
}
|
|
_, err := client.GetRemoteURL(repo, "origin")
|
|
if err == nil {
|
|
t.Error("Expected error with invalid repo path")
|
|
}
|
|
})
|
|
|
|
t.Run("GetCurrentBranch with invalid repo path", func(t *testing.T) {
|
|
repo := scm.Repo{
|
|
HostPath: "/nonexistent/path",
|
|
CloneBranch: "main",
|
|
}
|
|
_, err := client.GetCurrentBranch(repo)
|
|
if err == nil {
|
|
t.Error("Expected error with invalid repo path")
|
|
}
|
|
})
|
|
|
|
t.Run("HasCommitsNotOnDefaultBranch with invalid branch", func(t *testing.T) {
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
_, err := client.HasCommitsNotOnDefaultBranch(repo, "nonexistent-branch")
|
|
if err == nil {
|
|
t.Error("Expected error with nonexistent branch")
|
|
}
|
|
})
|
|
|
|
t.Run("IsDefaultBranchBehindHead with invalid branch", func(t *testing.T) {
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
_, err := client.IsDefaultBranchBehindHead(repo, "nonexistent-branch")
|
|
if err == nil {
|
|
t.Error("Expected error with nonexistent branch")
|
|
}
|
|
})
|
|
|
|
t.Run("MergeIntoDefaultBranch with invalid default branch", func(t *testing.T) {
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "nonexistent-default",
|
|
}
|
|
err := client.MergeIntoDefaultBranch(repo, "main")
|
|
if err == nil {
|
|
t.Error("Expected error when checking out nonexistent default branch")
|
|
}
|
|
})
|
|
|
|
t.Run("UpdateRef with invalid ref name", func(t *testing.T) {
|
|
repo := scm.Repo{
|
|
HostPath: repoPath,
|
|
CloneBranch: "main",
|
|
}
|
|
err := client.UpdateRef(repo, "invalid..ref", "HEAD")
|
|
if err == nil {
|
|
t.Error("Expected error with invalid ref name")
|
|
}
|
|
})
|
|
}
|