Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 1 addition & 20 deletions git/index/fun.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,6 @@ def _has_file_extension(path: str) -> str:
return osp.splitext(path)[1]


def _which_from_path(command: str) -> Union[str, None]:
"""Resolve an executable 'command' from PATH without considering the current directory."""
cwd = osp.normcase(osp.abspath(os.curdir))
for directory in os.get_exec_path():
if not directory:
continue
directory = osp.abspath(directory)
if osp.normcase(directory) == cwd:
continue
candidate = osp.join(directory, command)
if osp.isfile(candidate) and os.access(candidate, os.X_OK):
return candidate
return None


def run_commit_hook(name: str, index: "IndexFile", *args: str) -> None:
"""Run the commit hook of the given name. Silently ignore hooks that do not exist.

Expand Down Expand Up @@ -127,11 +112,7 @@ def run_commit_hook(name: str, index: "IndexFile", *args: str) -> None:
# an absolute path in this form, although a relative path is preferable
# because it also works with the Windows Subsystem for Linux wrapper.
bash_hp = hp
# Resolve through PATH before spawning. On Windows, CreateProcess searches
# the current and system directories before PATH for a bare executable name,
# which can otherwise select an impostor or the WSL launcher instead of Git
# for Windows' Bash.
cmd = [_which_from_path("bash.exe") or "bash.exe", Path(bash_hp).as_posix()]
cmd = ["bash.exe", Path(bash_hp).as_posix()]

process = safer_popen(
cmd + list(args),
Expand Down
8 changes: 2 additions & 6 deletions test/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -1128,20 +1128,16 @@ def test_run_commit_hook_outside_worktree_on_windows(self, rw_dir):
repo = Repo.init(root / "repo")
hooks_dir = root / "hooks"
_make_hook(root, "fake-hook", "exit 0")
bash = root / "git" / "bin" / "bash.exe"
with repo.config_writer() as writer:
writer.set_value("core", "hooksPath", str(hooks_dir))

with mock.patch("git.index.fun.sys.platform", "win32"), mock.patch(
"git.index.fun._which_from_path", return_value=str(bash)
) as which:
with mock.patch("git.index.fun.sys.platform", "win32"):
with mock.patch("git.index.fun.safer_popen") as popen, mock.patch("git.index.fun.handle_process_output"):
popen.return_value.returncode = 0
run_commit_hook("fake-hook", repo.index)

which.assert_called_once_with("bash.exe")
command = popen.call_args[0][0]
self.assertEqual(command, [str(bash), "../hooks/fake-hook"])
self.assertEqual(command, ["bash.exe", "../hooks/fake-hook"])

@ddt.data((False,), (True,))
@with_rw_directory
Expand Down
Loading