diff --git a/git/index/fun.py b/git/index/fun.py index f40928c33..1012f4801 100644 --- a/git/index/fun.py +++ b/git/index/fun.py @@ -11,6 +11,7 @@ S_ISDIR, S_IFMT, S_IFREG, + S_IXUSR, ) import subprocess @@ -115,7 +116,7 @@ def stat_mode_to_index_mode(mode): return S_IFLNK if S_ISDIR(mode) or S_IFMT(mode) == S_IFGITLINK: # submodules return S_IFGITLINK - return S_IFREG | 0o644 | (mode & 0o111) # blobs with or without executable bit + return S_IFREG | (mode & S_IXUSR and 0o755 or 0o644) # blobs with or without executable bit def write_cache(entries: Sequence[Union[BaseIndexEntry, 'IndexEntry']], stream: IO[bytes], diff --git a/test/test_fun.py b/test/test_fun.py index a7fb8f8bc..e3d07194b 100644 --- a/test/test_fun.py +++ b/test/test_fun.py @@ -1,5 +1,5 @@ from io import BytesIO -from stat import S_IFDIR, S_IFREG, S_IFLNK +from stat import S_IFDIR, S_IFREG, S_IFLNK, S_IXUSR from os import stat import os.path as osp from unittest import SkipTest @@ -7,7 +7,8 @@ from git import Git from git.index import IndexFile from git.index.fun import ( - aggressive_tree_merge + aggressive_tree_merge, + stat_mode_to_index_mode, ) from git.objects.fun import ( traverse_tree_recursive, @@ -206,6 +207,16 @@ def assert_entries(entries, num_entries, has_conflict=False): assert_entries(aggressive_tree_merge(odb, trees), 2, True) # END handle ours, theirs + def test_stat_mode_to_index_mode(self): + modes = ( + 0o600, 0o611, 0o640, 0o641, 0o644, 0o650, 0o651, + 0o700, 0o711, 0o740, 0o744, 0o750, 0o751, 0o755, + ) + for mode in modes: + expected_mode = S_IFREG | (mode & S_IXUSR and 0o755 or 0o644) + assert stat_mode_to_index_mode(mode) == expected_mode + # END for each mode + def _assert_tree_entries(self, entries, num_trees): for entry in entries: assert len(entry) == num_trees