11import os
22import tempfile
3+ from collections .abc import Generator
4+ from contextlib import contextmanager
35
46from git import Repo
57
68from cycode .cli import consts
79from cycode .cli .files_collector .commit_range_documents import get_safe_head_reference_for_diff
810
911
12+ @contextmanager
13+ def git_repository (path : str ) -> Generator [Repo , None , None ]:
14+ """Context manager for Git repositories that ensures proper cleanup on Windows."""
15+ repo = Repo .init (path )
16+ try :
17+ yield repo
18+ finally :
19+ # Properly close the repository to release file handles
20+ repo .close ()
21+
22+
23+ @contextmanager
24+ def temporary_git_repository () -> Generator [tuple [str , Repo ], None , None ]:
25+ """Combined context manager for temporary directory with Git repository."""
26+ with tempfile .TemporaryDirectory () as temp_dir , git_repository (temp_dir ) as repo :
27+ yield temp_dir , repo
28+
29+
1030class TestGetSafeHeadReferenceForDiff :
1131 """Test the safe HEAD reference functionality for git diff operations."""
1232
1333 def test_returns_head_when_repository_has_commits (self ) -> None :
1434 """Test that HEAD is returned when the repository has existing commits."""
15- with tempfile .TemporaryDirectory () as temp_dir :
16- repo = Repo .init (temp_dir )
17-
35+ with temporary_git_repository () as (temp_dir , repo ):
1836 test_file = os .path .join (temp_dir , 'test.py' )
1937 with open (test_file , 'w' ) as f :
2038 f .write ("print('test')" )
@@ -27,9 +45,7 @@ def test_returns_head_when_repository_has_commits(self) -> None:
2745
2846 def test_returns_empty_tree_hash_when_repository_has_no_commits (self ) -> None :
2947 """Test that an empty tree hash is returned when the repository has no commits."""
30- with tempfile .TemporaryDirectory () as temp_dir :
31- repo = Repo .init (temp_dir )
32-
48+ with temporary_git_repository () as (temp_dir , repo ):
3349 result = get_safe_head_reference_for_diff (repo )
3450 expected_empty_tree_hash = consts .GIT_EMPTY_TREE_OBJECT
3551 assert result == expected_empty_tree_hash
@@ -40,9 +56,7 @@ class TestIndexDiffWithSafeHeadReference:
4056
4157 def test_index_diff_works_on_bare_repository (self ) -> None :
4258 """Test that index.diff works on repositories with no commits."""
43- with tempfile .TemporaryDirectory () as temp_dir :
44- repo = Repo .init (temp_dir )
45-
59+ with temporary_git_repository () as (temp_dir , repo ):
4660 test_file = os .path .join (temp_dir , 'staged_file.py' )
4761 with open (test_file , 'w' ) as f :
4862 f .write ("print('staged content')" )
@@ -58,9 +72,7 @@ def test_index_diff_works_on_bare_repository(self) -> None:
5872
5973 def test_index_diff_works_on_repository_with_commits (self ) -> None :
6074 """Test that index.diff continues to work on repositories with existing commits."""
61- with tempfile .TemporaryDirectory () as temp_dir :
62- repo = Repo .init (temp_dir )
63-
75+ with temporary_git_repository () as (temp_dir , repo ):
6476 initial_file = os .path .join (temp_dir , 'initial.py' )
6577 with open (initial_file , 'w' ) as f :
6678 f .write ("print('initial')" )
@@ -88,9 +100,7 @@ def test_index_diff_works_on_repository_with_commits(self) -> None:
88100
89101 def test_sequential_operations_on_same_repository (self ) -> None :
90102 """Test behavior when transitioning from bare to committed repository."""
91- with tempfile .TemporaryDirectory () as temp_dir :
92- repo = Repo .init (temp_dir )
93-
103+ with temporary_git_repository () as (temp_dir , repo ):
94104 test_file = os .path .join (temp_dir , 'test.py' )
95105 with open (test_file , 'w' ) as f :
96106 f .write ("print('test')" )
0 commit comments