summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git/index/fun.py15
-rw-r--r--test/test_index.py9
2 files changed, 20 insertions, 4 deletions
diff --git a/git/index/fun.py b/git/index/fun.py
index 16ec744e..59fa1be1 100644
--- a/git/index/fun.py
+++ b/git/index/fun.py
@@ -3,6 +3,7 @@
# NOTE: Autodoc hates it if this is a docstring
from io import BytesIO
+from pathlib import Path
import os
from stat import (
S_IFDIR,
@@ -21,6 +22,7 @@ from git.compat import (
force_text,
force_bytes,
is_posix,
+ is_win,
safe_decode,
)
from git.exc import (
@@ -76,6 +78,10 @@ def hook_path(name: str, git_dir: PathLike) -> str:
return osp.join(git_dir, 'hooks', name)
+def _has_file_extension(path):
+ return osp.splitext(path)[1]
+
+
def run_commit_hook(name: str, index: 'IndexFile', *args: str) -> None:
"""Run the commit hook of the given name. Silently ignores hooks that do not exist.
:param name: name of hook, like 'pre-commit'
@@ -89,8 +95,15 @@ def run_commit_hook(name: str, index: 'IndexFile', *args: str) -> None:
env = os.environ.copy()
env['GIT_INDEX_FILE'] = safe_decode(str(index.path))
env['GIT_EDITOR'] = ':'
+ cmd = [hp]
try:
- cmd = subprocess.Popen([hp] + list(args),
+ if is_win and not _has_file_extension(hp):
+ # Windows only uses extensions to determine how to open files
+ # (doesn't understand shebangs). Try using bash to run the hook.
+ relative_hp = Path(hp).relative_to(index.repo.working_dir).as_posix()
+ cmd = ["bash.exe", relative_hp]
+
+ cmd = subprocess.Popen(cmd + list(args),
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
diff --git a/test/test_index.py b/test/test_index.py
index 02cb4e81..233a4c64 100644
--- a/test/test_index.py
+++ b/test/test_index.py
@@ -13,6 +13,7 @@ from stat import (
)
import tempfile
from unittest import skipIf
+import shutil
from git import (
IndexFile,
@@ -52,8 +53,9 @@ from git.cmd import Git
HOOKS_SHEBANG = "#!/usr/bin/env sh\n"
+is_win_without_bash = is_win and not shutil.which('bash.exe')
+
-@skipIf(HIDE_WINDOWS_KNOWN_ERRORS, "TODO: fix hooks execution on Windows: #703")
def _make_hook(git_dir, name, content, make_exec=True):
"""A helper to create a hook"""
hp = hook_path(name, git_dir)
@@ -881,7 +883,7 @@ class TestIndex(TestBase):
try:
index.commit("This should fail")
except HookExecutionError as err:
- if is_win:
+ if is_win_without_bash:
self.assertIsInstance(err.status, OSError)
self.assertEqual(err.command, [hp])
self.assertEqual(err.stdout, '')
@@ -896,6 +898,7 @@ class TestIndex(TestBase):
else:
raise AssertionError("Should have caught a HookExecutionError")
+ @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, "TODO: fix hooks execution on Windows: #703")
@with_rw_repo('HEAD', bare=True)
def test_commit_msg_hook_success(self, rw_repo):
commit_message = "commit default head by Frèderic Çaufl€"
@@ -920,7 +923,7 @@ class TestIndex(TestBase):
try:
index.commit("This should fail")
except HookExecutionError as err:
- if is_win:
+ if is_win_without_bash:
self.assertIsInstance(err.status, OSError)
self.assertEqual(err.command, [hp])
self.assertEqual(err.stdout, '')