Skip to content

Commit 8c56ef9

Browse files
committed
don't use system for ruby/node if it is a shim exe
1 parent 2779bde commit 8c56ef9

File tree

4 files changed

+51
-5
lines changed

4 files changed

+51
-5
lines changed

pre_commit/languages/helpers.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import multiprocessing
22
import os
33
import random
4+
import re
45
from typing import Any
56
from typing import List
67
from typing import Optional
@@ -10,6 +11,7 @@
1011
from typing import TYPE_CHECKING
1112

1213
import pre_commit.constants as C
14+
from pre_commit import parse_shebang
1315
from pre_commit.hook import Hook
1416
from pre_commit.prefix import Prefix
1517
from pre_commit.util import cmd_output_b
@@ -20,6 +22,24 @@
2022

2123
FIXED_RANDOM_SEED = 1542676187
2224

25+
SHIMS_RE = re.compile(r'[/\\]shims[/\\]')
26+
27+
28+
def exe_exists(exe: str) -> bool:
29+
# 1. exe exists
30+
# 2. it does not have /shims/ as a path segment
31+
# 3. it is not in the home directory
32+
found = parse_shebang.find_executable(exe)
33+
homedir = os.path.expanduser('~')
34+
if found is None: # exe exists
35+
return False
36+
elif SHIMS_RE.search(found): # it is not in a /shims/ directory
37+
return False
38+
elif os.path.commonpath((homedir, found)) == homedir: # not in homedir
39+
return False
40+
else:
41+
return True
42+
2343

2444
def run_setup_cmd(prefix: Prefix, cmd: Tuple[str, ...]) -> None:
2545
cmd_output_b(*cmd, cwd=prefix.prefix_dir)

pre_commit/languages/node.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from typing import Tuple
88

99
import pre_commit.constants as C
10-
from pre_commit import parse_shebang
1110
from pre_commit.envcontext import envcontext
1211
from pre_commit.envcontext import PatchesT
1312
from pre_commit.envcontext import UNSET
@@ -30,7 +29,7 @@ def get_default_version() -> str:
3029
return C.DEFAULT
3130
# if node is already installed, we can save a bunch of setup time by
3231
# using the installed version
33-
elif all(parse_shebang.find_executable(exe) for exe in ('node', 'npm')):
32+
elif all(helpers.exe_exists(exe) for exe in ('node', 'npm')):
3433
return 'system'
3534
else:
3635
return C.DEFAULT

pre_commit/languages/ruby.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from typing import Tuple
99

1010
import pre_commit.constants as C
11-
from pre_commit import parse_shebang
1211
from pre_commit.envcontext import envcontext
1312
from pre_commit.envcontext import PatchesT
1413
from pre_commit.envcontext import UNSET
@@ -26,7 +25,7 @@
2625

2726
@functools.lru_cache(maxsize=1)
2827
def get_default_version() -> str:
29-
if all(parse_shebang.find_executable(exe) for exe in ('ruby', 'gem')):
28+
if all(helpers.exe_exists(exe) for exe in ('ruby', 'gem')):
3029
return 'system'
3130
else:
3231
return C.DEFAULT

tests/languages/helpers_test.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,45 @@
11
import multiprocessing
2-
import os
2+
import os.path
33
import sys
44
from unittest import mock
55

66
import pytest
77

88
import pre_commit.constants as C
9+
from pre_commit import parse_shebang
910
from pre_commit.languages import helpers
1011
from pre_commit.prefix import Prefix
1112
from pre_commit.util import CalledProcessError
1213
from testing.auto_namedtuple import auto_namedtuple
1314

1415

16+
@pytest.fixture
17+
def find_exe_mck():
18+
with mock.patch.object(parse_shebang, 'find_executable') as mck:
19+
yield mck
20+
21+
22+
def test_exe_exists_does_not_exist(find_exe_mck):
23+
find_exe_mck.return_value = None
24+
assert helpers.exe_exists('ruby') is False
25+
26+
27+
def test_exe_exists_exists(find_exe_mck):
28+
find_exe_mck.return_value = '/usr/bin/ruby'
29+
assert helpers.exe_exists('ruby') is True
30+
31+
32+
def test_exe_exists_false_if_shim(find_exe_mck):
33+
find_exe_mck.return_value = '/foo/shims/ruby'
34+
assert helpers.exe_exists('ruby') is False
35+
36+
37+
def test_exe_exists_false_if_homedir(find_exe_mck):
38+
find_exe_mck.return_value = '/home/me/somedir/ruby'
39+
with mock.patch.object(os.path, 'expanduser', return_value='/home/me'):
40+
assert helpers.exe_exists('ruby') is False
41+
42+
1543
def test_basic_get_default_version():
1644
assert helpers.basic_get_default_version() == C.DEFAULT
1745

0 commit comments

Comments
 (0)