Skip to content

Commit 1a10226

Browse files
Add test for core.hooksPath in bare repositories
Also clean up whitespace and move type import to TYPE_CHECKING block.
1 parent 7977004 commit 1a10226

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

git/index/fun.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
if TYPE_CHECKING:
4949
from git.db import GitCmdObjectDB
5050
from git.objects.tree import TreeCacheTup
51+
from git.repo import Repo
5152

5253
from .base import IndexFile
5354

@@ -61,7 +62,7 @@
6162

6263
def hook_path(name: str, git_dir: PathLike) -> str:
6364
""":return: path to the given named hook in the given git repository directory
64-
65+
6566
Note: This function does not respect the core.hooksPath configuration.
6667
For commit hooks that should respect this config, use run_commit_hook() instead.
6768
"""
@@ -70,25 +71,22 @@ def hook_path(name: str, git_dir: PathLike) -> str:
7071

7172
def _get_hooks_dir(repo: "Repo") -> str:
7273
"""Get the hooks directory, respecting core.hooksPath configuration.
73-
74+
7475
:param repo: The repository to get the hooks directory for.
7576
:return: Path to the hooks directory.
76-
77+
7778
Per git-config documentation, core.hooksPath can be:
7879
- An absolute path: used as-is
7980
- A relative path: relative to the directory where hooks are run from
8081
(typically the working tree root for non-bare repos)
8182
- If not set: defaults to $GIT_DIR/hooks
8283
"""
83-
# Import here to avoid circular imports
84-
from git.repo.base import Repo
85-
8684
try:
8785
hooks_path = repo.config_reader().get_value("core", "hooksPath")
8886
except Exception:
8987
# Config key not found or other error - use default
9088
hooks_path = None
91-
89+
9290
if hooks_path:
9391
hooks_path = str(hooks_path)
9492
if osp.isabs(hooks_path):

test/test_index.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,48 @@ def test_run_commit_hook_respects_relative_core_hookspath(self, rw_repo):
11351135
output = output_file.read_text(encoding="utf-8")
11361136
self.assertEqual(output, "ran from relative hooks path\n")
11371137

1138+
@pytest.mark.xfail(
1139+
type(_win_bash_status) is WinBashStatus.Absent,
1140+
reason="Can't run a hook on Windows without bash.exe.",
1141+
raises=HookExecutionError,
1142+
)
1143+
@pytest.mark.xfail(
1144+
type(_win_bash_status) is WinBashStatus.WslNoDistro,
1145+
reason="Currently uses the bash.exe of WSL, even with no WSL distro installed",
1146+
raises=HookExecutionError,
1147+
)
1148+
@with_rw_repo("HEAD", bare=True)
1149+
def test_run_commit_hook_respects_core_hookspath_bare_repo(self, rw_repo):
1150+
"""Test that run_commit_hook() respects core.hooksPath in bare repositories.
1151+
1152+
For bare repos, relative paths should be resolved relative to git_dir since
1153+
there is no working tree.
1154+
"""
1155+
index = rw_repo.index
1156+
1157+
# Create a custom hooks directory (use absolute path for bare repo)
1158+
# Use a unique name based on the repo to avoid conflicts
1159+
custom_hooks_dir = Path(rw_repo.git_dir).parent / "bare-custom-hooks"
1160+
custom_hooks_dir.mkdir(exist_ok=True)
1161+
1162+
# Create a hook in the custom location
1163+
custom_hook = custom_hooks_dir / "fake-hook"
1164+
custom_hook.write_text(HOOKS_SHEBANG + "echo 'ran from custom hooks path in bare repo' >output.txt")
1165+
custom_hook.chmod(0o744)
1166+
1167+
# Set core.hooksPath in the repo config (absolute path)
1168+
with rw_repo.config_writer() as config:
1169+
config.set_value("core", "hooksPath", str(custom_hooks_dir))
1170+
1171+
# Run the hook - it should use the custom path
1172+
run_commit_hook("fake-hook", index)
1173+
1174+
# Output goes to cwd, which for bare repos during hook execution is git_dir
1175+
output_file = Path(rw_repo.git_dir) / "output.txt"
1176+
self.assertTrue(output_file.exists(), "Hook should have created output.txt")
1177+
output = output_file.read_text(encoding="utf-8")
1178+
self.assertEqual(output, "ran from custom hooks path in bare repo\n")
1179+
11381180
@ddt.data((False,), (True,))
11391181
@with_rw_directory
11401182
def test_hook_uses_shell_not_from_cwd(self, rw_dir, case):

0 commit comments

Comments
 (0)