1- from __future__ import annotations
2-
3- import unittest
41import os
2+ import shutil
3+ import subprocess
4+ import unittest
5+ from pathlib import Path
56
6- def require_bash () -> bool :
7- import shutil
8- bash = shutil .which ('bash' )
7+
8+ def get_bash_executable () -> str | None :
99 if os .name == 'nt' :
10- return False
11- return bash is not None
10+ for candidate in (
11+ r'C:\Program Files\Git\bin\bash.exe' ,
12+ r'C:\Program Files\Git\usr\bin\bash.exe' ,
13+ r'C:\Program Files (x86)\Git\bin\bash.exe' ,
14+ os .path .expandvars (r'%LOCALAPPDATA%\Programs\Git\bin\bash.exe' ),
15+ ):
16+ if os .path .exists (candidate ):
17+ return candidate
18+ bash = shutil .which ('bash' )
19+ if bash and 'WindowsApps' not in bash :
20+ return bash
21+ return None
1222
1323
14- import os
15- import subprocess
16- import unittest
17- from pathlib import Path
24+ def require_bash () -> bool :
25+ bash = get_bash_executable ()
26+ if not bash :
27+ return False
28+ try :
29+ res = subprocess .run ([bash , '-c' , 'echo 1' ], capture_output = True , text = True , timeout = 2 )
30+ return res .returncode == 0
31+ except Exception :
32+ return False
1833
1934
2035REPO_ROOT = Path (__file__ ).resolve ().parents [1 ]
@@ -24,11 +39,12 @@ def require_bash() -> bool:
2439class PrePushHookContractTests (unittest .TestCase ):
2540 @unittest .skipUnless (require_bash (), 'Requires bash' )
2641 def test_skip_escape_hatch_exits_successfully_with_stderr_notice (self ) -> None :
42+ bash_cmd = get_bash_executable () or 'bash'
2743 env = os .environ .copy ()
2844 env ['SKIP_CLAW_PRE_PUSH_BUILD' ] = '1'
2945
3046 result = subprocess .run (
31- ['bash' , str (PRE_PUSH_HOOK )],
47+ [bash_cmd , str (PRE_PUSH_HOOK )],
3248 cwd = REPO_ROOT ,
3349 env = env ,
3450 check = True ,
0 commit comments