Skip to content

Commit e85a895

Browse files
authoredMar 12, 2025
Merge pull request #2012 from kamilkozik7/fix-trailing-slash
`IndexFile._to_relative_path` - fix case where absolute path gets stripped of trailing slash
2 parents dc7ba87 + 11f7faf commit e85a895

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed
 

‎git/index/base.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,10 @@ def _to_relative_path(self, path: PathLike) -> PathLike:
655655
raise InvalidGitRepositoryError("require non-bare repository")
656656
if not osp.normpath(str(path)).startswith(str(self.repo.working_tree_dir)):
657657
raise ValueError("Absolute path %r is not in git repository at %r" % (path, self.repo.working_tree_dir))
658-
return os.path.relpath(path, self.repo.working_tree_dir)
658+
result = os.path.relpath(path, self.repo.working_tree_dir)
659+
if str(path).endswith(os.sep) and not result.endswith(os.sep):
660+
result += os.sep
661+
return result
659662

660663
def _preprocess_add_items(
661664
self, items: Union[PathLike, Sequence[Union[PathLike, Blob, BaseIndexEntry, "Submodule"]]]

‎test/test_index.py

+22
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import subprocess
1717
import sys
1818
import tempfile
19+
from unittest import mock
1920

2021
from gitdb.base import IStream
2122

@@ -1015,6 +1016,27 @@ class Mocked:
10151016
rel = index._to_relative_path(path)
10161017
self.assertEqual(rel, os.path.relpath(path, root))
10171018

1019+
def test__to_relative_path_absolute_trailing_slash(self):
1020+
repo_root = os.path.join(osp.abspath(os.sep), "directory1", "repo_root")
1021+
1022+
class Mocked:
1023+
bare = False
1024+
git_dir = repo_root
1025+
working_tree_dir = repo_root
1026+
1027+
repo = Mocked()
1028+
path = os.path.join(repo_root, f"directory2{os.sep}")
1029+
index = IndexFile(repo)
1030+
1031+
expected_path = f"directory2{os.sep}"
1032+
actual_path = index._to_relative_path(path)
1033+
self.assertEqual(expected_path, actual_path)
1034+
1035+
with mock.patch("git.index.base.os.path") as ospath_mock:
1036+
ospath_mock.relpath.return_value = f"directory2{os.sep}"
1037+
actual_path = index._to_relative_path(path)
1038+
self.assertEqual(expected_path, actual_path)
1039+
10181040
@pytest.mark.xfail(
10191041
type(_win_bash_status) is WinBashStatus.Absent,
10201042
reason="Can't run a hook on Windows without bash.exe.",

0 commit comments

Comments
 (0)
Failed to load comments.