Skip to content

Commit 19f46ae

Browse files
committed
feat: allow rust hooks to specify crate features
Now the rust hooks can use the parameter `additional_dependencies` to receive build-time features for the crate. The features must start with the string "--feature=" following the name of the feature; e.g. "--feature=full". Fixes #3230
1 parent 60db5d7 commit 19f46ae

2 files changed

Lines changed: 52 additions & 11 deletions

File tree

pre_commit/languages/rust.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from pre_commit.util import win_exe
2323

2424
ENVIRONMENT_DIR = 'rustenv'
25+
FEATURE_PREFIX = '--feature='
2526
health_check = lang_base.basic_health_check
2627
run_hook = lang_base.basic_run_hook
2728

@@ -55,7 +56,8 @@ def get_env_patch(target_dir: str, version: str) -> PatchesT:
5556
# toolchain
5657
*(
5758
(('RUSTUP_TOOLCHAIN', _rust_toolchain(version)),)
58-
if version != 'system' else ()
59+
if version != 'system'
60+
else ()
5961
),
6062
)
6163

@@ -68,11 +70,13 @@ def in_env(prefix: Prefix, version: str) -> Generator[None, None, None]:
6870

6971

7072
def _add_dependencies(
71-
prefix: Prefix,
72-
additional_dependencies: set[str],
73+
prefix: Prefix,
74+
additional_dependencies: set[str],
7375
) -> None:
7476
crates = []
7577
for dep in additional_dependencies:
78+
if dep.startswith(FEATURE_PREFIX):
79+
continue
7680
name, _, spec = dep.partition(':')
7781
crate = f'{name}@{spec or "*"}'
7882
crates.append(crate)
@@ -100,20 +104,27 @@ def install_rust_with_toolchain(toolchain: str, envdir: str) -> None:
100104

101105
# install rustup into `$CARGO_HOME/bin`
102106
cmd_output_b(
103-
rustup_init, '-y', '--quiet', '--no-modify-path',
104-
'--default-toolchain', 'none',
107+
rustup_init,
108+
'-y',
109+
'--quiet',
110+
'--no-modify-path',
111+
'--default-toolchain',
112+
'none',
105113
)
106114

107115
cmd_output_b(
108-
'rustup', 'toolchain', 'install', '--no-self-update',
116+
'rustup',
117+
'toolchain',
118+
'install',
119+
'--no-self-update',
109120
toolchain,
110121
)
111122

112123

113124
def install_environment(
114-
prefix: Prefix,
115-
version: str,
116-
additional_dependencies: Sequence[str],
125+
prefix: Prefix,
126+
version: str,
127+
additional_dependencies: Sequence[str],
117128
) -> None:
118129
envdir = lang_base.environment_dir(prefix, ENVIRONMENT_DIR, version)
119130

@@ -130,6 +141,12 @@ def install_environment(
130141
cli_deps = {
131142
dep for dep in additional_dependencies if dep.startswith('cli:')
132143
}
144+
# Features starts with "--feature="
145+
features = {
146+
dep.replace(FEATURE_PREFIX, '')
147+
for dep in additional_dependencies
148+
if dep.startswith(FEATURE_PREFIX)
149+
}
133150
lib_deps = set(additional_dependencies) - cli_deps
134151

135152
packages_to_install: set[tuple[str, ...]] = {('--path', '.')}
@@ -153,8 +170,17 @@ def install_environment(
153170
if len(lib_deps) > 0:
154171
_add_dependencies(prefix, lib_deps)
155172

173+
features_params = []
174+
if features:
175+
features_params = ['--features', *features]
156176
for args in packages_to_install:
157177
cmd_output_b(
158-
'cargo', 'install', '--bins', '--root', envdir, *args,
178+
'cargo',
179+
'install',
180+
'--bins',
181+
'--root',
182+
envdir,
183+
*args,
184+
*features_params,
159185
cwd=prefix.prefix_dir,
160186
)

tests/languages/rust_test.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,19 @@ def _make_hello_world(tmp_path):
4444
src_dir.joinpath('main.rs').write_text(
4545
'fn main() {\n'
4646
' println!("Hello, world!");\n'
47+
' if cfg!(feature = "foo") {\n'
48+
' println!("With feature foo");\n'
49+
' }\n'
4750
'}\n',
4851
)
4952
tmp_path.joinpath('Cargo.toml').write_text(
5053
'[package]\n'
5154
'name = "hello_world"\n'
5255
'version = "0.1.0"\n'
53-
'edition = "2021"\n',
56+
'edition = "2021"\n'
57+
'\n'
58+
'[features]\n'
59+
'foo = []\n',
5460
)
5561

5662

@@ -113,3 +119,12 @@ def test_run_lib_additional_dependencies(tmp_path):
113119
assert bin_dir.is_dir()
114120
assert not bin_dir.joinpath('shellharden').exists()
115121
assert not bin_dir.joinpath('shellharden.exe').exists()
122+
123+
124+
def test_run_features_additional_dependencies(tmp_path):
125+
_make_hello_world(tmp_path)
126+
127+
deps = ('shellharden:4.2.0', 'git-version')
128+
features = ('--feature=foo',)
129+
ret = run_language(tmp_path, rust, 'hello_world', deps=deps + features)
130+
assert ret == (0, b'Hello, world!\nWith feature foo\n')

0 commit comments

Comments
 (0)