@@ -155,3 +155,184 @@ def test_git_mv_pre_commit_scan() -> None:
155155 for diff in diff_index :
156156 file_path = get_path_by_os (get_diff_file_path (diff , repo = repo ))
157157 assert file_path == renamed_path
158+
159+
160+ class TestGetDiffFilePath :
161+ """Test the get_diff_file_path function with various diff scenarios."""
162+
163+ def test_diff_with_b_blob_and_working_tree (self ) -> None :
164+ """Test that blob.abspath is returned when b_blob is available and repo has a working tree."""
165+ with temporary_git_repository () as (temp_dir , repo ):
166+ test_file = os .path .join (temp_dir , 'test_file.py' )
167+ with open (test_file , 'w' ) as f :
168+ f .write ("print('original content')" )
169+
170+ repo .index .add (['test_file.py' ])
171+ repo .index .commit ('Initial commit' )
172+
173+ with open (test_file , 'w' ) as f :
174+ f .write ("print('modified content')" )
175+
176+ repo .index .add (['test_file.py' ])
177+
178+ # Get diff of staged changes
179+ head_ref = get_safe_head_reference_for_diff (repo )
180+ diff_index = repo .index .diff (head_ref )
181+
182+ assert len (diff_index ) == 1
183+
184+ result = get_diff_file_path (diff_index [0 ], repo = repo )
185+
186+ assert result == test_file
187+ assert os .path .isabs (result )
188+
189+ def test_diff_with_a_blob_only_and_working_tree (self ) -> None :
190+ """Test that a_blob.abspath is used when b_blob is None but a_blob exists."""
191+ with temporary_git_repository () as (temp_dir , repo ):
192+ test_file = os .path .join (temp_dir , 'to_delete.py' )
193+ with open (test_file , 'w' ) as f :
194+ f .write ("print('will be deleted')" )
195+
196+ repo .index .add (['to_delete.py' ])
197+ repo .index .commit ('Initial commit' )
198+
199+ os .remove (test_file )
200+ repo .index .remove (['to_delete.py' ])
201+
202+ # Get diff of staged changes
203+ head_ref = get_safe_head_reference_for_diff (repo )
204+ diff_index = repo .index .diff (head_ref )
205+
206+ assert len (diff_index ) == 1
207+
208+ result = get_diff_file_path (diff_index [0 ], repo = repo )
209+
210+ assert result == test_file
211+ assert os .path .isabs (result )
212+
213+ def test_diff_with_b_path_fallback (self ) -> None :
214+ """Test that b_path is used with working_tree_dir when blob is not available."""
215+ with temporary_git_repository () as (temp_dir , repo ):
216+ test_file = os .path .join (temp_dir , 'new_file.py' )
217+ with open (test_file , 'w' ) as f :
218+ f .write ("print('new file')" )
219+
220+ repo .index .add (['new_file.py' ])
221+
222+ # for new files, there's no a_blob
223+ head_ref = get_safe_head_reference_for_diff (repo )
224+ diff_index = repo .index .diff (head_ref )
225+ diff = diff_index [0 ]
226+
227+ assert len (diff_index ) == 1
228+
229+ result = get_diff_file_path (diff , repo = repo )
230+ assert result == test_file
231+ assert os .path .isabs (result )
232+
233+ result = get_diff_file_path (diff , relative = True , repo = repo )
234+ assert test_file .endswith (result )
235+ assert not os .path .isabs (result )
236+
237+ def test_diff_with_a_path_fallback (self ) -> None :
238+ """Test that a_path is used when b_path is None."""
239+ with temporary_git_repository () as (temp_dir , repo ):
240+ test_file = os .path .join (temp_dir , 'deleted_file.py' )
241+ with open (test_file , 'w' ) as f :
242+ f .write ("print('will be deleted')" )
243+
244+ repo .index .add (['deleted_file.py' ])
245+ repo .index .commit ('Initial commit' )
246+
247+ # for deleted files, b_path might be None, so a_path should be used
248+ os .remove (test_file )
249+ repo .index .remove (['deleted_file.py' ])
250+
251+ head_ref = get_safe_head_reference_for_diff (repo )
252+ diff_index = repo .index .diff (head_ref )
253+
254+ assert len (diff_index ) == 1
255+ diff = diff_index [0 ]
256+
257+ result = get_diff_file_path (diff , repo = repo )
258+ assert result == test_file
259+ assert os .path .isabs (result )
260+
261+ result = get_diff_file_path (diff , relative = True , repo = repo )
262+ assert test_file .endswith (result )
263+ assert not os .path .isabs (result )
264+
265+ def test_diff_without_repo (self ) -> None :
266+ """Test behavior when repo is None."""
267+ with temporary_git_repository () as (temp_dir , repo ):
268+ test_file = os .path .join (temp_dir , 'test.py' )
269+ with open (test_file , 'w' ) as f :
270+ f .write ("print('test')" )
271+
272+ repo .index .add (['test.py' ])
273+ head_ref = get_safe_head_reference_for_diff (repo )
274+ diff_index = repo .index .diff (head_ref )
275+
276+ assert len (diff_index ) == 1
277+ diff = diff_index [0 ]
278+
279+ result = get_diff_file_path (diff , repo = None )
280+
281+ expected_path = diff .b_path or diff .a_path
282+ assert result == expected_path
283+ assert not os .path .isabs (result )
284+
285+ def test_diff_with_bare_repository (self ) -> None :
286+ """Test behavior when the repository has no working tree directory."""
287+ with tempfile .TemporaryDirectory () as temp_dir :
288+ bare_repo = Repo .init (temp_dir , bare = True )
289+
290+ try :
291+ # Create a regular repo to push to the bare repo
292+ with tempfile .TemporaryDirectory () as work_dir :
293+ work_repo = Repo .init (work_dir , b = 'main' )
294+ try :
295+ test_file = os .path .join (work_dir , 'test.py' )
296+ with open (test_file , 'w' ) as f :
297+ f .write ("print('test')" )
298+
299+ work_repo .index .add (['test.py' ])
300+ work_repo .index .commit ('Initial commit' )
301+
302+ work_repo .create_remote ('origin' , temp_dir )
303+ work_repo .remotes .origin .push ('main:main' )
304+
305+ with open (test_file , 'w' ) as f :
306+ f .write ("print('modified')" )
307+ work_repo .index .add (['test.py' ])
308+
309+ # Get diff
310+ diff_index = work_repo .index .diff ('HEAD' )
311+ assert len (diff_index ) == 1
312+ diff = diff_index [0 ]
313+
314+ # Test with bare repo (no working_tree_dir)
315+ result = get_diff_file_path (diff , repo = bare_repo )
316+
317+ # Should return a relative path since bare repo has no working tree
318+ expected_path = diff .b_path or diff .a_path
319+ assert result == expected_path
320+ assert not os .path .isabs (result )
321+ finally :
322+ work_repo .close ()
323+ finally :
324+ bare_repo .close ()
325+
326+ def test_diff_with_no_paths (self ) -> None :
327+ """Test behavior when the diff has neither a_path nor b_path."""
328+ with temporary_git_repository () as (temp_dir , repo ):
329+
330+ class MockDiff :
331+ def __init__ (self ) -> None :
332+ self .a_path = None
333+ self .b_path = None
334+ self .a_blob = None
335+ self .b_blob = None
336+
337+ result = get_diff_file_path (MockDiff (), repo = repo )
338+ assert result is None
0 commit comments