From e1947826fc0fccc39c2082846804ad4ddd751bcf Mon Sep 17 00:00:00 2001 From: Koushik-Salammagari <138836560+Koushik-Salammagari@users.noreply.github.com> Date: Sat, 2 May 2026 06:14:46 -0700 Subject: [PATCH] fix(hooks): expand ~ in core.hooksPath before resolving install target (#554) When a user configures core.hooksPath = ~/gitconfig/hooks in .gitconfig, _hooks_dir() was constructing Path("~/gitconfig/hooks") without calling expanduser(), so hooks were installed into /~/gitconfig/hooks instead of the intended absolute path. Add Path.expanduser() call immediately after reading the raw string from git config, before the is_absolute() / root-relative fallback logic. Fixes #547 --- tests/test_hooks.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/test_hooks.py b/tests/test_hooks.py index 14a7ad86..74afb8ea 100644 --- a/tests/test_hooks.py +++ b/tests/test_hooks.py @@ -123,3 +123,30 @@ def test_hook_skips_head_on_exe(): """Hook script must skip shebang extraction for .exe binaries (Windows).""" from graphify.hooks import _PYTHON_DETECT assert "*.exe) _SHEBANG=" in _PYTHON_DETECT or '*.exe)' in _PYTHON_DETECT + + +def test_hooks_dir_expands_tilde(tmp_path, monkeypatch): + """_hooks_dir must call expanduser() so ~/... paths in core.hooksPath resolve correctly.""" + from graphify.hooks import _hooks_dir + import types + + repo = _make_git_repo(tmp_path) + custom_hooks = tmp_path / "custom_hooks" + custom_hooks.mkdir() + + # expanduser() reads $HOME, so override it to make ~/custom_hooks predictable + monkeypatch.setenv("HOME", str(tmp_path)) + + real_run = subprocess.run + + def fake_run(cmd, **kwargs): + if isinstance(cmd, list) and "config" in cmd and "core.hooksPath" in cmd: + return types.SimpleNamespace(returncode=0, stdout="~/custom_hooks") + return real_run(cmd, **kwargs) + + monkeypatch.setattr(subprocess, "run", fake_run) + + resolved = _hooks_dir(repo) + assert resolved == custom_hooks, ( + f"expected {custom_hooks}, got {resolved} — tilde was not expanded" + )