Skip to content

Commit 2cc1a2f

Browse files
fix: ensure env patch is applied for vanilla emulation
otherwise, installing the hooks when RENV_USER env variable is set (e.g. in RStudio with renv project) will result in executing the installation script in the wrong renv
1 parent cd429db commit 2cc1a2f

File tree

2 files changed

+111
-49
lines changed

2 files changed

+111
-49
lines changed

pre_commit/languages/r.py

Lines changed: 110 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,47 +15,101 @@
1515
from pre_commit.envcontext import UNSET
1616
from pre_commit.prefix import Prefix
1717
from pre_commit.util import cmd_output
18-
from pre_commit.util import cmd_output_b
1918
from pre_commit.util import win_exe
2019

2120
ENVIRONMENT_DIR = 'renv'
22-
RSCRIPT_OPTS = ('--no-save', '--no-restore', '--no-site-file', '--no-environ')
2321
get_default_version = lang_base.basic_get_default_version
2422

2523

26-
def _execute_vanilla_r_code_as_script(
27-
code: str, *,
28-
prefix: Prefix, version: str, args: Sequence[str] = (), cwd: str,
24+
_RENV_ACTIVATED_OPTS = (
25+
'--no-save', '--no-restore', '--no-site-file', '--no-environ',
26+
)
27+
28+
29+
def _execute_r(
30+
code: str,
31+
*,
32+
prefix: Prefix,
33+
version: str,
34+
args: Sequence[str] = (),
35+
cwd: str,
36+
cli_opts: Sequence[str],
2937
) -> str:
3038
with in_env(prefix, version), _r_code_in_tempfile(code) as f:
3139
_, out, _ = cmd_output(
32-
_rscript_exec(), *RSCRIPT_OPTS, f, *args, cwd=cwd,
40+
_rscript_exec(),
41+
*cli_opts,
42+
f,
43+
*args,
44+
cwd=cwd,
3345
)
3446
return out.rstrip('\n')
3547

3648

49+
def _execute_r_in_renv(
50+
code: str,
51+
*,
52+
prefix: Prefix,
53+
version: str,
54+
args: Sequence[str] = (),
55+
cwd: str,
56+
) -> str:
57+
return _execute_r(
58+
code=code,
59+
prefix=prefix,
60+
version=version,
61+
args=args,
62+
cwd=cwd,
63+
cli_opts=_RENV_ACTIVATED_OPTS,
64+
)
65+
66+
67+
def _execute_vanilla_r(
68+
code: str,
69+
*,
70+
prefix: Prefix,
71+
version: str,
72+
args: Sequence[str] = (),
73+
cwd: str,
74+
) -> str:
75+
_R_VANILLA_OPTS = ('--vanilla',)
76+
return _execute_r(
77+
code=code,
78+
prefix=prefix,
79+
version=version,
80+
args=args,
81+
cwd=cwd,
82+
cli_opts=_R_VANILLA_OPTS,
83+
)
84+
85+
3786
def _read_installed_version(envdir: str, prefix: Prefix, version: str) -> str:
38-
return _execute_vanilla_r_code_as_script(
87+
return _execute_r_in_renv(
3988
'cat(renv::settings$r.version())',
40-
prefix=prefix, version=version,
89+
prefix=prefix,
90+
version=version,
4191
cwd=envdir,
4292
)
4393

4494

4595
def _read_executable_version(envdir: str, prefix: Prefix, version: str) -> str:
46-
return _execute_vanilla_r_code_as_script(
96+
return _execute_r_in_renv(
4797
'cat(as.character(getRversion()))',
48-
prefix=prefix, version=version,
98+
prefix=prefix,
99+
version=version,
49100
cwd=envdir,
50101
)
51102

52103

53104
def _write_current_r_version(
54-
envdir: str, prefix: Prefix, version: str,
105+
envdir: str,
106+
prefix: Prefix,
107+
version: str,
55108
) -> None:
56-
_execute_vanilla_r_code_as_script(
109+
_execute_r_in_renv(
57110
'renv::settings$r.version(as.character(getRversion()))',
58-
prefix=prefix, version=version,
111+
prefix=prefix,
112+
version=version,
59113
cwd=envdir,
60114
)
61115

@@ -64,21 +118,25 @@ def health_check(prefix: Prefix, version: str) -> str | None:
64118
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
65119

66120
r_version_installation = _read_installed_version(
67-
envdir=envdir, prefix=prefix, version=version,
121+
envdir=envdir,
122+
prefix=prefix,
123+
version=version,
68124
)
69125
r_version_current_executable = _read_executable_version(
70-
envdir=envdir, prefix=prefix, version=version,
126+
envdir=envdir,
127+
prefix=prefix,
128+
version=version,
71129
)
72130
if r_version_installation in {'NULL', ''}:
73131
return (
74-
f'Hooks were installed with an unknown R version. R version for '
75-
f'hook repo now set to {r_version_current_executable}'
132+
f"Hooks were installed with an unknown R version. R version for "
133+
f"hook repo now set to {r_version_current_executable}"
76134
)
77135
elif r_version_installation != r_version_current_executable:
78136
return (
79-
f'Hooks were installed for R version {r_version_installation}, '
80-
f'but current R executable has version '
81-
f'{r_version_current_executable}'
137+
f"Hooks were installed for R version {r_version_installation}, "
138+
f"but current R executable has version "
139+
f"{r_version_current_executable}"
82140
)
83141

84142
return None
@@ -112,10 +170,10 @@ def in_env(prefix: Prefix, version: str) -> Generator[None]:
112170

113171

114172
def _prefix_if_file_entry(
115-
entry: list[str],
116-
prefix: Prefix,
117-
*,
118-
is_local: bool,
173+
entry: list[str],
174+
prefix: Prefix,
175+
*,
176+
is_local: bool,
119177
) -> Sequence[str]:
120178
if entry[1] == '-e' or is_local:
121179
return entry[1:]
@@ -151,23 +209,23 @@ def _entry_validate(entry: list[str]) -> None:
151209

152210

153211
def _cmd_from_hook(
154-
prefix: Prefix,
155-
entry: str,
156-
args: Sequence[str],
157-
*,
158-
is_local: bool,
212+
prefix: Prefix,
213+
entry: str,
214+
args: Sequence[str],
215+
*,
216+
is_local: bool,
159217
) -> tuple[str, ...]:
160218
cmd = shlex.split(entry)
161219
_entry_validate(cmd)
162220

163221
cmd_part = _prefix_if_file_entry(cmd, prefix, is_local=is_local)
164-
return (cmd[0], *RSCRIPT_OPTS, *cmd_part, *args)
222+
return (cmd[0], *_RENV_ACTIVATED_OPTS, *cmd_part, *args)
165223

166224

167225
def install_environment(
168-
prefix: Prefix,
169-
version: str,
170-
additional_dependencies: Sequence[str],
226+
prefix: Prefix,
227+
version: str,
228+
additional_dependencies: Sequence[str],
171229
) -> None:
172230
lang_base.assert_version_default('r', version)
173231

@@ -204,15 +262,17 @@ def install_environment(
204262
renv::install(prefix_dir)
205263
}}
206264
"""
207-
208-
with _r_code_in_tempfile(r_code_inst_environment) as f:
209-
cmd_output_b(_rscript_exec(), '--vanilla', f, cwd=env_dir)
265+
_execute_vanilla_r(
266+
r_code_inst_environment, prefix=prefix, version=version, cwd=env_dir,
267+
)
210268

211269
_write_current_r_version(envdir=env_dir, prefix=prefix, version=version)
212270
if additional_dependencies:
213271
r_code_inst_add = 'renv::install(commandArgs(trailingOnly = TRUE))'
214-
_execute_vanilla_r_code_as_script(
215-
code=r_code_inst_add, prefix=prefix, version=version,
272+
_execute_r_in_renv(
273+
code=r_code_inst_add,
274+
prefix=prefix,
275+
version=version,
216276
args=additional_dependencies,
217277
cwd=env_dir,
218278
)
@@ -224,26 +284,28 @@ def _inline_r_setup(code: str) -> str:
224284
only be configured via R options once R has started. These are set here.
225285
"""
226286
with_option = [
227-
textwrap.dedent("""\
287+
textwrap.dedent(
288+
"""\
228289
options(
229290
install.packages.compile.from.source = "never",
230291
pkgType = "binary"
231292
)
232-
"""),
293+
""",
294+
),
233295
code,
234296
]
235297
return '\n'.join(with_option)
236298

237299

238300
def run_hook(
239-
prefix: Prefix,
240-
entry: str,
241-
args: Sequence[str],
242-
file_args: Sequence[str],
243-
*,
244-
is_local: bool,
245-
require_serial: bool,
246-
color: bool,
301+
prefix: Prefix,
302+
entry: str,
303+
args: Sequence[str],
304+
file_args: Sequence[str],
305+
*,
306+
is_local: bool,
307+
require_serial: bool,
308+
color: bool,
247309
) -> tuple[int, bytes]:
248310
cmd = _cmd_from_hook(prefix, entry, args, is_local=is_local)
249311
return lang_base.run_xargs(

tests/languages/r_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ def test_health_check_without_version(prefix, installed_environment, version):
286286
prefix, env_dir = installed_environment
287287

288288
# simulate old pre-commit install by unsetting the installed version
289-
r._execute_vanilla_r_code_as_script(
289+
r._execute_r_in_renv(
290290
f'renv::settings$r.version({version})',
291291
prefix=prefix, version=C.DEFAULT, cwd=env_dir,
292292
)

0 commit comments

Comments
 (0)