nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: gitpython-developers/GitPython
Pull request #2012 (2025-03-07 17:39:58)

`IndexFile._to_relative_path` - fix case where absolute path gets stripped of trailing slash
I encountered this issue on MacOS, python 3.7 and later

Added fix and appropriate unit test.

Stripping of trailing slash seems to be happening in `os.path.relpath`, altough I am not sure whether that is expected behaviour. In case it is not expected, and ever gets fixed, I added an additional check (` and not result.endswith(os.sep)`) to make sure that the trailing slash doesn't get duplicated.


Patch:
diff --git a/git/index/base.py b/git/index/base.py
index 39cc9143..65b1f930 100644
--- a/git/index/base.py
+++ b/git/index/base.py
@@ -655,7 +655,10 @@ class IndexFile(LazyMixin, git_diff.Diffable, Serializable):
             raise InvalidGitRepositoryError("require non-bare repository")
         if not osp.normpath(str(path)).startswith(str(self.repo.working_tree_dir)):
             raise ValueError("Absolute path %r is not in git repository at %r" % (path, self.repo.working_tree_dir))
-        return os.path.relpath(path, self.repo.working_tree_dir)
+        result = os.path.relpath(path, self.repo.working_tree_dir)
+        if str(path).endswith(os.sep) and not result.endswith(os.sep):
+            result += os.sep
+        return result
 
     def _preprocess_add_items(
         self, items: Union[PathLike, Sequence[Union[PathLike, Blob, BaseIndexEntry, "Submodule"]]]


Test patch:
diff --git a/test/test_index.py b/test/test_index.py
index c586a0b5..c42032e7 100644
--- a/test/test_index.py
+++ b/test/test_index.py
@@ -16,6 +16,7 @@ from stat import S_ISLNK, ST_MODE
 import subprocess
 import sys
 import tempfile
+from unittest import mock
 
 from gitdb.base import IStream
 
@@ -1015,6 +1016,27 @@ class TestIndex(TestBase):
         rel = index._to_relative_path(path)
         self.assertEqual(rel, os.path.relpath(path, root))
 
+    def test__to_relative_path_absolute_trailing_slash(self):
+        repo_root = os.path.join(osp.abspath(os.sep), "directory1", "repo_root")
+
+        class Mocked:
+            bare = False
+            git_dir = repo_root
+            working_tree_dir = repo_root
+
+        repo = Mocked()
+        path = os.path.join(repo_root, f"directory2{os.sep}")
+        index = IndexFile(repo)
+
+        expected_path = f"directory2{os.sep}"
+        actual_path = index._to_relative_path(path)
+        self.assertEqual(expected_path, actual_path)
+
+        with mock.patch("git.index.base.os.path") as ospath_mock:
+            ospath_mock.relpath.return_value = f"directory2{os.sep}"
+            actual_path = index._to_relative_path(path)
+            self.assertEqual(expected_path, actual_path)
+
     @pytest.mark.xfail(
         type(_win_bash_status) is WinBashStatus.Absent,
         reason="Can't run a hook on Windows without bash.exe.",