package gitutil import ( "os" "os/exec" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestInspectGitState_GitNotAvailable(t *testing.T) { // Reset the PATH env var to simulate git not being available. t.Setenv("PATH", "") tmpDir := t.TempDir() state, err := InspectGitState(tmpDir) require.NoError(t, err) assert.False(t, state.IsRepo) assert.Empty(t, state.SHA) assert.Empty(t, state.ShortSHA(7)) assert.True(t, state.Date.IsZero()) assert.False(t, state.IsDirty) } func TestInspectGitState_NotARepo(t *testing.T) { // Create a temporary directory that's not a git repo. tmpDir := t.TempDir() state, err := InspectGitState(tmpDir) require.NoError(t, err) // If tmpDir happens to be in a git repo (e.g., parent directory), skip this test. // This is common when running tests from within the project itself. if state.IsRepo { t.Skip("tmpDir is within a git repository, skipping test") } assert.False(t, state.IsRepo) assert.Empty(t, state.SHA) assert.Empty(t, state.ShortSHA(7)) assert.True(t, state.Date.IsZero()) // Should have zero time if not a repo. assert.False(t, state.IsDirty) } func TestInspectGitState_EmptyRepo(t *testing.T) { // Create a temporary git repo with no commits. tmpDir := t.TempDir() initGitRepo(t, tmpDir) state, err := InspectGitState(tmpDir) require.NoError(t, err) // An empty repo should be treated as a non-repo so that callers fall back to non-git logic. assert.False(t, state.IsRepo) assert.Empty(t, state.SHA) assert.Empty(t, state.ShortSHA(7)) assert.True(t, state.Date.IsZero()) assert.False(t, state.IsDirty) } func TestInspectGitState_CleanRepo(t *testing.T) { // Create a temporary git repo. tmpDir := t.TempDir() initGitRepo(t, tmpDir) createAndCommitFile(t, tmpDir, "test.txt", "test content") state, err := InspectGitState(tmpDir) require.NoError(t, err) assert.True(t, state.IsRepo) assert.Len(t, state.SHA, 40) assert.Equal(t, state.ShortSHA(7), state.SHA[:7]) assert.False(t, state.Date.IsZero()) assert.False(t, state.IsDirty) } func TestInspectGitState_DirtyRepo(t *testing.T) { // Create a temporary git repo. tmpDir := t.TempDir() initGitRepo(t, tmpDir) createAndCommitFile(t, tmpDir, "test.txt", "test content") // Modify the file to make the repo dirty. err := os.WriteFile(filepath.Join(tmpDir, "test.txt"), []byte("modified content"), 0o644) require.NoError(t, err) state, err := InspectGitState(tmpDir) require.NoError(t, err) assert.True(t, state.IsRepo) assert.True(t, state.IsDirty) } func TestInspectGitState_UntrackedFiles(t *testing.T) { // Create a temporary git repo. tmpDir := t.TempDir() initGitRepo(t, tmpDir) createAndCommitFile(t, tmpDir, "test.txt", "test content") // Add an untracked file. err := os.WriteFile(filepath.Join(tmpDir, "untracked.txt"), []byte("untracked"), 0o644) require.NoError(t, err) state, err := InspectGitState(tmpDir) require.NoError(t, err) assert.True(t, state.IsRepo) assert.True(t, state.IsDirty) // Untracked files make the repo dirty. } func TestGitState_ShortSHA(t *testing.T) { state := &GitState{ SHA: "1234567890abcdef1234567890abcdef12345678", } tests := []struct { name string length int expected string }{ {"short 7", 7, "1234567"}, {"short 10", 10, "1234567890"}, {"full SHA", 40, "1234567890abcdef1234567890abcdef12345678"}, {"longer than SHA", 50, "1234567890abcdef1234567890abcdef12345678"}, {"negative", -42, "1234567890abcdef1234567890abcdef12345678"}, {"zero", 0, "1234567890abcdef1234567890abcdef12345678"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := state.ShortSHA(tt.length) assert.Equal(t, tt.expected, result) }) } } func TestGitState_ShortSHA_Empty(t *testing.T) { state := &GitState{ SHA: "", } result := state.ShortSHA(7) assert.Empty(t, result) } // Helper functions. func initGitRepo(t *testing.T, dir string) { t.Helper() // Initialize git repo. runGitCommand(t, dir, "init") runGitCommand(t, dir, "config", "user.email", "test@example.com") runGitCommand(t, dir, "config", "user.name", "Test User") } func createAndCommitFile(t *testing.T, dir, filename, content string) { t.Helper() // Create file. path := filepath.Join(dir, filename) err := os.WriteFile(path, []byte(content), 0o644) require.NoError(t, err) // Commit file. runGitCommand(t, dir, "add", filename) runGitCommand(t, dir, "commit", "-m", "Add "+filename) } func runGitCommand(t *testing.T, dir string, args ...string) { t.Helper() cmd := exec.Command("git", args...) cmd.Dir = dir output, err := cmd.CombinedOutput() require.NoError(t, err, "git command failed: %s", output) }